582
592
gtk_tree_store_append(store, &commentary, NULL);
583
593
gtk_tree_store_set(store, &commentary, 0, _("Commentaries"), -1);
585
/* Dictionaries folders */
586
gtk_tree_store_append(store, &dictionary, NULL);
587
gtk_tree_store_set(store, &dictionary, 0, _("Dictionaries"), -1);
589
/* Devotionals folders */
590
gtk_tree_store_append(store, &devotional, NULL);
591
gtk_tree_store_set(store, &devotional, 0, _("Daily Devotionals"), -1);
593
/* General Books folders */
594
gtk_tree_store_append(store, &book, NULL);
595
gtk_tree_store_set(store, &book, 0, _("General Books"), -1);
598
gtk_tree_store_append(store, &map, NULL);
599
gtk_tree_store_set(store, &map, 0, _("Maps"), -1);
602
gtk_tree_store_append(store, &image, NULL);
603
gtk_tree_store_set(store, &image, 0, _("Images"), -1);
605
/* Prayer lists folder */
606
if (settings.prayerlist) {
607
gtk_tree_store_append(store, &prayerlist, NULL);
608
gtk_tree_store_set(store, &prayerlist, 0, _("Prayer List/Journal"), -1);
596
/* Dictionaries folders */
597
gtk_tree_store_append(store, &dictionary, NULL);
598
gtk_tree_store_set(store, &dictionary, 0, _("Dictionaries"), -1);
600
/* Glossaries folders */
601
gtk_tree_store_append(store, &glossary, NULL);
602
gtk_tree_store_set(store, &glossary, 0, _("Glossaries"), -1);
604
/* Devotionals folders */
605
gtk_tree_store_append(store, &devotional, NULL);
606
gtk_tree_store_set(store, &devotional, 0, _("Daily Devotionals"), -1);
608
/* General Books folders */
609
gtk_tree_store_append(store, &book, NULL);
610
gtk_tree_store_set(store, &book, 0, _("General Books"), -1);
613
gtk_tree_store_append(store, &map, NULL);
614
gtk_tree_store_set(store, &map, 0, _("Maps"), -1);
617
gtk_tree_store_append(store, &image, NULL);
618
gtk_tree_store_set(store, &image, 0, _("Images"), -1);
621
gtk_tree_store_append(store, &cult, NULL);
622
gtk_tree_store_set(store, &cult, 0, _("Cult/Unorthodox"), -1);
624
/* Prayer lists folder */
625
if (settings.prayerlist) {
626
gtk_tree_store_append(store, &prayerlist, NULL);
627
gtk_tree_store_set(store, &prayerlist, 0, _("Prayer List/Journal"), -1);
611
631
tmp = mod_mgr_list_local_modules(settings.path_to_mods, TRUE);
613
633
language_make_list(tmp, store,
614
634
text, commentary, map, image,
615
devotional, dictionary, book,
635
devotional, dictionary, glossary, book, cult,
617
language_add_folders);
637
language_add_folders, limited);
620
640
while (tmp2 != NULL) {
621
641
info = (MOD_MGR *) tmp2->data;
623
// see comment on similar code in src/main/sidebar.cc.
643
/* see comment on similar code in src/main/sidebar.cc. */
625
if (info->type[0] == 'B') {
645
if ((info->type[0] == 'B') && !info->is_cult) {
626
646
add_module_to_language_folder(GTK_TREE_MODEL(store),
627
647
text, info->language,
630
else if (info->type[0] == 'C') {
650
else if ((info->type[0] == 'C') && !info->is_cult) {
631
651
add_module_to_language_folder(GTK_TREE_MODEL(store),
632
652
commentary, info->language,
635
else if (info->is_maps) {
636
add_module_to_language_folder(GTK_TREE_MODEL(store),
640
else if (info->is_images) {
641
add_module_to_language_folder(GTK_TREE_MODEL(store),
642
image, info->language,
645
else if (info->is_devotional) {
646
add_module_to_language_folder(GTK_TREE_MODEL(store),
647
devotional, info->language,
650
else if (info->type[0] == 'L') {
651
add_module_to_language_folder(GTK_TREE_MODEL(store),
652
dictionary, info->language,
655
else if (info->type[0] == 'G') {
656
gchar *gstype = main_get_mod_config_entry(info->name, "GSType");
657
if ((gstype == NULL) || strcmp(gstype, "PrayerList")) {
658
add_module_to_language_folder(GTK_TREE_MODEL(store),
659
book, info->language,
664
GS_warning(("mod `%s' unknown type `%s'",
665
info->name, info->type));
657
add_module_to_language_folder(GTK_TREE_MODEL(store),
658
cult, info->language,
661
else if (info->is_maps) {
662
add_module_to_language_folder(GTK_TREE_MODEL(store),
666
else if (info->is_images) {
667
add_module_to_language_folder(GTK_TREE_MODEL(store),
668
image, info->language,
671
else if (info->is_devotional) {
672
add_module_to_language_folder(GTK_TREE_MODEL(store),
673
devotional, info->language,
676
else if (info->is_glossary) {
677
add_module_to_language_folder(GTK_TREE_MODEL(store),
678
glossary, info->language,
681
else if (info->type[0] == 'L') {
682
add_module_to_language_folder(GTK_TREE_MODEL(store),
683
dictionary, info->language,
686
else if (info->type[0] == 'G') {
687
gchar *gstype = main_get_mod_config_entry(info->name, "GSType");
688
if ((gstype == NULL) || strcmp(gstype, "PrayerList")) {
689
add_module_to_language_folder(GTK_TREE_MODEL(store),
690
book, info->language,
695
GS_warning(("mod `%s' unknown type `%s'",
696
info->name, info->type));
668
700
g_free(info->name);
710
742
MOD_FONT *get_font(gchar * mod_name)
715
sprintf(file, "%s/fonts.conf", settings.gSwordDir);
717
mf = g_new(MOD_FONT, 1);
745
static gchar *file = NULL;
748
file = g_strdup_printf("%s/fonts.conf", settings.gSwordDir); /* not freed */
750
mf = g_new0(MOD_FONT, 1);
718
751
mf->mod_name = mod_name;
720
mf->old_gdk_font = NULL;
721
mf->old_font_size = NULL;
723
mf->new_gdk_font = NULL;
724
mf->new_font_size = NULL;
727
753
mf->old_font = get_conf_file_item(file, mod_name, "Font");
728
754
mf->old_gdk_font = get_conf_file_item(file, mod_name, "GdkFont");
729
755
mf->old_font_size = get_conf_file_item(file, mod_name, "Fontsize");
730
757
if ((mf->old_font == NULL) ||
731
758
!strcmp(mf->old_font, "none")) {
732
gchar *preferred_font =
733
main_get_mod_config_entry(mod_name, "Font");
736
g_free(mf->old_font);
737
if (preferred_font && (*preferred_font != '\0')) {
738
mf->old_font = g_strdup(preferred_font);
740
mf->old_font = g_strdup("none");
759
/* in absence of selected font, module can name its preference */
760
gchar *preferred_font = main_get_mod_config_entry(mod_name, "Font");
761
gchar *preferred_font_size = main_get_mod_config_entry(mod_name, "Fontsize");
763
/* in absence of module preference, user can specify language pref */
764
gchar *lang = main_get_mod_config_entry(mod_name, "Lang");
765
gchar *lang_lang = g_strdup_printf("Language:%s",
767
gchar *lang_font = get_conf_file_item(file, lang_lang, "Font");
768
gchar *lang_size = get_conf_file_item(file, lang_lang, "Fontsize");
770
g_free(mf->old_font);
772
if (preferred_font && (*preferred_font != '\0'))
773
mf->old_font = preferred_font;
775
g_free(preferred_font);
776
/* next try: fallback to per-language choice */
777
if (lang_font && (*lang_font != '\0'))
778
mf->old_font = lang_font;
780
/* nothing ever specified: utter default */
782
mf->old_font = g_strdup("none");
744
if ((mf->old_font_size == NULL) ||
745
!strcmp(mf->old_font_size, "+0")) {
746
gchar *preferred_font_size =
747
main_get_mod_config_entry(mod_name, "Fontsize");
749
if (mf->old_font_size)
786
if ((mf->old_font_size == NULL) ||
787
!strcmp(mf->old_font_size, "+0")) {
750
788
g_free(mf->old_font_size);
751
if (preferred_font_size && (*preferred_font_size != '\0')) {
752
mf->old_font_size = g_strdup(preferred_font_size);
754
mf->old_font_size = g_strdup("+0");
790
if (preferred_font_size && (*preferred_font_size != '\0'))
791
mf->old_font_size = preferred_font_size;
793
g_free(preferred_font_size);
794
if (lang_size && (*lang_size != '\0'))
795
mf->old_font_size = lang_size;
798
mf->old_font_size = g_strdup("+0");
1103
1155
language_get_type(LANGSET_BIBLE));
1104
1156
(*add)(GTK_TREE_MODEL(store), commentary,
1105
1157
language_get_type(LANGSET_COMMENTARY));
1106
(*add)(GTK_TREE_MODEL(store), map,
1107
language_get_type(LANGSET_MAP));
1108
(*add)(GTK_TREE_MODEL(store), image,
1109
language_get_type(LANGSET_IMAGE));
1110
(*add)(GTK_TREE_MODEL(store), devotional,
1111
language_get_type(LANGSET_DEVOTIONAL));
1112
(*add)(GTK_TREE_MODEL(store), dictionary,
1113
language_get_type(LANGSET_DICTIONARY));
1114
(*add)(GTK_TREE_MODEL(store), book,
1115
language_get_type(LANGSET_GENBOOK));
1116
if ((update != NULL) && (uninstalled != NULL)) {
1117
(*add)(GTK_TREE_MODEL(store), *update,
1118
language_get_type(LANGSET_UPDATE));
1119
(*add)(GTK_TREE_MODEL(store), *uninstalled,
1120
language_get_type(LANGSET_UNINSTALLED));
1159
(*add)(GTK_TREE_MODEL(store), map,
1160
language_get_type(LANGSET_MAP));
1161
(*add)(GTK_TREE_MODEL(store), image,
1162
language_get_type(LANGSET_IMAGE));
1163
(*add)(GTK_TREE_MODEL(store), cult,
1164
language_get_type(LANGSET_CULT));
1165
(*add)(GTK_TREE_MODEL(store), devotional,
1166
language_get_type(LANGSET_DEVOTIONAL));
1167
(*add)(GTK_TREE_MODEL(store), glossary,
1168
language_get_type(LANGSET_GLOSSARY));
1169
(*add)(GTK_TREE_MODEL(store), dictionary,
1170
language_get_type(LANGSET_DICTIONARY));
1171
(*add)(GTK_TREE_MODEL(store), book,
1172
language_get_type(LANGSET_GENBOOK));
1173
if ((update != NULL) && (uninstalled != NULL)) {
1174
(*add)(GTK_TREE_MODEL(store), *update,
1175
language_get_type(LANGSET_UPDATE));
1176
(*add)(GTK_TREE_MODEL(store), *uninstalled,
1177
language_get_type(LANGSET_UNINSTALLED));
1182
/******************************************************************************
1187
* #include "gui/search_dialog.h"
1198
gchar *get_modlist_string(GList * mods)
1201
GString *str = g_string_new("");
1202
GList *orig_mods = mods;
1204
while (mods != NULL) {
1205
str = g_string_append(str, (gchar *) mods->data);
1207
mods = g_list_next(mods);
1209
str = g_string_append_c(str, ',');
1211
g_list_free(orig_mods);
1213
rv = g_strdup(str->str);
1214
g_string_free(str, TRUE);
1220
/******************************************************************************
1225
* #include "gui/search_dialog.h"
1227
* GList *get_current_list(GtkTreeView *treeview)
1236
GList *get_current_list(GtkTreeView *treeview)
1238
GList *items = NULL;
1240
GtkTreeModel *model;
1243
model = gtk_tree_view_get_model(treeview);
1244
if (gtk_tree_model_get_iter_first(model, &iter)) {
1246
gtk_tree_model_get(model, &iter, 1, &buf, -1);
1248
g_list_append(items,
1249
(gchar *) g_strdup(buf));
1251
} while (gtk_tree_model_iter_next(model, &iter));
1125
1258
* caller must free the returned string.
1603
// Read aloud some text, i.e. the current verse.
1604
// Text is cleaned of '"', <tokens>, "&symbols;", and *n/*x strings,
1605
// then scribbled out the local static socket with (SayText "...").
1606
// Non-zero verse param is prefixed onto supplied text.
1609
#ifndef INVALID_SOCKET
1610
# define INVALID_SOCKET -1
1614
ReadAloud(unsigned int verse, const char *suppliedtext)
1616
static int tts_socket = INVALID_SOCKET; // no initial connection.
1617
static int use_counter = -2; // to shortcircuit early uses.
1619
if (settings.readaloud || // read anything, or
1620
(verse == 0)) { // read what's handed us.
1623
// setup for communication.
1624
if (tts_socket < 0) {
1625
struct sockaddr_in service;
1627
if ((tts_socket = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
1629
sprintf(msg, "ReadAloud disabled:\nsocket failed, %s",
1631
settings.readaloud = 0;
1632
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
1633
(widgets.readaloud_item),
1634
settings.readaloud);
1635
gui_generic_warning(msg);
1639
// festival's port (1314) on localhost (127.0.0.1).
1640
memset(&service, 0, sizeof service);
1641
service.sin_family = AF_INET;
1642
service.sin_port = htons(1314);
1643
service.sin_addr.s_addr = htonl(0x7f000001);
1644
if (connect(tts_socket, (const struct sockaddr *)&service,
1645
sizeof(service)) != 0) {
1648
Sleep(2); // give festival a moment to init.
1650
sleep(2); // give festival a moment to init.
1652
if (connect(tts_socket, (const struct sockaddr *)&service,
1653
sizeof(service)) != 0) {
1654
// it still didn't work -- missing.
1656
sprintf(msg, "%s\n%s, %s",
1657
"TTS \"festival\" not started -- perhaps not installed",
1658
"TTS connect failed", strerror(errno));
1659
StopFestival(&tts_socket);
1660
settings.readaloud = 0;
1661
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
1662
(widgets.readaloud_item),
1663
settings.readaloud);
1664
gui_generic_warning(msg);
1670
// avoid speaking the first *2* times.
1671
// (2 Display() calls are made during startup.)
1672
// though speaking may be intended, startup speech is annoying.
1673
if (verse && (++use_counter < 1))
1676
GString *text = g_string_new(NULL);
1678
g_string_printf(text, "%d. ... %s", verse, suppliedtext);
1679
// use of ". ..." is to induce proper pauses.
1681
g_string_printf(text, "%s", suppliedtext);
1682
GS_message(("ReadAloud: dirty: %s\n", text->str));
1684
// clean: no <span> surrounding strongs/morph.
1685
// i wish there was a regexp form of strstr().
1686
for (s = strstr(text->str, "<span class=\"strongs\">");
1688
s = strstr(s, "<span class=\"strongs\">")) {
1689
if ((t = strstr(s, "</span>"))) {
1694
GS_message(("ReadAloud: Unmatched <span strong></span> in %s\n", s));
1698
for (s = strstr(text->str, "<span class=\"morph\">");
1700
s = strstr(s, "<span class=\"morph\">")) {
1701
if ((t = strstr(s, "</span>"))) {
1706
GS_message(("ReadAloud: Unmatched <span morph></span> in %s\n", s));
1711
// clean: no quotes (conflict w/festival syntax).
1712
for (s = strchr(text->str, '"'); s; s = strchr(s, '"'))
1715
// clean: no <tokens>.
1716
for (s = strchr(text->str, '<'); s; s = strchr(s, '<')) {
1717
if ((t = strchr(s, '>'))) {
1721
GS_message(("ReadAloud: Unmatched <> in %s\n", s));
1726
// clean: no <...> sequences. (Strong's ref, "<1234>".)
1727
for (s = strstr(text->str, "<"); s; s = strstr(s, "<")) {
1728
if ((t = strstr(s, ">"))) {
1733
GS_message(("ReadAloud: Unmatched <> in %s\n", s));
1738
// clean: no other &symbols;.
1739
for (s = strchr(text->str, '&'); s; s = strchr(s, '&')) {
1740
if ((t = strchr(s, ';'))) {
1744
GS_message(("ReadAloud: Incomplete &xxx; in %s\n", s));
1749
// clean: no note/xref strings.
1750
for (s = strstr(text->str, "*n"); s; s = strstr(s, "*n")) {
1753
while (isdigit(*s)) *(s++) = ' ';
1755
for (s = strstr(text->str, "*u"); s; s = strstr(s, "*u")) {
1759
for (s = strstr(text->str, "*x"); s; s = strstr(s, "*x")) {
1762
while (isdigit(*s)) *(s++) = ' ';
1765
// festival *pronounces* brackets and asterisks -- idiots.
1766
for (s = strchr(text->str, '['); s; s = strchr(s, '['))
1768
for (s = strchr(text->str, ']'); s; s = strchr(s, ']'))
1770
for (s = strchr(text->str, '*'); s; s = strchr(s, '*'))
1772
// in case it isn't obvious, i'd really like a standard
1773
// function that walks a string for multiple individual chars.
1775
// walk the string, looking for dislocated "LORD" as "L<spaces>ORD".
1776
// this occurs in "smallcaps" use in many bibles.
1777
for (s = strchr(text->str, 'L'); s; s = strchr(s+1, 'L')) {
1781
if (!strncmp(s, "ORD", 3)) {
1786
// same song, second verse: G<spaces>OD.
1787
for (s = strchr(text->str, 'G'); s; s = strchr(s+1, 'G')) {
1791
if (!strncmp(s, "OD", 2)) {
1797
GS_message(("ReadAloud: clean: %s\n", text->str));
1798
// scribble clean text to the socket.
1799
if (FestivalSpeak(text->str, strlen(text->str), tts_socket) == FALSE)
1802
sprintf(msg, "TTS disappeared?\nTTS write failed: %s",
1804
StopFestival(&tts_socket);
1805
settings.readaloud = 0;
1806
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
1807
(widgets.readaloud_item),
1808
settings.readaloud);
1809
gui_generic_warning(msg);
1813
g_string_free(text, TRUE);
1818
// Reading aloud is disabled.
1819
// If we had been reading, shut it down.
1820
if (tts_socket >= 0) {
1821
StopFestival(&tts_socket);
1829
// starts festival in a async process
1835
//on windows, we will ship festival directly under Xiphos
1836
gchar *festival_args[5];
1837
gchar *festival_com = g_win32_get_package_installation_directory_of_module(NULL);
1838
festival_com = g_strconcat(festival_com, "\0", NULL);
1839
gchar *festival_lib = g_build_filename(festival_com, "festival\\lib\0");
1840
festival_com = g_build_filename(festival_com, "festival\\festival.exe\0");
1841
festival_args[0] = festival_com;
1842
festival_args[1] = g_strdup("--libdir");
1843
festival_args[2] = festival_lib;
1844
festival_args[3] = g_strdup("--server");
1845
festival_args[4] = NULL;
1847
gchar *festival_args[3];
1848
festival_args[0] = g_strdup("festival");
1849
festival_args[1] = g_strdup("--server");
1850
festival_args[2] = NULL;
1852
g_spawn_async ( NULL,
1855
G_SPAWN_SEARCH_PATH,
1863
// shuts down Festival
1866
StopFestival(int *tts_socket)
1869
closesocket(*tts_socket);
1871
shutdown(*tts_socket, SHUT_RDWR);
1874
*tts_socket = INVALID_SOCKET;
1878
// tells Festival to say the given text
1881
FestivalSpeak(gchar *text, int length, int tts_socket)
1884
if ((send(tts_socket, "(SayText \"", 10, MSG_DONTROUTE) == INVALID_SOCKET) ||
1885
(send(tts_socket, text, length, MSG_DONTROUTE) == INVALID_SOCKET) ||
1886
(send(tts_socket, "\")\r\n", 4, MSG_DONTROUTE) == INVALID_SOCKET ))
1889
if ((write(tts_socket, "(SayText \"", 10) < 0) ||
1890
(write(tts_socket, text, length ) < 0) ||
1891
(write(tts_socket, "\")\r\n", 4) < 0))
1897
#ifndef HAVE_STRCASESTR
1899
* strcasestr() turns out to be nonstandard extension, but we need it.
1902
strcasestr(const char *haystack, const char *needle)
1904
char *lower_haystack = g_strdup(haystack);
1905
char *lower_needle = g_strdup(needle);
1908
for (s = lower_haystack; *s; ++s)
1911
for (s = lower_needle; *s; ++s)
1915
s = strstr(lower_haystack, lower_needle);
1917
s = (char *)haystack + (s - lower_haystack);
1919
g_free(lower_haystack);
1920
g_free(lower_needle);
1923
#endif /* !HAVE_STRCASESTR */
1926
ImageDimensions(const char *path, int *x, int *y)
1929
if (gdk_pixbuf_get_file_info (path, x, y))
1935
#define IMGSRC_STRING "<img src=\""
1936
#define IMGSRC_LENGTH 10 // strlen(IMGSRC_STRING)
1937
const char *strcasestr(const char *haystack, const char *needle);
1940
AnalyzeForImageSize(const char *origtext,
1943
static GString *resized;
1944
static gint resized_init = FALSE;
1946
const char *trail; // "trail" trails behind ...
1947
char *path; // ... the current "path".
1948
char *end; // "end" is the path's end.
1949
char buf[32]; // for preparing new width+height spec.
1950
gint image_x, image_y, window_x, window_y = -999;
1952
gboolean no_warning_yet = TRUE;
1954
if (!resized_init) {
1955
resized = g_string_new("");
1956
resized_init = TRUE;
1959
// performance tweak:
1960
// image content is by no means common. therefore, spend an extra
1961
// search call to determine whether any of the rest is needed,
1962
// most especially to stop copying large blocks of text w/no images.
1963
if ((path = (char *)strcasestr(origtext, IMGSRC_STRING)) == NULL)
1966
for (resized = g_string_assign(resized, ""), trail = origtext
1967
/* and path was initialized just above */ ;
1969
path = (char *)strcasestr(path, IMGSRC_STRING)) {
1971
if (window_y == -999) {
1972
/* we have images, but we don't know bounds yet */
1974
gdk_drawable_get_size(window, &window_x, &window_y);
1975
if ((window_x > 200) || (window_y > 200)) {
1979
window_x = (window_x * 93)/100;
1980
window_y = (window_y * 93)/100;
1984
/* add the working segment, with annotation added */
1985
/* to keep us from matching IMGSRC_STRING again. */
1986
path += IMGSRC_LENGTH;
1987
resized = g_string_append_len(resized, trail, path-trail-5);
1988
resized = g_string_append(resized, "resized=\"yes\" ");
1989
resized = g_string_append_len(resized, path-5, 5);
1991
// some modules play fast-n-loose with proper file spec.
1992
if (strncmp(path, "file://", 7) == 0) {
1994
resized = g_string_append(resized, "file://");
1995
} else if (strncmp(path, "file:", 5) == 0) {
1997
resized = g_string_append(resized, "file:");
1999
continue; // no file spec there -- odd.
2001
// getting this far means we have a valid img src and file.
2002
// find closing '"' to determine pathname end.
2003
if ((end = strchr(path, '"')) == 0)
2007
resized = g_string_append(resized, path);
2008
image_retval = ImageDimensions(path, &image_x, &image_y);
2011
resized = g_string_append_c(resized, '"');
2015
if (image_retval != 0) {
2016
if (no_warning_yet) {
2017
gui_generic_warning(
2018
_("An image file's size could not be determined.\n"
2019
"Xiphos cannot resize images to fit window."));
2020
// settings.imageresize = 0;
2021
no_warning_yet = FALSE;
2026
// knowing image size & window size, adjust to fit.
2027
if (image_x > window_x) {
2028
float proportion = (float)window_x / (float)image_x;
2030
image_y = (int)((float)image_y * proportion);
2032
if (image_y > window_y) {
2033
float proportion = (float)window_y / (float)image_y;
2035
image_x = (int)((float)image_x * proportion);
2037
sprintf(buf, " width=\"%d\" height=\"%d\"", image_x, image_y);
2038
resized = g_string_append(resized, buf);
2041
resized = g_string_append(resized, trail); // remainder of text appended.
2042
return resized->str;
1439
2045
/****** end of file ******/