Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions src/backend/sword_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -925,11 +925,31 @@ GList *BackEnd::parse_verse_list(const char *module_name, const char *list, char
key->setText(current_key);
vs = key->parseVerseList(list, *key, TRUE);

if (!vs.getCount())
int count = vs.getCount();
if (!count)
return retlist;
while (!vs.popError()) {
retlist = g_list_append(retlist, strdup((char *)vs.getText()));
vs++;
/* Use indexed access rather than popError()-driven iteration:
* popError() on the ListKey stops the whole walk as soon as ANY
* single element fails to resolve, silently dropping every
* element after it, even when they are perfectly valid. Indexed
* access lets us simply skip a bad element and keep going.
*
* But each INDIVIDUAL element also carries its own error state:
* when a fragment of the input list doesn't parse as a valid
* verse reference at all (e.g. a dictionary/Strong's-number key
* or some other non-scriptural bookmark text accidentally fed
* in here), Sword does not simply omit it -- it silently falls
* back to some arbitrary boundary position (observed: the very
* last verse of the Bible) and reports that as a "resolved"
* element without necessarily failing the whole ListKey. Left
* unchecked, that spurious element then looks like a genuine
* match for whatever verse it landed on. Skip any element whose
* own popError() is set, since it does not represent a real
* reference from the input. */
for (int i = 0; i < count; i++) {
SWKey *elem = vs.getElement(i);
if (elem && !elem->popError())
retlist = g_list_append(retlist, strdup((char *)elem->getText()));
}
return retlist;
}
Expand Down
29 changes: 29 additions & 0 deletions src/gtk/bookmarks_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,31 @@ G_MODULE_EXPORT void on_crossref_popup_activate(GtkMenuItem *menuitem,
xml_set_value("Xiphos", "misc", "crossref_popup",
settings.crossref_popup ? "1" : "0");
}
/******************************************************************************
* Name
* on_tag_colorize_activate
*
* Synopsis
* #include "gui/bookmarks_menu.h"
*
* void on_tag_colorize_activate(GtkMenuItem *menuitem,
* gpointer user_data)
*
* Description
* toggle verse colorization by bookmark folder color
*
* Return value
* void
*/
G_MODULE_EXPORT void on_tag_colorize_activate(GtkMenuItem *menuitem,
gpointer user_data)
{
settings.tag_colorize =
gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem));
xml_set_value("Xiphos", "misc", "tag_colorize",
settings.tag_colorize ? "1" : "0");
main_display_bible(NULL, settings.currentverse);
}

