Gitweb links:

...log 
http://git.netsurf-browser.org/netsurf.git/shortlog/a8596a80aeb70acb05aba29f654df24210f50c19
...commit 
http://git.netsurf-browser.org/netsurf.git/commit/a8596a80aeb70acb05aba29f654df24210f50c19
...tree 
http://git.netsurf-browser.org/netsurf.git/tree/a8596a80aeb70acb05aba29f654df24210f50c19

The branch, master has been updated
       via  a8596a80aeb70acb05aba29f654df24210f50c19 (commit)
       via  e72ca36863f4b05e5e641e77472f0f7fef97d906 (commit)
      from  fbc0847db06fa91765d5b83b34dabee85f65d4ec (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=a8596a80aeb70acb05aba29f654df24210f50c19
commit a8596a80aeb70acb05aba29f654df24210f50c19
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>

    move free text search general interface to content.
    
    needs additional cleanup to call content through handler table to
      perform searches.

diff --git a/content/Makefile b/content/Makefile
index b4353ba..abc5a24 100644
--- a/content/Makefile
+++ b/content/Makefile
@@ -1,7 +1,16 @@
 # Content sources
 
-S_CONTENT := content.c content_factory.c dirlist.c fetch.c hlcache.c   \
-       llcache.c mimesniff.c urldb.c no_backing_store.c
+S_CONTENT :=                   \
+       content.c               \
+       content_factory.c       \
+       dirlist.c               \
+       fetch.c                 \
+       hlcache.c               \
+       llcache.c               \
+       mimesniff.c             \
+       textsearch.c            \
+       urldb.c                 \
+       no_backing_store.c
 
 # Make filesystem backing store available
 ifeq ($(NETSURF_FS_BACKING_STORE),YES)
diff --git a/content/handlers/html/Makefile b/content/handlers/html/Makefile
index 677786c..233fb13 100644
--- a/content/handlers/html/Makefile
+++ b/content/handlers/html/Makefile
@@ -20,5 +20,4 @@ S_HTML := box_construct.c     \
        redraw.c                \
        redraw_border.c         \
        script.c                \
-       search.c                \
        table.c
diff --git a/content/handlers/html/html.c b/content/handlers/html/html.c
index af06431..a3d4264 100644
--- a/content/handlers/html/html.c
+++ b/content/handlers/html/html.c
@@ -49,6 +49,7 @@
 #include "netsurf/misc.h"
 #include "content/hlcache.h"
 #include "content/content_factory.h"
+#include "content/textsearch.h"
 #include "desktop/selection.h"
 #include "desktop/scrollbar.h"
 #include "desktop/textarea.h"
@@ -69,7 +70,6 @@
 #include "html/form_internal.h"
 #include "html/imagemap.h"
 #include "html/layout.h"
-#include "html/search.h"
 
 #define CHUNK 4096
 
@@ -1327,7 +1327,7 @@ static nserror html_close(struct content *c)
        selection_clear(&htmlc->sel, false);
 
        if (htmlc->search != NULL) {
-               search_destroy_context(htmlc->search);
+               content_textsearch_destroy(htmlc->search);
        }
 
        /* clear the html content reference to the browser window */
diff --git a/content/handlers/html/interaction.c 
b/content/handlers/html/interaction.c
index 3f401bd..8ae5144 100644
--- a/content/handlers/html/interaction.c
+++ b/content/handlers/html/interaction.c
@@ -41,6 +41,7 @@
 #include "netsurf/layout.h"
 #include "netsurf/keypress.h"
 #include "content/hlcache.h"
+#include "content/textsearch.h"
 #include "desktop/frames.h"
 #include "desktop/scrollbar.h"
 #include "desktop/selection.h"
@@ -55,7 +56,6 @@
 #include "html/form_internal.h"
 #include "html/private.h"
 #include "html/imagemap.h"
-#include "html/search.h"
 #include "html/interaction.h"
 
 /**
@@ -1602,17 +1602,18 @@ bool html_keypress(struct content *c, uint32_t key)
  * Handle search.
  *
  * \param c content of type HTML
- * \param context front end private data
+ * \param fe_ctx front end private data
  * \param flags search flags
  * \param string search string
  */
 void
 html_search(struct content *c,
-           void *context,
+           void *fe_ctx,
            search_flags_t flags,
            const char *string)
 {
        html_content *html = (html_content *)c;
+       nserror res;
 
        assert(c != NULL);
 
@@ -1621,7 +1622,7 @@ html_search(struct content *c,
            (strcmp(string, html->search_string) == 0) &&
            (html->search != NULL)) {
                /* Continue prev. search */
-               search_step(html->search, flags, string);
+               content_textsearch_step(html->search, flags, string);
 
        } else if (string != NULL) {
                /* New search */
@@ -1631,16 +1632,16 @@ html_search(struct content *c,
                        return;
 
                if (html->search != NULL) {
-                       search_destroy_context(html->search);
+                       content_textsearch_destroy(html->search);
                        html->search = NULL;
                }
 
-               html->search = search_create_context(c, CONTENT_HTML, context);
-
-               if (html->search == NULL)
+               res = content_textsearch_create(c, fe_ctx, &html->search);
+               if (res != NSERROR_OK) {
                        return;
+               }
 
-               search_step(html->search, flags, string);
+               content_textsearch_step(html->search, flags, string);
 
        } else {
                /* Clear search */
@@ -1653,9 +1654,9 @@ html_search(struct content *c,
 
 
 /**
- * Terminate a search.
+ * Terminate a text search.
  *
- * \param  c                   content of type HTML
+ * \param c content of type HTML
  */
 void html_search_clear(struct content *c)
 {
@@ -1667,7 +1668,7 @@ void html_search_clear(struct content *c)
        html->search_string = NULL;
 
        if (html->search != NULL) {
-               search_destroy_context(html->search);
+               content_textsearch_destroy(html->search);
        }
        html->search = NULL;
 }
diff --git a/content/handlers/html/private.h b/content/handlers/html/private.h
index dff0b78..1367c62 100644
--- a/content/handlers/html/private.h
+++ b/content/handlers/html/private.h
@@ -211,7 +211,7 @@ typedef struct html_content {
        struct form_control *visible_select_menu;
 
        /** Context for free text search, or NULL if none */
-       struct search_context *search;
+       struct textsearch_context *search;
        /** Search string or NULL */
        char *search_string;
 
diff --git a/content/handlers/html/redraw.c b/content/handlers/html/redraw.c
index 936c1b3..f9fb6b4 100644
--- a/content/handlers/html/redraw.c
+++ b/content/handlers/html/redraw.c
@@ -47,6 +47,7 @@
 #include "netsurf/layout.h"
 #include "content/content.h"
 #include "content/content_protected.h"
+#include "content/textsearch.h"
 #include "css/utils.h"
 #include "desktop/selection.h"
 #include "desktop/print.h"
@@ -61,7 +62,6 @@
 #include "html/form_internal.h"
 #include "html/private.h"
 #include "html/layout.h"
-#include "html/search.h"
 
 
 bool html_redraw_debug = false;
@@ -167,7 +167,7 @@ text_redraw(const char *utf8_text,
            bool excluded,
            struct content *c,
            const struct selection *sel,
-           struct search_context *search,
+           struct textsearch_context *search,
            const struct redraw_context *ctx)
 {
        bool highlighted = false;
@@ -184,18 +184,23 @@ text_redraw(const char *utf8_text,
                unsigned end_idx;
 
                /* first try the browser window's current selection */
-               if (selection_defined(sel) && selection_highlighted(sel,
-                                       offset, offset + len,
-                                       &start_idx, &end_idx)) {
+               if (selection_defined(sel) &&
+                   selection_highlighted(sel,
+                                         offset,
+                                         offset + len,
+                                         &start_idx,
+                                         &end_idx)) {
                        highlighted = true;
                }
 
                /* what about the current search operation, if any? */
-               if (!highlighted && (search != NULL) &&
-                               search_term_highlighted(c,
-                                               offset, offset + len,
-                                               &start_idx, &end_idx,
-                                               search)) {
+               if (!highlighted &&
+                   (search != NULL) &&
+                   content_textsearch_ishighlighted(search,
+                                                    offset,
+                                                    offset + len,
+                                                    &start_idx,
+                                                    &end_idx)) {
                        highlighted = true;
                }
 
diff --git a/content/handlers/html/search.c b/content/handlers/html/search.c
deleted file mode 100644
index 8ccb692..0000000
--- a/content/handlers/html/search.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
- * Copyright 2004 John M Bell <[email protected]>
- * Copyright 2005 Adrian Lees <[email protected]>
- * Copyright 2009 Mark Benjamin <[email protected]>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * Free text search (core)
- */
-
-#include <ctype.h>
-#include <string.h>
-#include <dom/dom.h>
-
-#include "utils/config.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/utils.h"
-#include "content/content.h"
-#include "content/hlcache.h"
-#include "desktop/selection.h"
-#include "netsurf/search.h"
-#include "netsurf/misc.h"
-#include "desktop/gui_internal.h"
-
-#include "text/textplain.h"
-#include "html/box.h"
-#include "html/box_inspect.h"
-#include "html/html.h"
-#include "html/private.h"
-#include "html/search.h"
-
-#ifndef NOF_ELEMENTS
-#define NOF_ELEMENTS(array) (sizeof(array)/sizeof(*(array)))
-#endif
-
-
-struct list_entry {
-       unsigned start_idx;     /* start position of match */
-       unsigned end_idx;       /* end of match */
-
-       struct box *start_box;  /* used only for html contents */
-       struct box *end_box;
-
-       struct selection *sel;
-
-       struct list_entry *prev;
-       struct list_entry *next;
-};
-
-struct search_context {
-       void *gui_p;
-       struct content *c;
-       struct list_entry *found;
-       struct list_entry *current; /* first for select all */
-       char *string;
-       bool prev_case_sens;
-       bool newsearch;
-       bool is_html;
-};
-
-
-/* Exported function documented in search.h */
-struct search_context *
-search_create_context(struct content *c, content_type type, void *gui_data)
-{
-       struct search_context *context;
-       struct list_entry *search_head;
-
-       if (type != CONTENT_HTML && type != CONTENT_TEXTPLAIN) {
-               return NULL;
-       }
-
-       context = malloc(sizeof(struct search_context));
-       if (context == NULL) {
-               return NULL;
-       }
-
-       search_head = malloc(sizeof(struct list_entry));
-       if (search_head == NULL) {
-               free(context);
-               return NULL;
-       }
-
-       search_head->start_idx = 0;
-       search_head->end_idx = 0;
-       search_head->start_box = NULL;
-       search_head->end_box = NULL;
-       search_head->sel = NULL;
-       search_head->prev = NULL;
-       search_head->next = NULL;
-
-       context->found = search_head;
-       context->current = NULL;
-       context->string = NULL;
-       context->prev_case_sens = false;
-       context->newsearch = true;
-       context->c = c;
-       context->is_html = (type == CONTENT_HTML) ? true : false;
-       context->gui_p = gui_data;
-
-       return context;
-}
-
-
-/**
- * Release the memory used by the list of matches,
- * deleting selection objects too
- */
-
-static void free_matches(struct search_context *context)
-{
-       struct list_entry *a;
-       struct list_entry *b;
-
-       a = context->found->next;
-
-       /* empty the list before clearing and deleting the
-        * selections because the the clearing updates the
-        * screen immediately, causing nested accesses to the list */
-
-       context->found->prev = NULL;
-       context->found->next = NULL;
-
-       for (; a; a = b) {
-               b = a->next;
-               if (a->sel) {
-                       selection_clear(a->sel, true);
-                       selection_destroy(a->sel);
-               }
-               free(a);
-       }
-}
-
-
-/**
- * Find the first occurrence of 'match' in 'string' and return its index
- *
- * \param  string     the string to be searched (unterminated)
- * \param  s_len      length of the string to be searched
- * \param  pattern    the pattern for which we are searching (unterminated)
- * \param  p_len      length of pattern
- * \param  case_sens  true iff case sensitive match required
- * \param  m_len      accepts length of match in bytes
- * \return pointer to first match, NULL if none
- */
-
-static const char *find_pattern(const char *string, int s_len,
-               const char *pattern, int p_len, bool case_sens,
-               unsigned int *m_len)
-{
-       struct { const char *ss, *s, *p; bool first; } context[16];
-       const char *ep = pattern + p_len;
-       const char *es = string  + s_len;
-       const char *p = pattern - 1;  /* a virtual '*' before the pattern */
-       const char *ss = string;
-       const char *s = string;
-       bool first = true;
-       int top = 0;
-
-       while (p < ep) {
-               bool matches;
-               if (p < pattern || *p == '*') {
-                       char ch;
-
-                       /* skip any further asterisks; one is the same as many
-                       */
-                       do p++; while (p < ep && *p == '*');
-
-                       /* if we're at the end of the pattern, yes, it matches
-                       */
-                       if (p >= ep) break;
-
-                       /* anything matches a # so continue matching from
-                          here, and stack a context that will try to match
-                          the wildcard against the next character */
-
-                       ch = *p;
-                       if (ch != '#') {
-                               /* scan forwards until we find a match for
-                                  this char */
-                               if (!case_sens) ch = toupper(ch);
-                               while (s < es) {
-                                       if (case_sens) {
-                                               if (*s == ch) break;
-                                       } else if (toupper(*s) == ch)
-                                               break;
-                                       s++;
-                               }
-                       }
-
-                       if (s < es) {
-                               /* remember where we are in case the match
-                                  fails; we may then resume */
-                               if (top < (int)NOF_ELEMENTS(context)) {
-                                       context[top].ss = ss;
-                                       context[top].s  = s + 1;
-                                       context[top].p  = p - 1;
-                                       /* ptr to last asterisk */
-                                       context[top].first = first;
-                                       top++;
-                               }
-
-                               if (first) {
-                                       ss = s;
-                                       /* remember first non-'*' char */
-                                       first = false;
-                               }
-
-                               matches = true;
-                       } else {
-                               matches = false;
-                       }
-
-               } else if (s < es) {
-                       char ch = *p;
-                       if (ch == '#')
-                               matches = true;
-                       else {
-                               if (case_sens)
-                                       matches = (*s == ch);
-                               else
-                                       matches = (toupper(*s) == toupper(ch));
-                       }
-                       if (matches && first) {
-                               ss = s;  /* remember first non-'*' char */
-                               first = false;
-                       }
-               } else {
-                       matches = false;
-               }
-
-               if (matches) {
-                       p++; s++;
-               } else {
-                       /* doesn't match,
-                        * resume with stacked context if we have one */
-                       if (--top < 0)
-                               return NULL;  /* no match, give up */
-
-                       ss = context[top].ss;
-                       s  = context[top].s;
-                       p  = context[top].p;
-                       first = context[top].first;
-               }
-       }
-
-       /* end of pattern reached */
-       *m_len = max(s - ss, 1);
-       return ss;
-}
-
-
-/**
- * Add a new entry to the list of matches
- *
- * \param start_idx Offset of match start within textual representation
- * \param end_idx Offset of match end
- * \param context The search context to add the entry to.
- * \return Pointer to added entry, NULL iff failed.
- */
-static struct list_entry *
-add_entry(unsigned start_idx, unsigned end_idx,        struct search_context 
*context)
-{
-       struct list_entry *entry;
-
-       /* found string in box => add to list */
-       entry = calloc(1, sizeof(*entry));
-       if (!entry) {
-               return NULL;
-       }
-
-       entry->start_idx = start_idx;
-       entry->end_idx = end_idx;
-       entry->sel = NULL;
-
-       entry->next = 0;
-       entry->prev = context->found->prev;
-
-       if (context->found->prev == NULL) {
-               context->found->next = entry;
-       } else {
-               context->found->prev->next = entry;
-       }
-
-       context->found->prev = entry;
-
-       return entry;
-}
-
-
-/**
- * Finds all occurrences of a given string in the html box tree
- *
- * \param pattern   the string pattern to search for
- * \param p_len     pattern length
- * \param cur       pointer to the current box
- * \param case_sens whether to perform a case sensitive search
- * \param context   The search context to add the entry to.
- * \return true on success, false on memory allocation failure
- */
-static bool find_occurrences_html(const char *pattern, int p_len,
-               struct box *cur, bool case_sens,
-               struct search_context *context)
-{
-       struct box *a;
-
-       /* ignore this box, if there's no visible text */
-       if (!cur->object && cur->text) {
-               const char *text = cur->text;
-               unsigned length = cur->length;
-
-               while (length > 0) {
-                       struct list_entry *entry;
-                       unsigned match_length;
-                       unsigned match_offset;
-                       const char *new_text;
-                       const char *pos = find_pattern(text, length,
-                                       pattern, p_len, case_sens,
-                                       &match_length);
-                       if (!pos)
-                               break;
-
-                       /* found string in box => add to list */
-                       match_offset = pos - cur->text;
-
-                       entry = add_entry(cur->byte_offset + match_offset,
-                                               cur->byte_offset +
-                                                       match_offset +
-                                                       match_length, context);
-                       if (!entry)
-                               return false;
-
-                       entry->start_box = cur;
-                       entry->end_box = cur;
-
-                       new_text = pos + match_length;
-                       length -= (new_text - text);
-                       text = new_text;
-               }
-       }
-
-       /* and recurse */
-       for (a = cur->children; a; a = a->next) {
-               if (!find_occurrences_html(pattern, p_len, a, case_sens,
-                               context))
-                       return false;
-       }
-
-       return true;
-}
-
-
-/**
- * Finds all occurrences of a given string in a textplain content
- *
- * \param pattern   the string pattern to search for
- * \param p_len     pattern length
- * \param c         the content to be searched
- * \param case_sens whether to perform a case sensitive search
- * \param context   The search context to add the entry to.
- * \return true on success, false on memory allocation failure
- */
-
-static bool find_occurrences_text(const char *pattern, int p_len,
-               struct content *c, bool case_sens,
-               struct search_context *context)
-{
-       int nlines = textplain_line_count(c);
-       int line;
-
-       for(line = 0; line < nlines; line++) {
-               size_t offset, length;
-               const char *text = textplain_get_line(c, line,
-                               &offset, &length);
-               if (text) {
-                       while (length > 0) {
-                               struct list_entry *entry;
-                               unsigned match_length;
-                               size_t start_idx;
-                               const char *new_text;
-                               const char *pos = find_pattern(text, length,
-                                               pattern, p_len, case_sens,
-                                               &match_length);
-                               if (!pos)
-                                       break;
-
-                               /* found string in line => add to list */
-                               start_idx = offset + (pos - text);
-                               entry = add_entry(start_idx, start_idx +
-                                               match_length, context);
-                               if (!entry)
-                                       return false;
-
-                               new_text = pos + match_length;
-                               offset += (new_text - text);
-                               length -= (new_text - text);
-                               text = new_text;
-                       }
-               }
-       }
-
-       return true;
-}
-
-
-/**
- * Specifies whether all matches or just the current match should
- * be highlighted in the search text.
- */
-static void search_show_all(bool all, struct search_context *context)
-{
-       struct list_entry *a;
-
-       for (a = context->found->next; a; a = a->next) {
-               bool add = true;
-               if (!all && a != context->current) {
-                       add = false;
-                       if (a->sel) {
-                               selection_clear(a->sel, true);
-                               selection_destroy(a->sel);
-                               a->sel = NULL;
-                       }
-               }
-               if (add && !a->sel) {
-
-                       if (context->is_html == true) {
-                               html_content *html = (html_content *)context->c;
-                               a->sel = selection_create(context->c, true);
-                               if (!a->sel)
-                                       continue;
-
-                               selection_init(a->sel, html->layout,
-                                               &html->len_ctx);
-                       } else {
-                               a->sel = selection_create(context->c, false);
-                               if (!a->sel)
-                                       continue;
-
-                               selection_init(a->sel, NULL, NULL);
-                       }
-
-                       selection_set_start(a->sel, a->start_idx);
-                       selection_set_end(a->sel, a->end_idx);
-               }
-       }
-}
-
-
-/**
- * Search for a string in the box tree
- *
- * \param string the string to search for
- * \param string_len length of search string
- * \param context The search context to add the entry to.
- * \param flags flags to control the search.
- */
-static void
-search_text(const char *string,
-           int string_len,
-           struct search_context *context,
-           search_flags_t flags)
-{
-       struct rect bounds;
-       struct box *box = NULL;
-       union content_msg_data msg_data;
-       bool case_sensitive, forwards, showall;
-
-       case_sensitive = ((flags & SEARCH_FLAG_CASE_SENSITIVE) != 0) ?
-                       true : false;
-       forwards = ((flags & SEARCH_FLAG_FORWARDS) != 0) ? true : false;
-       showall = ((flags & SEARCH_FLAG_SHOWALL) != 0) ? true : false;
-
-       if (context->c == NULL)
-               return;
-
-       if (context->is_html == true) {
-               html_content *html = (html_content *)context->c;
-
-               box = html->layout;
-
-               if (!box)
-                       return;
-       }
-
-
-       /* check if we need to start a new search or continue an old one */
-       if ((context->newsearch) ||
-           (context->prev_case_sens != case_sensitive)) {
-               bool res;
-
-               if (context->string != NULL)
-                       free(context->string);
-
-               context->current = NULL;
-               free_matches(context);
-
-               context->string = malloc(string_len + 1);
-               if (context->string != NULL) {
-                       memcpy(context->string, string, string_len);
-                       context->string[string_len] = '\0';
-               }
-
-               guit->search->hourglass(true, context->gui_p);
-
-               if (context->is_html == true) {
-                       res = find_occurrences_html(string, string_len,
-                                       box, case_sensitive, context);
-               } else {
-                       res = find_occurrences_text(string, string_len,
-                                       context->c, case_sensitive, context);
-               }
-
-               if (!res) {
-                       free_matches(context);
-                       guit->search->hourglass(false, context->gui_p);
-                       return;
-               }
-               guit->search->hourglass(false, context->gui_p);
-
-               context->prev_case_sens = case_sensitive;
-
-               /* new search, beginning at the top of the page */
-               context->current = context->found->next;
-               context->newsearch = false;
-
-       } else if (context->current != NULL) {
-               /* continued search in the direction specified */
-               if (forwards) {
-                       if (context->current->next)
-                               context->current = context->current->next;
-               } else {
-                       if (context->current->prev)
-                               context->current = context->current->prev;
-               }
-       }
-
-       guit->search->status((context->current != NULL), context->gui_p);
-
-       search_show_all(showall, context);
-
-       guit->search->back_state((context->current != NULL) &&
-                               (context->current->prev != NULL),
-                               context->gui_p);
-       guit->search->forward_state((context->current != NULL) &&
-                               (context->current->next != NULL),
-                               context->gui_p);
-
-       if (context->current == NULL)
-               return;
-
-       if (context->is_html == true) {
-               /* get box position and jump to it */
-               box_coords(context->current->start_box, &bounds.x0, &bounds.y0);
-               /* \todo: move x0 in by correct idx */
-               box_coords(context->current->end_box, &bounds.x1, &bounds.y1);
-               /* \todo: move x1 in by correct idx */
-               bounds.x1 += context->current->end_box->width;
-               bounds.y1 += context->current->end_box->height;
-       } else {
-               textplain_coords_from_range(context->c,
-                               context->current->start_idx,
-                               context->current->end_idx, &bounds);
-       }
-
-       msg_data.scroll.area = true;
-       msg_data.scroll.x0 = bounds.x0;
-       msg_data.scroll.y0 = bounds.y0;
-       msg_data.scroll.x1 = bounds.x1;
-       msg_data.scroll.y1 = bounds.y1;
-       content_broadcast(context->c, CONTENT_MSG_SCROLL, &msg_data);
-}
-
-
-/* Exported function documented in search.h */
-void
-search_step(struct search_context *context,
-           search_flags_t flags,
-           const char *string)
-{
-       int string_len;
-       int i = 0;
-
-       assert(context != NULL);
-
-       guit->search->add_recent(string, context->gui_p);
-
-       string_len = strlen(string);
-       for (i = 0; i < string_len; i++)
-               if (string[i] != '#' && string[i] != '*')
-                       break;
-       if (i >= string_len) {
-               union content_msg_data msg_data;
-               free_matches(context);
-
-               guit->search->status(true, context->gui_p);
-               guit->search->back_state(false, context->gui_p);
-               guit->search->forward_state(false, context->gui_p);
-
-               msg_data.scroll.area = false;
-               msg_data.scroll.x0 = 0;
-               msg_data.scroll.y0 = 0;
-               content_broadcast(context->c, CONTENT_MSG_SCROLL, &msg_data);
-               return;
-       }
-       search_text(string, string_len, context, flags);
-}
-
-
-/* Exported function documented in search.h */
-bool search_term_highlighted(struct content *c,
-               unsigned start_offset, unsigned end_offset,
-               unsigned *start_idx, unsigned *end_idx,
-               struct search_context *context)
-{
-       if (c == context->c) {
-               struct list_entry *a;
-               for (a = context->found->next; a; a = a->next)
-                       if (a->sel && selection_defined(a->sel) &&
-                                       selection_highlighted(a->sel,
-                                               start_offset, end_offset,
-                                               start_idx, end_idx))
-                               return true;
-       }
-
-       return false;
-}
-
-
-
-
-/* Exported function documented in search.h */
-void search_destroy_context(struct search_context *context)
-{
-       assert(context != NULL);
-
-       if (context->string != NULL) {
-               guit->search->add_recent(context->string, context->gui_p);
-               free(context->string);
-       }
-
-       guit->search->forward_state(true, context->gui_p);
-       guit->search->back_state(true, context->gui_p);
-
-       free_matches(context);
-       free(context);
-}
diff --git a/content/handlers/html/search.h b/content/handlers/html/search.h
deleted file mode 100644
index dfb1afc..0000000
--- a/content/handlers/html/search.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2009 Mark Benjamin <[email protected]>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * Interface to HTML searching.
- */
-
-#ifndef NETSURF_HTML_SEARCH_H
-#define NETSURF_HTML_SEARCH_H
-
-#include <ctype.h>
-#include <string.h>
-
-#include "desktop/search.h"
-
-struct search_context;
-
-/**
- * create a search_context
- *
- * \param c       The content the search_context is connected to
- * \param type    The content type of c
- * \param context A context pointer passed to the provider routines.
- * \return A new search context or NULL on error.
- */
-struct search_context *search_create_context(struct content *c,
-                                     content_type type, void *context);
-
-/**
- * Ends the search process, invalidating all state
- * freeing the list of found boxes
- */
-void search_destroy_context(struct search_context *context);
-
-/**
- * Begins/continues the search process
- *
- * \note that this may be called many times for a single search.
- *
- * \param context The search context in use.
- * \param flags   The flags forward/back etc
- * \param string  The string to match
- */
-void search_step(struct search_context *context, search_flags_t flags,
-               const char * string);
-
-
-/**
- * Determines whether any portion of the given text box should be
- * selected because it matches the current search string.
- *
- * \param c            The content to hilight within.
- * \param start_offset byte offset within text of string to be checked
- * \param end_offset   byte offset within text
- * \param start_idx    byte offset within string of highlight start
- * \param end_idx      byte offset of highlight end
- * \param context      The search context to hilight entries from.
- * \return true iff part of the box should be highlighted
- */
-bool search_term_highlighted(struct content *c,
-               unsigned start_offset, unsigned end_offset,
-               unsigned *start_idx, unsigned *end_idx,
-               struct search_context *context);
-
-#endif
diff --git a/content/handlers/text/textplain.c 
b/content/handlers/text/textplain.c
index e9b5534..e8c3831 100644
--- a/content/handlers/text/textplain.c
+++ b/content/handlers/text/textplain.c
@@ -41,10 +41,10 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "content/hlcache.h"
+#include "content/textsearch.h"
 #include "desktop/selection.h"
 #include "desktop/gui_internal.h"
 
-#include "html/search.h"
 #include "text/textplain.h"
 
 struct textplain_line {
@@ -71,7 +71,7 @@ typedef struct textplain_content {
        struct selection sel;   /** Selection state */
 
        /** Context for free text search, or NULL if none */
-       struct search_context *search;
+       struct textsearch_context *search;
        /** Current search string, or NULL if none */
        char *search_string;
 } textplain_content;
@@ -753,7 +753,7 @@ static void textplain_search_clear(struct content *c)
        text->search_string = NULL;
 
        if (text->search != NULL) {
-               search_destroy_context(text->search);
+               content_textsearch_destroy(text->search);
        }
        text->search = NULL;
 }
@@ -771,14 +771,16 @@ static void textplain_search(struct content *c, void 
*gui_data,
                             search_flags_t flags, const char *string)
 {
        textplain_content *text = (textplain_content *) c;
+       nserror res;
 
        assert(c != NULL);
 
-       if (string != NULL && text->search_string != NULL &&
+       if (string != NULL &&
+           text->search_string != NULL &&
            strcmp(string, text->search_string) == 0 &&
            text->search != NULL) {
                /* Continue prev. search */
-               search_step(text->search, flags, string);
+               content_textsearch_step(text->search, flags, string);
 
        } else if (string != NULL) {
                /* New search */
@@ -788,17 +790,16 @@ static void textplain_search(struct content *c, void 
*gui_data,
                        return;
 
                if (text->search != NULL) {
-                       search_destroy_context(text->search);
+                       content_textsearch_destroy(text->search);
                        text->search = NULL;
                }
 
-               text->search = search_create_context(c, CONTENT_TEXTPLAIN,
-                                                    gui_data);
-
-               if (text->search == NULL)
+               res = content_textsearch_create(c, gui_data, &text->search);
+               if (res != NSERROR_OK) {
                        return;
+               }
 
-               search_step(text->search, flags, string);
+               content_textsearch_step(text->search, flags, string);
 
        } else {
                /* Clear search */
@@ -839,7 +840,6 @@ text_draw(const char *utf8_text,
            float scale,
            textplain_content *text,
            const struct selection *sel,
-           struct search_context *search,
            const struct redraw_context *ctx)
 {
        bool highlighted = false;
@@ -868,13 +868,12 @@ text_draw(const char *utf8_text,
 
                /* what about the current search operation, if any? */
                if (!highlighted &&
-                   (search != NULL) &&
-                   search_term_highlighted((struct content *)text,
-                                           offset,
-                                           offset + len,
-                                           &start_idx,
-                                           &end_idx,
-                                           search)) {
+                   (text->search != NULL) &&
+                   content_textsearch_ishighlighted(text->search,
+                                                    offset,
+                                                    offset + len,
+                                                    &start_idx,
+                                                    &end_idx)) {
                        highlighted = true;
                }
 
@@ -1125,7 +1124,6 @@ textplain_redraw(struct content *c,
                                       data->scale,
                                       text,
                                       &text->sel,
-                                      text->search,
                                       ctx)) {
                                return false;
                        }
@@ -1165,15 +1163,17 @@ textplain_redraw(struct content *c,
                                                highlighted = true;
                                }
 
-                               if (!highlighted && (text->search != NULL)) {
+                               if (!highlighted &&
+                                   (text->search != NULL)) {
                                        unsigned start_idx, end_idx;
-                                       if (search_term_highlighted(c,
-                                                                   tab_ofst,
-                                                                   tab_ofst + 
1,
-                                                                   &start_idx,
-                                                                   &end_idx,
-                                                                   
text->search))
+                                       if (content_textsearch_ishighlighted(
+                                                   text->search,
+                                                   tab_ofst,
+                                                   tab_ofst + 1,
+                                                   &start_idx,
+                                                   &end_idx)) {
                                                highlighted = true;
+                                       }
                                }
 
                                if (highlighted) {
@@ -1228,7 +1228,7 @@ static nserror textplain_close(struct content *c)
        textplain_content *text = (textplain_content *) c;
 
        if (text->search != NULL) {
-               search_destroy_context(text->search);
+               content_textsearch_destroy(text->search);
        }
 
        text->bw = NULL;
diff --git a/content/textsearch.c b/content/textsearch.c
new file mode 100644
index 0000000..c535948
--- /dev/null
+++ b/content/textsearch.c
@@ -0,0 +1,718 @@
+/*
+ * Copyright 2004 John M Bell <[email protected]>
+ * Copyright 2005 Adrian Lees <[email protected]>
+ * Copyright 2009 Mark Benjamin <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Free text search
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "utils/errors.h"
+#include "utils/utils.h"
+#include "content/content.h"
+#include "desktop/selection.h"
+#include "netsurf/search.h"
+#include "netsurf/content_type.h"
+#include "desktop/gui_internal.h"
+
+#include "text/textplain.h"
+#include "html/box.h"
+#include "html/box_inspect.h"
+#include "html/private.h"
+
+#include "content/textsearch.h"
+
+
+struct list_entry {
+       unsigned start_idx;     /* start position of match */
+       unsigned end_idx;       /* end of match */
+
+       struct box *start_box;  /* used only for html contents */
+       struct box *end_box;
+
+       struct selection *sel;
+
+       struct list_entry *prev;
+       struct list_entry *next;
+};
+
+/**
+ * The context for a free text search
+ */
+struct textsearch_context {
+       void *gui_p;
+       struct content *c;
+       struct list_entry *found;
+       struct list_entry *current; /* first for select all */
+       char *string;
+       bool prev_case_sens;
+       bool newsearch;
+       bool is_html;
+};
+
+
+
+
+/**
+ * Release the memory used by the list of matches,
+ * deleting selection objects too
+ */
+static void free_matches(struct textsearch_context *textsearch)
+{
+       struct list_entry *cur;
+       struct list_entry *nxt;
+
+       cur = textsearch->found->next;
+
+       /*
+        * empty the list before clearing and deleting the selections
+        * because the the clearing may update the toolkit immediately,
+        * causing nested accesses to the list
+        */
+
+       textsearch->found->prev = NULL;
+       textsearch->found->next = NULL;
+
+       for (; cur; cur = nxt) {
+               nxt = cur->next;
+               if (cur->sel) {
+                       selection_clear(cur->sel, true);
+                       selection_destroy(cur->sel);
+               }
+               free(cur);
+       }
+}
+
+
+/**
+ * Find the first occurrence of 'match' in 'string' and return its index
+ *
+ * \param  string     the string to be searched (unterminated)
+ * \param  s_len      length of the string to be searched
+ * \param  pattern    the pattern for which we are searching (unterminated)
+ * \param  p_len      length of pattern
+ * \param  case_sens  true iff case sensitive match required
+ * \param  m_len      accepts length of match in bytes
+ * \return pointer to first match, NULL if none
+ */
+static const char *
+find_pattern(const char *string,
+            int s_len,
+            const char *pattern,
+            int p_len,
+            bool case_sens,
+            unsigned int *m_len)
+{
+       struct { const char *ss, *s, *p; bool first; } context[16];
+       const char *ep = pattern + p_len;
+       const char *es = string  + s_len;
+       const char *p = pattern - 1;  /* a virtual '*' before the pattern */
+       const char *ss = string;
+       const char *s = string;
+       bool first = true;
+       int top = 0;
+
+       while (p < ep) {
+               bool matches;
+               if (p < pattern || *p == '*') {
+                       char ch;
+
+                       /* skip any further asterisks; one is the same as many
+                       */
+                       do p++; while (p < ep && *p == '*');
+
+                       /* if we're at the end of the pattern, yes, it matches
+                       */
+                       if (p >= ep) break;
+
+                       /* anything matches a # so continue matching from
+                          here, and stack a context that will try to match
+                          the wildcard against the next character */
+
+                       ch = *p;
+                       if (ch != '#') {
+                               /* scan forwards until we find a match for
+                                  this char */
+                               if (!case_sens) ch = toupper(ch);
+                               while (s < es) {
+                                       if (case_sens) {
+                                               if (*s == ch) break;
+                                       } else if (toupper(*s) == ch)
+                                               break;
+                                       s++;
+                               }
+                       }
+
+                       if (s < es) {
+                               /* remember where we are in case the match
+                                  fails; we may then resume */
+                               if (top < (int)NOF_ELEMENTS(context)) {
+                                       context[top].ss = ss;
+                                       context[top].s  = s + 1;
+                                       context[top].p  = p - 1;
+                                       /* ptr to last asterisk */
+                                       context[top].first = first;
+                                       top++;
+                               }
+
+                               if (first) {
+                                       ss = s;
+                                       /* remember first non-'*' char */
+                                       first = false;
+                               }
+
+                               matches = true;
+                       } else {
+                               matches = false;
+                       }
+
+               } else if (s < es) {
+                       char ch = *p;
+                       if (ch == '#')
+                               matches = true;
+                       else {
+                               if (case_sens)
+                                       matches = (*s == ch);
+                               else
+                                       matches = (toupper(*s) == toupper(ch));
+                       }
+                       if (matches && first) {
+                               ss = s;  /* remember first non-'*' char */
+                               first = false;
+                       }
+               } else {
+                       matches = false;
+               }
+
+               if (matches) {
+                       p++; s++;
+               } else {
+                       /* doesn't match,
+                        * resume with stacked context if we have one */
+                       if (--top < 0)
+                               return NULL;  /* no match, give up */
+
+                       ss = context[top].ss;
+                       s  = context[top].s;
+                       p  = context[top].p;
+                       first = context[top].first;
+               }
+       }
+
+       /* end of pattern reached */
+       *m_len = max(s - ss, 1);
+       return ss;
+}
+
+
+/**
+ * Add a new entry to the list of matches
+ *
+ * \param start_idx Offset of match start within textual representation
+ * \param end_idx Offset of match end
+ * \param context The search context to add the entry to.
+ * \return Pointer to added entry, NULL iff failed.
+ */
+static struct list_entry *
+add_entry(unsigned start_idx,
+         unsigned end_idx,
+         struct textsearch_context *context)
+{
+       struct list_entry *entry;
+
+       /* found string in box => add to list */
+       entry = calloc(1, sizeof(*entry));
+       if (!entry) {
+               return NULL;
+       }
+
+       entry->start_idx = start_idx;
+       entry->end_idx = end_idx;
+       entry->sel = NULL;
+
+       entry->next = NULL;
+       entry->prev = context->found->prev;
+
+       if (context->found->prev == NULL) {
+               context->found->next = entry;
+       } else {
+               context->found->prev->next = entry;
+       }
+
+       context->found->prev = entry;
+
+       return entry;
+}
+
+
+/**
+ * Finds all occurrences of a given string in an html box
+ *
+ * \param pattern   the string pattern to search for
+ * \param p_len     pattern length
+ * \param cur       pointer to the current box
+ * \param case_sens whether to perform a case sensitive search
+ * \param context   The search context to add the entry to.
+ * \return true on success, false on memory allocation failure
+ */
+static bool
+find_occurrences_html_box(const char *pattern,
+                         int p_len,
+                         struct box *cur,
+                         bool case_sens,
+                         struct textsearch_context *context)
+{
+       struct box *a;
+
+       /* ignore this box, if there's no visible text */
+       if (!cur->object && cur->text) {
+               const char *text = cur->text;
+               unsigned length = cur->length;
+
+               while (length > 0) {
+                       struct list_entry *entry;
+                       unsigned match_length;
+                       unsigned match_offset;
+                       const char *new_text;
+                       const char *pos;
+
+                       pos = find_pattern(text,
+                                          length,
+                                          pattern,
+                                          p_len,
+                                          case_sens,
+                                          &match_length);
+                       if (!pos)
+                               break;
+
+                       /* found string in box => add to list */
+                       match_offset = pos - cur->text;
+
+                       entry = add_entry(cur->byte_offset + match_offset,
+                                         cur->byte_offset + match_offset + 
match_length,
+                                         context);
+                       if (!entry)
+                               return false;
+
+                       entry->start_box = cur;
+                       entry->end_box = cur;
+
+                       new_text = pos + match_length;
+                       length -= (new_text - text);
+                       text = new_text;
+               }
+       }
+
+       /* and recurse */
+       for (a = cur->children; a; a = a->next) {
+               if (!find_occurrences_html_box(pattern,
+                                              p_len,
+                                              a,
+                                              case_sens,
+                                              context))
+                       return false;
+       }
+
+       return true;
+}
+
+/**
+ * Finds all occurrences of a given string in the html box tree
+ *
+ * \param pattern   the string pattern to search for
+ * \param p_len     pattern length
+ * \param c The content to search
+ * \param csens whether to perform a case sensitive search
+ * \param context   The search context to add the entry to.
+ * \return true on success, false on memory allocation failure
+ */
+static bool
+find_occurrences_html(const char *pattern,
+                     int p_len,
+                     struct content *c,
+                     bool csens,
+                     struct textsearch_context *context)
+{
+       html_content *html = (html_content *)c;
+
+       if (html->layout == NULL) {
+               return false;
+       }
+
+       return find_occurrences_html_box(pattern,
+                                        p_len,
+                                        html->layout,
+                                        csens,
+                                        context);
+}
+
+/**
+ * Finds all occurrences of a given string in a textplain content
+ *
+ * \param pattern   the string pattern to search for
+ * \param p_len     pattern length
+ * \param c         the content to be searched
+ * \param case_sens whether to perform a case sensitive search
+ * \param context   The search context to add the entry to.
+ * \return true on success, false on memory allocation failure
+ */
+static bool
+find_occurrences_text(const char *pattern,
+                     int p_len,
+                     struct content *c,
+                     bool case_sens,
+                     struct textsearch_context *context)
+{
+       int nlines = textplain_line_count(c);
+       int line;
+
+       for(line = 0; line < nlines; line++) {
+               size_t offset, length;
+               const char *text;
+
+               text = textplain_get_line(c, line, &offset, &length);
+               if (text) {
+                       while (length > 0) {
+                               struct list_entry *entry;
+                               unsigned match_length;
+                               size_t start_idx;
+                               const char *new_text;
+                               const char *pos;
+
+                               pos = find_pattern(text, length,
+                                                   pattern, p_len,
+                                                   case_sens,
+                                                   &match_length);
+                               if (!pos)
+                                       break;
+
+                               /* found string in line => add to list */
+                               start_idx = offset + (pos - text);
+                               entry = add_entry(start_idx,
+                                                 start_idx + match_length,
+                                                 context);
+                               if (!entry)
+                                       return false;
+
+                               new_text = pos + match_length;
+                               offset += (new_text - text);
+                               length -= (new_text - text);
+                               text = new_text;
+                       }
+               }
+       }
+
+       return true;
+}
+
+
+/**
+ * Specifies whether all matches or just the current match should
+ * be highlighted in the search text.
+ */
+static void search_show_all(bool all, struct textsearch_context *context)
+{
+       struct list_entry *a;
+
+       for (a = context->found->next; a; a = a->next) {
+               bool add = true;
+               if (!all && a != context->current) {
+                       add = false;
+                       if (a->sel) {
+                               selection_clear(a->sel, true);
+                               selection_destroy(a->sel);
+                               a->sel = NULL;
+                       }
+               }
+               if (add && !a->sel) {
+
+                       if (context->is_html == true) {
+                               html_content *html = (html_content *)context->c;
+                               a->sel = selection_create(context->c, true);
+                               if (!a->sel)
+                                       continue;
+
+                               selection_init(a->sel, html->layout,
+                                               &html->len_ctx);
+                       } else {
+                               a->sel = selection_create(context->c, false);
+                               if (!a->sel)
+                                       continue;
+
+                               selection_init(a->sel, NULL, NULL);
+                       }
+
+                       selection_set_start(a->sel, a->start_idx);
+                       selection_set_end(a->sel, a->end_idx);
+               }
+       }
+}
+
+
+/**
+ * Search for a string in the box tree
+ *
+ * \param string the string to search for
+ * \param string_len length of search string
+ * \param context The search context to add the entry to.
+ * \param flags flags to control the search.
+ */
+static void
+search_text(const char *string,
+           int string_len,
+           struct textsearch_context *context,
+           search_flags_t flags)
+{
+       struct rect bounds;
+       union content_msg_data msg_data;
+       bool case_sensitive, forwards, showall;
+
+       case_sensitive = ((flags & SEARCH_FLAG_CASE_SENSITIVE) != 0) ?
+                       true : false;
+       forwards = ((flags & SEARCH_FLAG_FORWARDS) != 0) ? true : false;
+       showall = ((flags & SEARCH_FLAG_SHOWALL) != 0) ? true : false;
+
+       if (context->c == NULL)
+               return;
+
+       /* check if we need to start a new search or continue an old one */
+       if ((context->newsearch) ||
+           (context->prev_case_sens != case_sensitive)) {
+               bool res;
+
+               if (context->string != NULL)
+                       free(context->string);
+
+               context->current = NULL;
+               free_matches(context);
+
+               context->string = malloc(string_len + 1);
+               if (context->string != NULL) {
+                       memcpy(context->string, string, string_len);
+                       context->string[string_len] = '\0';
+               }
+
+               guit->search->hourglass(true, context->gui_p);
+
+               if (context->is_html == true) {
+                       res = find_occurrences_html(string, string_len,
+                                       context->c, case_sensitive, context);
+               } else {
+                       res = find_occurrences_text(string, string_len,
+                                       context->c, case_sensitive, context);
+               }
+
+               guit->search->hourglass(false, context->gui_p);
+
+               if (!res) {
+                       free_matches(context);
+                       return;
+               }
+
+               context->prev_case_sens = case_sensitive;
+
+               /* new search, beginning at the top of the page */
+               context->current = context->found->next;
+               context->newsearch = false;
+
+       } else if (context->current != NULL) {
+               /* continued search in the direction specified */
+               if (forwards) {
+                       if (context->current->next)
+                               context->current = context->current->next;
+               } else {
+                       if (context->current->prev)
+                               context->current = context->current->prev;
+               }
+       }
+
+       guit->search->status((context->current != NULL), context->gui_p);
+
+       search_show_all(showall, context);
+
+       guit->search->back_state((context->current != NULL) &&
+                               (context->current->prev != NULL),
+                               context->gui_p);
+       guit->search->forward_state((context->current != NULL) &&
+                               (context->current->next != NULL),
+                               context->gui_p);
+
+       if (context->current == NULL)
+               return;
+
+       if (context->is_html == true) {
+               /* get box position and jump to it */
+               box_coords(context->current->start_box, &bounds.x0, &bounds.y0);
+               /* \todo: move x0 in by correct idx */
+               box_coords(context->current->end_box, &bounds.x1, &bounds.y1);
+               /* \todo: move x1 in by correct idx */
+               bounds.x1 += context->current->end_box->width;
+               bounds.y1 += context->current->end_box->height;
+       } else {
+               textplain_coords_from_range(context->c,
+                               context->current->start_idx,
+                               context->current->end_idx, &bounds);
+       }
+
+       msg_data.scroll.area = true;
+       msg_data.scroll.x0 = bounds.x0;
+       msg_data.scroll.y0 = bounds.y0;
+       msg_data.scroll.x1 = bounds.x1;
+       msg_data.scroll.y1 = bounds.y1;
+       content_broadcast(context->c, CONTENT_MSG_SCROLL, &msg_data);
+}
+
+
+/* Exported function documented in context/textsearch.h */
+nserror
+content_textsearch_step(struct textsearch_context *textsearch,
+                       search_flags_t flags,
+                       const char *string)
+{
+       int string_len;
+       int i = 0;
+
+       assert(textsearch != NULL);
+
+       guit->search->add_recent(string, textsearch->gui_p);
+
+       string_len = strlen(string);
+       for (i = 0; i < string_len; i++) {
+               if (string[i] != '#' && string[i] != '*')
+                       break;
+       }
+
+       if (i < string_len) {
+               search_text(string, string_len, textsearch, flags);
+       } else {
+               union content_msg_data msg_data;
+               free_matches(textsearch);
+
+               guit->search->status(true, textsearch->gui_p);
+               guit->search->back_state(false, textsearch->gui_p);
+               guit->search->forward_state(false, textsearch->gui_p);
+
+               msg_data.scroll.area = false;
+               msg_data.scroll.x0 = 0;
+               msg_data.scroll.y0 = 0;
+               content_broadcast(textsearch->c, CONTENT_MSG_SCROLL, &msg_data);
+       }
+
+       return NSERROR_OK;
+}
+
+
+/* Exported function documented in content/textsearch.h */
+bool
+content_textsearch_ishighlighted(struct textsearch_context *textsearch,
+                                unsigned start_offset,
+                                unsigned end_offset,
+                                unsigned *start_idx,
+                                unsigned *end_idx)
+{
+       struct list_entry *cur;
+
+       for (cur = textsearch->found->next; cur != NULL; cur = cur->next) {
+               if (cur->sel &&
+                   selection_defined(cur->sel) &&
+                   selection_highlighted(cur->sel,
+                                         start_offset,
+                                         end_offset,
+                                         start_idx,
+                                         end_idx)) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
+/* Exported function documented in content/textsearch.h */
+nserror
+content_textsearch_create(struct content *c,
+                         void *gui_data,
+                         struct textsearch_context **textsearch_out)
+{
+       struct textsearch_context *context;
+       struct list_entry *search_head;
+       content_type type;
+
+       type = c->handler->type();
+
+       if (type != CONTENT_HTML && type != CONTENT_TEXTPLAIN) {
+               return NSERROR_NOT_IMPLEMENTED;
+       }
+
+       context = malloc(sizeof(struct textsearch_context));
+       if (context == NULL) {
+               return NSERROR_NOMEM;
+       }
+
+       search_head = malloc(sizeof(struct list_entry));
+       if (search_head == NULL) {
+               free(context);
+               return NSERROR_NOMEM;
+       }
+
+       search_head->start_idx = 0;
+       search_head->end_idx = 0;
+       search_head->start_box = NULL;
+       search_head->end_box = NULL;
+       search_head->sel = NULL;
+       search_head->prev = NULL;
+       search_head->next = NULL;
+
+       context->found = search_head;
+       context->current = NULL;
+       context->string = NULL;
+       context->prev_case_sens = false;
+       context->newsearch = true;
+       context->c = c;
+       context->is_html = (type == CONTENT_HTML) ? true : false;
+       context->gui_p = gui_data;
+
+       *textsearch_out = context;
+
+       return NSERROR_OK;
+}
+
+
+/* Exported function documented in search.h */
+nserror content_textsearch_destroy(struct textsearch_context *textsearch)
+{
+       assert(textsearch != NULL);
+
+       if (textsearch->string != NULL) {
+               guit->search->add_recent(textsearch->string, textsearch->gui_p);
+               free(textsearch->string);
+       }
+
+       guit->search->forward_state(true, textsearch->gui_p);
+       guit->search->back_state(true, textsearch->gui_p);
+
+       free_matches(textsearch);
+       free(textsearch);
+
+       return NSERROR_OK;
+}
diff --git a/content/textsearch.h b/content/textsearch.h
new file mode 100644
index 0000000..f94bcdb
--- /dev/null
+++ b/content/textsearch.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2009 Mark Benjamin <[email protected]>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Interface to HTML searching.
+ */
+
+#ifndef NETSURF_CONTENT_SEARCH_H
+#define NETSURF_CONTENT_SEARCH_H
+
+#include <ctype.h>
+#include <string.h>
+
+#include "desktop/search.h"
+
+struct textsearch_context;
+struct content;
+
+/**
+ * create a search_context
+ *
+ * \param c The content the search_context is connected to
+ * \param context A context pointer passed to the provider routines.
+ * \param search_out A pointer to recive the new text search context
+ * \return NSERROR_OK on success and \a search_out updated else error code
+ */
+nserror content_textsearch_create(struct content *c, void *context, struct 
textsearch_context **textsearch_out);
+
+/**
+ * Begins/continues the search process
+ *
+ * \note that this may be called many times for a single search.
+ *
+ * \param context The search context in use.
+ * \param flags   The flags forward/back etc
+ * \param string  The string to match
+ */
+nserror content_textsearch_step(struct textsearch_context *textsearch, 
search_flags_t flags, const char *string);
+
+/**
+ * Ends the search process, invalidating all state freeing the list of
+ * found boxes.
+ */
+nserror content_textsearch_destroy(struct textsearch_context *textsearch);
+
+/**
+ * Determines whether any portion of the given text box should be
+ * selected because it matches the current search string.
+ *
+ * \param textsearch The search context to hilight entries from.
+ * \param c The content to highlight within.
+ * \param start_offset byte offset within text of string to be checked
+ * \param end_offset   byte offset within text
+ * \param start_idx    byte offset within string of highlight start
+ * \param end_idx      byte offset of highlight end
+ * \return true iff part of the box should be highlighted
+ */
+bool content_textsearch_ishighlighted(struct textsearch_context *textsearch,
+                                     unsigned start_offset,
+                                     unsigned end_offset,
+                                     unsigned *start_idx,
+                                     unsigned *end_idx);
+
+#endif


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=e72ca36863f4b05e5e641e77472f0f7fef97d906
commit e72ca36863f4b05e5e641e77472f0f7fef97d906
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>

    remove unecessary includes

diff --git a/content/handlers/text/textplain.c 
b/content/handlers/text/textplain.c
index e9037f9..e9b5534 100644
--- a/content/handlers/text/textplain.c
+++ b/content/handlers/text/textplain.c
@@ -23,22 +23,16 @@
  * plain text content handling implementation.
  */
 
-#include <assert.h>
-#include <errno.h>
-#include <stddef.h>
-#include <string.h>
-#include <strings.h>
-#include <math.h>
-
 #include <parserutils/input/inputstream.h>
-#include <parserutils/charset/utf8.h>
 
+#include "utils/errors.h"
 #include "utils/corestrings.h"
 #include "utils/http.h"
 #include "utils/log.h"
 #include "utils/messages.h"
 #include "utils/utils.h"
 #include "utils/utf8.h"
+#include "utils/nsoption.h"
 #include "netsurf/content.h"
 #include "netsurf/keypress.h"
 #include "netsurf/browser_window.h"
@@ -47,9 +41,6 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "content/hlcache.h"
-#include "css/utils.h"
-#include "utils/nsoption.h"
-#include "desktop/search.h"
 #include "desktop/selection.h"
 #include "desktop/gui_internal.h"
 
@@ -61,6 +52,9 @@ struct textplain_line {
        size_t  length;
 };
 
+/**
+ * plain text content
+ */
 typedef struct textplain_content {
        struct content base;
 
@@ -195,7 +189,7 @@ no_memory:
 static nserror
 textplain_create(const content_handler *handler,
                 lwc_string *imime_type,
-                const http_parameter *params,
+                const struct http_parameter *params,
                 llcache_handle *llcache,
                 const char *fallback_charset,
                 bool quirks,
diff --git a/content/handlers/text/textplain.h 
b/content/handlers/text/textplain.h
index 23917fb..9c6ad92 100644
--- a/content/handlers/text/textplain.h
+++ b/content/handlers/text/textplain.h
@@ -31,7 +31,6 @@
 
 struct content;
 struct hlcache_handle;
-struct http_parameter;
 struct rect;
 
 /**


-----------------------------------------------------------------------

Summary of changes:
 content/Makefile                                 |   13 +-
 content/handlers/html/Makefile                   |    1 -
 content/handlers/html/html.c                     |    4 +-
 content/handlers/html/interaction.c              |   25 +-
 content/handlers/html/private.h                  |    2 +-
 content/handlers/html/redraw.c                   |   25 +-
 content/handlers/text/textplain.c                |   74 ++---
 content/handlers/text/textplain.h                |    1 -
 content/{handlers/html/search.c => textsearch.c} |  366 +++++++++++++---------
 content/{handlers/html/search.h => textsearch.h} |   43 ++-
 10 files changed, 308 insertions(+), 246 deletions(-)
 rename content/{handlers/html/search.c => textsearch.c} (71%)
 rename content/{handlers/html/search.h => textsearch.h} (62%)

diff --git a/content/Makefile b/content/Makefile
index b4353ba..abc5a24 100644
--- a/content/Makefile
+++ b/content/Makefile
@@ -1,7 +1,16 @@
 # Content sources
 
-S_CONTENT := content.c content_factory.c dirlist.c fetch.c hlcache.c   \
-       llcache.c mimesniff.c urldb.c no_backing_store.c
+S_CONTENT :=                   \
+       content.c               \
+       content_factory.c       \
+       dirlist.c               \
+       fetch.c                 \
+       hlcache.c               \
+       llcache.c               \
+       mimesniff.c             \
+       textsearch.c            \
+       urldb.c                 \
+       no_backing_store.c
 
 # Make filesystem backing store available
 ifeq ($(NETSURF_FS_BACKING_STORE),YES)
diff --git a/content/handlers/html/Makefile b/content/handlers/html/Makefile
index 677786c..233fb13 100644
--- a/content/handlers/html/Makefile
+++ b/content/handlers/html/Makefile
@@ -20,5 +20,4 @@ S_HTML := box_construct.c     \
        redraw.c                \
        redraw_border.c         \
        script.c                \
-       search.c                \
        table.c
diff --git a/content/handlers/html/html.c b/content/handlers/html/html.c
index af06431..a3d4264 100644
--- a/content/handlers/html/html.c
+++ b/content/handlers/html/html.c
@@ -49,6 +49,7 @@
 #include "netsurf/misc.h"
 #include "content/hlcache.h"
 #include "content/content_factory.h"
+#include "content/textsearch.h"
 #include "desktop/selection.h"
 #include "desktop/scrollbar.h"
 #include "desktop/textarea.h"
@@ -69,7 +70,6 @@
 #include "html/form_internal.h"
 #include "html/imagemap.h"
 #include "html/layout.h"
-#include "html/search.h"
 
 #define CHUNK 4096
 
@@ -1327,7 +1327,7 @@ static nserror html_close(struct content *c)
        selection_clear(&htmlc->sel, false);
 
        if (htmlc->search != NULL) {
-               search_destroy_context(htmlc->search);
+               content_textsearch_destroy(htmlc->search);
        }
 
        /* clear the html content reference to the browser window */
diff --git a/content/handlers/html/interaction.c 
b/content/handlers/html/interaction.c
index 3f401bd..8ae5144 100644
--- a/content/handlers/html/interaction.c
+++ b/content/handlers/html/interaction.c
@@ -41,6 +41,7 @@
 #include "netsurf/layout.h"
 #include "netsurf/keypress.h"
 #include "content/hlcache.h"
+#include "content/textsearch.h"
 #include "desktop/frames.h"
 #include "desktop/scrollbar.h"
 #include "desktop/selection.h"
@@ -55,7 +56,6 @@
 #include "html/form_internal.h"
 #include "html/private.h"
 #include "html/imagemap.h"
-#include "html/search.h"
 #include "html/interaction.h"
 
 /**
@@ -1602,17 +1602,18 @@ bool html_keypress(struct content *c, uint32_t key)
  * Handle search.
  *
  * \param c content of type HTML
- * \param context front end private data
+ * \param fe_ctx front end private data
  * \param flags search flags
  * \param string search string
  */
 void
 html_search(struct content *c,
-           void *context,
+           void *fe_ctx,
            search_flags_t flags,
            const char *string)
 {
        html_content *html = (html_content *)c;
+       nserror res;
 
        assert(c != NULL);
 
@@ -1621,7 +1622,7 @@ html_search(struct content *c,
            (strcmp(string, html->search_string) == 0) &&
            (html->search != NULL)) {
                /* Continue prev. search */
-               search_step(html->search, flags, string);
+               content_textsearch_step(html->search, flags, string);
 
        } else if (string != NULL) {
                /* New search */
@@ -1631,16 +1632,16 @@ html_search(struct content *c,
                        return;
 
                if (html->search != NULL) {
-                       search_destroy_context(html->search);
+                       content_textsearch_destroy(html->search);
                        html->search = NULL;
                }
 
-               html->search = search_create_context(c, CONTENT_HTML, context);
-
-               if (html->search == NULL)
+               res = content_textsearch_create(c, fe_ctx, &html->search);
+               if (res != NSERROR_OK) {
                        return;
+               }
 
-               search_step(html->search, flags, string);
+               content_textsearch_step(html->search, flags, string);
 
        } else {
                /* Clear search */
@@ -1653,9 +1654,9 @@ html_search(struct content *c,
 
 
 /**
- * Terminate a search.
+ * Terminate a text search.
  *
- * \param  c                   content of type HTML
+ * \param c content of type HTML
  */
 void html_search_clear(struct content *c)
 {
@@ -1667,7 +1668,7 @@ void html_search_clear(struct content *c)
        html->search_string = NULL;
 
        if (html->search != NULL) {
-               search_destroy_context(html->search);
+               content_textsearch_destroy(html->search);
        }
        html->search = NULL;
 }
diff --git a/content/handlers/html/private.h b/content/handlers/html/private.h
index dff0b78..1367c62 100644
--- a/content/handlers/html/private.h
+++ b/content/handlers/html/private.h
@@ -211,7 +211,7 @@ typedef struct html_content {
        struct form_control *visible_select_menu;
 
        /** Context for free text search, or NULL if none */
-       struct search_context *search;
+       struct textsearch_context *search;
        /** Search string or NULL */
        char *search_string;
 
diff --git a/content/handlers/html/redraw.c b/content/handlers/html/redraw.c
index 936c1b3..f9fb6b4 100644
--- a/content/handlers/html/redraw.c
+++ b/content/handlers/html/redraw.c
@@ -47,6 +47,7 @@
 #include "netsurf/layout.h"
 #include "content/content.h"
 #include "content/content_protected.h"
+#include "content/textsearch.h"
 #include "css/utils.h"
 #include "desktop/selection.h"
 #include "desktop/print.h"
@@ -61,7 +62,6 @@
 #include "html/form_internal.h"
 #include "html/private.h"
 #include "html/layout.h"
-#include "html/search.h"
 
 
 bool html_redraw_debug = false;
@@ -167,7 +167,7 @@ text_redraw(const char *utf8_text,
            bool excluded,
            struct content *c,
            const struct selection *sel,
-           struct search_context *search,
+           struct textsearch_context *search,
            const struct redraw_context *ctx)
 {
        bool highlighted = false;
@@ -184,18 +184,23 @@ text_redraw(const char *utf8_text,
                unsigned end_idx;
 
                /* first try the browser window's current selection */
-               if (selection_defined(sel) && selection_highlighted(sel,
-                                       offset, offset + len,
-                                       &start_idx, &end_idx)) {
+               if (selection_defined(sel) &&
+                   selection_highlighted(sel,
+                                         offset,
+                                         offset + len,
+                                         &start_idx,
+                                         &end_idx)) {
                        highlighted = true;
                }
 
                /* what about the current search operation, if any? */
-               if (!highlighted && (search != NULL) &&
-                               search_term_highlighted(c,
-                                               offset, offset + len,
-                                               &start_idx, &end_idx,
-                                               search)) {
+               if (!highlighted &&
+                   (search != NULL) &&
+                   content_textsearch_ishighlighted(search,
+                                                    offset,
+                                                    offset + len,
+                                                    &start_idx,
+                                                    &end_idx)) {
                        highlighted = true;
                }
 
diff --git a/content/handlers/text/textplain.c 
b/content/handlers/text/textplain.c
index e9037f9..e8c3831 100644
--- a/content/handlers/text/textplain.c
+++ b/content/handlers/text/textplain.c
@@ -23,22 +23,16 @@
  * plain text content handling implementation.
  */
 
-#include <assert.h>
-#include <errno.h>
-#include <stddef.h>
-#include <string.h>
-#include <strings.h>
-#include <math.h>
-
 #include <parserutils/input/inputstream.h>
-#include <parserutils/charset/utf8.h>
 
+#include "utils/errors.h"
 #include "utils/corestrings.h"
 #include "utils/http.h"
 #include "utils/log.h"
 #include "utils/messages.h"
 #include "utils/utils.h"
 #include "utils/utf8.h"
+#include "utils/nsoption.h"
 #include "netsurf/content.h"
 #include "netsurf/keypress.h"
 #include "netsurf/browser_window.h"
@@ -47,13 +41,10 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "content/hlcache.h"
-#include "css/utils.h"
-#include "utils/nsoption.h"
-#include "desktop/search.h"
+#include "content/textsearch.h"
 #include "desktop/selection.h"
 #include "desktop/gui_internal.h"
 
-#include "html/search.h"
 #include "text/textplain.h"
 
 struct textplain_line {
@@ -61,6 +52,9 @@ struct textplain_line {
        size_t  length;
 };
 
+/**
+ * plain text content
+ */
 typedef struct textplain_content {
        struct content base;
 
@@ -77,7 +71,7 @@ typedef struct textplain_content {
        struct selection sel;   /** Selection state */
 
        /** Context for free text search, or NULL if none */
-       struct search_context *search;
+       struct textsearch_context *search;
        /** Current search string, or NULL if none */
        char *search_string;
 } textplain_content;
@@ -195,7 +189,7 @@ no_memory:
 static nserror
 textplain_create(const content_handler *handler,
                 lwc_string *imime_type,
-                const http_parameter *params,
+                const struct http_parameter *params,
                 llcache_handle *llcache,
                 const char *fallback_charset,
                 bool quirks,
@@ -759,7 +753,7 @@ static void textplain_search_clear(struct content *c)
        text->search_string = NULL;
 
        if (text->search != NULL) {
-               search_destroy_context(text->search);
+               content_textsearch_destroy(text->search);
        }
        text->search = NULL;
 }
@@ -777,14 +771,16 @@ static void textplain_search(struct content *c, void 
*gui_data,
                             search_flags_t flags, const char *string)
 {
        textplain_content *text = (textplain_content *) c;
+       nserror res;
 
        assert(c != NULL);
 
-       if (string != NULL && text->search_string != NULL &&
+       if (string != NULL &&
+           text->search_string != NULL &&
            strcmp(string, text->search_string) == 0 &&
            text->search != NULL) {
                /* Continue prev. search */
-               search_step(text->search, flags, string);
+               content_textsearch_step(text->search, flags, string);
 
        } else if (string != NULL) {
                /* New search */
@@ -794,17 +790,16 @@ static void textplain_search(struct content *c, void 
*gui_data,
                        return;
 
                if (text->search != NULL) {
-                       search_destroy_context(text->search);
+                       content_textsearch_destroy(text->search);
                        text->search = NULL;
                }
 
-               text->search = search_create_context(c, CONTENT_TEXTPLAIN,
-                                                    gui_data);
-
-               if (text->search == NULL)
+               res = content_textsearch_create(c, gui_data, &text->search);
+               if (res != NSERROR_OK) {
                        return;
+               }
 
-               search_step(text->search, flags, string);
+               content_textsearch_step(text->search, flags, string);
 
        } else {
                /* Clear search */
@@ -845,7 +840,6 @@ text_draw(const char *utf8_text,
            float scale,
            textplain_content *text,
            const struct selection *sel,
-           struct search_context *search,
            const struct redraw_context *ctx)
 {
        bool highlighted = false;
@@ -874,13 +868,12 @@ text_draw(const char *utf8_text,
 
                /* what about the current search operation, if any? */
                if (!highlighted &&
-                   (search != NULL) &&
-                   search_term_highlighted((struct content *)text,
-                                           offset,
-                                           offset + len,
-                                           &start_idx,
-                                           &end_idx,
-                                           search)) {
+                   (text->search != NULL) &&
+                   content_textsearch_ishighlighted(text->search,
+                                                    offset,
+                                                    offset + len,
+                                                    &start_idx,
+                                                    &end_idx)) {
                        highlighted = true;
                }
 
@@ -1131,7 +1124,6 @@ textplain_redraw(struct content *c,
                                       data->scale,
                                       text,
                                       &text->sel,
-                                      text->search,
                                       ctx)) {
                                return false;
                        }
@@ -1171,15 +1163,17 @@ textplain_redraw(struct content *c,
                                                highlighted = true;
                                }
 
-                               if (!highlighted && (text->search != NULL)) {
+                               if (!highlighted &&
+                                   (text->search != NULL)) {
                                        unsigned start_idx, end_idx;
-                                       if (search_term_highlighted(c,
-                                                                   tab_ofst,
-                                                                   tab_ofst + 
1,
-                                                                   &start_idx,
-                                                                   &end_idx,
-                                                                   
text->search))
+                                       if (content_textsearch_ishighlighted(
+                                                   text->search,
+                                                   tab_ofst,
+                                                   tab_ofst + 1,
+                                                   &start_idx,
+                                                   &end_idx)) {
                                                highlighted = true;
+                                       }
                                }
 
                                if (highlighted) {
@@ -1234,7 +1228,7 @@ static nserror textplain_close(struct content *c)
        textplain_content *text = (textplain_content *) c;
 
        if (text->search != NULL) {
-               search_destroy_context(text->search);
+               content_textsearch_destroy(text->search);
        }
 
        text->bw = NULL;
diff --git a/content/handlers/text/textplain.h 
b/content/handlers/text/textplain.h
index 23917fb..9c6ad92 100644
--- a/content/handlers/text/textplain.h
+++ b/content/handlers/text/textplain.h
@@ -31,7 +31,6 @@
 
 struct content;
 struct hlcache_handle;
-struct http_parameter;
 struct rect;
 
 /**
diff --git a/content/handlers/html/search.c b/content/textsearch.c
similarity index 71%
rename from content/handlers/html/search.c
rename to content/textsearch.c
index 8ccb692..c535948 100644
--- a/content/handlers/html/search.c
+++ b/content/textsearch.c
@@ -20,34 +20,27 @@
 
 /**
  * \file
- * Free text search (core)
+ * Free text search
  */
 
-#include <ctype.h>
-#include <string.h>
-#include <dom/dom.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
 
-#include "utils/config.h"
-#include "utils/log.h"
-#include "utils/messages.h"
+#include "utils/errors.h"
 #include "utils/utils.h"
 #include "content/content.h"
-#include "content/hlcache.h"
 #include "desktop/selection.h"
 #include "netsurf/search.h"
-#include "netsurf/misc.h"
+#include "netsurf/content_type.h"
 #include "desktop/gui_internal.h"
 
 #include "text/textplain.h"
 #include "html/box.h"
 #include "html/box_inspect.h"
-#include "html/html.h"
 #include "html/private.h"
-#include "html/search.h"
 
-#ifndef NOF_ELEMENTS
-#define NOF_ELEMENTS(array) (sizeof(array)/sizeof(*(array)))
-#endif
+#include "content/textsearch.h"
 
 
 struct list_entry {
@@ -63,7 +56,10 @@ struct list_entry {
        struct list_entry *next;
 };
 
-struct search_context {
+/**
+ * The context for a free text search
+ */
+struct textsearch_context {
        void *gui_p;
        struct content *c;
        struct list_entry *found;
@@ -75,75 +71,35 @@ struct search_context {
 };
 
 
-/* Exported function documented in search.h */
-struct search_context *
-search_create_context(struct content *c, content_type type, void *gui_data)
-{
-       struct search_context *context;
-       struct list_entry *search_head;
-
-       if (type != CONTENT_HTML && type != CONTENT_TEXTPLAIN) {
-               return NULL;
-       }
-
-       context = malloc(sizeof(struct search_context));
-       if (context == NULL) {
-               return NULL;
-       }
-
-       search_head = malloc(sizeof(struct list_entry));
-       if (search_head == NULL) {
-               free(context);
-               return NULL;
-       }
-
-       search_head->start_idx = 0;
-       search_head->end_idx = 0;
-       search_head->start_box = NULL;
-       search_head->end_box = NULL;
-       search_head->sel = NULL;
-       search_head->prev = NULL;
-       search_head->next = NULL;
-
-       context->found = search_head;
-       context->current = NULL;
-       context->string = NULL;
-       context->prev_case_sens = false;
-       context->newsearch = true;
-       context->c = c;
-       context->is_html = (type == CONTENT_HTML) ? true : false;
-       context->gui_p = gui_data;
-
-       return context;
-}
 
 
 /**
  * Release the memory used by the list of matches,
  * deleting selection objects too
  */
-
-static void free_matches(struct search_context *context)
+static void free_matches(struct textsearch_context *textsearch)
 {
-       struct list_entry *a;
-       struct list_entry *b;
+       struct list_entry *cur;
+       struct list_entry *nxt;
 
-       a = context->found->next;
+       cur = textsearch->found->next;
 
-       /* empty the list before clearing and deleting the
-        * selections because the the clearing updates the
-        * screen immediately, causing nested accesses to the list */
+       /*
+        * empty the list before clearing and deleting the selections
+        * because the the clearing may update the toolkit immediately,
+        * causing nested accesses to the list
+        */
 
-       context->found->prev = NULL;
-       context->found->next = NULL;
+       textsearch->found->prev = NULL;
+       textsearch->found->next = NULL;
 
-       for (; a; a = b) {
-               b = a->next;
-               if (a->sel) {
-                       selection_clear(a->sel, true);
-                       selection_destroy(a->sel);
+       for (; cur; cur = nxt) {
+               nxt = cur->next;
+               if (cur->sel) {
+                       selection_clear(cur->sel, true);
+                       selection_destroy(cur->sel);
                }
-               free(a);
+               free(cur);
        }
 }
 
@@ -159,10 +115,13 @@ static void free_matches(struct search_context *context)
  * \param  m_len      accepts length of match in bytes
  * \return pointer to first match, NULL if none
  */
-
-static const char *find_pattern(const char *string, int s_len,
-               const char *pattern, int p_len, bool case_sens,
-               unsigned int *m_len)
+static const char *
+find_pattern(const char *string,
+            int s_len,
+            const char *pattern,
+            int p_len,
+            bool case_sens,
+            unsigned int *m_len)
 {
        struct { const char *ss, *s, *p; bool first; } context[16];
        const char *ep = pattern + p_len;
@@ -275,7 +234,9 @@ static const char *find_pattern(const char *string, int 
s_len,
  * \return Pointer to added entry, NULL iff failed.
  */
 static struct list_entry *
-add_entry(unsigned start_idx, unsigned end_idx,        struct search_context 
*context)
+add_entry(unsigned start_idx,
+         unsigned end_idx,
+         struct textsearch_context *context)
 {
        struct list_entry *entry;
 
@@ -289,7 +250,7 @@ add_entry(unsigned start_idx, unsigned end_idx,     struct 
search_context *context)
        entry->end_idx = end_idx;
        entry->sel = NULL;
 
-       entry->next = 0;
+       entry->next = NULL;
        entry->prev = context->found->prev;
 
        if (context->found->prev == NULL) {
@@ -305,7 +266,7 @@ add_entry(unsigned start_idx, unsigned end_idx,     struct 
search_context *context)
 
 
 /**
- * Finds all occurrences of a given string in the html box tree
+ * Finds all occurrences of a given string in an html box
  *
  * \param pattern   the string pattern to search for
  * \param p_len     pattern length
@@ -314,9 +275,12 @@ add_entry(unsigned start_idx, unsigned end_idx,    struct 
search_context *context)
  * \param context   The search context to add the entry to.
  * \return true on success, false on memory allocation failure
  */
-static bool find_occurrences_html(const char *pattern, int p_len,
-               struct box *cur, bool case_sens,
-               struct search_context *context)
+static bool
+find_occurrences_html_box(const char *pattern,
+                         int p_len,
+                         struct box *cur,
+                         bool case_sens,
+                         struct textsearch_context *context)
 {
        struct box *a;
 
@@ -330,9 +294,14 @@ static bool find_occurrences_html(const char *pattern, int 
p_len,
                        unsigned match_length;
                        unsigned match_offset;
                        const char *new_text;
-                       const char *pos = find_pattern(text, length,
-                                       pattern, p_len, case_sens,
-                                       &match_length);
+                       const char *pos;
+
+                       pos = find_pattern(text,
+                                          length,
+                                          pattern,
+                                          p_len,
+                                          case_sens,
+                                          &match_length);
                        if (!pos)
                                break;
 
@@ -340,9 +309,8 @@ static bool find_occurrences_html(const char *pattern, int 
p_len,
                        match_offset = pos - cur->text;
 
                        entry = add_entry(cur->byte_offset + match_offset,
-                                               cur->byte_offset +
-                                                       match_offset +
-                                                       match_length, context);
+                                         cur->byte_offset + match_offset + 
match_length,
+                                         context);
                        if (!entry)
                                return false;
 
@@ -357,14 +325,46 @@ static bool find_occurrences_html(const char *pattern, 
int p_len,
 
        /* and recurse */
        for (a = cur->children; a; a = a->next) {
-               if (!find_occurrences_html(pattern, p_len, a, case_sens,
-                               context))
+               if (!find_occurrences_html_box(pattern,
+                                              p_len,
+                                              a,
+                                              case_sens,
+                                              context))
                        return false;
        }
 
        return true;
 }
 
+/**
+ * Finds all occurrences of a given string in the html box tree
+ *
+ * \param pattern   the string pattern to search for
+ * \param p_len     pattern length
+ * \param c The content to search
+ * \param csens whether to perform a case sensitive search
+ * \param context   The search context to add the entry to.
+ * \return true on success, false on memory allocation failure
+ */
+static bool
+find_occurrences_html(const char *pattern,
+                     int p_len,
+                     struct content *c,
+                     bool csens,
+                     struct textsearch_context *context)
+{
+       html_content *html = (html_content *)c;
+
+       if (html->layout == NULL) {
+               return false;
+       }
+
+       return find_occurrences_html_box(pattern,
+                                        p_len,
+                                        html->layout,
+                                        csens,
+                                        context);
+}
 
 /**
  * Finds all occurrences of a given string in a textplain content
@@ -376,34 +376,41 @@ static bool find_occurrences_html(const char *pattern, 
int p_len,
  * \param context   The search context to add the entry to.
  * \return true on success, false on memory allocation failure
  */
-
-static bool find_occurrences_text(const char *pattern, int p_len,
-               struct content *c, bool case_sens,
-               struct search_context *context)
+static bool
+find_occurrences_text(const char *pattern,
+                     int p_len,
+                     struct content *c,
+                     bool case_sens,
+                     struct textsearch_context *context)
 {
        int nlines = textplain_line_count(c);
        int line;
 
        for(line = 0; line < nlines; line++) {
                size_t offset, length;
-               const char *text = textplain_get_line(c, line,
-                               &offset, &length);
+               const char *text;
+
+               text = textplain_get_line(c, line, &offset, &length);
                if (text) {
                        while (length > 0) {
                                struct list_entry *entry;
                                unsigned match_length;
                                size_t start_idx;
                                const char *new_text;
-                               const char *pos = find_pattern(text, length,
-                                               pattern, p_len, case_sens,
-                                               &match_length);
+                               const char *pos;
+
+                               pos = find_pattern(text, length,
+                                                   pattern, p_len,
+                                                   case_sens,
+                                                   &match_length);
                                if (!pos)
                                        break;
 
                                /* found string in line => add to list */
                                start_idx = offset + (pos - text);
-                               entry = add_entry(start_idx, start_idx +
-                                               match_length, context);
+                               entry = add_entry(start_idx,
+                                                 start_idx + match_length,
+                                                 context);
                                if (!entry)
                                        return false;
 
@@ -423,7 +430,7 @@ static bool find_occurrences_text(const char *pattern, int 
p_len,
  * Specifies whether all matches or just the current match should
  * be highlighted in the search text.
  */
-static void search_show_all(bool all, struct search_context *context)
+static void search_show_all(bool all, struct textsearch_context *context)
 {
        struct list_entry *a;
 
@@ -473,11 +480,10 @@ static void search_show_all(bool all, struct 
search_context *context)
 static void
 search_text(const char *string,
            int string_len,
-           struct search_context *context,
+           struct textsearch_context *context,
            search_flags_t flags)
 {
        struct rect bounds;
-       struct box *box = NULL;
        union content_msg_data msg_data;
        bool case_sensitive, forwards, showall;
 
@@ -489,16 +495,6 @@ search_text(const char *string,
        if (context->c == NULL)
                return;
 
-       if (context->is_html == true) {
-               html_content *html = (html_content *)context->c;
-
-               box = html->layout;
-
-               if (!box)
-                       return;
-       }
-
-
        /* check if we need to start a new search or continue an old one */
        if ((context->newsearch) ||
            (context->prev_case_sens != case_sensitive)) {
@@ -520,18 +516,18 @@ search_text(const char *string,
 
                if (context->is_html == true) {
                        res = find_occurrences_html(string, string_len,
-                                       box, case_sensitive, context);
+                                       context->c, case_sensitive, context);
                } else {
                        res = find_occurrences_text(string, string_len,
                                        context->c, case_sensitive, context);
                }
 
+               guit->search->hourglass(false, context->gui_p);
+
                if (!res) {
                        free_matches(context);
-                       guit->search->hourglass(false, context->gui_p);
                        return;
                }
-               guit->search->hourglass(false, context->gui_p);
 
                context->prev_case_sens = case_sensitive;
 
@@ -587,76 +583,136 @@ search_text(const char *string,
 }
 
 
-/* Exported function documented in search.h */
-void
-search_step(struct search_context *context,
-           search_flags_t flags,
-           const char *string)
+/* Exported function documented in context/textsearch.h */
+nserror
+content_textsearch_step(struct textsearch_context *textsearch,
+                       search_flags_t flags,
+                       const char *string)
 {
        int string_len;
        int i = 0;
 
-       assert(context != NULL);
+       assert(textsearch != NULL);
 
-       guit->search->add_recent(string, context->gui_p);
+       guit->search->add_recent(string, textsearch->gui_p);
 
        string_len = strlen(string);
-       for (i = 0; i < string_len; i++)
+       for (i = 0; i < string_len; i++) {
                if (string[i] != '#' && string[i] != '*')
                        break;
-       if (i >= string_len) {
+       }
+
+       if (i < string_len) {
+               search_text(string, string_len, textsearch, flags);
+       } else {
                union content_msg_data msg_data;
-               free_matches(context);
+               free_matches(textsearch);
 
-               guit->search->status(true, context->gui_p);
-               guit->search->back_state(false, context->gui_p);
-               guit->search->forward_state(false, context->gui_p);
+               guit->search->status(true, textsearch->gui_p);
+               guit->search->back_state(false, textsearch->gui_p);
+               guit->search->forward_state(false, textsearch->gui_p);
 
                msg_data.scroll.area = false;
                msg_data.scroll.x0 = 0;
                msg_data.scroll.y0 = 0;
-               content_broadcast(context->c, CONTENT_MSG_SCROLL, &msg_data);
-               return;
+               content_broadcast(textsearch->c, CONTENT_MSG_SCROLL, &msg_data);
        }
-       search_text(string, string_len, context, flags);
+
+       return NSERROR_OK;
 }
 
 
-/* Exported function documented in search.h */
-bool search_term_highlighted(struct content *c,
-               unsigned start_offset, unsigned end_offset,
-               unsigned *start_idx, unsigned *end_idx,
-               struct search_context *context)
+/* Exported function documented in content/textsearch.h */
+bool
+content_textsearch_ishighlighted(struct textsearch_context *textsearch,
+                                unsigned start_offset,
+                                unsigned end_offset,
+                                unsigned *start_idx,
+                                unsigned *end_idx)
 {
-       if (c == context->c) {
-               struct list_entry *a;
-               for (a = context->found->next; a; a = a->next)
-                       if (a->sel && selection_defined(a->sel) &&
-                                       selection_highlighted(a->sel,
-                                               start_offset, end_offset,
-                                               start_idx, end_idx))
-                               return true;
+       struct list_entry *cur;
+
+       for (cur = textsearch->found->next; cur != NULL; cur = cur->next) {
+               if (cur->sel &&
+                   selection_defined(cur->sel) &&
+                   selection_highlighted(cur->sel,
+                                         start_offset,
+                                         end_offset,
+                                         start_idx,
+                                         end_idx)) {
+                       return true;
+               }
        }
 
        return false;
 }
 
 
+/* Exported function documented in content/textsearch.h */
+nserror
+content_textsearch_create(struct content *c,
+                         void *gui_data,
+                         struct textsearch_context **textsearch_out)
+{
+       struct textsearch_context *context;
+       struct list_entry *search_head;
+       content_type type;
+
+       type = c->handler->type();
+
+       if (type != CONTENT_HTML && type != CONTENT_TEXTPLAIN) {
+               return NSERROR_NOT_IMPLEMENTED;
+       }
+
+       context = malloc(sizeof(struct textsearch_context));
+       if (context == NULL) {
+               return NSERROR_NOMEM;
+       }
+
+       search_head = malloc(sizeof(struct list_entry));
+       if (search_head == NULL) {
+               free(context);
+               return NSERROR_NOMEM;
+       }
+
+       search_head->start_idx = 0;
+       search_head->end_idx = 0;
+       search_head->start_box = NULL;
+       search_head->end_box = NULL;
+       search_head->sel = NULL;
+       search_head->prev = NULL;
+       search_head->next = NULL;
+
+       context->found = search_head;
+       context->current = NULL;
+       context->string = NULL;
+       context->prev_case_sens = false;
+       context->newsearch = true;
+       context->c = c;
+       context->is_html = (type == CONTENT_HTML) ? true : false;
+       context->gui_p = gui_data;
+
+       *textsearch_out = context;
+
+       return NSERROR_OK;
+}
 
 
 /* Exported function documented in search.h */
-void search_destroy_context(struct search_context *context)
+nserror content_textsearch_destroy(struct textsearch_context *textsearch)
 {
-       assert(context != NULL);
+       assert(textsearch != NULL);
 
-       if (context->string != NULL) {
-               guit->search->add_recent(context->string, context->gui_p);
-               free(context->string);
+       if (textsearch->string != NULL) {
+               guit->search->add_recent(textsearch->string, textsearch->gui_p);
+               free(textsearch->string);
        }
 
-       guit->search->forward_state(true, context->gui_p);
-       guit->search->back_state(true, context->gui_p);
+       guit->search->forward_state(true, textsearch->gui_p);
+       guit->search->back_state(true, textsearch->gui_p);
+
+       free_matches(textsearch);
+       free(textsearch);
 
-       free_matches(context);
-       free(context);
+       return NSERROR_OK;
 }
diff --git a/content/handlers/html/search.h b/content/textsearch.h
similarity index 62%
rename from content/handlers/html/search.h
rename to content/textsearch.h
index dfb1afc..f94bcdb 100644
--- a/content/handlers/html/search.h
+++ b/content/textsearch.h
@@ -21,32 +21,26 @@
  * Interface to HTML searching.
  */
 
-#ifndef NETSURF_HTML_SEARCH_H
-#define NETSURF_HTML_SEARCH_H
+#ifndef NETSURF_CONTENT_SEARCH_H
+#define NETSURF_CONTENT_SEARCH_H
 
 #include <ctype.h>
 #include <string.h>
 
 #include "desktop/search.h"
 
-struct search_context;
+struct textsearch_context;
+struct content;
 
 /**
  * create a search_context
  *
- * \param c       The content the search_context is connected to
- * \param type    The content type of c
+ * \param c The content the search_context is connected to
  * \param context A context pointer passed to the provider routines.
- * \return A new search context or NULL on error.
+ * \param search_out A pointer to recive the new text search context
+ * \return NSERROR_OK on success and \a search_out updated else error code
  */
-struct search_context *search_create_context(struct content *c,
-                                     content_type type, void *context);
-
-/**
- * Ends the search process, invalidating all state
- * freeing the list of found boxes
- */
-void search_destroy_context(struct search_context *context);
+nserror content_textsearch_create(struct content *c, void *context, struct 
textsearch_context **textsearch_out);
 
 /**
  * Begins/continues the search process
@@ -57,25 +51,30 @@ void search_destroy_context(struct search_context *context);
  * \param flags   The flags forward/back etc
  * \param string  The string to match
  */
-void search_step(struct search_context *context, search_flags_t flags,
-               const char * string);
+nserror content_textsearch_step(struct textsearch_context *textsearch, 
search_flags_t flags, const char *string);
 
+/**
+ * Ends the search process, invalidating all state freeing the list of
+ * found boxes.
+ */
+nserror content_textsearch_destroy(struct textsearch_context *textsearch);
 
 /**
  * Determines whether any portion of the given text box should be
  * selected because it matches the current search string.
  *
- * \param c            The content to hilight within.
+ * \param textsearch The search context to hilight entries from.
+ * \param c The content to highlight within.
  * \param start_offset byte offset within text of string to be checked
  * \param end_offset   byte offset within text
  * \param start_idx    byte offset within string of highlight start
  * \param end_idx      byte offset of highlight end
- * \param context      The search context to hilight entries from.
  * \return true iff part of the box should be highlighted
  */
-bool search_term_highlighted(struct content *c,
-               unsigned start_offset, unsigned end_offset,
-               unsigned *start_idx, unsigned *end_idx,
-               struct search_context *context);
+bool content_textsearch_ishighlighted(struct textsearch_context *textsearch,
+                                     unsigned start_offset,
+                                     unsigned end_offset,
+                                     unsigned *start_idx,
+                                     unsigned *end_idx);
 
 #endif


-- 
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to