From 4b2101ba6ab62ae26d82cc8b86e0e61e9c007156 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 19 Jun 2014 18:27:24 +0100 Subject: clean up the fetcher factory and improve its API --- amiga/Makefile.target | 2 +- beos/fetch_rsrc.cpp | 21 +-- content/fetch.c | 313 ++++++++++++++++++++++---------------------- content/fetch.h | 65 +-------- content/fetchers.h | 119 +++++++++++++++++ content/fetchers/about.c | 25 ++-- content/fetchers/about.h | 2 +- content/fetchers/curl.c | 34 ++--- content/fetchers/data.c | 25 ++-- content/fetchers/data.h | 2 +- content/fetchers/file.c | 25 ++-- content/fetchers/file.h | 2 +- content/fetchers/resource.c | 35 ++--- content/fetchers/resource.h | 2 +- content/hlcache.c | 9 -- content/hlcache.h | 8 -- content/llcache.c | 8 -- content/llcache.h | 7 - desktop/netsurf.c | 8 +- render/html_css_fetcher.c | 21 +-- 20 files changed, 381 insertions(+), 352 deletions(-) create mode 100644 content/fetchers.h diff --git a/amiga/Makefile.target b/amiga/Makefile.target index c90027465..ea765af36 100644 --- a/amiga/Makefile.target +++ b/amiga/Makefile.target @@ -2,7 +2,7 @@ # Amiga target setup # ---------------------------------------------------------------------------- -CFLAGS += -std=c99 -Dnsamiga -DFETCHER_CURLL_SCHEDULED +CFLAGS += -std=c99 -Dnsamiga ifneq ($(SUBTARGET),os3) CFLAGS += -U__STRICT_ANSI__ -D__USE_INLINE__ -D__USE_BASETYPE__ diff --git a/beos/fetch_rsrc.cpp b/beos/fetch_rsrc.cpp index 887be7960..9461f5c79 100644 --- a/beos/fetch_rsrc.cpp +++ b/beos/fetch_rsrc.cpp @@ -33,6 +33,7 @@ extern "C" { #include "utils/config.h" #include "content/fetch.h" +#include "content/fetchers.h" #include "content/urldb.h" #include "desktop/netsurf.h" #include "utils/nsoption.h" @@ -358,6 +359,16 @@ void fetch_rsrc_register(void) { lwc_string *scheme; int err; + const struct fetcher_operation_table fetcher_ops_rsrc = { + fetch_rsrc_initialise, + fetch_rsrc_can_fetch, + fetch_rsrc_setup, + fetch_rsrc_start, + fetch_rsrc_abort, + fetch_rsrc_free, + fetch_rsrc_poll, + fetch_rsrc_finalise + }; err = find_app_resources(); @@ -371,15 +382,7 @@ void fetch_rsrc_register(void) "(couldn't intern \"rsrc\")."); } - fetch_add_fetcher(scheme, - fetch_rsrc_initialise, - fetch_rsrc_can_fetch, - fetch_rsrc_setup, - fetch_rsrc_start, - fetch_rsrc_abort, - fetch_rsrc_free, - fetch_rsrc_poll, - fetch_rsrc_finalise); + fetcher_add(scheme, &fetcher_ops_rsrc); } void fetch_rsrc_unregister(void) diff --git a/content/fetch.c b/content/fetch.c index 4736670ff..13c7c6542 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -19,12 +19,15 @@ */ /** \file - * Fetching of data from a URL (implementation). + * Implementation of fetching of data from a URL. + * + * The implementation is the fetch factory and the generic operations + * around the fetcher specific methods. * * Active fetches are held in the circular linked list ::fetch_ring. There may * be at most ::option_max_fetchers_per_host active requests per Host: header. * There may be at most ::option_max_fetchers active requests overall. Inactive - * fetchers are stored in the ::queue_ring waiting for use. + * fetches are stored in the ::queue_ring waiting for use. */ #include @@ -33,17 +36,9 @@ #include #include #include - #include #include "utils/config.h" -#include "content/fetch.h" -#include "content/fetchers/resource.h" -#include "content/fetchers/about.h" -#include "content/fetchers/curl.h" -#include "content/fetchers/data.h" -#include "content/fetchers/file.h" -#include "content/urldb.h" #include "desktop/netsurf.h" #include "utils/corestrings.h" #include "utils/nsoption.h" @@ -53,27 +48,34 @@ #include "utils/utils.h" #include "utils/ring.h" +#include "content/fetch.h" +#include "content/fetchers.h" +#include "content/fetchers/resource.h" +#include "content/fetchers/about.h" +#include "content/fetchers/curl.h" +#include "content/fetchers/data.h" +#include "content/fetchers/file.h" +#include "content/urldb.h" + /* Define this to turn on verbose fetch logging */ #undef DEBUG_FETCH_VERBOSE -bool fetch_active; /**< Fetches in progress, please call fetch_poll(). */ +/** The maximum number of fetchers that can be added */ +#define MAX_FETCHERS 8 -/** Information about a fetcher for a given scheme. */ +bool fetch_active; /**< Fetches in progress, please call fetch_poll(). */ + +/** + * Information about a fetcher for a given scheme. + */ typedef struct scheme_fetcher_s { - lwc_string *scheme_name; /**< The scheme. */ - fetcher_can_fetch can_fetch; /**< Ensure an URL can be fetched. */ - fetcher_setup_fetch setup_fetch; /**< Set up a fetch. */ - fetcher_start_fetch start_fetch; /**< Start a fetch. */ - fetcher_abort_fetch abort_fetch; /**< Abort a fetch. */ - fetcher_free_fetch free_fetch; /**< Free a fetch. */ - fetcher_poll_fetcher poll_fetcher; /**< Poll this fetcher. */ - fetcher_finalise finaliser; /**< Clean up this fetcher. */ - int refcount; /**< When zero, clean up the fetcher. */ - struct scheme_fetcher_s *next_fetcher; /**< Next fetcher in the list. */ - struct scheme_fetcher_s *prev_fetcher; /**< Prev fetcher in the list. */ + lwc_string *scheme; /**< The scheme. */ + + struct fetcher_operation_table ops; /**< The fetchers operations. */ + int refcount; /**< When zero the fetcher is no longer in use. */ } scheme_fetcher; -static scheme_fetcher *fetchers = NULL; +static scheme_fetcher fetchers[MAX_FETCHERS]; /** Information for a single fetch. */ struct fetch { @@ -85,43 +87,53 @@ struct fetch { void *p; /**< Private data for callback. */ lwc_string *host; /**< Host part of URL, interned */ long http_code; /**< HTTP response code, or 0. */ - scheme_fetcher *ops; /**< Fetcher operations for this fetch, - NULL if not set. */ + int fetcherd; /**< Fetcher descriptor for this fetch */ void *fetcher_handle; /**< The handle for the fetcher. */ bool fetch_is_active; /**< This fetch is active. */ struct fetch *r_prev; /**< Previous active fetch in ::fetch_ring. */ struct fetch *r_next; /**< Next active fetch in ::fetch_ring. */ }; -static struct fetch *fetch_ring = 0; /**< Ring of active fetches. */ -static struct fetch *queue_ring = 0; /**< Ring of queued fetches */ - -#define fetch_ref_fetcher(F) F->refcount++ +static struct fetch *fetch_ring = NULL; /**< Ring of active fetches. */ +static struct fetch *queue_ring = NULL; /**< Ring of queued fetches */ /****************************************************************************** * fetch internals * ******************************************************************************/ -static void fetch_unref_fetcher(scheme_fetcher *fetcher) +static inline void fetch_ref_fetcher(int fetcherd) { - if (--fetcher->refcount == 0) { - fetcher->finaliser(fetcher->scheme_name); - lwc_string_unref(fetcher->scheme_name); - if (fetcher == fetchers) { - fetchers = fetcher->next_fetcher; - if (fetchers) - fetchers->prev_fetcher = NULL; - } else { - fetcher->prev_fetcher->next_fetcher = - fetcher->next_fetcher; - if (fetcher->next_fetcher != NULL) - fetcher->next_fetcher->prev_fetcher = - fetcher->prev_fetcher; - } - free(fetcher); + fetchers[fetcherd].refcount++; +} + +static inline void fetch_unref_fetcher(int fetcherd) +{ + fetchers[fetcherd].refcount--; + if (fetchers[fetcherd].refcount == 0) { + fetchers[fetcherd].ops.finalise(fetchers[fetcherd].scheme); + lwc_string_unref(fetchers[fetcherd].scheme); } } +/** + * Find a suitable fetcher for a scheme. + */ +static int get_fetcher_for_scheme(lwc_string *scheme) +{ + int fetcherd; + bool match; + + for (fetcherd = 0; fetcherd < MAX_FETCHERS; fetcherd++) { + if ((fetchers[fetcherd].refcount > 0) && + (lwc_string_isequal(fetchers[fetcherd].scheme, + scheme, &match) == lwc_error_ok) && + (match == true)) { + return fetcherd; + } + } + return -1; +} + /** * Dispatch a single job */ @@ -132,7 +144,7 @@ static bool fetch_dispatch_job(struct fetch *fetch) LOG(("Attempting to start fetch %p, fetcher %p, url %s", fetch, fetch->fetcher_handle, nsurl_access(fetch->url))); #endif - if (!fetch->ops->start_fetch(fetch->fetcher_handle)) { + if (!fetchers[fetch->fetcherd].ops.start(fetch->fetcher_handle)) { RING_INSERT(queue_ring, fetch); /* Put it back on the end of the queue */ return false; } else { @@ -236,7 +248,7 @@ static void fetch_dispatch_jobs(void) ******************************************************************************/ /* exported interface documented in content/fetch.h */ -nserror fetch_init(void) +nserror fetcher_init(void) { fetch_curl_register(); fetch_data_register(); @@ -249,76 +261,81 @@ nserror fetch_init(void) return NSERROR_OK; } -/* exported interface documented in content/fetch.h */ -void fetch_quit(void) +/* exported interface documented in content/fetchers.h */ +void fetcher_quit(void) { - while (fetchers != NULL) { - if (fetchers->refcount != 1) { - LOG(("Fetcher for scheme %s still active?!", - lwc_string_data(fetchers->scheme_name))); - /* We shouldn't do this, but... */ - fetchers->refcount = 1; + int fetcherd; /* fetcher index */ + for (fetcherd = 0; fetcherd < MAX_FETCHERS; fetcherd++) { + if (fetchers[fetcherd].refcount > 0) { + /* assert if the fetcher is active at quit */ + assert(fetchers[fetcherd].refcount == 1); + + fetch_unref_fetcher(fetcherd); } - fetch_unref_fetcher(fetchers); } } -/* exported interface documented in content/fetch.h */ -bool fetch_add_fetcher(lwc_string *scheme, - fetcher_initialise initialiser, - fetcher_can_fetch can_fetch, - fetcher_setup_fetch setup_fetch, - fetcher_start_fetch start_fetch, - fetcher_abort_fetch abort_fetch, - fetcher_free_fetch free_fetch, - fetcher_poll_fetcher poll_fetcher, - fetcher_finalise finaliser) +/* exported interface documented in content/fetchers.h */ +nserror +fetcher_add(lwc_string *scheme, const struct fetcher_operation_table *ops) { - scheme_fetcher *new_fetcher; - if (!initialiser(scheme)) - return false; - new_fetcher = malloc(sizeof(scheme_fetcher)); - if (new_fetcher == NULL) { - finaliser(scheme); - return false; + int fetcherd; + + /* find unused fetcher descriptor */ + for (fetcherd = 0; fetcherd < MAX_FETCHERS; fetcherd++) { + if (fetchers[fetcherd].refcount == 0) { + break; + } } - new_fetcher->scheme_name = scheme; - new_fetcher->refcount = 0; - new_fetcher->can_fetch = can_fetch; - new_fetcher->setup_fetch = setup_fetch; - new_fetcher->start_fetch = start_fetch; - new_fetcher->abort_fetch = abort_fetch; - new_fetcher->free_fetch = free_fetch; - new_fetcher->poll_fetcher = poll_fetcher; - new_fetcher->finaliser = finaliser; - new_fetcher->next_fetcher = fetchers; - fetchers = new_fetcher; - fetch_ref_fetcher(new_fetcher); - - return true; + if (fetcherd == MAX_FETCHERS) { + return NSERROR_INIT_FAILED; + } + + if (!ops->initialise(scheme)) { + return NSERROR_INIT_FAILED; + } + + fetchers[fetcherd].scheme = scheme; + fetchers[fetcherd].ops = *ops; + + fetch_ref_fetcher(fetcherd); + + return NSERROR_OK; } /* exported interface documented in content/fetch.h */ -struct fetch * fetch_start(nsurl *url, nsurl *referer, - fetch_callback callback, - void *p, bool only_2xx, const char *post_urlenc, - const struct fetch_multipart_data *post_multipart, - bool verifiable, bool downgrade_tls, - const char *headers[]) +struct fetch * +fetch_start(nsurl *url, + nsurl *referer, + fetch_callback callback, + void *p, + bool only_2xx, + const char *post_urlenc, + const struct fetch_multipart_data *post_multipart, + bool verifiable, + bool downgrade_tls, + const char *headers[]) { struct fetch *fetch; - scheme_fetcher *fetcher = fetchers; lwc_string *scheme; bool match; fetch = malloc(sizeof (*fetch)); - if (fetch == NULL) + if (fetch == NULL) { return NULL; + } /* The URL we're fetching must have a scheme */ scheme = nsurl_get_component(url, NSURL_SCHEME); assert(scheme != NULL); + /* try and obtain a fetcher for this scheme */ + fetch->fetcherd = get_fetcher_for_scheme(scheme); + if (fetch->fetcherd == -1) { + lwc_string_unref(scheme); + return NULL; + } + #ifdef DEBUG_FETCH_VERBOSE LOG(("fetch %p, url '%s'", fetch, nsurl_access(url))); #endif @@ -334,7 +351,6 @@ struct fetch * fetch_start(nsurl *url, nsurl *referer, fetch->referer = NULL; fetch->send_referer = false; fetch->fetcher_handle = NULL; - fetch->ops = NULL; fetch->fetch_is_active = false; fetch->host = nsurl_get_component(url, NSURL_HOST); @@ -378,53 +394,38 @@ struct fetch * fetch_start(nsurl *url, nsurl *referer, lwc_string_unref(ref_scheme); } - /* Pick the scheme ops */ - while (fetcher) { - if ((lwc_string_isequal(fetcher->scheme_name, scheme, - &match) == lwc_error_ok) && (match == true)) { - fetch->ops = fetcher; - break; - } - fetcher = fetcher->next_fetcher; - } + /* these aren't needed past here */ + lwc_string_unref(scheme); - if (fetch->ops == NULL) - goto failed; + /* try and set up the fetch */ + fetch->fetcher_handle = fetchers[fetch->fetcherd].ops.setup(fetch, url, + only_2xx, downgrade_tls, + post_urlenc, post_multipart, + headers); + if (fetch->fetcher_handle == NULL) { - /* Got a scheme fetcher, try and set up the fetch */ - fetch->fetcher_handle = fetch->ops->setup_fetch(fetch, url, - only_2xx, downgrade_tls, - post_urlenc, post_multipart, - headers); + if (fetch->host != NULL) + lwc_string_unref(fetch->host); - if (fetch->fetcher_handle == NULL) - goto failed; + if (fetch->url != NULL) + nsurl_unref(fetch->url); - /* Rah, got it, so ref the fetcher. */ - fetch_ref_fetcher(fetch->ops); + if (fetch->referer != NULL) + nsurl_unref(fetch->referer); - /* these aren't needed past here */ - lwc_string_unref(scheme); + free(fetch); + + return NULL; + } + + /* Rah, got it, so ref the fetcher. */ + fetch_ref_fetcher(fetch->fetcherd); /* Dump us in the queue and ask the queue to run. */ RING_INSERT(queue_ring, fetch); fetch_dispatch_jobs(); return fetch; - -failed: - lwc_string_unref(scheme); - - if (fetch->host != NULL) - lwc_string_unref(fetch->host); - if (fetch->url != NULL) - nsurl_unref(fetch->url); - if (fetch->referer != NULL) - nsurl_unref(fetch->referer); - - free(fetch); - - return NULL; } /* exported interface documented in content/fetch.h */ @@ -435,7 +436,7 @@ void fetch_abort(struct fetch *f) LOG(("fetch %p, fetcher %p, url '%s'", f, f->fetcher_handle, nsurl_access(f->url))); #endif - f->ops->abort_fetch(f->fetcher_handle); + fetchers[f->fetcherd].ops.abort(f->fetcher_handle); } /* exported interface documented in content/fetch.h */ @@ -444,8 +445,10 @@ void fetch_free(struct fetch *f) #ifdef DEBUG_FETCH_VERBOSE LOG(("Freeing fetch %p, fetcher %p", f, f->fetcher_handle)); #endif - f->ops->free_fetch(f->fetcher_handle); - fetch_unref_fetcher(f->ops); + fetchers[f->fetcherd].ops.free(f->fetcher_handle); + + fetch_unref_fetcher(f->fetcherd); + nsurl_unref(f->url); if (f->referer != NULL) nsurl_unref(f->referer); @@ -454,45 +457,37 @@ void fetch_free(struct fetch *f) free(f); } -/* exported interface documented in content/fetch.h */ -void fetch_poll(void) +/* exported interface documented in content/fetchers.h */ +void fetcher_poll(void) { - scheme_fetcher *fetcher = fetchers; - scheme_fetcher *next_fetcher; + int fetcherd; fetch_dispatch_jobs(); - if (!fetch_active) - return; /* No point polling, there's no fetch active. */ - while (fetcher != NULL) { - next_fetcher = fetcher->next_fetcher; - if (fetcher->poll_fetcher != NULL) { - /* LOG(("Polling fetcher for %s", - lwc_string_data(fetcher->scheme_name))); */ - fetcher->poll_fetcher(fetcher->scheme_name); + if (fetch_active) { + for (fetcherd = 0; fetcherd < MAX_FETCHERS; fetcherd++) { + if (fetchers[fetcherd].refcount > 0) { + /* fetcher present */ + fetchers[fetcherd].ops.poll(fetchers[fetcherd].scheme); + } } - fetcher = next_fetcher; } } /* exported interface documented in content/fetch.h */ bool fetch_can_fetch(const nsurl *url) { - scheme_fetcher *fetcher = fetchers; - bool match; lwc_string *scheme = nsurl_get_component(url, NSURL_SCHEME); + int fetcherd; - while (fetcher != NULL) { - if (lwc_string_isequal(fetcher->scheme_name, scheme, &match) == lwc_error_ok && match == true) { - break; - } + fetcherd = get_fetcher_for_scheme(scheme); + lwc_string_unref(scheme); - fetcher = fetcher->next_fetcher; + if (fetcherd == -1) { + return false; } - lwc_string_unref(scheme); - - return fetcher == NULL ? false : fetcher->can_fetch(url); + return fetchers[fetcherd].ops.acceptable(url); } /* exported interface documented in content/fetch.h */ diff --git a/content/fetch.h b/content/fetch.h index f20b4f2d2..37539ef2b 100644 --- a/content/fetch.h +++ b/content/fetch.h @@ -25,8 +25,6 @@ #include -#include - #include "utils/config.h" #include "utils/nsurl.h" @@ -95,17 +93,8 @@ struct ssl_cert_info { int cert_type; /**< Certificate type */ }; -extern bool fetch_active; - typedef void (*fetch_callback)(const fetch_msg *msg, void *p); -/** - * Initialise the fetcher. - * - * @return NSERROR_OK or error code - */ -nserror fetch_init(void); - /** * Start fetching data for the given URL. * @@ -137,19 +126,6 @@ struct fetch *fetch_start(nsurl *url, nsurl *referer, */ void fetch_abort(struct fetch *f); -/** - * Do some work on current fetches. - * - * Must be called regularly to make progress on fetches. - */ -void fetch_poll(void); - -/** - * Clean up for quit. - * - * Must be called before exiting. - */ -void fetch_quit(void); /** * Check if a URL's scheme can be fetched. @@ -162,9 +138,7 @@ bool fetch_can_fetch(const nsurl *url); /** * Change the callback function for a fetch. */ -void fetch_change_callback(struct fetch *fetch, - fetch_callback callback, - void *p); +void fetch_change_callback(struct fetch *fetch, fetch_callback callback, void *p); /** * Get the HTTP response code. @@ -225,41 +199,4 @@ const char *fetch_get_referer_to_send(struct fetch *fetch); void fetch_set_cookie(struct fetch *fetch, const char *data); -/* API for fetchers themselves */ - -typedef bool (*fetcher_initialise)(lwc_string *scheme); -typedef bool (*fetcher_can_fetch)(const nsurl *url); -typedef void *(*fetcher_setup_fetch)(struct fetch *parent_fetch, nsurl *url, - bool only_2xx, bool downgrade_tls, const char *post_urlenc, - const struct fetch_multipart_data *post_multipart, - const char **headers); -typedef bool (*fetcher_start_fetch)(void *fetch); -typedef void (*fetcher_abort_fetch)(void *fetch); -typedef void (*fetcher_free_fetch)(void *fetch); -typedef void (*fetcher_poll_fetcher)(lwc_string *scheme); -typedef void (*fetcher_finalise)(lwc_string *scheme); - -/** Register a fetcher for a scheme - * - * \param scheme scheme fetcher is for (caller relinquishes ownership) - * \param initialiser fetcher initialiser - * \param can_fetch fetcher can fetch function - * \param setup_fetch fetcher fetch setup function - * \param start_fetch fetcher fetch start function - * \param abort_fetch fetcher fetch abort function - * \param free_fetch fetcher fetch free function - * \param poll_fetcher fetcher poll function - * \param finaliser fetcher finaliser - * \return true iff success - */ -bool fetch_add_fetcher(lwc_string *scheme, - fetcher_initialise initialiser, - fetcher_can_fetch can_fetch, - fetcher_setup_fetch setup_fetch, - fetcher_start_fetch start_fetch, - fetcher_abort_fetch abort_fetch, - fetcher_free_fetch free_fetch, - fetcher_poll_fetcher poll_fetcher, - fetcher_finalise finaliser); - #endif diff --git a/content/fetchers.h b/content/fetchers.h new file mode 100644 index 000000000..6ca52245c --- /dev/null +++ b/content/fetchers.h @@ -0,0 +1,119 @@ +/* + * Copyright 2014 Vincent Sanders + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file content/fetchers.h + * Interface for fetchers factory. + */ + +#ifndef _NETSURF_DESKTOP_FETCHERS_H_ +#define _NETSURF_DESKTOP_FETCHERS_H_ + +#include + +struct nsurl; +struct fetch_multipart_data; +struct fetch; + +extern bool fetch_active; + +/** + * Fetcher operations API + * + * These are the operations a fetcher must implement. + */ +struct fetcher_operation_table { + /** + * The initialiser for the fetcher. + * + * Called once to initialise the fetcher. + */ + bool (*initialise)(lwc_string *scheme); + + /** + * can this fetcher accept a url. + * + * \param url the URL to check + * \return true if the fetcher can handle the url else false. + */ + bool (*acceptable)(const struct nsurl *url); + + /** + * Setup a fetch + */ + void *(*setup)(struct fetch *parent_fetch, struct nsurl *url, + bool only_2xx, bool downgrade_tls, const char *post_urlenc, + const struct fetch_multipart_data *post_multipart, + const char **headers); + + /** + * start a fetch. + */ + bool (*start)(void *fetch); + + /** + * abort a fetch. + */ + void (*abort)(void *fetch); + + /** + * free a fetch allocated through the setup method. + */ + void (*free)(void *fetch); + + /** + * poll a fetcher to let it make progress. + */ + void (*poll)(lwc_string *scheme); + + /** + * finalise the fetcher. + */ + void (*finalise)(lwc_string *scheme); +}; + +/** + * Register a fetcher for a scheme + * + * \param scheme The scheme fetcher is for (caller relinquishes ownership) + * \param ops The operations for the fetcher. + * \return NSERROR_OK or appropriate error code. + */ +nserror fetcher_add(lwc_string *scheme, const struct fetcher_operation_table *ops); + +/** + * Initialise the fetchers. + * + * @return NSERROR_OK or error code + */ +nserror fetcher_init(void); + +/** + * Clean up for quit. + * + * Must be called before exiting. + */ +void fetcher_quit(void); + +/** + * Do some work on current fetches. + * + * Must be called regularly to make progress on fetches. + */ +void fetcher_poll(void); + +#endif diff --git a/content/fetchers/about.c b/content/fetchers/about.c index 17f220932..8c4d29a91 100644 --- a/content/fetchers/about.c +++ b/content/fetchers/about.c @@ -45,6 +45,7 @@ #include "utils/config.h" #include "content/fetch.h" +#include "content/fetchers.h" #include "content/fetchers/about.h" #include "content/urldb.h" #include "desktop/netsurf.h" @@ -837,17 +838,19 @@ static void fetch_about_poll(lwc_string *scheme) } while ( (c = next) != ring && ring != NULL); } -void fetch_about_register(void) +nserror fetch_about_register(void) { lwc_string *scheme = lwc_string_ref(corestring_lwc_about); - - fetch_add_fetcher(scheme, - fetch_about_initialise, - fetch_about_can_fetch, - fetch_about_setup, - fetch_about_start, - fetch_about_abort, - fetch_about_free, - fetch_about_poll, - fetch_about_finalise); + const struct fetcher_operation_table fetcher_ops = { + .initialise = fetch_about_initialise, + .acceptable = fetch_about_can_fetch, + .setup = fetch_about_setup, + .start = fetch_about_start, + .abort = fetch_about_abort, + .free = fetch_about_free, + .poll = fetch_about_poll, + .finalise = fetch_about_finalise + }; + + return fetcher_add(scheme, &fetcher_ops); } diff --git a/content/fetchers/about.h b/content/fetchers/about.h index f22be6a5d..9544971a6 100644 --- a/content/fetchers/about.h +++ b/content/fetchers/about.h @@ -23,6 +23,6 @@ #ifndef NETSURF_CONTENT_FETCHERS_FETCH_ABOUT_H #define NETSURF_CONTENT_FETCHERS_FETCH_ABOUT_H -void fetch_about_register(void); +nserror fetch_about_register(void); #endif diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c index 80ac5ec89..39c15b930 100644 --- a/content/fetchers/curl.c +++ b/content/fetchers/curl.c @@ -53,12 +53,10 @@ #include "utils/file.h" #include "content/fetch.h" +#include "content/fetchers.h" #include "content/fetchers/curl.h" #include "content/urldb.h" -/* uncomment this to use scheduler based calling -#define FETCHER_CURLL_SCHEDULED 1 -*/ /** SSL certificate info */ struct cert_info { @@ -160,6 +158,16 @@ void fetch_curl_register(void) curl_version_info_data *data; int i; lwc_string *scheme; + const struct fetcher_operation_table fetcher_ops = { + .initialise = fetch_curl_initialise, + .acceptable = fetch_curl_can_fetch, + .setup = fetch_curl_setup, + .start = fetch_curl_start, + .abort = fetch_curl_abort, + .free = fetch_curl_free, + .poll = fetch_curl_poll, + .finalise = fetch_curl_finalise + }; LOG(("curl_version %s", curl_version())); @@ -261,19 +269,7 @@ void fetch_curl_register(void) continue; } - if (!fetch_add_fetcher(scheme, - fetch_curl_initialise, - fetch_curl_can_fetch, - fetch_curl_setup, - fetch_curl_start, - fetch_curl_abort, - fetch_curl_free, -#ifdef FETCHER_CURLL_SCHEDULED - NULL, -#else - fetch_curl_poll, -#endif - fetch_curl_finalise)) { + if (fetcher_add(scheme, &fetcher_ops) != NSERROR_OK) { LOG(("Unable to register cURL fetcher for %s", data->protocols[i])); } @@ -835,12 +831,6 @@ void fetch_curl_poll(lwc_string *scheme_ignored) } curl_msg = curl_multi_info_read(fetch_curl_multi, &queue); } - -#ifdef FETCHER_CURLL_SCHEDULED - if (running != 0) { - guit->browser->schedule(10, fetch_curl_poll, fetch_curl_poll); - } -#endif } diff --git a/content/fetchers/data.c b/content/fetchers/data.c index f7ae17150..94ba63827 100644 --- a/content/fetchers/data.c +++ b/content/fetchers/data.c @@ -31,6 +31,7 @@ #include "utils/config.h" #include "content/fetch.h" +#include "content/fetchers.h" #include "content/fetchers/data.h" #include "content/urldb.h" #include "desktop/netsurf.h" @@ -324,17 +325,19 @@ static void fetch_data_poll(lwc_string *scheme) } while ( (c = next) != ring && ring != NULL); } -void fetch_data_register(void) +nserror fetch_data_register(void) { lwc_string *scheme = lwc_string_ref(corestring_lwc_data); - - fetch_add_fetcher(scheme, - fetch_data_initialise, - fetch_data_can_fetch, - fetch_data_setup, - fetch_data_start, - fetch_data_abort, - fetch_data_free, - fetch_data_poll, - fetch_data_finalise); + const struct fetcher_operation_table fetcher_ops = { + .initialise = fetch_data_initialise, + .acceptable = fetch_data_can_fetch, + .setup = fetch_data_setup, + .start = fetch_data_start, + .abort = fetch_data_abort, + .free = fetch_data_free, + .poll = fetch_data_poll, + .finalise = fetch_data_finalise + }; + + return fetcher_add(scheme, &fetcher_ops); } diff --git a/content/fetchers/data.h b/content/fetchers/data.h index 76f02cb3b..f6017e07a 100644 --- a/content/fetchers/data.h +++ b/content/fetchers/data.h @@ -23,6 +23,6 @@ #ifndef NETSURF_CONTENT_FETCHERS_FETCH_DATA_H #define NETSURF_CONTENT_FETCHERS_FETCH_DATA_H -void fetch_data_register(void); +nserror fetch_data_register(void); #endif diff --git a/content/fetchers/file.c b/content/fetchers/file.c index 7834b2702..f08be6288 100644 --- a/content/fetchers/file.c +++ b/content/fetchers/file.c @@ -55,6 +55,7 @@ #include "content/dirlist.h" #include "content/fetch.h" +#include "content/fetchers.h" #include "content/urldb.h" #include "content/fetchers/file.h" @@ -760,17 +761,19 @@ static void fetch_file_poll(lwc_string *scheme) } while ( (c = next) != ring && ring != NULL); } -void fetch_file_register(void) +nserror fetch_file_register(void) { lwc_string *scheme = lwc_string_ref(corestring_lwc_file); - - fetch_add_fetcher(scheme, - fetch_file_initialise, - fetch_file_can_fetch, - fetch_file_setup, - fetch_file_start, - fetch_file_abort, - fetch_file_free, - fetch_file_poll, - fetch_file_finalise); + const struct fetcher_operation_table fetcher_ops = { + .initialise = fetch_file_initialise, + .acceptable = fetch_file_can_fetch, + .setup = fetch_file_setup, + .start = fetch_file_start, + .abort = fetch_file_abort, + .free = fetch_file_free, + .poll = fetch_file_poll, + .finalise = fetch_file_finalise + }; + + return fetcher_add(scheme, &fetcher_ops); } diff --git a/content/fetchers/file.h b/content/fetchers/file.h index d1621b9ba..b3c39db9f 100644 --- a/content/fetchers/file.h +++ b/content/fetchers/file.h @@ -23,6 +23,6 @@ #ifndef NETSURF_CONTENT_FETCHERS_FETCH_FILE_H #define NETSURF_CONTENT_FETCHERS_FETCH_FILE_H -void fetch_file_register(void); +nserror fetch_file_register(void); #endif diff --git a/content/fetchers/resource.c b/content/fetchers/resource.c index 664c45720..18e302140 100644 --- a/content/fetchers/resource.c +++ b/content/fetchers/resource.c @@ -37,16 +37,19 @@ #include #include "utils/config.h" -#include "content/fetch.h" -#include "content/fetchers/resource.h" -#include "content/urldb.h" -#include "desktop/gui_factory.h" +#include "utils/errors.h" #include "utils/corestrings.h" #include "utils/nsoption.h" #include "utils/log.h" #include "utils/messages.h" #include "utils/utils.h" #include "utils/ring.h" +#include "desktop/gui_factory.h" + +#include "content/fetch.h" +#include "content/fetchers.h" +#include "content/fetchers/resource.h" +#include "content/urldb.h" struct fetch_resource_context; @@ -353,17 +356,19 @@ static void fetch_resource_poll(lwc_string *scheme) } while ( (c = next) != ring && ring != NULL); } -void fetch_resource_register(void) +nserror fetch_resource_register(void) { lwc_string *scheme = lwc_string_ref(corestring_lwc_resource); - - fetch_add_fetcher(scheme, - fetch_resource_initialise, - fetch_resource_can_fetch, - fetch_resource_setup, - fetch_resource_start, - fetch_resource_abort, - fetch_resource_free, - fetch_resource_poll, - fetch_resource_finalise); + const struct fetcher_operation_table fetcher_ops = { + .initialise = fetch_resource_initialise, + .acceptable = fetch_resource_can_fetch, + .setup = fetch_resource_setup, + .start = fetch_resource_start, + .abort = fetch_resource_abort, + .free = fetch_resource_free, + .poll = fetch_resource_poll, + .finalise = fetch_resource_finalise + }; + + return fetcher_add(scheme, &fetcher_ops); } diff --git a/content/fetchers/resource.h b/content/fetchers/resource.h index 79d8e37c4..cf4d6edac 100644 --- a/content/fetchers/resource.h +++ b/content/fetchers/resource.h @@ -35,6 +35,6 @@ * * should only be called from the fetch initialise */ -void fetch_resource_register(void); +nserror fetch_resource_register(void); #endif diff --git a/content/hlcache.c b/content/hlcache.c index e7c4cd84d..0d7996524 100644 --- a/content/hlcache.c +++ b/content/hlcache.c @@ -621,15 +621,6 @@ void hlcache_finalise(void) llcache_finalise(); } -/* See hlcache.h for documentation */ -nserror hlcache_poll(void) -{ - - llcache_poll(); - - return NSERROR_OK; -} - /* See hlcache.h for documentation */ nserror hlcache_handle_retrieve(nsurl *url, uint32_t flags, nsurl *referer, llcache_post_data *post, diff --git a/content/hlcache.h b/content/hlcache.h index 746b3c866..e0bf4161d 100644 --- a/content/hlcache.h +++ b/content/hlcache.h @@ -93,14 +93,6 @@ void hlcache_stop(void); */ void hlcache_finalise(void); -/** - * Drive the low-level cache poll loop, and attempt to clean the cache. - * No guarantee is made about what, if any, cache cleaning will occur. - * - * \return NSERROR_OK - */ -nserror hlcache_poll(void); - /** * Retrieve a high-level cache handle for an object * diff --git a/content/llcache.c b/content/llcache.c index b241ab22b..ad4d6d1f7 100644 --- a/content/llcache.c +++ b/content/llcache.c @@ -3087,14 +3087,6 @@ void llcache_finalise(void) llcache = NULL; } -/* See llcache.h for documentation */ -nserror llcache_poll(void) -{ - fetch_poll(); - - return NSERROR_OK; -} - /** * Catch up the cache users with state changes from fetchers. * diff --git a/content/llcache.h b/content/llcache.h index 4a3521637..d4ed5f095 100644 --- a/content/llcache.h +++ b/content/llcache.h @@ -238,13 +238,6 @@ nserror llcache_initialise(const struct llcache_parameters *parameters); */ void llcache_finalise(void); -/** - * Cause the low-level cache to emit any pending notifications. - * - * \return NSERROR_OK on success, appropriate error otherwise. - */ -nserror llcache_poll(void); - /** * Cause the low-level cache to attempt to perform cleanup. * diff --git a/desktop/netsurf.c b/desktop/netsurf.c index a1bc42b93..b0c338af6 100644 --- a/desktop/netsurf.c +++ b/desktop/netsurf.c @@ -29,7 +29,7 @@ #include "utils/config.h" #include "utils/utsname.h" #include "content/content_factory.h" -#include "content/fetch.h" +#include "content/fetchers.h" #include "content/hlcache.h" #include "content/mimesniff.h" #include "content/urldb.h" @@ -231,7 +231,7 @@ nserror netsurf_init(const char *messages, const char *store_path) setlocale(LC_ALL, "C"); /* initialise the fetchers */ - ret = fetch_init(); + ret = fetcher_init(); if (ret != NSERROR_OK) return ret; @@ -258,7 +258,7 @@ int netsurf_main_loop(void) { while (!netsurf_quit) { guit->browser->poll(fetch_active); - hlcache_poll(); + fetcher_poll(); } return 0; @@ -285,7 +285,7 @@ void netsurf_exit(void) hlcache_finalise(); LOG(("Closing fetches")); - fetch_quit(); + fetcher_quit(); mimesniff_fini(); diff --git a/render/html_css_fetcher.c b/render/html_css_fetcher.c index 9bd3b21a6..3df1528af 100644 --- a/render/html_css_fetcher.c +++ b/render/html_css_fetcher.c @@ -28,6 +28,7 @@ #include "utils/config.h" #include "content/fetch.h" +#include "content/fetchers.h" #include "render/html_internal.h" #include "utils/log.h" #include "utils/ring.h" @@ -276,6 +277,16 @@ static void html_css_fetcher_poll(lwc_string *scheme) void html_css_fetcher_register(void) { lwc_string *scheme; + const struct fetcher_operation_table html_css_fetcher_ops = { + .initialise = html_css_fetcher_initialise, + .acceptable = html_css_fetcher_can_fetch, + .setup = html_css_fetcher_setup, + .start = html_css_fetcher_start, + .abort = html_css_fetcher_abort, + .free = html_css_fetcher_free, + .poll = html_css_fetcher_poll, + .finalise = html_css_fetcher_finalise + }; if (lwc_intern_string("x-ns-css", SLEN("x-ns-css"), &scheme) != lwc_error_ok) { @@ -283,15 +294,7 @@ void html_css_fetcher_register(void) "(couldn't intern \"x-ns-css\")."); } - fetch_add_fetcher(scheme, - html_css_fetcher_initialise, - html_css_fetcher_can_fetch, - html_css_fetcher_setup, - html_css_fetcher_start, - html_css_fetcher_abort, - html_css_fetcher_free, - html_css_fetcher_poll, - html_css_fetcher_finalise); + fetcher_add(scheme, &html_css_fetcher_ops); } nserror html_css_fetcher_add_item(dom_string *data, nsurl *base_url, -- cgit v1.2.3 From c5383961266e6cdc330a6ee8fa97492ac27d81f2 Mon Sep 17 00:00:00 2001 From: François Revol Date: Fri, 20 Jun 2014 15:06:00 +0200 Subject: beos: Add missing include --- beos/plotters.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/beos/plotters.cpp b/beos/plotters.cpp index c2a99fea0..52ab4ec21 100644 --- a/beos/plotters.cpp +++ b/beos/plotters.cpp @@ -36,6 +36,7 @@ extern "C" { #include "utils/log.h" #include "utils/utils.h" #include "utils/nsoption.h" +#include "utils/nsurl.h" } #include "beos/font.h" #include "beos/gui.h" -- cgit v1.2.3 From 186f7479ee86609978540fb57299acc8e20d6f0c Mon Sep 17 00:00:00 2001 From: François Revol Date: Fri, 20 Jun 2014 15:06:16 +0200 Subject: beos: Adjust browser_table for removed call --- beos/gui.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/beos/gui.cpp b/beos/gui.cpp index db4374512..d7f4ab01e 100644 --- a/beos/gui.cpp +++ b/beos/gui.cpp @@ -990,9 +990,8 @@ static struct gui_fetch_table beos_fetch_table = { static struct gui_browser_table beos_browser_table = { gui_poll, - beos_schedule, + beos_schedule, gui_quit, - NULL, //set_search_ico gui_launch_url, NULL, //create_form_select_menu NULL, //cert_verify -- cgit v1.2.3 From fc290506a488d32f24c1e30257cd1883d57f77b3 Mon Sep 17 00:00:00 2001 From: François Revol Date: Fri, 20 Jun 2014 15:19:10 +0200 Subject: beos: Fix local variable shadowing a parameter --- beos/scaffolding.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/beos/scaffolding.cpp b/beos/scaffolding.cpp index 35153b33d..0f87420a5 100644 --- a/beos/scaffolding.cpp +++ b/beos/scaffolding.cpp @@ -196,12 +196,11 @@ NSIconTextControl::NSIconTextControl(BRect frame, const char* name, fIconBitmap(NULL) { BRect r(Bounds()); - BRect frame = r; - frame.right = frame.left + ICON_WIDTH - 1; - frame.bottom = frame.top + ICON_WIDTH - 1; - frame.OffsetBy((int32)((r.IntegerHeight() - ICON_WIDTH + 3) / 2), + fIconFrame = r; + fIconFrame.right = fIconFrame.left + ICON_WIDTH - 1; + fIconFrame.bottom = fIconFrame.top + ICON_WIDTH - 1; + fIconFrame.OffsetBy((int32)((r.IntegerHeight() - ICON_WIDTH + 3) / 2), (int32)((r.IntegerHeight() - ICON_WIDTH + 1) / 2)); - fIconFrame = frame; FixupTextRect(); } -- cgit v1.2.3 From d64fa80ba7798dafc580d531c36f42eb13a13074 Mon Sep 17 00:00:00 2001 From: François Revol Date: Fri, 20 Jun 2014 15:24:55 +0200 Subject: beos: Fix Haiku libnetwork detection post-PackageManagement --- beos/Makefile.target | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beos/Makefile.target b/beos/Makefile.target index a1259d644..bbeb0be22 100644 --- a/beos/Makefile.target +++ b/beos/Makefile.target @@ -38,7 +38,7 @@ ifeq ($(HOST),beos) ifneq ($(wildcard /boot/develop/lib/*/libzeta.so),) LDFLAGS += -lzeta endif - ifneq ($(wildcard /boot/develop/lib/*/libnetwork.so),) + ifneq ($(wildcard /boot/system/develop/lib/*/libnetwork.so),) # Haiku CFLAGS += -I/boot/common/include \ -I/boot/common/include/hubbub \ -- cgit v1.2.3 From 80cc3266580e9fbd77f07b094f6248326cf2cee3 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Fri, 20 Jun 2014 13:23:22 +0200 Subject: beos: Use PathFinder to locate resource folder. So it can work wherever NetSurf is installed... Note this uses a Haiku-specific API and definitely breaks BeOS build. --- beos/gui.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/beos/gui.cpp b/beos/gui.cpp index d7f4ab01e..4f06b9f04 100644 --- a/beos/gui.cpp +++ b/beos/gui.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -79,9 +80,6 @@ extern "C" { static void *myrealloc(void *ptr, size_t len, void *pw); -/* Where to search for shared resources. Must have trailing / */ -#define RESPATH "/boot/apps/netsurf/res/" - //TODO: use resources // enable using resources instead of files #define USE_RESOURCES 1 @@ -297,7 +295,13 @@ static char *find_resource(char *buf, const char *filename, const char *def) return buf; } - strcpy(t, RESPATH); + + BPathFinder f((void*)find_resource); + + BPath p; + f.FindPath(B_FIND_PATH_APPS_DIRECTORY, "netsurf/res/", p); + strcpy(t, p.Path()); + strcat(t, filename); realpath(t, buf); if (access(buf, R_OK) == 0) @@ -488,7 +492,10 @@ static bool nslog_stream_configure(FILE *fptr) static BPath get_messages_path() { - BPath p("/boot/apps/netsurf/res"); + BPathFinder f((void*)get_messages_path); + + BPath p; + f.FindPath(B_FIND_PATH_APPS_DIRECTORY, "netsurf/res", p); // TODO: use Haiku's BLocale stuff BString lang(getenv("LC_MESSAGES")); lang.Truncate(2); -- cgit v1.2.3 From dfc095bd900b37fb7e1ddb25fd2a85bf1839e41c Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Tue, 24 Jun 2014 13:26:39 +0100 Subject: Display U+FFFD for characters > U+FFFF. --- framebuffer/font_internal.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/framebuffer/font_internal.c b/framebuffer/font_internal.c index e514b12d9..4edb4ee4c 100644 --- a/framebuffer/font_internal.c +++ b/framebuffer/font_internal.c @@ -221,6 +221,12 @@ fb_get_glyph(uint32_t ucs4, enum fb_font_style style) unsigned int offset; uint16_t g_offset; + /* Internal font has no glyphs beyond U+FFFF and there isn't + * space to render a >4 digit codepoint; just show replacement + * character. */ + if (ucs4 > 0xffff) + ucs4 = 0xfffd; + switch (style) { case FB_BOLD_ITALIC: section = fb_bold_italic_section_table[ucs4 / 256]; -- cgit v1.2.3 From 1b7aa7ffe53843f072e3de5e28bdf06faa7980b9 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 26 Jun 2014 19:04:14 +0100 Subject: make fetchers scheduled --- content/fetch.c | 217 +++++++++++++++++++++++++++++++----------------- content/fetchers.h | 32 +++++-- content/fetchers/curl.c | 4 +- desktop/netsurf.c | 5 +- 4 files changed, 169 insertions(+), 89 deletions(-) diff --git a/content/fetch.c b/content/fetch.c index 13c7c6542..10cac9b27 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -37,9 +37,11 @@ #include #include #include +#include #include "utils/config.h" #include "desktop/netsurf.h" +#include "desktop/gui_factory.h" #include "utils/corestrings.h" #include "utils/nsoption.h" #include "utils/log.h" @@ -63,7 +65,11 @@ /** The maximum number of fetchers that can be added */ #define MAX_FETCHERS 8 -bool fetch_active; /**< Fetches in progress, please call fetch_poll(). */ +#ifdef DEBUG_FETCH_VERBOSE +#define FETCH_LOG(x) LOG(x) +#else +#define FETCH_LOG(x) +#endif /** * Information about a fetcher for a given scheme. @@ -129,7 +135,7 @@ static int get_fetcher_for_scheme(lwc_string *scheme) scheme, &match) == lwc_error_ok) && (match == true)) { return fetcherd; - } + } } return -1; } @@ -140,10 +146,9 @@ static int get_fetcher_for_scheme(lwc_string *scheme) static bool fetch_dispatch_job(struct fetch *fetch) { RING_REMOVE(queue_ring, fetch); -#ifdef DEBUG_FETCH_VERBOSE - LOG(("Attempting to start fetch %p, fetcher %p, url %s", fetch, + FETCH_LOG(("Attempting to start fetch %p, fetcher %p, url %s", fetch, fetch->fetcher_handle, nsurl_access(fetch->url))); -#endif + if (!fetchers[fetch->fetcherd].ops.start(fetch->fetcher_handle)) { RING_INSERT(queue_ring, fetch); /* Put it back on the end of the queue */ return false; @@ -191,56 +196,76 @@ static bool fetch_choose_and_dispatch(void) return false; } -/** - * Dispatch as many jobs as we have room to dispatch. - */ -static void fetch_dispatch_jobs(void) +static void dump_rings(void) { - int all_active, all_queued; #ifdef DEBUG_FETCH_VERBOSE struct fetch *q; struct fetch *f; -#endif - - if (!queue_ring) - return; /* Nothing to do, the queue is empty */ - RING_GETSIZE(struct fetch, queue_ring, all_queued); - RING_GETSIZE(struct fetch, fetch_ring, all_active); - -#ifdef DEBUG_FETCH_VERBOSE - LOG(("queue_ring %i, fetch_ring %i", all_queued, all_active)); q = queue_ring; if (q) { do { - LOG(("queue_ring: %s", q->url)); + LOG(("queue_ring: %s", nsurl_access(q->url))); q = q->r_next; } while (q != queue_ring); } f = fetch_ring; if (f) { do { - LOG(("fetch_ring: %s", f->url)); + LOG(("fetch_ring: %s", nsurl_access(f->url))); f = f->r_next; } while (f != fetch_ring); } #endif +} + +/** + * Dispatch as many jobs as we have room to dispatch. + * + * @return true if there are active fetchers that require polling else false. + */ +static bool fetch_dispatch_jobs(void) +{ + int all_active; + int all_queued; + + RING_GETSIZE(struct fetch, queue_ring, all_queued); + RING_GETSIZE(struct fetch, fetch_ring, all_active); + + FETCH_LOG(("queue_ring %i, fetch_ring %i", all_queued, all_active)); + dump_rings(); - while ( all_queued && all_active < nsoption_int(max_fetchers) ) { - /*LOG(("%d queued, %d fetching", all_queued, all_active));*/ - if (fetch_choose_and_dispatch()) { + while ((all_queued != 0) && + (all_active < nsoption_int(max_fetchers)) && + fetch_choose_and_dispatch()) { all_queued--; all_active++; - } else { - /* Either a dispatch failed or we ran out. Just stop */ - break; + FETCH_LOG(("%d queued, %d fetching", + all_queued, all_active)); + } + + FETCH_LOG(("Fetch ring is now %d elements.", all_active)); + FETCH_LOG(("Queue ring is now %d elements.", all_queued)); + + return (all_active > 0); +} + +static void fetcher_poll(void *unused) +{ + int fetcherd; + + if (fetch_dispatch_jobs()) { + FETCH_LOG(("Polling fetchers")); + for (fetcherd = 0; fetcherd < MAX_FETCHERS; fetcherd++) { + if (fetchers[fetcherd].refcount > 0) { + /* fetcher present */ + fetchers[fetcherd].ops.poll(fetchers[fetcherd].scheme); + } } + + /* schedule active fetchers to run again in 10ms */ + guit->browser->schedule(10, fetcher_poll, NULL); } - fetch_active = (all_active > 0); -#ifdef DEBUG_FETCH_VERBOSE - LOG(("Fetch ring is now %d elements.", all_active)); - LOG(("Queue ring is now %d elements.", all_queued)); -#endif } /****************************************************************************** @@ -256,8 +281,6 @@ nserror fetcher_init(void) fetch_resource_register(); fetch_about_register(); - fetch_active = false; - return NSERROR_OK; } @@ -303,6 +326,63 @@ fetcher_add(lwc_string *scheme, const struct fetcher_operation_table *ops) return NSERROR_OK; } +/* exported interface documented in content/fetch.h */ +nserror fetcher_fdset(fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *except_fd_set, + int *maxfd_out) +{ + CURLMcode code; + int maxfd; + int fetcherd; /* fetcher index */ + + if (!fetch_dispatch_jobs()) { + FETCH_LOG(("No jobs")); + *maxfd_out = -1; + return NSERROR_OK; + } + + FETCH_LOG(("Polling fetchers")); + + for (fetcherd = 0; fetcherd < MAX_FETCHERS; fetcherd++) { + if (fetchers[fetcherd].refcount > 0) { + /* fetcher present */ + fetchers[fetcherd].ops.poll(fetchers[fetcherd].scheme); + } + } + + FD_ZERO(read_fd_set); + FD_ZERO(write_fd_set); + FD_ZERO(except_fd_set); + code = curl_multi_fdset(fetch_curl_multi, + read_fd_set, + write_fd_set, + except_fd_set, + &maxfd); + assert(code == CURLM_OK); + + if (maxfd >= 0) { + /* change the scheduled poll to happen is a 1000ms as + * we assume fetching an fdset means the fetchers will + * be run by the client waking up on data available on + * the fd and re-calling fetcher_fdset() if this does + * not happen the fetch polling will continue as + * usual. + */ + /** @note adjusting the schedule time is only done for + * curl currently. This is because as it is assumed to + * be the only fetcher that can possibly have fd to + * select on. All the other fetchers continue to need + * polling frequently. + */ + guit->browser->schedule(1000, fetcher_poll, NULL); + } + + *maxfd_out = maxfd; + + return NSERROR_OK; +} + /* exported interface documented in content/fetch.h */ struct fetch * fetch_start(nsurl *url, @@ -336,9 +416,7 @@ fetch_start(nsurl *url, return NULL; } -#ifdef DEBUG_FETCH_VERBOSE - LOG(("fetch %p, url '%s'", fetch, nsurl_access(url))); -#endif + FETCH_LOG(("fetch %p, url '%s'", fetch, nsurl_access(url))); /* construct a new fetch structure */ fetch->callback = callback; @@ -421,9 +499,15 @@ fetch_start(nsurl *url, /* Rah, got it, so ref the fetcher. */ fetch_ref_fetcher(fetch->fetcherd); - /* Dump us in the queue and ask the queue to run. */ + /* Dump new fetch in the queue. */ RING_INSERT(queue_ring, fetch); - fetch_dispatch_jobs(); + + /* Ask the queue to run. */ + if (fetch_dispatch_jobs()) { + FETCH_LOG(("scheduling poll")); + /* schedule active fetchers to run again in 10ms */ + guit->browser->schedule(10, fetcher_poll, NULL); + } return fetch; } @@ -432,47 +516,31 @@ fetch_start(nsurl *url, void fetch_abort(struct fetch *f) { assert(f); -#ifdef DEBUG_FETCH_VERBOSE - LOG(("fetch %p, fetcher %p, url '%s'", f, f->fetcher_handle, + FETCH_LOG(("fetch %p, fetcher %p, url '%s'", f, f->fetcher_handle, nsurl_access(f->url))); -#endif fetchers[f->fetcherd].ops.abort(f->fetcher_handle); } /* exported interface documented in content/fetch.h */ void fetch_free(struct fetch *f) { -#ifdef DEBUG_FETCH_VERBOSE - LOG(("Freeing fetch %p, fetcher %p", f, f->fetcher_handle)); -#endif + FETCH_LOG(("Freeing fetch %p, fetcher %p", f, f->fetcher_handle)); + fetchers[f->fetcherd].ops.free(f->fetcher_handle); fetch_unref_fetcher(f->fetcherd); nsurl_unref(f->url); - if (f->referer != NULL) + if (f->referer != NULL) { nsurl_unref(f->referer); - if (f->host != NULL) + } + if (f->host != NULL) { lwc_string_unref(f->host); + } free(f); } -/* exported interface documented in content/fetchers.h */ -void fetcher_poll(void) -{ - int fetcherd; - - fetch_dispatch_jobs(); - if (fetch_active) { - for (fetcherd = 0; fetcherd < MAX_FETCHERS; fetcherd++) { - if (fetchers[fetcherd].refcount > 0) { - /* fetcher present */ - fetchers[fetcherd].ops.poll(fetchers[fetcherd].scheme); - } - } - } -} /* exported interface documented in content/fetch.h */ bool fetch_can_fetch(const nsurl *url) @@ -589,7 +657,7 @@ void fetch_multipart_data_destroy(struct fetch_multipart_data *list) free(list->name); free(list->value); if (list->file) { - LOG(("Freeing rawfile: %s", list->rawfile)); + FETCH_LOG(("Freeing rawfile: %s", list->rawfile)); free(list->rawfile); } free(list); @@ -607,12 +675,8 @@ fetch_send_callback(const fetch_msg *msg, struct fetch *fetch) /* exported interface documented in content/fetch.h */ void fetch_remove_from_queues(struct fetch *fetch) { - int all_active; - -#ifdef DEBUG_FETCH_VERBOSE - int all_queued; - LOG(("Fetch %p, fetcher %p can be freed", fetch, fetch->fetcher_handle)); -#endif + FETCH_LOG(("Fetch %p, fetcher %p can be freed", + fetch, fetch->fetcher_handle)); /* Go ahead and free the fetch properly now */ if (fetch->fetch_is_active) { @@ -621,15 +685,15 @@ void fetch_remove_from_queues(struct fetch *fetch) RING_REMOVE(queue_ring, fetch); } - RING_GETSIZE(struct fetch, fetch_ring, all_active); - - fetch_active = (all_active > 0); - #ifdef DEBUG_FETCH_VERBOSE - LOG(("Fetch ring is now %d elements.", all_active)); + int all_active; + int all_queued; + RING_GETSIZE(struct fetch, fetch_ring, all_active); RING_GETSIZE(struct fetch, queue_ring, all_queued); + LOG(("Fetch ring is now %d elements.", all_active)); + LOG(("Queue ring is now %d elements.", all_queued)); #endif } @@ -638,9 +702,8 @@ void fetch_remove_from_queues(struct fetch *fetch) /* exported interface documented in content/fetch.h */ void fetch_set_http_code(struct fetch *fetch, long http_code) { -#ifdef DEBUG_FETCH_VERBOSE - LOG(("Setting HTTP code to %ld", http_code)); -#endif + FETCH_LOG(("Setting HTTP code to %ld", http_code)); + fetch->http_code = http_code; } diff --git a/content/fetchers.h b/content/fetchers.h index 6ca52245c..3303379d2 100644 --- a/content/fetchers.h +++ b/content/fetchers.h @@ -23,14 +23,13 @@ #ifndef _NETSURF_DESKTOP_FETCHERS_H_ #define _NETSURF_DESKTOP_FETCHERS_H_ +#include #include struct nsurl; struct fetch_multipart_data; struct fetch; -extern bool fetch_active; - /** * Fetcher operations API * @@ -86,6 +85,7 @@ struct fetcher_operation_table { void (*finalise)(lwc_string *scheme); }; + /** * Register a fetcher for a scheme * @@ -95,6 +95,7 @@ struct fetcher_operation_table { */ nserror fetcher_add(lwc_string *scheme, const struct fetcher_operation_table *ops); + /** * Initialise the fetchers. * @@ -102,6 +103,7 @@ nserror fetcher_add(lwc_string *scheme, const struct fetcher_operation_table *op */ nserror fetcher_init(void); + /** * Clean up for quit. * @@ -109,11 +111,31 @@ nserror fetcher_init(void); */ void fetcher_quit(void); + /** - * Do some work on current fetches. + * Get the set of file descriptors the fetchers are currently using. + * + * This obtains the file descriptors the fetch system is using to + * obtain data. It will cause the fetchers to make progress, if + * possible, potentially completing fetches before requiring activity + * on file descriptors. + * + * If a set of descriptors is returned (maxfd is not -1) The caller is + * expected to wait on them (with select etc.) and continue to obtain + * the fdset with this call. This will switch the fetchers from polled + * mode to waiting for network activity which is much more efficient. + * + * \note If the caller does not subsequently obtain the fdset again + * the fetchers will fall back to the less efficient polled + * operation. The fallback to polled operation will only occour after + * a timeout which introduces additional delay. * - * Must be called regularly to make progress on fetches. + * \param read_fd_set[out] The fd set for read. + * \param write_fd_set[out] The fd set for write. + * \param except_fd_set[out] The fd set for exceptions. + * \param maxfd[out] The highest fd number in the set or -1 if no fd available. + * \return NSERROR_OK on success or appropriate error code. */ -void fetcher_poll(void); +nserror fetcher_fdset(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, int *maxfd); #endif diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c index 39c15b930..32b7189db 100644 --- a/content/fetchers/curl.c +++ b/content/fetchers/curl.c @@ -500,9 +500,7 @@ bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, CURL *handle) /* add to the global curl multi handle */ codem = curl_multi_add_handle(fetch_curl_multi, fetch->curl_handle); assert(codem == CURLM_OK || codem == CURLM_CALL_MULTI_PERFORM); - - guit->browser->schedule(10, (void *)fetch_curl_poll, NULL); - + return true; } diff --git a/desktop/netsurf.c b/desktop/netsurf.c index b0c338af6..579648bae 100644 --- a/desktop/netsurf.c +++ b/desktop/netsurf.c @@ -257,8 +257,7 @@ nserror netsurf_init(const char *messages, const char *store_path) int netsurf_main_loop(void) { while (!netsurf_quit) { - guit->browser->poll(fetch_active); - fetcher_poll(); + guit->browser->poll(false); } return 0; @@ -310,5 +309,3 @@ void netsurf_exit(void) LOG(("Exited successfully")); } - - -- cgit v1.2.3 From 8944edd649e74e4864f36d7293921385ba5ca2c7 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 26 Jun 2014 18:56:42 +0100 Subject: convert all frontends to scheduled fetch operation --- amiga/gui.c | 9 ------ atari/gui.c | 5 ++-- beos/gui.cpp | 34 ++++++++--------------- cocoa/gui.m | 2 +- content/fetch.c | 1 + framebuffer/gui.c | 4 --- gtk/gui.c | 69 +++++++++++++++++++--------------------------- monkey/poll.c | 82 +++++++++++++++++++++++-------------------------------- riscos/gui.c | 11 ++------ windows/gui.c | 5 ---- 10 files changed, 80 insertions(+), 142 deletions(-) diff --git a/amiga/gui.c b/amiga/gui.c index 756ed63e2..e2bb39c0c 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -2502,18 +2502,9 @@ void ami_get_msg(void) ami_quit_netsurf_delayed(); } -static void ami_gui_fetch_callback(void *p) -{ - /* This doesn't need to do anything - the scheduled event will - * send a message to trigger Wait() to return, thereby causing - * the event function to return, and NetSurf to call - * hlcache_poll() as part of the usual fetch/event loop. - */ -} static void gui_poll(bool active) { - if(active) ami_schedule(0, ami_gui_fetch_callback, NULL); ami_get_msg(); } diff --git a/atari/gui.c b/atari/gui.c index 7cac90c3b..608d0d859 100644 --- a/atari/gui.c +++ b/atari/gui.c @@ -121,7 +121,7 @@ static void gui_poll(bool active) aes_event_in.emi_tlow = schedule_run(); - if(active || rendering){ + if(rendering){ aes_event_in.emi_tlow = nsoption_int(atari_gui_poll_timeout); } @@ -130,11 +130,10 @@ static void gui_poll(bool active) printf("long poll!\n"); } - if( !active ) { if(input_window && input_window->root->redraw_slots.areas_used > 0) { window_process_redraws(input_window->root); } - } + graf_mkstate(&mx, &my, &dummy, &dummy); aes_event_in.emi_m1.g_x = mx; diff --git a/beos/gui.cpp b/beos/gui.cpp index db4374512..8518ba1ac 100644 --- a/beos/gui.cpp +++ b/beos/gui.cpp @@ -46,7 +46,7 @@ extern "C" { #include "content/content.h" #include "content/content_protected.h" #include "content/fetch.h" -#include "content/fetchers/curl.h" +#include "content/fetchers.h" #include "content/fetchers/resource.h" #include "content/hlcache.h" #include "content/urldb.h" @@ -702,32 +702,23 @@ void nsbeos_pipe_message_top(BMessage *message, BWindow *_this, struct beos_scaf static void gui_poll(bool active) { - CURLMcode code; fd_set read_fd_set, write_fd_set, exc_fd_set; - int max_fd = 0; + int max_fd; struct timeval timeout; unsigned int fd_count = 0; bool block = true; bigtime_t next_schedule = 0; - // handle early deadlines - schedule_run(); + /* get any active fetcher fd */ + fetcher_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd); - FD_ZERO(&read_fd_set); - FD_ZERO(&write_fd_set); - FD_ZERO(&exc_fd_set); - - if (active) { - code = curl_multi_fdset(fetch_curl_multi, - &read_fd_set, - &write_fd_set, - &exc_fd_set, - &max_fd); - assert(code == CURLM_OK); - } + /* run the scheduler */ + schedule_run(); // our own event pipe FD_SET(sEventPipe[0], &read_fd_set); + + /** @todo Check if this max_fd should have + 1 */ max_fd = MAX(max_fd, sEventPipe[0] + 1); // If there are pending events elsewhere, we should not be blocking @@ -741,8 +732,10 @@ static void gui_poll(bool active) if (next_schedule < 0) next_schedule = 0; - } else //we're not allowed to sleep, there is other activity going on. + } else {//we're not allowed to sleep, there is other activity going on. + nsbeos_window_process_reformats(); block = false; + } /* LOG(("gui_poll: browser_reformat_pending:%d earliest_callback_timeout:%Ld" @@ -767,11 +760,6 @@ static void gui_poll(bool active) nsbeos_dispatch_event(message); } } - - schedule_run(); - - if (browser_reformat_pending) - nsbeos_window_process_reformats(); } diff --git a/cocoa/gui.m b/cocoa/gui.m index 1cb19a756..713f456cd 100644 --- a/cocoa/gui.m +++ b/cocoa/gui.m @@ -53,7 +53,7 @@ static void gui_poll(bool active) { cocoa_autorelease(); - NSEvent *event = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: active ? nil : [NSDate distantFuture] + NSEvent *event = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: [NSDate distantFuture] inMode: NSDefaultRunLoopMode dequeue: YES]; if (nil != event) { diff --git a/content/fetch.c b/content/fetch.c index 10cac9b27..3d1183aa0 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -61,6 +61,7 @@ /* Define this to turn on verbose fetch logging */ #undef DEBUG_FETCH_VERBOSE +#define DEBUG_FETCH_VERBOSE /** The maximum number of fetchers that can be added */ #define MAX_FETCHERS 8 diff --git a/framebuffer/gui.c b/framebuffer/gui.c index 251326dc2..0632bf3c6 100644 --- a/framebuffer/gui.c +++ b/framebuffer/gui.c @@ -564,10 +564,6 @@ static void framebuffer_poll(bool active) /* run the scheduler and discover how long to wait for the next event */ timeout = schedule_run(); - /* if active do not wait for event, return immediately */ - if (active) - timeout = 0; - /* if redraws are pending do not wait for event, return immediately */ if (fbtk_get_redraw_pending(fbtk)) timeout = 0; diff --git a/gtk/gui.c b/gtk/gui.c index 7de448c0b..9cd89e627 100644 --- a/gtk/gui.c +++ b/gtk/gui.c @@ -33,13 +33,13 @@ #include #include #include -#include #include #include #include #include "content/content.h" #include "content/fetch.h" +#include "content/fetchers.h" #include "content/fetchers/curl.h" #include "content/fetchers/resource.h" #include "content/hlcache.h" @@ -485,51 +485,42 @@ static bool nslog_stream_configure(FILE *fptr) static void nsgtk_poll(bool active) { - CURLMcode code; fd_set read_fd_set, write_fd_set, exc_fd_set; int max_fd; GPollFD *fd_list[1000]; unsigned int fd_count = 0; bool block = true; + fetcher_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd); + for (int i = 0; i <= max_fd; i++) { + if (FD_ISSET(i, &read_fd_set)) { + GPollFD *fd = malloc(sizeof *fd); + fd->fd = i; + fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR; + g_main_context_add_poll(0, fd, 0); + fd_list[fd_count++] = fd; + } + if (FD_ISSET(i, &write_fd_set)) { + GPollFD *fd = malloc(sizeof *fd); + fd->fd = i; + fd->events = G_IO_OUT | G_IO_ERR; + g_main_context_add_poll(0, fd, 0); + fd_list[fd_count++] = fd; + } + if (FD_ISSET(i, &exc_fd_set)) { + GPollFD *fd = malloc(sizeof *fd); + fd->fd = i; + fd->events = G_IO_ERR; + g_main_context_add_poll(0, fd, 0); + fd_list[fd_count++] = fd; + } + } + schedule_run(); - if (browser_reformat_pending) + if (browser_reformat_pending) { + nsgtk_window_process_reformats(); block = false; - - if (active) { - FD_ZERO(&read_fd_set); - FD_ZERO(&write_fd_set); - FD_ZERO(&exc_fd_set); - code = curl_multi_fdset(fetch_curl_multi, - &read_fd_set, - &write_fd_set, - &exc_fd_set, - &max_fd); - assert(code == CURLM_OK); - for (int i = 0; i <= max_fd; i++) { - if (FD_ISSET(i, &read_fd_set)) { - GPollFD *fd = malloc(sizeof *fd); - fd->fd = i; - fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR; - g_main_context_add_poll(0, fd, 0); - fd_list[fd_count++] = fd; - } - if (FD_ISSET(i, &write_fd_set)) { - GPollFD *fd = malloc(sizeof *fd); - fd->fd = i; - fd->events = G_IO_OUT | G_IO_ERR; - g_main_context_add_poll(0, fd, 0); - fd_list[fd_count++] = fd; - } - if (FD_ISSET(i, &exc_fd_set)) { - GPollFD *fd = malloc(sizeof *fd); - fd->fd = i; - fd->events = G_IO_ERR; - g_main_context_add_poll(0, fd, 0); - fd_list[fd_count++] = fd; - } - } } gtk_main_iteration_do(block); @@ -539,10 +530,6 @@ static void nsgtk_poll(bool active) free(fd_list[i]); } - schedule_run(); - - if (browser_reformat_pending) - nsgtk_window_process_reformats(); } diff --git a/monkey/poll.c b/monkey/poll.c index 414d458bd..d5b49f059 100644 --- a/monkey/poll.c +++ b/monkey/poll.c @@ -22,7 +22,7 @@ #include "desktop/gui.h" #include "monkey/schedule.h" #include "monkey/browser.h" -#include "content/fetchers/curl.h" +#include "content/fetchers.h" #include "monkey/dispatch.h" #include "monkey/poll.h" @@ -90,58 +90,48 @@ monkey_prepare_input(void) void monkey_poll(bool active) { - CURLMcode code; fd_set read_fd_set, write_fd_set, exc_fd_set; int max_fd; GPollFD *fd_list[1000]; unsigned int fd_count = 0; bool block = true; - + + fetcher_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd); + for (int i = 0; i <= max_fd; i++) { + if (FD_ISSET(i, &read_fd_set)) { + GPollFD *fd = malloc(sizeof *fd); + fd->fd = i; + fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR; + g_main_context_add_poll(0, fd, 0); + fd_list[fd_count++] = fd; + LOG(("Want to read %d", i)); + } + if (FD_ISSET(i, &write_fd_set)) { + GPollFD *fd = malloc(sizeof *fd); + fd->fd = i; + fd->events = G_IO_OUT | G_IO_ERR; + g_main_context_add_poll(0, fd, 0); + fd_list[fd_count++] = fd; + LOG(("Want to write %d", i)); + } + if (FD_ISSET(i, &exc_fd_set)) { + GPollFD *fd = malloc(sizeof *fd); + fd->fd = i; + fd->events = G_IO_ERR; + g_main_context_add_poll(0, fd, 0); + fd_list[fd_count++] = fd; + LOG(("Want to check %d", i)); + } + } + schedule_run(); - if (browser_reformat_pending) + if (browser_reformat_pending) { + monkey_window_process_reformats(); block = false; - - if (active) { - FD_ZERO(&read_fd_set); - FD_ZERO(&write_fd_set); - FD_ZERO(&exc_fd_set); - code = curl_multi_fdset(fetch_curl_multi, - &read_fd_set, - &write_fd_set, - &exc_fd_set, - &max_fd); - assert(code == CURLM_OK); - LOG(("maxfd from curl is %d", max_fd)); - for (int i = 0; i <= max_fd; i++) { - if (FD_ISSET(i, &read_fd_set)) { - GPollFD *fd = malloc(sizeof *fd); - fd->fd = i; - fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR; - g_main_context_add_poll(0, fd, 0); - fd_list[fd_count++] = fd; - LOG(("Want to read %d", i)); - } - if (FD_ISSET(i, &write_fd_set)) { - GPollFD *fd = malloc(sizeof *fd); - fd->fd = i; - fd->events = G_IO_OUT | G_IO_ERR; - g_main_context_add_poll(0, fd, 0); - fd_list[fd_count++] = fd; - LOG(("Want to write %d", i)); - } - if (FD_ISSET(i, &exc_fd_set)) { - GPollFD *fd = malloc(sizeof *fd); - fd->fd = i; - fd->events = G_IO_ERR; - g_main_context_add_poll(0, fd, 0); - fd_list[fd_count++] = fd; - LOG(("Want to check %d", i)); - } - } } - - LOG(("Iterate %sactive %sblocking", active?"":"in", block?"":"non-")); + + LOG(("Iterate %sblocking", block?"":"non-")); if (block) { fprintf(stdout, "GENERIC POLL BLOCKING\n"); } @@ -152,9 +142,5 @@ monkey_poll(bool active) free(fd_list[i]); } - schedule_run(); - - if (browser_reformat_pending) - monkey_window_process_reformats(); } diff --git a/riscos/gui.c b/riscos/gui.c index 09f254bb4..00f6ebc11 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -1852,24 +1852,19 @@ static void ro_gui_handle_event(wimp_event_no event, wimp_block *block) /** - * Poll the OS for events (RISC OS). - * - * \param active return as soon as possible + * Poll the RISC OS wimp for events. */ static void riscos_poll(bool active) { wimp_event_no event; wimp_block block; - const wimp_poll_flags mask = wimp_MASK_LOSE | wimp_MASK_GAIN | - wimp_SAVE_FP; + const wimp_poll_flags mask = wimp_MASK_LOSE | wimp_MASK_GAIN | wimp_SAVE_FP; os_t track_poll_offset; /* Poll wimp. */ xhourglass_off(); track_poll_offset = ro_mouse_poll_interval(); - if (active) { - event = wimp_poll(mask, &block, 0); - } else if (sched_active || (track_poll_offset > 0) || + if (sched_active || (track_poll_offset > 0) || browser_reformat_pending) { os_t t = os_read_monotonic_time(); diff --git a/windows/gui.c b/windows/gui.c index 21eff0ef4..824abade7 100644 --- a/windows/gui.c +++ b/windows/gui.c @@ -107,10 +107,6 @@ static void win32_poll(bool active) /* run the scheduler and discover how long to wait for the next event */ timeout = schedule_run(); - /* if active set timeout so message is not waited for */ - if (active) - timeout = 0; - if (timeout == 0) { bRet = PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE); } else { @@ -128,7 +124,6 @@ static void win32_poll(bool active) } } - if (bRet > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); -- cgit v1.2.3 From 0c5bb37bea878d6b0b622cb7ea6eab649e4c578b Mon Sep 17 00:00:00 2001 From: Chris Young Date: Sun, 29 Jun 2014 22:35:52 +0100 Subject: Implement a very basic favicon cache for the hotlist menu to use --- amiga/bitmap.c | 4 +++- amiga/bitmap.h | 1 + amiga/gui.c | 37 +++++++++++++++++++++++++++++++++++++ amiga/gui.h | 1 + amiga/menu.c | 16 +++++++++++++--- 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/amiga/bitmap.c b/amiga/bitmap.c index f25ac2b81..271978b2e 100644 --- a/amiga/bitmap.c +++ b/amiga/bitmap.c @@ -152,7 +152,9 @@ bool bitmap_save(void *bitmap, const char *path, unsigned flags) int err = 0; Object *dto = NULL; - if(!ami_download_check_overwrite(path, NULL, 0)) return false; + if ((flags & AMI_BITMAP_FORCE_OVERWRITE) == 0) { + if(!ami_download_check_overwrite(path, NULL, 0)) return false; + } if(dto = ami_datatype_object_from_bitmap(bitmap)) { diff --git a/amiga/bitmap.h b/amiga/bitmap.h index 0435aec5b..6657d2f8a 100755 --- a/amiga/bitmap.h +++ b/amiga/bitmap.h @@ -26,6 +26,7 @@ #include #define AMI_BITMAP_FORMAT RGBFB_R8G8B8A8 +#define AMI_BITMAP_FORCE_OVERWRITE 0xFF struct bitmap { int width; diff --git a/amiga/gui.c b/amiga/gui.c index 756ed63e2..8985d4f33 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -181,6 +181,7 @@ bool cli_force = false; static char *current_user; static char *current_user_dir; +static char *current_user_faviconcache; static const __attribute__((used)) char *stack_cookie = "\0$STACK:262144\0"; @@ -2769,9 +2770,40 @@ static void gui_quit(void) FreeVec(current_user_options); FreeVec(current_user_dir); + FreeVec(current_user_faviconcache); FreeVec(current_user); } +char *ami_gui_get_cache_favicon_name(nsurl *url, bool only_if_avail) +{ + STRPTR filename = NULL; + BPTR lock = 0; + + if (filename = ASPrintf("%s/%x", current_user_faviconcache, nsurl_hash(url))) { + LOG(("favicon cache location: %s", filename)); + + if (only_if_avail == true) { + if(lock = Lock(filename, ACCESS_READ)) { + UnLock(lock); + return filename; + } + } else { + return filename; + } + } + return NULL; +} + +static void ami_gui_cache_favicon(nsurl *url, struct bitmap *favicon) +{ + STRPTR filename = NULL; + + if (filename = ami_gui_get_cache_favicon_name(url, false)) { + if(favicon) bitmap_save(favicon, filename, AMI_BITMAP_FORCE_OVERWRITE); + FreeVec(filename); + } +} + void ami_gui_update_hotlist_button(struct gui_window_2 *gwin) { char *url; @@ -2785,6 +2817,9 @@ void ami_gui_update_hotlist_button(struct gui_window_2 *gwin) if(hotlist_has_url(nsurl)) { RefreshSetGadgetAttrs((struct Gadget *)gwin->objects[GID_FAVE], gwin->win, NULL, BUTTON_RenderImage, gwin->objects[GID_FAVE_RMV], TAG_DONE); + + if (gwin->bw->window->favicon) + ami_gui_cache_favicon(nsurl, content_get_bitmap(gwin->bw->window->favicon)); } else { RefreshSetGadgetAttrs((struct Gadget *)gwin->objects[GID_FAVE], gwin->win, NULL, BUTTON_RenderImage, gwin->objects[GID_FAVE_ADD], TAG_DONE); @@ -5127,8 +5162,10 @@ int main(int argc, char** argv) current_user_options = ASPrintf("%s/Choices", current_user_dir); current_user_cache = ASPrintf("%s/Cache", current_user_dir); + current_user_faviconcache = ASPrintf("%s/IconCache", current_user_dir); if(lock = CreateDirTree(current_user_cache)) UnLock(lock); + if(lock = CreateDirTree(current_user_faviconcache)) UnLock(lock); ami_mime_init("PROGDIR:Resources/mimetypes"); sprintf(temp, "%s/mimetypes.user", current_user_dir); diff --git a/amiga/gui.h b/amiga/gui.h index f5a9030c9..87258a1e4 100755 --- a/amiga/gui.h +++ b/amiga/gui.h @@ -167,6 +167,7 @@ void ami_gui_tabs_toggle_all(void); bool ami_locate_resource(char *fullpath, const char *file); void ami_gui_update_hotlist_button(struct gui_window_2 *gwin); nserror ami_gui_new_blank_tab(struct gui_window_2 *gwin); +char *ami_gui_get_cache_favicon_name(nsurl *url, bool only_if_avail); struct TextFont *origrpfont; struct MinList *window_list; diff --git a/amiga/menu.c b/amiga/menu.c index 43c8c188b..c6258be6f 100644 --- a/amiga/menu.c +++ b/amiga/menu.c @@ -405,6 +405,13 @@ static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) BITMAP_SourceFile, gwin->menuicon[i], BITMAP_Masking, TRUE, BitMapEnd; + + /* \todo make this scale the bitmap to these dimensions */ + SetAttrs(icon, + BITMAP_Width, 16, + BITMAP_Height, 16, + TAG_DONE); + GetAttr(IA_Width, icon, (ULONG *)&icon_width); if((gwin->menutype[i] == NM_ITEM) && (gwin->menutype[i+1] == NM_SUB)) { @@ -551,7 +558,7 @@ void ami_menu_arexx_scan(struct gui_window_2 *gwin) static bool ami_menu_hotlist_add(void *userdata, int level, int item, const char *title, nsurl *url, bool is_folder) { UBYTE type; - char *icon; + STRPTR icon; struct gui_window_2 *gw = (struct gui_window_2 *)userdata; if(item >= AMI_MENU_HOTLIST_MAX) return false; @@ -570,9 +577,10 @@ static bool ami_menu_hotlist_add(void *userdata, int level, int item, const char } if(is_folder == true) { - icon = "icons/directory.png"; + icon = ASPrintf("icons/directory.png"); } else { - icon = "icons/content.png"; + icon = ami_gui_get_cache_favicon_name(url, true); + if (icon == NULL) icon = ASPrintf("icons/content.png"); } ami_menu_alloc_item(gw, item, type, title, @@ -580,6 +588,8 @@ static bool ami_menu_hotlist_add(void *userdata, int level, int item, const char if((is_folder == true) && (type == NM_SUB)) gw->menu[item].nm_Flags = NM_ITEMDISABLED; + if(icon) FreeVec(icon); + return true; } -- cgit v1.2.3 From 01271f4061bbc8f8b26492a26e04bdbb8b9746c9 Mon Sep 17 00:00:00 2001 From: Chris Young Date: Mon, 30 Jun 2014 22:21:10 +0100 Subject: Re-enable favicon render hook. Not sure why or when this was disabled. --- amiga/gui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amiga/gui.c b/amiga/gui.c index 8985d4f33..6e84e7077 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -3542,7 +3542,7 @@ gui_window_create(struct browser_window *bw, SPACE_MinWidth, 16, SPACE_MinHeight, 16, SPACE_Transparent, FALSE, - // SPACE_RenderHook, &g->shared->favicon_hook, + SPACE_RenderHook, &g->shared->favicon_hook, SpaceEnd, CHILD_WeightedWidth, 0, CHILD_WeightedHeight, 0, -- cgit v1.2.3 From 846b53485474211a24248c9b0d5cc4205104a772 Mon Sep 17 00:00:00 2001 From: Chris Young Date: Mon, 30 Jun 2014 22:37:05 +0100 Subject: Recreate the entire menu when the hotlist window is closed. This ensures the hotlist entries in the menu are in sync with reality, and mirrors the existing hotlist toolbar update. --- amiga/gui.c | 6 +++++- amiga/gui.h | 2 +- amiga/menu.c | 8 -------- amiga/options.h | 2 -- amiga/tree.c | 2 +- 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/amiga/gui.c b/amiga/gui.c index 6e84e7077..543a77479 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -3030,7 +3030,10 @@ void ami_gui_hotlist_toolbar_update(struct gui_window_2 *gwin) } } -void ami_gui_hotlist_toolbar_update_all(void) +/** + * Update hotlist toolbar and recreate the menu for all windows + */ +void ami_gui_hotlist_update_all(void) { struct nsObject *node; struct nsObject *nnode; @@ -3047,6 +3050,7 @@ void ami_gui_hotlist_toolbar_update_all(void) if(node->Type == AMINS_WINDOW) { ami_gui_hotlist_toolbar_update(gwin); + ami_menu_refresh(gwin); } } while(node = nnode); } diff --git a/amiga/gui.h b/amiga/gui.h index 87258a1e4..c106455d1 100755 --- a/amiga/gui.h +++ b/amiga/gui.h @@ -162,7 +162,7 @@ int ami_key_to_nskey(ULONG keycode, struct InputEvent *ie); bool ami_text_box_at_point(struct gui_window_2 *gwin, ULONG *x, ULONG *y); BOOL ami_gadget_hit(Object *obj, int x, int y); void ami_gui_history(struct gui_window_2 *gwin, bool back); -void ami_gui_hotlist_toolbar_update_all(void); +void ami_gui_hotlist_update_all(void); void ami_gui_tabs_toggle_all(void); bool ami_locate_resource(char *fullpath, const char *file); void ami_gui_update_hotlist_button(struct gui_window_2 *gwin); diff --git a/amiga/menu.c b/amiga/menu.c index c6258be6f..784fec163 100644 --- a/amiga/menu.c +++ b/amiga/menu.c @@ -485,14 +485,6 @@ struct NewMenu *ami_create_menu(struct gui_window_2 *gwin) if(nsoption_bool(background_images) == true) gwin->menu[M_IMGBACK].nm_Flags |= CHECKED; - /* Set up scheduler to refresh the hotlist menu */ - if(nsoption_int(menu_refresh) > 0) - { - ami_schedule(nsoption_int(menu_refresh) * 10, - (void *)ami_menu_refresh, - gwin); - } - return(gwin->menu); } diff --git a/amiga/options.h b/amiga/options.h index e383dcf9a..868e28fdb 100644 --- a/amiga/options.h +++ b/amiga/options.h @@ -86,6 +86,4 @@ NSOPTION_INTEGER(redraw_tile_size_y, 0) NSOPTION_INTEGER(monitor_aspect_x, 0) NSOPTION_INTEGER(monitor_aspect_y, 0) NSOPTION_BOOL(accept_lang_locale, true) -NSOPTION_INTEGER(menu_refresh, 0) - diff --git a/amiga/tree.c b/amiga/tree.c index 04c799603..18b071de3 100644 --- a/amiga/tree.c +++ b/amiga/tree.c @@ -711,7 +711,7 @@ void ami_tree_close(struct treeview_window *twin) ami_ssl_free(twin); } - ami_gui_hotlist_toolbar_update_all(); + ami_gui_hotlist_update_all(); } void ami_tree_update_quals(struct treeview_window *twin) -- cgit v1.2.3 From 1aed82b07428d17b74435c29ac240de8288b85ab Mon Sep 17 00:00:00 2001 From: Chris Young Date: Mon, 30 Jun 2014 22:38:58 +0100 Subject: fix warnings --- amiga/launch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/amiga/launch.c b/amiga/launch.c index 1405d6a71..d3c9ff11e 100755 --- a/amiga/launch.c +++ b/amiga/launch.c @@ -31,6 +31,7 @@ #include #include "utils/nsoption.h" +#include "utils/nsurl.h" #include "utils/url.h" struct Library *OpenURLBase = NULL; -- cgit v1.2.3 From 01088bb63b1ab1ff7453c199a1c875483b1e5084 Mon Sep 17 00:00:00 2001 From: Chris Young Date: Tue, 1 Jul 2014 08:28:07 +0100 Subject: Re-disable the favicon render hook --- amiga/gui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amiga/gui.c b/amiga/gui.c index 543a77479..487128d32 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -3546,7 +3546,7 @@ gui_window_create(struct browser_window *bw, SPACE_MinWidth, 16, SPACE_MinHeight, 16, SPACE_Transparent, FALSE, - SPACE_RenderHook, &g->shared->favicon_hook, + // SPACE_RenderHook, &g->shared->favicon_hook, SpaceEnd, CHILD_WeightedWidth, 0, CHILD_WeightedHeight, 0, -- cgit v1.2.3 From 06eb81235d975bc7721719d25ac114b4ab2c94da Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Tue, 1 Jul 2014 09:17:22 +0100 Subject: fix fetchers include on windows --- content/fetchers.h | 2 +- utils/config.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/content/fetchers.h b/content/fetchers.h index 3303379d2..d123de986 100644 --- a/content/fetchers.h +++ b/content/fetchers.h @@ -23,7 +23,7 @@ #ifndef _NETSURF_DESKTOP_FETCHERS_H_ #define _NETSURF_DESKTOP_FETCHERS_H_ -#include +#include "utils/config.h" #include struct nsurl; diff --git a/utils/config.h b/utils/config.h index c0a3c0d1b..d44359576 100644 --- a/utils/config.h +++ b/utils/config.h @@ -58,15 +58,18 @@ char *strcasestr(const char *haystack, const char *needle); char *strchrnul(const char *s, int c); #endif +#define HAVE_SYS_SELECT #define HAVE_INETATON #if (defined(_WIN32)) #undef HAVE_INETATON +#undef HAVE_SYS_SELECT #include #define EAFNOSUPPORT WSAEAFNOSUPPORT int inet_aton(const char *cp, struct in_addr *inp); #else #include #include +#include #endif #define HAVE_INETPTON -- cgit v1.2.3 From 18aefabd20a16dda9ed5363088f0da5ada0d4431 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 30 Jun 2014 16:40:56 +0100 Subject: change reformat to be driven from the scheduler like redraw --- amiga/gui.c | 37 ++++++++++++++++---------------- atari/deskmenu.c | 8 +++++-- atari/gui.c | 21 ++++++------------ atari/gui.h | 3 --- atari/rootwin.c | 2 +- beos/gui.cpp | 30 ++++++++------------------ beos/window.cpp | 54 ++++++++++++++++++----------------------------- beos/window.h | 1 - cocoa/BrowserView.m | 29 +------------------------ cocoa/gui.m | 17 +++++++++++++-- desktop/browser.c | 23 ++++++++++++++------ desktop/browser.h | 17 +++++++++++++-- desktop/browser_private.h | 3 --- desktop/gui.h | 15 ++++++++++++- desktop/gui_factory.c | 3 +++ framebuffer/gui.c | 10 +++++++++ gtk/gui.c | 5 ----- gtk/window.c | 32 +++++++++------------------- gtk/window.h | 1 - monkey/browser.c | 19 ++++++----------- monkey/poll.c | 5 ----- riscos/gui.c | 14 ++++++------ riscos/gui.h | 1 - riscos/window.c | 45 ++++++++++++++------------------------- windows/gui.c | 12 ++++++++++- 25 files changed, 187 insertions(+), 220 deletions(-) diff --git a/amiga/gui.c b/amiga/gui.c index 6b02cac4f..bc01ff99e 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -2128,12 +2128,11 @@ void ami_handle_msg(void) GetClickTabNodeAttrs(tab, TNA_UserData, &bw, TAG_DONE); - bw->reformat_pending = true; } while(tab=ntab); } refresh_favicon = TRUE; - gwin->bw->reformat_pending = true; + browser_window_schedule_reformat(gwin->bw); ami_schedule_redraw(gwin, true); break; } @@ -2204,11 +2203,6 @@ void ami_handle_msg(void) if(node->Type == AMINS_WINDOW) { - /* Catch any reformats tagged by the core - only used by scale? */ - if(gwin->bw->reformat_pending) { - ami_schedule_redraw(gwin, true); - } - if(gwin->bw->window->throbbing) ami_update_throbber(gwin,false); } @@ -2950,7 +2944,6 @@ void ami_gui_hotlist_toolbar_add(struct gui_window_2 *gwin) gwin->win, NULL, TRUE); if(gwin->bw) { - gwin->bw->reformat_pending = true; ami_schedule_redraw(gwin, true); } } @@ -2992,7 +2985,6 @@ void ami_gui_hotlist_toolbar_remove(struct gui_window_2 *gwin) RethinkLayout((struct Gadget *)gwin->objects[GID_MAIN], gwin->win, NULL, TRUE); - gwin->bw->reformat_pending = true; ami_schedule_redraw(gwin, true); } @@ -3105,7 +3097,6 @@ void ami_toggletabbar(struct gui_window_2 *gwin, bool show) gwin->win, NULL, TRUE); if(gwin->bw) { - gwin->bw->reformat_pending = true; ami_schedule_redraw(gwin, true); } } @@ -4031,7 +4022,7 @@ static void ami_redraw_callback(void *p) { struct gui_window_2 *gwin = (struct gui_window_2 *)p; - if(gwin->redraw_required || gwin->bw->reformat_pending) { + if(gwin->redraw_required) { ami_do_redraw(gwin); } @@ -4060,7 +4051,6 @@ void ami_schedule_redraw(struct gui_window_2 *gwin, bool full_redraw) if(full_redraw) gwin->redraw_required = true; if(gwin->redraw_scheduled == true) return; - if(gwin->bw->reformat_pending) ms = nsoption_int(reformat_delay) * 10; ami_schedule(ms, ami_redraw_callback, gwin); gwin->redraw_scheduled = true; } @@ -4291,6 +4281,21 @@ static void gui_window_update_box(struct gui_window *g, const struct rect *rect) ami_schedule_redraw(g->shared, false); } +/** + * callback from core to reformat a window. + */ +static void amiga_window_reformat(struct gui_window *gw) +{ + struct IBox *bbox; + + if (gw != NULL) { + GetAttr(SPACE_AreaBox, (Object *)gw->shared->objects[GID_BROWSER], (ULONG *)&bbox); + browser_window_reformat(gw->shared->bw, false, bbox->Width, bbox->Height); + + gw->shared->redraw_scroll = false; + } +} + static void ami_do_redraw(struct gui_window_2 *gwin) { struct Rectangle rect; @@ -4313,13 +4318,6 @@ static void ami_do_redraw(struct gui_window_2 *gwin) xoffset=bbox->Left; yoffset=bbox->Top; - if(gwin->bw->reformat_pending) - { - browser_window_reformat(gwin->bw, false, width, height); - gwin->bw->reformat_pending = false; - gwin->redraw_scroll = false; - } - if(gwin->redraw_scroll) { if((abs(vcurrent-oldv) > height) || (abs(hcurrent-oldh) > width)) @@ -5060,6 +5058,7 @@ static struct gui_window_table amiga_window_table = { .set_scroll = gui_window_set_scroll, .get_dimensions = gui_window_get_dimensions, .update_extent = gui_window_update_extent, + .reformat = amiga_window_reformat, .set_icon = gui_window_set_icon, .set_title = gui_window_set_title, diff --git a/atari/deskmenu.c b/atari/deskmenu.c index 8de2e327f..53e24a4d4 100644 --- a/atari/deskmenu.c +++ b/atari/deskmenu.c @@ -394,7 +394,9 @@ static void __CDECL menu_inc_scale(short item, short title, void *data) if(input_window == NULL) return; - gui_window_set_scale(input_window, gui_window_get_scale(input_window)+0.25); + browser_window_set_scale(input_window->bw, + browser_window_get_scale(input_window->bw) + 0.25, + true); } @@ -403,7 +405,9 @@ static void __CDECL menu_dec_scale(short item, short title, void *data) if(input_window == NULL) return; - gui_window_set_scale(input_window, gui_window_get_scale(input_window)-0.25); + browser_window_set_scale(input_window->bw, + browser_window_get_scale(input_window->bw) - 0.25, + true); } diff --git a/atari/gui.c b/atari/gui.c index 608d0d859..efa23efe4 100644 --- a/atari/gui.c +++ b/atari/gui.c @@ -201,7 +201,6 @@ gui_window_create(struct browser_window *bw, option_window_x, option_window_y, option_window_width, option_window_height }; - gui_window_set_scale(gw, 1.0); gui_window_set_url(gw, ""); gui_window_set_pointer(gw, BROWSER_POINTER_DEFAULT); gui_set_input_gui_window(gw); @@ -343,21 +342,14 @@ void gui_window_set_status(struct gui_window *w, const char *text) window_set_stauts(w->root, (char*)text); } -float gui_window_get_scale(struct gui_window *gw) +static void atari_window_reformat(struct gui_window *gw) { - return(gw->scale); -} - -void gui_window_set_scale(struct gui_window *gw, float scale) -{ - int width = 0, heigth = 0; + int width = 0, height = 0; - LOG(("scale: %f", scale)); - - gw->scale = MAX(scale, 0.25); - - gui_window_get_dimensions(gw, &width, &heigth, true); - browser_window_reformat(gw->browser->bw, false, width, heigth); + if (gw != NULL) { + gui_window_get_dimensions(gw, &width, &height, true); + browser_window_reformat(gw->browser->bw, false, width, height); + } } static void gui_window_redraw_window(struct gui_window *gw) @@ -1017,6 +1009,7 @@ static struct gui_window_table atari_window_table = { .set_scroll = gui_window_set_scroll, .get_dimensions = gui_window_get_dimensions, .update_extent = gui_window_update_extent, + .reformat = atari_window_reformat, .set_title = gui_window_set_title, .set_url = gui_window_set_url, diff --git a/atari/gui.h b/atari/gui.h index 978c0d093..10736c5f8 100755 --- a/atari/gui.h +++ b/atari/gui.h @@ -149,7 +149,6 @@ struct gui_window { char * title; char * url; struct bitmap * icon; - float scale; struct s_caret caret; struct s_search_form_session *search; struct gui_window *next, *prev; @@ -168,7 +167,5 @@ char *gui_window_get_title(struct gui_window *gw); void gui_window_set_status(struct gui_window *w, const char *text); void gui_window_set_pointer(struct gui_window *gw, gui_pointer_shape shape); void gui_window_destroy(struct gui_window *w); -void gui_window_set_scale(struct gui_window *gw, float scale); -float gui_window_get_scale(struct gui_window *gw); #endif diff --git a/atari/rootwin.c b/atari/rootwin.c index fde0bd3b5..7c2cdbcf1 100755 --- a/atari/rootwin.c +++ b/atari/rootwin.c @@ -834,7 +834,7 @@ static void window_redraw_content(ROOTWIN *rootwin, GRECT *content_area, plot_set_dimensions(content_area->g_x, content_area->g_y, content_area->g_w, content_area->g_h); - oldscale = plot_set_scale(gui_window_get_scale(rootwin->active_gui_window)); + oldscale = plot_set_scale(browser_window_get_scale(rootwin->active_gui_window->bw)); /* first, we make the coords relative to the content area: */ content_area_rel.g_x = clip->g_x - content_area->g_x; diff --git a/beos/gui.cpp b/beos/gui.cpp index f9e02d0de..84f397b0b 100644 --- a/beos/gui.cpp +++ b/beos/gui.cpp @@ -713,7 +713,6 @@ static void gui_poll(bool active) int max_fd; struct timeval timeout; unsigned int fd_count = 0; - bool block = true; bigtime_t next_schedule = 0; /* get any active fetcher fd */ @@ -728,34 +727,23 @@ static void gui_poll(bool active) /** @todo Check if this max_fd should have + 1 */ max_fd = MAX(max_fd, sEventPipe[0] + 1); - // If there are pending events elsewhere, we should not be blocking - if (!browser_reformat_pending) { - if (earliest_callback_timeout != B_INFINITE_TIMEOUT) { - next_schedule = earliest_callback_timeout - system_time(); - block = false; - } - - // we're quite late already... - if (next_schedule < 0) - next_schedule = 0; - - } else {//we're not allowed to sleep, there is other activity going on. - nsbeos_window_process_reformats(); - block = false; + // compute schedule timeout + if (earliest_callback_timeout != B_INFINITE_TIMEOUT) { + next_schedule = earliest_callback_timeout - system_time(); + } else { + next_schedule = earliest_callback_timeout; } - /* - LOG(("gui_poll: browser_reformat_pending:%d earliest_callback_timeout:%Ld" - " next_schedule:%Ld block:%d ", browser_reformat_pending, - earliest_callback_timeout, next_schedule, block)); - */ + // we're quite late already... + if (next_schedule < 0) + next_schedule = 0; timeout.tv_sec = (long)(next_schedule / 1000000LL); timeout.tv_usec = (long)(next_schedule % 1000000LL); //LOG(("gui_poll: select(%d, ..., %Ldus", max_fd, next_schedule)); fd_count = select(max_fd, &read_fd_set, &write_fd_set, &exc_fd_set, - block ? NULL : &timeout); + &timeout); //LOG(("select: %d\n", fd_count)); if (fd_count > 0 && FD_ISSET(sEventPipe[0], &read_fd_set)) { diff --git a/beos/window.cpp b/beos/window.cpp index 8975c1871..d27bca758 100644 --- a/beos/window.cpp +++ b/beos/window.cpp @@ -883,9 +883,7 @@ void nsbeos_window_resize_event(BView *view, gui_window *g, BMessage *event) width++; height++; - - g->bw->reformat_pending = true; - browser_reformat_pending = true; + browser_window_schedule_reformat(g->bw); return; } @@ -901,51 +899,40 @@ void nsbeos_window_moved_event(BView *view, gui_window *g, BMessage *event) //view->Invalidate(view->Bounds()); view->UnlockLooper(); - //g->bw->reformat_pending = true; - //browser_reformat_pending = true; - - return; } void nsbeos_reflow_all_windows(void) { - for (struct gui_window *g = window_list; g; g = g->next) - g->bw->reformat_pending = true; - - browser_reformat_pending = true; + for (struct gui_window *g = window_list; g; g = g->next) { + browser_window_schedule_reformat(g->bw); + } } + /** - * Process pending reformats + * callback from core to reformat a window. */ - -void nsbeos_window_process_reformats(void) +static void beos_window_reformat(struct gui_window *g) { - struct gui_window *g; - - browser_reformat_pending = false; - for (g = window_list; g; g = g->next) { - NSBrowserFrameView *view = g->view; - if (!g->bw->reformat_pending) - continue; - if (!view || !view->LockLooper()) - continue; - g->bw->reformat_pending = false; - BRect bounds = view->Bounds(); - view->UnlockLooper(); + if (g == NULL) { + return; + } + + NSBrowserFrameView *view = g->view; + if (view && view->LockLooper()) { + BRect bounds = view->Bounds(); + view->UnlockLooper(); #warning XXX why - 1 & - 2 !??? - browser_window_reformat(g->bw, - false, - bounds.Width() + 1 /* - 2*/, - bounds.Height() + 1); - } - + browser_window_reformat(g->bw, + false, + bounds.Width() + 1 /* - 2*/, + bounds.Height() + 1); + } } - void nsbeos_window_destroy_browser(struct gui_window *g) { browser_window_destroy(g->bw); @@ -1356,6 +1343,7 @@ static struct gui_window_table window_table = { gui_window_set_scroll, gui_window_get_dimensions, gui_window_update_extent, + beos_window_reformat, /* from scaffold */ gui_window_set_title, diff --git a/beos/window.h b/beos/window.h index fb67517d2..0e38d88ed 100644 --- a/beos/window.h +++ b/beos/window.h @@ -51,7 +51,6 @@ void nsbeos_dispatch_event(BMessage *message); void nsbeos_reflow_all_windows(void); -void nsbeos_window_process_reformats(void); nsbeos_scaffolding *nsbeos_get_scaffold(struct gui_window *g); struct browser_window *nsbeos_get_browser_for_gui(struct gui_window *g); diff --git a/cocoa/BrowserView.m b/cocoa/BrowserView.m index b0042f760..2a3382c8c 100644 --- a/cocoa/BrowserView.m +++ b/cocoa/BrowserView.m @@ -38,7 +38,6 @@ - (void) scrollVertical: (CGFloat) amount; - (CGFloat) pageScroll; -+ (void)reformatTimerFired: (NSTimer *) timer; - (void) reformat; - (void) popUpContextMenuForEvent: (NSEvent *) event; @@ -60,8 +59,6 @@ static const CGFloat CaretWidth = 1.0; static const NSTimeInterval CaretBlinkTime = 0.8; -static NSMutableArray *cocoa_reformat_pending = nil; - - initWithFrame: (NSRect) frame; { @@ -438,13 +435,7 @@ static browser_mouse_state cocoa_mouse_flags_for_event( NSEvent *evt ) - (void) adjustFrame; { - browser->reformat_pending = true; - browser_reformat_pending = true; - - if (cocoa_reformat_pending == nil) { - cocoa_reformat_pending = [[NSMutableArray alloc] init]; - } - [cocoa_reformat_pending addObject: self]; + browser_window_schedule_reformat(browser); [super adjustFrame]; } @@ -492,24 +483,6 @@ static browser_mouse_state cocoa_mouse_flags_for_event( NSEvent *evt ) browser_window_reformat( browser, false, cocoa_pt_to_px( NSWidth( size ) ), cocoa_pt_to_px( NSHeight( size ) ) ); } -+ (void)reformatTimerFired: (NSTimer *) timer; -{ - if (browser_reformat_pending) { - [cocoa_reformat_pending makeObjectsPerformSelector: @selector( reformat )]; - [cocoa_reformat_pending removeAllObjects]; - browser_reformat_pending = false; - } -} - -+ (void) initialize; -{ - NSTimer *timer = [[NSTimer alloc] initWithFireDate: nil interval: 0.02 - target: self selector: @selector(reformatTimerFired:) - userInfo: nil repeats: YES]; - [[NSRunLoop currentRunLoop] addTimer: timer forMode: NSRunLoopCommonModes]; - [timer release]; -} - - (void) popUpContextMenuForEvent: (NSEvent *) event; { if (content_get_type( browser->current_content ) != CONTENT_HTML) return; diff --git a/cocoa/gui.m b/cocoa/gui.m index 713f456cd..405dab9c2 100644 --- a/cocoa/gui.m +++ b/cocoa/gui.m @@ -129,8 +129,20 @@ static void gui_window_set_scroll(struct gui_window *g, int sx, int sy) [[(BrowserViewController *)g browserView] scrollPoint: cocoa_point( sx, sy )]; } -static void gui_window_get_dimensions(struct gui_window *g, int *width, int *height, - bool scaled) +/** + * callback from core to reformat a window. + */ +static void cocoa_window_reformat(struct gui_window *gw) +{ + if (gw != NULL) { + [[(BrowserViewController *)g browserView] reformat ]; + } +} + + +static void gui_window_get_dimensions(struct gui_window *g, + int *width, int *height, + bool scaled) { NSCParameterAssert( width != NULL && height != NULL ); @@ -278,6 +290,7 @@ static struct gui_window_table window_table = { .set_scroll = gui_window_set_scroll, .get_dimensions = gui_window_get_dimensions, .update_extent = gui_window_update_extent, + .reformat = cocoa_window_reformat, .set_title = gui_window_set_title, .set_url = gui_window_set_url, diff --git a/desktop/browser.c b/desktop/browser.c index 6e3ed9718..dc2db723c 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -66,14 +66,11 @@ #include "utils/utils.h" #include "utils/utf8.h" -/** one or more windows require a reformat */ -bool browser_reformat_pending; /** maximum frame depth */ #define FRAME_DEPTH 8 - /** * Get position of scrollbar widget within browser window. * @@ -795,7 +792,6 @@ nserror browser_window_initialise_common(enum browser_window_create_flags flags, /* window characteristics */ bw->refresh_interval = -1; - bw->reformat_pending = false; bw->drag_type = DRAGGING_NONE; bw->scale = (float) nsoption_int(scale) / 100.0; @@ -1623,7 +1619,13 @@ void browser_window_destroy_internal(struct browser_window *bw) browser_window_destroy_children(bw); } + /* clear any pending callbacks */ guit->browser->schedule(-1, browser_window_refresh, bw); + /* The ugly cast here is so the reformat function can be + * passed a gui window pointer in its API rather than void* + */ + LOG(("Clearing schedule %p(%p)", guit->window->reformat, bw->window)); + guit->browser->schedule(-1, (void(*)(void*))guit->window->reformat, bw->window); /* If this brower window is not the root window, and has focus, unset * the root browser window's focus pointer. */ @@ -2362,6 +2364,16 @@ void browser_window_set_pointer(struct browser_window *bw, guit->window->set_pointer(root->window, gui_shape); } +/* exported function documented in desktop/browser.h */ +nserror browser_window_schedule_reformat(struct browser_window *bw) +{ + /* The ugly cast here is so the reformat function can be + * passed a gui window pointer in its API rather than void* + */ + LOG(("Scheduleing %p(%p)", guit->window->reformat, bw->window)); + guit->browser->schedule(0, (void(*)(void*))guit->window->reformat, bw->window); + return NSERROR_OK; +} /** * Reformat a browser window contents to a new width or height. @@ -2413,8 +2425,7 @@ static void browser_window_set_scale_internal(struct browser_window *bw, if (content_can_reformat(c) == false) { browser_window_update(bw, false); } else { - bw->reformat_pending = true; - browser_reformat_pending = true; + browser_window_schedule_reformat(bw); } } diff --git a/desktop/browser.h b/desktop/browser.h index ca99a5d16..88b757727 100644 --- a/desktop/browser.h +++ b/desktop/browser.h @@ -60,8 +60,6 @@ typedef enum { BW_EDITOR_CAN_PASTE = (1 << 2) /**< Can paste, input */ } browser_editor_flags; -extern bool browser_reformat_pending; - /** flags to browser_window_create */ enum browser_window_create_flags { /** No flags set */ @@ -259,6 +257,21 @@ struct browser_window *browser_window_find_target( struct browser_window *bw, const char *target, browser_mouse_state mouse); +/** + * Cause the frontends reformat entry to be called in safe context. + * + * The browser_window_reformat call cannot safely be called from some + * contexts, this call allows for the reformat to happen from a safe + * top level context. + * + * The callback is frontend provided as the context information (size + * etc.) about the windowing toolkit is only available to the + * frontend. + */ +nserror browser_window_schedule_reformat(struct browser_window *bw); + + + void browser_select_menu_callback(void *client_data, int x, int y, int width, int height); diff --git a/desktop/browser_private.h b/desktop/browser_private.h index 339bc46ee..cbc29aaa3 100644 --- a/desktop/browser_private.h +++ b/desktop/browser_private.h @@ -87,9 +87,6 @@ struct browser_window { /** Refresh interval (-1 if undefined) */ int refresh_interval; - /** Window has been resized, and content needs reformatting. */ - bool reformat_pending; - /** Window dimensions */ int x; int y; diff --git a/desktop/gui.h b/desktop/gui.h index d44b57d1c..a19f30115 100644 --- a/desktop/gui.h +++ b/desktop/gui.h @@ -105,7 +105,9 @@ struct gui_window_table { struct gui_window *existing, gui_window_create_flags flags); - /** destroy previously created gui window */ + /** + * Destroy previously created gui window + */ void (*destroy)(struct gui_window *g); /** @@ -168,6 +170,17 @@ struct gui_window_table { */ void (*update_extent)(struct gui_window *g); + /** + * Reformat a window. + * + * This is used to perform reformats when the page contents + * require reformating. The reformat is requested using + * browser_window_schedule_reformat and occours via a scheduled + * callback hence from top level context. + * + * \param g gui_window to reformat. + */ + void (*reformat)(struct gui_window *g); /* Optional entries */ diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c index fd0867491..977805e9c 100644 --- a/desktop/gui_factory.c +++ b/desktop/gui_factory.c @@ -154,6 +154,9 @@ static nserror verify_window_register(struct gui_window_table *gwt) if (gwt->update_extent == NULL) { return NSERROR_BAD_PARAMETER; } + if (gwt->reformat == NULL) { + return NSERROR_BAD_PARAMETER; + } /* fill in the optional entries with defaults */ diff --git a/framebuffer/gui.c b/framebuffer/gui.c index 0632bf3c6..727319f0f 100644 --- a/framebuffer/gui.c +++ b/framebuffer/gui.c @@ -1758,6 +1758,15 @@ gui_window_remove_caret(struct gui_window *g) } } +static void nsgtk_window_reformat(struct gui_window *gw) +{ + /** @todo if we ever do zooming reformat should be implemented */ + LOG(("window:%p", gw)); + + /* + browser_window_reformat(gw->bw, false, width, height); + */ +} static struct gui_window_table framebuffer_window_table = { .create = gui_window_create, @@ -1768,6 +1777,7 @@ static struct gui_window_table framebuffer_window_table = { .set_scroll = gui_window_set_scroll, .get_dimensions = gui_window_get_dimensions, .update_extent = gui_window_update_extent, + .reformat = framebuffer_window_reformat, .set_url = gui_window_set_url, .set_status = gui_window_set_status, diff --git a/gtk/gui.c b/gtk/gui.c index 9cd89e627..bb83721fe 100644 --- a/gtk/gui.c +++ b/gtk/gui.c @@ -518,11 +518,6 @@ static void nsgtk_poll(bool active) schedule_run(); - if (browser_reformat_pending) { - nsgtk_window_process_reformats(); - block = false; - } - gtk_main_iteration_do(block); for (unsigned int i = 0; i != fd_count; i++) { diff --git a/gtk/window.c b/gtk/window.c index a3d6d4936..d1cd6b1a5 100644 --- a/gtk/window.c +++ b/gtk/window.c @@ -638,9 +638,7 @@ static gboolean nsgtk_window_size_allocate_event(GtkWidget *widget, { struct gui_window *g = data; - g->bw->reformat_pending = true; - browser_reformat_pending = true; - + browser_window_schedule_reformat(g->bw); return TRUE; } @@ -854,35 +852,24 @@ gui_window_create(struct browser_window *bw, void nsgtk_reflow_all_windows(void) { for (struct gui_window *g = window_list; g; g = g->next) { - nsgtk_tab_options_changed( - nsgtk_scaffolding_notebook(g->scaffold)); - g->bw->reformat_pending = true; + nsgtk_tab_options_changed(nsgtk_scaffolding_notebook(g->scaffold)); + browser_window_schedule_reformat(g->bw); } - - browser_reformat_pending = true; } /** - * Process pending reformats + * callback from core to reformat a window. */ - -void nsgtk_window_process_reformats(void) +static void nsgtk_window_reformat(struct gui_window *gw) { - struct gui_window *g; GtkAllocation alloc; - browser_reformat_pending = false; - for (g = window_list; g; g = g->next) { - if (!g->bw->reformat_pending) - continue; - - g->bw->reformat_pending = false; - - /* @todo consider gtk_widget_get_allocated_width() */ - nsgtk_widget_get_allocation(GTK_WIDGET(g->layout), &alloc); + if (gw != NULL) { + /** @todo consider gtk_widget_get_allocated_width() */ + nsgtk_widget_get_allocation(GTK_WIDGET(gw->layout), &alloc); - browser_window_reformat(g->bw, false, alloc.width, alloc.height); + browser_window_reformat(gw->bw, false, alloc.width, alloc.height); } } @@ -1242,6 +1229,7 @@ static struct gui_window_table window_table = { .set_scroll = gui_window_set_scroll, .get_dimensions = gui_window_get_dimensions, .update_extent = gui_window_update_extent, + .reformat = nsgtk_window_reformat, .set_icon = gui_window_set_icon, .set_status = gui_window_set_status, diff --git a/gtk/window.h b/gtk/window.h index e4a4fda6a..01345b993 100644 --- a/gtk/window.h +++ b/gtk/window.h @@ -36,7 +36,6 @@ struct browser_window *nsgtk_get_browser_window(struct gui_window *g); nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *g); GdkPixbuf *nsgtk_get_icon(struct gui_window *gw); void nsgtk_reflow_all_windows(void); -void nsgtk_window_process_reformats(void); float nsgtk_get_scale_for_gui(struct gui_window *g); int nsgtk_gui_window_update_targets(struct gui_window *g); void nsgtk_window_destroy_browser(struct gui_window *g); diff --git a/monkey/browser.c b/monkey/browser.c index e61d6deb3..0e488c578 100644 --- a/monkey/browser.c +++ b/monkey/browser.c @@ -64,19 +64,13 @@ monkey_find_window_by_content(hlcache_handle *content) return ret; } -void -monkey_window_process_reformats(void) + +/** + * callback from core to reformat a window. + */ +static void monkey_window_reformat(struct gui_window *gw) { - RING_ITERATE_START(struct gui_window, gw_ring, c_ring) { - if (c_ring == NULL) - RING_ITERATE_STOP(gw_ring, c_ring); - if (c_ring->bw->reformat_pending) { - browser_window_reformat(c_ring->bw, - false, - c_ring->width, - c_ring->height); - } - } RING_ITERATE_END(gw_ring, c_ring); + browser_window_reformat(gw->bw, false, gw->width, gw->height); } void @@ -511,6 +505,7 @@ static struct gui_window_table window_table = { .set_scroll = gui_window_set_scroll, .get_dimensions = gui_window_get_dimensions, .update_extent = gui_window_update_extent, + .reformat = monkey_window_reformat, .set_title = gui_window_set_title, .set_url = gui_window_set_url, diff --git a/monkey/poll.c b/monkey/poll.c index d5b49f059..e65f2d3e2 100644 --- a/monkey/poll.c +++ b/monkey/poll.c @@ -126,11 +126,6 @@ monkey_poll(bool active) schedule_run(); - if (browser_reformat_pending) { - monkey_window_process_reformats(); - block = false; - } - LOG(("Iterate %sblocking", block?"":"non-")); if (block) { fprintf(stdout, "GENERIC POLL BLOCKING\n"); diff --git a/riscos/gui.c b/riscos/gui.c index 00f6ebc11..3253f796f 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -1864,17 +1864,18 @@ static void riscos_poll(bool active) /* Poll wimp. */ xhourglass_off(); track_poll_offset = ro_mouse_poll_interval(); - if (sched_active || (track_poll_offset > 0) || - browser_reformat_pending) { + if (sched_active || (track_poll_offset > 0)) { os_t t = os_read_monotonic_time(); - if (track_poll_offset > 0) + if (track_poll_offset > 0) { t += track_poll_offset; - else + } else { t += 10; + } - if (sched_active && (sched_time - t) < 0) + if (sched_active && (sched_time - t) < 0) { t = sched_time; + } event = wimp_poll_idle(mask, &block, t, 0); } else { @@ -1895,9 +1896,6 @@ static void riscos_poll(bool active) } ro_gui_window_update_boxes(); - - if (browser_reformat_pending && event == wimp_NULL_REASON_CODE) - ro_gui_window_process_reformats(); } diff --git a/riscos/gui.h b/riscos/gui.h index bc59b5db9..3403f551e 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -134,7 +134,6 @@ void ro_gui_window_iconise(struct gui_window *g, bool ro_gui_toolbar_dataload(struct gui_window *g, wimp_message *message); void ro_gui_window_redraw_all(void); void ro_gui_window_update_boxes(void); -void ro_gui_window_process_reformats(void); void ro_gui_window_quit(void); /* void ro_gui_window_close_all(void); */ #define ro_gui_window_close_all ro_gui_window_quit /* no need for a separate fn */ diff --git a/riscos/window.c b/riscos/window.c index e1eaf871d..3bb359d31 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -975,7 +975,6 @@ static void gui_window_update_extent(struct gui_window *g) os_error *error; wimp_window_info info; wimp_window_state state; - bool update; unsigned int flags; assert(g); @@ -995,9 +994,8 @@ static void gui_window_update_extent(struct gui_window *g) info.yscroll += scroll; } - /* only allow a further reformat if we've gained/lost scrollbars */ + /* only schedule a reformat if we've gained/lost scrollbars */ flags = info.flags & (wimp_WINDOW_HSCROLL | wimp_WINDOW_VSCROLL); - update = g->bw->reformat_pending; g->update_extent = true; ro_gui_window_open(PTR_WIMP_OPEN(&info)); @@ -1009,8 +1007,9 @@ static void gui_window_update_extent(struct gui_window *g) warn_user("WimpError", error->errmess); return; } - if (flags == (state.flags & (wimp_WINDOW_HSCROLL | wimp_WINDOW_VSCROLL))) - g->bw->reformat_pending = update; + if (flags == (state.flags & (wimp_WINDOW_HSCROLL | wimp_WINDOW_VSCROLL))) { + browser_window_schedule_reformat(g->bw); + } } @@ -1563,8 +1562,7 @@ void ro_gui_window_open(wimp_open *open) height -= size; state.visible.y0 += size; if (h) { - g->bw->reformat_pending = true; - browser_reformat_pending = true; + browser_window_schedule_reformat(g->bw); } } state.flags |= wimp_WINDOW_HSCROLL; @@ -1573,8 +1571,7 @@ void ro_gui_window_open(wimp_open *open) height += size; state.visible.y0 -= size; if (h) { - g->bw->reformat_pending = true; - browser_reformat_pending = true; + browser_window_schedule_reformat(g->bw); } } state.flags &= ~wimp_WINDOW_HSCROLL; @@ -1589,8 +1586,7 @@ void ro_gui_window_open(wimp_open *open) width -= size; state.visible.x1 -= size; if (h) { - g->bw->reformat_pending = true; - browser_reformat_pending = true; + browser_window_schedule_reformat(g->bw); } } state.flags |= wimp_WINDOW_VSCROLL; @@ -1599,8 +1595,7 @@ void ro_gui_window_open(wimp_open *open) width += size; state.visible.x1 += size; if (h) { - g->bw->reformat_pending = true; - browser_reformat_pending = true; + browser_window_schedule_reformat(g->bw); } } state.flags &= ~wimp_WINDOW_VSCROLL; @@ -1613,8 +1608,7 @@ void ro_gui_window_open(wimp_open *open) if ((g->old_width > 0) && (g->old_width != width) && (ro_gui_ctrl_pressed())) new_scale = (g->bw->scale * width) / g->old_width; - g->bw->reformat_pending = true; - browser_reformat_pending = true; + browser_window_schedule_reformat(g->bw); } if (g->update_extent || g->old_width != width || g->old_height != height) { @@ -4385,25 +4379,17 @@ void ro_gui_window_update_boxes(void) /** - * Process pending reformats + * callback from core to reformat a window. */ - -void ro_gui_window_process_reformats(void) +static void riscos_window_reformat(struct gui_window *gw) { - struct gui_window *g; - - browser_reformat_pending = false; - for (g = window_list; g; g = g->next) { - if (!g->bw->reformat_pending) - continue; - g->bw->reformat_pending = false; - browser_window_reformat(g->bw, false, - g->old_width / 2, - g->old_height / 2); + if (gw != NULL) { + browser_window_reformat(gw->bw, false, + gw->old_width / 2, + gw->old_height / 2); } } - /** * Destroy all browser windows. */ @@ -5180,6 +5166,7 @@ static struct gui_window_table window_table = { .set_scroll = gui_window_set_scroll, .get_dimensions = gui_window_get_dimensions, .update_extent = gui_window_update_extent, + .reformat = riscos_window_reformat, .set_title = gui_window_set_title, .set_url = gui_window_set_url, diff --git a/windows/gui.c b/windows/gui.c index 824abade7..19a31c1be 100644 --- a/windows/gui.c +++ b/windows/gui.c @@ -93,7 +93,6 @@ static void nsws_set_scale(struct gui_window *gw, float scale) return; browser_window_set_scale(gw->bw, scale, true); - browser_window_reformat(gw->bw, false, gw->width, gw->height); } @@ -1820,6 +1819,16 @@ nsws_create_main_class(HINSTANCE hinstance) { return ret; } +/** + * callback from core to reformat a window. + */ +static void win32_window_reformat(struct gui_window *gw) +{ + if (gw != NULL) { + browser_window_reformat(gw->bw, false, gw->width, gw->height); + } +} + /** * Generate a windows path from one or more component elemnts. * @@ -2087,6 +2096,7 @@ static struct gui_window_table window_table = { .set_scroll = gui_window_set_scroll, .get_dimensions = gui_window_get_dimensions, .update_extent = gui_window_update_extent, + .reformat = win32_window_reformat, .set_title = gui_window_set_title, .set_url = gui_window_set_url, -- cgit v1.2.3 From 291f1094eb871874bf2e01579522d9fbefde0ee8 Mon Sep 17 00:00:00 2001 From: Chris Young Date: Tue, 1 Jul 2014 18:29:10 +0100 Subject: Add some space between icon and text in the menu --- amiga/menu.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/amiga/menu.c b/amiga/menu.c index 784fec163..7568a7d2f 100644 --- a/amiga/menu.c +++ b/amiga/menu.c @@ -362,9 +362,11 @@ static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) { int i, j; int txtlen = 0; + int left_posn; struct RastPort *rp = &scrn->RastPort; struct DrawInfo *dri = GetScreenDrawInfo(scrn); - + int space_width = TextLength(rp, " ", 1); + if(menu_glyphs_loaded == false) ami_menu_load_glyphs(dri); @@ -378,6 +380,8 @@ static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) if(gwin->menulab[j] != NM_BARLABEL) { if(gwin->menutype[j] == NM_ITEM) { item_size = TextLength(rp, gwin->menulab[j], strlen(gwin->menulab[j])); + item_size += space_width; + if(gwin->menukey[j]) { item_size += TextLength(rp, &gwin->menukey[j], 1); item_size += menu_glyph_width[NSA_GLYPH_AMIGAKEY]; @@ -413,13 +417,17 @@ static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) TAG_DONE); GetAttr(IA_Width, icon, (ULONG *)&icon_width); - + if((gwin->menutype[i] == NM_ITEM) && (gwin->menutype[i+1] == NM_SUB)) { + left_posn = txtlen - + TextLength(rp, gwin->menulab[i], strlen(gwin->menulab[i])) - + menu_glyph_width[NSA_GLYPH_SUBMENU] - + icon_width - space_width; + submenuarrow = NewObject(NULL, "sysiclass", - SYSIA_Which, MENUSUB, - SYSIA_DrawInfo, dri, - IA_Left, txtlen - TextLength(rp, gwin->menulab[i], strlen(gwin->menulab[i])) - - menu_glyph_width[NSA_GLYPH_SUBMENU] - icon_width, + SYSIA_Which, MENUSUB, + SYSIA_DrawInfo, dri, + IA_Left, left_posn, TAG_DONE); } @@ -430,6 +438,7 @@ static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) LABEL_DrawInfo, dri, LABEL_DisposeImage, TRUE, LABEL_Image, icon, + LABEL_Text, " ", LABEL_Text, gwin->menulab[i], LABEL_DisposeImage, TRUE, LABEL_Image, submenuarrow, -- cgit v1.2.3 From 4497e9aab748a4e3f3615cafb7ef8f896ede660d Mon Sep 17 00:00:00 2001 From: Chris Young Date: Tue, 1 Jul 2014 23:16:24 +0100 Subject: Neaten up sub-menu highlighting --- amiga/menu.c | 74 +++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 18 deletions(-) diff --git a/amiga/menu.c b/amiga/menu.c index 7568a7d2f..c1e863a65 100644 --- a/amiga/menu.c +++ b/amiga/menu.c @@ -35,8 +35,6 @@ #include #include #include -#include -#include #include @@ -358,10 +356,29 @@ void ami_menu_free_glyphs(void) menu_glyphs_loaded = false; } +static int ami_menu_calc_item_width(struct gui_window_2 *gwin, int j, struct RastPort *rp) +{ + int space_width = TextLength(rp, " ", 1); + int item_size; + + item_size = TextLength(rp, gwin->menulab[j], strlen(gwin->menulab[j])); + item_size += space_width; + + if(gwin->menukey[j]) { + item_size += TextLength(rp, &gwin->menukey[j], 1); + item_size += menu_glyph_width[NSA_GLYPH_AMIGAKEY]; + /**TODO: take account of the size of other imagery too + */ + } + + return item_size; +} + + static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) { int i, j; - int txtlen = 0; + int txtlen = 0, subtxtlen = 0; int left_posn; struct RastPort *rp = &scrn->RastPort; struct DrawInfo *dri = GetScreenDrawInfo(scrn); @@ -375,20 +392,10 @@ static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) if(gwin->menutype[i] == NM_TITLE) { j = i + 1; txtlen = 0; - int item_size = 0; do { if(gwin->menulab[j] != NM_BARLABEL) { if(gwin->menutype[j] == NM_ITEM) { - item_size = TextLength(rp, gwin->menulab[j], strlen(gwin->menulab[j])); - item_size += space_width; - - if(gwin->menukey[j]) { - item_size += TextLength(rp, &gwin->menukey[j], 1); - item_size += menu_glyph_width[NSA_GLYPH_AMIGAKEY]; - /**TODO: take account of the size of other imagery too - */ - } - + int item_size = ami_menu_calc_item_width(gwin, j, rp); if(item_size > txtlen) { txtlen = item_size; } @@ -403,6 +410,7 @@ static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) using label.image if there's a bitmap associated with the item. */ if((gwin->menuicon[i] != NULL) && (gwin->menulab[i] != NM_BARLABEL)) { int icon_width = 0; + Object *blank_space = NULL; Object *submenuarrow = NULL; Object *icon = BitMapObject, BITMAP_Screen, scrn, @@ -418,21 +426,49 @@ static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) GetAttr(IA_Width, icon, (ULONG *)&icon_width); + if(gwin->menutype[i] == NM_SUB) { + left_posn = subtxtlen; + } else { + left_posn = txtlen; + } + + left_posn = left_posn - + TextLength(rp, gwin->menulab[i], strlen(gwin->menulab[i])) - + icon_width - space_width; + if((gwin->menutype[i] == NM_ITEM) && (gwin->menutype[i+1] == NM_SUB)) { - left_posn = txtlen - - TextLength(rp, gwin->menulab[i], strlen(gwin->menulab[i])) - - menu_glyph_width[NSA_GLYPH_SUBMENU] - - icon_width - space_width; + left_posn -= menu_glyph_width[NSA_GLYPH_SUBMENU]; submenuarrow = NewObject(NULL, "sysiclass", SYSIA_Which, MENUSUB, SYSIA_DrawInfo, dri, IA_Left, left_posn, TAG_DONE); + + j = i + 1; + subtxtlen = 0; + do { + if(gwin->menulab[j] != NM_BARLABEL) { + if(gwin->menutype[j] == NM_SUB) { + int item_size = ami_menu_calc_item_width(gwin, j, rp); + if(item_size > subtxtlen) { + subtxtlen = item_size; + } + } + } + j++; + } while((gwin->menutype[j] == NM_SUB)); } /**TODO: Checkmark/MX images and keyboard shortcuts */ + + if(gwin->menutype[i] == NM_SUB) { + blank_space = NewObject(NULL, "fillrectclass", + IA_Height, 0, + IA_Width, left_posn + icon_width, + TAG_DONE); + } gwin->menuobj[i] = LabelObject, LABEL_DrawInfo, dri, @@ -441,6 +477,8 @@ static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) LABEL_Text, " ", LABEL_Text, gwin->menulab[i], LABEL_DisposeImage, TRUE, + LABEL_Image, blank_space, + LABEL_DisposeImage, TRUE, LABEL_Image, submenuarrow, LabelEnd; -- cgit v1.2.3 From dcf3a55ae6083da252af43d7958981080e7e9e41 Mon Sep 17 00:00:00 2001 From: François Revol Date: Wed, 2 Jul 2014 03:11:25 +0200 Subject: beos: Avoid crashing if FindPath() returns an error This can happen when running from the build directory, without the package already installed. --- beos/gui.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/beos/gui.cpp b/beos/gui.cpp index f9e02d0de..19046a5e4 100644 --- a/beos/gui.cpp +++ b/beos/gui.cpp @@ -299,13 +299,13 @@ static char *find_resource(char *buf, const char *filename, const char *def) BPathFinder f((void*)find_resource); BPath p; - f.FindPath(B_FIND_PATH_APPS_DIRECTORY, "netsurf/res/", p); - strcpy(t, p.Path()); - - strcat(t, filename); - realpath(t, buf); - if (access(buf, R_OK) == 0) - return buf; + if (f.FindPath(B_FIND_PATH_APPS_DIRECTORY, "netsurf/res", p) == B_OK) { + strcpy(t, p.Path()); + strcat(t, filename); + realpath(t, buf); + if (access(buf, R_OK) == 0) + return buf; + } if (def[0] == '%') { snprintf(t, PATH_MAX, "%s%s", path.Path(), def + 1); -- cgit v1.2.3 From 36ba460fe4edd25c6bfd5daae8b25a7d2dc23d68 Mon Sep 17 00:00:00 2001 From: François Revol Date: Wed, 2 Jul 2014 03:40:32 +0200 Subject: beos: handle realpath() returning NULL Else we return with an uninitialized buffer... --- beos/gui.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/beos/gui.cpp b/beos/gui.cpp index 19046a5e4..9ecfbd0ff 100644 --- a/beos/gui.cpp +++ b/beos/gui.cpp @@ -309,12 +309,18 @@ static char *find_resource(char *buf, const char *filename, const char *def) if (def[0] == '%') { snprintf(t, PATH_MAX, "%s%s", path.Path(), def + 1); - realpath(t, buf); + if (realpath(t, buf) == NULL) { + strcpy(buf, t); + } } else if (def[0] == '~') { snprintf(t, PATH_MAX, "%s%s", getenv("HOME"), def + 1); - realpath(t, buf); + if (realpath(t, buf) == NULL) { + strcpy(buf, t); + } } else { - realpath(def, buf); + if (realpath(def, buf) == NULL) { + strcpy(buf, def); + } } return buf; -- cgit v1.2.3 From c574780d29dde43fbf8fdfc2e6465e98ff0f3e10 Mon Sep 17 00:00:00 2001 From: François Revol Date: Wed, 2 Jul 2014 03:43:13 +0200 Subject: beos: drop @todo From the select(2) linux manpage: "nfds is the highest-numbered file descriptor in any of the three sets, plus 1." As sEventPipe[0] is definitely a descriptor, it must be 1 more here. --- beos/gui.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/beos/gui.cpp b/beos/gui.cpp index 9ecfbd0ff..d6bfc1e50 100644 --- a/beos/gui.cpp +++ b/beos/gui.cpp @@ -731,7 +731,6 @@ static void gui_poll(bool active) // our own event pipe FD_SET(sEventPipe[0], &read_fd_set); - /** @todo Check if this max_fd should have + 1 */ max_fd = MAX(max_fd, sEventPipe[0] + 1); // If there are pending events elsewhere, we should not be blocking -- cgit v1.2.3 From 516dcb96e111c6e1e0c1503ac156497aa15894d6 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 2 Jul 2014 14:50:23 +0100 Subject: fix unhelpful assert at quit --- content/fetch.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/content/fetch.c b/content/fetch.c index 3d1183aa0..abfdf4c97 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -290,9 +290,28 @@ void fetcher_quit(void) { int fetcherd; /* fetcher index */ for (fetcherd = 0; fetcherd < MAX_FETCHERS; fetcherd++) { - if (fetchers[fetcherd].refcount > 0) { - /* assert if the fetcher is active at quit */ - assert(fetchers[fetcherd].refcount == 1); + if (fetchers[fetcherd].refcount > 1) { + /* fetcher still has reference at quit. This + * should not happen as the fetch should have + * been aborted in llcache shutdown. + * + * This appears to be normal behaviour if a + * curl operation is still in progress at exit + * as the abort waits for curl to complete. + * + * We could make the user wait for curl to + * complete but we are exiting anyway so thats + * unhelpful. Instead we just log it and force + * the reference count to allow the fetcher to + * be stopped. + */ + LOG(("Fetcher for scheme %s still has %d active users at quit.", + lwc_string_data(fetchers->scheme_name), + fetchers->refcount)); + + fetchers->refcount = 1; + } + if (fetchers[fetcherd].refcount == 1) { fetch_unref_fetcher(fetcherd); } -- cgit v1.2.3 From 29e29cccd772c7be1b5cc878313287307ed7490f Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 2 Jul 2014 15:01:24 +0100 Subject: fix dumb error in previous commit and get scheme name element correct --- content/fetch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/fetch.c b/content/fetch.c index abfdf4c97..6ee3872aa 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -306,10 +306,10 @@ void fetcher_quit(void) * be stopped. */ LOG(("Fetcher for scheme %s still has %d active users at quit.", - lwc_string_data(fetchers->scheme_name), - fetchers->refcount)); + lwc_string_data(fetchers[fetcherd].scheme), + fetchers[fetcherd].refcount)); - fetchers->refcount = 1; + fetchers[fetcherd].refcount = 1; } if (fetchers[fetcherd].refcount == 1) { -- cgit v1.2.3 From 8848f754e07264a8b358c34048d84139660291d1 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 2 Jul 2014 16:39:08 +0100 Subject: documentation fixes and cleanups --- amiga/misc.c | 6 +++--- atari/misc.c | 11 +++++++---- atari/schedule.h | 15 +++++++++------ framebuffer/fbtk.h | 5 +++-- riscos/history.c | 5 ++--- riscos/window.c | 36 +++++++++++++++--------------------- riscos/window.h | 6 ++++++ utils/file.h | 2 +- windows/findfile.c | 2 +- 9 files changed, 47 insertions(+), 41 deletions(-) diff --git a/amiga/misc.c b/amiga/misc.c index 67240006d..7d126c906 100755 --- a/amiga/misc.c +++ b/amiga/misc.c @@ -112,7 +112,7 @@ void die(const char *error) /** * Create a path from a nsurl using amiga file handling. * - * @parm[in] url The url to encode. + * @param[in] url The url to encode. * @param[out] path_out A string containing the result path which should * be freed by the caller. * @return NSERROR_OK and the path is written to \a path or error code @@ -254,8 +254,8 @@ char *translate_escape_chars(const char *s) * @param[in,out] size The size of the space available if \a str not * NULL on input and if not NULL set to the total * output length on output. - * @param[in] nemb The number of elements. - * @param[in] ... The elements of the path as string pointers. + * @param[in] nelm The number of elements. + * @param[in] ap The elements of the path as string pointers. * @return NSERROR_OK and the complete path is written to str * or error code on faliure. */ diff --git a/atari/misc.c b/atari/misc.c index e689b8249..bd3158406 100755 --- a/atari/misc.c +++ b/atari/misc.c @@ -203,12 +203,15 @@ static nserror load_icon_callback(hlcache_handle *handle, /** * utility function. Copied from NetSurf tree API. * - * \param name the name of the loaded icon, if it's not a full path the icon is - * looked for in the directory specified by icons_dir + * \param name the name of the loaded icon, if it's not a full path + * the icon is looked for in the directory specified by + * icons_dir. + * \param cb callback function to deal with hlcache callback. + * \param pw Context pointer to be passed to callback. * \return the icon in form of a content or NULL on failure */ -hlcache_handle *load_icon(const char *name, hlcache_handle_callback cb, - void * pw ) +hlcache_handle * +load_icon(const char *name, hlcache_handle_callback cb, void *pw) { hlcache_handle *c; nserror err; diff --git a/atari/schedule.h b/atari/schedule.h index 47d8c2ddf..05eebb2d7 100755 --- a/atari/schedule.h +++ b/atari/schedule.h @@ -22,20 +22,23 @@ /** * Process events up to current time. + * + * \return The number of miliseconds until the next scheduled event. */ int schedule_run(void); /** * Schedule a callback. * - * \param tival interval before the callback should be made in ms - * \param callback callback function - * \param p user parameter, passed to callback function + * \param ival interval before the callback should be made in miliseconds. + * \param callback callback function. + * \param p user parameter, passed to callback function. + * \return NSERROR_OK on success or appropriate error code. * - * The callback function will be called as soon as possible after t ms have - * passed. + * The callback function will be called as soon as possible after \a ival + * ms have passed. */ -nserror atari_schedule(int cs_ival, void (*callback)(void *p), void *p); +nserror atari_schedule(int ival, void (*callback)(void *p), void *p); /** * LOG all current scheduled events. diff --git a/framebuffer/fbtk.h b/framebuffer/fbtk.h index 220700fef..325db0e9b 100644 --- a/framebuffer/fbtk.h +++ b/framebuffer/fbtk.h @@ -312,7 +312,8 @@ int fbtk_destroy_widget(fbtk_widget_t *widget); /********************************* Widgets *********************************/ -/** Create a window widget. +/** + * Create a window widget. * * @param parent The parent window or the root widget for a top level window. * @param x The x location relative to the parent window. @@ -323,7 +324,7 @@ int fbtk_destroy_widget(fbtk_widget_t *widget); * window. * @param height The height of the window limited in a similar way to the * /a width. - * @param c The background colour. + * @param bg The background colour. * @return new window widget handle or NULL on error. */ fbtk_widget_t *fbtk_create_window(fbtk_widget_t *parent, int x, int y, int width, int height, colour bg); diff --git a/riscos/history.c b/riscos/history.c index 8c096b88c..3b8b63ae1 100644 --- a/riscos/history.c +++ b/riscos/history.c @@ -74,9 +74,8 @@ void ro_gui_history_init(void) /** * Open history window. * - * \param bw browser window to open history for - * \param history history to open - * \param at_pointer open the window at the pointer + * \param g The riscos window to open history for. + * \param at_pointer open the window at the pointer. */ void ro_gui_history_open(struct gui_window *g, bool at_pointer) diff --git a/riscos/window.c b/riscos/window.c index e1eaf871d..5a3369769 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -1072,13 +1072,7 @@ void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape) } -/** - * Set the contents of a window's address bar. - * - * \param g gui_window to update - * \param url new url for address bar - */ - +/* exported function documented in riscos/window.h */ void gui_window_set_url(struct gui_window *g, const char *url) { if (!g->toolbar) @@ -3810,13 +3804,13 @@ bool ro_gui_window_check_menu(wimp_menu *menu) * Return boolean flags to show what RISC OS types we can sensibly convert * the given object into. * - * \TODO -- This should probably be somewhere else but in window.c, and - * should probably even be done in content_(). + * \todo This should probably be somewhere else but in window.c, and + * should probably even be done in content_(). * - * \param *h The object to test. - * \param *export_draw true on exit if a drawfile would be possible. - * \param *export_sprite true on exit if a sprite would be possible. - * \return true if valid data is returned; else false. + * \param h The object to test. + * \param export_draw true on exit if a drawfile would be possible. + * \param export_sprite true on exit if a sprite would be possible. + * \return true if valid data is returned; else false. */ bool ro_gui_window_content_export_types(hlcache_handle *h, @@ -3855,10 +3849,10 @@ bool ro_gui_window_content_export_types(hlcache_handle *h, /** * Return true if a browser window can navigate upwards. * - * \TODO -- This should probably be somewhere else but in window.c. + * \todo This should probably be somewhere else but in window.c. * - * \param *bw the browser window to test. - * \return true if navigation up is possible; else false. + * \param bw the browser window to test. + * \return true if navigation up is possible otherwise false. */ bool ro_gui_window_up_available(struct browser_window *bw) @@ -3986,8 +3980,8 @@ void ro_gui_window_prepare_objectinfo(hlcache_handle *object, const char *href) /** * Launch a new url in the given window. * - * \param g gui_window to update - * \param url url to be launched + * \param g gui_window to update + * \param url1 url to be launched */ void ro_gui_window_launch_url(struct gui_window *g, const char *url1) @@ -4860,8 +4854,8 @@ void ro_gui_window_process_form_select_menu(struct gui_window *g, /** * Convert a RISC OS window handle to a gui_window. * - * \param w RISC OS window handle - * \return pointer to a structure if found, 0 otherwise + * \param window RISC OS window handle. + * \return A pointer to a riscos gui window if found or NULL. */ struct gui_window *ro_gui_window_lookup(wimp_w window) @@ -4870,7 +4864,7 @@ struct gui_window *ro_gui_window_lookup(wimp_w window) for (g = window_list; g; g = g->next) if (g->window == window) return g; - return 0; + return NULL; } diff --git a/riscos/window.h b/riscos/window.h index a55ce1b9f..c4daf8bb8 100644 --- a/riscos/window.h +++ b/riscos/window.h @@ -33,6 +33,12 @@ void ro_gui_window_initialise(void); bool ro_gui_window_check_menu(wimp_menu *menu); +/** + * Set the contents of a window's address bar. + * + * \param g gui_window to update + * \param url new url for address bar + */ void gui_window_set_url(struct gui_window *g, const char *url); #endif diff --git a/utils/file.h b/utils/file.h index 7baf2f019..dbbab300e 100644 --- a/utils/file.h +++ b/utils/file.h @@ -86,7 +86,7 @@ struct gui_file_table { /** * Create a path from a nsurl. * - * @parm[in] url The url to encode. + * @param[in] url The url to encode. * @param[out] path A string containing the result path which * must be freed by the caller. * @return NSERROR_OK and the path is written to \a path diff --git a/windows/findfile.c b/windows/findfile.c index 51ce74829..aed43b0bf 100644 --- a/windows/findfile.c +++ b/windows/findfile.c @@ -93,7 +93,7 @@ static char *realpath(const char *path, char *resolved_path) * * Search order is: ~/.netsurf/, $NETSURFRES/ (where NETSURFRES is an * environment variable), then the path specified in - NETSURF_WINDOWS_RESPATH in the Makefile then .\res\ [windows paths] + * NETSURF_WINDOWS_RESPATH in the Makefile then .\res\ [windows paths] */ char *nsws_find_resource(char *buf, const char *filename, const char *def) -- cgit v1.2.3 From 4073a991ddb92adb3eb0d91d3cbc11f97807c0cb Mon Sep 17 00:00:00 2001 From: François Revol Date: Wed, 2 Jul 2014 17:54:57 +0200 Subject: beos: Fix an oversight with number of fds for select() curl_multi_fdset() does not include the +1 required for select(), so we always need to add it. --- beos/gui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/beos/gui.cpp b/beos/gui.cpp index d6bfc1e50..eee56d8c6 100644 --- a/beos/gui.cpp +++ b/beos/gui.cpp @@ -731,7 +731,8 @@ static void gui_poll(bool active) // our own event pipe FD_SET(sEventPipe[0], &read_fd_set); - max_fd = MAX(max_fd, sEventPipe[0] + 1); + // max of all the fds in the set, plus one for select() + max_fd = MAX(max_fd, sEventPipe[0]) + 1; // If there are pending events elsewhere, we should not be blocking if (!browser_reformat_pending) { -- cgit v1.2.3 From a71865b328b721dcba49696f942335ec2baddc0f Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 2 Jul 2014 17:07:05 +0100 Subject: turn off verbose fetch debugging --- content/fetch.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/content/fetch.c b/content/fetch.c index 6ee3872aa..2160204ef 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -61,17 +61,27 @@ /* Define this to turn on verbose fetch logging */ #undef DEBUG_FETCH_VERBOSE -#define DEBUG_FETCH_VERBOSE - -/** The maximum number of fetchers that can be added */ -#define MAX_FETCHERS 8 +/** Verbose fetcher logging */ #ifdef DEBUG_FETCH_VERBOSE #define FETCH_LOG(x) LOG(x) #else #define FETCH_LOG(x) #endif +/** The maximum number of fetchers that can be added */ +#define MAX_FETCHERS 8 + +/** The time in ms between polling the fetchers. + * + * \todo The schedule timeout should be profiled to see if there is a + * better value or even if it needs to be dynamic. + */ +#define SCHEDULE_TIME 10 + +/** The fdset timeout in ms */ +#define FDSET_TIMEOUT 1000 + /** * Information about a fetcher for a given scheme. */ @@ -265,7 +275,7 @@ static void fetcher_poll(void *unused) } /* schedule active fetchers to run again in 10ms */ - guit->browser->schedule(10, fetcher_poll, NULL); + guit->browser->schedule(SCHEDULE_TIME, fetcher_poll, NULL); } } @@ -395,7 +405,7 @@ nserror fetcher_fdset(fd_set *read_fd_set, * select on. All the other fetchers continue to need * polling frequently. */ - guit->browser->schedule(1000, fetcher_poll, NULL); + guit->browser->schedule(FDSET_TIMEOUT, fetcher_poll, NULL); } *maxfd_out = maxfd; -- cgit v1.2.3 From 5105249bf7aa91fc84fd53af06cc073ff7987168 Mon Sep 17 00:00:00 2001 From: Chris Young Date: Wed, 2 Jul 2014 18:35:16 +0100 Subject: tidy up schedule removal --- amiga/schedule.c | 59 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/amiga/schedule.c b/amiga/schedule.c index 9aa74881f..d0a0570dd 100755 --- a/amiga/schedule.c +++ b/amiga/schedule.c @@ -53,6 +53,32 @@ static void ami_remove_timer_event(struct nscallback *nscb) } } +static struct nscallback *ami_schedule_locate(void (*callback)(void *p), void *p, bool remove) +{ + PblIterator *iterator; + struct nscallback *nscb; + bool found_cb = false; + + /* check there is something on the list */ + if (schedule_list == NULL) return NULL; + if(pblHeapIsEmpty(schedule_list)) return NULL; + + iterator = pblHeapIterator(schedule_list); + + while ((nscb = pblIteratorNext(iterator)) != -1) { + if ((nscb->callback == callback) && (nscb->p == p)) { + if (remove == true) pblIteratorRemove(iterator); + found_cb = true; + break; + } + }; + + pblIteratorFree(iterator); + + if (found_cb == true) return nscb; + else return NULL; +} + /** * Unschedule a callback. * @@ -66,36 +92,12 @@ static nserror schedule_remove(void (*callback)(void *p), void *p) { PblIterator *iterator; struct nscallback *nscb; - bool restoreheap = false; - - /* check there is something on the list to remove */ - if (schedule_list == NULL) - { - return NSERROR_OK; - } - - if(pblHeapIsEmpty(schedule_list)) - { - return NSERROR_OK; - } - - iterator = pblHeapIterator(schedule_list); - - while ((nscb = pblIteratorNext(iterator)) != -1) - { - if((nscb->callback == callback) && (nscb->p == p)) - { - ami_remove_timer_event(nscb); - pblIteratorRemove(iterator); - FreeVec(nscb); - restoreheap = true; - } - }; - pblIteratorFree(iterator); + nscb = ami_schedule_locate(callback, p, true); - if(restoreheap) - { + if(nscb != NULL) { + ami_remove_timer_event(nscb); + FreeVec(nscb); pblHeapConstruct(schedule_list); } @@ -257,3 +259,4 @@ nserror ami_schedule(int t, void (*callback)(void *p), void *p) return NSERROR_OK; } + -- cgit v1.2.3 From f52501d9ad77cf11ae7eedcc2ca3c9eeddaaf7d8 Mon Sep 17 00:00:00 2001 From: Chris Young Date: Wed, 2 Jul 2014 18:43:44 +0100 Subject: If we try to duplicate an existing scheduled event, reschedule it instead. --- amiga/schedule.c | 49 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/amiga/schedule.c b/amiga/schedule.c index d0a0570dd..2aacb22ee 100755 --- a/amiga/schedule.c +++ b/amiga/schedule.c @@ -79,6 +79,37 @@ static struct nscallback *ami_schedule_locate(void (*callback)(void *p), void *p else return NULL; } +/** + * Reschedule a callback. + */ + +static nserror ami_schedule_reschedule(int t, struct nscallback *nscb) +{ + struct TimeVal tv; + ULONG time_us = t * 1000; /* t converted to µs */ + + ami_remove_timer_event(nscb); + + nscb->tv.Seconds = time_us / 1000000; + nscb->tv.Microseconds = time_us % 1000000; + + GetSysTime(&tv); + AddTime(&nscb->tv, &tv); // now contains time when event occurs + + if(nscb->treq = AllocVecTagList(sizeof(struct TimeRequest), NULL)) + { + *nscb->treq = *tioreq; + nscb->treq->Request.io_Command=TR_ADDREQUEST; + nscb->treq->Time.Seconds=nscb->tv.Seconds; // secs + nscb->treq->Time.Microseconds=nscb->tv.Microseconds; // micro + SendIO((struct IORequest *)nscb->treq); + } + + pblHeapConstruct(schedule_list); + + return NSERROR_OK; +} + /** * Unschedule a callback. * @@ -219,21 +250,15 @@ nserror ami_schedule(int t, void (*callback)(void *p), void *p) struct TimeVal tv; ULONG time_us = 0; - if(schedule_list == NULL) - { - return NSERROR_INIT_FAILED; - } - - if(t < 0) - { - return schedule_remove(callback, p); + if(schedule_list == NULL) return NSERROR_INIT_FAILED; + if (t < 0) return schedule_remove(callback, p); + + if (nscb = ami_schedule_locate(callback, p, false)) { + return ami_schedule_reschedule(t, nscb); } nscb = AllocVecTagList(sizeof(struct nscallback), NULL); - if(!nscb) - { - return NSERROR_NOMEM; - } + if(!nscb) return NSERROR_NOMEM; time_us = t * 1000; /* t converted to µs */ -- cgit v1.2.3 From 074e6f3ec6f048a1861efec84bd91136761492fa Mon Sep 17 00:00:00 2001 From: Chris Young Date: Thu, 3 Jul 2014 00:08:56 +0100 Subject: Remove some code duplication, tidy up and documentation --- amiga/schedule.c | 117 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 49 deletions(-) diff --git a/amiga/schedule.c b/amiga/schedule.c index 2aacb22ee..6222917cf 100755 --- a/amiga/schedule.c +++ b/amiga/schedule.c @@ -39,7 +39,15 @@ struct nscallback PblHeap *schedule_list; -static void ami_remove_timer_event(struct nscallback *nscb) +/** + * Remove timer event + * + * \param nscb callback + * + * The timer event for the callback is aborted + */ + +static void ami_schedule_remove_timer_event(struct nscallback *nscb) { if(!nscb) return; @@ -53,6 +61,49 @@ static void ami_remove_timer_event(struct nscallback *nscb) } } +/** + * Add timer event + * + * \param nscb callback + * \param t time in ms + * + * NetSurf will be signalled in t ms for this event. + */ + +static nserror ami_schedule_add_timer_event(struct nscallback *nscb, int t) +{ + struct TimeVal tv; + ULONG time_us = t * 1000; /* t converted to µs */ + + nscb->tv.Seconds = time_us / 1000000; + nscb->tv.Microseconds = time_us % 1000000; + + GetSysTime(&tv); + AddTime(&nscb->tv,&tv); // now contains time when event occurs + + if(nscb->treq = AllocVecTagList(sizeof(struct TimeRequest), NULL)) { + *nscb->treq = *tioreq; + nscb->treq->Request.io_Command=TR_ADDREQUEST; + nscb->treq->Time.Seconds=nscb->tv.Seconds; // secs + nscb->treq->Time.Microseconds=nscb->tv.Microseconds; // micro + SendIO((struct IORequest *)nscb->treq); + } else { + return NSERROR_NOMEM; + } + + return NSERROR_OK; +} + +/** + * Locate a scheduled callback + * + * \param callback callback function + * \param p user parameter, passed to callback function + * \param remove remove callback from the heap + * + * A scheduled callback matching both callback and p is returned, or NULL if none present. + */ + static struct nscallback *ami_schedule_locate(void (*callback)(void *p), void *p, bool remove) { PblIterator *iterator; @@ -81,32 +132,20 @@ static struct nscallback *ami_schedule_locate(void (*callback)(void *p), void *p /** * Reschedule a callback. + * + * \param nscb callback + * \param t time in ms + * + * The nscallback will be rescheduled for t ms. */ -static nserror ami_schedule_reschedule(int t, struct nscallback *nscb) +static nserror ami_schedule_reschedule(struct nscallback *nscb, int t) { - struct TimeVal tv; - ULONG time_us = t * 1000; /* t converted to µs */ - - ami_remove_timer_event(nscb); - - nscb->tv.Seconds = time_us / 1000000; - nscb->tv.Microseconds = time_us % 1000000; - - GetSysTime(&tv); - AddTime(&nscb->tv, &tv); // now contains time when event occurs - - if(nscb->treq = AllocVecTagList(sizeof(struct TimeRequest), NULL)) - { - *nscb->treq = *tioreq; - nscb->treq->Request.io_Command=TR_ADDREQUEST; - nscb->treq->Time.Seconds=nscb->tv.Seconds; // secs - nscb->treq->Time.Microseconds=nscb->tv.Microseconds; // micro - SendIO((struct IORequest *)nscb->treq); - } + ami_schedule_remove_timer_event(nscb); + if (ami_schedule_add_timer_event(nscb, t) != NSERROR_OK) + return NSERROR_NOMEM; pblHeapConstruct(schedule_list); - return NSERROR_OK; } @@ -127,7 +166,7 @@ static nserror schedule_remove(void (*callback)(void *p), void *p) nscb = ami_schedule_locate(callback, p, true); if(nscb != NULL) { - ami_remove_timer_event(nscb); + ami_schedule_remove_timer_event(nscb); FreeVec(nscb); pblHeapConstruct(schedule_list); } @@ -146,7 +185,7 @@ static void schedule_remove_all(void) while ((nscb = pblIteratorNext(iterator)) != -1) { - ami_remove_timer_event(nscb); + ami_schedule_remove_timer_event(nscb); pblIteratorRemove(iterator); FreeVec(nscb); }; @@ -188,7 +227,7 @@ void schedule_run(BOOL poll) callback = nscb->callback; p = nscb->p; - ami_remove_timer_event(nscb); + ami_schedule_remove_timer_event(nscb); pblHeapRemoveFirst(schedule_list); FreeVec(nscb); callback(p); @@ -233,11 +272,7 @@ void ami_schedule_open_timer(void) /* exported function documented in amiga/schedule.h */ void ami_schedule_close_timer(void) { - if(ITimer) - { - DropInterface((struct Interface *)ITimer); - } - + if(ITimer) DropInterface((struct Interface *)ITimer); CloseDevice((struct IORequest *) tioreq); FreeSysObject(ASOT_IOREQUEST,tioreq); FreeSysObject(ASOT_PORT,msgport); @@ -247,35 +282,19 @@ void ami_schedule_close_timer(void) nserror ami_schedule(int t, void (*callback)(void *p), void *p) { struct nscallback *nscb; - struct TimeVal tv; - ULONG time_us = 0; if(schedule_list == NULL) return NSERROR_INIT_FAILED; if (t < 0) return schedule_remove(callback, p); if (nscb = ami_schedule_locate(callback, p, false)) { - return ami_schedule_reschedule(t, nscb); + return ami_schedule_reschedule(nscb, t); } nscb = AllocVecTagList(sizeof(struct nscallback), NULL); if(!nscb) return NSERROR_NOMEM; - time_us = t * 1000; /* t converted to µs */ - - nscb->tv.Seconds = time_us / 1000000; - nscb->tv.Microseconds = time_us % 1000000; - - GetSysTime(&tv); - AddTime(&nscb->tv,&tv); // now contains time when event occurs - - if(nscb->treq = AllocVecTagList(sizeof(struct TimeRequest), NULL)) - { - *nscb->treq = *tioreq; - nscb->treq->Request.io_Command=TR_ADDREQUEST; - nscb->treq->Time.Seconds=nscb->tv.Seconds; // secs - nscb->treq->Time.Microseconds=nscb->tv.Microseconds; // micro - SendIO((struct IORequest *)nscb->treq); - } + if (ami_schedule_add_timer_event(nscb, t) != NSERROR_OK) + return NSERROR_NOMEM; nscb->callback = callback; nscb->p = p; -- cgit v1.2.3 From eccfdec27ac1f59c18374edfec517749b47bfff6 Mon Sep 17 00:00:00 2001 From: Chris Young Date: Thu, 3 Jul 2014 20:53:28 +0100 Subject: Wait for network activity instead of polling. --- amiga/gui.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/amiga/gui.c b/amiga/gui.c index 6b02cac4f..f41ac5305 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -18,6 +18,7 @@ /* NetSurf core includes */ #include "content/backing_store.h" +#include "content/fetchers.h" #include "content/fetchers/resource.h" #include "content/urldb.h" #include "css/utils.h" @@ -2462,15 +2463,36 @@ void ami_get_msg(void) ULONG appsig = 1L << appport->mp_SigBit; ULONG schedulesig = 1L << msgport->mp_SigBit; ULONG ctrlcsig = SIGBREAKF_CTRL_C; - ULONG signal; + uint32 signal = 0; + fd_set read_fd_set, write_fd_set, except_fd_set; + int max_fd = -1; struct TimerRequest *timermsg = NULL; struct MsgPort *printmsgport = ami_print_get_msgport(); ULONG printsig = 0; ULONG helpsignal = ami_help_signal(); if(printmsgport) printsig = 1L << printmsgport->mp_SigBit; - ULONG signalmask = winsignal | appsig | schedulesig | rxsig | printsig | applibsig | ctrlcsig | helpsignal; - - signal = Wait(signalmask); + uint32 signalmask = winsignal | appsig | schedulesig | rxsig | + printsig | applibsig | helpsignal; + + if ((fetcher_fdset(&read_fd_set, &write_fd_set, &except_fd_set, &max_fd) == NSERROR_OK) && + (max_fd != -1)) { + /* max_fd is the highest fd in use, but waitselect() needs to know how many + * are in use, so we add 1. */ + int ws = waitselect(max_fd + 1, &read_fd_set, &write_fd_set, &except_fd_set, + NULL, (unsigned int *)&signalmask); + signal = signalmask; + + /* \todo Fix Ctrl-C handling. + * WaitSelect() from bsdsocket.library returns -1 if the task was signalled + * with a Ctrl-C. waitselect() from newlib.library does not - instead + * the task terminates (rather than be signalled) when it receives a Ctrl-C. + * Adding the Ctrl-C signal to our user signal mask causes a Ctrl-C to occur + * immediately. */ + } else { + /* If fetcher_fdset fails or no network activity, do it the old fashioned way. */ + signalmask |= ctrlcsig; + signal = Wait(signalmask); + } if(signal & winsignal) ami_handle_msg(); -- cgit v1.2.3 From 219f505a65035b2f975109c64103a2b708176296 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 4 Jul 2014 17:06:15 +0100 Subject: version 1.1 of the backing store disc layout using base32 encoded filenames to allow for case insensitive filenames. --- Docs/source-object-backing-store | 28 ++++++--- content/fs_backing_store.c | 125 ++++++++++++++++++++------------------- 2 files changed, 83 insertions(+), 70 deletions(-) diff --git a/Docs/source-object-backing-store b/Docs/source-object-backing-store index e55a99db3..5d4d3049d 100644 --- a/Docs/source-object-backing-store +++ b/Docs/source-object-backing-store @@ -34,8 +34,8 @@ As the backing store only holds cache data one should not expect a great deal of effort to be expended converting formats (i.e. the cache may simply be discarded). -Layout version 1 ----------------- +Layout version 1.1 +------------------ An object has an identifier value generated from the url (NetSurf backing stores uses the url as the unique key). The value used is @@ -54,7 +54,7 @@ overhead of reconstructing it at initialisation and to keep the data used to improve the eviction decisions. Each object is stored and retrived directly into the filesystem using -a filename generated from a base64url encoding of an address +a filename generated from a RFC4648 base32 encoding of an address value. The objects address is derived from the identifier by cropping it to a shorter length. @@ -71,17 +71,27 @@ E.g. Linux based systems can easily cope with several megabytes of mmaped index but RISC OS might want to limit this to a few megabytes of heap at most. -The files are stored on disc using their base64url address value. +The files are stored on disc using their base32 address value. By creating a directory for each character of the encoded filename (except the last which is of course the leafname) we create a -directory structure where no directory has more than 64 entries. +directory structure where no directory has more than 32 entries. -E.g. A 19bit address of 0x1 would be base64url encoded into AAAB +E.g. A 19bit address of 0x1 would be base32 encoded into AAAB resulting in the data being stored in a file path of -"/store/prefix/data/B/A/A/BAAAAA". +"/store/prefix/d/B/A/A/BAAAAA". An address of 0x00040001 encodes to BAAB and a file path of -"/store/prefix/meta/B/A/A/BAABAA" +"/store/prefix/m/B/A/A/BAABAAA" + +Version 1.0 +----------- + +The version 1 layout was identical to the 1.1 except base64url +encoding was used, this proved problematic as some systems filesystems +were case insensitive so upper and lower case letetrs collided. + +There is no upgrade provision from the previous version simply delete +the cache directory. Control files ~~~~~~~~~~~~~ @@ -99,7 +109,7 @@ filesystem. Each control file table entry is 28 bytes and consists of - - signed 64 but value for last use time + - signed 64 bit value for last use time - 32bit full url hash allowing for index reconstruction and addiitonal collision detection. Also the possibility of increasing diff --git a/content/fs_backing_store.c b/content/fs_backing_store.c index d29fcaac7..fde17ed62 100644 --- a/content/fs_backing_store.c +++ b/content/fs_backing_store.c @@ -54,7 +54,7 @@ #define DEFAULT_ENTRY_SIZE 16 /** Backing store file format version */ -#define CONTROL_VERSION 100 +#define CONTROL_VERSION 110 /** Get address from ident */ #define BS_ADDRESS(ident, state) ((ident) & ((1 << state->ident_bits) - 1)) @@ -215,6 +215,26 @@ remove_store_entry(struct store_state *state, /** * Generate a filename for an object. * + * this generates the filename for an object on disc. It is necessary + * for this to generate a filename which conforms to the limitations + * of all the filesystems the cache can be placed upon. + * + * From http://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits + * the relevant subset is: + * - path elements no longer than 8 characters + * - acceptable characters are A-Z, 0-9 + * - short total path lengths (255 or less) + * + * The short total path lengths mean the encoding must represent as + * much data as possible in the least number of characters. + * + * To achieve all these goals we use RFC4648 base32 encoding which packs + * 5bits into each character of the filename. + * + * @note Version 1.00 of the cache implementation used base64 to + * encode this, however that did not meet the requirement for only + * using uppercase characters. + * * @param state The store state to use. * @param ident The identifier to use. * @return The filename string or NULL on allocation error. @@ -225,96 +245,79 @@ store_fname(struct store_state *state, enum backing_store_flags flags) { char *fname = NULL; - uint8_t b64u_i[7]; /* base64 ident */ - uint8_t b64u_d[6][2]; /* base64 ident as separate components */ + uint8_t b32u_i[8]; /* base32 encoded ident */ + uint8_t b32u_d[6][2]; /* base64 ident as separate components */ const char *dat; - /** Base64url encoding table */ + /* RFC4648 base32 encoding table */ static const uint8_t encoding_table[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '-', '_' + 'Y', 'Z', '2', '3', '4', '5', '6', '7' }; - /* base64 encode ident */ - b64u_i[0] = b64u_d[0][0] = encoding_table[(ident ) & 0x3f]; - b64u_i[1] = b64u_d[1][0] = encoding_table[(ident >> 6) & 0x3f]; - b64u_i[2] = b64u_d[2][0] = encoding_table[(ident >> 12) & 0x3f]; - b64u_i[3] = b64u_d[3][0] = encoding_table[(ident >> 18) & 0x3f]; - b64u_i[4] = b64u_d[4][0] = encoding_table[(ident >> 24) & 0x3f]; - b64u_i[5] = b64u_d[5][0] = encoding_table[(ident >> 30) & 0x3f]; + /* base32 encode ident */ + b32u_i[0] = b32u_d[0][0] = encoding_table[(ident ) & 0x1f]; + b32u_i[1] = b32u_d[1][0] = encoding_table[(ident >> 5) & 0x1f]; + b32u_i[2] = b32u_d[2][0] = encoding_table[(ident >> 10) & 0x1f]; + b32u_i[3] = b32u_d[3][0] = encoding_table[(ident >> 15) & 0x1f]; + b32u_i[4] = b32u_d[4][0] = encoding_table[(ident >> 20) & 0x1f]; + b32u_i[5] = b32u_d[5][0] = encoding_table[(ident >> 25) & 0x1f]; + b32u_i[6] = encoding_table[(ident >> 30) & 0x1f]; /* null terminate strings */ - b64u_i[6] = b64u_d[0][1] = b64u_d[1][1] = b64u_d[2][1] = - b64u_d[3][1] = b64u_d[4][1] = b64u_d[5][1] = 0; + b32u_i[7] = b32u_d[0][1] = b32u_d[1][1] = b32u_d[2][1] = + b32u_d[3][1] = b32u_d[4][1] = b32u_d[5][1] = 0; if ((flags & BACKING_STORE_META) != 0) { - dat = "meta"; + dat = "m"; /* metadata */ } else { - dat = "data"; + dat = "d"; /* data */ } - /* number of chars with usefully encoded data in b64 */ - switch(((state->ident_bits + 5) / 6)) { + /* number of chars with usefully encoded data in base 32 */ + switch(((state->ident_bits + 4) / 5)) { case 1: - netsurf_mkpath(&fname, NULL, 3, - state->path, - dat, - b64u_i); + netsurf_mkpath(&fname, NULL, 3, state->path, dat, + b32u_i); break; case 2: - netsurf_mkpath(&fname, NULL, 4, - state->path, - dat, - b64u_d[0], - b64u_i); + netsurf_mkpath(&fname, NULL, 4, state->path, dat, + b32u_d[0], + b32u_i); break; case 3: - netsurf_mkpath(&fname, NULL, 5, - state->path, - dat, - b64u_d[0], - b64u_d[1], - b64u_i); + netsurf_mkpath(&fname, NULL, 5, state->path, dat, + b32u_d[0], b32u_d[1], + b32u_i); break; case 4: - netsurf_mkpath(&fname, NULL, 6, - state->path, - dat, - b64u_d[0], - b64u_d[1], - b64u_d[2], - b64u_i); + netsurf_mkpath(&fname, NULL, 6, state->path, dat, + b32u_d[0], b32u_d[1], b32u_d[2], + b32u_i); break; case 5: - netsurf_mkpath(&fname, NULL, 7, - state->path, - dat, - b64u_d[0], - b64u_d[1], - b64u_d[2], - b64u_d[3], - b64u_i); + netsurf_mkpath(&fname, NULL, 7, state->path, dat, + b32u_d[0], b32u_d[1], b32u_d[2], b32u_d[3], + b32u_i); break; case 6: - netsurf_mkpath(&fname, NULL, 8, - state->path, - dat, - b64u_d[0], - b64u_d[1], - b64u_d[2], - b64u_d[3], - b64u_d[4], - b64u_i); + netsurf_mkpath(&fname, NULL, 8, state->path, dat, + b32u_d[0], b32u_d[1], b32u_d[2], b32u_d[3], + b32u_d[4], + b32u_i); + break; + + case 7: + netsurf_mkpath(&fname, NULL, 9, state->path, dat, + b32u_d[0], b32u_d[1], b32u_d[2], b32u_d[3], + b32u_d[4], b32u_d[5], + b32u_i); break; default: -- cgit v1.2.3 From f3508427f84ae00ec3d597778ae27c426d17e99b Mon Sep 17 00:00:00 2001 From: Chris Young Date: Sat, 5 Jul 2014 09:36:43 +0100 Subject: Ensure Ctrl-C does not terminate NetSurf abruptly. --- amiga/gui.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/amiga/gui.c b/amiga/gui.c index f41ac5305..1cbccd672 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -2472,22 +2472,25 @@ void ami_get_msg(void) ULONG helpsignal = ami_help_signal(); if(printmsgport) printsig = 1L << printmsgport->mp_SigBit; uint32 signalmask = winsignal | appsig | schedulesig | rxsig | - printsig | applibsig | helpsignal; + printsig | applibsig | helpsignal; if ((fetcher_fdset(&read_fd_set, &write_fd_set, &except_fd_set, &max_fd) == NSERROR_OK) && (max_fd != -1)) { /* max_fd is the highest fd in use, but waitselect() needs to know how many * are in use, so we add 1. */ - int ws = waitselect(max_fd + 1, &read_fd_set, &write_fd_set, &except_fd_set, - NULL, (unsigned int *)&signalmask); - signal = signalmask; - - /* \todo Fix Ctrl-C handling. - * WaitSelect() from bsdsocket.library returns -1 if the task was signalled - * with a Ctrl-C. waitselect() from newlib.library does not - instead - * the task terminates (rather than be signalled) when it receives a Ctrl-C. - * Adding the Ctrl-C signal to our user signal mask causes a Ctrl-C to occur - * immediately. */ + if (waitselect(max_fd + 1, &read_fd_set, &write_fd_set, &except_fd_set, + NULL, (unsigned int *)&signalmask) != -1) { + signal = signalmask; + } else { + LOG(("waitselect() returned error")); + /* \todo Fix Ctrl-C handling. + * WaitSelect() from bsdsocket.library returns -1 if the task was + * signalled with a Ctrl-C. waitselect() from newlib.library does not. + * Adding the Ctrl-C signal to our user signal mask causes a Ctrl-C to + * occur sporadically. Otherwise we never get a -1 except on error. + * NetSurf still terminates at the Wait() when network activity is over. + */ + } } else { /* If fetcher_fdset fails or no network activity, do it the old fashioned way. */ signalmask |= ctrlcsig; @@ -5152,6 +5155,8 @@ int main(int argc, char** argv) .llcache = filesystem_llcache_table, }; + signal(SIGINT, SIG_IGN); + ret = netsurf_register(&amiga_table); if (ret != NSERROR_OK) { die("NetSurf operation table failed registration"); -- cgit v1.2.3 From bdcb123f0aa7670b25d346876aea8a5b0384d71a Mon Sep 17 00:00:00 2001 From: Chris Young Date: Sat, 5 Jul 2014 17:47:40 +0100 Subject: Replace a flag for search ico refresh with a scheduled callback --- amiga/gui.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/amiga/gui.c b/amiga/gui.c index 1cbccd672..67e5e7a33 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -172,7 +172,6 @@ ULONG screen_signal = -1; struct MsgPort *applibport = NULL; ULONG applibsig = 0; -BOOL refresh_search_ico = FALSE; BOOL refresh_favicon = FALSE; BOOL refresh_throbber = FALSE; struct Hook newprefs_hook; @@ -2215,12 +2214,6 @@ void ami_handle_msg(void) } } while(node = nnode); - if(refresh_search_ico) - { - search_web_select_provider(-1); - refresh_search_ico = FALSE; - } - if(refresh_favicon) { gui_window_set_icon(gwin->bw->window, gwin->bw->window->favicon); @@ -3806,7 +3799,7 @@ gui_window_create(struct browser_window *bw, if(locked_screen) UnlockPubScreen(NULL,scrn); - refresh_search_ico = TRUE; + ami_schedule(0, search_web_select_provider, -1); ScreenToFront(scrn); -- cgit v1.2.3 From 0e28071fa3d7af6cae3d01fa979dfed48a5a0b35 Mon Sep 17 00:00:00 2001 From: Chris Young Date: Sat, 5 Jul 2014 17:59:54 +0100 Subject: Moved forced throbber redraw to a scheduled callback --- amiga/theme.c | 16 ++++++++++++++-- amiga/theme.h | 4 +++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/amiga/theme.c b/amiga/theme.c index 29c72574b..a04efe8bc 100644 --- a/amiga/theme.c +++ b/amiga/theme.c @@ -36,11 +36,12 @@ #include "amiga/bitmap.h" #include "amiga/drag.h" -#include "desktop/browser_private.h" -#include "utils/nsoption.h" +#include "amiga/schedule.h" #include "amiga/theme.h" +#include "desktop/browser_private.h" #include "desktop/searchweb.h" #include "utils/messages.h" +#include "utils/nsoption.h" #include "utils/utils.h" struct BitMap *throbber = NULL; @@ -519,3 +520,14 @@ void ami_update_throbber(struct gui_window_2 *g, bool redraw) // BLITA_UseSrcAlpha,TRUE, TAG_DONE); } + +static void ami_throbber_redraw(void *gwin) +{ + ami_update_throbber((struct gui_window_2 *)gwin, true); +} + +void ami_throbber_redraw_schedule(int t, struct gui_window_2 *gwin) +{ + ami_schedule(t, ami_throbber_redraw, (void *)gwin); +} + diff --git a/amiga/theme.h b/amiga/theme.h index e81db33dd..ed61ef148 100644 --- a/amiga/theme.h +++ b/amiga/theme.h @@ -44,6 +44,8 @@ void ami_update_pointer(struct Window *win, gui_pointer_shape shape); void gui_window_start_throbber(struct gui_window *g); void gui_window_stop_throbber(struct gui_window *g); -void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape); +void ami_throbber_redraw_schedule(int t, struct gui_window_2 *gwin); +void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape); #endif + -- cgit v1.2.3 From 21a21e8143cf68295944bc9bbcad66cb59726f4f Mon Sep 17 00:00:00 2001 From: Chris Young Date: Sat, 5 Jul 2014 18:44:44 +0100 Subject: Move the throbber to proper scheduled operation --- amiga/gui.c | 25 ++++++--------- amiga/theme.c | 101 +++++++++++++++++++++++----------------------------------- amiga/theme.h | 2 +- 3 files changed, 50 insertions(+), 78 deletions(-) diff --git a/amiga/gui.c b/amiga/gui.c index 67e5e7a33..fd59b5b70 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -173,7 +173,6 @@ ULONG screen_signal = -1; struct MsgPort *applibport = NULL; ULONG applibsig = 0; BOOL refresh_favicon = FALSE; -BOOL refresh_throbber = FALSE; struct Hook newprefs_hook; STRPTR temp_homepage_url = NULL; @@ -2116,7 +2115,7 @@ void ami_handle_msg(void) case AMINS_WINDOW: ami_set_border_gadget_balance(gwin); - ami_update_throbber(gwin,true); + ami_throbber_redraw_schedule(0, gwin->bw->window); if(gwin->tabs) { @@ -2208,9 +2207,6 @@ void ami_handle_msg(void) if(gwin->bw->reformat_pending) { ami_schedule_redraw(gwin, true); } - - if(gwin->bw->window->throbbing) - ami_update_throbber(gwin,false); } } while(node = nnode); @@ -2220,12 +2216,6 @@ void ami_handle_msg(void) refresh_favicon = FALSE; } - if(refresh_throbber) - { - ami_update_throbber(gwin, true); - refresh_throbber = FALSE; - } - if(ami_menu_window_close) { if(ami_menu_window_close == (void *)AMI_MENU_WINDOW_CLOSE_ALL) @@ -2596,7 +2586,6 @@ void ami_switch_tab(struct gui_window_2 *gwin,bool redraw) p96RectFill(gwin->win->RPort, bbox->Left, bbox->Top, bbox->Width+bbox->Left, bbox->Height+bbox->Top, 0xffffffff); - browser_window_update(gwin->bw, false); gui_window_set_scroll(gwin->bw->window, @@ -2604,8 +2593,8 @@ void ami_switch_tab(struct gui_window_2 *gwin,bool redraw) gwin->redraw_scroll = false; browser_window_refresh_url_bar(gwin->bw); - ami_gui_update_hotlist_button(gwin); + ami_throbber_redraw_schedule(0, gwin->bw->window); } } @@ -3155,6 +3144,11 @@ void ami_gui_tabs_toggle_all(void) } while(node = nnode); } +void ami_gui_search_ico_refresh(void *p) +{ + search_web_select_provider(-1); +} + nserror ami_gui_new_blank_tab(struct gui_window_2 *gwin) { nsurl *url; @@ -3799,7 +3793,7 @@ gui_window_create(struct browser_window *bw, if(locked_screen) UnlockPubScreen(NULL,scrn); - ami_schedule(0, search_web_select_provider, -1); + ami_schedule(0, ami_gui_search_ico_refresh, NULL); ScreenToFront(scrn); @@ -4756,7 +4750,8 @@ static nserror gui_search_web_provider_update(const char *provider_name, static uint32 ami_set_throbber_render_hook(struct Hook *hook, APTR space, struct gpRender *msg) { - refresh_throbber = TRUE; + struct gui_window_2 *gwin = hook->h_Data; + ami_throbber_redraw_schedule(0, gwin->bw->window); return 0; } diff --git a/amiga/theme.c b/amiga/theme.c index a04efe8bc..d56a07048 100644 --- a/amiga/theme.c +++ b/amiga/theme.c @@ -158,7 +158,7 @@ void ami_theme_throbber_setup(void) ami_get_theme_filename(throbberfile,"theme_throbber",false); throbber_frames=atoi(messages_get("theme_throbber_frames")); throbber_update_interval = atoi(messages_get("theme_throbber_delay")); - if(throbber_update_interval == 0) throbber_update_interval = 100; + if(throbber_update_interval == 0) throbber_update_interval = 250; bm = ami_bitmap_from_datatype(throbberfile); throbber = ami_bitmap_get_native(bm, bm->width, bm->height, NULL); @@ -424,16 +424,8 @@ void gui_window_start_throbber(struct gui_window *g) } g->throbbing = true; - - if((cur_tab == g->tab) || (g->shared->tabs <= 1)) - { - GetAttr(SPACE_AreaBox, g->shared->objects[GID_THROBBER], - (ULONG *)&bbox); - - if(g->shared->throbber_frame == 0) g->shared->throbber_frame=1; - - BltBitMapRastPort(throbber,throbber_width,0,g->shared->win->RPort,bbox->Left,bbox->Top,throbber_width,throbber_height,0x0C0); - } + g->shared->throbber_frame = 1; + ami_throbber_redraw_schedule(throbber_update_interval, g); } void gui_window_stop_throbber(struct gui_window *g) @@ -453,8 +445,6 @@ void gui_window_stop_throbber(struct gui_window *g) g->shared->win, NULL); } - g->throbbing = false; - if((cur_tab == g->tab) || (g->shared->tabs <= 1)) { GetAttr(SPACE_AreaBox, g->shared->objects[GID_THROBBER], @@ -463,71 +453,58 @@ void gui_window_stop_throbber(struct gui_window *g) BltBitMapRastPort(throbber, 0, 0, g->shared->win->RPort, bbox->Left, bbox->Top, throbber_width, throbber_height, 0x0C0); } -// g->shared->throbber_frame = 0; + + g->throbbing = false; + ami_throbber_redraw_schedule(-1, g); } -void ami_update_throbber(struct gui_window_2 *g, bool redraw) +static void ami_throbber_update(void *p) { + struct gui_window *g = (struct gui_window *)p; struct IBox *bbox; - int frame; + int frame = 0; + ULONG cur_tab = 0; if(!g) return; - if(!g->objects[GID_THROBBER]) return; + if(!g->shared->objects[GID_THROBBER]) return; - if(g->bw->window->throbbing == false) - { - frame = 0; - g->throbber_frame = 1; + if(g->throbbing == true) { + frame = g->shared->throbber_frame; + g->shared->throbber_frame++; + if(g->shared->throbber_frame > (throbber_frames-1)) + g->shared->throbber_frame=1; } - else - { - frame = g->throbber_frame; - if(!redraw) - { - if(g->throbber_update_count < throbber_update_interval) - { - g->throbber_update_count++; - return; - } - - g->throbber_update_count = 0; - - g->throbber_frame++; - if(g->throbber_frame > (throbber_frames-1)) - g->throbber_frame=1; - - } + if(g->tab_node && (g->shared->tabs > 1)) + { + GetAttr(CLICKTAB_Current, g->shared->objects[GID_TABS], + (ULONG *)&cur_tab); } - GetAttr(SPACE_AreaBox,(Object *)g->objects[GID_THROBBER],(ULONG *)&bbox); + if((cur_tab == g->tab) || (g->shared->tabs <= 1)) + { + GetAttr(SPACE_AreaBox, g->shared->objects[GID_THROBBER], + (ULONG *)&bbox); -/* - EraseRect(g->win->RPort,bbox->Left,bbox->Top, - bbox->Left+throbber_width,bbox->Top+throbber_height); -*/ - - BltBitMapTags(BLITA_SrcX, throbber_width * frame, - BLITA_SrcY,0, - BLITA_DestX,bbox->Left, - BLITA_DestY,bbox->Top, - BLITA_Width,throbber_width, - BLITA_Height,throbber_height, - BLITA_Source,throbber, - BLITA_Dest,g->win->RPort, - BLITA_SrcType,BLITT_BITMAP, - BLITA_DestType,BLITT_RASTPORT, -// BLITA_UseSrcAlpha,TRUE, + BltBitMapTags(BLITA_SrcX, throbber_width * frame, + BLITA_SrcY, 0, + BLITA_DestX, bbox->Left, + BLITA_DestY, bbox->Top, + BLITA_Width, throbber_width, + BLITA_Height, throbber_height, + BLITA_Source, throbber, + BLITA_Dest, g->shared->win->RPort, + BLITA_SrcType, BLITT_BITMAP, + BLITA_DestType, BLITT_RASTPORT, + // BLITA_UseSrcAlpha, TRUE, TAG_DONE); -} + } -static void ami_throbber_redraw(void *gwin) -{ - ami_update_throbber((struct gui_window_2 *)gwin, true); + if(frame > 0) ami_throbber_redraw_schedule(throbber_update_interval, g); } -void ami_throbber_redraw_schedule(int t, struct gui_window_2 *gwin) +void ami_throbber_redraw_schedule(int t, struct gui_window *g) { - ami_schedule(t, ami_throbber_redraw, (void *)gwin); + ami_schedule(t, ami_throbber_update, g); } diff --git a/amiga/theme.h b/amiga/theme.h index ed61ef148..c1aca15d7 100644 --- a/amiga/theme.h +++ b/amiga/theme.h @@ -44,7 +44,7 @@ void ami_update_pointer(struct Window *win, gui_pointer_shape shape); void gui_window_start_throbber(struct gui_window *g); void gui_window_stop_throbber(struct gui_window *g); -void ami_throbber_redraw_schedule(int t, struct gui_window_2 *gwin); +void ami_throbber_redraw_schedule(int t, struct gui_window *g); void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape); #endif -- cgit v1.2.3 From ab5b2d9afed9f6252630221723e0c2ed86fb6b5d Mon Sep 17 00:00:00 2001 From: Chris Young Date: Sat, 5 Jul 2014 19:00:21 +0100 Subject: Move favicon redraw to scheduled callback --- amiga/gui.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/amiga/gui.c b/amiga/gui.c index fd59b5b70..8d6d19ee4 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -172,7 +172,6 @@ ULONG screen_signal = -1; struct MsgPort *applibport = NULL; ULONG applibsig = 0; -BOOL refresh_favicon = FALSE; struct Hook newprefs_hook; STRPTR temp_homepage_url = NULL; @@ -1418,6 +1417,12 @@ static void gui_window_set_icon(struct gui_window *g, hlcache_handle *icon) g->favicon = icon; } +static void ami_gui_refresh_favicon(void *p) +{ + struct gui_window_2 *gwin = (struct gui_window_2 *)p; + gui_window_set_icon(gwin->bw->window, gwin->bw->window->favicon); +} + void ami_handle_msg(void) { ULONG class,result,storage = 0,x,y,xs,ys,width=800,height=600; @@ -2131,7 +2136,7 @@ void ami_handle_msg(void) } while(tab=ntab); } - refresh_favicon = TRUE; + ami_schedule(0, ami_gui_refresh_favicon, gwin); gwin->bw->reformat_pending = true; ami_schedule_redraw(gwin, true); break; @@ -2210,12 +2215,6 @@ void ami_handle_msg(void) } } while(node = nnode); - if(refresh_favicon) - { - gui_window_set_icon(gwin->bw->window, gwin->bw->window->favicon); - refresh_favicon = FALSE; - } - if(ami_menu_window_close) { if(ami_menu_window_close == (void *)AMI_MENU_WINDOW_CLOSE_ALL) @@ -2561,8 +2560,8 @@ void ami_switch_tab(struct gui_window_2 *gwin,bool redraw) GetAttr(CLICKTAB_CurrentNode, (Object *)gwin->objects[GID_TABS], (ULONG *)&tabnode); GetClickTabNodeAttrs(tabnode, - TNA_UserData, &gwin->bw, - TAG_DONE); + TNA_UserData, &gwin->bw, + TAG_DONE); curbw = gwin->bw; GetAttr(SPACE_AreaBox, (Object *)gwin->objects[GID_BROWSER], (ULONG *)&bbox); @@ -3271,6 +3270,7 @@ gui_window_create(struct browser_window *bw, if(nsoption_bool(new_tab_is_active)) ami_switch_tab(g->shared,false); ami_update_buttons(g->shared); + ami_schedule(0, ami_gui_refresh_favicon, g->shared); return g; } @@ -4690,7 +4690,7 @@ static void gui_window_set_url(struct gui_window *g, const char *url) static uint32 ami_set_favicon_render_hook(struct Hook *hook, APTR space, struct gpRender *msg) { - refresh_favicon = TRUE; + ami_schedule(0, ami_gui_refresh_favicon, hook->h_Data); return 0; } -- cgit v1.2.3 From f5c62c2291add5e6e3b8fc604831283e4883a3c6 Mon Sep 17 00:00:00 2001 From: Chris Young Date: Sat, 5 Jul 2014 19:07:20 +0100 Subject: Stop the throbber resetting itself to frame 1 --- amiga/theme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amiga/theme.c b/amiga/theme.c index d56a07048..cc8b55d7f 100644 --- a/amiga/theme.c +++ b/amiga/theme.c @@ -424,7 +424,7 @@ void gui_window_start_throbber(struct gui_window *g) } g->throbbing = true; - g->shared->throbber_frame = 1; + if(g->shared->throbber_frame == 0) g->shared->throbber_frame = 1; ami_throbber_redraw_schedule(throbber_update_interval, g); } -- cgit v1.2.3 From caf918d2f28f600184036aef3f096024d3af62a7 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 6 Jul 2014 11:01:39 +0100 Subject: fixup merge of scheduled reformat --- atari/deskmenu.c | 8 ++++---- atari/rootwin.c | 2 +- cocoa/gui.m | 2 +- framebuffer/gui.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/atari/deskmenu.c b/atari/deskmenu.c index 53e24a4d4..96b2d02ce 100644 --- a/atari/deskmenu.c +++ b/atari/deskmenu.c @@ -394,8 +394,8 @@ static void __CDECL menu_inc_scale(short item, short title, void *data) if(input_window == NULL) return; - browser_window_set_scale(input_window->bw, - browser_window_get_scale(input_window->bw) + 0.25, + browser_window_set_scale(input_window->browser->bw, + browser_window_get_scale(input_window->browser->bw) + 0.25, true); } @@ -405,8 +405,8 @@ static void __CDECL menu_dec_scale(short item, short title, void *data) if(input_window == NULL) return; - browser_window_set_scale(input_window->bw, - browser_window_get_scale(input_window->bw) - 0.25, + browser_window_set_scale(input_window->browser->bw, + browser_window_get_scale(input_window->browser->bw) - 0.25, true); } diff --git a/atari/rootwin.c b/atari/rootwin.c index 7c2cdbcf1..a9c958e04 100755 --- a/atari/rootwin.c +++ b/atari/rootwin.c @@ -834,7 +834,7 @@ static void window_redraw_content(ROOTWIN *rootwin, GRECT *content_area, plot_set_dimensions(content_area->g_x, content_area->g_y, content_area->g_w, content_area->g_h); - oldscale = plot_set_scale(browser_window_get_scale(rootwin->active_gui_window->bw)); + oldscale = plot_set_scale(browser_window_get_scale(rootwin->active_gui_window->browser->bw)); /* first, we make the coords relative to the content area: */ content_area_rel.g_x = clip->g_x - content_area->g_x; diff --git a/cocoa/gui.m b/cocoa/gui.m index 405dab9c2..8f08fc7fa 100644 --- a/cocoa/gui.m +++ b/cocoa/gui.m @@ -135,7 +135,7 @@ static void gui_window_set_scroll(struct gui_window *g, int sx, int sy) static void cocoa_window_reformat(struct gui_window *gw) { if (gw != NULL) { - [[(BrowserViewController *)g browserView] reformat ]; + [[(BrowserViewController *)gw browserView] reformat ]; } } diff --git a/framebuffer/gui.c b/framebuffer/gui.c index 727319f0f..2a691f7f6 100644 --- a/framebuffer/gui.c +++ b/framebuffer/gui.c @@ -1758,7 +1758,7 @@ gui_window_remove_caret(struct gui_window *g) } } -static void nsgtk_window_reformat(struct gui_window *gw) +static void framebuffer_window_reformat(struct gui_window *gw) { /** @todo if we ever do zooming reformat should be implemented */ LOG(("window:%p", gw)); -- cgit v1.2.3 From 3a9fa29ee53bef70a0e643847acc2fb374501f70 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 6 Jul 2014 18:34:34 +0100 Subject: try and improve usage of browser window internals --- amiga/menu.c | 8 ++++++-- atari/gui.c | 10 +++++----- desktop/browser.c | 40 +++++++++++++++++++++++----------------- desktop/browser.h | 35 ++++++++++++++++++++++++++++++----- desktop/browser_private.h | 1 + gtk/scaffolding.c | 5 ++--- gtk/window.c | 8 +------- render/form.h | 3 ++- render/html.h | 7 ++++--- riscos/dialog.c | 1 + riscos/iconbar.c | 1 + riscos/window.c | 10 +++------- 12 files changed, 79 insertions(+), 50 deletions(-) diff --git a/amiga/menu.c b/amiga/menu.c index c1e863a65..70028af68 100644 --- a/amiga/menu.c +++ b/amiga/menu.c @@ -893,8 +893,12 @@ static void ami_menu_item_edit_copy(struct Hook *hook, APTR window, struct Intui } else if(bm = content_get_bitmap(gwin->bw->current_content)) { - bm->url = (char *)nsurl_access(hlcache_handle_get_url(gwin->bw->current_content)); - bm->title = (char *)content_get_title(gwin->bw->current_content); + /** @todo It should be checked that the lifetime of + * the objects containing the values returned (and the + * constness cast away) is safe. + */ + bm->url = (char *)nsurl_access(browser_window_get_url(gwin->bw)); + bm->title = (char *)browser_window_get_title(gwin->bw); ami_easy_clipboard_bitmap(bm); } #ifdef WITH_NS_SVG diff --git a/atari/gui.c b/atari/gui.c index efa23efe4..f267b69a8 100644 --- a/atari/gui.c +++ b/atari/gui.c @@ -394,10 +394,10 @@ bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy) static void gui_window_set_scroll(struct gui_window *w, int sx, int sy) { - if ((w == NULL) - || (w->browser->bw == NULL) - || (w->browser->bw->current_content == NULL)) - return; + if ( (w == NULL) + || (w->browser->bw == NULL) + || (!browser_window_has_content(w->browser->bw))) + return; LOG(("scroll (gui_window: %p) %d, %d\n", w, sx, sy)); window_scroll_by(w->root, sx, sy); @@ -412,7 +412,7 @@ static void gui_window_set_scroll(struct gui_window *w, int sx, int sy) static void gui_window_update_extent(struct gui_window *gw) { - if( gw->browser->bw->current_content != NULL ) { + if(browser_window_has_content(gw->browser->bw)) { // TODO: store content size! if(window_get_active_gui_window(gw->root) == gw) { window_set_content_size( gw->root, diff --git a/desktop/browser.c b/desktop/browser.c index dc2db723c..684035a0a 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -781,9 +781,18 @@ nserror browser_window_initialise_common(enum browser_window_create_flags flags, if (flags & BW_CREATE_CLONE) { assert(existing != NULL); + + /* clone history */ err = browser_window_history_clone(existing, bw); + + /* copy the scale */ + bw->scale = existing->scale; } else { + /* create history */ err = browser_window_history_create(bw); + + /* default scale */ + bw->scale = (float) nsoption_int(scale) / 100.0; } if (err != NSERROR_OK) @@ -793,7 +802,6 @@ nserror browser_window_initialise_common(enum browser_window_create_flags flags, bw->refresh_interval = -1; bw->drag_type = DRAGGING_NONE; - bw->scale = (float) nsoption_int(scale) / 100.0; bw->scroll_x = NULL; bw->scroll_y = NULL; @@ -1958,7 +1966,7 @@ nserror browser_window_navigate(struct browser_window *bw, /* Exported interface, documented in browser.h */ -nsurl * browser_window_get_url(struct browser_window *bw) +nsurl* browser_window_get_url(struct browser_window *bw) { assert(bw != NULL); @@ -1973,6 +1981,17 @@ nsurl * browser_window_get_url(struct browser_window *bw) return corestring_nsurl_about_blank; } +/* Exported interface, documented in browser.h */ +const char* browser_window_get_title(struct browser_window *bw) +{ + assert(bw != NULL); + + if (bw->current_content != NULL) { + return content_get_title(bw->current_content); + } + + return NULL; +} /* Exported interface, documented in browser.h */ struct history * browser_window_get_history(struct browser_window *bw) @@ -2436,14 +2455,7 @@ static void browser_window_set_scale_internal(struct browser_window *bw, } -/** - * Sets the scale of a browser window - * - * \param bw The browser window to scale - * \param scale The new scale - * \param all Scale all windows in the tree (ie work up aswell as down) - */ - +/* exported interface documented in desktop/browser.h */ void browser_window_set_scale(struct browser_window *bw, float scale, bool all) { while (bw->parent && all) @@ -2458,13 +2470,7 @@ void browser_window_set_scale(struct browser_window *bw, float scale, bool all) } -/** - * Gets the scale of a browser window - * - * \param bw The browser window to scale - * \return - */ - +/* exported interface documented in desktop/browser.h */ float browser_window_get_scale(struct browser_window *bw) { return bw->scale; diff --git a/desktop/browser.h b/desktop/browser.h index 88b757727..6e893fffb 100644 --- a/desktop/browser.h +++ b/desktop/browser.h @@ -28,7 +28,7 @@ #include #include "utils/types.h" -#include "utils/nsurl.h" +#include "utils/errors.h" #include "desktop/plot_style.h" #include "desktop/frame_types.h" #include "desktop/mouse.h" @@ -41,6 +41,7 @@ struct history; struct selection; struct fetch_multipart_data; struct form_control; +struct nsurl; typedef enum { DRAGGING_NONE, @@ -120,7 +121,7 @@ enum browser_window_nav_flags { * \return NSERROR_OK, or appropriate error otherwise. */ nserror browser_window_create(enum browser_window_create_flags flags, - nsurl *url, nsurl *referrer, + struct nsurl *url, struct nsurl *referrer, struct browser_window *existing, struct browser_window **bw); @@ -142,8 +143,8 @@ nserror browser_window_create(enum browser_window_create_flags flags, * */ nserror browser_window_navigate(struct browser_window *bw, - nsurl *url, - nsurl *referrer, + struct nsurl *url, + struct nsurl *referrer, enum browser_window_nav_flags flags, char *post_urlenc, struct fetch_multipart_data *post_multipart, @@ -157,7 +158,14 @@ nserror browser_window_navigate(struct browser_window *bw, * * Note: guaranteed to return a valid nsurl ptr, never returns NULL. */ -nsurl * browser_window_get_url(struct browser_window *bw); +struct nsurl* browser_window_get_url(struct browser_window *bw); + +/** + * Get the title of a browser_window. + * + * \param bw The browser window. + */ +const char* browser_window_get_title(struct browser_window *bw); /** * Get a browser window's history object. @@ -200,7 +208,24 @@ void browser_window_reload(struct browser_window *bw, bool all); void browser_window_destroy(struct browser_window *bw); void browser_window_reformat(struct browser_window *bw, bool background, int width, int height); + + +/** + * Sets the scale of a browser window. + * + * \param bw The browser window to scale. + * \param scale The new scale. + * \param all Scale all windows in the tree (ie work up aswell as down) + */ void browser_window_set_scale(struct browser_window *bw, float scale, bool all); + + +/** + * Gets the scale of a browser window + * + * \param bw The browser window to get the scale of. + * \return The scale of teh window. + */ float browser_window_get_scale(struct browser_window *bw); /** diff --git a/desktop/browser_private.h b/desktop/browser_private.h index cbc29aaa3..d2c48d704 100644 --- a/desktop/browser_private.h +++ b/desktop/browser_private.h @@ -25,6 +25,7 @@ #define _NETSURF_DESKTOP_BROWSER_PRIVATE_H_ #include +#include #include "desktop/browser.h" diff --git a/gtk/scaffolding.c b/gtk/scaffolding.c index c2dc0fdc9..ee2d46227 100644 --- a/gtk/scaffolding.c +++ b/gtk/scaffolding.c @@ -2444,9 +2444,8 @@ void nsgtk_scaffolding_set_top_level(struct gui_window *gw) nsgtk_scaffolding_set_icon(gw); /* Ensure the window's title bar is updated */ - if (bw->current_content != NULL) { - gui_window_set_title(gw, content_get_title(bw->current_content)); - } + gui_window_set_title(gw, browser_window_get_title(bw)); + } /* exported interface documented in scaffolding.h */ diff --git a/gtk/window.c b/gtk/window.c index d1cd6b1a5..9c4b668b9 100644 --- a/gtk/window.c +++ b/gtk/window.c @@ -34,7 +34,7 @@ #include "gtk/window.h" #include "gtk/selection.h" #include "desktop/gui.h" -#include "desktop/browser_private.h" +#include "desktop/browser.h" #include "desktop/mouse.h" #include "desktop/searchweb.h" #include "desktop/textinput.h" @@ -728,12 +728,6 @@ gui_window_create(struct browser_window *bw, g->bw = bw; g->mouse.state = 0; g->current_pointer = GUI_POINTER_DEFAULT; - if (flags & GW_CREATE_CLONE) { - assert(existing != NULL); - bw->scale = existing->bw->scale; - } else { - bw->scale = nsoption_int(scale) / 100; - } /* attach scaffold */ if (flags & GW_CREATE_TAB) { diff --git a/render/form.h b/render/form.h index f072b801e..7715b9ad3 100644 --- a/render/form.h +++ b/render/form.h @@ -36,6 +36,7 @@ struct form_select_menu; struct html_content; struct dom_string; struct content; +struct nsurl; /** Form submit method. */ typedef enum { @@ -188,7 +189,7 @@ void form_select_mouse_drag_end(struct form_control *control, void form_select_get_dimensions(struct form_control *control, int *width, int *height); void form_select_process_selection(struct form_control *control, int item); -void form_submit(nsurl *page_url, struct browser_window *target, +void form_submit(struct nsurl *page_url, struct browser_window *target, struct form *form, struct form_control *submit_button); void form_radio_set(struct form_control *radio); diff --git a/render/html.h b/render/html.h index 7ca75e713..a5ee5ffa5 100644 --- a/render/html.h +++ b/render/html.h @@ -51,6 +51,7 @@ struct scrollbar; struct scrollbar_msg_data; struct search_context; struct selection; +struct nsurl; /** * Container for stylesheets used by an HTML document @@ -113,7 +114,7 @@ struct content_html_frames { int margin_height; /** frame margin height */ char *name; /** frame name (for targetting) */ - nsurl *url; /** frame url */ + struct nsurl *url; /** frame url */ bool no_resize; /** frame is not resizable */ frame_scrolling scrolling; /** scrolling characteristics */ @@ -131,7 +132,7 @@ struct content_html_iframe { int margin_height; /** frame margin height */ char *name; /** frame name (for targetting) */ - nsurl *url; /** frame url */ + struct nsurl *url; /** frame url */ frame_scrolling scrolling; /** scrolling characteristics */ bool border; /** frame has a border */ @@ -176,7 +177,7 @@ const char *html_get_encoding(struct hlcache_handle *h); dom_hubbub_encoding_source html_get_encoding_source(struct hlcache_handle *h); struct content_html_frames *html_get_frameset(struct hlcache_handle *h); struct content_html_iframe *html_get_iframe(struct hlcache_handle *h); -nsurl *html_get_base_url(struct hlcache_handle *h); +struct nsurl *html_get_base_url(struct hlcache_handle *h); const char *html_get_base_target(struct hlcache_handle *h); void html_set_file_gadget_filename(struct hlcache_handle *hl, struct form_control *gadget, const char *fn); diff --git a/riscos/dialog.c b/riscos/dialog.c index 1c95a7099..fd854b857 100644 --- a/riscos/dialog.c +++ b/riscos/dialog.c @@ -37,6 +37,7 @@ #include "utils/nsoption.h" #include "utils/log.h" #include "utils/messages.h" +#include "utils/nsurl.h" #include "utils/url.h" #include "utils/utils.h" #include "desktop/netsurf.h" diff --git a/riscos/iconbar.c b/riscos/iconbar.c index 11640fe7c..f29b019a2 100644 --- a/riscos/iconbar.c +++ b/riscos/iconbar.c @@ -36,6 +36,7 @@ #include "utils/log.h" #include "utils/messages.h" #include "utils/utils.h" +#include "utils/nsurl.h" #include "desktop/netsurf.h" #include "desktop/browser.h" diff --git a/riscos/window.c b/riscos/window.c index 2ad432b2e..ab4cb0c50 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -602,8 +602,6 @@ static struct gui_window *gui_window_create(struct browser_window *bw, ro_gui_window_menu_close); /* Set the window options */ - bw->window = g; - bw->scale = ((float)nsoption_int(scale)) / 100; ro_gui_window_clone_options(g, existing); ro_gui_window_update_toolbar_buttons(g); @@ -2424,7 +2422,6 @@ void ro_gui_window_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, wimp_selection *selection, menu_action action) { struct gui_window *g; - struct browser_window *bw; hlcache_handle *h; struct toolbar *toolbar; bool export; @@ -2434,8 +2431,7 @@ void ro_gui_window_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, g = (struct gui_window *) ro_gui_wimp_event_get_user_data(w); toolbar = g->toolbar; - bw = g->bw; - h = bw->current_content; + h = g->bw->current_content; switch (action) { case BROWSER_PAGE_INFO: @@ -2472,9 +2468,9 @@ void ro_gui_window_menu_warning(wimp_w w, wimp_i i, wimp_menu *menu, break; case BROWSER_SELECTION_SAVE: - if (browser_window_get_editor_flags(bw) & BW_EDITOR_CAN_COPY) + if (browser_window_get_editor_flags(g->bw) & BW_EDITOR_CAN_COPY) ro_gui_save_prepare(GUI_SAVE_TEXT_SELECTION, NULL, - browser_window_get_selection(bw), + browser_window_get_selection(g->bw), NULL, NULL); break; -- cgit v1.2.3 From 07f1ae746145022fb07ecb9e9163c013f432d13f Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 6 Jul 2014 19:36:12 +0100 Subject: fixup missing includes --- atari/toolbar.h | 3 ++- cocoa/BrowserWindowController.m | 1 + cocoa/NetSurfAppDelegate.m | 1 + windows/main.c | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/atari/toolbar.h b/atari/toolbar.h index be4bd038e..284376fcb 100644 --- a/atari/toolbar.h +++ b/atari/toolbar.h @@ -26,6 +26,7 @@ #include "desktop/browser.h" struct s_toolbar; +struct nsurl; enum toolbar_textarea { URL_INPUT_TEXT_AREA = 1 @@ -76,7 +77,7 @@ OBJECT *toolbar_get_form(struct s_toolbar *tb); struct textarea *toolbar_get_textarea(struct s_toolbar *tb, enum toolbar_textarea which); char *toolbar_get_url(struct s_toolbar *tb); -nsurl * toolbar_get_nsurl(struct s_toolbar * tb); +struct nsurl * toolbar_get_nsurl(struct s_toolbar * tb); void toolbar_set_throbber_state(struct s_toolbar *tb, bool active); void toolbar_set_attached(struct s_toolbar *tb, bool attached); void toolbar_set_visible(struct s_toolbar *tb, short area, bool visible); diff --git a/cocoa/BrowserWindowController.m b/cocoa/BrowserWindowController.m index 1d70778a1..cfc45cd7c 100644 --- a/cocoa/BrowserWindowController.m +++ b/cocoa/BrowserWindowController.m @@ -29,6 +29,7 @@ #import "utils/nsoption.h" #import "utils/messages.h" #import "utils/utils.h" +#import "utils/nsurl.h" @interface BrowserWindowController () diff --git a/cocoa/NetSurfAppDelegate.m b/cocoa/NetSurfAppDelegate.m index e17353529..34605a95c 100644 --- a/cocoa/NetSurfAppDelegate.m +++ b/cocoa/NetSurfAppDelegate.m @@ -25,6 +25,7 @@ #import "utils/nsoption.h" #import "utils/messages.h" #import "utils/utils.h" +#import "utils/nsurl.h" @interface NetSurfAppDelegate () diff --git a/windows/main.c b/windows/main.c index f9792c259..20f9f041a 100644 --- a/windows/main.c +++ b/windows/main.c @@ -32,6 +32,7 @@ #include "utils/messages.h" #include "utils/filepath.h" #include "utils/file.h" +#include "utils/nsurl.h" #include "content/fetchers/resource.h" #include "windows/findfile.h" -- cgit v1.2.3 From 5ce4f11eac7fae76fe2965f92daf2910f80eb6a1 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 7 Jul 2014 23:29:06 +0100 Subject: add link context menu to gtk and add link copying and bookmarking --- gtk/menu.c | 86 +++++++++++++++---------- gtk/menu.h | 30 ++++++++- gtk/scaffolding.c | 174 +++++++++++++++++++++++++++++++++++--------------- gtk/scaffolding.h | 11 +++- gtk/window.c | 5 +- resources/FatMessages | 42 +++++++----- utils/types.h | 6 +- 7 files changed, 248 insertions(+), 106 deletions(-) diff --git a/gtk/menu.c b/gtk/menu.c index 7c55a9fd6..14eb1f286 100644 --- a/gtk/menu.c +++ b/gtk/menu.c @@ -53,6 +53,13 @@ static bool nsgtk_menu_add_image_item(GtkMenu *menu, return true; } +#define NEW_MENU(n, m) \ + n = malloc(sizeof(*n)); \ + if (n == NULL) { \ + return NULL; \ + } \ + n->m##_menu = GTK_MENU(gtk_menu_new()) + #define IMAGE_ITEM(p, q, r, s, t)\ nsgtk_menu_add_image_item(s->p##_menu, &(s->q##_menuitem), #r,\ #r "Accel", t) @@ -66,7 +73,7 @@ static bool nsgtk_menu_add_image_item(GtkMenu *menu, GTK_WIDGET(s->q##_menuitem));\ gtk_widget_show(GTK_WIDGET(s->q##_menuitem));\ } - + #define SET_SUBMENU(q, r) \ do { \ r->q##_submenu = nsgtk_menu_##q##_submenu(group); \ @@ -76,7 +83,7 @@ static bool nsgtk_menu_add_image_item(GtkMenu *menu, gtk_menu_item_set_submenu(GTK_MENU_ITEM(r->q##_menuitem), \ GTK_WIDGET(r->q##_submenu->q##_menu)); \ } \ - } while(0) + } while(0) #define ADD_NAMED_SEP(q, r, s) \ do { \ @@ -85,7 +92,7 @@ static bool nsgtk_menu_add_image_item(GtkMenu *menu, gtk_menu_shell_append(GTK_MENU_SHELL(s->q##_menu), s->r##_separator); \ gtk_widget_show(s->r##_separator); \ } \ - } while(0) + } while(0) #define ADD_SEP(q, r) \ do { \ @@ -94,7 +101,7 @@ static bool nsgtk_menu_add_image_item(GtkMenu *menu, gtk_menu_shell_append(GTK_MENU_SHELL(r->q##_menu), w); \ gtk_widget_show(w); \ } \ - } while(0) + } while(0) #define ATTACH_PARENT(parent, msgname, menuv, group) \ do { \ @@ -107,9 +114,9 @@ static bool nsgtk_menu_add_image_item(GtkMenu *menu, gtk_menu_item_set_submenu(menuv, GTK_WIDGET(menuv##_menu)); \ gtk_menu_set_accel_group(menuv##_menu, group); \ } \ - } while(0) + } while(0) -/** +/** * creates an export submenu * \param group the 'global' in a gtk sense accelerator reference */ @@ -135,7 +142,7 @@ static struct nsgtk_export_submenu *nsgtk_menu_export_submenu(GtkAccelGroup *gro return ret; } -/** +/** * creates a scaleview submenu * \param group the 'global' in a gtk sense accelerator reference */ @@ -143,7 +150,7 @@ static struct nsgtk_export_submenu *nsgtk_menu_export_submenu(GtkAccelGroup *gro static struct nsgtk_scaleview_submenu *nsgtk_menu_scaleview_submenu( GtkAccelGroup *group) { - struct nsgtk_scaleview_submenu *ret = + struct nsgtk_scaleview_submenu *ret = malloc(sizeof(struct nsgtk_scaleview_submenu)); if (ret == NULL) { warn_user(messages_get("NoMemory"), 0); @@ -161,7 +168,7 @@ static struct nsgtk_scaleview_submenu *nsgtk_menu_scaleview_submenu( return ret; } -/** +/** * creates a tab navigation submenu * \param group the 'global' in a gtk sense accelerator reference */ @@ -186,7 +193,7 @@ static struct nsgtk_tabs_submenu *nsgtk_menu_tabs_submenu(GtkAccelGroup *group) return ret; } -/** +/** * creates an images submenu * \param group the 'global' in a gtk sense accelerator reference */ @@ -210,7 +217,7 @@ static struct nsgtk_images_submenu *nsgtk_menu_images_submenu(GtkAccelGroup *gro return ret; } -/** +/** * creates a toolbars submenu * \param group the 'global' in a gtk sense accelerator reference */ @@ -234,12 +241,12 @@ static struct nsgtk_toolbars_submenu *nsgtk_menu_toolbars_submenu( if (ret->menubar_menuitem != NULL) gtk_check_menu_item_set_active(ret->menubar_menuitem, TRUE); CHECK_ITEM(toolbars, toolbar, gtkToolBar, ret) - if (ret->toolbar_menuitem != NULL) + if (ret->toolbar_menuitem != NULL) gtk_check_menu_item_set_active(ret->toolbar_menuitem, TRUE); return ret; } -/** +/** * creates a debugging submenu * \param group the 'global' in a gtk sense accelerator reference */ @@ -264,8 +271,8 @@ static struct nsgtk_debugging_submenu *nsgtk_menu_debugging_submenu( IMAGE_ITEM(debugging, savedomtree, gtkSaveDomTree, ret, group); return ret; } - -/** + +/** * creates the file menu * \param group The gtk 'global' accelerator reference * \param parent The parent menu to attach to or NULL @@ -304,7 +311,7 @@ static struct nsgtk_file_menu *nsgtk_menu_file_submenu(GtkAccelGroup *group) return fmenu; } -/** +/** * creates an edit menu * \param group the 'global' in a gtk sense accelerator reference */ @@ -336,7 +343,7 @@ static struct nsgtk_edit_menu *nsgtk_menu_edit_submenu(GtkAccelGroup *group) return ret; } -/** +/** * creates a view menu * \param group the 'global' in a gtk sense accelerator reference */ @@ -378,7 +385,7 @@ static struct nsgtk_view_menu *nsgtk_menu_view_submenu(GtkAccelGroup *group) return ret; } -/** +/** * creates a nav menu * \param group the 'global' in a gtk sense accelerator reference */ @@ -415,7 +422,7 @@ static struct nsgtk_nav_menu *nsgtk_menu_nav_submenu(GtkAccelGroup *group) return ret; } -/** +/** * creates a help menu * \param group the 'global' in a gtk sense accelerator reference */ @@ -448,9 +455,9 @@ static struct nsgtk_help_menu *nsgtk_menu_help_submenu(GtkAccelGroup *group) * * Generate the main menu structure and attach it to a menubar widget. */ -struct nsgtk_bar_submenu *nsgtk_menu_bar_create(GtkMenuShell *menubar, GtkAccelGroup *group) +struct nsgtk_bar_submenu * +nsgtk_menu_bar_create(GtkMenuShell *menubar, GtkAccelGroup *group) { - ; struct nsgtk_bar_submenu *nmenu; nmenu = malloc(sizeof(struct nsgtk_bar_submenu)); @@ -479,22 +486,13 @@ struct nsgtk_bar_submenu *nsgtk_menu_bar_create(GtkMenuShell *menubar, GtkAccelG return nmenu; } -/** - * Generate right click menu menu. - * - */ -struct nsgtk_popup_submenu *nsgtk_menu_popup_create(GtkAccelGroup *group) +/* exported function documented in gtk/menu.h */ +struct nsgtk_popup_menu *nsgtk_popup_menu_create(GtkAccelGroup *group) { - struct nsgtk_popup_submenu *nmenu; + struct nsgtk_popup_menu *nmenu; - nmenu = malloc(sizeof(struct nsgtk_popup_submenu)); - if (nmenu == NULL) { - warn_user(messages_get("NoMemory"), 0); - return NULL; - } + NEW_MENU(nmenu, popup); - nmenu->popup_menu = GTK_MENU(gtk_menu_new()); - IMAGE_ITEM(popup, file, gtkFile, nmenu, group); SET_SUBMENU(file, nmenu); @@ -530,6 +528,26 @@ struct nsgtk_popup_submenu *nsgtk_menu_popup_create(GtkAccelGroup *group) IMAGE_ITEM(popup, paste, gtkPaste, nmenu, group); IMAGE_ITEM(popup, customize, gtkCustomize, nmenu, group); + return nmenu; +} + + +/* exported function documented in gtk/menu.h */ +struct nsgtk_link_menu * +nsgtk_link_menu_create(GtkAccelGroup *group) +{ + struct nsgtk_link_menu *nmenu; + + NEW_MENU(nmenu, link); + + IMAGE_ITEM(link, opentab, gtkOpentab, nmenu, group); + IMAGE_ITEM(link, openwin, gtkOpenwin, nmenu, group); + + ADD_SEP(link, nmenu); + + IMAGE_ITEM(link, save, gtkSavelink, nmenu, group); + IMAGE_ITEM(link, bookmark, gtkBookmarklink, nmenu, group); + IMAGE_ITEM(link, copy, gtkCopylink, nmenu, group); return nmenu; } diff --git a/gtk/menu.h b/gtk/menu.h index 681f43c2b..48b3f0f5c 100644 --- a/gtk/menu.h +++ b/gtk/menu.h @@ -143,7 +143,7 @@ struct nsgtk_bar_submenu { struct nsgtk_help_menu *help_submenu; }; -struct nsgtk_popup_submenu { +struct nsgtk_popup_menu { GtkMenu *popup_menu; GtkImageMenuItem *file_menuitem; @@ -189,7 +189,33 @@ struct nsgtk_popup_submenu { }; +struct nsgtk_link_menu { + GtkMenu *link_menu; + + GtkImageMenuItem *opentab_menuitem; + GtkImageMenuItem *openwin_menuitem; + + GtkImageMenuItem *save_menuitem; + GtkImageMenuItem *bookmark_menuitem; + GtkImageMenuItem *copy_menuitem; +}; + +/** + * Create main menu bar. + */ struct nsgtk_bar_submenu *nsgtk_menu_bar_create(GtkMenuShell *menubar, GtkAccelGroup *group); -struct nsgtk_popup_submenu *nsgtk_menu_popup_create(GtkAccelGroup *group); + +/** + * Generate right click menu menu. + * + */ +struct nsgtk_popup_menu *nsgtk_popup_menu_create(GtkAccelGroup *group); + +/** + * Generate context sensitive popup menu for link. + * + */ +struct nsgtk_link_menu *nsgtk_link_menu_create(GtkAccelGroup *group); + #endif diff --git a/gtk/scaffolding.c b/gtk/scaffolding.c index ee2d46227..d6cb58b27 100644 --- a/gtk/scaffolding.c +++ b/gtk/scaffolding.c @@ -107,7 +107,10 @@ struct gtk_scaffolding { struct nsgtk_bar_submenu *menu_bar; /** right click popup menu hierarchy */ - struct nsgtk_popup_submenu *menu_popup; + struct nsgtk_popup_menu *menu_popup; + + /** link popup menu */ + struct nsgtk_link_menu *link_menu; GtkToolbar *tool_bar; struct nsgtk_button_connect *buttons[PLACEHOLDER_BUTTON]; @@ -147,7 +150,7 @@ static struct contextual_content current_menu_ctx; /** * Helper to hide popup menu entries by grouping */ -static void popup_menu_hide(struct nsgtk_popup_submenu *menu, bool submenu, +static void popup_menu_hide(struct nsgtk_popup_menu *menu, bool submenu, bool link, bool nav, bool cnp, bool custom) { if (submenu){ @@ -190,7 +193,7 @@ static void popup_menu_hide(struct nsgtk_popup_submenu *menu, bool submenu, /** * Helper to show popup menu entries by grouping */ -static void popup_menu_show(struct nsgtk_popup_submenu *menu, bool submenu, +static void popup_menu_show(struct nsgtk_popup_menu *menu, bool submenu, bool link, bool nav, bool cnp, bool custom) { if (submenu){ @@ -1023,6 +1026,44 @@ MENUHANDLER(link_opentab) return TRUE; } +/** + * Handler for bookmarking a link. attached to the popup menu. + */ +MENUHANDLER(link_bookmark) +{ + nsurl *url; + nserror error; + + if (current_menu_ctx.link_url == NULL) + return FALSE; + + error = nsurl_create(current_menu_ctx.link_url, &url); + if (error == NSERROR_OK) { + hotlist_add_url(url); + nsurl_unref(url); + } + if (error != NSERROR_OK) { + warn_user(messages_get_errorcode(error), 0); + } + + return TRUE; +} + +/** + * Handler for copying a link. attached to the popup menu. + */ +MENUHANDLER(link_copy) +{ + GtkClipboard *clipboard; + + if (current_menu_ctx.link_url == NULL) + return FALSE; + + clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); + gtk_clipboard_set_text(clipboard, current_menu_ctx.link_url, -1); + return TRUE; +} + MULTIHANDLER(cut) { @@ -1755,23 +1796,21 @@ static void nsgtk_attach_menu_handlers(struct gtk_scaffolding *g) * Create and connect handlers to popup menu. * * \param g scaffoliding to attach popup menu to. - * \return true on success or false on error. + * \return menu structure on sucess or NULL on error. */ -static bool nsgtk_new_scaffolding_popup(struct gtk_scaffolding *g, GtkAccelGroup *group) +static struct nsgtk_popup_menu * +nsgtk_new_scaffolding_popup(struct gtk_scaffolding *g, GtkAccelGroup *group) { - struct nsgtk_popup_submenu *nmenu; - - nmenu = nsgtk_menu_popup_create(group); + struct nsgtk_popup_menu *nmenu; - if (nmenu == NULL) - return false; + nmenu = nsgtk_popup_menu_create(group); -/** Connect a GTK signal handler to a widget */ -#define SIG_CONNECT(obj, sig, callback, ptr) \ - g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr)) + if (nmenu == NULL) { + return NULL; + } - SIG_CONNECT(nmenu->popup_menu, "hide", - nsgtk_window_popup_menu_hidden, g); + g_signal_connect(nmenu->popup_menu, "hide", + G_CALLBACK(nsgtk_window_popup_menu_hidden), g); g_signal_connect(nmenu->savelink_menuitem, "activate", G_CALLBACK(nsgtk_on_savelink_activate_menu), g); @@ -1797,9 +1836,42 @@ static bool nsgtk_new_scaffolding_popup(struct gtk_scaffolding *g, GtkAccelGroup /* set initial popup menu visibility */ popup_menu_hide(nmenu, true, false, false, false, true); - g->menu_popup = nmenu; + return nmenu; +} - return true; +/** + * Create and connect handlers to link popup menu. + * + * \param g scaffoliding to attach popup menu to. + * \return true on success or false on error. + */ +static struct nsgtk_link_menu * +nsgtk_new_scaffolding_link_popup(struct gtk_scaffolding *g, GtkAccelGroup *group) +{ + struct nsgtk_link_menu *nmenu; + + nmenu = nsgtk_link_menu_create(group); + + if (nmenu == NULL) { + return NULL; + } + + g_signal_connect(nmenu->save_menuitem, "activate", + G_CALLBACK(nsgtk_on_savelink_activate_menu), g); + + g_signal_connect(nmenu->opentab_menuitem, "activate", + G_CALLBACK(nsgtk_on_link_opentab_activate_menu), g); + + g_signal_connect(nmenu->openwin_menuitem, "activate", + G_CALLBACK(nsgtk_on_link_openwin_activate_menu), g); + + g_signal_connect(nmenu->bookmark_menuitem, "activate", + G_CALLBACK(nsgtk_on_link_bookmark_activate_menu), g); + + g_signal_connect(nmenu->copy_menuitem, "activate", + G_CALLBACK(nsgtk_on_link_copy_activate_menu), g); + + return nmenu; } nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) @@ -2061,7 +2133,9 @@ nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel) nsgtk_window_tool_bar_clicked, g); /* create popup menu */ - nsgtk_new_scaffolding_popup(g, group); + g->menu_popup = nsgtk_new_scaffolding_popup(g, group); + + g->link_menu = nsgtk_new_scaffolding_link_popup(g, group); /* set up the menu signal handlers */ nsgtk_scaffolding_toolbar_init(g); @@ -2509,53 +2583,53 @@ void nsgtk_scaffolding_initial_sensitivity(struct gtk_scaffolding *g) gtk_widget_set_sensitive(GTK_WIDGET(g->menu_bar->view_submenu->images_menuitem), FALSE); } -/** - * Checks if a location is over a link. - * - * Side effect of this function is to set the global current_menu_ctx - */ -static bool is_menu_over_link(struct gtk_scaffolding *g, gdouble x, gdouble y) +/* exported interface documented in gtk/scaffolding.h */ +void nsgtk_scaffolding_context_menu(struct gtk_scaffolding *g, + gdouble x, + gdouble y) { + GtkMenu *gtkmenu; + + /* update the global current_menu_ctx */ browser_window_get_contextual_content( nsgtk_get_browser_window(g->top_level), x, y, ¤t_menu_ctx); - if (current_menu_ctx.link_url == NULL) - return false; - return true; -} + if (current_menu_ctx.link_url != NULL) { + /* menu is opening over a link */ + gtkmenu = g->link_menu->link_menu; -void nsgtk_scaffolding_popup_menu(struct gtk_scaffolding *g, gdouble x, gdouble y) -{ - if (is_menu_over_link(g, x, y)) { popup_menu_show(g->menu_popup, false, true, false, false, false); + } else { - popup_menu_hide(g->menu_popup, false, true, false, false, false); - } + gtkmenu = g->menu_popup->popup_menu; - nsgtk_scaffolding_update_edit_actions_sensitivity(g); + popup_menu_hide(g->menu_popup, false, true, false, false, false); + + nsgtk_scaffolding_update_edit_actions_sensitivity(g); - if (!(g->buttons[COPY_BUTTON]->sensitivity)) - gtk_widget_hide(GTK_WIDGET(g->menu_popup->copy_menuitem)); - else - gtk_widget_show(GTK_WIDGET(g->menu_popup->copy_menuitem)); + if (!(g->buttons[COPY_BUTTON]->sensitivity)) + gtk_widget_hide(GTK_WIDGET(g->menu_popup->copy_menuitem)); + else + gtk_widget_show(GTK_WIDGET(g->menu_popup->copy_menuitem)); - if (!(g->buttons[CUT_BUTTON]->sensitivity)) - gtk_widget_hide(GTK_WIDGET(g->menu_popup->cut_menuitem)); - else - gtk_widget_show(GTK_WIDGET(g->menu_popup->cut_menuitem)); + if (!(g->buttons[CUT_BUTTON]->sensitivity)) + gtk_widget_hide(GTK_WIDGET(g->menu_popup->cut_menuitem)); + else + gtk_widget_show(GTK_WIDGET(g->menu_popup->cut_menuitem)); - if (!(g->buttons[PASTE_BUTTON]->sensitivity)) - gtk_widget_hide(GTK_WIDGET(g->menu_popup->paste_menuitem)); - else - gtk_widget_show(GTK_WIDGET(g->menu_popup->paste_menuitem)); + if (!(g->buttons[PASTE_BUTTON]->sensitivity)) + gtk_widget_hide(GTK_WIDGET(g->menu_popup->paste_menuitem)); + else + gtk_widget_show(GTK_WIDGET(g->menu_popup->paste_menuitem)); - /* hide customize */ - popup_menu_hide(g->menu_popup, false, false, false, false, true); + /* hide customize */ + popup_menu_hide(g->menu_popup, false, false, false, false, true); + } - gtk_menu_popup(g->menu_popup->popup_menu, NULL, NULL, NULL, NULL, 0, - gtk_get_current_event_time()); + gtk_menu_popup(gtkmenu, NULL, NULL, NULL, NULL, 0, + gtk_get_current_event_time()); } /** diff --git a/gtk/scaffolding.h b/gtk/scaffolding.h index f03a3402a..44f816037 100644 --- a/gtk/scaffolding.h +++ b/gtk/scaffolding.h @@ -166,8 +166,15 @@ void nsgtk_scaffolding_destroy(nsgtk_scaffolding *g); void nsgtk_scaffolding_set_sensitivity(struct gtk_scaffolding *g); void nsgtk_scaffolding_initial_sensitivity(struct gtk_scaffolding *g); -void nsgtk_scaffolding_popup_menu(struct gtk_scaffolding *g, gdouble x, - gdouble y); + +/** + * Open a context sensitive menu. + * + * \param g the scaffolding containing the browser window. + * \param x The x co-ordinate. + * \param y The y co-ordinate. + */ +void nsgtk_scaffolding_context_menu(struct gtk_scaffolding *g, gdouble x, gdouble y); void nsgtk_scaffolding_toolbar_size_allocate(GtkWidget *widget, GtkAllocation *alloc, gpointer data); void nsgtk_scaffolding_set_icon(struct gui_window *gw); diff --git a/gtk/window.c b/gtk/window.c index 9c4b668b9..dc8cbf935 100644 --- a/gtk/window.c +++ b/gtk/window.c @@ -338,8 +338,9 @@ static gboolean nsgtk_window_button_press_event(GtkWidget *widget, case 3: /* Right button, usually. Action button, context menu. */ browser_window_remove_caret(g->bw, true); - nsgtk_scaffolding_popup_menu(g->scaffold, g->mouse.pressed_x, - g->mouse.pressed_y); + nsgtk_scaffolding_context_menu(g->scaffold, + g->mouse.pressed_x, + g->mouse.pressed_y); return TRUE; default: diff --git a/resources/FatMessages b/resources/FatMessages index ccc6d2097..77251c9cb 100644 --- a/resources/FatMessages +++ b/resources/FatMessages @@ -2222,26 +2222,38 @@ fr.gtk.gtkAbout:_A propos... it.gtk.gtkAbout:_Informazioni nl.gtk.gtkAbout:_About + en.gtk.gtkCustomize:Customise… de.gtk.gtkCustomize:Customise.. fr.gtk.gtkCustomize:Customise… it.gtk.gtkCustomize:Personalizza... nl.gtk.gtkCustomize:Customise… -en.gtk.gtkOpentab:Open Link in _New Tab -de.gtk.gtkOpentab:Link in _neuem Tab öffnen -fr.gtk.gtkOpentab:Open Link in _New Tab -it.gtk.gtkOpentab:Apri in una _nuova scheda -nl.gtk.gtkOpentab:Open Link in _New Tab -en.gtk.gtkOpenwin:Open Link in New Window -de.gtk.gtkOpenwin:Link in neuem Fenster öffnen -fr.gtk.gtkOpenwin:Open Link in New Window -it.gtk.gtkOpenwin:Apri in una nuova finestra -nl.gtk.gtkOpenwin:Open Link in New Window -en.gtk.gtkSavelink:Save Link -de.gtk.gtkSavelink:Link speichern.. -fr.gtk.gtkSavelink:Save Link -it.gtk.gtkSavelink:Salva Link -nl.gtk.gtkSavelink:Save Link +en.gtk.gtkOpentab:Open Link in New _Tab +de.gtk.gtkOpentab:Link in neuem _Tab öffnen +fr.gtk.gtkOpentab:Ouvrir dans un nouvel _Onglet +it.gtk.gtkOpentab:Apri in una nuova _scheda +nl.gtk.gtkOpentab:Open Link in New _Tab +en.gtk.gtkOpenwin:Open Link in New _Window +de.gtk.gtkOpenwin:Link in neuem _Fenster öffnen +fr.gtk.gtkOpenwin:Ouvrir dans une nouvelle _Fenêtre +it.gtk.gtkOpenwin:Apri in una nuova _finestra +nl.gtk.gtkOpenwin:Open Link in New _Window +en.gtk.gtkSavelink:Save Lin_k +de.gtk.gtkSavelink:Lin_k speichern.. +fr.gtk.gtkSavelink:Save Lin_k +it.gtk.gtkSavelink:Salva Lin_k +nl.gtk.gtkSavelink:Save Lin_k +en.gtk.gtkBookmarklink:Bookmark _Link +de.gtk.gtkBookmarklink:Bookmark _Link +fr.gtk.gtkBookmarklink:Bookmark _Link +it.gtk.gtkBookmarklink:Bookmark _Link +nl.gtk.gtkBookmarklink:Bookmark _Link +en.gtk.gtkCopylink:Copy link loc_ation +de.gtk.gtkCopylink:Copy link loc_ation +fr.gtk.gtkCopylink:Copy link loc_ation +it.gtk.gtkCopylink:Copy link loc_ation +nl.gtk.gtkCopylink:Copy link loc_ation + en.gtk.gtkToolBarTitle:Toolbar custom button store de.gtk.gtkToolBarTitle:Benutzerdefinierter Ort für Toolbar-Icons diff --git a/utils/types.h b/utils/types.h index e3f2e838c..035ff76cb 100644 --- a/utils/types.h +++ b/utils/types.h @@ -49,7 +49,11 @@ struct redraw_context { }; -/* Content located at a specific spatial location */ +/** + * Content located at a specific spatial location. + * + * \todo This structure should contain a nsurl not a string. + */ struct contextual_content { const char *link_url; struct hlcache_handle *object; -- cgit v1.2.3 From 89a02c3a8fa8b386224e531118c82a6a76332229 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Tue, 8 Jul 2014 13:25:54 +0100 Subject: when walking the css imports ensure the content is present before dereferencing it css import entries may not have a valid content if the resource failed to load or was unsuitable in some otehr way. The save_complete iterator did not cope with this. fixes #2166 --- css/css.c | 4 ++-- desktop/save_complete.c | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/css/css.c b/css/css.c index 94c0be3be..9dc6e8cba 100644 --- a/css/css.c +++ b/css/css.c @@ -575,14 +575,14 @@ css_error nscss_handle_import(void *pw, css_stylesheet *parent, /* Create content */ c->imports[c->import_count].media = media; - /* TODO: Why aren't we getting a relative url part, to join? */ + /** \todo Why aren't we getting a relative url part, to join? */ nerror = nsurl_create(lwc_string_data(url), &ns_url); if (nerror != NSERROR_OK) { free(ctx); return CSS_NOMEM; } - /* TODO: Constructing nsurl for referer here is silly, avoid */ + /** \todo Constructing nsurl for referer here is silly, avoid */ nerror = nsurl_create(referer, &ns_ref); if (nerror != NSERROR_OK) { nsurl_unref(ns_url); diff --git a/desktop/save_complete.c b/desktop/save_complete.c index f6d3e7664..71187eb10 100644 --- a/desktop/save_complete.c +++ b/desktop/save_complete.c @@ -355,8 +355,11 @@ static bool save_complete_save_imported_sheets(save_complete_ctx *ctx, uint32_t i; for (i = 0; i < import_count; i++) { - if (save_complete_save_stylesheet(ctx, imports[i].c) == false) - return false; + /* treat a valid content as a stylesheet to save */ + if ((imports[i].c != NULL) && + (save_complete_save_stylesheet(ctx, imports[i].c) == false)) { + return false; + } } return true; -- cgit v1.2.3 From 6ae1841b5a65b8f86f361924b909dbb6217f84a1 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Tue, 8 Jul 2014 15:37:23 +0100 Subject: stop using invalid gdkpixbuf --- gtk/scaffolding.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gtk/scaffolding.c b/gtk/scaffolding.c index d6cb58b27..5b05fccdf 100644 --- a/gtk/scaffolding.c +++ b/gtk/scaffolding.c @@ -2309,6 +2309,10 @@ gui_search_web_provider_update(const char *provider_name, nsgtk_entry_set_icon_from_pixbuf(current->webSearchEntry, GTK_ENTRY_ICON_PRIMARY, srch_pixbuf); + } else { + nsgtk_entry_set_icon_from_stock(current->webSearchEntry, + GTK_ENTRY_ICON_PRIMARY, + "gtk-find"); } /* set search entry text */ @@ -2321,7 +2325,9 @@ gui_search_web_provider_update(const char *provider_name, free(searchcontent); - g_object_unref(srch_pixbuf); + if (srch_pixbuf != NULL) { + g_object_unref(srch_pixbuf); + } return NSERROR_OK; } -- cgit v1.2.3 From 0694f345daa509546d79f31be285987f43cc5be3 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Tue, 8 Jul 2014 15:57:48 +0100 Subject: fix leak on error path (coverity 1224429) --- content/fetch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/content/fetch.c b/content/fetch.c index 2160204ef..6948fcbea 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -443,6 +443,7 @@ fetch_start(nsurl *url, fetch->fetcherd = get_fetcher_for_scheme(scheme); if (fetch->fetcherd == -1) { lwc_string_unref(scheme); + free(fetch); return NULL; } -- cgit v1.2.3