summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--content/fetchcache.c8
-rw-r--r--content/url_store.c475
-rw-r--r--content/url_store.h39
-rw-r--r--desktop/browser.c6
-rw-r--r--makefile4
-rw-r--r--riscos/dialog.c7
-rw-r--r--riscos/gui.c29
-rw-r--r--riscos/gui.h3
-rw-r--r--riscos/hotlist.c5
-rw-r--r--riscos/sprite.h2
-rw-r--r--riscos/url_complete.c558
-rw-r--r--riscos/url_complete.h26
-rw-r--r--riscos/window.c30
-rw-r--r--utils/url.c2
14 files changed, 1174 insertions, 20 deletions
diff --git a/content/fetchcache.c b/content/fetchcache.c
index 327a32613..4714d8002 100644
--- a/content/fetchcache.c
+++ b/content/fetchcache.c
@@ -22,6 +22,7 @@
#include "netsurf/content/content.h"
#include "netsurf/content/fetchcache.h"
#include "netsurf/content/fetch.h"
+#include "netsurf/content/url_store.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
#include "netsurf/utils/url.h"
@@ -74,7 +75,7 @@ struct content * fetchcache(const char *url,
struct content *c;
char *url1;
char *hash;
-
+
if ((url1 = strdup(url)) == NULL)
return NULL;
@@ -210,6 +211,7 @@ void fetchcache_go(struct content *content, char *referer,
void fetchcache_callback(fetch_msg msg, void *p, const char *data,
unsigned long size)
{
+ struct url_content *url_content;
bool res;
struct content *c = p;
content_type type;
@@ -279,6 +281,10 @@ void fetchcache_callback(fetch_msg msg, void *p, const char *data,
break;
case FETCH_FINISHED:
+ url_content = url_store_find(c->url);
+ if (url_content)
+ url_content->requests++;
+
LOG(("FETCH_FINISHED"));
c->fetch = 0;
content_set_status(c, messages_get("Converting"),
diff --git a/content/url_store.c b/content/url_store.c
new file mode 100644
index 000000000..5d83c3751
--- /dev/null
+++ b/content/url_store.c
@@ -0,0 +1,475 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ */
+
+/** \file
+ * Central repository for URL data (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "netsurf/content/url_store.h"
+#include "netsurf/utils/url.h"
+#include "netsurf/utils/log.h"
+
+
+#define ITERATIONS_BEFORE_TEST 32
+#define MAXIMUM_URL_LENGTH 1024
+
+struct hostname_data {
+ char *hostname; /** Hostname (lowercase) */
+ int hostname_length; /** Length of hostname */
+ struct url_data *url; /** URLs for this host */
+ struct hostname_data *previous; /** Previous hostname */
+ struct hostname_data *next; /** Next hostname */
+};
+
+static struct hostname_data *url_store_hostnames = NULL;
+
+static struct hostname_data *url_store_find_hostname(const char *url);
+static struct hostname_data *url_store_match_hostname(const char *url,
+ struct hostname_data *previous);
+
+
+/**
+ * Returns the hostname data for the specified URL. If no hostname
+ * data is currently available then it is created.
+ *
+ * \param url the url to find hostname data for
+ * \return the current hostname data, or NULL on error
+ */
+static struct hostname_data *url_store_find_hostname(const char *url) {
+ struct hostname_data *search;
+ struct hostname_data *result;
+ url_func_result res;
+ char *hostname;
+ int hostname_length;
+ int compare;
+ int fast_exit_counter = ITERATIONS_BEFORE_TEST;
+
+ assert(url);
+
+ res = url_host(url, &hostname);
+ if (res != URL_FUNC_OK)
+ return NULL;
+ hostname_length = strlen(hostname);
+
+ /* try to find a matching hostname fairly quickly */
+ for (search = url_store_hostnames; search; search = search->next) {
+ if ((fast_exit_counter <= 0) ||
+ (search->hostname_length == hostname_length)) {
+ compare = strcmp(hostname, search->hostname);
+ if (compare == 0) {
+ free(hostname);
+ return search;
+ } else if (compare < 0)
+ break;
+ fast_exit_counter = ITERATIONS_BEFORE_TEST;
+ } else {
+ fast_exit_counter--;
+ }
+ }
+
+ /* no hostname is available: create a new one */
+ result = calloc(sizeof(struct hostname_data), 1);
+ if (!result)
+ return NULL;
+ result->hostname = hostname;
+ result->hostname_length = hostname_length;
+
+ /* simple case: no current hostnames */
+ if (!url_store_hostnames) {
+ url_store_hostnames = result;
+ return result;
+ }
+
+ /* worst case scenario: the place we need to link is within the last
+ * section of the hostname list so we have no reference to work back
+ * from. rather than slowing with the very common case of searching,
+ * we take a speed hit for this case and simply move to the very end
+ * of the hostname list ready to work backwards. */
+ if (!search)
+ for (search = url_store_hostnames; search->next;
+ search = search->next);
+
+ /* we can now simply scan backwards as we know roughly where we need
+ * to link to (we either had an early exit from the searching so we
+ * know we're in the block following where we need to link, or we're
+ * at the very end of the list as we were in the last block.) */
+ while ((search) && (strcmp(hostname, search->hostname) < 0))
+ search = search->previous;
+
+ /* simple case: our new hostname is the first in the list */
+ if (!search) {
+ result->next = url_store_hostnames;
+ url_store_hostnames->previous = result;
+ url_store_hostnames = result;
+ return result;
+ }
+
+ /* general case: link in after the found hostname */
+ result->previous = search;
+ result->next = search->next;
+ if (search->next)
+ search->next->previous = result;
+ search->next = result;
+ return result;
+}
+
+
+/**
+ * Returns the url data for the specified URL. If no url
+ * data is currently available then it is created.
+ *
+ * \param url a normalized url to find hostname data for
+ * \return the current hostname data, or NULL on error
+ */
+struct url_content *url_store_find(const char *url) {
+ struct hostname_data *hostname_data;
+ struct url_data *search;
+ struct url_data *result;
+ int url_length;
+ int compare;
+ int fast_exit_counter = ITERATIONS_BEFORE_TEST;
+
+ assert(url);
+
+ /* find the corresponding hostname data */
+ hostname_data = url_store_find_hostname(url);
+ if (!hostname_data)
+ return NULL;
+
+ /* move to the start of the leafname */
+ url_length = strlen(url);
+
+ /* try to find a matching url fairly quickly */
+ for (search = hostname_data->url; search; search = search->next) {
+ if ((fast_exit_counter <= 0) ||
+ (search->url_length == url_length)) {
+ compare = strcmp(url, search->url);
+ if (compare == 0)
+ return &search->data;
+ else if (compare < 0)
+ break;
+ fast_exit_counter = ITERATIONS_BEFORE_TEST;
+ } else {
+ fast_exit_counter--;
+ }
+ }
+
+ /* no URL is available: create a new one */
+ result = calloc(sizeof(struct url_data), 1);
+ if (!result)
+ return NULL;
+ result->url = malloc(url_length + 1);
+ if (!result->url) {
+ free(result);
+ return NULL;
+ }
+ strcpy(result->url, url);
+ result->url_length = url_length;
+ result->data.requests = 0;
+ result->data.visits = 0;
+ result->parent = hostname_data;
+
+ /* simple case: no current URLs */
+ if (!hostname_data->url) {
+ hostname_data->url = result;
+ return &result->data;
+ }
+
+ /* worst case scenario: the place we need to link is within the last
+ * section of the URL list so we have no reference to work back
+ * from. rather than slowing with the very common case of searching,
+ * we take a speed hit for this case and simply move to the very end
+ * of the URL list ready to work backwards. */
+ if (!search)
+ for (search = hostname_data->url; search->next;
+ search = search->next);
+
+ /* we can now simply scan backwards as we know roughly where we need
+ * to link to (we either had an early exit from the searching so we
+ * know we're in the block following where we need to link, or we're
+ * at the very end of the list as we were in the last block.) */
+ while ((search) && (strcmp(url, search->url) < 0))
+ search = search->previous;
+
+ /* simple case: our new hostname is the first in the list */
+ if (!search) {
+ result->next = hostname_data->url;
+ hostname_data->url->previous = result;
+ hostname_data->url = result;
+ return &result->data;
+ }
+
+ /* general case: link in after the found hostname */
+ result->previous = search;
+ result->next = search->next;
+ if (search->next)
+ search->next->previous = result;
+ search->next = result;
+ return &result->data;
+}
+
+
+/**
+ * Returns the next hostname that matches a part of the specified URL.
+ *
+ * \param url a normalized url to find the next match for
+ * \param current the current hostname to search forward from, or NULL
+ * \return the next matching hostname, or NULL
+ */
+static struct hostname_data *url_store_match_hostname(const char *url,
+ struct hostname_data *current) {
+ url_func_result res;
+ char *hostname;
+ int hostname_length;
+ int compare;
+ bool www_test;
+
+ assert(url);
+
+ res = url_host(url, &hostname);
+ if (res != URL_FUNC_OK)
+ return NULL;
+ hostname_length = strlen(hostname);
+ www_test = strncmp(hostname, "www.", 4);
+
+ /* advance to the next hostname */
+ if (!current)
+ current = url_store_hostnames;
+ else
+ current = current->next;
+
+ /* skip past hostname data without URLs */
+ for (; current && (!current->url); current = current->next);
+
+ while (current) {
+ if (current->hostname_length >= hostname_length) {
+ compare = strncmp(hostname, current->hostname,
+ hostname_length);
+ if (compare == 0) {
+ free(hostname);
+ return current;
+ } else if ((compare < 0) && !www_test)
+ break;
+ }
+ /* special case: if hostname is not www then try it */
+ if (www_test && ((current->hostname_length - 4) >= hostname_length) &&
+ (!strncmp(current->hostname, "www.", 4)) &&
+ (!strncmp(hostname, current->hostname + 4,
+ hostname_length))) {
+ free(hostname);
+ return current;
+ }
+
+ /* move to next hostname with URLs */
+ current = current->next;
+ for (; current && (!current->url); current = current->next);
+ }
+
+ free(hostname);
+ return NULL;
+}
+
+
+
+/**
+ * Returns the complete URL for the next matched stored URL.
+ *
+ * \param url a normalized url to find the next match for
+ * \param reference internal reference (NULL for first call)
+ * \return the next URL that matches
+ */
+char *url_store_match(const char *url, struct url_data **reference) {
+ struct hostname_data *hostname;
+ struct url_data *search = NULL;
+ char *scheme;
+ int scheme_length;
+ int url_length;
+ url_func_result res;
+ bool www_test;
+
+ assert(url);
+
+ if (!url_store_hostnames)
+ return NULL;
+
+ /* find the first URL, not necessarily matching */
+ if (!*reference) {
+ hostname = url_store_match_hostname(url, NULL);
+ if (!hostname)
+ return NULL;
+ } else {
+ search = *reference;
+ hostname = search->parent;
+ }
+
+ res = url_scheme(url, &scheme);
+ if (res != URL_FUNC_OK)
+ return NULL;
+ scheme_length = strlen(scheme);
+ url_length = strlen(url);
+ www_test = (!strcmp(scheme, "http") &&
+ strncmp(url + 4 + 3, "www.", 4)); /* 'http' + '://' */
+
+ /* work through all our strings, ignoring the scheme and 'www.' */
+ while (hostname) {
+
+ /* get the next URL to test */
+ if (!search)
+ search = hostname->url;
+ else
+ search = search->next;
+
+ /* loop past end of list, or search */
+ if (!search) {
+ hostname = url_store_match_hostname(url, hostname);
+ if (!hostname)
+ return NULL;
+ } else if ((search->data.visits > 0) && (search->data.requests > 0)){
+ /* straight match */
+ if ((search->url_length >= url_length) &&
+ (!strncmp(search->url, url, url_length))) {
+ free(scheme);
+ *reference = search;
+ return search->url;
+ }
+ /* try with 'www.' inserted after the scheme */
+ if (www_test && ((search->url_length - 4) >= url_length) &&
+ (!strncmp(search->url, scheme, scheme_length)) &&
+ (!strncmp(search->url + scheme_length + 3, "www.", 4)) &&
+ (!strncmp(search->url + scheme_length + 7,
+ url + scheme_length + 3,
+ url_length - scheme_length - 3))) {
+ free(scheme);
+ *reference = search;
+ return search->url;
+ }
+ }
+ }
+
+ free(scheme);
+ return NULL;
+}
+
+
+/**
+ * Converts a text string into one suitable for URL matching.
+ *
+ * \param text the text to search with
+ * \return URL matching string allocated on heap, or NULL on error
+ */
+char *url_store_match_string(const char *text) {
+ url_func_result res;
+ char *url;
+
+ assert(text);
+
+ res = url_normalize(text, &url);
+ if (res != URL_FUNC_OK)
+ return NULL;
+
+ /* drop the '/' from the end if it was added when normalizing */
+ if ((url[strlen(url) - 1] == '/') && (text[strlen(text) - 1] != '/'))
+ url[strlen(url) - 1] = '\0';
+ return url;
+}
+
+
+/**
+ * Loads the current contents of the URL store to disk
+ *
+ * \param file the file to load options from
+ */
+void url_store_load(const char *file) {
+ struct url_content *url;
+ char s[MAXIMUM_URL_LENGTH];
+ FILE *fp;
+
+ fp = fopen(file, "r");
+ if (!fp) {
+ LOG(("Failed to open file '%s' for reading", file));
+ return;
+ }
+
+ if (!fgets(s, MAXIMUM_URL_LENGTH, fp))
+ return;
+ if (strncmp(s, "100", 3)) {
+ LOG(("Invalid header"));
+ return;
+ }
+
+ while (fgets(s, MAXIMUM_URL_LENGTH, fp)) {
+ if (s[strlen(s) - 1] == '\n')
+ s[strlen(s) - 1] = '\0';
+ url = url_store_find(s);
+ if (!url)
+ break;
+ if (!fgets(s, MAXIMUM_URL_LENGTH, fp))
+ break;
+ url->visits = atoi(s);
+ if (!fgets(s, MAXIMUM_URL_LENGTH, fp))
+ break;
+ url->requests = atoi(s);
+ }
+ fclose(fp);
+}
+
+
+/**
+ * Saves the current contents of the URL store to disk
+ *
+ * \param file the file to load options from
+ */
+void url_store_save(const char *file) {
+ struct hostname_data *search;
+ struct url_data *url;
+ FILE *fp;
+
+ fp = fopen(file, "w");
+ if (!fp) {
+ LOG(("Failed to open file '%s' for writing", file));
+ return;
+ }
+
+ /* file format version number */
+ fprintf(fp, "100\n");
+ for (search = url_store_hostnames; search; search = search->next) {
+ for (url = search->url; url; url = url->next) {
+ if (strlen(url->url) < 1024) {
+ fprintf(fp, "%s\n%i\n%i\n", url->url,
+ url->data.visits, url->data.requests);
+ }
+ }
+ }
+ fclose(fp);
+}
+
+
+/**
+ * Dumps the currently stored URLs and hostnames to stderr.
+ */
+void url_store_dump(void) {
+ struct hostname_data *search;
+ struct url_data *url;
+
+ fprintf(stderr, "\nDumping hostname data:\n");
+ for (search = url_store_hostnames; search; search = search->next) {
+ fprintf(stderr, "\n");
+ fprintf(stderr, search->hostname);
+ fprintf(stderr, ":\n");
+ for (url = search->url; url; url = url->next) {
+ fprintf(stderr, " - ");
+ fprintf(stderr, url->url);
+ fprintf(stderr, "\n");
+ }
+ }
+ fprintf(stderr, "\nEnd of hostname data.\n\n");
+}
diff --git a/content/url_store.h b/content/url_store.h
new file mode 100644
index 000000000..b152508af
--- /dev/null
+++ b/content/url_store.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ */
+
+/** \file
+ * Central repository for URL data (interface).
+ */
+
+#ifndef _NETSURF_CONTENT_URLSTORE_H_
+#define _NETSURF_CONTENT_URLSTORE_H_
+
+struct url_content {
+ int visits; /** Number of times visited */
+ int requests; /** Number of times requested */
+};
+
+struct url_data {
+ struct url_content data; /** Stored URL content data */
+ char *url; /** URL (including hostname) */
+ int url_length; /** Length of URL (including hostname) */
+ struct url_data *previous; /** Previous URL */
+ struct url_data *next; /** Next URL */
+ struct hostname_data *parent; /** Parent hostname data */
+};
+
+
+struct url_content *url_store_find(const char *url);
+char *url_store_match(const char *url, struct url_data **reference);
+char *url_store_match_string(const char *text);
+
+void url_store_load(const char *file);
+void url_store_save(const char *file);
+
+void url_store_dump(void);
+
+#endif
diff --git a/desktop/browser.c b/desktop/browser.c
index e4cfb2273..9e17657e1 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -22,6 +22,7 @@
#include "netsurf/utils/config.h"
#include "netsurf/content/fetch.h"
#include "netsurf/content/fetchcache.h"
+#include "netsurf/content/url_store.h"
#include "netsurf/css/css.h"
#ifdef WITH_AUTH
#include "netsurf/desktop/401login.h"
@@ -166,6 +167,7 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
char *url2;
char *hash;
url_func_result res;
+ struct url_content *url_content;
LOG(("bw %p, url %s", bw, url));
@@ -194,6 +196,10 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
bw->frag_id = strdup(hash+1);
}
+ url_content = url_store_find(url2);
+ if (url_content)
+ url_content->visits++;
+
browser_window_set_status(bw, messages_get("Loading"));
bw->history_add = history_add;
bw->time0 = clock();
diff --git a/makefile b/makefile
index 991d83c97..4f5f324f1 100644
--- a/makefile
+++ b/makefile
@@ -17,7 +17,7 @@
# "riscos", "riscos_small", "ncos", and "riscos_debug" can be compiled under
# RISC OS, or cross-compiled using gccsdk.
-OBJECTS_COMMON = content.o fetch.o fetchcache.o # content/
+OBJECTS_COMMON = content.o fetch.o fetchcache.o url_store.o # content/
OBJECTS_COMMON += css.o css_enum.o parser.o ruleset.o scanner.o # css/
OBJECTS_COMMON += box.o form.o html.o html_redraw.o layout.o \
list.o textplain.o # render/
@@ -35,7 +35,7 @@ OBJECTS_RISCOS += 401login.o bitmap.o buffer.o debugwin.o \
save.o save_complete.o save_draw.o save_text.o \
schedule.o search.o sprite.o textselection.o theme.o \
theme_install.o thumbnail.o treeview.o ufont.o uri.o \
- url_protocol.o wimp.o window.o # riscos/
+ url_complete.o url_protocol.o wimp.o window.o # riscos/
# OBJECTS_RISCOS += memdebug.o
OBJECTS_NCOS = $(OBJECTS_RISCOS)
diff --git a/riscos/dialog.c b/riscos/dialog.c
index c6cb54fc7..223c268d0 100644
--- a/riscos/dialog.c
+++ b/riscos/dialog.c
@@ -43,7 +43,7 @@ wimp_w dialog_info, dialog_saveas, dialog_config, dialog_config_br,
dialog_zoom, dialog_pageinfo, dialog_objinfo, dialog_tooltip,
dialog_warning, dialog_config_th_pane, dialog_debug,
dialog_folder, dialog_entry, dialog_search, dialog_print,
- dialog_config_font, dialog_config_image;
+ dialog_config_font, dialog_config_image, dialog_url_complete;
static int ro_gui_choices_font_size;
static int ro_gui_choices_font_min_size;
@@ -140,6 +140,7 @@ void ro_gui_dialog_init(void)
dialog_config_font = ro_gui_dialog_create("config_font");
dialog_config_image = ro_gui_dialog_create("config_img");
dialog_theme_install = ro_gui_dialog_create("theme_inst");
+ dialog_url_complete = ro_gui_dialog_create("url_suggest");
}
@@ -811,12 +812,8 @@ void ro_gui_save_options(void)
/* NCOS doesnt have the fancy Universal Boot vars; so select
* the path to the choices file based on the build options */
#ifndef NCOS
- xosfile_create_dir("<Choices$Write>.WWW", 0);
- xosfile_create_dir("<Choices$Write>.WWW.NetSurf", 0);
options_write("<Choices$Write>.WWW.NetSurf.Choices");
#else
- xosfile_create_dir("<User$Path>.Choices.NetSurf", 0);
- xosfile_create_dir("<User$Path>.Choices.NetSurf.Choices", 0);
options_write("<User$Path>.Choices.NetSurf.Choices");
#endif
}
diff --git a/riscos/gui.c b/riscos/gui.c
index 131320347..5750119d6 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -32,6 +32,7 @@
#include "oslib/wimp.h"
#include "oslib/wimpspriteop.h"
#include "oslib/uri.h"
+#include "netsurf/content/url_store.h"
#include "netsurf/utils/config.h"
#include "netsurf/desktop/gui.h"
#include "netsurf/desktop/netsurf.h"
@@ -57,6 +58,7 @@
#ifdef WITH_URL
#include "netsurf/riscos/url_protocol.h"
#endif
+#include "netsurf/riscos/url_complete.h"
#include "netsurf/riscos/wimp.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
@@ -184,6 +186,17 @@ void gui_init(int argc, char** argv)
xhourglass_start(1);
+ /* create our choices directories */
+#ifndef NCOS
+ xosfile_create_dir("<Choices$Write>.WWW", 0);
+ xosfile_create_dir("<Choices$Write>.WWW.NetSurf", 0);
+ xosfile_create_dir("<Choices$Write>.WWW.NetSurf.Themes", 0);
+#else
+ xosfile_create_dir("<User$Path>.Choices.NetSurf", 0);
+ xosfile_create_dir("<User$Path>.Choices.NetSurf.Choices", 0);
+ xosfile_create_dir("<User$Path>.Choices.NetSurf.Choices.Themes", 0);
+#endif
+
#ifdef WITH_SAVE_COMPLETE
save_complete_init();
#endif
@@ -195,6 +208,8 @@ void gui_init(int argc, char** argv)
options_read("<User$Path>.Choices.NetSurf.Choices");
#endif
ro_gui_choose_language();
+
+ url_store_load("Choices:WWW.NetSurf.URL");
NETSURF_DIR = getenv("NetSurf$Dir");
if ((length = snprintf(path, sizeof(path),
@@ -527,6 +542,7 @@ void gui_init2(int argc, char** argv)
void gui_quit(void)
{
+ url_store_save("<Choices$Write>.WWW.NetSurf.URL");
ro_gui_window_quit();
ro_gui_hotlist_save();
ro_gui_history_quit();
@@ -751,6 +767,8 @@ void ro_gui_null_reason_code(void)
if (gui_track_wimp_w == history_window)
ro_gui_history_mouse_at(&pointer);
+ if (gui_track_wimp_w == dialog_url_complete)
+ ro_gui_url_complete_mouse_at(&pointer);
else if (gui_track_gui_window)
ro_gui_window_mouse_at(gui_track_gui_window, &pointer);
}
@@ -766,6 +784,8 @@ void ro_gui_redraw_window_request(wimp_draw *redraw)
if (redraw->w == history_window)
ro_gui_history_redraw(redraw);
+ else if (redraw->w == dialog_url_complete)
+ ro_gui_url_complete_redraw(redraw);
else if ((hotlist_tree) && (redraw->w == (wimp_w)hotlist_tree->handle))
ro_gui_tree_redraw(redraw, hotlist_tree);
else if ((hotlist_toolbar) && (hotlist_toolbar->toolbar_handle == redraw->w))
@@ -827,8 +847,10 @@ void ro_gui_close_window_request(wimp_close *close)
if (close->w == dialog_debug)
ro_gui_debugwin_close();
- else if ((g = ro_gui_window_lookup(close->w)) != NULL)
+ else if ((g = ro_gui_window_lookup(close->w)) != NULL) {
+ ro_gui_url_complete_close(NULL, 0);
browser_window_destroy(g->bw);
+ }
else if ((dw = ro_gui_download_window_lookup(close->w)) != NULL)
ro_gui_download_window_destroy(dw);
else
@@ -866,7 +888,8 @@ void ro_gui_pointer_entering_window(wimp_entering *entering)
{
gui_track_wimp_w = entering->w;
gui_track_gui_window = ro_gui_window_lookup(entering->w);
- gui_track = gui_track_gui_window || gui_track_wimp_w == history_window;
+ gui_track = gui_track_gui_window || gui_track_wimp_w == history_window ||
+ gui_track_wimp_w == dialog_url_complete;
}
@@ -883,6 +906,8 @@ void ro_gui_mouse_click(wimp_pointer *pointer)
ro_gui_icon_bar_click(pointer);
else if (pointer->w == history_window)
ro_gui_history_click(pointer);
+ else if (pointer->w == dialog_url_complete)
+ ro_gui_url_complete_mouse_at(pointer);
else if ((hotlist_tree) && (pointer->w == (wimp_w)hotlist_tree->handle))
ro_gui_hotlist_click(pointer);
else if (pointer->w == dialog_saveas)
diff --git a/riscos/gui.h b/riscos/gui.h
index 8d78b411f..7a3264c5e 100644
--- a/riscos/gui.h
+++ b/riscos/gui.h
@@ -30,7 +30,8 @@ extern wimp_w dialog_info, dialog_saveas, dialog_config, dialog_config_br,
dialog_config_prox, dialog_config_th, dialog_zoom, dialog_pageinfo,
dialog_objinfo, dialog_tooltip, dialog_warning,
dialog_config_th_pane, dialog_debug, dialog_folder, dialog_entry,
- dialog_search, dialog_print, dialog_config_font, dialog_theme_install;
+ dialog_search, dialog_print, dialog_config_font, dialog_theme_install,
+ dialog_url_complete;
extern wimp_w history_window;
extern wimp_menu *iconbar_menu, *browser_menu, *combo_menu, *hotlist_menu,
*proxyauth_menu, *languages_menu, *toolbar_menu,
diff --git a/riscos/hotlist.c b/riscos/hotlist.c
index e1303c51e..3edec0ad0 100644
--- a/riscos/hotlist.c
+++ b/riscos/hotlist.c
@@ -152,11 +152,6 @@ void ro_gui_hotlist_save(void) {
if (!hotlist_tree) return;
- /* Ensure we have a directory to save to later.
- */
- xosfile_create_dir("<Choices$Write>.WWW", 0);
- xosfile_create_dir("<Choices$Write>.WWW.NetSurf", 0);
-
/* Save to our file
*/
options_save_hotlist(hotlist_tree, "<Choices$Write>.WWW.NetSurf.Hotlist");
diff --git a/riscos/sprite.h b/riscos/sprite.h
index 605027635..3824ace43 100644
--- a/riscos/sprite.h
+++ b/riscos/sprite.h
@@ -12,6 +12,8 @@
#ifndef _NETSURF_RISCOS_SPRITE_H_
#define _NETSURF_RISCOS_SPRITE_H_
+#include <stdbool.h>
+
struct content;
struct content_sprite_data {
diff --git a/riscos/url_complete.c b/riscos/url_complete.c
new file mode 100644
index 000000000..2aecfbdb9
--- /dev/null
+++ b/riscos/url_complete.c
@@ -0,0 +1,558 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ */
+
+/** \file
+ * GUI URL auto-completion (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "oslib/wimp.h"
+#include "netsurf/content/url_store.h"
+#include "netsurf/utils/log.h"
+#include "netsurf/riscos/gui.h"
+#include "netsurf/riscos/theme.h"
+#include "netsurf/riscos/url_complete.h"
+#include "netsurf/riscos/wimp.h"
+#include "netsurf/utils/utils.h"
+
+#define MAXIMUM_VISIBLE_LINES 7
+
+static char **url_complete_matches = NULL;
+static int url_complete_matches_allocated = 0;
+static int url_complete_matches_available = 0;
+static char *url_complete_matched_string = NULL;
+static int url_complete_matches_selection = -1;
+static int url_complete_keypress_selection = -1;
+static wimp_w url_complete_parent = 0;
+static bool url_complete_matches_reset = false;
+static char *url_complete_original_url = NULL;
+
+static char *url_complete_redraw[MAXIMUM_VISIBLE_LINES];
+static char url_complete_icon_null[] = "\0";
+static wimp_icon url_complete_icon;
+static int mouse_x;
+static int mouse_y;
+
+
+/**
+ * Handles a keypress for URL completion
+ *
+ * \param g the gui_window to update
+ * \param key the key pressed
+ */
+bool ro_gui_url_complete_keypress(struct gui_window *g, int key) {
+ wimp_window_state state;
+ char **array_extend;
+ struct url_data *reference = NULL;
+ char *match_url;
+ char *url;
+ char *output;
+ int i, lines;
+ int old_selection;
+ bool ignore_changes = false;
+ int height;
+ os_error *error;
+ bool currently_open;
+
+ /* we must have a toolbar/url bar */
+ if ((!g->toolbar) || (!g->toolbar->display_url)) {
+ ro_gui_url_complete_close(NULL, 0);
+ return false;
+ }
+
+ /* if we are currently active elsewhere, remove the previous window */
+ currently_open = g->window == url_complete_parent;
+ if (g->window != url_complete_parent) {
+ ro_gui_url_complete_close(NULL, 0);
+ url_complete_parent = g->window;
+ }
+
+ /* get the text to match */
+ url = ro_gui_get_icon_string(g->toolbar->toolbar_handle, ICON_TOOLBAR_URL);
+ match_url = url_store_match_string(url);
+ if (!match_url) {
+ ro_gui_url_complete_close(NULL, 0);
+ return false;
+ }
+
+ /* check if we should ignore text changes */
+ if (url_complete_keypress_selection >= 0)
+ ignore_changes = !strcmp(url,
+ url_complete_matches[url_complete_keypress_selection]);
+
+ /* if the text to match has changed then update it */
+ if (!ignore_changes && ((!url_complete_matched_string) ||
+ (strcmp(match_url, url_complete_matched_string)))) {
+
+ /* memorize the current matches */
+ lines = MAXIMUM_VISIBLE_LINES;
+ if (lines > url_complete_matches_available)
+ lines = url_complete_matches_available;
+ for (i = 0; i < MAXIMUM_VISIBLE_LINES; i++)
+ url_complete_redraw[i] = url_complete_matches[i];
+
+ /* our selection gets wiped */
+ error = xwimp_force_redraw(dialog_url_complete,
+ 0, -(url_complete_matches_selection + 1) * 44,
+ 65536, -url_complete_matches_selection * 44);
+ if (error) {
+ LOG(("xwimp_force_redraw: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+
+ /* clear our state */
+ free(url_complete_original_url);
+ free(url_complete_matched_string);
+ url_complete_matched_string = match_url;
+ url_complete_original_url = NULL;
+ url_complete_matches_available = 0;
+ url_complete_matches_selection = -1;
+ url_complete_keypress_selection = -1;
+
+ /* get some initial memory */
+ if (!url_complete_matches) {
+ url_complete_matches = malloc(64 * sizeof(char *));
+ if (!url_complete_matches) {
+ ro_gui_url_complete_close(NULL, 0);
+ return false;
+ }
+ url_complete_matches_allocated = 64;
+ }
+
+ /* get all our matches */
+ while ((output = url_store_match(match_url, &reference))) {
+ url_complete_matches_available++;
+ if (url_complete_matches_available >
+ url_complete_matches_allocated) {
+
+ array_extend = realloc(url_complete_matches,
+ (url_complete_matches_allocated + 64) *
+ sizeof(char *));
+ if (!array_extend) {
+ ro_gui_url_complete_close(NULL, 0);
+ return false;
+ }
+ url_complete_matches = array_extend;
+ url_complete_matches_allocated += 64;
+ }
+ url_complete_matches[url_complete_matches_available - 1] =
+ output;
+
+ }
+
+ /* update the window */
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+ url_complete_matches_reset = true;
+ ro_gui_url_complete_resize(g, (wimp_open *)&state);
+ url_complete_matches_reset = false;
+
+ /* redraw the relevant bits of the window */
+ lines = MAXIMUM_VISIBLE_LINES;
+ if (lines > url_complete_matches_available)
+ lines = url_complete_matches_available;
+ for (i = 0; i < MAXIMUM_VISIBLE_LINES; i++) {
+ if (url_complete_redraw[i] != url_complete_matches[i]) {
+ error = xwimp_force_redraw(dialog_url_complete,
+ 0, -(i + 1) * 44, 65536, -i * 44);
+ if (error) {
+ LOG(("xwimp_force_redraw: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ }
+ }
+
+ } else {
+ free(match_url);
+ }
+
+ /* handle keypresses */
+ if (!currently_open)
+ return false;
+ old_selection = url_complete_matches_selection;
+ switch (key) {
+ case wimp_KEY_UP:
+ url_complete_matches_selection--;
+ break;
+ case wimp_KEY_DOWN:
+ url_complete_matches_selection++;
+ break;
+ case wimp_KEY_PAGE_UP:
+ url_complete_matches_selection -= MAXIMUM_VISIBLE_LINES;
+ break;
+ case wimp_KEY_PAGE_DOWN:
+ url_complete_matches_selection += MAXIMUM_VISIBLE_LINES;
+ break;
+ case wimp_KEY_CONTROL | wimp_KEY_UP:
+ url_complete_matches_selection = 0;
+ break;
+ case wimp_KEY_CONTROL | wimp_KEY_DOWN:
+ url_complete_matches_selection = 65536;
+ break;
+ }
+ if (url_complete_matches_selection > url_complete_matches_available - 1)
+ url_complete_matches_selection = url_complete_matches_available - 1;
+ else if (url_complete_matches_selection < -1)
+ url_complete_matches_selection = -1;
+
+ if (old_selection == url_complete_matches_selection)
+ return false;
+
+ error = xwimp_force_redraw(dialog_url_complete,
+ 0, -(old_selection + 1) * 44, 65536, -old_selection * 44);
+ if (error) {
+ LOG(("xwimp_force_redraw: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ error = xwimp_force_redraw(dialog_url_complete,
+ 0, -(url_complete_matches_selection + 1) * 44,
+ 65536, -url_complete_matches_selection * 44);
+ if (error) {
+ LOG(("xwimp_force_redraw: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ if (old_selection == -1) {
+ free(url_complete_original_url);
+ url_complete_original_url = malloc(strlen(url) + 1);
+ if (!url_complete_original_url)
+ return false;
+ strcpy(url_complete_original_url, url);
+ }
+ if (url_complete_matches_selection == -1) {
+ ro_gui_set_icon_string(g->toolbar->toolbar_handle,
+ ICON_TOOLBAR_URL,
+ url_complete_original_url);
+ } else {
+ ro_gui_set_icon_string(g->toolbar->toolbar_handle,
+ ICON_TOOLBAR_URL,
+ url_complete_matches[url_complete_matches_selection]);
+ }
+ url_complete_keypress_selection = url_complete_matches_selection;
+
+ /* auto-scroll */
+ state.w = dialog_url_complete;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return true;
+ }
+ if (state.yscroll < -(url_complete_matches_selection * 44))
+ state.yscroll = -(url_complete_matches_selection * 44);
+ height = state.visible.y1 - state.visible.y0;
+ if (state.yscroll - height > -((url_complete_matches_selection + 1) * 44))
+ state.yscroll = -((url_complete_matches_selection + 1) * 44) + height;
+ error = xwimp_open_window((wimp_open *)(&state));
+ if (error) {
+ LOG(("xwimp_open_window: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return true;
+ }
+
+ return true;
+}
+
+
+/**
+ * Move and resize the url completion window to match the toolbar.
+ *
+ * \param g the gui_window to update
+ * \param open the wimp_open request (updated on exit)
+ */
+void ro_gui_url_complete_resize(struct gui_window *g, wimp_open *open) {
+ os_box extent = { 0, 0, 0, 0 };
+ wimp_icon_state url_state;
+ wimp_window_state toolbar_state;
+ wimp_window_state state;
+ os_error *error;
+ int lines;
+ int scroll_v = 0;
+
+ /* if we the URL completion isn't for our window, or there is no toolbar,
+ * or there is no URL bar shown, or there are no URL matches, close it */
+ if ((open->w != url_complete_parent) || (!g->toolbar) ||
+ (!g->toolbar->display_url) ||
+ (url_complete_matches_available == 0)) {
+ ro_gui_url_complete_close(NULL, 0);
+ return;
+ }
+
+ /* get our current auto-complete window state for the scroll values */
+ state.w = dialog_url_complete;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+ if (url_complete_matches_reset)
+ state.yscroll = 0;
+
+ /* move the window to the correct position */
+ toolbar_state.w = g->toolbar->toolbar_handle;
+ error = xwimp_get_window_state(&toolbar_state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+ url_state.w = g->toolbar->toolbar_handle;
+ url_state.i = ICON_TOOLBAR_URL;
+ error = xwimp_get_icon_state(&url_state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+ lines = url_complete_matches_available;
+ extent.y0 = -(lines * 44);
+ extent.x1 = 65536;
+ error = xwimp_set_extent(dialog_url_complete, &extent);
+ if (error) {
+ LOG(("xwimp_set_extent: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+ state.next = open->next;
+ state.flags &= ~wimp_WINDOW_VSCROLL;
+ state.flags &= ~(4095 << 16); /* clear bits 16-27 */
+ if (lines > MAXIMUM_VISIBLE_LINES) {
+ lines = MAXIMUM_VISIBLE_LINES;
+ scroll_v = ro_get_vscroll_width(NULL) - 2;
+ state.flags |= wimp_WINDOW_VSCROLL;
+ }
+ state.visible.x0 = open->visible.x0 + 2 + url_state.icon.extent.x0;
+ state.visible.x1 = open->visible.x0 - 2 + url_state.icon.extent.x1 - scroll_v;
+ state.visible.y1 = open->visible.y1 - url_state.icon.extent.y1 + 2;
+ state.visible.y0 = state.visible.y1 - (lines * 44);
+ if (state.visible.x1 > toolbar_state.visible.x1)
+ state.visible.x1 = toolbar_state.visible.x1;
+ if (state.visible.x1 - state.visible.x0 - scroll_v < 0) {
+ error = xwimp_close_window(dialog_url_complete);
+ if (error) {
+ LOG(("xwimp_close_window: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ } else {
+ error = xwimp_open_window_nested_with_flags(&state, (wimp_w)-1, 0);
+ if (error) {
+ LOG(("xwimp_open_window: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+ open->next = dialog_url_complete;
+ }
+}
+
+
+/**
+ * Try to close the current url completion window
+ *
+ * \param g the gui_window the user clicked on (or NULL to forcibly close)
+ * \param i the icon the user clicked on to prompt the close
+ * \return whether the window was closed
+ */
+bool ro_gui_url_complete_close(struct gui_window *g, wimp_i i) {
+ os_error *error;
+
+ if ((g && (i == ICON_TOOLBAR_URL) && (g->window == url_complete_parent)))
+ return false;
+
+ free(url_complete_matches);
+ free(url_complete_matched_string);
+ free(url_complete_original_url);
+ url_complete_matches = NULL;
+ url_complete_matched_string = NULL;
+ url_complete_original_url = NULL;
+ url_complete_matches_allocated = 0;
+ url_complete_matches_available = 0;
+ url_complete_keypress_selection = -1;
+ url_complete_matches_selection = -1;
+ url_complete_parent = 0;
+
+ error = xwimp_close_window(dialog_url_complete);
+ if (error) {
+ LOG(("xwimp_close_window: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ return true;
+}
+
+
+/**
+ * Redraws a section of the URL completion window
+ *
+ * \param redraw the area to redraw
+ * \param tree the tree to redraw
+ */
+void ro_gui_url_complete_redraw(wimp_draw *redraw) {
+ osbool more;
+ os_error *error;
+ int clip_y0, clip_y1, origin_y;
+ int first_line, last_line, line;
+
+ /* initialise our icon */
+ url_complete_icon.flags = wimp_ICON_INDIRECTED | wimp_ICON_VCENTRED |
+ wimp_ICON_TEXT | wimp_ICON_FILLED |
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT);
+ url_complete_icon.extent.x0 = 0;
+ url_complete_icon.extent.x1 = 16384;
+ url_complete_icon.data.indirected_text.validation = url_complete_icon_null;
+
+ /* redraw */
+ more = wimp_redraw_window(redraw);
+ while (more) {
+ origin_y = redraw->box.y1 - redraw->yscroll;
+ clip_y0 = redraw->clip.y0 - origin_y;
+ clip_y1 = redraw->clip.y1 - origin_y;
+
+ first_line = (-clip_y1) / 44;
+ last_line = (-clip_y0 + 43) / 44;
+
+ for (line = first_line; line < last_line; line++) {
+ if (line == url_complete_matches_selection)
+ url_complete_icon.flags |= wimp_ICON_SELECTED;
+ else
+ url_complete_icon.flags &= ~wimp_ICON_SELECTED;
+ url_complete_icon.extent.y1 = -line * 44;
+ url_complete_icon.extent.y0 = -(line + 1) * 44;
+ url_complete_icon.data.indirected_text.text =
+ url_complete_matches[line];
+ url_complete_icon.data.indirected_text.size =
+ strlen(url_complete_matches[line]);
+ error = xwimp_plot_icon(&url_complete_icon);
+ if (error) {
+ LOG(("xwimp_plot_icon: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ }
+ more = wimp_get_rectangle(redraw);
+ }
+}
+
+
+/**
+ * Handle mouse movements/clicks over the URL completion window.
+ */
+void ro_gui_url_complete_mouse_at(wimp_pointer *pointer) {
+ wimp_window_state state;
+ os_error *error;
+ int selection, old_selection;
+ struct gui_window *g;
+ char *url;
+
+ if ((mouse_x == pointer->pos.x) && (mouse_y == pointer->pos.y) &&
+ (pointer->buttons == 0))
+ return;
+ mouse_x = pointer->pos.x;
+ mouse_y = pointer->pos.y;
+
+ state.w = dialog_url_complete;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+ selection = (state.visible.y1 - pointer->pos.y - state.yscroll) / 44;
+ if (selection != url_complete_matches_selection) {
+ if (url_complete_matches_selection == -1) {
+ g = ro_gui_window_lookup(url_complete_parent);
+ if (!g)
+ return;
+ url = ro_gui_get_icon_string(g->toolbar->toolbar_handle,
+ ICON_TOOLBAR_URL);
+ free(url_complete_original_url);
+ url_complete_original_url = malloc(strlen(url) + 1);
+ if (!url_complete_original_url)
+ return;
+ strcpy(url_complete_original_url, url);
+ }
+ old_selection = url_complete_matches_selection;
+ url_complete_matches_selection = selection;
+ error = xwimp_force_redraw(dialog_url_complete,
+ 0, -(old_selection + 1) * 44, 65536, -old_selection * 44);
+ if (error) {
+ LOG(("xwimp_force_redraw: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ error = xwimp_force_redraw(dialog_url_complete,
+ 0, -(url_complete_matches_selection + 1) * 44,
+ 65536, -url_complete_matches_selection * 44);
+ if (error) {
+ LOG(("xwimp_force_redraw: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ }
+
+ /* clicks */
+ if ((pointer->buttons == wimp_CLICK_SELECT) ||
+ (pointer->buttons == wimp_CLICK_ADJUST)) {
+ g = ro_gui_window_lookup(url_complete_parent);
+ if (!g)
+ return;
+ ro_gui_set_icon_string(g->toolbar->toolbar_handle,
+ ICON_TOOLBAR_URL,
+ url_complete_matches[url_complete_matches_selection]);
+ browser_window_go(g->bw,
+ url_complete_matches[url_complete_matches_selection],
+ 0);
+ ro_gui_url_complete_close(NULL, 0);
+ }
+
+}
+
+
+/**
+ * Dumps all matching URLs to stderr.
+ */
+void url_complete_dump_matches(const char *url) {
+ char *match_url;
+ struct url_data *reference = NULL;
+ char *output;
+
+ match_url = url_store_match_string(url);
+ if (!match_url)
+ return;
+
+ fprintf(stderr, "\nDumping matches for '%s' ('%s'):\n", url, match_url);
+ while ((output = url_store_match(match_url, &reference))) {
+ fprintf(stderr, " - ");
+ fprintf(stderr, output);
+ fprintf(stderr, "\n");
+ }
+ fprintf(stderr, "\nEnd of matches.\n\n");
+ free(match_url);
+}
diff --git a/riscos/url_complete.h b/riscos/url_complete.h
new file mode 100644
index 000000000..fa70efc14
--- /dev/null
+++ b/riscos/url_complete.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2005 Richard Wilson <info@tinct.net>
+ */
+
+/** \file
+ * Central repository for URL data (interface).
+ */
+
+#ifndef _NETSURF_RISCOS_URLCOMPLETE_H_
+#define _NETSURF_RISCOS_URLCOMPLETE_H_
+
+#include <stdbool.h>
+#include "netsurf/riscos/gui.h"
+
+bool ro_gui_url_complete_keypress(struct gui_window *g, int key);
+void ro_gui_url_complete_resize(struct gui_window *g, wimp_open *open);
+bool ro_gui_url_complete_close(struct gui_window *g, wimp_i i);
+void ro_gui_url_complete_redraw(wimp_draw *redraw);
+void ro_gui_url_complete_mouse_at(wimp_pointer *pointer);
+
+void url_complete_dump_matches(const char *url);
+
+#endif
diff --git a/riscos/window.c b/riscos/window.c
index 87d63d86a..50c103739 100644
--- a/riscos/window.c
+++ b/riscos/window.c
@@ -25,6 +25,7 @@
#include "oslib/wimpspriteop.h"
#include "netsurf/utils/config.h"
#include "netsurf/content/content.h"
+#include "netsurf/content/url_store.h"
#include "netsurf/css/css.h"
#include "netsurf/desktop/plotters.h"
#include "netsurf/render/box.h"
@@ -35,6 +36,7 @@
#include "netsurf/riscos/theme.h"
#include "netsurf/riscos/thumbnail.h"
#include "netsurf/riscos/treeview.h"
+#include "netsurf/riscos/url_complete.h"
#include "netsurf/riscos/wimp.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/url.h"
@@ -929,6 +931,9 @@ void ro_gui_window_open(struct gui_window *g, wimp_open *open)
}
+ /* first resize stops any flickering by making the URL window on top */
+ ro_gui_url_complete_resize(g, open);
+
error = xwimp_open_window(open);
if (error) {
LOG(("xwimp_open_window: 0x%x: %s",
@@ -957,8 +962,11 @@ void ro_gui_window_open(struct gui_window *g, wimp_open *open)
g->old_height = height;
}
- if (g->toolbar)
+ if (g->toolbar) {
ro_gui_theme_process_toolbar(g->toolbar, -1);
+ /* second resize updates to the new URL bar width */
+ ro_gui_url_complete_resize(g, open);
+ }
}
@@ -1090,6 +1098,9 @@ void ro_gui_toolbar_click(struct gui_window *g, wimp_pointer *pointer)
/* Store the toolbar
*/
current_toolbar = g->toolbar;
+
+ /* try to close url-completion */
+ ro_gui_url_complete_close(g, pointer->i);
/* Handle Menu clicks
*/
@@ -1232,6 +1243,9 @@ void ro_gui_window_click(struct gui_window *g, wimp_pointer *pointer)
assert(g);
+ /* try to close url-completion */
+ ro_gui_url_complete_close(g, pointer->i);
+
xosbyte1(osbyte_SCAN_KEYBOARD, 0 ^ 0x80, 0, &shift);
state.w = pointer->w;
@@ -1486,6 +1500,10 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar)
ro_gui_view_source(content);
return true;
+ case wimp_KEY_CONTROL + wimp_KEY_F8: /* Dump url_store. */
+ url_store_dump();
+ return true;
+
case wimp_KEY_F9: /* Dump content for debugging. */
switch (content->type) {
case CONTENT_HTML:
@@ -1513,6 +1531,7 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar)
case wimp_KEY_RETURN:
if (!toolbar)
break;
+ ro_gui_url_complete_close(NULL, 0);
toolbar_url = ro_gui_get_icon_string(g->toolbar->toolbar_handle,
ICON_TOOLBAR_URL);
res = url_normalize(toolbar_url, &url);
@@ -1524,6 +1543,8 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar)
return true;
case wimp_KEY_ESCAPE:
+ if (ro_gui_url_complete_close(0, 0))
+ return true;
browser_window_stop(g->bw);
return true;
@@ -1569,9 +1590,12 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar)
case wimp_KEY_PAGE_DOWN:
case wimp_KEY_CONTROL | wimp_KEY_UP:
case wimp_KEY_CONTROL | wimp_KEY_DOWN:
+ if (toolbar)
+ return ro_gui_url_complete_keypress(g, key);
break;
-
default:
+ if (toolbar)
+ return ro_gui_url_complete_keypress(g, key);
return false;
}
@@ -1601,7 +1625,7 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar)
break;
}
- wimp_open_window((wimp_open *) &state);
+ wimp_open_window((wimp_open *) &state);
return true;
}
diff --git a/utils/url.c b/utils/url.c
index 5eb7c97b9..23273a848 100644
--- a/utils/url.c
+++ b/utils/url.c
@@ -77,7 +77,7 @@ url_func_result url_normalize(const char *url, char **result)
if (match[1].rm_so == -1) {
/* scheme missing: add http:// and reparse */
- LOG(("scheme missing: using http"));
+/* LOG(("scheme missing: using http"));*/
if ((*result = malloc(len + 13)) == NULL) {
LOG(("malloc failed"));
return URL_FUNC_NOMEM;