1 /*
2 * Xiphos Bible Study Tool
3 * sword.cc - glue
4 *
5 * Copyright (C) 2000-2020 Xiphos Developer Team
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <gtk/gtk.h>
27 #include <glib.h>
28 #include <glib/gstdio.h>
29
30 #include <swmgr.h>
31 #include <swmodule.h>
32 #include <stringmgr.h>
33 #include <localemgr.h>
34
35 extern "C" {
36 #include "gui/bibletext.h"
37 #include "main/gtk_compat.h"
38 }
39
40 #include <ctype.h>
41 #include <time.h>
42
43 #include "gui/main_window.h"
44 #include "gui/font_dialog.h"
45 #include "gui/widgets.h"
46 #include "gui/commentary.h"
47 #include "gui/dialog.h"
48 #include "gui/parallel_dialog.h"
49 #include "gui/parallel_tab.h"
50 #include "gui/parallel_view.h"
51 #include "gui/tabbed_browser.h"
52 #include "gui/xiphos.h"
53 #include "gui/sidebar.h"
54 #include "gui/utilities.h"
55 #include "gui/cipher_key_dialog.h"
56 #include "gui/main_menu.h"
57
58 #include "main/biblesync_glue.h"
59 #include "main/display.hh"
60 #include "main/lists.h"
61 #include "main/navbar.h"
62 #include "main/navbar_book.h"
63 #include "main/search_sidebar.h"
64 #include "main/previewer.h"
65 #include "main/settings.h"
66 #include "main/sidebar.h"
67 #include "main/sword.h"
68 #include "main/url.hh"
69 #include "main/xml.h"
70 #include "main/parallel_view.h"
71 #include "main/modulecache.hh"
72
73 #include "backend/sword_main.hh"
74 #include "backend/gs_stringmgr.h"
75
76 #include "biblesync/biblesync.hh"
77
78 #include "gui/debug_glib_null.h"
79
80 #ifdef HAVE_DBUS
81 #include "gui/ipc.h"
82 #endif
83
84 extern BibleSync *biblesync;
85
86 using namespace sword;
87
88 char *sword_locale = NULL;
89 gboolean companion_activity = FALSE;
90
91 /* Unicode collation necessities. */
92 UCollator* collator;
93 UErrorCode collator_status;
94
95 extern gboolean valid_scripture_key;
96
97 // these track together. when one changes, so does the other.
98 static std::map<string, string> abbrev_name2abbrev, abbrev_abbrev2name;
99 typedef std::map<string, string>::iterator abbrev_iter;
100
101 /******************************************************************************
102 * Name
103 * main_add_abbreviation
104 *
105 * Synopsis
106 * #include "main/sword.h"
107 *
108 * void main_add_abbreviation(char *name, char *abbreviation)
109 *
110 * Description
111 * adds an element to each of the abbreviation maps.
112 *
113 * Return value
114 * void
115 */
116
main_add_abbreviation(const char * name,const char * abbreviation)117 void main_add_abbreviation(const char *name, const char *abbreviation)
118 {
119 // let's not be stupid about abbreviations chosen, ok?
120 if (!strchr(abbreviation, '(')) {
121 abbrev_name2abbrev[name] = abbreviation;
122 abbrev_abbrev2name[abbreviation] = name;
123 }
124 }
125
126 /******************************************************************************
127 * Name
128 * main_get_abbreviation
129 *
130 * Synopsis
131 * #include "main/sword.h"
132 *
133 * const char * main_get_abbreviation(const char *name)
134 *
135 * Description
136 * gets abbreviation from real module, if available.
137 *
138 * Return value
139 * const char *
140 */
141
main_get_abbreviation(const char * name)142 const char *main_get_abbreviation(const char *name)
143 {
144 if (name == NULL)
145 return NULL;
146 abbrev_iter it = abbrev_name2abbrev.find(name);
147 if (it != abbrev_name2abbrev.end()) {
148 return it->second.c_str();
149 }
150 return NULL;
151 }
152
153 /******************************************************************************
154 * Name
155 * main_get_name
156 *
157 * Synopsis
158 * #include "main/sword.h"
159 *
160 * const char * main_get_name(const char *abbreviation)
161 *
162 * Description
163 * gets real module name from abbreviation, if available.
164 *
165 * Return value
166 * const char *
167 */
168
main_get_name(const char * abbreviation)169 const char *main_get_name(const char *abbreviation)
170 {
171 if (abbreviation == NULL)
172 return NULL;
173 abbrev_iter it = abbrev_abbrev2name.find(abbreviation);
174 if (it != abbrev_abbrev2name.end()) {
175 return it->second.c_str();
176 }
177 return NULL;
178 }
179
180 /******************************************************************************
181 * Name
182 * main_book_heading
183 *
184 * Synopsis
185 * #include "main/sword.h"
186 *
187 * void main_book_heading(char * mod_name)
188 *
189 * Description
190 *
191 *
192 * Return value
193 * void
194 */
195
main_book_heading(char * mod_name)196 void main_book_heading(char *mod_name)
197 {
198 VerseKey *vkey;
199 SWMgr *mgr = backend->get_mgr();
200
201 backend->display_mod = mgr->Modules[mod_name];
202 vkey = (VerseKey *)(SWKey *)(*backend->display_mod);
203 vkey->setIntros(1);
204 vkey->setAutoNormalize(0);
205 vkey->setChapter(0);
206 vkey->setVerse(0);
207 backend->display_mod->display();
208 }
209
210 /******************************************************************************
211 * Name
212 * main_chapter_heading
213 *
214 * Synopsis
215 * #include "main/module_dialogs.h"
216 *
217 * void main_chapter_heading(char * mod_name)
218 *
219 * Description
220 *
221 *
222 * Return value
223 * void
224 */
225
main_chapter_heading(char * mod_name)226 void main_chapter_heading(char *mod_name)
227 {
228 VerseKey *vkey;
229 SWMgr *mgr = backend->get_mgr();
230
231 backend->display_mod = mgr->Modules[mod_name];
232 backend->display_mod->setKey(settings.currentverse);
233 vkey = (VerseKey *)(SWKey *)(*backend->display_mod);
234 vkey->setIntros(1);
235 vkey->setAutoNormalize(0);
236 vkey->setVerse(0);
237 backend->display_mod->display();
238 }
239
240 /******************************************************************************
241 * Name
242 * main_save_note
243 *
244 * Synopsis
245 * #include "main/sword.h"
246 *
247 * void main_save_note(const gchar * module_name,
248 * const gchar * key_str ,
249 * const gchar * note_str )
250 *
251 * Description
252 *
253 *
254 * Return value
255 * void
256 */
257
main_save_note(const gchar * module_name,const gchar * key_str,const gchar * note_str)258 void main_save_note(const gchar *module_name,
259 const gchar *key_str,
260 const gchar *note_str)
261 {
262 // Massage encoded spaces ("%20") back to real spaces.
263 // This is a sick. unreliable hack that should be removed
264 // after the underlying problem is fixed in Sword.
265 gchar *rework;
266 for (rework = (char *)strstr(note_str, "%20");
267 rework;
268 rework = strstr(rework + 1, "%20")) {
269 *rework = ' ';
270 (void)strcpy(rework + 1, rework + 3);
271 }
272
273 XI_message(("note module %s\nnote key %s\nnote text%s",
274 module_name,
275 key_str,
276 note_str));
277 backend->save_note_entry(module_name, key_str, note_str);
278
279 main_display_commentary(module_name, settings.currentverse);
280 }
281
282 /******************************************************************************
283 * Name
284 * main_delete_note
285 *
286 * Synopsis
287 * #include "main/sword.h"
288 *
289 * void main_delete_note(DIALOG_DATA * d)
290 *
291 * Description
292 *
293 *
294 * Return value
295 * void
296 */
297
main_delete_note(const gchar * module_name,const gchar * key_str)298 void main_delete_note(const gchar *module_name,
299 const gchar *key_str)
300 {
301 backend->set_module_key(module_name, key_str);
302 XI_message(("note module %s\nnote key %s\n",
303 module_name,
304 key_str));
305 backend->delete_entry();
306
307 if ((!strcmp(settings.CommWindowModule, module_name)) &&
308 (!strcmp(settings.currentverse, key_str)))
309 main_display_commentary(module_name, key_str);
310 }
311
312 /******************************************************************************
313 * Name
314 * set_module_unlocked
315 *
316 * Synopsis
317 * #include "bibletext.h"
318 *
319 * void set_module_unlocked(char *mod_name, char *key)
320 *
321 * Description
322 * unlocks locked module -
323 *
324 * Return value
325 * void
326 */
327
main_set_module_unlocked(const char * mod_name,char * key)328 void main_set_module_unlocked(const char *mod_name, char *key)
329 {
330 SWMgr *mgr = backend->get_mgr();
331 mgr->setCipherKey(mod_name, key);
332 }
333
334 /******************************************************************************
335 * Name
336 * main_save_module_key
337 *
338 * Synopsis
339 * #include "main/configs.h"
340 *
341 * void main_save_module_key(gchar * mod_name, gchar * key)
342 *
343 * Description
344 * to unlock locked modules
345 *
346 * Return value
347 * void
348 */
349
main_save_module_key(const char * mod_name,char * key)350 void main_save_module_key(const char *mod_name, char *key)
351 {
352 backend->save_module_key((char *)mod_name, key);
353 }
354
355 /******************************************************************************
356 * Name
357 * main_getText
358 *
359 * Synopsis
360 * #include "main/sword.h"
361 * void main_getText(gchar * key)
362 *
363 * Description
364 * get unabbreviated key
365 *
366 * Return value
367 * char *
368 */
369
main_getText(char * key)370 char *main_getText(char *key)
371 {
372 VerseKey vkey(key);
373 return strdup((char *)vkey.getText());
374 }
375
376 /******************************************************************************
377 * Name
378 * main_getShortText
379 *
380 * Synopsis
381 * #include "main/sword.h"
382 * void main_getShortText(gchar * key)
383 *
384 * Description
385 * get short-name key
386 *
387 * Return value
388 * char *
389 */
390
main_getShortText(char * key)391 char *main_getShortText(char *key)
392 {
393 VerseKey vkey(key);
394 return strdup((char *)vkey.getShortText());
395 }
396
397 /******************************************************************************
398 * Name
399 * main_update_nav_controls
400 *
401 * Synopsis
402 * #include "toolbar_nav.h"
403 *
404 * gchar *main_update_nav_controls(const gchar * key)
405 *
406 * Description
407 * updates the nav toolbar controls
408 *
409 * Return value
410 * gchar *
411 */
412
main_update_nav_controls(const char * module_name,const gchar * key)413 gchar *main_update_nav_controls(const char *module_name, const gchar *key)
414 {
415 char *val_key = backend->get_valid_key(module_name, key);
416
417 // we got a valid key. but was it really a valid key within v11n?
418 // for future use in determining whether to show normal navbar content.
419 navbar_versekey.valid_key = main_is_Bible_key(module_name, key);
420
421 /*
422 * remember verse
423 */
424 xml_set_value("Xiphos", "keys", "verse", val_key);
425 settings.currentverse = xml_get_value("keys", "verse");
426
427 settings.apply_change = FALSE;
428
429 navbar_versekey.module_name = g_string_assign(navbar_versekey.module_name, settings.MainWindowModule);
430 navbar_versekey.key = g_string_assign(navbar_versekey.key, val_key);
431 main_navbar_versekey_set(navbar_versekey, val_key);
432
433 settings.apply_change = TRUE;
434
435 #ifdef HAVE_DBUS
436 IpcObject *ipc = ipc_get_main_ipc();
437 if (ipc)
438 ipc_object_navigation_signal(ipc, (const gchar *)val_key, NULL);
439 #endif
440 return val_key;
441 }
442
443 /******************************************************************************
444 * Name
445 * get_module_key
446 *
447 * Synopsis
448 * #include "main/module.h"
449 *
450 * char *get_module_key(void)
451 *
452 * Description
453 * returns module key
454 *
455 * Return value
456 * char *
457 */
458
main_get_active_pane_key(void)459 char *main_get_active_pane_key(void)
460 {
461 if (settings.havebible) {
462 switch (settings.whichwindow) {
463 case MAIN_TEXT_WINDOW:
464 case COMMENTARY_WINDOW:
465 return (char *)settings.currentverse;
466 break;
467 case DICTIONARY_WINDOW:
468 return (char *)settings.dictkey;
469 break;
470 case parallel_WINDOW:
471 return (char *)settings.cvparallel;
472 break;
473 case BOOK_WINDOW:
474 return (char *)settings.book_key;
475 break;
476 }
477 }
478 return NULL;
479 }
480
481 /******************************************************************************
482 * Name
483 * get_module_name
484 *
485 * Synopsis
486 * #include "main/module.h"
487 *
488 * char *get_module_name(void)
489 *
490 * Description
491 * returns module name
492 *
493 * Return value
494 * char *
495 */
496
main_get_active_pane_module(void)497 char *main_get_active_pane_module(void)
498 {
499 if (settings.havebible) {
500 switch (settings.whichwindow) {
501 case MAIN_TEXT_WINDOW:
502 return (char *)xml_get_value("modules",
503 "bible");
504 break;
505 case COMMENTARY_WINDOW:
506 return (char *)xml_get_value("modules",
507 "comm");
508 break;
509 case DICTIONARY_WINDOW:
510 return (char *)settings.DictWindowModule;
511 break;
512 case BOOK_WINDOW:
513 return (char *)settings.book_mod;
514 break;
515 }
516 }
517 return NULL;
518 }
519
520 /******************************************************************************
521 * Name
522 * module_name_from_description
523 *
524 * Synopsis
525 * #include ".h"
526 *
527 * void module_name_from_description(gchar *mod_name, gchar *description)
528 *
529 * Description
530 *
531 *
532 * Return value
533 * void
534 */
535
main_module_name_from_description(char * description)536 char *main_module_name_from_description(char *description)
537 {
538 return backend->module_name_from_description(description);
539 }
540
541 /******************************************************************************
542 * Name
543 * main_get_sword_version
544 *
545 * Synopsis
546 * #include "sword.h"
547 *
548 * const char *main_get_sword_version(void)
549 *
550 * Description
551 *
552 *
553 * Return value
554 * const char *
555 */
556
main_get_sword_version(void)557 const char *main_get_sword_version(void)
558 {
559 return backend->get_sword_version();
560 }
561
562 /******************************************************************************
563 * Name
564 * get_search_results_text
565 *
566 * Synopsis
567 * #include "sword.h"
568 *
569 * char *get_search_results_text(char * mod_name, char * key)
570 *
571 * Description
572 *
573 *
574 * Return value
575 * char *
576 */
577
main_get_search_results_text(char * mod_name,char * key)578 char *main_get_search_results_text(char *mod_name, char *key)
579 {
580 return backend->get_render_text((char *)mod_name, (char *)key);
581 }
582
583 /******************************************************************************
584 * Name
585 * main_get_path_to_mods
586 *
587 * Synopsis
588 * #include "sword.h"
589 *
590 * gchar *main_get_path_to_mods(void)
591 *
592 * Description
593 * returns the path to the sword modules
594 *
595 * Return value
596 * gchar *
597 */
598
main_get_path_to_mods(void)599 char *main_get_path_to_mods(void)
600 {
601 SWMgr *mgr = backend->get_mgr();
602 char *path = mgr->prefixPath;
603 return (path ? g_strdup(path) : NULL);
604 }
605
606 /******************************************************************************
607 * Name
608 * main_init_language_map
609 *
610 * Synopsis
611 * #include "sword.h"
612 *
613 * void main_init_language_map(void)
614 *
615 * Description
616 * initializes the hard-coded abbrev->name mapping.
617 *
618 * Return value
619 * void
620 */
621
622 typedef std::map<SWBuf, SWBuf> ModLanguageMap;
623 ModLanguageMap languageMap;
624
main_init_language_map()625 void main_init_language_map()
626 {
627 gchar *language_file;
628 FILE *language;
629 gchar *s, *end, *abbrev, *name, *newline;
630 gchar *mapspace;
631 size_t length;
632
633 if ((language_file = gui_general_user_file("languages", FALSE)) == NULL) {
634 gui_generic_warning(_("Xiphos's file for language\nabbreviations is missing."));
635 return;
636 }
637 XI_message(("%s", language_file));
638
639 if ((language = g_fopen(language_file, "r")) == NULL) {
640 gui_generic_warning(_("Xiphos's language abbreviation\nfile cannot be opened."));
641 g_free(language_file);
642 return;
643 }
644 g_free(language_file);
645 (void)fseek(language, 0L, SEEK_END);
646 length = ftell(language);
647 rewind(language);
648
649 if ((length == 0) ||
650 (mapspace = (gchar *)g_malloc(length + 2)) == NULL) {
651 fclose(language);
652 gui_generic_warning(_("Xiphos cannot allocate space\nfor language abbreviations."));
653 return;
654 }
655 if (fread(mapspace, 1, length, language) != length) {
656 fclose(language);
657 g_free(mapspace);
658 gui_generic_warning(_("Xiphos cannot read the\nlanguage abbreviation file."));
659 return;
660 }
661 fclose(language);
662 end = length + mapspace;
663 *end = '\0';
664
665 for (s = mapspace; s < end; ++s) {
666 if ((newline = strchr(s, '\n')) == NULL) {
667 XI_message(("incomplete last line in languages"));
668 break;
669 }
670 *newline = '\0';
671
672 if ((*s == '#') || (s == newline)) {
673 s = newline; // comment or empty line.
674 continue;
675 }
676
677 abbrev = s;
678 if ((name = strchr(s, '\t')) == NULL) {
679 XI_message(("tab-less line in languages"));
680 break;
681 }
682 *(name++) = '\0'; // NUL-terminate abbrev, mark name.
683 languageMap[SWBuf(abbrev)] = SWBuf(name);
684 s = newline;
685 }
686
687 g_free(mapspace);
688 }
689
main_get_language_map(const char * language)690 const char *main_get_language_map(const char *language)
691 {
692 if (language == NULL)
693 return "Unknown";
694 return languageMap[language].c_str();
695 }
696
main_get_module_language_list(void)697 char **main_get_module_language_list(void)
698 {
699 return backend->get_module_language_list();
700 }
701
702 /******************************************************************************
703 * Name
704 * set_sword_locale
705 *
706 * Synopsis
707 * #include "main/sword.h"
708 *
709 * char *set_sword_locale(const char *sys_locale)
710 *
711 * Description
712 * set sword's idea of the locale in which the user operates
713 *
714 * Return value
715 * char *
716 */
set_sword_locale(const char * sys_locale)717 char *set_sword_locale(const char *sys_locale)
718 {
719 if (sys_locale) {
720 SWBuf locale;
721 StringList localelist = LocaleMgr::getSystemLocaleMgr()->getAvailableLocales();
722 StringList::iterator it;
723 int ncmp[3] = {100, 5, 2}; // fixed data
724
725 // length-limited match
726 for (int i = 0; i < 3; ++i) {
727 for (it = localelist.begin(); it != localelist.end(); ++it) {
728 locale = *it;
729 if (!strncmp(sys_locale, locale.c_str(), ncmp[i])) {
730 LocaleMgr::getSystemLocaleMgr()->setDefaultLocaleName(locale.c_str());
731 return g_strdup(locale.c_str());
732 }
733 }
734 }
735 }
736
737 // either we were given a null sys_locale, or it didn't match anything.
738 char *err = g_strdup_printf(_("No matching locale found for `%s'.\n%s"),
739 sys_locale,
740 _("Book names and menus may not be translated."));
741 gui_generic_warning(err);
742 g_free(err);
743 return NULL;
744 }
745
746 /******************************************************************************
747 * Name
748 * backend_init
749 *
750 * Synopsis
751 * #include "main/sword.h"
752 *
753 * void main_init_backend(void)
754 *
755 * Description
756 * start sword
757 *
758 * Return value
759 * void
760 */
761
main_init_backend(void)762 void main_init_backend(void)
763 {
764 StringMgr::setSystemStringMgr(new GS_StringMgr());
765
766 const char *lang = getenv("LANG");
767 if (!lang)
768 lang = "C";
769 sword_locale = set_sword_locale(lang);
770 collator = ucol_open(sword_locale, &collator_status);
771 lang = LocaleMgr::getSystemLocaleMgr()->getDefaultLocaleName();
772
773 backend = new BackEnd();
774
775 backend->init_SWORD(0);
776 settings.path_to_mods = main_get_path_to_mods();
777 //#ifndef DEBUG
778 g_chdir(settings.path_to_mods);
779 //#else
780 // XI_warning(("no chdir(SWORD_PATH) => modmgr 'archive' may not work"));
781 //#endif
782 XI_print(("%s sword-%s\n", "Starting", backend->get_sword_version()));
783 XI_print(("%s\n", "Initiating SWORD"));
784 XI_print(("%s: %s\n", "path to sword", settings.path_to_mods));
785 XI_print(("%s %s\n", "SWORD locale is", lang));
786 XI_print(("%s\n", "Checking for SWORD Modules"));
787 settings.spell_language = strdup(lang);
788 main_init_lists();
789
790 //
791 // BibleSync backend startup. identify the user by name.
792 //
793 biblesync = new BibleSync("Xiphos", VERSION,
794 #ifdef WIN32
795 // in win32 glib, get_real_name and get_user_name are the same.
796 (string)g_get_real_name()
797 #else
798 (string)g_get_real_name() + " (" + g_get_user_name() + ")"
799 #endif
800 );
801 }
802
803 /******************************************************************************
804 * Name
805 * shutdown_sword
806 *
807 * Synopsis
808 * #include "sword.h"
809 *
810 * void shutdown_sword(void)
811 *
812 * Description
813 * close down sword by deleting backend;
814 *
815 * Return value
816 * void
817 */
818
main_shutdown_backend(void)819 void main_shutdown_backend(void)
820 {
821 if (sword_locale)
822 free((char *)sword_locale);
823 sword_locale = NULL;
824 if (backend)
825 delete backend;
826 backend = NULL;
827
828 XI_print(("%s\n", "SWORD is shutdown"));
829 }
830
831 /******************************************************************************
832 * Name
833 * main_dictionary_entry_changed
834 *
835 * Synopsis
836 * #include "main/sword.h"
837 *
838 * void main_dictionary_entry_changed(char * mod_name)
839 *
840 * Description
841 * text in the dictionary entry has changed and the entry activated
842 *
843 * Return value
844 * void
845 */
846
main_dictionary_entry_changed(char * mod_name)847 void main_dictionary_entry_changed(char *mod_name)
848 {
849 gchar *key = NULL;
850
851 if (!mod_name)
852 return;
853 if (strcmp(settings.DictWindowModule, mod_name)) {
854 xml_set_value("Xiphos", "modules", "dict", mod_name);
855 settings.DictWindowModule = xml_get_value("modules", "dict");
856 }
857
858 key = g_strdup((gchar *)gtk_entry_get_text(GTK_ENTRY(widgets.entry_dict)));
859
860 backend->set_module_key(mod_name, key);
861 g_free(key);
862 key = backend->get_module_key();
863
864 xml_set_value("Xiphos", "keys", "dictionary", key);
865 settings.dictkey = xml_get_value("keys", "dictionary");
866
867 main_check_unlock(mod_name, TRUE);
868
869 backend->set_module_key(mod_name, key);
870 backend->display_mod->display();
871
872 gtk_entry_set_text(GTK_ENTRY(widgets.entry_dict), key);
873 g_free(key);
874 }
875
dict_key_list_select(GtkMenuItem * menuitem,gpointer user_data)876 static void dict_key_list_select(GtkMenuItem *menuitem, gpointer user_data)
877 {
878 gtk_entry_set_text(GTK_ENTRY(widgets.entry_dict), (gchar *)user_data);
879 gtk_widget_activate(widgets.entry_dict);
880 }
881
882 /******************************************************************************
883 * Name
884 *
885 *
886 * Synopsis
887 * #include "main/sword.h"
888 *
889 *
890 *
891 * Description
892 * text in the dictionary entry has changed and the entry activated
893 *
894 * Return value
895 * void
896 */
897
main_dictionary_drop_down_new(char * mod_name,char * old_key)898 GtkWidget *main_dictionary_drop_down_new(char *mod_name, char *old_key)
899 {
900 gint count = 9, i;
901 gchar *new_key;
902 gchar *key = NULL;
903 GtkWidget *menu;
904
905 menu = gtk_menu_new();
906
907 if (!settings.havedict || !mod_name)
908 return NULL;
909 if (strcmp(settings.DictWindowModule, mod_name)) {
910 xml_set_value("Xiphos", "modules", "dict",
911 mod_name);
912 settings.DictWindowModule = xml_get_value(
913 "modules", "dict");
914 }
915 key = g_strdup((gchar *)gtk_entry_get_text(GTK_ENTRY(widgets.entry_dict)));
916
917 XI_message(("\nold_key: %s\nkey: %s", old_key, key));
918 backend->set_module_key(mod_name, key);
919 g_free(key);
920 key = backend->get_module_key();
921
922 xml_set_value("Xiphos", "keys", "dictionary", key);
923 settings.dictkey = xml_get_value("keys", "dictionary");
924
925 main_check_unlock(mod_name, TRUE);
926
927 backend->set_module_key(mod_name, key);
928 backend->display_mod->display();
929
930 new_key = g_strdup((char *)backend->display_mod->getKeyText());
931
932 for (i = 0; i < (count / 2) + 1; i++) {
933 (*backend->display_mod)--;
934 }
935
936 for (i = 0; i < count; i++) {
937 free(new_key);
938 (*backend->display_mod)++;
939 new_key = g_strdup((char *)backend->display_mod->getKeyText());
940 /* add menu item */
941 GtkWidget *item =
942 gtk_menu_item_new_with_label((gchar *)new_key);
943 gtk_widget_show(item);
944 g_signal_connect(G_OBJECT(item), "activate",
945 G_CALLBACK(dict_key_list_select),
946 g_strdup(new_key));
947 gtk_container_add(GTK_CONTAINER(menu), item);
948 }
949
950 free(new_key);
951 g_free(key);
952 return menu;
953 }
954
955 /******************************************************************************
956 * Name
957 * main_dictionary_button_clicked
958 *
959 * Synopsis
960 * #include "main/sword.h"
961 *
962 * void main_dictionary_button_clicked(gint direction)
963 *
964 * Description
965 * The back or foward dictinary key button was clicked.
966 * the module key is set to the current dictkey.
967 * then the module is incremented or decremented.
968 * the new key is returned from the module and the dictionary entry is set
969 * to the new key. The entry is then activated.
970 *
971 * Return value
972 * void
973 */
974
main_dictionary_button_clicked(gint direction)975 void main_dictionary_button_clicked(gint direction)
976 {
977 gchar *key = NULL;
978
979 if (!settings.havedict || !settings.DictWindowModule)
980 return;
981
982 backend->set_module_key(settings.DictWindowModule,
983 settings.dictkey);
984 if (direction == 0)
985 (*backend->display_mod)--;
986 else
987 (*backend->display_mod)++;
988 key = g_strdup((char *)backend->display_mod->getKeyText());
989 gtk_entry_set_text(GTK_ENTRY(widgets.entry_dict), key);
990 gtk_widget_activate(widgets.entry_dict);
991 g_free(key);
992 }
993
main_display_book(const char * mod_name,const char * key)994 void main_display_book(const char *mod_name,
995 const char *key)
996 {
997 if (!settings.havebook || !mod_name)
998 return;
999
1000 if (key == NULL)
1001 key = "0";
1002
1003 XI_message(("main_display_book\nmod_name: %s\nkey: %s", mod_name, key));
1004
1005 if (!backend->is_module(mod_name))
1006 return;
1007 if (!settings.book_mod)
1008 settings.book_mod = g_strdup((char *)mod_name);
1009
1010 if (strcmp(settings.book_mod, mod_name)) {
1011 xml_set_value("Xiphos", "modules", "book", mod_name);
1012 gui_reassign_strdup(&settings.book_mod, (gchar *)mod_name);
1013 }
1014
1015 if (!isdigit(key[0])) {
1016 xml_set_value("Xiphos", "keys", "book", key);
1017 settings.book_key = xml_get_value("keys", "book");
1018
1019 backend->set_module(mod_name);
1020 backend->set_treekey(0);
1021 settings.book_offset = backend->treekey_set_key((char *)key);
1022 } else {
1023 settings.book_offset = atol(key);
1024 if (settings.book_offset < 4)
1025 settings.book_offset = 4;
1026 xml_set_value("Xiphos", "keys", "book", key);
1027 settings.book_key = xml_get_value("keys", "book");
1028 xml_set_value("Xiphos", "keys", "offset", key);
1029
1030 backend->set_module(mod_name);
1031 backend->set_treekey(settings.book_offset);
1032 }
1033
1034 main_check_unlock(mod_name, TRUE);
1035
1036 backend->display_mod->display();
1037 main_setup_navbar_book(settings.book_mod, settings.book_offset);
1038 //if (settings.browsing)
1039 gui_update_tab_struct(NULL,
1040 NULL,
1041 NULL,
1042 mod_name,
1043 NULL,
1044 key,
1045 FALSE,
1046 settings.showtexts,
1047 settings.showpreview,
1048 settings.showcomms,
1049 settings.showdicts);
1050 }
1051
main_display_commentary(const char * mod_name,const char * key)1052 void main_display_commentary(const char *mod_name,
1053 const char *key)
1054 {
1055 if (!settings.havecomm || !settings.comm_showing)
1056 return;
1057
1058 if (!mod_name)
1059 mod_name = ((settings.browsing && (cur_passage_tab != NULL))
1060 ? g_strdup(cur_passage_tab->commentary_mod)
1061 : xml_get_value("modules", "comm"));
1062
1063 if (!mod_name || !backend->is_module(mod_name))
1064 return;
1065
1066 int modtype = backend->module_type(mod_name);
1067 if ((modtype != COMMENTARY_TYPE) && (modtype != PERCOM_TYPE))
1068 return; // what are we doing here?
1069
1070 if (!settings.CommWindowModule)
1071 settings.CommWindowModule = g_strdup((gchar *)mod_name);
1072
1073 settings.comm_showing = TRUE;
1074 settings.whichwindow = COMMENTARY_WINDOW;
1075
1076 if (strcmp(settings.CommWindowModule, mod_name)) {
1077 xml_set_value("Xiphos", "modules", "comm", mod_name);
1078 gui_reassign_strdup(&settings.CommWindowModule, (gchar *)mod_name);
1079
1080 // handle a conf directive "Companion=This,That,TheOther"
1081 char *companion = main_get_mod_config_entry(mod_name, "Companion");
1082 gchar **name_set = (companion ? g_strsplit(companion, ",", -1) : NULL);
1083
1084 if (companion &&
1085 (!companion_activity) &&
1086 name_set[0] &&
1087 *name_set[0] &&
1088 backend->is_module(name_set[0]) &&
1089 ((settings.MainWindowModule == NULL) ||
1090 strcmp(name_set[0], settings.MainWindowModule))) {
1091 companion_activity = TRUE;
1092
1093 gint name_length = g_strv_length(name_set);
1094 char *companion_question =
1095 g_strdup_printf(_("Module %s has companion modules:\n%s.\n"
1096 "Would you like to open these as well?%s"),
1097 mod_name, companion,
1098 ((name_length > 1)
1099 ? _("\n\nThe first will open in the main window\n"
1100 "and others in separate windows.")
1101 : ""));
1102
1103 if (gui_yes_no_dialog(companion_question, NULL)) {
1104 main_display_bible(name_set[0], key);
1105 for (int i = 1; i < name_length; i++) {
1106 main_dialogs_open(name_set[i], key, FALSE);
1107 }
1108 }
1109 g_free(companion_question);
1110 companion_activity = FALSE;
1111 }
1112 if (name_set)
1113 g_strfreev(name_set);
1114 if (companion)
1115 g_free(companion);
1116 }
1117
1118 main_check_unlock(mod_name, TRUE);
1119
1120 valid_scripture_key = main_is_Bible_key(mod_name, key);
1121
1122 backend->set_module_key(mod_name, key);
1123 backend->display_mod->display();
1124
1125 valid_scripture_key = TRUE; // leave nice for future use.
1126
1127 //if (settings.browsing)
1128 gui_update_tab_struct(NULL,
1129 mod_name,
1130 NULL,
1131 NULL,
1132 NULL,
1133 NULL,
1134 TRUE,
1135 settings.showtexts,
1136 settings.showpreview,
1137 settings.showcomms,
1138 settings.showdicts);
1139 }
1140
main_display_dictionary(const char * mod_name,const char * key)1141 void main_display_dictionary(const char *mod_name,
1142 const char *key)
1143 {
1144 const gchar *old_key, *feature;
1145
1146 // for devotional use.
1147 gchar buf[10];
1148
1149 if (!settings.havedict || !mod_name)
1150 return;
1151
1152 XI_message(("main_display_dictionary\nmod_name: %s\nkey: %s", mod_name, key));
1153
1154 if (!backend->is_module(mod_name))
1155 return;
1156 if (!settings.DictWindowModule)
1157 settings.DictWindowModule = g_strdup((gchar *)mod_name);
1158
1159 if (key == NULL)
1160 key = (char *)"Grace";
1161
1162 feature = (char *)backend->get_mgr()->getModule(mod_name)->getConfigEntry("Feature");
1163
1164 // turn on "all strong's" iff we have that kind of dictionary.
1165 if (feature && (!strcmp(feature, "HebrewDef") || !strcmp(feature, "GreekDef")))
1166 gtk_widget_show(widgets.all_strongs);
1167 else
1168 gtk_widget_hide(widgets.all_strongs);
1169
1170 if (strcmp(settings.DictWindowModule, mod_name)) {
1171 // new dict -- is it actually a devotional?
1172 time_t curtime;
1173
1174 if (feature && !strcmp(feature, "DailyDevotion")) {
1175 if ((strlen(key) != 5) || // blunt tests.
1176 (key[0] < '0') || (key[0] > '9') ||
1177 (key[1] < '0') || (key[1] > '9') ||
1178 (key[2] != '.') ||
1179 (key[3] < '0') || (key[3] > '9') ||
1180 (key[4] < '0') || (key[4] > '9')) { // not MM.DD
1181 struct tm *loctime;
1182
1183 curtime = time(NULL);
1184 loctime = localtime(&curtime);
1185 strftime(buf, 10, "%m.%d", loctime);
1186 key = buf;
1187 }
1188 }
1189 xml_set_value("Xiphos", "modules", "dict", mod_name);
1190 gui_reassign_strdup(&settings.DictWindowModule, (gchar *)mod_name);
1191 }
1192
1193 // old_key is uppercase
1194 key = g_utf8_strup(key, -1);
1195 old_key = gtk_entry_get_text(GTK_ENTRY(widgets.entry_dict));
1196 if (!strcmp(old_key, key))
1197 main_dictionary_entry_changed(settings.DictWindowModule);
1198 else {
1199 gtk_entry_set_text(GTK_ENTRY(widgets.entry_dict), key);
1200 gtk_widget_activate(widgets.entry_dict);
1201 }
1202
1203 //if (settings.browsing)
1204 gui_update_tab_struct(NULL,
1205 NULL,
1206 mod_name,
1207 NULL,
1208 key,
1209 NULL,
1210 settings.comm_showing,
1211 settings.showtexts,
1212 settings.showpreview,
1213 settings.showcomms,
1214 settings.showdicts);
1215 }
1216
main_display_bible(const char * mod_name,const char * key)1217 void main_display_bible(const char *mod_name,
1218 const char *key)
1219 {
1220 gchar *bs_key = g_strdup(key); // avoid tab data corruption problem.
1221
1222 /* keeps us out of a crash causing loop */
1223 extern guint scroll_adj_signal;
1224 extern GtkAdjustment *adjustment;
1225 if (adjustment)
1226 g_signal_handler_block(adjustment, scroll_adj_signal);
1227
1228 if (!gtk_widget_get_realized(GTK_WIDGET(widgets.html_text)))
1229 return;
1230 if (!mod_name)
1231 mod_name = ((settings.browsing && (cur_passage_tab != NULL))
1232 ? g_strdup(cur_passage_tab->text_mod)
1233 : xml_get_value("modules", "bible"));
1234
1235 if (!settings.havebible || !mod_name)
1236 return;
1237 if (!backend->is_module(mod_name))
1238 return;
1239
1240 int modtype = backend->module_type(mod_name);
1241 if (modtype != TEXT_TYPE)
1242 return; // what are we doing here?
1243
1244 if (!settings.MainWindowModule)
1245 settings.MainWindowModule = g_strdup((gchar *)mod_name);
1246
1247 if (strcmp(settings.currentverse, key)) {
1248 xml_set_value("Xiphos", "keys", "verse",
1249 key);
1250 settings.currentverse = xml_get_value(
1251 "keys", "verse");
1252 }
1253
1254 if (strcmp(settings.MainWindowModule, mod_name)) {
1255 xml_set_value("Xiphos", "modules", "bible", mod_name);
1256 gui_reassign_strdup(&settings.MainWindowModule, (gchar *)mod_name);
1257
1258 // handle a conf directive "Companion=This,That,TheOther"
1259 char *companion = main_get_mod_config_entry(mod_name, "Companion");
1260 gchar **name_set = (companion ? g_strsplit(companion, ",", -1) : NULL);
1261
1262 if (companion &&
1263 (!companion_activity) &&
1264 name_set[0] &&
1265 *name_set[0] &&
1266 backend->is_module(name_set[0]) &&
1267 ((settings.CommWindowModule == NULL) ||
1268 strcmp(name_set[0], settings.CommWindowModule))) {
1269 companion_activity = TRUE;
1270
1271 gint name_length = g_strv_length(name_set);
1272 char *companion_question =
1273 g_strdup_printf(_("Module %s has companion modules:\n%s.\n"
1274 "Would you like to open these as well?%s"),
1275 mod_name, companion,
1276 ((name_length > 1)
1277 ? _("\n\nThe first will open in the main window\n"
1278 "and others in separate windows.")
1279 : ""));
1280
1281 if (gui_yes_no_dialog(companion_question, NULL)) {
1282 main_display_commentary(name_set[0], key);
1283 for (int i = 1; i < name_length; i++) {
1284 main_dialogs_open(name_set[i], key, FALSE);
1285 }
1286 }
1287 g_free(companion_question);
1288 companion_activity = FALSE;
1289 }
1290 if (name_set)
1291 g_strfreev(name_set);
1292 if (companion)
1293 g_free(companion);
1294
1295 navbar_versekey.module_name = g_string_assign(navbar_versekey.module_name,
1296 settings.MainWindowModule);
1297
1298 navbar_versekey.key = g_string_assign(navbar_versekey.key,
1299 settings.currentverse);
1300
1301 main_search_sidebar_fill_bounds_combos();
1302 }
1303
1304 settings.whichwindow = MAIN_TEXT_WINDOW;
1305
1306 main_check_unlock(mod_name, TRUE);
1307
1308 valid_scripture_key = main_is_Bible_key(mod_name, key);
1309
1310 if (backend->module_has_testament(mod_name,
1311 backend->get_key_testament(mod_name, key))) {
1312 backend->set_module_key(mod_name, key);
1313 backend->display_mod->display();
1314 } else {
1315 gchar *val_key = NULL;
1316
1317 if (backend->get_key_testament(mod_name, key) == 1)
1318 val_key = main_update_nav_controls(mod_name, "Matthew 1:1");
1319 else
1320 val_key = main_update_nav_controls(mod_name, "Genesis 1:1");
1321
1322 backend->set_module_key(mod_name, val_key);
1323 backend->display_mod->display();
1324 g_free(val_key);
1325 }
1326
1327 valid_scripture_key = TRUE; // leave nice for future use.
1328
1329 XI_message(("mod_name = %s", mod_name));
1330 //if (settings.browsing) {
1331 gui_update_tab_struct(mod_name,
1332 NULL,
1333 NULL,
1334 NULL,
1335 NULL,
1336 NULL,
1337 settings.comm_showing,
1338 settings.showtexts,
1339 settings.showpreview,
1340 settings.showcomms,
1341 settings.showdicts);
1342 gui_set_tab_label(settings.currentverse, FALSE);
1343 //}
1344
1345 gui_change_window_title(settings.MainWindowModule);
1346 // (called _after_ tab data updated so not overwritten with old tab)
1347
1348 /*
1349 * change parallel verses
1350 */
1351 if (settings.dockedInt)
1352 main_update_parallel_page();
1353 else {
1354 if (settings.showparatab)
1355 gui_keep_parallel_tab_in_sync();
1356 else
1357 gui_keep_parallel_dialog_in_sync();
1358 }
1359
1360 // multicast now, iff user has not asked for keyboard-only xmit.
1361 if (!settings.bs_keyboard)
1362 biblesync_prep_and_xmit(mod_name, bs_key);
1363 g_free(bs_key);
1364
1365 if (adjustment)
1366 g_signal_handler_unblock(adjustment, scroll_adj_signal);
1367 }
1368
1369 /******************************************************************************
1370 * Name
1371 * main_display_devotional
1372 *
1373 * Synopsis
1374 * #include "main/sword.h"
1375 *
1376 * void main_display_devotional(void)
1377 *
1378 * Description
1379 *
1380 *
1381 * Return value
1382 * void
1383 */
1384
main_display_devotional(void)1385 void main_display_devotional(void)
1386 {
1387 gchar buf[10];
1388 gchar *prettybuf;
1389 time_t curtime;
1390 struct tm *loctime;
1391 gchar *text;
1392
1393 /*
1394 * This makes sense only if you've installed & defined one.
1395 */
1396 if (settings.devotionalmod == NULL) {
1397 GList *glist = get_list(DEVOTION_LIST);
1398
1399 if (g_list_length(glist) != 0) {
1400 xml_set_value("Xiphos", "modules", "devotional",
1401 (char *)glist->data);
1402 gui_reassign_strdup(&settings.devotionalmod, (gchar *)glist->data);
1403 } else {
1404 gui_generic_warning(_("Daily devotional was requested, but there are none installed."));
1405 }
1406 }
1407
1408 /*
1409 * Get the current time, converted to local time.
1410 */
1411 curtime = time(NULL);
1412 loctime = localtime(&curtime);
1413 strftime(buf, 10, "%m.%d", loctime);
1414 prettybuf = g_strdup_printf("<b>%s %d</b>",
1415 gettext(month_names[loctime->tm_mon]),
1416 loctime->tm_mday);
1417
1418 text = backend->get_render_text(settings.devotionalmod, buf);
1419 if (text) {
1420 main_entry_display(settings.show_previewer_in_sidebar
1421 ? sidebar.html_viewer_widget
1422 : widgets.html_previewer_text,
1423 settings.devotionalmod, text, prettybuf, TRUE);
1424 g_free(text);
1425 }
1426 g_free(prettybuf);
1427 }
1428
main_setup_displays(void)1429 void main_setup_displays(void)
1430 {
1431 backend->textDisplay = new GTKChapDisp(widgets.html_text, backend);
1432 backend->commDisplay = new GTKEntryDisp(widgets.html_comm, backend);
1433 backend->bookDisplay = new GTKEntryDisp(widgets.html_book, backend);
1434 backend->dictDisplay = new GTKEntryDisp(widgets.html_dict, backend);
1435 }
1436
main_get_module_language(const char * module_name)1437 const char *main_get_module_language(const char *module_name)
1438 {
1439 return backend->module_get_language(module_name);
1440 }
1441
1442 /******************************************************************************
1443 * Name
1444 * main_check_for_option
1445 *
1446 * Synopsis
1447 * #include ".h"
1448 *
1449 * gint main_check_for_option(const gchar * mod_name, const gchar * key, const gchar * option)
1450 *
1451 * Description
1452 * get any option for a module
1453 *
1454 * Return value
1455 * gint
1456 */
1457
main_check_for_option(const gchar * mod_name,const gchar * key,const gchar * option)1458 gint main_check_for_option(const gchar *mod_name, const gchar *key, const gchar *option)
1459 {
1460 return backend->has_option(mod_name, key, option);
1461 }
1462
1463 /******************************************************************************
1464 * Name
1465 * main_check_for_global_option
1466 *
1467 * Synopsis
1468 * #include ".h"
1469 *
1470 * gint main_check_for_global_option(const gchar * mod_name, const gchar * option)
1471 *
1472 * Description
1473 * get global options for a module
1474 *
1475 * Return value
1476 * gint
1477 */
1478
main_check_for_global_option(const gchar * mod_name,const gchar * option)1479 gint main_check_for_global_option(const gchar *mod_name, const gchar *option)
1480 {
1481 return backend->has_global_option(mod_name, option);
1482 }
1483
1484 /******************************************************************************
1485 * Name
1486 * main_is_module
1487 *
1488 * Synopsis
1489 * #include "main/module.h"
1490 *
1491 * int main_is_module(char * mod_name)
1492 *
1493 * Description
1494 * check for presents of a module by name
1495 *
1496 * Return value
1497 * int
1498 */
1499
main_is_module(char * mod_name)1500 int main_is_module(char *mod_name)
1501 {
1502 return backend->is_module(mod_name);
1503 }
1504
1505 /******************************************************************************
1506 * Name
1507 * main_has_search_framework
1508 *
1509 * Synopsis
1510 * #include "main/module.h"
1511 *
1512 * int main_has_search_framework(char * mod_name)
1513 *
1514 * Description
1515 * tells us whether CLucene is available
1516 *
1517 * Return value
1518 * int (boolean)
1519 */
1520
main_has_search_framework(char * mod_name)1521 int main_has_search_framework(char *mod_name)
1522 {
1523 SWMgr *mgr = backend->get_mgr();
1524 SWModule *mod = mgr->getModule(mod_name);
1525 return (mod && mod->hasSearchFramework());
1526 }
1527
1528 /******************************************************************************
1529 * Name
1530 * main_optimal_search
1531 *
1532 * Synopsis
1533 * #include "main/module.h"
1534 *
1535 * int main_optimal_search(char * mod_name)
1536 *
1537 * Description
1538 * tells us whether a CLucene index exists
1539 *
1540 * Return value
1541 * int (boolean)
1542 */
1543
main_optimal_search(char * mod_name)1544 int main_optimal_search(char *mod_name)
1545 {
1546 SWMgr *mgr = backend->get_mgr();
1547 SWModule *mod = mgr->Modules.find(mod_name)->second;
1548 return mod->isSearchOptimallySupported("God", -4, 0, 0);
1549 }
1550
main_get_mod_config_entry(const char * module_name,const char * entry)1551 char *main_get_mod_config_entry(const char *module_name,
1552 const char *entry)
1553 {
1554 return backend->get_config_entry((char *)module_name, (char *)entry);
1555 }
1556
main_get_mod_config_file(const char * module_name,const char * moddir)1557 char *main_get_mod_config_file(const char *module_name,
1558 const char *moddir)
1559 {
1560 #ifdef SWORD_SHOULD_HAVE_A_WAY_TO_GET_A_CONF_FILENAME_FROM_A_MODNAME
1561 return backend->get_config_file((char *)module_name, (char *)moddir);
1562 #else
1563 GDir *dir;
1564 SWBuf name;
1565
1566 name = moddir;
1567 name += "/mods.d";
1568 if ((dir = g_dir_open(name, 0, NULL))) {
1569 const gchar *ent;
1570
1571 g_dir_rewind(dir);
1572 while ((ent = g_dir_read_name(dir))) {
1573 name = moddir;
1574 name += "/mods.d/";
1575 name += ent;
1576 SWConfig *config = new SWConfig(name.c_str());
1577 if (config->getSections().find(module_name) !=
1578 config->getSections().end()) {
1579 gchar *ret_name = g_strdup(ent);
1580 g_dir_close(dir);
1581 delete config;
1582 return ret_name;
1583 } else
1584 delete config;
1585 }
1586 g_dir_close(dir);
1587 }
1588 return NULL;
1589 #endif
1590 }
1591
main_is_mod_rtol(const char * module_name)1592 int main_is_mod_rtol(const char *module_name)
1593 {
1594 char *direction = backend->get_config_entry((char *)module_name, (char *)"Direction");
1595 return (direction && !strcmp(direction, "RtoL"));
1596 }
1597
1598 /******************************************************************************
1599 * Name
1600 * main_has_cipher_tag
1601 *
1602 * Synopsis
1603 * #include "main/.h"
1604 *
1605 * int main_has_cipher_tag(char *mod_name)
1606 *
1607 * Description
1608 *
1609 *
1610 * Return value
1611 * int
1612 */
1613
main_has_cipher_tag(char * mod_name)1614 int main_has_cipher_tag(char *mod_name)
1615 {
1616 gchar *cipherkey = backend->get_config_entry(mod_name, (char *)"CipherKey");
1617 int retval = (cipherkey != NULL);
1618 g_free(cipherkey);
1619 return retval;
1620 }
1621
1622 #define CIPHER_INTRO \
1623 _("<b>Locked Module.</b>\n\n<u>You are opening a module which requires a <i>key</i>.</u>\n\nThe module is locked, meaning that the content is encrypted by its publisher, and you must enter its key in order for the content to become useful. This key should have been received by you on the web page which confirmed your purchase, or perhaps sent via email after purchase.\n\nPlease enter the key in the dialog.")
1624
1625 /******************************************************************************
1626 * Name
1627 * main_check_unlock
1628 *
1629 * Synopsis
1630 * #include "main/.h"
1631 *
1632 * int main_check_unlock(const char *mod_name)
1633 *
1634 * Description
1635 *
1636 *
1637 * Return value
1638 * int
1639 */
1640
main_check_unlock(const char * mod_name,gboolean conditional)1641 void main_check_unlock(const char *mod_name, gboolean conditional)
1642 {
1643 gchar *cipher_old = main_get_mod_config_entry(mod_name, "CipherKey");
1644
1645 /* if forced by the unlock menu item, or it's present but empty... */
1646 if (!conditional ||
1647 ((cipher_old != NULL) && (*cipher_old == '\0'))) {
1648
1649 if (conditional) {
1650 GtkWidget *dialog;
1651 dialog = gtk_message_dialog_new_with_markup(NULL, /* no need for a parent window */
1652 GTK_DIALOG_DESTROY_WITH_PARENT,
1653 GTK_MESSAGE_INFO,
1654 GTK_BUTTONS_OK,
1655 CIPHER_INTRO);
1656 g_signal_connect_swapped(dialog, "response",
1657 G_CALLBACK(gtk_widget_destroy),
1658 dialog);
1659 gtk_widget_show(dialog);
1660 }
1661
1662 gchar *cipher_key = gui_add_cipher_key(mod_name, cipher_old);
1663 if (cipher_key) {
1664 ModuleCacheErase(mod_name);
1665 redisplay_to_realign();
1666 g_free(cipher_key);
1667 }
1668 }
1669 g_free(cipher_old);
1670 }
1671
1672 /******************************************************************************
1673 * Name
1674 * main_get_striptext
1675 *
1676 * Synopsis
1677 * #include "main/sword.h"
1678 *
1679 * char *main_get_striptext(char *module_name, char *key)
1680 *
1681 * Description
1682 *
1683 *
1684 * Return value
1685 * char *
1686 */
1687
main_get_striptext(char * module_name,char * key)1688 char *main_get_striptext(char *module_name, char *key)
1689 {
1690 return backend->get_strip_text(module_name, key);
1691 }
1692
1693 /******************************************************************************
1694 * Name
1695 * main_get_rendered_text
1696 *
1697 * Synopsis
1698 * #include "main/sword.h"
1699 *
1700 * char *main_get_rendered_text(char *module_name, char *key)
1701 *
1702 * Description
1703 *
1704 *
1705 * Return value
1706 * char *
1707 */
1708
main_get_rendered_text(const char * module_name,const char * key)1709 char *main_get_rendered_text(const char *module_name, const char *key)
1710 {
1711 return backend->get_render_text(module_name, key);
1712 }
1713
1714 /******************************************************************************
1715 * Name
1716 * main_get_raw_text
1717 *
1718 * Synopsis
1719 * #include "main/sword.h"
1720 *
1721 * char *main_get_raw_text(char *module_name, char *key)
1722 *
1723 * Description
1724 *
1725 *
1726 * Return value
1727 * char *
1728 */
1729
main_get_raw_text(char * module_name,char * key)1730 char *main_get_raw_text(char *module_name, char *key)
1731 {
1732 return backend->get_raw_text(module_name, key);
1733 }
1734
1735 /******************************************************************************
1736 * Name
1737 * main_get_mod_type
1738 *
1739 * Synopsis
1740 * #include "main/module.h"
1741 *
1742 * int main_get_mod_type(char * mod_name)
1743 *
1744 * Description
1745 *
1746 *
1747 * Return value
1748 * int
1749 */
1750
main_get_mod_type(char * mod_name)1751 int main_get_mod_type(char *mod_name)
1752 {
1753
1754 return backend->module_type(mod_name);
1755 }
1756
1757 /******************************************************************************
1758 * Name
1759 * main_get_module_description
1760 *
1761 * Synopsis
1762 * #include "main/module.h"
1763 *
1764 * gchar *main_get_module_description(gchar * module_name)
1765 *
1766 * Description
1767 *
1768 *
1769 * Return value
1770 * gchar *
1771 */
1772
main_get_module_description(const char * module_name)1773 const char *main_get_module_description(const char *module_name)
1774 {
1775 return backend->module_description(module_name);
1776 }
1777
1778 /******************************************************************************
1779 * Name
1780 * main_format_number
1781 *
1782 * Synopsis
1783 * #include "main/sword.h"
1784 * char *main_format_number(int x)
1785 *
1786 * Description
1787 * returns a digit string in either "latinate arabic" (normal) or
1788 * farsi characters.
1789 * re_encode_digits is chosen at startup in settings.c.
1790 * caller must free allocated string space when finished with it.
1791 *
1792 * Return value
1793 * char *
1794 */
1795
1796 int re_encode_digits = FALSE;
1797
1798 char *
main_format_number(int x)1799 main_format_number(int x)
1800 {
1801 char *digits = g_strdup_printf("%d", x);
1802
1803 if (re_encode_digits) {
1804 //
1805 // "\333\260" is farsi "zero".
1806 //
1807 char *d, *f, *farsi = g_new(char, 2 * (strlen(digits) + 1));
1808 // 2 "chars" per farsi-displayed digit + slop.
1809
1810 for (d = digits, f = farsi; *d; ++d) {
1811 *(f++) = '\333';
1812 *(f++) = '\260' + ((*d) - '0');
1813 }
1814 *f = '\0';
1815 g_free(digits);
1816 return farsi;
1817 }
1818 return digits;
1819 }
1820
1821 /******************************************************************************
1822 * Name
1823 * main_flush_widgets_content
1824 *
1825 * Synopsis
1826 * #include "main/sword.h"
1827 * void main_flush_widgets_content()
1828 *
1829 * Description
1830 * cleans content from all subwindow widgets.
1831 *
1832 * Return value
1833 * int
1834 */
main_flush_widgets_content(void)1835 void main_flush_widgets_content(void)
1836 {
1837 GString *blank_html_content = g_string_new(NULL);
1838 g_string_printf(blank_html_content,
1839 "<html><head></head><body bgcolor=\"%s\" text=\"%s\"> </body></html>",
1840 settings.bible_bg_color, settings.bible_text_color);
1841
1842 if (gtk_widget_get_realized(GTK_WIDGET(widgets.html_text)))
1843 HtmlOutput(blank_html_content->str, widgets.html_text, NULL, NULL);
1844 if (gtk_widget_get_realized(GTK_WIDGET(widgets.html_comm)))
1845 HtmlOutput(blank_html_content->str, widgets.html_comm, NULL, NULL);
1846 if (gtk_widget_get_realized(GTK_WIDGET(widgets.html_dict)))
1847 HtmlOutput(blank_html_content->str, widgets.html_dict, NULL, NULL);
1848 if (gtk_widget_get_realized(GTK_WIDGET(widgets.html_book)))
1849 HtmlOutput(blank_html_content->str, widgets.html_book, NULL, NULL);
1850 g_string_free(blank_html_content, TRUE);
1851 }
1852
1853 /******************************************************************************
1854 * Name
1855 * main_is_Bible_key
1856 *
1857 * Synopsis
1858 * #include "main/sword.h"
1859 * void main_is_Bible_key()
1860 *
1861 * Description
1862 * returns boolean status of whether input is a legit Bible key.
1863 *
1864 * Return value
1865 * gboolean
1866 */
main_is_Bible_key(const gchar * name,const gchar * key)1867 gboolean main_is_Bible_key(const gchar *name, const gchar *key)
1868 {
1869 return (gboolean)(backend->is_Bible_key(name, key, settings.currentverse) != 0);
1870 }
1871
1872 /******************************************************************************
1873 * Name
1874 * main_get_osisref_from_key
1875 *
1876 * Synopsis
1877 * #include "main/sword.h"
1878 * void main_get_osisref_from_key()
1879 *
1880 * Description
1881 * returns OSISRef-formatted key value.
1882 *
1883 * Return value
1884 * const char *
1885 */
1886 const char *
main_get_osisref_from_key(const char * module,const char * key)1887 main_get_osisref_from_key(const char *module, const char *key)
1888 {
1889 return backend->get_osisref_from_key(module, key);
1890 }
1891