/******************************************************************************
* Name
Expand Down Expand Up @@ -1263,6 +1288,10 @@ void gui_create_bookmark_menu(void)
gtk_check_menu_item_set_active(
GTK_CHECK_MENU_ITEM(menu.crossref_popup),
settings.crossref_popup);
menu.tag_colorize = UI_GET_ITEM(gxml, "tag_colorize");
gtk_check_menu_item_set_active(
GTK_CHECK_MENU_ITEM(menu.tag_colorize),
settings.tag_colorize);

gtk_widget_set_sensitive(menu.in_tab, FALSE);
gtk_widget_set_sensitive(menu.in_dialog, FALSE);
Expand Down
73 changes: 73 additions & 0 deletions src/gtk/bookmarks_treeview.c
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,54 @@ void bookmark_debug_dump_colors(void)
}


/* Recursively search @folder (and its sub-folders) for a bookmark whose
* key resolves to @versekey_text. On match, returns "<immediate parent
* folder caption>: <bookmark caption>". Helper for
* bookmark_get_tag_info_for_key(). */
static gchar *bookmark_find_in_folder(GtkTreeIter *folder, const gchar *versekey_text)
{
gchar *folder_caption = NULL;
gtk_tree_model_get(GTK_TREE_MODEL(model), folder,
COL_CAPTION, &folder_caption, -1);
GtkTreeIter child;
gchar *result = NULL;
if (gtk_tree_model_iter_children(GTK_TREE_MODEL(model), &child, folder)) {
do {
gchar *node_key = NULL, *node_caption = NULL;
gtk_tree_model_get(GTK_TREE_MODEL(model), &child,
COL_KEY, &node_key,
COL_CAPTION, &node_caption, -1);
if (node_key) {
/* leaf: a bookmark. Resolve its (possibly
* multi-reference) key via Sword and compare
* each resolved verse to versekey_text. */
GList *verses = main_parse_verse_list(
settings.MainWindowModule, node_key,
(char *)settings.currentverse);
for (GList *l = verses; l && !result; l = l->next) {
gchar *v = g_strstrip(g_strdup((const char *)l->data));
gchar *q = g_strstrip(g_strdup(versekey_text));
if (!g_ascii_strcasecmp(v, q))
result = g_strdup_printf("%s: %s",
folder_caption ? folder_caption : "",
node_caption ? node_caption : node_key);
g_free(v);
g_free(q);
}
for (GList *l = verses; l; l = l->next)
g_free(l->data);
g_list_free(verses);
} else {
/* sub-folder: recurse */
result = bookmark_find_in_folder(&child, versekey_text);
}
g_free(node_key);
g_free(node_caption);
} while (!result && gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &child));
}
g_free(folder_caption);
return result;
}
gchar *bookmark_get_tag_color_for_key(const gchar *osiskey)
{
GtkTreeIter folder, child;
Expand Down Expand Up @@ -1102,6 +1150,31 @@ gchar *bookmark_get_tag_color_for_key(const gchar *osiskey)

return NULL;
}
/**
* bookmark_get_tag_info_for_key:
* @versekey_text: a Sword-formatted verse key string, e.g. "Rom 16:23"
*
* Finds the first bookmark, anywhere in the tree, whose (possibly
* multi-reference) key resolves to @versekey_text, and returns
* "<containing folder>: <bookmark name>" -- just the single
* immediate parent folder, not the full nested path.
* Returns NULL if no bookmark matches. Caller must g_free() the result.
*/
gchar *bookmark_get_tag_info_for_key(const gchar *versekey_text)
{
if (!versekey_text || !model)
return NULL;
GtkTreeIter folder;
if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &folder))
return NULL;
gchar *result = NULL;
do {
result = bookmark_find_in_folder(&folder, versekey_text);
if (result)
return result;
} while (gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &folder));
return NULL;
}

GtkWidget *gui_create_bookmark_tree(void)
{
Expand Down
3 changes: 3 additions & 0 deletions src/gui/bookmarks_menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct _bookmark_menu
GtkWidget *remove;
GtkWidget *set_color;
GtkWidget *crossref_popup;
GtkWidget *tag_colorize;
};
typedef struct _bookmark_menu BOOKMARK_MENU;
extern BOOKMARK_MENU menu;
Expand All @@ -64,6 +65,8 @@ void on_allow_reordering_activate(GtkMenuItem *menuitem,
gpointer user_data);
void on_crossref_popup_activate(GtkMenuItem *menuitem,
gpointer user_data);
void on_tag_colorize_activate(GtkMenuItem *menuitem,
gpointer user_data);
void on_dialog_activate(GtkMenuItem *menuitem,
gpointer user_data);
void on_edit_item_activate(GtkMenuItem *menuitem,
Expand Down
1 change: 1 addition & 0 deletions src/gui/bookmarks_treeview.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ void gui_verselist_to_bookmarks(GList *verses,
GtkWidget *gui_create_bookmark_tree(void);
void bookmark_debug_dump_colors(void);
gchar *bookmark_get_tag_color_for_key(const gchar *osiskey);
gchar *bookmark_get_tag_info_for_key(const gchar *versekey_text);
void gui_parse_bookmarks(GtkTreeView *tree, const xmlChar *file,
GtkTreeIter *parent);
GtkWidget *gui_create_dialog_add_bookmark(gchar *label,
Expand Down
Loading