From 2b1aedf6d172b41d03bb65d93c28adb3efbc03ee Mon Sep 17 00:00:00 2001 From: Miciah Dashiel Butler Masters Date: Wed, 3 Jun 2009 19:09:20 +0000 Subject: [PATCH] Cache manager: Add 'Search contents' button Add a 'Search contents' button to the cache manager that searches through the cache items' data rather than their metadata. Add match_cache_entry_contents. Add push_cache_hierbox_search_button and push_cache_hierbox_search_contents_button, which call push_hierbox_search_button after setting box->ops to either cache_entry_listbox_ops or cache_entry_listbox_ops_match_contents, respectively, which define the appropriate match callback for the hierbox search code. Add strlcasestr, used in the new match_cache_entry_contents routine. --- NEWS | 3 ++ src/cache/dialogs.c | 80 +++++++++++++++++++++++++++++++++++++-------- src/util/string.c | 21 ++++++++++++ src/util/string.h | 4 +++ 4 files changed, 95 insertions(+), 13 deletions(-) diff --git a/NEWS b/NEWS index a30b2577..eb286605 100644 --- a/NEWS +++ b/NEWS @@ -62,6 +62,9 @@ Miscellaneous: * Report if the Lua function edit_bookmark_dialog receives the wrong number or types of arguments instead of silently failing. * enhancement: Add ``Invalidate'' button to the cache manager. +* enhancement: Add ``Search contents'' button to the cache manager with + which one can search through the cache items' data rather than their + metadata. ////////////////////////////////////////////////////////////////////// The following changes should be removed from NEWS before ELinks 0.13.0 diff --git a/src/cache/dialogs.c b/src/cache/dialogs.c index 5b48eb59..ec253308 100644 --- a/src/cache/dialogs.c +++ b/src/cache/dialogs.c @@ -200,6 +200,43 @@ match_cache_entry(struct listbox_item *item, struct terminal *term, return LISTBOX_MATCH_NO; } +static enum listbox_match +match_cache_entry_contents(struct listbox_item *item, struct terminal *term, + unsigned char *text) +{ + struct cache_entry *cached = item->udata; + struct fragment *fragment = get_cache_fragment(cached); + + if (fragment && strlcasestr(fragment->data, fragment->length, text, -1)) + return LISTBOX_MATCH_OK; + + return LISTBOX_MATCH_NO; +} + +const static struct listbox_ops cache_entry_listbox_ops; + +static widget_handler_status_T +push_cache_hierbox_search_button(struct dialog_data *dlg_data, struct widget_data *button) +{ + struct listbox_data *box = get_dlg_listbox_data(dlg_data); + + box->ops = &cache_entry_listbox_ops; + + return push_hierbox_search_button(dlg_data, button); +} + +const static struct listbox_ops cache_entry_listbox_ops_match_contents; + +static widget_handler_status_T +push_cache_hierbox_search_contents_button(struct dialog_data *dlg_data, struct widget_data *button) +{ + struct listbox_data *box = get_dlg_listbox_data(dlg_data); + + box->ops = &cache_entry_listbox_ops_match_contents; + + return push_hierbox_search_button(dlg_data, button); +} + static struct listbox_ops_messages cache_messages = { /* cant_delete_item */ N_("Sorry, but cache entry \"%s\" cannot be deleted."), @@ -227,21 +264,37 @@ static struct listbox_ops_messages cache_messages = { NULL, }; -static const struct listbox_ops cache_entry_listbox_ops = { - lock_cache_entry, - unlock_cache_entry, - is_cache_entry_used, - get_cache_entry_text, - get_cache_entry_info, - get_cache_entry_uri, - get_cache_entry_root, - match_cache_entry, - can_delete_cache_entry, - delete_cache_entry_item, - NULL, +#define ops(matchfn) \ + lock_cache_entry, \ + unlock_cache_entry, \ + is_cache_entry_used, \ + get_cache_entry_text, \ + get_cache_entry_info, \ + get_cache_entry_uri, \ + get_cache_entry_root, \ + matchfn, \ + can_delete_cache_entry, \ + delete_cache_entry_item, \ + NULL, \ &cache_messages, + +/* Each hierbox window is represented by an instance of struct hierbox, + * which has a corresponding instance of struct listbox_data. That + * instance of struct listbox_data will point one of the following two + * struct listbox_ops instances depending on which type of search the + * user is performing in that hierbox. The two struct listbox_ops + * instances differ only in the match callback. */ + +const static struct listbox_ops cache_entry_listbox_ops_match_contents = { + ops(match_cache_entry_contents) }; +const static struct listbox_ops cache_entry_listbox_ops = { + ops(match_cache_entry) +}; + +#undef ops + static widget_handler_status_T push_invalidate_button(struct dialog_data *dlg_data, struct widget_data *button) { @@ -266,7 +319,8 @@ static const struct hierbox_browser_button cache_buttons[] = { { N_("~Info"), push_hierbox_info_button, 1 }, { N_("~Goto"), push_hierbox_goto_button, 1 }, { N_("~Delete"), push_hierbox_delete_button, 1 }, - { N_("~Search"), push_hierbox_search_button, 1 }, + { N_("~Search"), push_cache_hierbox_search_button, 1 }, + { N_("Search c~ontents"), push_cache_hierbox_search_contents_button, 1 }, { N_("In~validate"), push_invalidate_button, 1 }, }; diff --git a/src/util/string.c b/src/util/string.c index 604a00d7..c8ee7d77 100644 --- a/src/util/string.c +++ b/src/util/string.c @@ -245,6 +245,27 @@ elinks_strlcasecmp(const unsigned char *s1, size_t n1, } } +/* strlcasestr - adapted from c_strcasestr */ +char * +elinks_strlcasestr(const char *haystack, const int haystackl, + const char *needle, const int needlel) +{ + size_t haystack_length = haystackl == -1 ? strlen(haystack) : haystackl; + size_t needle_length = needlel == -1 ? strlen(needle) : needlel; + int i; + + if (haystack_length < needle_length) + return NULL; + + for (i = haystack_length - needle_length + 1; i; i--) { + if (!c_strncasecmp(haystack, needle, needle_length)) + return (char *) haystack; + haystack++; + } + + return NULL; +} + int c_strcasecmp(const char *s1, const char *s2) { diff --git a/src/util/string.h b/src/util/string.h index 37ea336a..509453da 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -106,6 +106,10 @@ int elinks_strlcasecmp(const unsigned char *s1, size_t n1, const unsigned char *s2, size_t n2, const int locale_indep); +#define strlcasestr(a,b,c,d) (errfile = __FILE__, errline = __LINE__, elinks_strlcasestr(a,b,c,d)) +char *elinks_strlcasestr(const char *haystack, const int haystackl, + const char *needle, const int needlel); + /* strcasecmp and strncasecmp which work as if they are * in the C locale */ int c_strcasecmp(const char *s1, const char *s2);