1 /*
2  * Xiphos Bible Study Tool
3  * navbar_versekey.cc - glue between all navbar_versekey and sword
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 #include <gtk/gtk.h>
26 #include <swmodule.h>
27 #include <versekey.h>
28 
29 #include "main/module_dialogs.h"
30 #include "main/navbar_versekey.h"
31 #include "main/settings.h"
32 #include "main/sword.h"
33 #include "main/xml.h"
34 
35 #include "gui/navbar_versekey.h"
36 #include "gui/tabbed_browser.h"
37 
38 #ifdef USE_WEBKIT_EDITOR
39 #include "editor/webkit_editor.h"
40 #else
41 #include "editor/slib-editor.h"
42 #endif
43 
44 #include "backend/sword_main.hh"
45 
46 #include "gui/debug_glib_null.h"
47 
48 extern gboolean do_display;
49 extern gboolean do_display_dict;
50 
51 static DIALOG_DATA *c_dialog;
52 static EDITOR *c_editor;
53 static gint c_type;
54 
55 /******************************************************************************
56  * Name
57  *   main_get_valid_key
58  *
59  * Synopsis
60  *   #include "main/navbar_versekey.h"
61  *
62  *   const char *main_get_valid_key(const char *module, const char * key)
63  *
64  * Description
65  *   get a valid versekey from the backend
66  *
67  * Return value
68  *   void
69  */
70 
main_get_valid_key(const char * module_name,const char * key)71 const char *main_get_valid_key(const char *module_name, const char *key)
72 {
73 	return backend->get_valid_key(module_name, key);
74 }
75 
76 /******************************************************************************
77  * Name
78  *  main_navbar_versekey_spin_book
79  *
80  * Synopsis
81  *   #include "main/navbar_versekey.h"
82  *
83  *   void main_navbar_versekey_spin_book(NAVBAR_VERSEKEY navbar, int direction)
84  *
85  * Description
86  *
87  *
88  * Return value
89  *   void
90  */
91 
main_navbar_versekey_spin_book(NAVBAR_VERSEKEY navbar,int direction)92 void main_navbar_versekey_spin_book(NAVBAR_VERSEKEY navbar, int direction)
93 {
94 	char *tmpkey = NULL;
95 	int book;
96 
97 	if (!navbar.module_name->len)
98 		return;
99 
100 	SWModule *mod = backend->get_SWModule(navbar.module_name->str);
101 	if (!mod)
102 		return;
103 
104 	VerseKey *vkey = (VerseKey *)mod->createKey();
105 	tmpkey = backend->get_valid_key(navbar.module_name->str, navbar.key->str);
106 
107 	vkey->setAutoNormalize(1);
108 	vkey->setText(tmpkey);
109 
110 	book = vkey->getBook() + (direction ? 1 : -1);
111 	vkey->setBook(book);
112 
113 	tmpkey = g_strdup_printf("%s 1:1", vkey->getBookName());
114 	gtk_entry_set_text(GTK_ENTRY(navbar.lookup_entry), tmpkey);
115 	gtk_widget_activate(navbar.lookup_entry);
116 	g_free(tmpkey);
117 	delete vkey;
118 }
119 
120 /******************************************************************************
121  * Name
122  *  main_navbar_versekey_spin_chapter
123  *
124  * Synopsis
125  *   #include "main/navbar_versekey.h"
126  *
127  *   void main_navbar_versekey_spin_chapter(NAVBAR_VERSEKEY navbar, int direction)
128  *
129  * Description
130  *
131  *
132  * Return value
133  *   void
134  */
135 
main_navbar_versekey_spin_chapter(NAVBAR_VERSEKEY navbar,int direction)136 void main_navbar_versekey_spin_chapter(NAVBAR_VERSEKEY navbar, int direction)
137 {
138 	char *tmpkey = NULL;
139 	int chapter;
140 
141 	if (!navbar.module_name->len)
142 		return;
143 
144 	SWModule *mod = backend->get_SWModule(navbar.module_name->str);
145 	if (!mod)
146 		return;
147 
148 	VerseKey *vkey = (VerseKey *)mod->createKey();
149 	tmpkey = backend->get_valid_key(navbar.module_name->str, navbar.key->str);
150 
151 	vkey->setAutoNormalize(1);
152 	vkey->setText(tmpkey);
153 
154 	chapter = vkey->getChapter() + (direction ? 1 : -1);
155 	vkey->setChapter(chapter);
156 
157 	tmpkey = g_strdup_printf("%s %d:1", vkey->getBookName(), vkey->getChapter());
158 	gtk_entry_set_text(GTK_ENTRY(navbar.lookup_entry), tmpkey);
159 	gtk_widget_activate(navbar.lookup_entry);
160 	g_free(tmpkey);
161 	delete vkey;
162 }
163 
164 /******************************************************************************
165  * Name
166  *  main_navbar_versekey_spin_verse
167  *
168  * Synopsis
169  *   #include "main/navbar_versekey.h"
170  *
171  *   char * main_navbar_versekey_spin_verse(NAVBAR_VERSEKEY navbar, int direction)
172  *
173  * Description
174  *
175  *
176  * Return value
177  *   void
178  */
179 
main_navbar_versekey_spin_verse(NAVBAR_VERSEKEY navbar,int direction)180 void main_navbar_versekey_spin_verse(NAVBAR_VERSEKEY navbar, int direction)
181 {
182 
183 	char *tmpkey = NULL;
184 	int verse;
185 
186 	if (!navbar.module_name->len)
187 		return;
188 
189 	SWModule *mod = backend->get_SWModule(navbar.module_name->str);
190 	if (!mod)
191 		return;
192 
193 	VerseKey *vkey = (VerseKey *)mod->createKey();
194 	tmpkey = backend->get_valid_key(navbar.module_name->str, navbar.key->str);
195 
196 	vkey->setAutoNormalize(1);
197 	vkey->setText(tmpkey);
198 
199 	verse = vkey->getVerse() + (direction ? 1 : -1);
200 	vkey->setVerse(verse);
201 
202 	tmpkey = g_strdup_printf("%s %d:%d", vkey->getBookName(),
203 				 vkey->getChapter(), vkey->getVerse());
204 	gtk_entry_set_text(GTK_ENTRY(navbar.lookup_entry), tmpkey);
205 	gtk_widget_activate(navbar.lookup_entry);
206 	g_free(tmpkey);
207 	delete vkey;
208 }
209 
210 /******************************************************************************
211  * Name
212  *  on_nt_book_menu_select
213  *
214  * Synopsis
215  *   #include "main/navbar_versekey.h"
216  *
217  *   void on_nt_book_menu_select(GtkMenuItem * menuitem, gpointer user_data)
218  *
219  * Description
220  *   user selected new new testament book from dropdown menu - change verse key
221  *   to new book set lookup_entry text to new verse key and activate entry
222  *
223  * Return value
224  *   void
225  */
226 
on_nt_book_menu_select(GtkMenuItem * menuitem,gpointer user_data)227 static void on_nt_book_menu_select(GtkMenuItem *menuitem, gpointer user_data)
228 {
229 	GtkWidget *entry = NULL;
230 	int book = GPOINTER_TO_INT(user_data);
231 	gchar *name, *key;
232 
233 	switch (c_type) {
234 	case NB_MAIN:
235 		name = navbar_versekey.module_name->str;
236 		key = navbar_versekey.key->str;
237 		entry = navbar_versekey.lookup_entry;
238 		break;
239 
240 	case NB_PARALLEL:
241 		name = navbar_parallel.module_name->str;
242 		key = navbar_parallel.key->str;
243 		entry = navbar_parallel.lookup_entry;
244 		break;
245 
246 	case NB_DIALOG:
247 		if (!c_dialog)
248 			return;
249 		name = c_dialog->navbar.module_name->str;
250 		key = c_dialog->navbar.key->str;
251 		entry = c_dialog->navbar.lookup_entry;
252 		break;
253 
254 	case NB_EDITOR:
255 		if (!c_editor)
256 			return;
257 		name = c_editor->navbar.module_name->str;
258 		key = c_editor->navbar.key->str;
259 		entry = c_editor->navbar.lookup_entry;
260 		break;
261 	}
262 
263 	if (entry) {
264 		SWModule *mod = backend->get_SWModule(name);
265 		if (mod) {
266 			VerseKey *vkey = (VerseKey *)mod->createKey();
267 			vkey->setAutoNormalize(1);
268 			vkey->setText(key);
269 			vkey->setTestament(2);
270 			vkey->setBook(book + 1);
271 
272 			gtk_entry_set_text(GTK_ENTRY(entry), vkey->getText());
273 			gtk_widget_activate(entry);
274 
275 			delete vkey;
276 		}
277 	}
278 }
279 
280 /******************************************************************************
281  * Name
282  *  on_ot_book_menu_select
283  *
284  * Synopsis
285  *   #include "main/navbar_versekey.h"
286  *
287  *   void on_ot_book_menu_select(GtkMenuItem * menuitem, gpointer user_data)
288  *
289  * Description
290  *   user selected new old testament book from dropdown menu - change verse key
291  *   to new book set lookup_entry text to new verse key and activate entry
292  *
293  * Return value
294  *   void
295  */
296 
on_ot_book_menu_select(GtkMenuItem * menuitem,gpointer user_data)297 static void on_ot_book_menu_select(GtkMenuItem *menuitem, gpointer user_data)
298 {
299 	GtkWidget *entry = NULL;
300 	int book = GPOINTER_TO_INT(user_data);
301 	gchar *name, *key;
302 
303 	switch (c_type) {
304 	case NB_MAIN:
305 		name = navbar_versekey.module_name->str;
306 		key = navbar_versekey.key->str;
307 		entry = navbar_versekey.lookup_entry;
308 		break;
309 
310 	case NB_PARALLEL:
311 		name = navbar_parallel.module_name->str;
312 		key = navbar_parallel.key->str;
313 		entry = navbar_parallel.lookup_entry;
314 		break;
315 
316 	case NB_DIALOG:
317 		if (!c_dialog)
318 			return;
319 		name = c_dialog->navbar.module_name->str;
320 		key = c_dialog->navbar.key->str;
321 		entry = c_dialog->navbar.lookup_entry;
322 		break;
323 
324 	case NB_EDITOR:
325 		if (!c_editor)
326 			return;
327 		name = c_editor->navbar.module_name->str;
328 		key = c_editor->navbar.key->str;
329 		entry = c_editor->navbar.lookup_entry;
330 		break;
331 	}
332 
333 	if (entry) {
334 		SWModule *mod = backend->get_SWModule(name);
335 		if (mod) {
336 			VerseKey *vkey = (VerseKey *)mod->createKey();
337 			vkey->setAutoNormalize(1);
338 			vkey->setText(key);
339 			vkey->setTestament(1);
340 			vkey->setBook(book + 1);
341 
342 			gtk_entry_set_text(GTK_ENTRY(entry), vkey->getText());
343 			gtk_widget_activate(entry);
344 
345 			delete vkey;
346 		}
347 	}
348 }
349 
350 /******************************************************************************
351  * Name
352  *  on_chapter_menu_select
353  *
354  * Synopsis
355  *   #include "main/navbar_versekey.h"
356  *
357  *   void on_chapter_menu_select(GtkMenuItem * menuitem, gpointer user_data)
358  *
359  * Description
360  *   user selected new chapter from dropdown menu - change verse key to new chapter
361  *   set lookup_entry text to new verse key and activate entry
362  *
363  * Return value
364  *   void
365  */
366 
on_chapter_menu_select(GtkMenuItem * menuitem,gpointer user_data)367 static void on_chapter_menu_select(GtkMenuItem *menuitem, gpointer user_data)
368 {
369 	GtkWidget *entry = NULL;
370 	int chapter = GPOINTER_TO_INT(user_data);
371 	gchar *name, *key;
372 
373 	switch (c_type) {
374 	case NB_MAIN:
375 		name = navbar_versekey.module_name->str;
376 		key = navbar_versekey.key->str;
377 		entry = navbar_versekey.lookup_entry;
378 		break;
379 
380 	case NB_PARALLEL:
381 		name = navbar_parallel.module_name->str;
382 		key = navbar_parallel.key->str;
383 		entry = navbar_parallel.lookup_entry;
384 		break;
385 
386 	case NB_DIALOG:
387 		if (!c_dialog)
388 			return;
389 		name = c_dialog->navbar.module_name->str;
390 		key = c_dialog->navbar.key->str;
391 		entry = c_dialog->navbar.lookup_entry;
392 		break;
393 
394 	case NB_EDITOR:
395 		if (!c_editor)
396 			return;
397 		name = c_editor->navbar.module_name->str;
398 		key = c_editor->navbar.key->str;
399 		entry = c_editor->navbar.lookup_entry;
400 		break;
401 	}
402 	if (entry) {
403 		SWModule *mod = backend->get_SWModule(name);
404 		if (mod) {
405 			VerseKey *vkey = (VerseKey *)mod->createKey();
406 			vkey->setAutoNormalize(1);
407 			vkey->setText(key);
408 			vkey->setChapter(chapter);
409 
410 			gtk_entry_set_text(GTK_ENTRY(entry), vkey->getText());
411 			gtk_widget_activate(entry);
412 
413 			delete vkey;
414 		}
415 	}
416 }
417 
418 /******************************************************************************
419  * Name
420  *  on_verse_menu_select
421  *
422  * Synopsis
423  *   #include "main/navbar_versekey.h"
424  *
425  *   void on_verse_menu_select(GtkMenuItem * menuitem, gpointer user_data)
426  *
427  * Description
428  *   user selected new verse from dropdown menu - change verse key to new verse
429  *   set lookup_entry text to new verse key and activate entry
430  *
431  * Return value
432  *   void
433  */
434 
on_verse_menu_select(GtkMenuItem * menuitem,gpointer user_data)435 static void on_verse_menu_select(GtkMenuItem *menuitem, gpointer user_data)
436 {
437 	GtkWidget *entry = NULL;
438 	int verse = GPOINTER_TO_INT(user_data);
439 	gchar *name, *key;
440 
441 	switch (c_type) {
442 	case NB_MAIN:
443 		name = navbar_versekey.module_name->str;
444 		key = navbar_versekey.key->str;
445 		entry = navbar_versekey.lookup_entry;
446 		break;
447 
448 	case NB_PARALLEL:
449 		name = navbar_parallel.module_name->str;
450 		key = navbar_parallel.key->str;
451 		entry = navbar_parallel.lookup_entry;
452 		break;
453 
454 	case NB_DIALOG:
455 		if (!c_dialog)
456 			return;
457 		name = c_dialog->navbar.module_name->str;
458 		key = c_dialog->navbar.key->str;
459 		entry = c_dialog->navbar.lookup_entry;
460 		break;
461 
462 	case NB_EDITOR:
463 		if (!c_editor)
464 			return;
465 		name = c_editor->navbar.module_name->str;
466 		key = c_editor->navbar.key->str;
467 		entry = c_editor->navbar.lookup_entry;
468 		break;
469 	}
470 	if (entry) {
471 		SWModule *mod = backend->get_SWModule(name);
472 		if (mod) {
473 			VerseKey *vkey = (VerseKey *)mod->createKey();
474 			vkey->setAutoNormalize(1);
475 			vkey->setText(key);
476 			vkey->setVerse(verse);
477 
478 			gtk_entry_set_text(GTK_ENTRY(entry), vkey->getText());
479 			gtk_widget_activate(entry);
480 
481 			delete vkey;
482 		}
483 	}
484 }
485 
486 /******************************************************************************
487  * Name
488  *  main_navbar_versekey_set
489  *
490  * Synopsis
491  *   #include "main/navbar_versekey.h"
492  *
493  *   void main_navbar_versekey_set(NAVBAR_VERSEKEY navbar, const char * key)
494  *
495  * Description
496  *   separate key info John 3:16 to book=john chapter=3 verse=16 and write
497  *   to navbar labels - also set lookup entry text
498  *
499  * Return value
500  *   void
501  */
502 
main_navbar_versekey_set(NAVBAR_VERSEKEY navbar,const char * key)503 void main_navbar_versekey_set(NAVBAR_VERSEKEY navbar, const char *key)
504 {
505 	char *tmpbuf = NULL;
506 
507 	if (!navbar.module_name->len)
508 		return;
509 
510 	SWModule *mod = backend->get_SWModule(navbar.module_name->str);
511 	if (!mod)
512 		return;
513 
514 	// previously, we set and normalized the key, but we also
515 	// kept a record of whether that key made sense.
516 	if (navbar.valid_key) {
517 		VerseKey *vkey = (VerseKey *)mod->createKey();
518 		vkey->setAutoNormalize(1);
519 		vkey->setText(key);
520 
521 		tmpbuf = g_strdup_printf("<b>%s</b>", vkey->getBookName());
522 		gtk_label_set_label(GTK_LABEL(navbar.label_book_menu), tmpbuf);
523 		g_free(tmpbuf);
524 
525 		gchar *num = main_format_number(vkey->getChapter());
526 		tmpbuf = g_strdup_printf("<b>%s</b>", num);
527 		g_free(num);
528 		gtk_label_set_label(GTK_LABEL(navbar.label_chapter_menu), tmpbuf);
529 		g_free(tmpbuf);
530 
531 		num = main_format_number(vkey->getVerse());
532 		tmpbuf = g_strdup_printf("<b>%s</b>", num);
533 		g_free(num);
534 		gtk_label_set_label(GTK_LABEL(navbar.label_verse_menu), tmpbuf);
535 		g_free(tmpbuf);
536 
537 		navbar.key = g_string_assign(navbar.key, (char *)vkey->getText());
538 		gtk_entry_set_text(GTK_ENTRY(navbar.lookup_entry), navbar.key->str);
539 
540 		delete vkey;
541 	} else {
542 		tmpbuf = g_strdup(" ");
543 		gtk_label_set_label(GTK_LABEL(navbar.label_book_menu), tmpbuf);
544 		gtk_label_set_label(GTK_LABEL(navbar.label_chapter_menu), tmpbuf);
545 		gtk_label_set_label(GTK_LABEL(navbar.label_verse_menu), tmpbuf);
546 		gtk_entry_set_text(GTK_ENTRY(navbar.lookup_entry), tmpbuf);
547 		g_free(tmpbuf);
548 	}
549 }
550 
551 /******************************************************************************
552  * Name
553  *  main_versekey_drop_down_verse_menu
554  *
555  * Synopsis
556  *   #include "main/navbar_versekey.h"
557  *
558  *   GtkWidget *main_versekey_drop_down_verse_menu(NAVBAR_VERSEKEY navbar)
559  *
560  * Description
561  *   create and return a dropdown menu of verses for the current chapter
562  *
563  * Return value
564  *   GtkWidget*
565  */
566 
main_versekey_drop_down_verse_menu(NAVBAR_VERSEKEY navbar,gint nb_type,gpointer dialog,gpointer editor)567 GtkWidget *main_versekey_drop_down_verse_menu(NAVBAR_VERSEKEY navbar,
568 					      gint nb_type,
569 					      gpointer dialog,
570 					      gpointer editor)
571 {
572 	gint i, x;
573 	GtkWidget *menu;
574 	GtkMenuShell *menu_shell;
575 	GtkWidget *item;
576 	GtkWidget *select_item = NULL;
577 	c_dialog = (DIALOG_DATA *)dialog;
578 	c_editor = (EDITOR *)editor;
579 	c_type = nb_type;
580 
581 	menu = gtk_menu_new();
582 	menu_shell = GTK_MENU_SHELL(menu);
583 
584 	SWModule *mod = backend->get_SWModule(navbar.module_name->str);
585 	if (!mod)
586 		return menu;
587 
588 	VerseKey *vkey = (VerseKey *)mod->createKey();
589 	vkey->setAutoNormalize(1);
590 	vkey->setText(navbar.key->str);
591 	int xverse = vkey->getVerse();
592 
593 	x = vkey->getVerseMax();
594 	delete vkey;
595 
596 	for (i = 1; i <= x; i++) {
597 		gchar *num = main_format_number(i);
598 		item = gtk_menu_item_new_with_label(num);
599 		gtk_widget_show(item);
600 		gtk_menu_shell_append(menu_shell, item);
601 		g_signal_connect(G_OBJECT(item), "activate",
602 				 G_CALLBACK(on_verse_menu_select),
603 				 GINT_TO_POINTER(i));
604 
605 		if (i == xverse)
606 			select_item = item;
607 		g_free(num);
608 	}
609 
610 	if (select_item)
611 		gtk_menu_shell_select_item(menu_shell, select_item);
612 
613 	return menu;
614 }
615 
616 /******************************************************************************
617  * Name
618  *  main_versekey_drop_down_chapter_menu
619  *
620  * Synopsis
621  *   #include "main/navbar_versekey.h"
622  *
623  *   GtkWidget *main_versekey_drop_down_chapter_menu(NAVBAR_VERSEKEY navbar)
624  *
625  * Description
626  *   create and return a dropdown menu for chapters for the current book
627  *
628  * Return value
629  *   GtkWidget*
630  */
631 
main_versekey_drop_down_chapter_menu(NAVBAR_VERSEKEY navbar,gint nb_type,gpointer dialog,gpointer editor)632 GtkWidget *main_versekey_drop_down_chapter_menu(NAVBAR_VERSEKEY navbar,
633 						gint nb_type,
634 						gpointer dialog,
635 						gpointer editor)
636 {
637 	gint i, x;
638 	GtkWidget *menu;
639 	GtkMenuShell *menu_shell;
640 	GtkWidget *item;
641 	GtkWidget *select_item = NULL;
642 	c_dialog = (DIALOG_DATA *)dialog;
643 	c_editor = (EDITOR *)editor;
644 	c_type = nb_type;
645 
646 	menu = gtk_menu_new();
647 	menu_shell = GTK_MENU_SHELL(menu);
648 
649 	SWModule *mod = backend->get_SWModule(navbar.module_name->str);
650 	if (!mod)
651 		return menu;
652 
653 	VerseKey *vkey = (VerseKey *)mod->createKey();
654 	vkey->setAutoNormalize(1);
655 	vkey->setText(navbar.key->str);
656 	int xchapter = vkey->getChapter();
657 
658 	x = vkey->getChapterMax();
659 	delete vkey;
660 
661 	for (i = 1; i <= x; i++) {
662 		gchar *num = main_format_number(i);
663 		item = gtk_menu_item_new_with_label(num);
664 		gtk_widget_show(item);
665 		gtk_menu_shell_append(menu_shell, item);
666 		g_signal_connect(G_OBJECT(item), "activate",
667 				 G_CALLBACK(on_chapter_menu_select),
668 				 GINT_TO_POINTER(i));
669 
670 		if (i == xchapter)
671 			select_item = item;
672 		g_free(num);
673 	}
674 
675 	if (select_item)
676 		gtk_menu_shell_select_item(menu_shell, select_item);
677 
678 	return menu;
679 }
680 
681 /******************************************************************************
682  * Name
683  *  main_versekey_drop_down_book_menu
684  *
685  * Synopsis
686  *   #include "main/navbar_versekey.h"
687  *
688  *   GtkWidget *main_versekey_drop_down_book_menu(NAVBAR_VERSEKEY navbar, gpointer data)
689  *
690  * Description
691  *   create and return a dropdown menu of books of the current Bible module
692  *
693  * Return value
694  *   GtkWidget*
695  */
696 
main_versekey_drop_down_book_menu(NAVBAR_VERSEKEY navbar,gint nb_type,gpointer dialog,gpointer editor)697 GtkWidget *main_versekey_drop_down_book_menu(NAVBAR_VERSEKEY navbar,
698 					     gint nb_type,
699 					     gpointer dialog,
700 					     gpointer editor)
701 {
702 	GtkWidget *menu;
703 	GtkMenuShell *menu_shell;
704 	GtkWidget *item;
705 	GtkWidget *select_item = NULL;
706 	char *book = NULL;
707 	char *current_book = NULL;
708 	int i = 0;
709 
710 	c_dialog = (DIALOG_DATA *)dialog;
711 	c_editor = (EDITOR *)editor;
712 	c_type = nb_type;
713 
714 	menu = gtk_menu_new();
715 	menu_shell = GTK_MENU_SHELL(menu);
716 
717 	SWModule *mod = backend->get_SWModule(navbar.module_name->str);
718 	if (!mod)
719 		return menu;
720 
721 	VerseKey *key = (VerseKey *)mod->createKey();
722 	VerseKey *key_current = (VerseKey *)mod->createKey();
723 	key->setAutoNormalize(1);
724 	key_current->setAutoNormalize(1);
725 	key_current->setText(navbar.key->str);
726 	current_book = strdup((const char *)key_current->getBookName());
727 
728 	if (backend->module_has_testament(navbar.module_name->str, 1)) {
729 		while (i < key->BMAX[0]) {
730 			key->setTestament(1);
731 			key->setBook(i + 1);
732 			book = strdup((const char *)key->getBookName());
733 			item = gtk_menu_item_new_with_label(book);
734 			gtk_widget_show(item);
735 			gtk_menu_shell_append(menu_shell, item);
736 			g_signal_connect(G_OBJECT(item), "activate",
737 					 G_CALLBACK(on_ot_book_menu_select),
738 					 GINT_TO_POINTER(i));
739 
740 			if (!strcmp(book, current_book))
741 				select_item = item;
742 			++i;
743 			g_free(book);
744 		}
745 	}
746 
747 	i = 0;
748 	if (backend->module_has_testament(navbar.module_name->str, 2)) {
749 		while (i < key->BMAX[1]) {
750 			key->setTestament(2);
751 			key->setBook(i + 1);
752 			book = strdup((const char *)key->getBookName());
753 			item = gtk_menu_item_new_with_label(book);
754 			gtk_widget_show(item);
755 			gtk_menu_shell_append(menu_shell, item);
756 			g_signal_connect(G_OBJECT(item), "activate",
757 					 G_CALLBACK(on_nt_book_menu_select),
758 					 GINT_TO_POINTER(i));
759 
760 			if (!strcmp(book, current_book))
761 				select_item = item;
762 			++i;
763 			g_free(book);
764 		}
765 	}
766 
767 	delete key;
768 	delete key_current;
769 
770 	if (select_item)
771 		gtk_menu_shell_select_item(menu_shell, select_item);
772 	if (current_book)
773 		g_free(current_book);
774 	return menu;
775 }
776