// SPDX-FileCopyrightText: 2019-2022 Badwolf Authors // SPDX-License-Identifier: BSD-3-Clause #include "bookmarks.h" #include "badwolf.h" #include "config.h" #include /* _() and other internationalization/localization helpers */ #include /* g_fprintf() */ #include #include #include #include /* access() */ static gboolean location_completion_matches(GtkEntryCompletion *completion, const gchar *key, GtkTreeIter *iter, gpointer UNUSED(user_data)) { gchar *buffer; gchar *pattern; gboolean result; pattern = g_strdup_printf("*%s*", key); gtk_tree_model_get(gtk_entry_completion_get_model(completion), iter, 0, &buffer, -1); result = g_pattern_match_simple(pattern, buffer); g_free(buffer); g_free(pattern); return result; } void bookmarks_completion_setup(GtkEntryCompletion *location_completion, GtkTreeModel *tree_model) { gtk_entry_completion_set_model(location_completion, tree_model); gtk_entry_completion_set_text_column(location_completion, 0); gtk_entry_completion_set_match_func(location_completion, location_completion_matches, NULL, NULL); gtk_entry_completion_set_inline_selection(location_completion, BADWOLF_LOCATION_INLINE_SELECTION); } static void location_completion_cleanup(xmlXPathObjectPtr xpathObj, xmlXPathContextPtr xpathCtx, xmlDocPtr doc) { if(xpathObj != NULL) xmlXPathFreeObject(xpathObj); if(xpathCtx != NULL) xmlXPathFreeContext(xpathCtx); if(doc != NULL) xmlFreeDoc(doc); } static void load_xpath_results(GtkListStore *list_store, xmlNodeSetPtr nodes) { GtkTreeIter iter; int size; size = (nodes) ? nodes->nodeNr : 0; g_fprintf(stderr, _("Bookmarks: Found %d bookmarks.\n"), size); for(int i = 0; i < size; i++) if(nodes->nodeTab[i]) { gtk_list_store_append(list_store, &iter); gtk_list_store_set( list_store, &iter, 0, (char *)xmlXPathCastNodeToString(nodes->nodeTab[i]), -1); } } GtkTreeModel * bookmarks_completion_init() { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; xmlXPathObjectPtr xpathObj = NULL; const xmlChar *xpathExpr = (const xmlChar *)"//bookmark/@href"; char *filename = g_build_filename(g_get_user_data_dir(), "badwolf", "bookmarks.xbel", NULL); GtkListStore *list_store = gtk_list_store_new(1, G_TYPE_STRING); /* flawfinder: ignore, just a presence check */ if(access(filename, R_OK) != 0) { g_fprintf(stderr, _("Bookmarks: No loadable file found at %s\n"), filename); goto failure; } g_fprintf(stderr, _("Bookmarks: loading at %s\n"), filename); doc = xmlParseFile(filename); if(doc == NULL) { g_fprintf(stderr, _("Bookmarks: unable to parse file \"%s\"\n"), filename); goto failure; } xmlXIncludeProcess(doc); xpathCtx = xmlXPathNewContext(doc); if(xpathCtx == NULL) { g_fprintf(stderr, _("Bookmarks: unable to create new XPath context\n")); goto failure; } xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); if(xpathObj == NULL) { g_fprintf(stderr, _("Bookmarks: unable to evaluate XPath expression \"%s\"\n"), xpathExpr); goto failure; } load_xpath_results(list_store, xpathObj->nodesetval); location_completion_cleanup(xpathObj, xpathCtx, doc); g_fprintf(stderr, _("Bookmarks: Done.\n")); return GTK_TREE_MODEL(list_store); failure: location_completion_cleanup(xpathObj, xpathCtx, doc); g_free(filename); return NULL; }