summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2014-07-08 19:23:55 +0100
committerMichael Drake <tlsa@netsurf-browser.org>2014-07-08 19:23:55 +0100
commit3c818abaea53b61c15393d1aeaefd1eba52f4d5c (patch)
tree13704d81d7041a4cd4bc44414baf0de6045021db
parente7e914b6242a17abebb84ecfc5f0b1facaac4e94 (diff)
parent0694f345daa509546d79f31be285987f43cc5be3 (diff)
downloadnetsurf-3c818abaea53b61c15393d1aeaefd1eba52f4d5c.tar.gz
netsurf-3c818abaea53b61c15393d1aeaefd1eba52f4d5c.tar.bz2
Merge branch 'master' of git://git.netsurf-browser.org/netsurf
-rw-r--r--Docs/source-object-backing-store28
-rw-r--r--amiga/Makefile.target2
-rw-r--r--amiga/bitmap.c4
-rwxr-xr-xamiga/bitmap.h1
-rw-r--r--amiga/gui.c180
-rwxr-xr-xamiga/gui.h3
-rwxr-xr-xamiga/launch.c1
-rw-r--r--amiga/menu.c115
-rwxr-xr-xamiga/misc.c6
-rw-r--r--amiga/options.h2
-rwxr-xr-xamiga/schedule.c171
-rw-r--r--amiga/theme.c103
-rw-r--r--amiga/theme.h4
-rw-r--r--amiga/tree.c2
-rw-r--r--atari/deskmenu.c8
-rw-r--r--atari/gui.c36
-rwxr-xr-xatari/gui.h3
-rwxr-xr-xatari/misc.c11
-rwxr-xr-xatari/rootwin.c2
-rwxr-xr-xatari/schedule.h15
-rw-r--r--atari/toolbar.h3
-rw-r--r--beos/Makefile.target2
-rw-r--r--beos/fetch_rsrc.cpp21
-rw-r--r--beos/gui.cpp100
-rw-r--r--beos/plotters.cpp1
-rw-r--r--beos/scaffolding.cpp9
-rw-r--r--beos/window.cpp54
-rw-r--r--beos/window.h1
-rw-r--r--cocoa/BrowserView.m29
-rw-r--r--cocoa/BrowserWindowController.m1
-rw-r--r--cocoa/NetSurfAppDelegate.m1
-rw-r--r--cocoa/gui.m19
-rw-r--r--content/fetch.c537
-rw-r--r--content/fetch.h65
-rw-r--r--content/fetchers.h141
-rw-r--r--content/fetchers/about.c25
-rw-r--r--content/fetchers/about.h2
-rw-r--r--content/fetchers/curl.c38
-rw-r--r--content/fetchers/data.c25
-rw-r--r--content/fetchers/data.h2
-rw-r--r--content/fetchers/file.c25
-rw-r--r--content/fetchers/file.h2
-rw-r--r--content/fetchers/resource.c35
-rw-r--r--content/fetchers/resource.h2
-rw-r--r--content/fs_backing_store.c125
-rw-r--r--content/hlcache.c9
-rw-r--r--content/hlcache.h8
-rw-r--r--content/llcache.c8
-rw-r--r--content/llcache.h7
-rw-r--r--css/css.c4
-rw-r--r--desktop/browser.c63
-rw-r--r--desktop/browser.h52
-rw-r--r--desktop/browser_private.h4
-rw-r--r--desktop/gui.h15
-rw-r--r--desktop/gui_factory.c3
-rw-r--r--desktop/netsurf.c11
-rw-r--r--desktop/save_complete.c7
-rw-r--r--framebuffer/fbtk.h5
-rw-r--r--framebuffer/font_internal.c6
-rw-r--r--framebuffer/gui.c14
-rw-r--r--gtk/gui.c68
-rw-r--r--gtk/menu.c86
-rw-r--r--gtk/menu.h30
-rw-r--r--gtk/scaffolding.c187
-rw-r--r--gtk/scaffolding.h11
-rw-r--r--gtk/window.c45
-rw-r--r--gtk/window.h1
-rw-r--r--monkey/browser.c19
-rw-r--r--monkey/poll.c79
-rw-r--r--render/form.h3
-rw-r--r--render/html.h7
-rw-r--r--render/html_css_fetcher.c21
-rw-r--r--resources/FatMessages42
-rw-r--r--riscos/dialog.c1
-rw-r--r--riscos/gui.c23
-rw-r--r--riscos/gui.h1
-rw-r--r--riscos/history.c5
-rw-r--r--riscos/iconbar.c1
-rw-r--r--riscos/window.c91
-rw-r--r--riscos/window.h6
-rw-r--r--utils/config.h3
-rw-r--r--utils/file.h2
-rw-r--r--utils/types.h6
-rw-r--r--windows/findfile.c2
-rw-r--r--windows/gui.c17
-rw-r--r--windows/main.c1
86 files changed, 1674 insertions, 1262 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/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/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 <libraries/Picasso96.h>
#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..9bf049a15 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"
@@ -171,9 +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;
STRPTR temp_homepage_url = NULL;
@@ -181,6 +179,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";
@@ -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;
@@ -2115,7 +2120,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)
{
@@ -2127,12 +2132,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;
+ ami_schedule(0, ami_gui_refresh_favicon, gwin);
+ browser_window_schedule_reformat(gwin->bw);
ami_schedule_redraw(gwin, true);
break;
}
@@ -2201,36 +2205,8 @@ void ami_handle_msg(void)
// ReplyMsg((struct Message *)message);
}
- 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);
- }
} 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);
- 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)
@@ -2461,15 +2437,39 @@ 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. */
+ 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;
+ signal = Wait(signalmask);
+ }
if(signal & winsignal)
ami_handle_msg();
@@ -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();
}
@@ -2561,8 +2552,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);
@@ -2586,7 +2577,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,
@@ -2594,8 +2584,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);
}
}
@@ -2769,9 +2759,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 +2806,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);
@@ -2924,7 +2948,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);
}
}
@@ -2966,7 +2989,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);
}
@@ -2995,7 +3017,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;
@@ -3012,6 +3037,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);
}
@@ -3075,7 +3101,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);
}
}
@@ -3107,6 +3132,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;
@@ -3229,6 +3259,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;
}
@@ -3751,7 +3782,7 @@ gui_window_create(struct browser_window *bw,
if(locked_screen) UnlockPubScreen(NULL,scrn);
- refresh_search_ico = TRUE;
+ ami_schedule(0, ami_gui_search_ico_refresh, NULL);
ScreenToFront(scrn);
@@ -4001,7 +4032,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);
}
@@ -4030,7 +4061,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;
}
@@ -4261,6 +4291,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;
@@ -4283,13 +4328,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))
@@ -4648,7 +4686,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;
}
@@ -4708,7 +4746,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;
}
@@ -5030,6 +5069,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,
@@ -5100,6 +5140,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");
@@ -5127,8 +5169,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..c106455d1 100755
--- a/amiga/gui.h
+++ b/amiga/gui.h
@@ -162,11 +162,12 @@ 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);
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/launch.c b/amiga/launch.c
index 1405d6a71..d3c9ff11e 100755
--- a/amiga/launch.c
+++ b/amiga/launch.c
@@ -31,6 +31,7 @@
#include <proto/openurl.h>
#include "utils/nsoption.h"
+#include "utils/nsurl.h"
#include "utils/url.h"
struct Library *OpenURLBase = NULL;
diff --git a/amiga/menu.c b/amiga/menu.c
index 43c8c188b..70028af68 100644
--- a/amiga/menu.c
+++ b/amiga/menu.c
@@ -35,8 +35,6 @@
#include <images/label.h>
#include <proto/bitmap.h>
#include <images/bitmap.h>
-#include <proto/glyph.h>
-#include <images/glyph.h>
#include <reaction/reaction_macros.h>
@@ -358,13 +356,34 @@ 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);
-
+ int space_width = TextLength(rp, " ", 1);
+
if(menu_glyphs_loaded == false)
ami_menu_load_glyphs(dri);
@@ -373,18 +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]));
- 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;
}
@@ -399,32 +410,75 @@ 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,
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_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 -= menu_glyph_width[NSA_GLYPH_SUBMENU];
+
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);
+
+ 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,
LABEL_DisposeImage, TRUE,
LABEL_Image, icon,
+ LABEL_Text, " ",
LABEL_Text, gwin->menulab[i],
LABEL_DisposeImage, TRUE,
+ LABEL_Image, blank_space,
+ LABEL_DisposeImage, TRUE,
LABEL_Image, submenuarrow,
LabelEnd;
@@ -478,14 +532,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);
}
@@ -551,7 +597,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 +616,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 +627,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;
}
@@ -844,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/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/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/schedule.c b/amiga/schedule.c
index 9aa74881f..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;
@@ -54,48 +62,112 @@ static void ami_remove_timer_event(struct nscallback *nscb)
}
/**
- * Unschedule a callback.
+ * 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
*
- * All scheduled callbacks matching both callback and p are removed.
+ * A scheduled callback matching both callback and p is returned, or NULL if none present.
*/
-static nserror schedule_remove(void (*callback)(void *p), void *p)
+static struct nscallback *ami_schedule_locate(void (*callback)(void *p), void *p, bool remove)
{
PblIterator *iterator;
struct nscallback *nscb;
- bool restoreheap = false;
-
- /* check there is something on the list to remove */
- if (schedule_list == NULL)
- {
- return NSERROR_OK;
- }
+ bool found_cb = false;
- if(pblHeapIsEmpty(schedule_list))
- {
- return NSERROR_OK;
- }
+ /* 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))
- {
- ami_remove_timer_event(nscb);
- pblIteratorRemove(iterator);
- FreeVec(nscb);
- restoreheap = true;
+ while ((nscb = pblIteratorNext(iterator)) != -1) {
+ if ((nscb->callback == callback) && (nscb->p == p)) {
+ if (remove == true) pblIteratorRemove(iterator);
+ found_cb = true;
+ break;
}
};
pblIteratorFree(iterator);
- if(restoreheap)
- {
+ if (found_cb == true) return nscb;
+ else return NULL;
+}
+
+/**
+ * Reschedule a callback.
+ *
+ * \param nscb callback
+ * \param t time in ms
+ *
+ * The nscallback will be rescheduled for t ms.
+ */
+
+static nserror ami_schedule_reschedule(struct nscallback *nscb, int t)
+{
+ 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;
+}
+
+/**
+ * Unschedule a callback.
+ *
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * All scheduled callbacks matching both callback and p are removed.
+ */
+
+static nserror schedule_remove(void (*callback)(void *p), void *p)
+{
+ PblIterator *iterator;
+ struct nscallback *nscb;
+
+ nscb = ami_schedule_locate(callback, p, true);
+
+ if(nscb != NULL) {
+ ami_schedule_remove_timer_event(nscb);
+ FreeVec(nscb);
pblHeapConstruct(schedule_list);
}
@@ -113,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);
};
@@ -155,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);
@@ -200,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);
@@ -214,41 +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(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(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;
+ if(!nscb) return NSERROR_NOMEM;
- 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;
@@ -257,3 +303,4 @@ nserror ami_schedule(int t, void (*callback)(void *p), void *p)
return NSERROR_OK;
}
+
diff --git a/amiga/theme.c b/amiga/theme.c
index 29c72574b..cc8b55d7f 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;
@@ -157,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);
@@ -423,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);
- }
+ if(g->shared->throbber_frame == 0) g->shared->throbber_frame = 1;
+ ami_throbber_redraw_schedule(throbber_update_interval, g);
}
void gui_window_stop_throbber(struct gui_window *g)
@@ -452,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],
@@ -462,60 +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;
+ if(g->tab_node && (g->shared->tabs > 1))
+ {
+ GetAttr(CLICKTAB_Current, g->shared->objects[GID_TABS],
+ (ULONG *)&cur_tab);
+ }
- g->throbber_frame++;
- if(g->throbber_frame > (throbber_frames-1))
- g->throbber_frame=1;
+ if((cur_tab == g->tab) || (g->shared->tabs <= 1))
+ {
+ GetAttr(SPACE_AreaBox, g->shared->objects[GID_THROBBER],
+ (ULONG *)&bbox);
- }
+ 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);
}
- GetAttr(SPACE_AreaBox,(Object *)g->objects[GID_THROBBER],(ULONG *)&bbox);
+ if(frame > 0) ami_throbber_redraw_schedule(throbber_update_interval, g);
+}
-/*
- 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,
- TAG_DONE);
+void ami_throbber_redraw_schedule(int t, struct gui_window *g)
+{
+ ami_schedule(t, ami_throbber_update, g);
}
+
diff --git a/amiga/theme.h b/amiga/theme.h
index e81db33dd..c1aca15d7 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 *g);
+void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape);
#endif
+
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)
diff --git a/atari/deskmenu.c b/atari/deskmenu.c
index 8de2e327f..96b2d02ce 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->browser->bw,
+ browser_window_get_scale(input_window->browser->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->browser->bw,
+ browser_window_get_scale(input_window->browser->bw) - 0.25,
+ true);
}
diff --git a/atari/gui.c b/atari/gui.c
index 7cac90c3b..f267b69a8 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;
@@ -202,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);
@@ -344,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)
-{
- return(gw->scale);
-}
-
-void gui_window_set_scale(struct gui_window *gw, float scale)
+static void atari_window_reformat(struct gui_window *gw)
{
- 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)
@@ -403,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);
@@ -421,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,
@@ -1018,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/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/rootwin.c b/atari/rootwin.c
index fde0bd3b5..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(gui_window_get_scale(rootwin->active_gui_window));
+ 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/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/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/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 \
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/beos/gui.cpp b/beos/gui.cpp
index db4374512..cb7effead 100644
--- a/beos/gui.cpp
+++ b/beos/gui.cpp
@@ -37,6 +37,7 @@
#include <FindDirectory.h>
#include <Mime.h>
#include <Path.h>
+#include <PathFinder.h>
#include <Roster.h>
#include <Screen.h>
#include <String.h>
@@ -46,7 +47,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"
@@ -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,20 +295,32 @@ static char *find_resource(char *buf, const char *filename, const char *def)
return buf;
}
- strcpy(t, RESPATH);
- strcat(t, filename);
- realpath(t, buf);
- if (access(buf, R_OK) == 0)
- return buf;
+
+ BPathFinder f((void*)find_resource);
+
+ BPath p;
+ 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);
- 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;
@@ -488,7 +498,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);
@@ -702,60 +715,41 @@ 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);
- 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;
- }
+ // max of all the fds in the set, plus one for select()
+ max_fd = MAX(max_fd, sEventPipe[0]) + 1;
- // 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.
- 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)) {
@@ -767,11 +761,6 @@ static void gui_poll(bool active)
nsbeos_dispatch_event(message);
}
}
-
- schedule_run();
-
- if (browser_reformat_pending)
- nsbeos_window_process_reformats();
}
@@ -990,9 +979,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
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"
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();
}
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/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/cocoa/gui.m b/cocoa/gui.m
index 1cb19a756..8f08fc7fa 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) {
@@ -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 *)gw 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/content/fetch.c b/content/fetch.c
index 4736670ff..6948fcbea 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 <assert.h>
@@ -33,18 +36,12 @@
#include <string.h>
#include <strings.h>
#include <time.h>
-
#include <libwapcaplet/libwapcaplet.h>
+#include <curl/curl.h>
#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 "desktop/gui_factory.h"
#include "utils/corestrings.h"
#include "utils/nsoption.h"
#include "utils/log.h"
@@ -53,27 +50,49 @@
#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(). */
+/** 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
-/** Information about a fetcher for a given scheme. */
+/** The fdset timeout in ms */
+#define FDSET_TIMEOUT 1000
+
+/**
+ * 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,41 +104,51 @@ 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;
}
/**
@@ -128,11 +157,10 @@ static void fetch_unref_fetcher(scheme_fetcher *fetcher)
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 (!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 {
@@ -179,56 +207,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
+}
- while ( all_queued && all_active < nsoption_int(max_fetchers) ) {
- /*LOG(("%d queued, %d fetching", all_queued, all_active));*/
- if (fetch_choose_and_dispatch()) {
+/**
+ * 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 != 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(SCHEDULE_TIME, 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
}
/******************************************************************************
@@ -236,7 +284,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();
@@ -244,84 +292,162 @@ nserror fetch_init(void)
fetch_resource_register();
fetch_about_register();
- fetch_active = false;
-
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)
+{
+ int fetcherd; /* fetcher index */
+ for (fetcherd = 0; fetcherd < MAX_FETCHERS; fetcherd++) {
+ 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[fetcherd].scheme),
+ fetchers[fetcherd].refcount));
+
+ fetchers[fetcherd].refcount = 1;
+ }
+ if (fetchers[fetcherd].refcount == 1) {
+
+ fetch_unref_fetcher(fetcherd);
+ }
+ }
+}
+
+/* exported interface documented in content/fetchers.h */
+nserror
+fetcher_add(lwc_string *scheme, const struct fetcher_operation_table *ops)
{
- 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;
+
+ /* find unused fetcher descriptor */
+ for (fetcherd = 0; fetcherd < MAX_FETCHERS; fetcherd++) {
+ if (fetchers[fetcherd].refcount == 0) {
+ break;
}
- fetch_unref_fetcher(fetchers);
}
+ 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 */
-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)
+nserror fetcher_fdset(fd_set *read_fd_set,
+ fd_set *write_fd_set,
+ fd_set *except_fd_set,
+ int *maxfd_out)
{
- scheme_fetcher *new_fetcher;
- if (!initialiser(scheme))
- return false;
- new_fetcher = malloc(sizeof(scheme_fetcher));
- if (new_fetcher == NULL) {
- finaliser(scheme);
- return false;
+ 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);
+ }
}
- 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;
+
+ 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(FDSET_TIMEOUT, fetcher_poll, NULL);
+ }
+
+ *maxfd_out = maxfd;
+
+ 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);
-#ifdef DEBUG_FETCH_VERBOSE
- LOG(("fetch %p, url '%s'", fetch, nsurl_access(url)));
-#endif
+ /* try and obtain a fetcher for this scheme */
+ fetch->fetcherd = get_fetcher_for_scheme(scheme);
+ if (fetch->fetcherd == -1) {
+ lwc_string_unref(scheme);
+ free(fetch);
+ return NULL;
+ }
+
+ FETCH_LOG(("fetch %p, url '%s'", fetch, nsurl_access(url)));
/* construct a new fetch structure */
fetch->callback = callback;
@@ -334,7 +460,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,121 +503,90 @@ 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;
- }
-
- if (fetch->ops == NULL)
- goto failed;
+ /* these aren't needed past here */
+ lwc_string_unref(scheme);
- /* 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);
+ /* 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) {
- if (fetch->fetcher_handle == NULL)
- goto failed;
+ if (fetch->host != NULL)
+ lwc_string_unref(fetch->host);
- /* Rah, got it, so ref the fetcher. */
- fetch_ref_fetcher(fetch->ops);
+ if (fetch->url != NULL)
+ nsurl_unref(fetch->url);
- /* these aren't needed past here */
- lwc_string_unref(scheme);
+ if (fetch->referer != NULL)
+ nsurl_unref(fetch->referer);
- /* Dump us in the queue and ask the queue to run. */
- RING_INSERT(queue_ring, fetch);
- fetch_dispatch_jobs();
+ free(fetch);
- return fetch;
+ return NULL;
+ }
-failed:
- lwc_string_unref(scheme);
+ /* Rah, got it, so ref the fetcher. */
+ fetch_ref_fetcher(fetch->fetcherd);
- 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);
+ /* Dump new fetch in the queue. */
+ RING_INSERT(queue_ring, fetch);
- free(fetch);
+ /* 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 NULL;
+ return fetch;
}
/* exported interface documented in content/fetch.h */
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
- f->ops->abort_fetch(f->fetcher_handle);
+ 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
- f->ops->free_fetch(f->fetcher_handle);
- fetch_unref_fetcher(f->ops);
+ 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/fetch.h */
-void fetch_poll(void)
-{
- scheme_fetcher *fetcher = fetchers;
- scheme_fetcher *next_fetcher;
-
- 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);
- }
- 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 */
@@ -594,7 +688,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);
@@ -612,12 +706,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) {
@@ -626,15 +716,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
}
@@ -643,9 +733,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/fetch.h b/content/fetch.h
index f20b4f2d2..37539ef2b 100644
--- a/content/fetch.h
+++ b/content/fetch.h
@@ -25,8 +25,6 @@
#include <stdbool.h>
-#include <libwapcaplet/libwapcaplet.h>
-
#include "utils/config.h"
#include "utils/nsurl.h"
@@ -95,18 +93,9 @@ 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.
*
* The function returns immediately. The fetch may be queued for later
@@ -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..d123de986
--- /dev/null
+++ b/content/fetchers.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2014 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file content/fetchers.h
+ * Interface for fetchers factory.
+ */
+
+#ifndef _NETSURF_DESKTOP_FETCHERS_H_
+#define _NETSURF_DESKTOP_FETCHERS_H_
+
+#include "utils/config.h"
+#include <libwapcaplet/libwapcaplet.h>
+
+struct nsurl;
+struct fetch_multipart_data;
+struct fetch;
+
+/**
+ * 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);
+
+
+/**
+ * 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.
+ *
+ * \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.
+ */
+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/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..32b7189db 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]));
}
@@ -504,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;
}
@@ -835,12 +829,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 <libwapcaplet/libwapcaplet.h>
#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/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:
diff --git a/content/hlcache.c b/content/hlcache.c
index e7c4cd84d..0d7996524 100644
--- a/content/hlcache.c
+++ b/content/hlcache.c
@@ -622,15 +622,6 @@ void hlcache_finalise(void)
}
/* 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,
hlcache_handle_callback cb, void *pw,
diff --git a/content/hlcache.h b/content/hlcache.h
index 746b3c866..e0bf4161d 100644
--- a/content/hlcache.h
+++ b/content/hlcache.h
@@ -94,14 +94,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
*
* \param url URL of the object to retrieve handle for
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
@@ -239,13 +239,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.
*
* No guarantees are made as to whether or not cleanups will take
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/browser.c b/desktop/browser.c
index 6e3ed9718..684035a0a 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.
*
@@ -784,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)
@@ -795,9 +801,7 @@ 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;
bw->scroll_x = NULL;
bw->scroll_y = NULL;
@@ -1623,7 +1627,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. */
@@ -1956,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);
@@ -1971,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)
@@ -2362,6 +2383,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 +2444,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);
}
}
@@ -2425,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)
@@ -2447,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 ca99a5d16..6e893fffb 100644
--- a/desktop/browser.h
+++ b/desktop/browser.h
@@ -28,7 +28,7 @@
#include <stdio.h>
#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,
@@ -60,8 +61,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 */
@@ -122,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);
@@ -144,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,
@@ -159,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.
@@ -202,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);
/**
@@ -259,6 +282,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..d2c48d704 100644
--- a/desktop/browser_private.h
+++ b/desktop/browser_private.h
@@ -25,6 +25,7 @@
#define _NETSURF_DESKTOP_BROWSER_PRIVATE_H_
#include <stdbool.h>
+#include <libwapcaplet/libwapcaplet.h>
#include "desktop/browser.h"
@@ -87,9 +88,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/desktop/netsurf.c b/desktop/netsurf.c
index a1bc42b93..579648bae 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;
@@ -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);
- hlcache_poll();
+ guit->browser->poll(false);
}
return 0;
@@ -285,7 +284,7 @@ void netsurf_exit(void)
hlcache_finalise();
LOG(("Closing fetches"));
- fetch_quit();
+ fetcher_quit();
mimesniff_fini();
@@ -310,5 +309,3 @@ void netsurf_exit(void)
LOG(("Exited successfully"));
}
-
-
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;
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/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];
diff --git a/framebuffer/gui.c b/framebuffer/gui.c
index 251326dc2..2a691f7f6 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;
@@ -1762,6 +1758,15 @@ gui_window_remove_caret(struct gui_window *g)
}
}
+static void framebuffer_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,
@@ -1772,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 7de448c0b..bb83721fe 100644
--- a/gtk/gui.c
+++ b/gtk/gui.c
@@ -33,13 +33,13 @@
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <curl/curl.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <glib.h>
#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,53 +485,39 @@ 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;
- schedule_run();
-
- if (browser_reformat_pending)
- 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;
- }
+ 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();
+
gtk_main_iteration_do(block);
for (unsigned int i = 0; i != fd_count; i++) {
@@ -539,10 +525,6 @@ static void nsgtk_poll(bool active)
free(fd_list[i]);
}
- schedule_run();
-
- if (browser_reformat_pending)
- nsgtk_window_process_reformats();
}
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 c2dc0fdc9..5b05fccdf 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;
+}
+
+/**
+ * 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);
- return true;
+ 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);
@@ -2235,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 */
@@ -2247,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;
}
@@ -2444,9 +2524,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 */
@@ -2510,53 +2589,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, &current_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 a3d6d4936..dc8cbf935 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"
@@ -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:
@@ -638,9 +639,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;
}
@@ -730,12 +729,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) {
@@ -854,35 +847,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 +1224,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 414d458bd..e65f2d3e2 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,43 @@ 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;
-
- schedule_run();
- if (browser_reformat_pending)
- 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));
- }
+ 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));
}
}
-
- LOG(("Iterate %sactive %sblocking", active?"":"in", block?"":"non-"));
+
+ schedule_run();
+
+ LOG(("Iterate %sblocking", block?"":"non-"));
if (block) {
fprintf(stdout, "GENERIC POLL BLOCKING\n");
}
@@ -152,9 +137,5 @@ monkey_poll(bool active)
free(fd_list[i]);
}
- schedule_run();
-
- if (browser_reformat_pending)
- monkey_window_process_reformats();
}
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/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,
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/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/gui.c b/riscos/gui.c
index 09f254bb4..3253f796f 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -1852,34 +1852,30 @@ 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) ||
- 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 {
@@ -1900,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/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/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 e1eaf871d..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);
@@ -975,7 +973,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 +992,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 +1005,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);
+ }
}
@@ -1072,13 +1069,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)
@@ -1563,8 +1554,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 +1563,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 +1578,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 +1587,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 +1600,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) {
@@ -2436,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;
@@ -2446,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:
@@ -2484,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;
@@ -3810,13 +3794,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 +3839,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 +3970,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)
@@ -4385,25 +4369,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.
*/
@@ -4860,8 +4836,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 +4846,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;
}
@@ -5180,6 +5156,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/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/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 <winsock2.h>
#define EAFNOSUPPORT WSAEAFNOSUPPORT
int inet_aton(const char *cp, struct in_addr *inp);
#else
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <sys/select.h>
#endif
#define HAVE_INETPTON
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/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;
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)
diff --git a/windows/gui.c b/windows/gui.c
index 21eff0ef4..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);
}
@@ -107,10 +106,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 +123,6 @@ static void win32_poll(bool active)
}
}
-
if (bRet > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
@@ -1826,6 +1820,16 @@ nsws_create_main_class(HINSTANCE hinstance) {
}
/**
+ * 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.
*
* If a string is allocated it must be freed by the caller.
@@ -2092,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,
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"