Gitweb links:
...log
http://git.netsurf-browser.org/netsurf.git/shortlog/3a7fc30a5f1c0945c021abf185274e88f72e7080
...commit
http://git.netsurf-browser.org/netsurf.git/commit/3a7fc30a5f1c0945c021abf185274e88f72e7080
...tree
http://git.netsurf-browser.org/netsurf.git/tree/3a7fc30a5f1c0945c021abf185274e88f72e7080
The branch, master has been updated
via 3a7fc30a5f1c0945c021abf185274e88f72e7080 (commit)
via 95e0a24fac2abc4cddaa91bf44304ebc3d776b17 (commit)
from f4e50b45c834b644caa6a82bd044faa82f6f4860 (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=3a7fc30a5f1c0945c021abf185274e88f72e7080
commit 3a7fc30a5f1c0945c021abf185274e88f72e7080
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
implement content opacity check through the function table
diff --git a/content/content.c b/content/content.c
index bc3f484..f72f3d4 100644
--- a/content/content.c
+++ b/content/content.c
@@ -33,7 +33,6 @@
#include "netsurf/bitmap.h"
#include "netsurf/content.h"
#include "desktop/knockout.h"
-#include "desktop/gui_internal.h"
#include "content/content_protected.h"
#include "content/textsearch.h"
@@ -1294,21 +1293,13 @@ bool content_get_opaque(hlcache_handle *h)
/* exported interface documented in content/content_protected.h */
bool content__get_opaque(struct content *c)
{
- bool opaque = false;
-
if ((c != NULL) &&
(c->handler != NULL) &&
- (c->handler->type != NULL) &&
- (c->handler->type() == CONTENT_IMAGE) &&
- (c->handler->get_internal != NULL) ) {
- struct bitmap *bitmap = NULL;
- bitmap = c->handler->get_internal(c, NULL);
- if (bitmap != NULL) {
- opaque = guit->bitmap->get_opaque(bitmap);
- }
+ (c->handler->is_opaque != NULL)) {
+ return c->handler->is_opaque(c);
}
- return opaque;
+ return false;
}
diff --git a/content/content_protected.h b/content/content_protected.h
index 667f5ba..881a432 100644
--- a/content/content_protected.h
+++ b/content/content_protected.h
@@ -119,7 +119,16 @@ struct content_handler {
/**
* handler dependant content sensitive internal data interface.
*/
- void * (*get_internal)(const struct content *c, void *context);
+ void *(*get_internal)(const struct content *c, void *context);
+
+ /**
+ * are the content contents opaque.
+ *
+ * Determine if this content would obscure (not mix with) any background
+ *
+ * \param c The content to check
+ */
+ bool (*is_opaque)(struct content *c);
/**
* There must be one content per user for this type.
diff --git a/content/handlers/image/bmp.c b/content/handlers/image/bmp.c
index a1a6ce6..a723022 100644
--- a/content/handlers/image/bmp.c
+++ b/content/handlers/image/bmp.c
@@ -264,6 +264,16 @@ static content_type nsbmp_content_type(void)
return CONTENT_IMAGE;
}
+static bool nsbmp_content_is_opaque(struct content *c)
+{
+ nsbmp_content *bmp = (nsbmp_content *)c;
+
+ if (bmp->bitmap != NULL) {
+ return guit->bitmap->get_opaque(bmp->bitmap);
+ }
+
+ return false;
+}
static const content_handler nsbmp_content_handler = {
.create = nsbmp_create,
@@ -273,6 +283,7 @@ static const content_handler nsbmp_content_handler = {
.clone = nsbmp_clone,
.get_internal = nsbmp_get_internal,
.type = nsbmp_content_type,
+ .is_opaque = nsbmp_content_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/gif.c b/content/handlers/image/gif.c
index 6ef4fa7..e2a0ca5 100644
--- a/content/handlers/image/gif.c
+++ b/content/handlers/image/gif.c
@@ -416,6 +416,19 @@ static content_type nsgif_content_type(void)
return CONTENT_IMAGE;
}
+static bool nsgif_content_is_opaque(struct content *c)
+{
+ nsgif_content *gif = (nsgif_content *) c;
+
+ if (gif->current_frame != gif->gif->decoded_frame) {
+ if (nsgif_get_frame(gif) != GIF_OK) {
+ return false;
+ }
+ }
+
+ return guit->bitmap->get_opaque(gif->gif->frame_image);
+}
+
static const content_handler nsgif_content_handler = {
.create = nsgif_create,
.data_complete = nsgif_convert,
@@ -426,6 +439,7 @@ static const content_handler nsgif_content_handler = {
.remove_user = nsgif_remove_user,
.get_internal = nsgif_get_internal,
.type = nsgif_content_type,
+ .is_opaque = nsgif_content_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/ico.c b/content/handlers/image/ico.c
index 3121278..2d839b1 100644
--- a/content/handlers/image/ico.c
+++ b/content/handlers/image/ico.c
@@ -84,7 +84,7 @@ static nserror nsico_create_ico_data(nsico_content *c)
}
-static nserror nsico_create(const content_handler *handler,
+static nserror nsico_create(const content_handler *handler,
lwc_string *imime_type, const struct http_parameter *params,
llcache_handle *llcache, const char *fallback_charset,
bool quirks, struct content **c)
@@ -251,7 +251,7 @@ static void *nsico_get_internal(const struct content *c,
void *context)
nsico_content *ico = (nsico_content *) c;
/* TODO: Pick best size for purpose.
* Currently assumes it's for a URL bar. */
- struct bmp_image *bmp;
+ struct bmp_image *bmp;
bmp = ico_find(ico->ico, 16, 16);
if (bmp == NULL) {
@@ -276,6 +276,33 @@ static content_type nsico_content_type(void)
return CONTENT_IMAGE;
}
+static bool nsico_is_opaque(struct content *c)
+{
+ nsico_content *ico = (nsico_content *) c;
+ struct bmp_image *bmp;
+
+ /**
+ * \todo Pick best size for purpose. Currently assumes
+ * it's for a URL bar.
+ */
+ bmp = ico_find(ico->ico, 16, 16);
+ if (bmp == NULL) {
+ /* return error */
+ NSLOG(netsurf, INFO, "Failed to select icon");
+ return false;
+ }
+
+ if (bmp->decoded == false) {
+ if (bmp_decode(bmp) != BMP_OK) {
+ return false;
+ }
+
+ guit->bitmap->modified(bmp->bitmap);
+ }
+
+ return guit->bitmap->get_opaque(bmp->bitmap);
+}
+
static const content_handler nsico_content_handler = {
.create = nsico_create,
.data_complete = nsico_convert,
@@ -284,6 +311,7 @@ static const content_handler nsico_content_handler = {
.clone = nsico_clone,
.get_internal = nsico_get_internal,
.type = nsico_content_type,
+ .is_opaque = nsico_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/image_cache.c
b/content/handlers/image/image_cache.c
index a1de01d..bc0b914 100644
--- a/content/handlers/image/image_cache.c
+++ b/content/handlers/image/image_cache.c
@@ -859,6 +859,17 @@ void *image_cache_get_internal(const struct content *c,
void *context)
}
/* exported interface documented in image_cache.h */
+bool image_cache_is_opaque(struct content *c)
+{
+ struct bitmap *bmp;
+ bmp = image_cache_get_bitmap(c);
+ if (bmp != NULL) {
+ return guit->bitmap->get_opaque(bmp);
+ }
+ return false;
+}
+
+/* exported interface documented in image_cache.h */
content_type image_cache_content_type(void)
{
return CONTENT_IMAGE;
diff --git a/content/handlers/image/image_cache.h
b/content/handlers/image/image_cache.h
index d57a3a9..955306e 100644
--- a/content/handlers/image/image_cache.h
+++ b/content/handlers/image/image_cache.h
@@ -170,7 +170,8 @@ int image_cache_snsummaryf(char *string, size_t size, const
char *fmt);
/********* Image content handler generic cache callbacks ************/
-/** Generic content redraw callback
+/**
+ * Generic content redraw callback
*
* May be used by image content handlers as their redraw
* callback. Performs all neccissary cache lookups and conversions and
@@ -185,6 +186,8 @@ void image_cache_destroy(struct content *c);
void *image_cache_get_internal(const struct content *c, void *context);
+bool image_cache_is_opaque(struct content *c);
+
content_type image_cache_content_type(void);
#endif
diff --git a/content/handlers/image/jpeg.c b/content/handlers/image/jpeg.c
index 09e68fd..549c2b6 100644
--- a/content/handlers/image/jpeg.c
+++ b/content/handlers/image/jpeg.c
@@ -414,6 +414,7 @@ static const content_handler nsjpeg_content_handler = {
.clone = nsjpeg_clone,
.get_internal = image_cache_get_internal,
.type = image_cache_content_type,
+ .is_opaque = image_cache_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/nssprite.c
b/content/handlers/image/nssprite.c
index f0114ee..a4ce6b5 100644
--- a/content/handlers/image/nssprite.c
+++ b/content/handlers/image/nssprite.c
@@ -258,6 +258,17 @@ static content_type nssprite_content_type(void)
}
+static bool nssprite_content_is_opaque(struct content *c)
+{
+ nssprite_content *nssprite = (nssprite_content *) c;
+
+ if (nssprite->bitmap != NULL) {
+ return guit->bitmap->get_opaque(nssprite->bitmap);
+ }
+
+ return false;
+}
+
static const content_handler nssprite_content_handler = {
.create = nssprite_create,
.data_complete = nssprite_convert,
@@ -266,6 +277,7 @@ static const content_handler nssprite_content_handler = {
.clone = nssprite_clone,
.get_internal = nssprite_get_internal,
.type = nssprite_content_type,
+ .is_opaque = nssprite_content_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/png.c b/content/handlers/image/png.c
index 1fa707d..4926d9a 100644
--- a/content/handlers/image/png.c
+++ b/content/handlers/image/png.c
@@ -602,6 +602,7 @@ static const content_handler nspng_content_handler = {
.redraw = image_cache_redraw,
.get_internal = image_cache_get_internal,
.type = image_cache_content_type,
+ .is_opaque = image_cache_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/rsvg.c b/content/handlers/image/rsvg.c
index 5cf900d..0051df3 100644
--- a/content/handlers/image/rsvg.c
+++ b/content/handlers/image/rsvg.c
@@ -316,6 +316,19 @@ static content_type rsvg_content_type(void)
return CONTENT_IMAGE;
}
+
+static bool rsvg_content_is_opaque(struct content *c)
+{
+ rsvg_content *d = (rsvg_content *) c;
+
+ if (d->bitmap != NULL) {
+ return guit->bitmap->get_opaque(d->bitmap);
+ }
+
+ return false;
+}
+
+
static const content_handler rsvg_content_handler = {
.create = rsvg_create,
.process_data = rsvg_process_data,
@@ -325,6 +338,7 @@ static const content_handler rsvg_content_handler = {
.clone = rsvg_clone,
.get_internal = rsvg_get_internal,
.type = rsvg_content_type,
+ .is_opaque = rsvg_content_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/webp.c b/content/handlers/image/webp.c
index 8450fb1..721e924 100644
--- a/content/handlers/image/webp.c
+++ b/content/handlers/image/webp.c
@@ -225,6 +225,7 @@ static const content_handler webp_content_handler = {
.clone = webp_clone,
.get_internal = image_cache_get_internal,
.type = image_cache_content_type,
+ .is_opaque = image_cache_is_opaque,
.no_share = false,
};
diff --git a/frontends/amiga/icon.c b/frontends/amiga/icon.c
index 353ba91..001874c 100644
--- a/frontends/amiga/icon.c
+++ b/frontends/amiga/icon.c
@@ -48,6 +48,7 @@
#include "content/content.h"
#include "content/content_protected.h"
#include "content/content_factory.h"
+#include "desktop/gui_internal.h"
#include "amiga/os3support.h"
#include "amiga/bitmap.h"
@@ -87,6 +88,17 @@ static void *amiga_icon_get_internal(const struct content
*c, void *context)
return icon_c->bitmap;
}
+static bool amiga_icon_is_opaque(struct content *c)
+{
+ amiga_icon_content *icon_c = (amiga_icon_content *)c;
+
+ if (icon_c->bitmap != NULL) {
+ return guit->bitmap->get_opaque(icon_c->bitmap);
+ }
+
+ return false;
+}
+
static const content_handler amiga_icon_content_handler = {
.create = amiga_icon_create,
.data_complete = amiga_icon_convert,
@@ -95,6 +107,7 @@ static const content_handler amiga_icon_content_handler = {
.clone = amiga_icon_clone,
.get_internal = amiga_icon_get_internal,
.type = amiga_icon_content_type,
+ .is_opaque = amiga_icon_is_opaque,
.no_share = false,
};
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=95e0a24fac2abc4cddaa91bf44304ebc3d776b17
commit 95e0a24fac2abc4cddaa91bf44304ebc3d776b17
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>
use content messages to inform frontend of text search changes
diff --git a/content/content.h b/content/content.h
index f68af53..edf9ed2 100644
--- a/content/content.h
+++ b/content/content.h
@@ -242,6 +242,50 @@ union content_msg_data {
struct {
struct form_control *gadget;
} gadget_click;
+
+ /**
+ * CONTENT_MSG_TEXTSEARCH - Free text search action
+ */
+ struct {
+ /**
+ * The type of text search operation
+ */
+ enum {
+ /**
+ * Free text search find operation has started or finished
+ */
+ CONTENT_TEXTSEARCH_FIND,
+ /**
+ * Free text search match state has changed
+ */
+ CONTENT_TEXTSEARCH_MATCH,
+ /**
+ * Free text search back available state changed
+ */
+ CONTENT_TEXTSEARCH_BACK,
+ /**
+ * Free text search forward available state changed
+ */
+ CONTENT_TEXTSEARCH_FORWARD,
+ /**
+ * add a search query string to the recent searches
+ */
+ CONTENT_TEXTSEARCH_RECENT
+ } type;
+ /**
+ * context passed to browser_window_search()
+ */
+ void *ctx;
+ /**
+ * state for operation
+ */
+ bool state;
+ /**
+ * search string
+ */
+ const char *string;
+ } textsearch;
+
};
diff --git a/content/textsearch.c b/content/textsearch.c
index 145c8c4..8997394 100644
--- a/content/textsearch.c
+++ b/content/textsearch.c
@@ -1,7 +1,6 @@
/*
* Copyright 2004 John M Bell <[email protected]>
- * Copyright 2005 Adrian Lees <[email protected]>
- * Copyright 2009 Mark Benjamin <[email protected]>
+ * Copyright 2020 Vincent Sanders <[email protected]>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -28,37 +27,81 @@
#include "utils/errors.h"
#include "utils/utils.h"
#include "netsurf/types.h"
-#include "netsurf/search.h"
#include "desktop/selection.h"
-#include "desktop/gui_internal.h"
#include "content/content.h"
#include "content/content_protected.h"
#include "content/hlcache.h"
#include "content/textsearch.h"
-
+/**
+ * search match
+ */
struct list_entry {
- unsigned start_idx; /* start position of match */
- unsigned end_idx; /* end of match */
+ /**
+ * previous match
+ */
+ struct list_entry *prev;
+
+ /**
+ * next match
+ */
+ struct list_entry *next;
+
+ /**
+ * start position of match
+ */
+ unsigned start_idx;
+
+ /**
+ * end of match
+ */
+ unsigned end_idx;
+
+ /**
+ * content opaque start pointer
+ */
+ struct box *start_box;
- struct box *start_box; /* used only for html contents */
+ /**
+ * content opaque end pointer
+ */
struct box *end_box;
+ /**
+ * content specific selection object
+ */
struct selection *sel;
-
- struct list_entry *prev;
- struct list_entry *next;
};
/**
* The context for a free text search
*/
struct textsearch_context {
- void *gui_p;
+
+ /**
+ * content search was performed upon
+ */
struct content *c;
+
+ /**
+ * opaque pointer passed to constructor.
+ */
+ void *gui_p;
+
+ /**
+ * List of matches
+ */
struct list_entry *found;
+
+ /**
+ * current selected match
+ */
struct list_entry *current; /* first for select all */
+
+ /**
+ * query string search results are for
+ */
char *string;
bool prev_case_sens;
bool newsearch;
@@ -66,6 +109,24 @@ struct textsearch_context {
/**
+ * broadcast textsearch message
+ */
+static inline void
+textsearch_broadcast(struct textsearch_context *textsearch,
+ int type,
+ bool state,
+ const char *string)
+{
+ union content_msg_data msg_data;
+ msg_data.textsearch.type = type;
+ msg_data.textsearch.ctx = textsearch->gui_p;
+ msg_data.textsearch.state = state;
+ msg_data.textsearch.string = string;
+ content_broadcast(textsearch->c, CONTENT_MSG_TEXTSEARCH, &msg_data);
+}
+
+
+/**
* Release the memory used by the list of matches,
* deleting selection objects too
*/
@@ -96,154 +157,6 @@ static void free_matches(struct textsearch_context
*textsearch)
}
-/* Exported function documented in content/textsearch.h */
-const char *
-content_textsearch_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;
-}
-
-
-/* Exported function documented in content/textsearch.h */
-nserror
-content_textsearch_add_match(struct textsearch_context *context,
- unsigned start_idx,
- unsigned end_idx,
- struct box *start_box,
- struct box *end_box)
-{
- struct list_entry *entry;
-
- /* found string in box => add to list */
- entry = calloc(1, sizeof(*entry));
- if (entry == NULL) {
- return NSERROR_NOMEM;
- }
-
- entry->start_idx = start_idx;
- entry->end_idx = end_idx;
- entry->start_box = start_box;
- entry->end_box = end_box;
- 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 NSERROR_OK;
-}
-
-
/**
* Specifies whether all matches or just the current match should
* be highlighted in the search text.
@@ -278,17 +191,17 @@ static void search_show_all(bool all, struct
textsearch_context *context)
/**
- * Search for a string in the box tree
+ * Search for a string in a content.
*
+ * \param context The search context.
* \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 nserror
-search_text(const char *string,
+search_text(struct textsearch_context *context,
+ const char *string,
int string_len,
- struct textsearch_context *context,
search_flags_t flags)
{
struct rect bounds;
@@ -322,7 +235,9 @@ search_text(const char *string,
context->string[string_len] = '\0';
}
- guit->search->hourglass(true, context->gui_p);
+ /* indicate find operation starting */
+ textsearch_broadcast(context, CONTENT_TEXTSEARCH_FIND, true,
NULL);
+
/* call content find handler */
res = context->c->handler->textsearch_find(context->c,
@@ -331,7 +246,8 @@ search_text(const char *string,
string_len,
case_sensitive);
- guit->search->hourglass(false, context->gui_p);
+ /* indicate find operation finished */
+ textsearch_broadcast(context, CONTENT_TEXTSEARCH_FIND, false,
NULL);
if (res != NSERROR_OK) {
free_matches(context);
@@ -355,29 +271,41 @@ search_text(const char *string,
}
}
- guit->search->status((context->current != NULL), context->gui_p);
+ /* update match state */
+ textsearch_broadcast(context,
+ CONTENT_TEXTSEARCH_MATCH,
+ (context->current != NULL),
+ NULL);
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);
+ /* update back state */
+ textsearch_broadcast(context,
+ CONTENT_TEXTSEARCH_BACK,
+ ((context->current != NULL) &&
+ (context->current->prev != NULL)),
+ NULL);
+
+ /* update forward state */
+ textsearch_broadcast(context,
+ CONTENT_TEXTSEARCH_FORWARD,
+ ((context->current != NULL) &&
+ (context->current->next != NULL)),
+ NULL);
+
if (context->current == NULL) {
+ /* no current match */
return res;
}
/* call content match bounds handler */
res = context->c->handler->textsearch_bounds(context->c,
-
context->current->start_idx,
- context->current->end_idx,
-
-
context->current->start_box,
- context->current->end_box,
- &bounds);
+ context->current->start_idx,
+ context->current->end_idx,
+ context->current->start_box,
+ context->current->end_box,
+ &bounds);
if (res == NSERROR_OK) {
msg_data.scroll.area = true;
msg_data.scroll.x0 = bounds.x0;
@@ -411,7 +339,11 @@ content_textsearch_step(struct textsearch_context
*textsearch,
assert(textsearch != NULL);
- guit->search->add_recent(string, textsearch->gui_p);
+ /* broadcast recent query string */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_RECENT,
+ false,
+ string);
string_len = strlen(string);
for (i = 0; i < string_len; i++) {
@@ -420,52 +352,61 @@ content_textsearch_step(struct textsearch_context
*textsearch,
}
if (i < string_len) {
- res = search_text(string, string_len, textsearch, flags);
+ res = search_text(textsearch, string, string_len, 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);
+ free_matches(textsearch);
+ /* update match state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_MATCH,
+ true,
+ NULL);
+
+ /* update back state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_BACK,
+ false,
+ NULL);
+
+ /* update forward state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_FORWARD,
+ false,
+ NULL);
+
+ /* clear scroll */
msg_data.scroll.area = false;
msg_data.scroll.x0 = 0;
msg_data.scroll.y0 = 0;
- content_broadcast(textsearch->c, CONTENT_MSG_SCROLL, &msg_data);
+ content_broadcast(textsearch->c,
+ CONTENT_MSG_SCROLL,
+ &msg_data);
}
return res;
}
-/* 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)
+/**
+ * Terminate a search.
+ *
+ * \param c content to clear
+ */
+static nserror content_textsearch__clear(struct content *c)
{
- struct list_entry *cur;
+ free(c->textsearch.string);
+ c->textsearch.string = NULL;
- 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;
- }
+ if (c->textsearch.context != NULL) {
+ content_textsearch_destroy(c->textsearch.context);
+ c->textsearch.context = NULL;
}
-
- return false;
+ return NSERROR_OK;
}
-/* Exported function documented in content/textsearch.h */
/**
* create a search_context
*
@@ -528,44 +469,215 @@ content_textsearch_create(struct content *c,
}
-/* Exported function documented in search.h */
-nserror content_textsearch_destroy(struct textsearch_context *textsearch)
+/* exported interface, documented in content/textsearch.h */
+const char *
+content_textsearch_find_pattern(const char *string,
+ int s_len,
+ const char *pattern,
+ int p_len,
+ bool case_sens,
+ unsigned int *m_len)
{
- assert(textsearch != NULL);
+ 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;
- if (textsearch->string != NULL) {
- guit->search->add_recent(textsearch->string, textsearch->gui_p);
- free(textsearch->string);
+ 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;
+ }
}
- guit->search->forward_state(true, textsearch->gui_p);
- guit->search->back_state(true, textsearch->gui_p);
+ /* end of pattern reached */
+ *m_len = max(s - ss, 1);
+ return ss;
+}
- free_matches(textsearch);
- free(textsearch);
+
+/* exported interface, documented in content/textsearch.h */
+nserror
+content_textsearch_add_match(struct textsearch_context *context,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct box *start_box,
+ struct box *end_box)
+{
+ struct list_entry *entry;
+
+ /* found string in box => add to list */
+ entry = calloc(1, sizeof(*entry));
+ if (entry == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ entry->start_idx = start_idx;
+ entry->end_idx = end_idx;
+ entry->start_box = start_box;
+ entry->end_box = end_box;
+ 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 NSERROR_OK;
}
-/**
- * Terminate a search.
- *
- * \param c content to clear
- */
-static nserror content_textsearch__clear(struct content *c)
+
+/* exported interface, 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)
{
- free(c->textsearch.string);
- c->textsearch.string = NULL;
+ struct list_entry *cur;
- if (c->textsearch.context != NULL) {
- content_textsearch_destroy(c->textsearch.context);
- c->textsearch.context = NULL;
+ 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 NSERROR_OK;
+
+ return false;
}
/* exported interface, documented in content/textsearch.h */
+nserror content_textsearch_destroy(struct textsearch_context *textsearch)
+{
+ assert(textsearch != NULL);
+
+ if (textsearch->string != NULL) {
+ /* broadcast recent query string */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_RECENT,
+ false,
+ textsearch->string);
+
+ free(textsearch->string);
+ }
+
+ /* update back state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_BACK,
+ true,
+ NULL);
+
+ /* update forward state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_FORWARD,
+ true,
+ NULL);
+
+ free_matches(textsearch);
+ free(textsearch);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in content/content.h */
nserror
content_textsearch(struct hlcache_handle *h,
void *context,
@@ -618,7 +730,7 @@ content_textsearch(struct hlcache_handle *h,
}
-/* exported interface, documented in content/textsearch.h */
+/* exported interface, documented in content/content.h */
nserror content_textsearch_clear(struct hlcache_handle *h)
{
struct content *c = hlcache_handle_get_content(h);
diff --git a/desktop/browser_window.c b/desktop/browser_window.c
index 8ef2c77..9cc95b6 100644
--- a/desktop/browser_window.c
+++ b/desktop/browser_window.c
@@ -46,6 +46,7 @@
#include "utils/nsoption.h"
#include "netsurf/misc.h"
#include "netsurf/window.h"
+#include "netsurf/search.h"
#include "netsurf/content.h"
#include "netsurf/plotters.h"
#include "content/content_debug.h"
@@ -1658,6 +1659,37 @@ browser_window_callback(hlcache_handle *c, const
hlcache_event *event, void *pw)
break;
+
+ case CONTENT_MSG_TEXTSEARCH:
+ switch (event->data.textsearch.type) {
+ case CONTENT_TEXTSEARCH_FIND:
+ guit->search->hourglass(event->data.textsearch.state,
+ event->data.textsearch.ctx);
+ break;
+
+ case CONTENT_TEXTSEARCH_MATCH:
+ guit->search->status(event->data.textsearch.state,
+ event->data.textsearch.ctx);
+ break;
+
+ case CONTENT_TEXTSEARCH_BACK:
+ guit->search->back_state(event->data.textsearch.state,
+ event->data.textsearch.ctx);
+ break;
+
+ case CONTENT_TEXTSEARCH_FORWARD:
+
guit->search->forward_state(event->data.textsearch.state,
+ event->data.textsearch.ctx);
+ break;
+
+ case CONTENT_TEXTSEARCH_RECENT:
+ guit->search->add_recent(event->data.textsearch.string,
+ event->data.textsearch.ctx);
+
+ break;
+ }
+ break;
+
default:
break;
}
diff --git a/include/netsurf/content_type.h b/include/netsurf/content_type.h
index b6bc5c2..0a6b830 100644
--- a/include/netsurf/content_type.h
+++ b/include/netsurf/content_type.h
@@ -173,7 +173,10 @@ typedef enum {
CONTENT_MSG_SELECTMENU,
/** A gadget has been clicked on (mainly for file) */
- CONTENT_MSG_GADGETCLICK
+ CONTENT_MSG_GADGETCLICK,
+
+ /** A free text search action has occurred */
+ CONTENT_MSG_TEXTSEARCH
} content_msg;
-----------------------------------------------------------------------
Summary of changes:
content/content.c | 15 +-
content/content.h | 44 +++
content/content_protected.h | 11 +-
content/handlers/image/bmp.c | 11 +
content/handlers/image/gif.c | 14 +
content/handlers/image/ico.c | 32 +-
content/handlers/image/image_cache.c | 11 +
content/handlers/image/image_cache.h | 5 +-
content/handlers/image/jpeg.c | 1 +
content/handlers/image/nssprite.c | 12 +
content/handlers/image/png.c | 1 +
content/handlers/image/rsvg.c | 14 +
content/handlers/image/webp.c | 1 +
content/textsearch.c | 572 ++++++++++++++++++++--------------
desktop/browser_window.c | 32 ++
frontends/amiga/icon.c | 13 +
include/netsurf/content_type.h | 5 +-
17 files changed, 547 insertions(+), 247 deletions(-)
diff --git a/content/content.c b/content/content.c
index bc3f484..f72f3d4 100644
--- a/content/content.c
+++ b/content/content.c
@@ -33,7 +33,6 @@
#include "netsurf/bitmap.h"
#include "netsurf/content.h"
#include "desktop/knockout.h"
-#include "desktop/gui_internal.h"
#include "content/content_protected.h"
#include "content/textsearch.h"
@@ -1294,21 +1293,13 @@ bool content_get_opaque(hlcache_handle *h)
/* exported interface documented in content/content_protected.h */
bool content__get_opaque(struct content *c)
{
- bool opaque = false;
-
if ((c != NULL) &&
(c->handler != NULL) &&
- (c->handler->type != NULL) &&
- (c->handler->type() == CONTENT_IMAGE) &&
- (c->handler->get_internal != NULL) ) {
- struct bitmap *bitmap = NULL;
- bitmap = c->handler->get_internal(c, NULL);
- if (bitmap != NULL) {
- opaque = guit->bitmap->get_opaque(bitmap);
- }
+ (c->handler->is_opaque != NULL)) {
+ return c->handler->is_opaque(c);
}
- return opaque;
+ return false;
}
diff --git a/content/content.h b/content/content.h
index f68af53..edf9ed2 100644
--- a/content/content.h
+++ b/content/content.h
@@ -242,6 +242,50 @@ union content_msg_data {
struct {
struct form_control *gadget;
} gadget_click;
+
+ /**
+ * CONTENT_MSG_TEXTSEARCH - Free text search action
+ */
+ struct {
+ /**
+ * The type of text search operation
+ */
+ enum {
+ /**
+ * Free text search find operation has started or finished
+ */
+ CONTENT_TEXTSEARCH_FIND,
+ /**
+ * Free text search match state has changed
+ */
+ CONTENT_TEXTSEARCH_MATCH,
+ /**
+ * Free text search back available state changed
+ */
+ CONTENT_TEXTSEARCH_BACK,
+ /**
+ * Free text search forward available state changed
+ */
+ CONTENT_TEXTSEARCH_FORWARD,
+ /**
+ * add a search query string to the recent searches
+ */
+ CONTENT_TEXTSEARCH_RECENT
+ } type;
+ /**
+ * context passed to browser_window_search()
+ */
+ void *ctx;
+ /**
+ * state for operation
+ */
+ bool state;
+ /**
+ * search string
+ */
+ const char *string;
+ } textsearch;
+
};
diff --git a/content/content_protected.h b/content/content_protected.h
index 667f5ba..881a432 100644
--- a/content/content_protected.h
+++ b/content/content_protected.h
@@ -119,7 +119,16 @@ struct content_handler {
/**
* handler dependant content sensitive internal data interface.
*/
- void * (*get_internal)(const struct content *c, void *context);
+ void *(*get_internal)(const struct content *c, void *context);
+
+ /**
+ * are the content contents opaque.
+ *
+ * Determine if this content would obscure (not mix with) any background
+ *
+ * \param c The content to check
+ */
+ bool (*is_opaque)(struct content *c);
/**
* There must be one content per user for this type.
diff --git a/content/handlers/image/bmp.c b/content/handlers/image/bmp.c
index a1a6ce6..a723022 100644
--- a/content/handlers/image/bmp.c
+++ b/content/handlers/image/bmp.c
@@ -264,6 +264,16 @@ static content_type nsbmp_content_type(void)
return CONTENT_IMAGE;
}
+static bool nsbmp_content_is_opaque(struct content *c)
+{
+ nsbmp_content *bmp = (nsbmp_content *)c;
+
+ if (bmp->bitmap != NULL) {
+ return guit->bitmap->get_opaque(bmp->bitmap);
+ }
+
+ return false;
+}
static const content_handler nsbmp_content_handler = {
.create = nsbmp_create,
@@ -273,6 +283,7 @@ static const content_handler nsbmp_content_handler = {
.clone = nsbmp_clone,
.get_internal = nsbmp_get_internal,
.type = nsbmp_content_type,
+ .is_opaque = nsbmp_content_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/gif.c b/content/handlers/image/gif.c
index 6ef4fa7..e2a0ca5 100644
--- a/content/handlers/image/gif.c
+++ b/content/handlers/image/gif.c
@@ -416,6 +416,19 @@ static content_type nsgif_content_type(void)
return CONTENT_IMAGE;
}
+static bool nsgif_content_is_opaque(struct content *c)
+{
+ nsgif_content *gif = (nsgif_content *) c;
+
+ if (gif->current_frame != gif->gif->decoded_frame) {
+ if (nsgif_get_frame(gif) != GIF_OK) {
+ return false;
+ }
+ }
+
+ return guit->bitmap->get_opaque(gif->gif->frame_image);
+}
+
static const content_handler nsgif_content_handler = {
.create = nsgif_create,
.data_complete = nsgif_convert,
@@ -426,6 +439,7 @@ static const content_handler nsgif_content_handler = {
.remove_user = nsgif_remove_user,
.get_internal = nsgif_get_internal,
.type = nsgif_content_type,
+ .is_opaque = nsgif_content_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/ico.c b/content/handlers/image/ico.c
index 3121278..2d839b1 100644
--- a/content/handlers/image/ico.c
+++ b/content/handlers/image/ico.c
@@ -84,7 +84,7 @@ static nserror nsico_create_ico_data(nsico_content *c)
}
-static nserror nsico_create(const content_handler *handler,
+static nserror nsico_create(const content_handler *handler,
lwc_string *imime_type, const struct http_parameter *params,
llcache_handle *llcache, const char *fallback_charset,
bool quirks, struct content **c)
@@ -251,7 +251,7 @@ static void *nsico_get_internal(const struct content *c,
void *context)
nsico_content *ico = (nsico_content *) c;
/* TODO: Pick best size for purpose.
* Currently assumes it's for a URL bar. */
- struct bmp_image *bmp;
+ struct bmp_image *bmp;
bmp = ico_find(ico->ico, 16, 16);
if (bmp == NULL) {
@@ -276,6 +276,33 @@ static content_type nsico_content_type(void)
return CONTENT_IMAGE;
}
+static bool nsico_is_opaque(struct content *c)
+{
+ nsico_content *ico = (nsico_content *) c;
+ struct bmp_image *bmp;
+
+ /**
+ * \todo Pick best size for purpose. Currently assumes
+ * it's for a URL bar.
+ */
+ bmp = ico_find(ico->ico, 16, 16);
+ if (bmp == NULL) {
+ /* return error */
+ NSLOG(netsurf, INFO, "Failed to select icon");
+ return false;
+ }
+
+ if (bmp->decoded == false) {
+ if (bmp_decode(bmp) != BMP_OK) {
+ return false;
+ }
+
+ guit->bitmap->modified(bmp->bitmap);
+ }
+
+ return guit->bitmap->get_opaque(bmp->bitmap);
+}
+
static const content_handler nsico_content_handler = {
.create = nsico_create,
.data_complete = nsico_convert,
@@ -284,6 +311,7 @@ static const content_handler nsico_content_handler = {
.clone = nsico_clone,
.get_internal = nsico_get_internal,
.type = nsico_content_type,
+ .is_opaque = nsico_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/image_cache.c
b/content/handlers/image/image_cache.c
index a1de01d..bc0b914 100644
--- a/content/handlers/image/image_cache.c
+++ b/content/handlers/image/image_cache.c
@@ -859,6 +859,17 @@ void *image_cache_get_internal(const struct content *c,
void *context)
}
/* exported interface documented in image_cache.h */
+bool image_cache_is_opaque(struct content *c)
+{
+ struct bitmap *bmp;
+ bmp = image_cache_get_bitmap(c);
+ if (bmp != NULL) {
+ return guit->bitmap->get_opaque(bmp);
+ }
+ return false;
+}
+
+/* exported interface documented in image_cache.h */
content_type image_cache_content_type(void)
{
return CONTENT_IMAGE;
diff --git a/content/handlers/image/image_cache.h
b/content/handlers/image/image_cache.h
index d57a3a9..955306e 100644
--- a/content/handlers/image/image_cache.h
+++ b/content/handlers/image/image_cache.h
@@ -170,7 +170,8 @@ int image_cache_snsummaryf(char *string, size_t size, const
char *fmt);
/********* Image content handler generic cache callbacks ************/
-/** Generic content redraw callback
+/**
+ * Generic content redraw callback
*
* May be used by image content handlers as their redraw
* callback. Performs all neccissary cache lookups and conversions and
@@ -185,6 +186,8 @@ void image_cache_destroy(struct content *c);
void *image_cache_get_internal(const struct content *c, void *context);
+bool image_cache_is_opaque(struct content *c);
+
content_type image_cache_content_type(void);
#endif
diff --git a/content/handlers/image/jpeg.c b/content/handlers/image/jpeg.c
index 09e68fd..549c2b6 100644
--- a/content/handlers/image/jpeg.c
+++ b/content/handlers/image/jpeg.c
@@ -414,6 +414,7 @@ static const content_handler nsjpeg_content_handler = {
.clone = nsjpeg_clone,
.get_internal = image_cache_get_internal,
.type = image_cache_content_type,
+ .is_opaque = image_cache_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/nssprite.c
b/content/handlers/image/nssprite.c
index f0114ee..a4ce6b5 100644
--- a/content/handlers/image/nssprite.c
+++ b/content/handlers/image/nssprite.c
@@ -258,6 +258,17 @@ static content_type nssprite_content_type(void)
}
+static bool nssprite_content_is_opaque(struct content *c)
+{
+ nssprite_content *nssprite = (nssprite_content *) c;
+
+ if (nssprite->bitmap != NULL) {
+ return guit->bitmap->get_opaque(nssprite->bitmap);
+ }
+
+ return false;
+}
+
static const content_handler nssprite_content_handler = {
.create = nssprite_create,
.data_complete = nssprite_convert,
@@ -266,6 +277,7 @@ static const content_handler nssprite_content_handler = {
.clone = nssprite_clone,
.get_internal = nssprite_get_internal,
.type = nssprite_content_type,
+ .is_opaque = nssprite_content_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/png.c b/content/handlers/image/png.c
index 1fa707d..4926d9a 100644
--- a/content/handlers/image/png.c
+++ b/content/handlers/image/png.c
@@ -602,6 +602,7 @@ static const content_handler nspng_content_handler = {
.redraw = image_cache_redraw,
.get_internal = image_cache_get_internal,
.type = image_cache_content_type,
+ .is_opaque = image_cache_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/rsvg.c b/content/handlers/image/rsvg.c
index 5cf900d..0051df3 100644
--- a/content/handlers/image/rsvg.c
+++ b/content/handlers/image/rsvg.c
@@ -316,6 +316,19 @@ static content_type rsvg_content_type(void)
return CONTENT_IMAGE;
}
+
+static bool rsvg_content_is_opaque(struct content *c)
+{
+ rsvg_content *d = (rsvg_content *) c;
+
+ if (d->bitmap != NULL) {
+ return guit->bitmap->get_opaque(d->bitmap);
+ }
+
+ return false;
+}
+
+
static const content_handler rsvg_content_handler = {
.create = rsvg_create,
.process_data = rsvg_process_data,
@@ -325,6 +338,7 @@ static const content_handler rsvg_content_handler = {
.clone = rsvg_clone,
.get_internal = rsvg_get_internal,
.type = rsvg_content_type,
+ .is_opaque = rsvg_content_is_opaque,
.no_share = false,
};
diff --git a/content/handlers/image/webp.c b/content/handlers/image/webp.c
index 8450fb1..721e924 100644
--- a/content/handlers/image/webp.c
+++ b/content/handlers/image/webp.c
@@ -225,6 +225,7 @@ static const content_handler webp_content_handler = {
.clone = webp_clone,
.get_internal = image_cache_get_internal,
.type = image_cache_content_type,
+ .is_opaque = image_cache_is_opaque,
.no_share = false,
};
diff --git a/content/textsearch.c b/content/textsearch.c
index 145c8c4..8997394 100644
--- a/content/textsearch.c
+++ b/content/textsearch.c
@@ -1,7 +1,6 @@
/*
* Copyright 2004 John M Bell <[email protected]>
- * Copyright 2005 Adrian Lees <[email protected]>
- * Copyright 2009 Mark Benjamin <[email protected]>
+ * Copyright 2020 Vincent Sanders <[email protected]>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -28,37 +27,81 @@
#include "utils/errors.h"
#include "utils/utils.h"
#include "netsurf/types.h"
-#include "netsurf/search.h"
#include "desktop/selection.h"
-#include "desktop/gui_internal.h"
#include "content/content.h"
#include "content/content_protected.h"
#include "content/hlcache.h"
#include "content/textsearch.h"
-
+/**
+ * search match
+ */
struct list_entry {
- unsigned start_idx; /* start position of match */
- unsigned end_idx; /* end of match */
+ /**
+ * previous match
+ */
+ struct list_entry *prev;
+
+ /**
+ * next match
+ */
+ struct list_entry *next;
+
+ /**
+ * start position of match
+ */
+ unsigned start_idx;
+
+ /**
+ * end of match
+ */
+ unsigned end_idx;
+
+ /**
+ * content opaque start pointer
+ */
+ struct box *start_box;
- struct box *start_box; /* used only for html contents */
+ /**
+ * content opaque end pointer
+ */
struct box *end_box;
+ /**
+ * content specific selection object
+ */
struct selection *sel;
-
- struct list_entry *prev;
- struct list_entry *next;
};
/**
* The context for a free text search
*/
struct textsearch_context {
- void *gui_p;
+
+ /**
+ * content search was performed upon
+ */
struct content *c;
+
+ /**
+ * opaque pointer passed to constructor.
+ */
+ void *gui_p;
+
+ /**
+ * List of matches
+ */
struct list_entry *found;
+
+ /**
+ * current selected match
+ */
struct list_entry *current; /* first for select all */
+
+ /**
+ * query string search results are for
+ */
char *string;
bool prev_case_sens;
bool newsearch;
@@ -66,6 +109,24 @@ struct textsearch_context {
/**
+ * broadcast textsearch message
+ */
+static inline void
+textsearch_broadcast(struct textsearch_context *textsearch,
+ int type,
+ bool state,
+ const char *string)
+{
+ union content_msg_data msg_data;
+ msg_data.textsearch.type = type;
+ msg_data.textsearch.ctx = textsearch->gui_p;
+ msg_data.textsearch.state = state;
+ msg_data.textsearch.string = string;
+ content_broadcast(textsearch->c, CONTENT_MSG_TEXTSEARCH, &msg_data);
+}
+
+
+/**
* Release the memory used by the list of matches,
* deleting selection objects too
*/
@@ -96,154 +157,6 @@ static void free_matches(struct textsearch_context
*textsearch)
}
-/* Exported function documented in content/textsearch.h */
-const char *
-content_textsearch_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;
-}
-
-
-/* Exported function documented in content/textsearch.h */
-nserror
-content_textsearch_add_match(struct textsearch_context *context,
- unsigned start_idx,
- unsigned end_idx,
- struct box *start_box,
- struct box *end_box)
-{
- struct list_entry *entry;
-
- /* found string in box => add to list */
- entry = calloc(1, sizeof(*entry));
- if (entry == NULL) {
- return NSERROR_NOMEM;
- }
-
- entry->start_idx = start_idx;
- entry->end_idx = end_idx;
- entry->start_box = start_box;
- entry->end_box = end_box;
- 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 NSERROR_OK;
-}
-
-
/**
* Specifies whether all matches or just the current match should
* be highlighted in the search text.
@@ -278,17 +191,17 @@ static void search_show_all(bool all, struct
textsearch_context *context)
/**
- * Search for a string in the box tree
+ * Search for a string in a content.
*
+ * \param context The search context.
* \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 nserror
-search_text(const char *string,
+search_text(struct textsearch_context *context,
+ const char *string,
int string_len,
- struct textsearch_context *context,
search_flags_t flags)
{
struct rect bounds;
@@ -322,7 +235,9 @@ search_text(const char *string,
context->string[string_len] = '\0';
}
- guit->search->hourglass(true, context->gui_p);
+ /* indicate find operation starting */
+ textsearch_broadcast(context, CONTENT_TEXTSEARCH_FIND, true,
NULL);
+
/* call content find handler */
res = context->c->handler->textsearch_find(context->c,
@@ -331,7 +246,8 @@ search_text(const char *string,
string_len,
case_sensitive);
- guit->search->hourglass(false, context->gui_p);
+ /* indicate find operation finished */
+ textsearch_broadcast(context, CONTENT_TEXTSEARCH_FIND, false,
NULL);
if (res != NSERROR_OK) {
free_matches(context);
@@ -355,29 +271,41 @@ search_text(const char *string,
}
}
- guit->search->status((context->current != NULL), context->gui_p);
+ /* update match state */
+ textsearch_broadcast(context,
+ CONTENT_TEXTSEARCH_MATCH,
+ (context->current != NULL),
+ NULL);
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);
+ /* update back state */
+ textsearch_broadcast(context,
+ CONTENT_TEXTSEARCH_BACK,
+ ((context->current != NULL) &&
+ (context->current->prev != NULL)),
+ NULL);
+
+ /* update forward state */
+ textsearch_broadcast(context,
+ CONTENT_TEXTSEARCH_FORWARD,
+ ((context->current != NULL) &&
+ (context->current->next != NULL)),
+ NULL);
+
if (context->current == NULL) {
+ /* no current match */
return res;
}
/* call content match bounds handler */
res = context->c->handler->textsearch_bounds(context->c,
-
context->current->start_idx,
- context->current->end_idx,
-
-
context->current->start_box,
- context->current->end_box,
- &bounds);
+ context->current->start_idx,
+ context->current->end_idx,
+ context->current->start_box,
+ context->current->end_box,
+ &bounds);
if (res == NSERROR_OK) {
msg_data.scroll.area = true;
msg_data.scroll.x0 = bounds.x0;
@@ -411,7 +339,11 @@ content_textsearch_step(struct textsearch_context
*textsearch,
assert(textsearch != NULL);
- guit->search->add_recent(string, textsearch->gui_p);
+ /* broadcast recent query string */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_RECENT,
+ false,
+ string);
string_len = strlen(string);
for (i = 0; i < string_len; i++) {
@@ -420,52 +352,61 @@ content_textsearch_step(struct textsearch_context
*textsearch,
}
if (i < string_len) {
- res = search_text(string, string_len, textsearch, flags);
+ res = search_text(textsearch, string, string_len, 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);
+ free_matches(textsearch);
+ /* update match state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_MATCH,
+ true,
+ NULL);
+
+ /* update back state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_BACK,
+ false,
+ NULL);
+
+ /* update forward state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_FORWARD,
+ false,
+ NULL);
+
+ /* clear scroll */
msg_data.scroll.area = false;
msg_data.scroll.x0 = 0;
msg_data.scroll.y0 = 0;
- content_broadcast(textsearch->c, CONTENT_MSG_SCROLL, &msg_data);
+ content_broadcast(textsearch->c,
+ CONTENT_MSG_SCROLL,
+ &msg_data);
}
return res;
}
-/* 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)
+/**
+ * Terminate a search.
+ *
+ * \param c content to clear
+ */
+static nserror content_textsearch__clear(struct content *c)
{
- struct list_entry *cur;
+ free(c->textsearch.string);
+ c->textsearch.string = NULL;
- 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;
- }
+ if (c->textsearch.context != NULL) {
+ content_textsearch_destroy(c->textsearch.context);
+ c->textsearch.context = NULL;
}
-
- return false;
+ return NSERROR_OK;
}
-/* Exported function documented in content/textsearch.h */
/**
* create a search_context
*
@@ -528,44 +469,215 @@ content_textsearch_create(struct content *c,
}
-/* Exported function documented in search.h */
-nserror content_textsearch_destroy(struct textsearch_context *textsearch)
+/* exported interface, documented in content/textsearch.h */
+const char *
+content_textsearch_find_pattern(const char *string,
+ int s_len,
+ const char *pattern,
+ int p_len,
+ bool case_sens,
+ unsigned int *m_len)
{
- assert(textsearch != NULL);
+ 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;
- if (textsearch->string != NULL) {
- guit->search->add_recent(textsearch->string, textsearch->gui_p);
- free(textsearch->string);
+ 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;
+ }
}
- guit->search->forward_state(true, textsearch->gui_p);
- guit->search->back_state(true, textsearch->gui_p);
+ /* end of pattern reached */
+ *m_len = max(s - ss, 1);
+ return ss;
+}
- free_matches(textsearch);
- free(textsearch);
+
+/* exported interface, documented in content/textsearch.h */
+nserror
+content_textsearch_add_match(struct textsearch_context *context,
+ unsigned start_idx,
+ unsigned end_idx,
+ struct box *start_box,
+ struct box *end_box)
+{
+ struct list_entry *entry;
+
+ /* found string in box => add to list */
+ entry = calloc(1, sizeof(*entry));
+ if (entry == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ entry->start_idx = start_idx;
+ entry->end_idx = end_idx;
+ entry->start_box = start_box;
+ entry->end_box = end_box;
+ 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 NSERROR_OK;
}
-/**
- * Terminate a search.
- *
- * \param c content to clear
- */
-static nserror content_textsearch__clear(struct content *c)
+
+/* exported interface, 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)
{
- free(c->textsearch.string);
- c->textsearch.string = NULL;
+ struct list_entry *cur;
- if (c->textsearch.context != NULL) {
- content_textsearch_destroy(c->textsearch.context);
- c->textsearch.context = NULL;
+ 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 NSERROR_OK;
+
+ return false;
}
/* exported interface, documented in content/textsearch.h */
+nserror content_textsearch_destroy(struct textsearch_context *textsearch)
+{
+ assert(textsearch != NULL);
+
+ if (textsearch->string != NULL) {
+ /* broadcast recent query string */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_RECENT,
+ false,
+ textsearch->string);
+
+ free(textsearch->string);
+ }
+
+ /* update back state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_BACK,
+ true,
+ NULL);
+
+ /* update forward state */
+ textsearch_broadcast(textsearch,
+ CONTENT_TEXTSEARCH_FORWARD,
+ true,
+ NULL);
+
+ free_matches(textsearch);
+ free(textsearch);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface, documented in content/content.h */
nserror
content_textsearch(struct hlcache_handle *h,
void *context,
@@ -618,7 +730,7 @@ content_textsearch(struct hlcache_handle *h,
}
-/* exported interface, documented in content/textsearch.h */
+/* exported interface, documented in content/content.h */
nserror content_textsearch_clear(struct hlcache_handle *h)
{
struct content *c = hlcache_handle_get_content(h);
diff --git a/desktop/browser_window.c b/desktop/browser_window.c
index 8ef2c77..9cc95b6 100644
--- a/desktop/browser_window.c
+++ b/desktop/browser_window.c
@@ -46,6 +46,7 @@
#include "utils/nsoption.h"
#include "netsurf/misc.h"
#include "netsurf/window.h"
+#include "netsurf/search.h"
#include "netsurf/content.h"
#include "netsurf/plotters.h"
#include "content/content_debug.h"
@@ -1658,6 +1659,37 @@ browser_window_callback(hlcache_handle *c, const
hlcache_event *event, void *pw)
break;
+
+ case CONTENT_MSG_TEXTSEARCH:
+ switch (event->data.textsearch.type) {
+ case CONTENT_TEXTSEARCH_FIND:
+ guit->search->hourglass(event->data.textsearch.state,
+ event->data.textsearch.ctx);
+ break;
+
+ case CONTENT_TEXTSEARCH_MATCH:
+ guit->search->status(event->data.textsearch.state,
+ event->data.textsearch.ctx);
+ break;
+
+ case CONTENT_TEXTSEARCH_BACK:
+ guit->search->back_state(event->data.textsearch.state,
+ event->data.textsearch.ctx);
+ break;
+
+ case CONTENT_TEXTSEARCH_FORWARD:
+
guit->search->forward_state(event->data.textsearch.state,
+ event->data.textsearch.ctx);
+ break;
+
+ case CONTENT_TEXTSEARCH_RECENT:
+ guit->search->add_recent(event->data.textsearch.string,
+ event->data.textsearch.ctx);
+
+ break;
+ }
+ break;
+
default:
break;
}
diff --git a/frontends/amiga/icon.c b/frontends/amiga/icon.c
index 353ba91..001874c 100644
--- a/frontends/amiga/icon.c
+++ b/frontends/amiga/icon.c
@@ -48,6 +48,7 @@
#include "content/content.h"
#include "content/content_protected.h"
#include "content/content_factory.h"
+#include "desktop/gui_internal.h"
#include "amiga/os3support.h"
#include "amiga/bitmap.h"
@@ -87,6 +88,17 @@ static void *amiga_icon_get_internal(const struct content
*c, void *context)
return icon_c->bitmap;
}
+static bool amiga_icon_is_opaque(struct content *c)
+{
+ amiga_icon_content *icon_c = (amiga_icon_content *)c;
+
+ if (icon_c->bitmap != NULL) {
+ return guit->bitmap->get_opaque(icon_c->bitmap);
+ }
+
+ return false;
+}
+
static const content_handler amiga_icon_content_handler = {
.create = amiga_icon_create,
.data_complete = amiga_icon_convert,
@@ -95,6 +107,7 @@ static const content_handler amiga_icon_content_handler = {
.clone = amiga_icon_clone,
.get_internal = amiga_icon_get_internal,
.type = amiga_icon_content_type,
+ .is_opaque = amiga_icon_is_opaque,
.no_share = false,
};
diff --git a/include/netsurf/content_type.h b/include/netsurf/content_type.h
index b6bc5c2..0a6b830 100644
--- a/include/netsurf/content_type.h
+++ b/include/netsurf/content_type.h
@@ -173,7 +173,10 @@ typedef enum {
CONTENT_MSG_SELECTMENU,
/** A gadget has been clicked on (mainly for file) */
- CONTENT_MSG_GADGETCLICK
+ CONTENT_MSG_GADGETCLICK,
+
+ /** A free text search action has occurred */
+ CONTENT_MSG_TEXTSEARCH
} content_msg;
--
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]