summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--!NetSurf/!Sprites22,ff9bin18840 -> 18728 bytes
-rwxr-xr-x!NetSurf/5Sprites22,ff9bin40912 -> 40800 bytes
-rw-r--r--!NetSurf/Resources/de/Messages12
-rwxr-xr-x!NetSurf/Resources/de/Templates,fecbin18687 -> 18840 bytes
-rw-r--r--!NetSurf/Resources/en/Messages12
-rw-r--r--!NetSurf/Resources/en/Templates,fecbin18616 -> 18781 bytes
-rw-r--r--!NetSurf/Resources/fr/Messages14
-rw-r--r--!NetSurf/Resources/fr/Templates,fecbin19029 -> 19194 bytes
-rw-r--r--!NetSurf/Resources/nl/Messages12
-rw-r--r--!NetSurf/Resources/nl/Templates,fecbin18702 -> 18867 bytes
-rw-r--r--content/content.c2
-rw-r--r--content/urldb.c61
-rw-r--r--content/urldb.h5
-rw-r--r--desktop/browser.c1115
-rw-r--r--desktop/browser.h74
-rw-r--r--desktop/gui.h6
-rw-r--r--desktop/history_core.c76
-rw-r--r--desktop/netsurf.c5
-rw-r--r--desktop/options.c5
-rw-r--r--desktop/options.h1
-rw-r--r--render/box.h1
-rw-r--r--render/box_construct.c530
-rw-r--r--render/html.c186
-rw-r--r--render/html.h66
-rw-r--r--riscos/configure/con_content.c14
-rw-r--r--riscos/gui.c34
-rw-r--r--riscos/gui.h6
-rw-r--r--riscos/theme.c5
-rw-r--r--riscos/window.c859
-rw-r--r--utils/filename.c24
-rw-r--r--utils/filename.h1
31 files changed, 2319 insertions, 807 deletions
diff --git a/!NetSurf/!Sprites22,ff9 b/!NetSurf/!Sprites22,ff9
index bdeb46384..5c9d32287 100644
--- a/!NetSurf/!Sprites22,ff9
+++ b/!NetSurf/!Sprites22,ff9
Binary files differ
diff --git a/!NetSurf/5Sprites22,ff9 b/!NetSurf/5Sprites22,ff9
index 3b8ef0936..766471428 100755
--- a/!NetSurf/5Sprites22,ff9
+++ b/!NetSurf/5Sprites22,ff9
Binary files differ
diff --git a/!NetSurf/Resources/de/Messages b/!NetSurf/Resources/de/Messages
index 8e00b308a..430b87b56 100644
--- a/!NetSurf/Resources/de/Messages
+++ b/!NetSurf/Resources/de/Messages
@@ -363,6 +363,11 @@ Encoding1:detected
Encoding2:from <meta>
EncodingUnk:Unknown
+# Misc
+#
+Selecting:Selecting
+FrameDrag:Resizing frames
+
# Errors
# ======
@@ -809,9 +814,10 @@ HelpContentConfig:\Tcontent configuration \w
HelpContentConfig2:This indicates whether NetSurf will atempt to block advertisements on web pages|MIn rare circumstances, this option may cause valid content to be blocked too.
HelpContentConfig3:This indicates whether NetSurf will stop web sites from automatically opening new windows on your desktop.
HelpContentConfig4:This indicates whether NetSurf will allow external plug-ins to handle additional types of content, such as Flash.
-HelpContentConfig5:\Sreset the Content options back to their default values.
-HelpContentConfig6:\Sclose this \w without saving changes.|M\Areturn the cache options to the last saved configuration.
-HelpContentConfig7:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+HelpContentConfig7:This indicates whether NetSurf will allow links to open in new windows.
+HelpContentConfig8:\Sreset the Content options back to their default values.
+HelpContentConfig9:\Sclose this \w without saving changes.|M\Areturn the cache options to the last saved configuration.
+HelpContentConfig10:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
HelpFontConfig:\font configuration \w
HelpFontConfig3:\Tcurrently selected sans-serif font.|MNetSurf will use this font wherever a web page specifies a sans-serif typeface.
diff --git a/!NetSurf/Resources/de/Templates,fec b/!NetSurf/Resources/de/Templates,fec
index 821894164..9e9adcce7 100755
--- a/!NetSurf/Resources/de/Templates,fec
+++ b/!NetSurf/Resources/de/Templates,fec
Binary files differ
diff --git a/!NetSurf/Resources/en/Messages b/!NetSurf/Resources/en/Messages
index 796c93add..b35f6aaed 100644
--- a/!NetSurf/Resources/en/Messages
+++ b/!NetSurf/Resources/en/Messages
@@ -363,6 +363,11 @@ Encoding1:detected
Encoding2:from <meta>
EncodingUnk:Unknown
+# Misc
+#
+Selecting:Selecting
+FrameDrag:Resizing frames
+
# Errors
# ======
@@ -809,9 +814,10 @@ HelpContentConfig:\Tcontent configuration \w
HelpContentConfig2:This indicates whether NetSurf will attempt to block advertisements on web pages|MIn rare circumstances, this option may cause valid content to be blocked too.
HelpContentConfig3:This indicates whether NetSurf will stop web sites from automatically opening new windows on your desktop.
HelpContentConfig4:This indicates whether NetSurf will allow external plug-ins to handle additional types of content, such as Flash.
-HelpContentConfig5:\Sreset the Content options back to their default values.
-HelpContentConfig6:\Sclose this \w without saving changes.|M\Areturn the content options to the last saved configuration.
-HelpContentConfig7:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+HelpContentConfig7:This indicates whether NetSurf will allow links to open in new windows.
+HelpContentConfig8:\Sreset the Content options back to their default values.
+HelpContentConfig9:\Sclose this \w without saving changes.|M\Areturn the content options to the last saved configuration.
+HelpContentConfig10:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
HelpFontConfig:\Tfont configuration \w
HelpFontConfig3:\Tcurrently selected sans-serif font.|MNetSurf will use this font wherever a web page specifies a sans-serif typeface.
diff --git a/!NetSurf/Resources/en/Templates,fec b/!NetSurf/Resources/en/Templates,fec
index 51a7b44ac..a821819cd 100644
--- a/!NetSurf/Resources/en/Templates,fec
+++ b/!NetSurf/Resources/en/Templates,fec
Binary files differ
diff --git a/!NetSurf/Resources/fr/Messages b/!NetSurf/Resources/fr/Messages
index 0b7732a6b..9ba9db628 100644
--- a/!NetSurf/Resources/fr/Messages
+++ b/!NetSurf/Resources/fr/Messages
@@ -363,6 +363,11 @@ Encoding1:détecté
Encoding2:de <meta>
EncodingUnk:Inconnu
+# Misc
+#
+Selecting:Selecting
+FrameDrag:Resizing frames
+
# Errors
# ======
@@ -806,12 +811,13 @@ HelpConnectConfig28:\Sfermer cette fenêtre sans sauvegarder les changements.|M\
HelpConnectConfig29:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
HelpContentConfig:\Tla fenêtre de configuration du Contenu
-HelpContentConfig2:Ceci indique si Netsurf doit essayer de bloquer les pubs sur les pages web.|MEn de rares circonstances, cette option peut également bloquer du contenu valide.
+HelpContentConfig2:Ceci indique si Netsurf doit essayer de bloquer les pubs sur les pages web.|MEn de rares circonstances, cette option peut également bloquer du contenu valide.
HelpContentConfig3:Ceci indique si Netsurf doit empêcher les sites web d'ouvrir automatiquement de nouvelles fenêtres sur votre Bureau.
HelpContentConfig4:Ceci indique si Netsurf doit autoriser les plug-ins externes à manipuler des types de contenu supplémentaires, comme le Flash.
-HelpContentConfig5:\Srevenir aux valeurs par défaut des options du Contenu.
-HelpContentConfig6:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options de Contenu précédemment sauvegardées.
-HelpContentConfig7:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
+HelpContentConfig7:This indicates whether NetSurf will allow links to open in new windows.
+HelpContentConfig8:\Srevenir aux valeurs par défaut des options du Contenu.
+HelpContentConfig9:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options de Contenu précédemment sauvegardées.
+HelpContentConfig10:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
HelpFontConfig:\Tla fenêtre de configuration de Fontes
HelpFontConfig3:\Tla fonte sans-sérif actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu'une page web spécifiera une police sans-sérif.
diff --git a/!NetSurf/Resources/fr/Templates,fec b/!NetSurf/Resources/fr/Templates,fec
index 61d278440..49ca62f20 100644
--- a/!NetSurf/Resources/fr/Templates,fec
+++ b/!NetSurf/Resources/fr/Templates,fec
Binary files differ
diff --git a/!NetSurf/Resources/nl/Messages b/!NetSurf/Resources/nl/Messages
index 8d41c6019..529451fa6 100644
--- a/!NetSurf/Resources/nl/Messages
+++ b/!NetSurf/Resources/nl/Messages
@@ -363,6 +363,11 @@ Encoding1:detected
Encoding2:from <meta>
EncodingUnk:Unknown
+# Misc
+#
+Selecting:Selecting
+FrameDrag:Resizing frames
+
# Errors
# ======
@@ -809,9 +814,10 @@ HelpContentConfig:\Tcontent configuration \w
HelpContentConfig2:This indicates whether NetSurf will atempt to block advertisements on web pages|MIn rare circumstances, this option may cause valid content to be blocked too.
HelpContentConfig3:This indicates whether NetSurf will stop web sites from automatically opening new windows on your desktop.
HelpContentConfig4:This indicates whether NetSurf will allow external plug-ins to handle additional types of content, such as Flash.
-HelpContentConfig5:\Sreset the Content options back to their default values.
-HelpContentConfig6:\Sclose this \w without saving changes.|M\Areturn the cache options to the last saved configuration.
-HelpContentConfig7:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
+HelpContentConfig7:This indicates whether NetSurf will allow links to open in new windows.
+HelpContentConfig8:\Sreset the Content options back to their default values.
+HelpContentConfig9:\Sclose this \w without saving changes.|M\Areturn the cache options to the last saved configuration.
+HelpContentConfig10:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
HelpFontConfig:\font configuration \w
HelpFontConfig3:\Tcurrently selected sans-serif font.|MNetSurf will use this font wherever a web page specifies a sans-serif typeface.
diff --git a/!NetSurf/Resources/nl/Templates,fec b/!NetSurf/Resources/nl/Templates,fec
index 128de698c..6b58eb0e1 100644
--- a/!NetSurf/Resources/nl/Templates,fec
+++ b/!NetSurf/Resources/nl/Templates,fec
Binary files differ
diff --git a/content/content.c b/content/content.c
index 68c90a7f0..6b8d7b9fe 100644
--- a/content/content.c
+++ b/content/content.c
@@ -816,7 +816,6 @@ void content_destroy(struct content *c)
if (c->type < HANDLER_MAP_COUNT && handler_map[c->type].destroy)
handler_map[c->type].destroy(c);
-
talloc_free(c);
}
@@ -855,6 +854,7 @@ void content_quit(void)
while (content_list && progress) {
progress = false;
for (c = content_list; c; c = next) {
+ assert(c->next != c);
next = c->next;
if (c->user_list->next &&
diff --git a/content/urldb.c b/content/urldb.c
index f498f106e..1e51d45db 100644
--- a/content/urldb.c
+++ b/content/urldb.c
@@ -81,6 +81,7 @@
#include <curl/curl.h>
#include "netsurf/image/bitmap.h"
+#include "netsurf/content/content.h"
#include "netsurf/content/urldb.h"
#include "netsurf/desktop/cookies.h"
#include "netsurf/desktop/options.h"
@@ -89,6 +90,7 @@
#include "netsurf/riscos/bitmap.h"
#endif
#include "netsurf/utils/log.h"
+#include "netsurf/utils/filename.h"
#include "netsurf/utils/url.h"
#include "netsurf/utils/utils.h"
@@ -117,6 +119,10 @@ struct auth_data {
* username:password */
};
+struct cache_internal_data {
+ char filename[12]; /**< Cached filename, or first byte 0 for none */
+};
+
struct url_internal_data {
char *title; /**< Resource title */
unsigned int visits; /**< Visit count */
@@ -135,6 +141,7 @@ struct path_data {
struct bitmap *thumb; /**< Thumbnail image of resource */
struct url_internal_data urld; /**< URL data for resource */
+ struct cache_internal_data cache; /**< Cache data for resource */
struct auth_data auth; /**< Authentication data for resource */
struct cookie_internal_data *cookies; /**< Cookies associated with resource */
@@ -3361,6 +3368,60 @@ void urldb_save_cookie_paths(FILE *fp, struct path_data *parent)
}
+/**
+ * Sets the content data associated with a particular URL
+ *
+ * \param url the URL to associate content with
+ * \param content the content to associate
+ * \return true on success, false otherwise
+ */
+bool urldb_set_cache_data(const char *url, const struct content *content) {
+ struct path_data *p;
+ char *filename;
+
+ assert(url && content);
+
+ p = urldb_find_url(url);
+ if (!p)
+ return false;
+
+ /* new filename needed */
+ if (p->cache.filename[0] == 0) {
+ filename = filename_request();
+ if (!filename)
+ return false;
+ sprintf(p->cache.filename, filename);
+ }
+
+ /* todo: save content, set cache data etc */
+ return true;
+}
+
+
+/**
+ * Gets a file:// URL for the cached data associated with a URL
+ *
+ * \param url the URL to get the associated content for
+ * \return a local URL allocated on heap, or NULL
+ */
+char *urldb_get_cache_data(const char *url) {
+ struct path_data *p;
+
+ assert(url);
+
+ p = urldb_find_url(url);
+ if (!p)
+ return NULL;
+
+ /* no file cache */
+ if (p->cache.filename[0] == 0)
+ return NULL;
+
+ /* todo: handle cache expiry etc */
+ return filename_as_url(p->cache.filename);
+}
+
+
#ifdef TEST_URLDB
int option_expire_url = 0;
diff --git a/content/urldb.h b/content/urldb.h
index 20d97ebca..aa8ec7742 100644
--- a/content/urldb.h
+++ b/content/urldb.h
@@ -14,6 +14,7 @@
#include <stdbool.h>
#include <time.h>
+#include "netsurf/content/content.h"
#include "netsurf/content/content_type.h"
typedef enum {
@@ -100,4 +101,8 @@ void urldb_delete_cookie(const char *domain, const char *path, const char *name)
void urldb_load_cookies(const char *filename);
void urldb_save_cookies(const char *filename);
+/* Cache */
+bool urldb_set_cache_data(const char *url, const struct content *content);
+char *urldb_get_cache_data(const char *url);
+
#endif
diff --git a/desktop/browser.c b/desktop/browser.c
index d35ea1120..7efbad534 100644
--- a/desktop/browser.c
+++ b/desktop/browser.c
@@ -1,7 +1,7 @@
/*
* This file is part of NetSurf, http://netsurf.sourceforge.net/
* Licensed under the GNU General Public License,
- * http://www.opensource.org/licenses/gpl-license
+ * http://www.opensource.org/licenses/gpl-license
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
* Copyright 2005 James Bursa <bursa@users.sourceforge.net>
* Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk>
@@ -48,6 +48,8 @@
#include "netsurf/utils/utils.h"
#include "netsurf/utils/utf8.h"
+/** maximum frame resize margin */
+#define FRAME_RESIZE 6
/** browser window which is being redrawn. Valid only during redraw. */
struct browser_window *current_redraw_browser;
@@ -55,10 +57,13 @@ struct browser_window *current_redraw_browser;
/** fake content for <a> being saved as a link */
struct content browser_window_href_content;
-
+static void browser_window_resize_frame(struct browser_window *bw, int x, int y);
+static bool browser_window_resolve_frame_dimension(struct browser_window *bw,
+ struct browser_window *sibling, int x, int y, bool width, bool height);
static void browser_window_callback(content_msg msg, struct content *c,
intptr_t p1, intptr_t p2, union content_msg_data data);
static void browser_window_refresh(void *p);
+static bool browser_window_check_throbber(struct browser_window *bw);
static void browser_window_convert_to_download(struct browser_window *bw);
static void browser_window_start_throbber(struct browser_window *bw);
static void browser_window_stop_throbber(struct browser_window *bw);
@@ -67,8 +72,15 @@ static void browser_window_set_status(struct browser_window *bw,
static void browser_window_set_pointer(struct gui_window *g, gui_pointer_shape shape);
static void download_window_callback(fetch_msg msg, void *p, const void *data,
unsigned long size);
+static void browser_window_destroy_children(struct browser_window *bw);
+static void browser_window_destroy_internal(struct browser_window *bw);
+static struct browser_window *browser_window_find_target(struct browser_window *bw, const char *target);
+static void browser_window_find_target_internal(struct browser_window *bw, const char *target,
+ int depth, struct browser_window *page, int *rdepth, struct browser_window **bw_target);
static void browser_window_mouse_action_html(struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
+static bool browser_window_resize_frames(struct browser_window *bw, browser_mouse_state mouse,
+ int x, int y, gui_pointer_shape *pointer, const char **status, bool *action);
static void browser_window_mouse_action_text(struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
static void browser_window_mouse_track_html(struct browser_window *bw,
@@ -95,7 +107,7 @@ static void browser_window_scroll_box(struct browser_window *bw,
/**
* Create and open a new browser window with the given page.
*
- * \param url URL to start fetching in the new window (copied)
+ * \param url URL to start fetching in the new window (copied)
* \param clone The browser window to clone
* \param referer The referring uri
*/
@@ -107,13 +119,12 @@ struct browser_window *browser_window_create(const char *url, struct browser_win
assert(clone || history_add);
- if ((bw = malloc(sizeof *bw)) == NULL) {
+ if ((bw = calloc(1, sizeof *bw)) == NULL) {
warn_user("NoMemory", 0);
return NULL;
}
- bw->current_content = NULL;
- bw->loading_content = NULL;
+ /* content */
if (!clone)
bw->history = history_create();
else
@@ -122,21 +133,21 @@ struct browser_window *browser_window_create(const char *url, struct browser_win
bw->gesturer = NULL;
else
bw->gesturer = gesturer_clone(clone->gesturer);
+
+ /* window characteristics */
bw->sel = selection_create(bw);
- bw->throbbing = false;
- bw->caret_callback = NULL;
- bw->paste_callback = NULL;
- bw->move_callback = NULL;
- bw->frag_id = NULL;
+ bw->refresh_interval = -1;
bw->drag_type = DRAGGING_NONE;
- bw->scrolling_box = NULL;
- bw->referer = NULL;
- bw->download = false;
+ bw->browser_window_type = BROWSER_WINDOW_NORMAL;
+ bw->scrolling = SCROLLING_YES;
+ bw->border = true;
+ bw->no_resize = true;
+
+ /* gui window */
if ((bw->window = gui_create_browser_window(bw, clone)) == NULL) {
- free(bw);
+ browser_window_destroy(bw);
return NULL;
}
- bw->refresh_interval = -1;
if (url)
browser_window_go(bw, url, referer, history_add);
return bw;
@@ -144,10 +155,544 @@ struct browser_window *browser_window_create(const char *url, struct browser_win
/**
+ * Returns the browser window that is responsible for the child.
+ *
+ * \param bw The browser window to find the owner of
+ * \return the browser window's owner
+ */
+
+struct browser_window *browser_window_owner(struct browser_window *bw) {
+ /* an iframe's parent is just the parent window */
+ if (bw->browser_window_type == BROWSER_WINDOW_IFRAME)
+ return bw->parent;
+
+ /* the parent of a frameset is either a NORMAL window or an IFRAME */
+ while (bw->parent) {
+ switch (bw->browser_window_type) {
+ case BROWSER_WINDOW_NORMAL:
+ case BROWSER_WINDOW_IFRAME:
+ return bw;
+ case BROWSER_WINDOW_FRAME:
+ case BROWSER_WINDOW_FRAMESET:
+ bw = bw->parent;
+ break;
+ }
+ }
+ return bw;
+}
+
+
+/**
+ * Create and open a iframes for a browser window.
+ *
+ * \param bw The browser window to create iframes for
+ * \param iframe The iframes to create
+ */
+
+void browser_window_create_iframes(struct browser_window *bw,
+ struct content_html_iframe *iframe) {
+ struct browser_window *window;
+ struct content_html_iframe *cur;
+ int iframes = 0;
+ int index;
+
+ for (cur = iframe; cur; cur = cur->next)
+ iframes++;
+ bw->iframes = calloc(iframes, sizeof(*bw));
+ if (!bw->iframes)
+ return;
+ bw->iframe_count = iframes;
+
+ index = 0;
+ for (cur = iframe; cur; cur = cur->next) {
+ window = &(bw->iframes[index++]);
+
+ /* content */
+ window->history = history_create();
+ window->sel = selection_create(window);
+ window->refresh_interval = -1;
+
+ /* window characteristics */
+ window->drag_type = DRAGGING_NONE;
+ window->browser_window_type = BROWSER_WINDOW_IFRAME;
+ window->scrolling = cur->scrolling;
+ window->border = cur->border;
+ window->border_colour = cur->border_colour;
+ window->no_resize = true;
+ window->margin_width = cur->margin_width;
+ window->margin_height = cur->margin_height;
+ if (cur->name)
+ window->name = strdup(cur->name);
+
+ /* linking */
+ window->box = cur->box;
+ window->parent = bw;
+
+ /* gui window */
+ window->window = gui_create_browser_window(window, bw);
+ }
+
+ /* calculate dimensions */
+ gui_window_update_extent(bw->window);
+ browser_window_recalculate_iframes(bw);
+
+ index = 0;
+ for (cur = iframe; cur; cur = cur->next) {
+ window = &(bw->iframes[index++]);
+ if (iframe->url)
+ browser_window_go(window, iframe->url, NULL, true);
+ }
+}
+
+
+/**
+ * Recalculate iframe positions following a resize.
+ *
+ * \param bw The browser window to reposition iframes for
+ */
+
+void browser_window_recalculate_iframes(struct browser_window *bw) {
+ struct browser_window *window;
+ struct rect rect;
+ int bw_width, bw_height;
+ int index;
+
+ assert(bw);
+
+ /* update window dimensions */
+ gui_window_get_dimensions(bw->window, &bw_width, &bw_height);
+ if (!bw->parent) {
+ bw->x0 = 0;
+ bw->y0 = 0;
+ bw->x1 = bw_width;
+ bw->y1 = bw_height;
+ }
+
+ for (index = 0; index < bw->iframe_count; index++) {
+ window = &(bw->iframes[index]);
+ box_bounds(window->box, &rect);
+ gui_window_position_frame(window->window, rect.x0, rect.y0,
+ rect.x1, rect.y1);
+ }
+}
+
+
+/**
+ * Create and open aframeset for a browser window.
+ *
+ * \param bw The browser window to create the frameset for
+ * \param iframe The frameset to create
+ */
+
+void browser_window_create_frameset(struct browser_window *bw,
+ struct content_html_frames *frameset) {
+ int row, col, index;
+ struct content_html_frames *frame;
+ struct browser_window *window;
+
+ /* we use a 3 stage approach such that the content is initially formatted to the
+ * correct frameset dimensions */
+ assert(bw && frameset);
+
+ /* create children */
+ assert(bw->children == NULL);
+ assert(frameset->cols + frameset->rows != 0);
+
+ bw->children = calloc((frameset->cols * frameset->rows), sizeof(*bw));
+ if (!bw->children)
+ return;
+ bw->cols = frameset->cols;
+ bw->rows = frameset->rows;
+ for (row = 0; row < bw->rows; row++) {
+ for (col = 0; col < bw->cols; col++) {
+ index = (row * bw->cols) + col;
+ frame = &frameset->children[index];
+ window = &bw->children[index];
+
+ /* content */
+ window->history = history_create();
+ window->sel = selection_create(window);
+ window->refresh_interval = -1;
+
+ /* window characteristics */
+ window->drag_type = DRAGGING_NONE;
+ if (frame->children)
+ window->browser_window_type = BROWSER_WINDOW_FRAMESET;
+ else
+ window->browser_window_type = BROWSER_WINDOW_FRAME;
+ window->scrolling = frame->scrolling;
+ window->border = frame->border;
+ window->border_colour = frame->border_colour;
+ window->no_resize = frame->no_resize;
+ window->frame_width = frame->width;
+ window->frame_height = frame->height;
+ window->margin_width = frame->margin_width;
+ window->margin_height = frame->margin_height;
+ if (frame->name)
+ window->name = strdup(frame->name);
+
+ /* linking */
+ window->parent = bw;
+
+ /* gui window */
+ window->window = gui_create_browser_window(window, bw);
+ if (frame->children)
+ browser_window_create_frameset(window, frame);
+ }
+ }
+
+ /* calculate dimensions */
+ gui_window_update_extent(bw->window);
+ browser_window_recalculate_frameset(bw);
+
+ /* launch content */
+ for (row = 0; row < bw->rows; row++) {
+ for (col = 0; col < bw->cols; col++) {
+ index = (row * bw->cols) + col;
+ frame = &frameset->children[index];
+ window = &bw->children[index];
+
+ if (frame->url)
+ browser_window_go(window, frame->url, NULL, true);
+ }
+ }
+}
+
+
+/**
+ * Recalculate frameset positions following a resize.
+ *
+ * \param bw The browser window to reposition framesets for
+ */
+
+void browser_window_recalculate_frameset(struct browser_window *bw) {
+ int widths[bw->cols][bw->rows];
+ int heights[bw->cols][bw->rows];
+ int bw_width, bw_height;
+ int avail_width, avail_height;
+ int row, row2, col, index;
+ struct browser_window *window;
+ float relative;
+ int size, extent;
+ int x, y;
+
+ assert(bw);
+
+ /* window dimensions */
+ if (!bw->parent) {
+ gui_window_get_dimensions(bw->window, &bw_width, &bw_height);
+ bw->x0 = 0;
+ bw->y0 = 0;
+ bw->x1 = bw_width;
+ bw->y1 = bw_height;
+ } else {
+ bw_width = bw->x1 - bw->x0;
+ bw_height = bw->y1 - bw->y0;
+ }
+ bw_width++;
+ bw_height++;
+
+ /* widths */
+ for (row = 0; row < bw->rows; row++) {
+ avail_width = bw_width;
+ relative = 0;
+ for (col = 0; col < bw->cols; col++) {
+ index = (row * bw->cols) + col;
+ window = &bw->children[index];
+
+ switch (window->frame_width.unit) {
+ case FRAME_DIMENSION_PIXELS:
+ widths[col][row] = window->frame_width.value;
+ break;
+ case FRAME_DIMENSION_PERCENT:
+ widths[col][row] = bw_width * window->frame_width.value / 100;
+ break;
+ case FRAME_DIMENSION_RELATIVE:
+ widths[col][row] = 0;
+ relative += window->frame_width.value;
+ break;
+ }
+ avail_width -= widths[col][row];
+ }
+
+ /* try to distribute remainder to relative values in preference */
+ if ((relative > 0) && (avail_width > 0)) {
+ for (col = 0; col < bw->cols; col++) {
+ index = (row * bw->cols) + col;
+ window = &bw->children[index];
+
+ if (window->frame_width.unit == FRAME_DIMENSION_RELATIVE) {
+ size = avail_width * window->frame_width.value / relative;
+ avail_width -= size;
+ relative -= window->frame_width.value;
+ widths[col][row] += size;
+ }
+ }
+ } else {
+ /* proportionally distribute error */
+ extent = bw_width - avail_width;
+ for (col = 0; col < bw->cols; col++) {
+ index = (row * bw->cols) + col;
+ window = &bw->children[index];
+
+ if (col == bw->cols - 1) {
+ widths[col][row] = bw_width;
+ } else {
+ size = bw_width * widths[col][row] / extent;
+ bw_width -= size;
+ extent -= widths[col][row];
+ widths[col][row] = size;
+ }
+ }
+ }
+ }
+
+ /* heights */
+ for (col = 0; col < bw->cols; col++) {
+ avail_height = bw_height;
+ relative = 0;
+ for (row = 0; row < bw->rows; row++) {
+ index = (row * bw->cols) + col;
+ window = &bw->children[index];
+
+ switch (window->frame_height.unit) {
+ case FRAME_DIMENSION_PIXELS:
+ heights[col][row] = window->frame_height.value;
+ break;
+ case FRAME_DIMENSION_PERCENT:
+ heights[col][row] = bw_height *
+ window->frame_height.value / 100;
+ break;
+ case FRAME_DIMENSION_RELATIVE:
+ heights[col][row] = 0;
+ relative += window->frame_height.value;
+ break;
+ }
+ avail_height -= heights[col][row];
+ }
+
+ if (avail_height == 0)
+ continue;
+
+ /* try to distribute remainder to relative values in preference */
+ if ((relative > 0) && (avail_height > 0)) {
+ for (row = 0; row < bw->rows; row++) {
+ index = (row * bw->cols) + col;
+ window = &bw->children[index];
+
+ if (window->frame_height.unit == FRAME_DIMENSION_RELATIVE) {
+ size = avail_height * window->frame_height.value / relative;
+ avail_height -= size;
+ relative -= window->frame_height.value;
+ heights[col][row] += size;
+ }
+ }
+ } else {
+ /* proportionally distribute error */
+ extent = bw_height - avail_height;
+ for (row = 0; row < bw->rows; row++) {
+ index = (row * bw->cols) + col;
+ window = &bw->children[index];
+
+ if (row == bw->rows - 1) {
+ heights[col][row] = bw_height;
+ } else {
+ size = bw_height * heights[col][row] / extent;
+ bw_height -= size;
+ extent -= heights[col][row];
+ heights[col][row] = size;
+ }
+ }
+ }
+ }
+
+ /* position frames and calculate children */
+ for (row = 0; row < bw->rows; row++) {
+ x = 0;
+ for (col = 0; col < bw->cols; col++) {
+ index = (row * bw->cols) + col;
+ window = &bw->children[index];
+
+ y = 0;
+ for (row2 = 0; row2 < row; row2++)
+ y+= heights[col][row2];
+ gui_window_position_frame(window->window, x, y,
+ x + widths[col][row] - 1,
+ y + heights[col][row] - 1);
+ x += widths[col][row];
+ if (window->children)
+ browser_window_recalculate_frameset(window);
+ }
+ }
+}
+
+
+/**
+ * Resize a browser window that is a frame.
+ *
+ * \param bw The browser window to resize
+ */
+
+void browser_window_resize_frame(struct browser_window *bw, int x, int y) {
+ struct browser_window *parent;
+ struct browser_window *sibling;
+ int col = -1, row = -1, i;
+ bool change = false;
+
+ parent = bw->parent;
+ assert(parent);
+
+ /* get frame location */
+ for (i = 0; i < (parent->cols * parent->rows); i++) {
+ if (&parent->children[i] == bw) {
+ col = i % parent->cols;
+ row = i / parent->cols;
+ }
+ }
+ assert((col >= 0) && (row >= 0));
+
+ sibling = NULL;
+ if (bw->drag_resize_left)
+ sibling = &parent->children[row * parent->cols + (col - 1)];
+ else if (bw->drag_resize_right)
+ sibling = &parent->children[row * parent->cols + (col + 1)];
+ if (sibling)
+ change |= browser_window_resolve_frame_dimension(bw, sibling, x, y, true, false);
+
+ sibling = NULL;
+ if (bw->drag_resize_up)
+ sibling = &parent->children[(row - 1) * parent->cols + col];
+ else if (bw->drag_resize_down)
+ sibling = &parent->children[(row + 1) * parent->cols + col];
+ if (sibling)
+ change |= browser_window_resolve_frame_dimension(bw, sibling, x, y, false, true);
+
+ if (change)
+ browser_window_recalculate_frameset(parent);
+}
+
+
+bool browser_window_resolve_frame_dimension(struct browser_window *bw, struct browser_window *sibling,
+ int x, int y, bool width, bool height) {
+ int bw_dimension, sibling_dimension;
+ int bw_pixels, sibling_pixels;
+ struct frame_dimension *bw_d, *sibling_d;
+ float total_new;
+ int frame_size;
+
+ assert(!(width && height));
+
+ /* extend/shrink the box to the pointer */
+ if (width) {
+ if (bw->drag_resize_left)
+ bw_dimension = bw->x1 - x;
+ else
+ bw_dimension = x - bw->x0;
+ bw_pixels = (bw->x1 - bw->x0);
+ sibling_pixels = (sibling->x1 - sibling->x0);
+ bw_d = &bw->frame_width;
+ sibling_d = &sibling->frame_width;
+ frame_size = bw->parent->x1 - bw->parent->x0;
+ } else {
+ if (bw->drag_resize_up)
+ bw_dimension = bw->y1 - y;
+ else
+ bw_dimension = y - bw->y0;
+ bw_pixels = (bw->y1 - bw->y0);
+ sibling_pixels = (sibling->y1 - sibling->y0);
+ bw_d = &bw->frame_height;
+ sibling_d = &sibling->frame_height;
+ frame_size = bw->parent->y1 - bw->parent->y0;
+ }
+ sibling_dimension = bw_pixels + sibling_pixels - bw_dimension;
+
+ /* check for no change or no frame size*/
+ if ((bw_dimension == bw_pixels) || (frame_size == 0))
+ return false;
+ /* check for both being 0 */
+ total_new = bw_dimension + sibling_dimension;
+ if ((bw_dimension + sibling_dimension) == 0)
+ return false;
+
+ /* our frame dimensions are now known to be:
+ *
+ * <-- frame_size --> [VISIBLE PIXELS]
+ * |<-- bw_pixels -->|<-- sibling_pixels -->| [VISIBLE PIXELS, BEFORE RESIZE]
+ * |<-- bw_d->value-->|<-- sibling_d->value-->| [SPECIFIED UNITS, BEFORE RESIZE]
+ * |<--bw_dimension-->|<--sibling_dimension-->| [VISIBLE PIXELS, AFTER RESIZE]
+ * |<-- total_new -->| [VISIBLE PIXELS, AFTER RESIZE]
+ *
+ * when we resize, we must retain the original unit specification such that any
+ * subsequent resizing of the parent window will recalculate the page as the
+ * author specified.
+ *
+ * if the units of both frames are the same then we can resize the values simply
+ * by updating the values to be a percentage of the original widths.
+ */
+ if (bw_d->unit == sibling_d->unit) {
+ float total_specified = bw_d->value + sibling_d->value;
+ bw_d->value = (total_specified * bw_dimension) / total_new;
+ sibling_d->value = total_specified - bw_d->value;
+ return true;
+ }
+
+ /* if one of the sizes is relative then we don't alter the relative width and
+ * just let it reflow across. the non-relative (pixel/percentage) value can
+ * simply be resolved to the specified width that will result in the required
+ * dimension.
+ */
+ if (bw_d->unit == FRAME_DIMENSION_RELATIVE) {
+ if ((sibling_pixels == 0) && (bw_dimension == 0))
+ return false;
+ if (sibling_d->value == 0)
+ bw_d->value = 1;
+ if (sibling_pixels == 0)
+ sibling_d->value = (sibling_d->value * bw_pixels) / bw_dimension;
+ else
+ sibling_d->value =
+ (sibling_d->value * sibling_dimension) / sibling_pixels;
+
+ /* todo: the availble resize may have changed, update the drag box */
+ return true;
+ } else if (sibling_d->unit == FRAME_DIMENSION_RELATIVE) {
+ if ((bw_pixels == 0) && (sibling_dimension == 0))
+ return false;
+ if (bw_d->value == 0)
+ bw_d->value = 1;
+ if (bw_pixels == 0)
+ bw_d->value = (bw_d->value * sibling_pixels) / sibling_dimension;
+ else
+ bw_d->value = (bw_d->value * bw_dimension) / bw_pixels;
+
+ /* todo: the availble resize may have changed, update the drag box */
+ return true;
+ }
+
+ /* finally we have a pixel/percentage mix. unlike relative values, percentages
+ * can easily be backwards-calculated as they can simply be scaled like pixel
+ * values
+ */
+ if (bw_d->unit == FRAME_DIMENSION_PIXELS) {
+ float total_specified = bw_d->value + frame_size * sibling_d->value / 100;
+ bw_d->value = (total_specified * bw_dimension) / total_new;
+ sibling_d->value = (total_specified - bw_d->value) * 100 / frame_size;
+ return true;
+ } else if (sibling_d->unit == FRAME_DIMENSION_PIXELS) {
+ float total_specified = bw_d->value * frame_size / 100 + sibling_d->value;
+ sibling_d->value = (total_specified * sibling_dimension) / total_new;
+ bw_d->value = (total_specified - sibling_d->value) * 100 / frame_size;
+ return true;
+ }
+ assert(!"Invalid frame dimension unit");
+ return false;
+}
+
+
+/**
* Start fetching a page in a browser window.
*
- * \param bw browser window
- * \param url URL to start fetching (copied)
+ * \param bw browser window
+ * \param url URL to start fetching (copied)
* \param referer the referring uri
*
* Any existing fetches in the window are aborted.
@@ -163,13 +708,13 @@ void browser_window_go(struct browser_window *bw, const char *url,
/**
* Start fetching a page in a browser window, POSTing form data.
*
- * \param bw browser window
- * \param url URL to start fetching (copied)
- * \param post_urlenc url encoded post data, or 0 if none
+ * \param bw browser window
+ * \param url URL to start fetching (copied)
+ * \param post_urlenc url encoded post data, or 0 if none
* \param post_multipart multipart post data, or 0 if none
- * \param history_add add to window history
- * \param referer the referring uri
- * \param download download, rather than render the uri
+ * \param history_add add to window history
+ * \param referer the referring uri
+ * \param download download, rather than render the uri
*
* Any existing fetches in the window are aborted.
*
@@ -238,6 +783,7 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
browser_window_stop(bw);
browser_window_remove_caret(bw);
+ browser_window_destroy_children(bw);
browser_window_set_status(bw, messages_get("Loading"));
bw->history_add = history_add;
@@ -263,7 +809,6 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
}
bw->download = download;
-
fetchcache_go(c, option_send_referer ? referer : 0,
browser_window_callback, (intptr_t) bw, 0,
gui_window_get_width(bw->window),
@@ -283,6 +828,7 @@ void browser_window_callback(content_msg msg, struct content *c,
char status[40];
char url[256];
+
switch (msg) {
case CONTENT_MSG_LOADING:
assert(bw->loading_content == c);
@@ -339,7 +885,7 @@ void browser_window_callback(content_msg msg, struct content *c,
browser_window_update(bw, true);
content_open(c, bw, 0, 0, 0, 0);
browser_window_set_status(bw, c->status_message);
- if (bw->history_add) {
+ if ((bw->history_add) && (bw->history)) {
history_add(bw->history, c, bw->frag_id);
if (urldb_add_url(c->url)) {
urldb_set_url_title(c->url,
@@ -550,6 +1096,9 @@ void browser_window_convert_to_download(struct browser_window *bw)
void browser_window_start_throbber(struct browser_window *bw)
{
bw->throbbing = true;
+
+ while (bw->parent)
+ bw = bw->parent;
gui_window_start_throbber(bw->window);
}
@@ -563,14 +1112,42 @@ void browser_window_start_throbber(struct browser_window *bw)
void browser_window_stop_throbber(struct browser_window *bw)
{
bw->throbbing = false;
- gui_window_stop_throbber(bw->window);
+
+ while (bw->parent)
+ bw = bw->parent;
+
+ if (!browser_window_check_throbber(bw))
+ gui_window_stop_throbber(bw->window);
+}
+
+bool browser_window_check_throbber(struct browser_window *bw)
+{
+ int children, index;
+
+ if (bw->throbbing)
+ return true;
+
+ if (bw->children) {
+ children = bw->rows * bw->cols;
+ for (index = 0; index < children; index++) {
+ if (browser_window_check_throbber(&bw->children[index]))
+ return true;
+ }
+ }
+ if (bw->iframes) {
+ for (index = 0; index < bw->iframe_count; index++) {
+ if (browser_window_check_throbber(&bw->iframes[index]))
+ return true;
+ }
+ }
+ return false;
}
/**
* Redraw browser window, set extent to content, and update title.
*
- * \param bw browser_window
+ * \param bw browser_window
* \param scroll_to_top move view to top of page
*/
@@ -588,8 +1165,7 @@ void browser_window_update(struct browser_window *bw,
} else
gui_window_set_title(bw->window, bw->current_content->url);
- gui_window_set_extent(bw->window, bw->current_content->width,
- bw->current_content->height);
+ gui_window_update_extent(bw->window);
if (scroll_to_top)
gui_window_set_scroll(bw->window, 0, 0);
@@ -614,6 +1190,8 @@ void browser_window_update(struct browser_window *bw,
void browser_window_stop(struct browser_window *bw)
{
+ int children, index;
+
if (bw->loading_content) {
content_remove_user(bw->loading_content,
browser_window_callback, (intptr_t) bw, 0);
@@ -628,6 +1206,17 @@ void browser_window_stop(struct browser_window *bw)
}
schedule_remove(browser_window_refresh, bw);
+
+ if (bw->children) {
+ children = bw->rows * bw->cols;
+ for (index = 0; index < children; index++)
+ browser_window_stop(&bw->children[index]);
+ }
+ if (bw->iframes) {
+ children = bw->iframe_count;
+ for (index = 0; index < children; index++)
+ browser_window_stop(&bw->iframes[index]);
+ }
browser_window_stop_throbber(bw);
}
@@ -672,12 +1261,14 @@ void browser_window_reload(struct browser_window *bw, bool all)
/**
* Change the status bar of a browser window.
*
- * \param bw browser window
+ * \param bw browser window
* \param text new status text (copied)
*/
void browser_window_set_status(struct browser_window *bw, const char *text)
{
+ while (bw->parent)
+ bw = bw->parent;
gui_window_set_status(bw->window, text);
}
@@ -702,12 +1293,61 @@ void browser_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
void browser_window_destroy(struct browser_window *bw)
{
+
+ /* can't destoy child windows on their own */
+ assert(!bw->parent);
+
+ /* destroy */
+ browser_window_destroy_internal(bw);
+ free(bw);
+}
+
+
+/**
+ * Close and destroy all child browser window.
+ *
+ * \param bw browser window
+ */
+
+void browser_window_destroy_children(struct browser_window *bw)
+{
+ int i;
+
+ if (bw->children) {
+ for (i = 0; i < (bw->rows * bw->cols); i++)
+ browser_window_destroy_internal(&bw->children[i]);
+ free(bw->children);
+ bw->children = NULL;
+ bw->rows = 0;
+ bw->cols = 0;
+ }
+ if (bw->iframes) {
+ for (i = 0; i < bw->iframe_count; i++)
+ browser_window_destroy_internal(&bw->iframes[i]);
+ free(bw->iframes);
+ bw->iframes = NULL;
+ bw->iframe_count = 0;
+ }
+}
+
+
+/**
+ * Release all memory associated with a browser window.
+ *
+ * \param bw browser window
+ */
+
+void browser_window_destroy_internal(struct browser_window *bw)
+{
+ assert(bw);
+
+ if ((bw->children) || (bw->iframes))
+ browser_window_destroy_children(bw);
if (bw->loading_content) {
content_remove_user(bw->loading_content,
browser_window_callback, (intptr_t) bw, 0);
bw->loading_content = 0;
}
-
if (bw->current_content) {
if (bw->current_content->status == CONTENT_STATUS_READY ||
bw->current_content->status ==
@@ -715,6 +1355,7 @@ void browser_window_destroy(struct browser_window *bw)
content_close(bw->current_content);
content_remove_user(bw->current_content,
browser_window_callback, (intptr_t) bw, 0);
+ bw->current_content = 0;
}
schedule_remove(browser_window_refresh, bw);
@@ -723,8 +1364,99 @@ void browser_window_destroy(struct browser_window *bw)
history_destroy(bw->history);
gui_window_destroy(bw->window);
+ free(bw->name);
free(bw->frag_id);
- free(bw);
+}
+
+
+/**
+ * Locate a browser window in the specified stack according.
+ *
+ * \param bw the browser_window to search all relatives of
+ * \param target the target to locate
+ */
+
+struct browser_window *browser_window_find_target(struct browser_window *bw, const char *target)
+{
+ struct browser_window *bw_target;
+ struct browser_window *top;
+ struct content *c;
+ int rdepth;
+
+ /* use the base target if we don't have one */
+ c = bw->current_content;
+ if (!target && c && c->data.html.base_target)
+ target = c->data.html.base_target;
+
+ /* allow target="_blank" to be ignored so zamez, tlsa and jmb don't lynch me */
+ if (!option_target_blank) {
+ if ((target == TARGET_BLANK) || (!strcasecmp(target, "_blank")))
+ target = TARGET_SELF;
+ }
+
+ /* todo: correctly follow B.8
+ * http://www.w3.org/TR/REC-html40/appendix/notes.html#notes-frames
+ */
+ if ((!target) || (target == TARGET_SELF) || (!strcasecmp(target, "_self")))
+ return bw;
+ else if ((target == TARGET_PARENT) || (!strcasecmp(target, "_parent"))) {
+ if (bw->parent)
+ return bw->parent;
+ return bw;
+ } else if ((target == TARGET_TOP) || (!strcasecmp(target, "_top"))) {
+ while (bw->parent)
+ bw = bw->parent;
+ return bw;
+ } else if ((target == TARGET_BLANK) || (!strcasecmp(target, "_blank"))) {
+ bw_target = browser_window_create(NULL, bw, NULL, false);
+ if (!bw_target)
+ return bw;
+ return bw_target;
+ }
+
+ /* find frame according to B.8, ie using the following priorities:
+ *
+ * 1) current frame
+ * 2) closest to front
+ */
+
+ rdepth = -1;
+ bw_target = bw;
+ for (top = bw; top->parent; top = top->parent);
+ browser_window_find_target_internal(top, target, 0, bw, &rdepth, &bw_target);
+ return bw_target;
+}
+
+void browser_window_find_target_internal(struct browser_window *bw, const char *target,
+ int depth, struct browser_window *page, int *rdepth, struct browser_window **bw_target)
+{
+ int i;
+
+ if ((bw->name) && (!strcasecmp(bw->name, target))) {
+ if ((bw == page) || (depth > *rdepth)) {
+ *rdepth = depth;
+ *bw_target = bw;
+ }
+ }
+
+ if ((!bw->children) && (!bw->iframes))
+ return;
+
+ depth++;
+ for (i = 0; i < (bw->cols * bw->rows); i++) {
+ if ((bw->children[i].name) && (!strcasecmp(bw->children[i].name, target))) {
+ if ((page == &bw->children[i]) || (depth > *rdepth)) {
+ *rdepth = depth;
+ *bw_target = &bw->children[i];
+ }
+ }
+ if (bw->children[i].children)
+ browser_window_find_target_internal(&bw->children[i], target, depth,
+ page, rdepth, bw_target);
+ }
+ for (i = 0; i < bw->iframe_count; i++)
+ browser_window_find_target_internal(&bw->iframes[i], target, depth, page,
+ rdepth, bw_target);
}
@@ -770,10 +1502,10 @@ void download_window_callback(fetch_msg msg, void *p, const void *data,
/**
* Handle mouse clicks in a browser window.
*
- * \param bw browser window
+ * \param bw browser window
* \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
*/
void browser_window_mouse_click(struct browser_window *bw,
@@ -817,10 +1549,10 @@ void browser_window_mouse_click(struct browser_window *bw,
/**
* Handle mouse clicks and movements in an HTML content window.
*
- * \param bw browser window
+ * \param bw browser window
* \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
*
* This function handles both hovering and clicking. It is important that the
* code path is identical (except that hovering doesn't carry out the action),
@@ -1089,18 +1821,9 @@ void browser_window_mouse_action_html(struct browser_window *bw,
c->url, true);
} else if (mouse & BROWSER_MOUSE_CLICK_1) {
- struct content *page = 0;
- unsigned int i = 0;
-
- html_find_target(url_content, target, &page, &i);
-
- if (page) {
- if (!html_replace_object(page, i, url, 0, 0))
- warn_user("NoMemory", 0);
- } else {
- browser_window_go(bw, url, c->url, true);
- }
-
+ bw = browser_window_find_target(bw, target);
+ assert(bw);
+ browser_window_go(bw, url, c->url, true);
} else if (mouse & BROWSER_MOUSE_CLICK_2 &&
mouse & BROWSER_MOUSE_MOD_1) {
free(browser_window_href_content.url);
@@ -1116,39 +1839,49 @@ void browser_window_mouse_action_html(struct browser_window *bw,
} else {
bool done = false;
+
+ /* frame resizing */
+ if (bw->parent) {
+ struct browser_window *parent;
+ for (parent = bw->parent; parent->parent; parent = parent->parent);
+ browser_window_resize_frames(parent, mouse, x + bw->x0, y + bw->y0,
+ &pointer, &status, &done);
+ }
/* if clicking in the main page, remove the selection from any text areas */
- if (text_box &&
- (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)) &&
- selection_root(bw->sel) != c->data.html.layout)
- selection_init(bw->sel, c->data.html.layout);
-
- if (text_box) {
- int pixel_offset;
- int idx;
-
- nsfont_position_in_string(text_box->style,
- text_box->text,
- text_box->length,
- x - text_box_x,
- &idx,
- &pixel_offset);
-
- if (selection_click(bw->sel, mouse, text_box->byte_offset + idx)) {
- /* key presses must be directed at the main browser
- * window, paste text operations ignored */
- browser_window_remove_caret(bw);
+ if (!done) {
+ if (text_box &&
+ (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)) &&
+ selection_root(bw->sel) != c->data.html.layout)
+ selection_init(bw->sel, c->data.html.layout);
- if (selection_dragging(bw->sel)) {
- bw->drag_type = DRAGGING_SELECTION;
- status = messages_get("Selecting");
- } else
- status = c->status_message;
+ if (text_box) {
+ int pixel_offset;
+ int idx;
+
+ nsfont_position_in_string(text_box->style,
+ text_box->text,
+ text_box->length,
+ x - text_box_x,
+ &idx,
+ &pixel_offset);
- done = true;
+ if (selection_click(bw->sel, mouse, text_box->byte_offset + idx)) {
+ /* key presses must be directed at the main browser
+ * window, paste text operations ignored */
+ browser_window_remove_caret(bw);
+
+ if (selection_dragging(bw->sel)) {
+ bw->drag_type = DRAGGING_SELECTION;
+ status = messages_get("Selecting");
+ } else
+ status = c->status_message;
+
+ done = true;
+ }
}
}
-
+
if (!done) {
if (title)
status = title;
@@ -1186,14 +1919,115 @@ void browser_window_mouse_action_html(struct browser_window *bw,
browser_window_set_pointer(bw->window, pointer);
}
+bool browser_window_resize_frames(struct browser_window *bw, browser_mouse_state mouse, int x, int y,
+ gui_pointer_shape *pointer, const char **status, bool *action) {
+ bool left, right, up, down;
+ int i, resize_margin;
+
+ if ((x < bw->x0) || (x > bw->x1) || (y < bw->y0) || (y > bw->y1))
+ return false;
+
+ if ((!bw->no_resize) && (bw->parent)) {
+ resize_margin = FRAME_RESIZE;
+ if (resize_margin * 2 > (bw->x1 - bw->x0))
+ resize_margin = (bw->x1 - bw->x0) / 2;
+ left = (x < bw->x0 + resize_margin);
+ right = (x > bw->x1 - resize_margin);
+ resize_margin = FRAME_RESIZE;
+ if (resize_margin * 2 > (bw->y1 - bw->y0))
+ resize_margin = (bw->y1 - bw->y0) / 2;
+ up = (y < bw->y0 + resize_margin);
+ down = (y > bw->y1 - resize_margin);
+
+ /* check if the edges can actually be moved */
+ if (left || right || up || down) {
+ int row = -1, col = -1;
+ switch (bw->browser_window_type) {
+ case BROWSER_WINDOW_NORMAL:
+ case BROWSER_WINDOW_IFRAME:
+ assert(0);
+ break;
+ case BROWSER_WINDOW_FRAME:
+ case BROWSER_WINDOW_FRAMESET:
+ assert(bw->parent);
+ break;
+ }
+ for (i = 0; i < (bw->parent->cols * bw->parent->rows); i++) {
+ if (&bw->parent->children[i] == bw) {
+ col = i % bw->parent->cols;
+ row = i / bw->parent->cols;
+ }
+ }
+ assert((row >= 0) && (col >= 0));
+
+ left &= (col > 0);
+ right &= (col < bw->parent->cols - 1) & (!left);
+ up &= (row > 0);
+ down &= (row < bw->parent->rows - 1) & (!up);
+ }
+
+ if (left || right || up || down) {
+ if (left) {
+ if (down)
+ *pointer = GUI_POINTER_LD;
+ else if (up)
+ *pointer = GUI_POINTER_LU;
+ else
+ *pointer = GUI_POINTER_LEFT;
+ } else if (right) {
+ if (down)
+ *pointer = GUI_POINTER_RD;
+ else if (up)
+ *pointer = GUI_POINTER_RU;
+ else
+ *pointer = GUI_POINTER_RIGHT;
+ } else if (up) {
+ *pointer = GUI_POINTER_UP;
+ } else {
+ *pointer = GUI_POINTER_DOWN;
+ }
+ if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2)) {
+ bw->drag_type = DRAGGING_FRAME;
+ bw->drag_start_x = x;
+ bw->drag_start_y = y;
+ bw->drag_resize_left = left;
+ bw->drag_resize_right = right;
+ bw->drag_resize_up = up;
+ bw->drag_resize_down = down;
+ gui_window_frame_resize_start(bw->window);
+
+ *status = messages_get("FrameDrag");
+ *action = true;
+ }
+ return true;
+ }
+ }
+
+ if (bw->children) {
+ for (i = 0; i < (bw->cols * bw->rows); i++)
+ if (browser_window_resize_frames(&bw->children[i], mouse, x, y, pointer, status,
+ action))
+ return true;
+ }
+ if (bw->iframes) {
+ for (i = 0; i < bw->iframe_count; i++)
+ if (browser_window_resize_frames(&bw->iframes[i], mouse, x, y, pointer, status,
+ action))
+ return true;
+ }
+ return false;
+}
+
+
+
/**
* Handle mouse clicks and movements in a TEXTPLAIN content window.
*
- * \param bw browser window
+ * \param bw browser window
* \param click type of mouse click
- * \param x coordinate of mouse
- * \param y coordinate of mouse
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
*
* This function handles both hovering and clicking. It is important that the
* code path is identical (except that hovering doesn't carry out the action),
@@ -1247,17 +2081,17 @@ void browser_window_mouse_action_text(struct browser_window *bw,
/**
* Handle mouse movements in a browser window.
*
- * \param bw browser window
+ * \param bw browser window
* \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
*/
void browser_window_mouse_track(struct browser_window *bw,
browser_mouse_state mouse, int x, int y)
{
struct content *c = bw->current_content;
- if (!c)
+ if ((!c) && (bw->drag_type != DRAGGING_FRAME))
return;
/* detect end of drag operation in case the platform-specific code
@@ -1266,18 +2100,19 @@ void browser_window_mouse_track(struct browser_window *bw,
if (bw->drag_type != DRAGGING_NONE && !mouse) {
browser_window_mouse_drag_end(bw, mouse, x, y);
}
-
- if (bw->drag_type == DRAGGING_PAGE_SCROLL) {
+ if (bw->drag_type == DRAGGING_FRAME) {
+ browser_window_resize_frame(bw, bw->x0 + x, bw->y0 + y);
+ } else if (bw->drag_type == DRAGGING_PAGE_SCROLL) {
/* mouse movement since drag started */
- int scrollx = bw->scrolling_start_x - x;
- int scrolly = bw->scrolling_start_y - y;
+ int scrollx = bw->drag_start_x - x;
+ int scrolly = bw->drag_start_y - y;
/* new scroll offsets */
- scrollx += bw->scrolling_start_scroll_x;
- scrolly += bw->scrolling_start_scroll_y;
+ scrollx += bw->drag_start_scroll_x;
+ scrolly += bw->drag_start_scroll_y;
- bw->scrolling_start_scroll_x = scrollx;
- bw->scrolling_start_scroll_y = scrolly;
+ bw->drag_start_scroll_x = scrollx;
+ bw->drag_start_scroll_y = scrolly;
gui_window_set_scroll(bw->window, scrollx, scrolly);
@@ -1299,17 +2134,16 @@ void browser_window_mouse_track(struct browser_window *bw,
/**
* Handle mouse tracking (including drags) in an HTML content window.
*
- * \param bw browser window
+ * \param bw browser window
* \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
*/
void browser_window_mouse_track_html(struct browser_window *bw,
browser_mouse_state mouse, int x, int y)
{
switch (bw->drag_type) {
-
case DRAGGING_HSCROLL:
case DRAGGING_VSCROLL:
case DRAGGING_2DSCROLL: {
@@ -1322,9 +2156,9 @@ void browser_window_mouse_track_html(struct browser_window *bw,
if (bw->drag_type == DRAGGING_HSCROLL) {
scroll_y = box->scroll_y;
} else {
- scroll_y = bw->scrolling_start_scroll_y +
- (float) (y - bw->scrolling_start_y) /
- (float) bw->scrolling_well_height *
+ scroll_y = bw->drag_start_scroll_y +
+ (float) (y - bw->drag_start_y) /
+ (float) bw->drag_well_height *
(float) (box->descendant_y1 -
box->descendant_y0);
if (scroll_y < box->descendant_y0)
@@ -1338,9 +2172,9 @@ void browser_window_mouse_track_html(struct browser_window *bw,
if (bw->drag_type == DRAGGING_VSCROLL) {
scroll_x = box->scroll_x;
} else {
- scroll_x = bw->scrolling_start_scroll_x +
- (float) (x - bw->scrolling_start_x) /
- (float) bw->scrolling_well_width *
+ scroll_x = bw->drag_start_scroll_x +
+ (float) (x - bw->drag_start_x) /
+ (float) bw->drag_well_width *
(float) (box->descendant_x1 -
box->descendant_x0);
if (scroll_x < box->descendant_x0)
@@ -1388,10 +2222,10 @@ void browser_window_mouse_track_html(struct browser_window *bw,
/**
* Handle mouse tracking (including drags) in a TEXTPLAIN content window.
*
- * \param bw browser window
+ * \param bw browser window
* \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
*/
void browser_window_mouse_track_text(struct browser_window *bw,
@@ -1421,10 +2255,10 @@ void browser_window_mouse_track_text(struct browser_window *bw,
/**
* Handles the end of a drag operation in a browser window.
*
- * \param bw browser window
+ * \param bw browser window
* \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
*/
void browser_window_mouse_drag_end(struct browser_window *bw,
@@ -1475,6 +2309,7 @@ void browser_window_mouse_drag_end(struct browser_window *bw,
case DRAGGING_2DSCROLL:
case DRAGGING_PAGE_SCROLL:
+ case DRAGGING_FRAME:
browser_window_set_pointer(bw->window, GUI_POINTER_DEFAULT);
break;
@@ -1489,13 +2324,13 @@ void browser_window_mouse_drag_end(struct browser_window *bw,
/**
* Handle mouse clicks in a box scrollbar.
*
- * \param bw browser window
+ * \param bw browser window
* \param mouse state of mouse buttons and modifier keys
- * \param box scrolling box
+ * \param box scrolling box
* \param box_x position of box in global document coordinates
* \param box_y position of box in global document coordinates
- * \param x coordinate of click relative to box position
- * \param y coordinate of click relative to box position
+ * \param x coordinate of click relative to box position
+ * \param y coordinate of click relative to box position
* \return status bar message
*/
@@ -1525,12 +2360,12 @@ const char *browser_window_scrollbar_click(struct browser_window *bw,
/* store some data for scroll drags */
bw->scrolling_box = box;
- bw->scrolling_start_x = box_x + x;
- bw->scrolling_start_y = box_y + y;
- bw->scrolling_start_scroll_x = box->scroll_x;
- bw->scrolling_start_scroll_y = box->scroll_y;
- bw->scrolling_well_width = well_width;
- bw->scrolling_well_height = well_height;
+ bw->drag_start_x = box_x + x;
+ bw->drag_start_y = box_y + y;
+ bw->drag_start_scroll_x = box->scroll_x;
+ bw->drag_start_scroll_y = box->scroll_y;
+ bw->drag_well_width = well_width;
+ bw->drag_well_height = well_height;
/* determine which scrollbar was clicked */
if (box_vscrollbar_present(box) &&
@@ -1672,9 +2507,9 @@ void browser_radio_set(struct content *content,
/**
* Redraw a rectangular region of a browser window
*
- * \param bw browser window to be redrawn
- * \param x x co-ord of top-left
- * \param y y co-ord of top-left
+ * \param bw browser window to be redrawn
+ * \param x x co-ord of top-left
+ * \param y y co-ord of top-left
* \param width width of rectangle
* \param height height of rectangle
*/
@@ -1708,7 +2543,7 @@ void browser_window_redraw_rect(struct browser_window *bw, int x, int y,
/**
* Redraw a box.
*
- * \param c content containing the box, of type CONTENT_HTML
+ * \param c content containing the box, of type CONTENT_HTML
* \param box box to redraw
*/
@@ -1742,8 +2577,8 @@ void browser_redraw_box(struct content *c, struct box *box)
* Update the scroll offsets of a box within a browser window
* (In future, copying where possible, rather than redrawing the entire box)
*
- * \param bw browser window
- * \param box box to be updated
+ * \param bw browser window
+ * \param box box to be updated
* \param scroll_x new horizontal scroll offset
* \param scroll_y new vertical scroll offset
*/
@@ -1762,9 +2597,9 @@ void browser_window_scroll_box(struct browser_window *bw, struct box *box,
/**
* Process a selection from a form select menu.
*
- * \param bw browser window with menu
+ * \param bw browser window with menu
* \param control form control with menu
- * \param item index of item selected from the menu
+ * \param item index of item selected from the menu
*/
void browser_window_form_select(struct browser_window *bw,
@@ -1912,7 +2747,7 @@ void browser_form_submit(struct browser_window *bw, struct form *form,
if (!target)
return;
} else {
- target = bw;
+ target = bw;
}
switch (form->method) {
@@ -1926,7 +2761,7 @@ void browser_form_submit(struct browser_window *bw, struct form *form,
url = calloc(1, strlen(form->action) + strlen(data) + 2);
if (!url) {
form_free_successful(success);
- free(data);
+ free(data);
warn_user("NoMemory", 0);
return;
}
@@ -1973,8 +2808,8 @@ void browser_form_submit(struct browser_window *bw, struct form *form,
* (dir -ve) or below-right (dir +ve) of the point 'x,y'
*
* \param box parent box
- * \param x x ordinate relative to parent box
- * \param y y ordinate relative to parent box
+ * \param x x ordinate relative to parent box
+ * \param y y ordinate relative to parent box
* \param dir direction in which to search (-1 = above-left, +1 = below-right)
* \return ptr to the nearest box, or NULL if none found
*/
@@ -2030,13 +2865,13 @@ struct box *browser_window_nearest_text_box(struct box *box, int x, int y, int d
* the mouse pointer, or nearest in the given direction if the pointer is
* not over a text box.
*
- * \param bw browser window
+ * \param bw browser window
* \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- * \param dx receives x ordinate of mouse relative to innermost containing box
- * \param dy receives y ordinate
- * \param dir direction to search (-1 = above-left, +1 = below-right)
+ * \param x coordinate of mouse
+ * \param y coordinate of mouse
+ * \param dx receives x ordinate of mouse relative to innermost containing box
+ * \param dy receives y ordinate
+ * \param dir direction to search (-1 = above-left, +1 = below-right)
*/
struct box *browser_window_pick_text_box(struct browser_window *bw,
@@ -2111,10 +2946,10 @@ void browser_window_page_drag_start(struct browser_window *bw, int x, int y)
{
bw->drag_type = DRAGGING_PAGE_SCROLL;
- bw->scrolling_start_x = x;
- bw->scrolling_start_y = y;
+ bw->drag_start_x = x;
+ bw->drag_start_y = y;
- gui_window_get_scroll(bw->window, &bw->scrolling_start_scroll_x, &bw->scrolling_start_scroll_y);
+ gui_window_get_scroll(bw->window, &bw->drag_start_scroll_x, &bw->drag_start_scroll_y);
gui_window_scroll_start(bw->window);
}
diff --git a/desktop/browser.h b/desktop/browser.h
index cb7246e91..b9516c78b 100644
--- a/desktop/browser.h
+++ b/desktop/browser.h
@@ -16,6 +16,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <time.h>
+#include "netsurf/render/html.h"
struct box;
struct content;
@@ -38,6 +39,8 @@ typedef bool (*browser_paste_callback)(struct browser_window *bw,
typedef void (*browser_move_callback)(struct browser_window *bw,
void *p);
+
+
/** Browser window data. */
struct browser_window {
/** Page currently displayed, or 0. Must have status READY or DONE. */
@@ -84,20 +87,26 @@ struct browser_window {
DRAGGING_HSCROLL,
DRAGGING_SELECTION,
DRAGGING_PAGE_SCROLL,
- DRAGGING_2DSCROLL
+ DRAGGING_2DSCROLL,
+ DRAGGING_FRAME
} drag_type;
/** Box currently being scrolled, or 0. */
struct box *scrolling_box;
/** Mouse position at start of current scroll drag. */
- int scrolling_start_x;
- int scrolling_start_y;
+ int drag_start_x;
+ int drag_start_y;
/** Scroll offsets at start of current scroll draw. */
- int scrolling_start_scroll_x;
- int scrolling_start_scroll_y;
+ int drag_start_scroll_x;
+ int drag_start_scroll_y;
/** Well dimensions for current scroll drag. */
- int scrolling_well_width;
- int scrolling_well_height;
+ int drag_well_width;
+ int drag_well_height;
+ /** Frame resize directions for current frame resize drag. */
+ unsigned int drag_resize_left : 1;
+ unsigned int drag_resize_right : 1;
+ unsigned int drag_resize_up : 1;
+ unsigned int drag_resize_down : 1;
/** Referer for current fetch, or 0. */
char *referer;
@@ -107,6 +116,50 @@ struct browser_window {
/** Refresh interval (-1 if undefined) */
int refresh_interval;
+
+ /** Window dimensions */
+ int x0;
+ int y0;
+ int x1;
+ int y1;
+
+ /** Window characteristics */
+ enum {
+ BROWSER_WINDOW_NORMAL,
+ BROWSER_WINDOW_IFRAME,
+ BROWSER_WINDOW_FRAME,
+ BROWSER_WINDOW_FRAMESET,
+ } browser_window_type;
+
+ /** frameset characteristics */
+ int rows;
+ int cols;
+
+ /** frame dimensions */
+ struct frame_dimension frame_width;
+ struct frame_dimension frame_height;
+ int margin_width;
+ int margin_height;
+
+ /** frame name for targetting */
+ char *name;
+
+ /** frame characteristics */
+ bool no_resize;
+ frame_scrolling scrolling;
+ bool border;
+ colour border_colour;
+
+ /** iframe parent box */
+ struct box *box;
+
+ /** [cols * rows] children */
+ struct browser_window *children;
+ struct browser_window *parent;
+
+ /** [iframe_count] iframes */
+ int iframe_count;
+ struct browser_window *iframes;
};
@@ -129,6 +182,7 @@ extern struct browser_window *current_redraw_browser;
struct browser_window * browser_window_create(const char *url,
struct browser_window *clone, char *referer, bool history_add);
+struct browser_window * browser_window_owner(struct browser_window *bw);
void browser_window_go(struct browser_window *bw, const char *url,
char *referer, bool history_add);
void browser_window_go_post(struct browser_window *bw, const char *url,
@@ -139,6 +193,12 @@ void browser_window_stop(struct browser_window *bw);
void browser_window_reload(struct browser_window *bw, bool all);
void browser_window_destroy(struct browser_window *bw);
void browser_window_update(struct browser_window *bw, bool scroll_to_top);
+void browser_window_create_iframes(struct browser_window *bw,
+ struct content_html_iframe *iframe);
+void browser_window_recalculate_iframes(struct browser_window *bw);
+void browser_window_create_frameset(struct browser_window *bw,
+ struct content_html_frames *frameset);
+void browser_window_recalculate_frameset(struct browser_window *bw);
void browser_window_mouse_click(struct browser_window *bw,
browser_mouse_state mouse, int x, int y);
diff --git a/desktop/gui.h b/desktop/gui.h
index 1e27d851f..4d09921a8 100644
--- a/desktop/gui.h
+++ b/desktop/gui.h
@@ -65,9 +65,12 @@ bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy);
void gui_window_set_scroll(struct gui_window *g, int sx, int sy);
void gui_window_scroll_visible(struct gui_window *g, int x0, int y0,
int x1, int y1);
+void gui_window_position_frame(struct gui_window *g, int x0, int y0,
+ int x1, int y1);
+void gui_window_get_dimensions(struct gui_window *g, int *width, int *height);
int gui_window_get_width(struct gui_window *g);
int gui_window_get_height(struct gui_window *g);
-void gui_window_set_extent(struct gui_window *g, int width, int height);
+void gui_window_update_extent(struct gui_window *g);
void gui_window_set_status(struct gui_window *g, const char *text);
void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape);
void gui_window_hide_pointer(struct gui_window *g);
@@ -81,6 +84,7 @@ bool gui_window_scroll_start(struct gui_window *g);
bool gui_window_box_scroll_start(struct gui_window *g,
int x0, int y0, int x1, int y1);
void gui_window_save_as_link(struct gui_window *g, struct content *c);
+bool gui_window_frame_resize_start(struct gui_window *g);
struct gui_download_window *gui_download_window_create(const char *url,
const char *mime_type, struct fetch *fetch,
diff --git a/desktop/history_core.c b/desktop/history_core.c
index b7fd66648..227e811a5 100644
--- a/desktop/history_core.c
+++ b/desktop/history_core.c
@@ -33,12 +33,15 @@
#define RIGHT_MARGIN 50
#define BOTTOM_MARGIN 30
-
-/** A node in the history tree. */
-struct history_entry {
+struct history_page {
char *url; /**< Page URL. */
char *frag_id; /** Fragment identifier */
char *title; /**< Page title. */
+};
+
+/** A node in the history tree. */
+struct history_entry {
+ struct history_page page;
struct history_entry *back; /**< Parent. */
struct history_entry *next; /**< Next sibling. */
struct history_entry *forward; /**< First child. */
@@ -153,16 +156,16 @@ struct history_entry *history_clone_entry(struct history *history,
if (!new_entry)
return 0;
memcpy(new_entry, entry, sizeof *entry);
- new_entry->url = strdup(entry->url);
- if (entry->frag_id)
- new_entry->frag_id = strdup(entry->frag_id);
- new_entry->title = strdup(entry->title);
- if (((entry->url) && (!new_entry->url)) ||
- ((entry->title) && (!new_entry->title)) ||
- ((entry->frag_id) && (!new_entry->frag_id))) {
- free(new_entry->url);
- free(new_entry->title);
- free(new_entry->frag_id);
+ new_entry->page.url = strdup(entry->page.url);
+ if (entry->page.frag_id)
+ new_entry->page.frag_id = strdup(entry->page.frag_id);
+ new_entry->page.title = strdup(entry->page.title);
+ if (((entry->page.url) && (!new_entry->page.url)) ||
+ ((entry->page.title) && (!new_entry->page.title)) ||
+ ((entry->page.frag_id) && (!new_entry->page.frag_id))) {
+ free(new_entry->page.url);
+ free(new_entry->page.title);
+ free(new_entry->page.frag_id);
free(new_entry);
return 0;
}
@@ -230,9 +233,9 @@ void history_add(struct history *history, struct content *content,
return;
}
- entry->url = url;
- entry->frag_id = frag_id ? strdup(frag_id) : 0;
- entry->title = title;
+ entry->page.url = url;
+ entry->page.frag_id = frag_id ? strdup(frag_id) : 0;
+ entry->page.title = title;
entry->back = history->current;
entry->next = 0;
entry->forward = entry->forward_pref = entry->forward_last = 0;
@@ -282,12 +285,12 @@ void history_update(struct history *history, struct content *content)
if (!history || !history->current || !history->current->bitmap)
return;
- if (history->current->title)
- free(history->current->title);
+ if (history->current->page.title)
+ free(history->current->page.title);
if (content->title)
- history->current->title = strdup(content->title);
+ history->current->page.title = strdup(content->title);
else
- history->current->title = 0;
+ history->current->page.title = 0;
thumbnail_create(content, history->current->bitmap, 0);
}
@@ -318,10 +321,10 @@ void history_free_entry(struct history_entry *entry)
return;
history_free_entry(entry->forward);
history_free_entry(entry->next);
- free(entry->url);
- if (entry->frag_id)
- free(entry->frag_id);
- free(entry->title);
+ free(entry->page.url);
+ if (entry->page.frag_id)
+ free(entry->page.frag_id);
+ free(entry->page.title);
free(entry);
}
@@ -397,16 +400,17 @@ void history_go(struct browser_window *bw, struct history *history,
char *url;
struct history_entry *current;
- if (entry->frag_id) {
- url = malloc(strlen(entry->url) + strlen(entry->frag_id) + 5);
+ if (entry->page.frag_id) {
+ url = malloc(strlen(entry->page.url) +
+ strlen(entry->page.frag_id) + 5);
if (!url) {
warn_user("NoMemory", 0);
return;
}
- sprintf(url, "%s#%s", entry->url, entry->frag_id);
+ sprintf(url, "%s#%s", entry->page.url, entry->page.frag_id);
}
else
- url = entry->url;
+ url = entry->page.url;
if (new_window) {
current = history->current;
@@ -418,7 +422,7 @@ void history_go(struct browser_window *bw, struct history *history,
browser_window_go(bw, url, 0, false);
}
- if (entry->frag_id)
+ if (entry->page.frag_id)
free(url);
}
@@ -552,19 +556,19 @@ bool history_redraw_entry(struct history *history,
struct history_entry *child;
colour c = entry == history->current ? 0x0000ff : 0x333333;
int tailsize = 5;
-
- if (!plot.bitmap(entry->x, entry->y, WIDTH, HEIGHT, entry->bitmap,
- 0xffffff))
+
+ if (!plot.bitmap(entry->x, entry->y, WIDTH, HEIGHT,
+ entry->bitmap, 0xffffff))
return false;
if (!plot.rectangle(entry->x - 1, entry->y - 1, WIDTH + 1, HEIGHT + 1,
entry == history->current ? 2 : 1, c, false, false))
return false;
- if (!nsfont_position_in_string(&css_base_style, entry->title,
- strlen(entry->title), WIDTH, &char_offset, &actual_x))
+ if (!nsfont_position_in_string(&css_base_style, entry->page.title,
+ strlen(entry->page.title), WIDTH, &char_offset, &actual_x))
return false;
if (!plot.text(entry->x, entry->y + HEIGHT + 12, &css_base_style,
- entry->title, char_offset, 0xffffff, c))
+ entry->page.title, char_offset, 0xffffff, c))
return false;
for (child = entry->forward; child; child = child->next) {
@@ -635,7 +639,7 @@ const char *history_position_url(struct history *history, int x, int y)
if (!entry)
return 0;
- return entry->url;
+ return entry->page.url;
}
diff --git a/desktop/netsurf.c b/desktop/netsurf.c
index 606774bf3..f0b7e32f6 100644
--- a/desktop/netsurf.c
+++ b/desktop/netsurf.c
@@ -102,10 +102,15 @@ void netsurf_poll(void)
void netsurf_exit(void)
{
+ LOG(("Closing GUI"));
gui_quit();
+ LOG(("Closing content"));
content_quit();
+ LOG(("Closing fetches"));
fetch_quit();
+ LOG(("Closing utf8"));
utf8_finalise();
+ LOG(("Exited successfully"));
}
diff --git a/desktop/options.c b/desktop/options.c
index 58c9ef24b..9679e82fe 100644
--- a/desktop/options.c
+++ b/desktop/options.c
@@ -124,7 +124,8 @@ int option_max_fetchers_per_host = 2;
* is this plus option_max_fetchers.
*/
int option_max_cached_fetch_handles = 6;
-/** Whether to use knockout rendering */
+/** Whether to allow target="_blank" */
+bool option_target_blank = true;
EXTRA_OPTION_DEFINE
@@ -174,6 +175,8 @@ struct {
OPTION_INTEGER, &option_max_fetchers_per_host },
{ "max_cached_fetch_handles",
OPTION_INTEGER, &option_max_cached_fetch_handles },
+ { "target_blank",
+ OPTION_BOOL, &option_target_blank },
EXTRA_OPTION_TABLE
};
diff --git a/desktop/options.h b/desktop/options.h
index 551fef5f8..64944eb47 100644
--- a/desktop/options.h
+++ b/desktop/options.h
@@ -57,6 +57,7 @@ extern char *option_ca_bundle;
extern char *option_cookie_file;
extern char *option_cookie_jar;
extern char *option_homepage_url;
+extern bool option_target_blank;
extern bool option_url_suggestion;
extern int option_window_x;
extern int option_window_y;
diff --git a/render/box.h b/render/box.h
index ce439381b..90d011486 100644
--- a/render/box.h
+++ b/render/box.h
@@ -253,6 +253,7 @@ struct object_param {
extern const char *TARGET_SELF;
extern const char *TARGET_PARENT;
extern const char *TARGET_TOP;
+extern const char *TARGET_BLANK;
#define UNKNOWN_WIDTH INT_MAX
diff --git a/render/box_construct.c b/render/box_construct.c
index 4dfb54c05..b61cb5d24 100644
--- a/render/box_construct.c
+++ b/render/box_construct.c
@@ -1,10 +1,11 @@
/*
* This file is part of NetSurf, http://netsurf.sourceforge.net/
* Licensed under the GNU General Public License,
- * http://www.opensource.org/licenses/gpl-license
+ * http://www.opensource.org/licenses/gpl-license
* Copyright 2005 James Bursa <bursa@users.sourceforge.net>
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
* Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2006 Richard Wilson <info@tinct.net>
*/
/** \file
@@ -22,6 +23,7 @@
#include "netsurf/utils/config.h"
#include "netsurf/content/content.h"
#include "netsurf/css/css.h"
+#include "netsurf/desktop/browser.h"
#include "netsurf/desktop/options.h"
#include "netsurf/render/box.h"
#include "netsurf/render/form.h"
@@ -37,13 +39,6 @@
#include "netsurf/utils/utils.h"
-/** MultiLength, as defined by HTML 4.01. */
-struct box_multi_length {
- enum { LENGTH_PX, LENGTH_PERCENT, LENGTH_RELATIVE } type;
- float value;
-};
-
-
static const content_type image_types[] = {
#ifdef WITH_JPEG
CONTENT_JPEG,
@@ -77,6 +72,7 @@ static const content_type image_types[] = {
const char *TARGET_SELF = "_self";
const char *TARGET_PARENT = "_parent";
const char *TARGET_TOP = "_top";
+const char *TARGET_BLANK = "_blank";
static bool convert_xml_to_box(xmlNode *n, struct content *content,
@@ -114,6 +110,8 @@ static bool box_input(BOX_SPECIAL_PARAMS);
static bool box_input_text(BOX_SPECIAL_PARAMS, bool password);
static bool box_button(BOX_SPECIAL_PARAMS);
static bool box_frameset(BOX_SPECIAL_PARAMS);
+static bool box_create_frameset(struct content_html_frames *f, xmlNode *n,
+ struct content *content);
static bool box_select_add_option(struct form_control *control, xmlNode *n);
static bool box_object(BOX_SPECIAL_PARAMS);
static bool box_embed(BOX_SPECIAL_PARAMS);
@@ -122,13 +120,13 @@ static bool box_pre(BOX_SPECIAL_PARAMS);
static bool box_iframe(BOX_SPECIAL_PARAMS);
static bool box_get_attribute(xmlNode *n, const char *attribute,
void *context, char **value);
-static struct box_multi_length *box_parse_multi_lengths(const char *s,
- unsigned int *count, void *context);
+static struct frame_dimension *box_parse_multi_lengths(const char *s,
+ unsigned int *count);
/* element_table must be sorted by name */
struct element_entry {
- char name[10]; /* element type */
+ char name[10]; /* element type */
bool (*convert)(BOX_SPECIAL_PARAMS);
};
static const struct element_entry element_table[] = {
@@ -228,17 +226,17 @@ static const box_type box_map[] = {
/**
* Recursively construct a box tree from an xml tree and stylesheets.
*
- * \param n fragment of xml tree
- * \param content content of type CONTENT_HTML that is being processed
+ * \param n fragment of xml tree
+ * \param content content of type CONTENT_HTML that is being processed
* \param parent_style style at this point in xml tree
- * \param parent parent in box tree
+ * \param parent parent in box tree
* \param inline_container current inline container box, or 0, updated to
- * new current inline container on exit
+ * new current inline container on exit
* \param containing_block current containing block for absolutes, as defined
- * by CSS 2.1 10.1 4
- * \param href current link URL, or 0 if not in a link
- * \param target current link target, or 0 if none
- * \param title current title, or 0 if none
+ * by CSS 2.1 10.1 4
+ * \param href current link URL, or 0 if not in a link
+ * \param target current link target, or 0 if none
+ * \param title current title, or 0 if none
* \return true on success, false on memory exhaustion
*/
@@ -266,17 +264,17 @@ bool convert_xml_to_box(xmlNode *n, struct content *content,
/**
* Construct the box tree for an XML element.
*
- * \param n XML node of type XML_ELEMENT_NODE
- * \param content content of type CONTENT_HTML that is being processed
+ * \param n XML node of type XML_ELEMENT_NODE
+ * \param content content of type CONTENT_HTML that is being processed
* \param parent_style style at this point in xml tree
- * \param parent parent in box tree
+ * \param parent parent in box tree
* \param inline_container current inline container box, or 0, updated to
- * new current inline container on exit
+ * new current inline container on exit
* \param containing_block current containing block for absolutes, as defined
- * by CSS 2.1 10.1 4
- * \param href current link URL, or 0 if not in a link
- * \param target current link target, or 0 if none
- * \param title current title, or 0 if none
+ * by CSS 2.1 10.1 4
+ * \param href current link URL, or 0 if not in a link
+ * \param target current link target, or 0 if none
+ * \param title current title, or 0 if none
* \return true on success, false on memory exhaustion
*/
@@ -471,8 +469,8 @@ bool box_construct_element(xmlNode *n, struct content *content,
xmlFree(s);
}
if (strcmp((const char *) n->name, "table") == 0) {
- border_color = 0x888888; /* default colour */
- if ((s = (char *) xmlGetProp(n,
+ border_color = 0x888888; /* default colour */
+ if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "cellpadding"))) {
char *endp;
long value = strtol(s, &endp, 10);
@@ -481,7 +479,7 @@ bool box_construct_element(xmlNode *n, struct content *content,
box_set_cellpadding(box, value);
xmlFree(s);
}
- if ((s = (char *) xmlGetProp(n,
+ if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "bordercolor"))) {
unsigned int r, g, b;
if (s[0] == '#' && sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3)
@@ -490,7 +488,7 @@ bool box_construct_element(xmlNode *n, struct content *content,
border_color = named_colour(s);
xmlFree(s);
}
- if ((s = (char *) xmlGetProp(n,
+ if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "border"))) {
int value = atoi(s);
if (!strrchr(s, '%') && 0 < value) /* % not implemented */
@@ -501,7 +499,7 @@ bool box_construct_element(xmlNode *n, struct content *content,
/* transfer <tr height="n"> down to the <td> elements */
if (strcmp((const char *) n->name, "tr") == 0) {
- if ((s = (char *) xmlGetProp(n,
+ if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "height"))) {
float value = atof(s);
if (value < 0 || strlen(s) == 0) {
@@ -515,12 +513,12 @@ bool box_construct_element(xmlNode *n, struct content *content,
struct box *child;
float current;
for (child = box->children; child; child = child->next) {
- if (child->type == BOX_TABLE_CELL) {
- current = css_len2px(
- &child->style->height.length,
- child->style);
- value = (value > current) ?
- value : current;
+ if (child->type == BOX_TABLE_CELL) {
+ current = css_len2px(
+ &child->style->height.length,
+ child->style);
+ value = (value > current) ?
+ value : current;
child->style->height.height =
CSS_HEIGHT_LENGTH;
child->style->height.length.unit =
@@ -538,7 +536,7 @@ bool box_construct_element(xmlNode *n, struct content *content,
if (style->background_image.type == CSS_BACKGROUND_IMAGE_URI) {
if (!html_fetch_object(content, style->background_image.uri,
box, image_types, content->available_width,
- 1000, true, 0))
+ 1000, true))
return false;
}
@@ -549,15 +547,15 @@ bool box_construct_element(xmlNode *n, struct content *content,
/**
* Construct the box tree for an XML text node.
*
- * \param n XML node of type XML_TEXT_NODE
- * \param content content of type CONTENT_HTML that is being processed
+ * \param n XML node of type XML_TEXT_NODE
+ * \param content content of type CONTENT_HTML that is being processed
* \param parent_style style at this point in xml tree
- * \param parent parent in box tree
+ * \param parent parent in box tree
* \param inline_container current inline container box, or 0, updated to
- * new current inline container on exit
- * \param href current link URL, or 0 if not in a link
- * \param target current link target, or 0 if none
- * \param title current title, or 0 if none
+ * new current inline container on exit
+ * \param href current link URL, or 0 if not in a link
+ * \param target current link target, or 0 if none
+ * \param title current title, or 0 if none
* \return true on success, false on memory exhaustion
*/
@@ -726,9 +724,9 @@ bool box_construct_text(xmlNode *n, struct content *content,
/**
* Get the style for an element.
*
- * \param c content of type CONTENT_HTML that is being processed
+ * \param c content of type CONTENT_HTML that is being processed
* \param parent_style style at this point in xml tree
- * \param n node in xml tree
+ * \param n node in xml tree
* \return the new style, or 0 on memory exhaustion
*
* The style is collected from three sources:
@@ -985,7 +983,7 @@ struct css_style * box_get_style(struct content *c,
* by CSS 2.1 9.7.
*
* \param style style to update
- * \param root this is the root element
+ * \param root this is the root element
*/
void box_solve_display(struct css_style *style, bool root)
@@ -1016,7 +1014,7 @@ void box_solve_display(struct css_style *style, bool root)
/**
* Set the cellpadding on a table.
*
- * \param box box to set cellpadding on
+ * \param box box to set cellpadding on
* \param value padding in pixels
*
* The descendants of the box are searched for table cells, and the padding is
@@ -1046,7 +1044,7 @@ void box_set_cellpadding(struct box *box, int value)
break;
default:
break;
- }
+ }
}
}
@@ -1054,7 +1052,7 @@ void box_set_cellpadding(struct box *box, int value)
/**
* Set the borders on a table.
*
- * \param box box to set cellpadding on
+ * \param box box to set cellpadding on
* \param value border in pixels
*
* The descendants of the box are searched for table cells, and the border is
@@ -1067,8 +1065,8 @@ void box_set_table_border(struct box *box, int value, colour color)
if (box->type == BOX_TABLE) {
for (unsigned int i = 0; i != 4; i++) {
- if (box->style->border[i].style ==
- CSS_BORDER_STYLE_NONE) {
+ if (box->style->border[i].style ==
+ CSS_BORDER_STYLE_NONE) {
box->style->border[i].color = color;
box->style->border[i].width.width =
CSS_BORDER_WIDTH_LENGTH;
@@ -1092,8 +1090,8 @@ void box_set_table_border(struct box *box, int value, colour color)
break;
case BOX_TABLE_CELL:
for (unsigned int i = 0; i != 4; i++) {
- if (child->style->border[i].style ==
- CSS_BORDER_STYLE_NONE) {
+ if (child->style->border[i].style ==
+ CSS_BORDER_STYLE_NONE) {
child->style->border[i].color = color;
child->style->border[i].width.width =
CSS_BORDER_WIDTH_LENGTH;
@@ -1108,7 +1106,7 @@ void box_set_table_border(struct box *box, int value, colour color)
break;
default:
break;
- }
+ }
}
}
@@ -1116,9 +1114,9 @@ void box_set_table_border(struct box *box, int value, colour color)
/**
* Apply the CSS text-transform property to given text for its ASCII chars.
*
- * \param s string to transform
+ * \param s string to transform
* \param len length of s
- * \param tt transform type
+ * \param tt transform type
*/
void box_text_transform(char *s, unsigned int len,
@@ -1231,11 +1229,13 @@ bool box_a(BOX_SPECIAL_PARAMS)
/* target frame [16.3] */
if ((s = xmlGetProp(n, (const xmlChar *) "target"))) {
- if (!strcmp(s, "_blank") || !strcmp(s, "_top"))
+ if (!strcasecmp(s, "_blank"))
+ box->target = TARGET_BLANK;
+ else if (!strcasecmp(s, "_top"))
box->target = TARGET_TOP;
- else if (!strcmp(s, "_parent"))
+ else if (!strcasecmp(s, "_parent"))
box->target = TARGET_PARENT;
- else if (!strcmp(s, "_self"))
+ else if (!strcasecmp(s, "_self"))
/* the default may have been overridden by a
* <base target=...>, so this is different to 0 */
box->target = TARGET_SELF;
@@ -1246,7 +1246,7 @@ bool box_a(BOX_SPECIAL_PARAMS)
xmlFree(s);
return false;
}
- }
+ }
xmlFree(s);
}
@@ -1294,7 +1294,7 @@ bool box_image(BOX_SPECIAL_PARAMS)
/* start fetch */
ok = html_fetch_object(content, url, box, image_types,
- content->available_width, 1000, false, 0);
+ content->available_width, 1000, false);
free(url);
return ok;
}
@@ -1406,7 +1406,7 @@ bool box_object(BOX_SPECIAL_PARAMS)
/* start fetch (MIME type is ok or not specified) */
if (!html_fetch_object(content, params->data, box, 0,
- content->available_width, 1000, false, 0))
+ content->available_width, 1000, false))
return false;
/* convert children and place into fallback */
@@ -1563,96 +1563,117 @@ no_memory:
bool box_frameset(BOX_SPECIAL_PARAMS)
{
- unsigned int row, col;
+ bool ok;
+
+ if (content->data.html.frameset) {
+ LOG(("Error: multiple framesets in document."));
+ return false;
+ }
+
+ content->data.html.frameset = talloc_zero(content, struct content_html_frames);
+ if (!content->data.html.frameset)
+ return false;
+
+ ok = box_create_frameset(content->data.html.frameset, n, content);
+ if (ok)
+ box->style->display = CSS_DISPLAY_NONE;
+
+ if (convert_children)
+ *convert_children = false;
+ return ok;
+}
+
+bool box_create_frameset(struct content_html_frames *f, xmlNode *n,
+ struct content *content) {
+ unsigned int row, col, index, i;
unsigned int rows = 1, cols = 1;
- int object_width, object_height;
- char *s, *s1, *url, *name;
- struct box *row_box;
- struct box *cell_box;
- struct box *frameset_box;
- struct css_style *style = box->style;
- struct css_style *row_style;
- struct css_style *cell_style;
- struct box_multi_length *row_height = 0, *col_width = 0;
+ char *s, *url;
+ struct frame_dimension *row_height = 0, *col_width = 0;
xmlNode *c;
- url_func_result res;
-
- box->type = BOX_TABLE;
+ struct content_html_frames *frame;
+ bool default_border = true;
+ colour default_border_colour = 0x000000;
/* parse rows and columns */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "rows"))) {
- row_height = box_parse_multi_lengths(s, &rows, content);
+ row_height = box_parse_multi_lengths(s, &rows);
xmlFree(s);
if (!row_height)
return false;
+ } else {
+ row_height = calloc(1, sizeof(struct frame_dimension));
+ if (!row_height)
+ return false;
+ row_height->value = 100;
+ row_height->unit = FRAME_DIMENSION_PERCENT;
}
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "cols"))) {
- col_width = box_parse_multi_lengths(s, &cols, content);
+ col_width = box_parse_multi_lengths(s, &cols);
xmlFree(s);
if (!col_width)
return false;
+ } else {
+ col_width = calloc(1, sizeof(struct frame_dimension));
+ if (!col_width)
+ return false;
+ col_width->value = 100;
+ col_width->unit = FRAME_DIMENSION_PERCENT;
}
- LOG(("rows %u, cols %u", rows, cols));
-
- box->min_width = 1;
- box->max_width = 10000;
- box->col = talloc_array(content, struct column, cols);
- if (!box->col)
- return false;
-
- if (col_width) {
- for (col = 0; col != cols; col++) {
- if (col_width[col].type == LENGTH_PX) {
- box->col[col].type = COLUMN_WIDTH_FIXED;
- box->col[col].width = col_width[col].value;
- } else if (col_width[col].type == LENGTH_PERCENT) {
- box->col[col].type = COLUMN_WIDTH_PERCENT;
- box->col[col].width = col_width[col].value;
- } else {
- box->col[col].type = COLUMN_WIDTH_RELATIVE;
- box->col[col].width = col_width[col].value;
- }
- box->col[col].min = 1;
- box->col[col].max = 10000;
+ /* common extension: border="0|1" to control all children */
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "border"))) {
+ if ((s[0] == '0') && (s[1] == '\0'))
+ default_border = false;
+ xmlFree(s);
+ }
+ /* common extension: frameborder="yes|no" to control all children */
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "frameborder"))) {
+ if (!strcasecmp(s, "no"))
+ default_border = false;
+ xmlFree(s);
+ }
+ /* common extension: bordercolor="#RRGGBB|<named colour>" to control all children */
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "bordercolor"))) {
+ unsigned int r, g, b;
+ if (s[0] == '#' && sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3)
+ default_border_colour = (b << 16) | (g << 8) | r;
+ else if (s[0] != '#')
+ default_border_colour = named_colour(s);
+ xmlFree(s);
+ }
+
+ /* update frameset and create default children */
+ f->cols = cols;
+ f->rows = rows;
+ f->scrolling = SCROLLING_NO;
+ f->children = talloc_array(content, struct content_html_frames, (rows * cols));
+ for (row = 0; row < rows; row++) {
+ for (col = 0; col < cols; col++) {
+ index = (row * cols) + col;
+ frame = &f->children[index];
+ frame->cols = 0;
+ frame->rows = 0;
+ frame->width = col_width[col];
+ frame->height = row_height[row];
+ frame->margin_width = -1;
+ frame->margin_height = -1;
+ frame->name = NULL;
+ frame->url = NULL;
+ frame->no_resize = false;
+ frame->scrolling = SCROLLING_AUTO;
+ frame->border = default_border;
+ frame->border_colour = default_border_colour;
+ frame->children = NULL;
}
- } else {
- box->col[0].type = COLUMN_WIDTH_RELATIVE;
- box->col[0].width = 1;
- box->col[0].min = 1;
- box->col[0].max = 10000;
}
+ free(col_width);
+ free(row_height);
- /* create the frameset table */
+ /* create the frameset windows */
c = n->children;
- for (row = 0; c && row != rows; row++) {
- row_style = talloc_memdup(content, style, sizeof *style);
- if (!row_style)
- return false;
- object_height = 1000; /** \todo get available height */
- /* if (row_height) {
- row_style->height.height = CSS_HEIGHT_LENGTH;
- row_style->height.length.unit = CSS_UNIT_PX;
- if (row_height[row].type == LENGTH_PERCENT)
- row_style->height.length.value = 1000 *
- row_height[row].value / 100;
- else if (row_height[row].type == LENGTH_RELATIVE)
- row_style->height.length.value = 100 *
- row_height[row].value;
- else
- row_style->height.length.value =
- row_height[row].value;
- object_height = row_style->height.length.value;
- }*/
- row_box = box_create(row_style, 0, 0, 0, 0, content);
- if (!row_box)
- return false;
-
- row_box->type = BOX_TABLE_ROW;
- box_add_child(box, row_box);
-
- for (col = 0; c && col != cols; col++) {
+ for (row = 0; c && row < rows; row++) {
+ for (col = 0; c && col < cols; col++) {
while (c && !(c->type == XML_ELEMENT_NODE && (
strcmp((const char *) c->name, "frame") == 0 ||
strcmp((const char *) c->name, "frameset") == 0
@@ -1661,83 +1682,91 @@ bool box_frameset(BOX_SPECIAL_PARAMS)
if (!c)
break;
- /* estimate frame width */
- object_width = content->available_width;
- if (col_width && col_width[col].type == LENGTH_PX)
- object_width = col_width[col].value;
-
- cell_style = talloc_memdup(content, style,
- sizeof *style);
- if (!cell_style)
- return false;
- cell_style->overflow = CSS_OVERFLOW_AUTO;
-
- cell_box = box_create(cell_style, 0, 0, 0, 0, content);
- if (!cell_box)
- return false;
- cell_box->type = BOX_TABLE_CELL;
- box_add_child(row_box, cell_box);
+ /* get current frame */
+ index = (row * cols) + col;
+ frame = &f->children[index];
+ /* nest framesets */
if (strcmp((const char *) c->name, "frameset") == 0) {
- LOG(("frameset"));
- frameset_box = box_create(cell_style, 0, 0, 0,
- 0, content);
- if (!frameset_box)
- return false;
- if (!box_frameset(c, content, frameset_box, 0))
+ frame->border = 0;
+ if (!box_create_frameset(frame, c, content))
return false;
- box_add_child(cell_box, frameset_box);
-
c = c->next;
continue;
}
+ /* get frame URL */
if (!(s = (char *) xmlGetProp(c,
(const xmlChar *) "src"))) {
c = c->next;
continue;
}
-
- s1 = strip(s);
- res = url_join(s1, content->data.html.base_url, &url);
+ if (!box_extract_link(s, content->data.html.base_url, &url)) {
+ xmlFree(s);
+ c = c->next;
+ continue;
+ }
xmlFree(s);
- /* if url is equivalent to the parent's url,
- * we've got infinite inclusion. stop it here.
- * also bail if url_join failed.
- */
- if (res != URL_FUNC_OK || strcasecmp(url,
- content->data.html.base_url) == 0) {
- LOG(("url_join failed"));
+ if (!url) {
c = c->next;
continue;
}
- name = xmlGetProp(c, (const xmlChar *) "name");
+ /* don't include ourself */
+ if (strcmp(content->data.html.base_url, url) == 0) {
+ free(url);
+ c = c->next;
+ continue;
+ }
- LOG(("frame, url '%s', name '%s'", url, name));
+ /* fill in specified values */
+ frame->url = talloc_strdup(content, url);
+ if ((s = (char *) xmlGetProp(c,
+ (const xmlChar *) "name"))) {
+ frame->name = talloc_strdup(content, s);
+ xmlFree(s);
+ }
+ frame->no_resize = xmlHasProp(c,
+ (const xmlChar *) "noresize");
+ if ((s = (char *) xmlGetProp(c,
+ (const xmlChar *) "frameborder"))) {
+ i = atoi(s);
+ frame->border = (i != 0);
+ xmlFree(s);
+ }
+ if ((s = (char *) xmlGetProp(c,
+ (const xmlChar *) "scrolling"))) {
+ if (!strcasecmp(s, "yes"))
+ frame->scrolling = SCROLLING_YES;
+ else if (!strcasecmp(s, "no"))
+ frame->scrolling = SCROLLING_NO;
+ xmlFree(s);
+ }
+ if ((s = (char *) xmlGetProp(c,
+ (const xmlChar *) "marginwidth"))) {
+ frame->margin_width = atoi(s);
+ xmlFree(s);
+ }
+ if ((s = (char *) xmlGetProp(c,
+ (const xmlChar *) "marginheight"))) {
+ frame->margin_width = atoi(s);
+ xmlFree(s);
+ }
+ if ((s = (char *) xmlGetProp(c, (const xmlChar *) "bordercolor"))) {
+ unsigned int r, g, b;
+ if (s[0] == '#' && sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3)
+ frame->border_colour = (b << 16) | (g << 8) | r;
+ else if (s[0] != '#')
+ frame->border_colour = named_colour(s);
+ xmlFree(s);
+ }
- if (!html_fetch_object(content, url,
- cell_box, 0,
- object_width, object_height, false,
- name))
- return false;
+ /* release temporary memory */
free(url);
-
- if (name)
- xmlFree(name);
-
c = c->next;
}
}
- talloc_free(row_height);
- talloc_free(col_width);
-
- style->width.width = CSS_WIDTH_PERCENT;
- style->width.value.percent = 100;
-
- if (convert_children)
- *convert_children = false;
return true;
}
@@ -1748,33 +1777,93 @@ bool box_frameset(BOX_SPECIAL_PARAMS)
bool box_iframe(BOX_SPECIAL_PARAMS)
{
- bool ok;
- char *url;
- xmlChar *src;
+ char *url, *s;
+ struct content_html_iframe *iframe;
+ int i;
/* get frame URL */
- if (!(src = xmlGetProp(n, (const xmlChar *) "src")))
+ if (!(s = (char *) xmlGetProp(n,
+ (const xmlChar *) "src")))
return true;
- if (!box_extract_link((char *) src, content->data.html.base_url, &url))
+ if (!box_extract_link(s, content->data.html.base_url, &url)) {
+ xmlFree(s);
return false;
+ }
+ xmlFree(s);
if (!url)
return true;
- /* Don't include ourself */
+ /* don't include ourself */
if (strcmp(content->data.html.base_url, url) == 0) {
free(url);
return true;
}
- /* start fetch */
- ok = html_fetch_object(content, url, box, 0,
- content->available_width, 0, false, 0);
-
+ /* create a new iframe */
+ iframe = talloc(content, struct content_html_iframe);
+ if (!iframe) {
+ free(url);
+ return false;
+ }
+ iframe->box = box;
+ iframe->margin_width = -1;
+ iframe->margin_height = -1;
+ iframe->name = NULL;
+ iframe->url = talloc_strdup(content, url);
+ iframe->scrolling = SCROLLING_AUTO;
+ iframe->border = true;
+ iframe->next = content->data.html.iframe;
+ content->data.html.iframe = iframe;
+
+ /* fill in specified values */
+ if ((s = (char *) xmlGetProp(n,
+ (const xmlChar *) "name"))) {
+ iframe->name = talloc_strdup(content, s);
+ xmlFree(s);
+ }
+ if ((s = (char *) xmlGetProp(n,
+ (const xmlChar *) "frameborder"))) {
+ i = atoi(s);
+ iframe->border = (i != 0);
+ xmlFree(s);
+ }
+ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "bordercolor"))) {
+ unsigned int r, g, b;
+ if (s[0] == '#' && sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3)
+ iframe->border_colour = (b << 16) | (g << 8) | r;
+ else if (s[0] != '#')
+ iframe->border_colour = named_colour(s);
+ xmlFree(s);
+ }
+ if ((s = (char *) xmlGetProp(n,
+ (const xmlChar *) "scrolling"))) {
+ if (!strcasecmp(s, "yes"))
+ iframe->scrolling = SCROLLING_YES;
+ else if (!strcasecmp(s, "no"))
+ iframe->scrolling = SCROLLING_NO;
+ xmlFree(s);
+ }
+ if ((s = (char *) xmlGetProp(n,
+ (const xmlChar *) "marginwidth"))) {
+ iframe->margin_width = atoi(s);
+ xmlFree(s);
+ }
+ if ((s = (char *) xmlGetProp(n,
+ (const xmlChar *) "marginheight"))) {
+ iframe->margin_width = atoi(s);
+ xmlFree(s);
+ }
+
+ /* release temporary memory */
free(url);
- *convert_children = false;
+ /* box */
+ box->type = BOX_INLINE_BLOCK;
+ assert(box->style);
- return ok;
+ if (convert_children)
+ *convert_children = false;
+ return true;
}
@@ -1976,12 +2065,12 @@ bool box_input(BOX_SPECIAL_PARAMS)
if (!html_fetch_object(content, url,
box, image_types,
content->available_width,
- 1000, false, 0)) {
+ 1000, false)) {
free(url);
goto no_memory;
- }
- }
- free(url);
+ }
+ }
+ free(url);
}
} else {
@@ -2244,7 +2333,7 @@ no_memory:
* Add an option to a form select control (helper function for box_select()).
*
* \param control select containing the option
- * \param n xml element node for <option>
+ * \param n xml element node for <option>
* \return true on success, false on memory exhaustion
*/
@@ -2432,7 +2521,7 @@ bool box_embed(BOX_SPECIAL_PARAMS)
/* start fetch */
return html_fetch_object(content, params->data, box, 0,
- content->available_width, 1000, false, 0);
+ content->available_width, 1000, false);
}
/**
@@ -2443,7 +2532,7 @@ bool box_embed(BOX_SPECIAL_PARAMS)
/**
* Get the value of an XML element's attribute.
*
- * \param n xmlNode, of type XML_ELEMENT_NODE
+ * \param n xmlNode, of type XML_ELEMENT_NODE
* \param attribute name of attribute
* \param context talloc context for result buffer
* \param value updated to value, if the attribute is present
@@ -2471,8 +2560,8 @@ bool box_get_attribute(xmlNode *n, const char *attribute,
* Extract a URL from a relative link, handling junk like whitespace and
* attempting to read a real URL from "javascript:" links.
*
- * \param rel relative URL taken from page
- * \param base base for relative URLs
+ * \param rel relative URL taken from page
+ * \param base base for relative URLs
* \param result updated to target URL on heap, unchanged if extract failed
* \return true on success, false on memory exhaustion
*/
@@ -2537,24 +2626,23 @@ bool box_extract_link(const char *rel, const char *base, char **result)
/**
* Parse a multi-length-list, as defined by HTML 4.01.
*
- * \param s string to parse
+ * \param s string to parse
* \param count updated to number of entries
- * \param context talloc context block
* \return array of struct box_multi_length, or 0 on memory exhaustion
*/
-struct box_multi_length *box_parse_multi_lengths(const char *s,
- unsigned int *count, void *context)
+struct frame_dimension *box_parse_multi_lengths(const char *s,
+ unsigned int *count)
{
char *end;
unsigned int i, n;
- struct box_multi_length *length;
+ struct frame_dimension *length;
for (i = 0, n = 1; s[i]; i++)
if (s[i] == ',')
n++;
- length = talloc_array(context, struct box_multi_length, n);
+ length = calloc(n, sizeof(struct frame_dimension));
if (!length)
return NULL;
@@ -2566,9 +2654,15 @@ struct box_multi_length *box_parse_multi_lengths(const char *s,
length[i].value = 1;
s = end;
switch (*s) {
- case '%': length[i].type = LENGTH_PERCENT; break;
- case '*': length[i].type = LENGTH_RELATIVE; break;
- default: length[i].type = LENGTH_PX; break;
+ case '%':
+ length[i].unit = FRAME_DIMENSION_PERCENT;
+ break;
+ case '*':
+ length[i].unit = FRAME_DIMENSION_RELATIVE;
+ break;
+ default:
+ length[i].unit = FRAME_DIMENSION_PIXELS;
+ break;
}
while (*s && *s != ',')
s++;
diff --git a/render/html.c b/render/html.c
index ca95f2f0e..6af3e3932 100644
--- a/render/html.c
+++ b/render/html.c
@@ -53,8 +53,8 @@ static void html_object_failed(struct box *box, struct content *content,
static bool html_object_type_permitted(const content_type type,
const content_type *permitted_types);
static void html_object_refresh(void *p);
-static bool html_find_frame(struct content *c, const char *frame,
- struct content **page, unsigned int *i);
+static void html_destroy_frameset(struct content_html_frames *frameset);
+static void html_destroy_iframe(struct content_html_iframe *iframe);
/**
@@ -75,6 +75,7 @@ bool html_create(struct content *c, const char *params[])
html->encoding = 0;
html->getenc = true;
html->base_url = c->url;
+ html->base_target = NULL;
html->layout = 0;
html->background_colour = TRANSPARENT;
html->stylesheet_count = 0;
@@ -86,6 +87,8 @@ bool html_create(struct content *c, const char *params[])
html->forms = 0;
html->imagemaps = 0;
html->bw = 0;
+ html->frameset = 0;
+ html->iframe = 0;
html->page = 0;
html->index = 0;
html->box = 0;
@@ -494,6 +497,7 @@ bool html_meta_refresh(struct content *c, xmlNode *head)
bool html_head(struct content *c, xmlNode *head)
{
xmlNode *node;
+ xmlChar *s;
c->title = 0;
@@ -528,6 +532,21 @@ bool html_head(struct content *c, xmlNode *head)
}
xmlFree(href);
}
+ /* don't use the central values to ease freeing later on */
+ if ((s = xmlGetProp(node, (const xmlChar *) "target"))) {
+ if ((!strcasecmp(s, "_blank")) || (!strcasecmp(s, "_top")) ||
+ (!strcasecmp(s, "_parent")) ||
+ (!strcasecmp(s, "_self")) ||
+ ('a' <= s[0] && s[0] <= 'z') ||
+ ('A' <= s[0] && s[0] <= 'Z')) { /* [6.16] */
+ c->data.html.base_target = talloc_strdup(c, s);
+ if (!c->data.html.base_target) {
+ xmlFree(s);
+ return false;
+ }
+ }
+ xmlFree(s);
+ }
}
}
return true;
@@ -903,7 +922,7 @@ void html_convert_css_callback(content_msg msg, struct content *css,
bool html_fetch_object(struct content *c, char *url, struct box *box,
const content_type *permitted_types,
int available_width, int available_height,
- bool background, char *frame)
+ bool background)
{
unsigned int i = c->data.html.object_count;
struct content_html_object *object;
@@ -935,9 +954,6 @@ bool html_fetch_object(struct content *c, char *url, struct box *box,
c->data.html.object[i].permitted_types = permitted_types;
c->data.html.object[i].background = background;
c->data.html.object[i].content = c_fetch;
- c->data.html.object[i].frame = 0;
- if (frame)
- c->data.html.object[i].frame = talloc_strdup(c, frame);
c->data.html.object_count++;
c->active++;
@@ -1388,6 +1404,7 @@ void html_stop(struct content *c)
void html_reformat(struct content *c, int width, int height)
{
struct box *doc;
+
layout_document(c, width, height);
doc = c->data.html.layout;
@@ -1396,6 +1413,11 @@ void html_reformat(struct content *c, int width, int height)
c->height = doc->descendant_y1 +
doc->margin[TOP] + doc->margin[BOTTOM];
+
+ if ((c->data.html.frameset) && (c->data.html.bw))
+ browser_window_recalculate_frameset(c->data.html.bw);
+ if ((c->data.html.iframe) && (c->data.html.bw))
+ browser_window_recalculate_iframes(c->data.html.bw);
}
@@ -1418,6 +1440,25 @@ void html_destroy(struct content *c)
if (c->data.html.parser)
htmlFreeParserCtxt(c->data.html.parser);
+ /* Free base target */
+ if (c->data.html.base_target) {
+ talloc_free(c->data.html.base_target);
+ c->data.html.base_target = NULL;
+ }
+
+ /* Free frameset */
+ if (c->data.html.frameset) {
+ html_destroy_frameset(c->data.html.frameset);
+ talloc_free(c->data.html.frameset);
+ c->data.html.frameset = NULL;
+ }
+
+ /* Free iframes */
+ if (c->data.html.iframe) {
+ html_destroy_iframe(c->data.html.iframe);
+ c->data.html.iframe = NULL;
+ }
+
/* Free stylesheets */
if (c->data.html.stylesheet_count) {
for (i = 0; i != c->data.html.stylesheet_count; i++) {
@@ -1430,7 +1471,7 @@ void html_destroy(struct content *c)
}
talloc_free(c->data.html.working_stylesheet);
-
+
/*if (c->data.html.style)
css_free_style(c->data.html.style);*/
@@ -1447,6 +1488,48 @@ void html_destroy(struct content *c)
}
}
+void html_destroy_frameset(struct content_html_frames *frameset) {
+ int i;
+
+ if (frameset->name) {
+ talloc_free(frameset->name);
+ frameset->name = NULL;
+ }
+ if (frameset->url) {
+ talloc_free(frameset->url);
+ frameset->url = NULL;
+ }
+ if (frameset->children) {
+ for (i = 0; i < (frameset->rows * frameset->cols); i++) {
+ if (frameset->children[i].name) {
+ talloc_free(frameset->children[i].name);
+ frameset->children[i].name = NULL;
+ }
+ if (frameset->children[i].url) {
+ talloc_free(frameset->children[i].url);
+ frameset->children[i].url = NULL;
+ }
+ if (frameset->children[i].children)
+ html_destroy_frameset(&frameset->children[i]);
+ }
+ talloc_free(frameset->children);
+ frameset->children = NULL;
+ }
+}
+
+void html_destroy_iframe(struct content_html_iframe *iframe) {
+ struct content_html_iframe *next;
+ next = iframe;
+ while ((iframe = next) != NULL) {
+ next = iframe->next;
+ if (iframe->name)
+ talloc_free(iframe->name);
+ if (iframe->url)
+ talloc_free(iframe->url);
+ talloc_free(iframe);
+ }
+}
+
/**
* Handle a window containing a CONTENT_HTML being opened.
@@ -1471,6 +1554,11 @@ void html_open(struct content *c, struct browser_window *bw,
c->data.html.object[i].box,
c->data.html.object[i].box->object_params);
}
+
+ if (c->data.html.frameset)
+ browser_window_create_frameset(bw, c->data.html.frameset);
+ if (c->data.html.iframe)
+ browser_window_create_iframes(bw, c->data.html.iframe);
}
@@ -1491,87 +1579,3 @@ void html_close(struct content *c)
content_close(c->data.html.object[i].content);
}
}
-
-
-/**
- * Find the target frame for a link.
- *
- * \param c content containing the link, of type CONTENT_HTML
- * \param target target frame
- * \retval page updated to content containing target object, or 0 if the
- * target should replace the top-level content
- * \retval i updated to index of target object in page->data.html.object
- */
-
-void html_find_target(struct content *c, const char *target,
- struct content **page, unsigned int *i)
-{
- *page = 0;
-
- assert(c->type == CONTENT_HTML);
-
- if (!target) {
- /** \todo get target from <base target=...> */
- *page = c->data.html.page;
- *i = c->data.html.index;
- return;
- }
-
- if (target == TARGET_SELF) {
- *page = c->data.html.page;
- *i = c->data.html.index;
- return;
- } else if (target == TARGET_PARENT) {
- if (c->data.html.page && c->data.html.page->data.html.page) {
- *page = c->data.html.page->data.html.page;
- *i = c->data.html.page->data.html.index;
- }
- return;
- } else if (target == TARGET_TOP) {
- return;
- }
-
- /* recursively search for a frame named target, starting with the
- * top-level content in the frameset */
- while (c->data.html.page)
- c = c->data.html.page;
-
- html_find_frame(c, target, page, i);
-}
-
-
-/**
- * Recursively search a frameset for a frame.
- *
- * \param c frameset page, of type CONTENT_HTML
- * \param frame name of frame
- * \retval page updated to content containing the frame, if true returned
- * \retval i updated to index of target frame in page->data.html.object
- * \return true iff the frame was found
- */
-
-bool html_find_frame(struct content *c, const char *frame,
- struct content **page, unsigned int *i)
-{
- unsigned int j;
-
- assert(c->type == CONTENT_HTML);
-
- for (j = 0; j != c->data.html.object_count; j++) {
- if (c->data.html.object[j].frame &&
- !strcmp(c->data.html.object[j].frame, frame)) {
- *page = c;
- *i = j;
- return true;
- }
- if (c->data.html.object[j].content &&
- c->data.html.object[j].content->type ==
- CONTENT_HTML) {
- if (html_find_frame(c->data.html.object[j].content,
- frame, page, i))
- return true;
- }
- }
-
- return false;
-}
diff --git a/render/html.h b/render/html.h
index 8ad0a7742..4e19364e3 100644
--- a/render/html.h
+++ b/render/html.h
@@ -37,6 +37,22 @@ struct plotters;
extern char *default_stylesheet_url;
extern char *adblock_stylesheet_url;
+struct frame_dimension {
+ float value;
+ enum {
+ FRAME_DIMENSION_PIXELS, /* '100', '200' */
+ FRAME_DIMENSION_PERCENT, /* '5%', '20%' */
+ FRAME_DIMENSION_RELATIVE /* '*', '2*' */
+ } unit;
+};
+
+typedef enum {
+ SCROLLING_AUTO,
+ SCROLLING_YES,
+ SCROLLING_NO
+} frame_scrolling;
+
+
/** An object (<img>, <object>, etc.) in a CONTENT_HTML document. */
struct content_html_object {
char *url; /**< URL of this object. */
@@ -46,7 +62,44 @@ struct content_html_object {
* CONTENT_UNKNOWN, or 0 if any type is acceptable. */
const content_type *permitted_types;
bool background; /**< This object is a background image. */
- char *frame; /**< Name of frame, or 0 if not a frame. */
+};
+
+/** Frame tree (<frameset>, <frame>) */
+struct content_html_frames {
+ int cols; /** number of columns in frameset */
+ int rows; /** number of rows in frameset */
+
+ struct frame_dimension width; /** frame width */
+ struct frame_dimension height; /** frame width */
+ int margin_width; /** frame margin width */
+ int margin_height; /** frame margin height */
+
+ char *name; /** frame name (for targetting) */
+ char *url; /** frame url */
+
+ bool no_resize; /** frame is not resizable */
+ frame_scrolling scrolling; /** scrolling characteristics */
+ bool border; /** frame has a border */
+ colour border_colour; /** frame border colour */
+
+ struct content_html_frames *children; /** [cols * rows] children */
+};
+
+/** Inline frame list (<iframe>) */
+struct content_html_iframe {
+ struct box *box;
+
+ int margin_width; /** frame margin width */
+ int margin_height; /** frame margin height */
+
+ char *name; /** frame name (for targetting) */
+ char *url; /** frame url */
+
+ frame_scrolling scrolling; /** scrolling characteristics */
+ bool border; /** frame has a border */
+ colour border_colour; /** frame border colour */
+
+ struct content_html_iframe *next;
};
/** Data specific to CONTENT_HTML. */
@@ -63,6 +116,7 @@ struct content_html_data {
* wasn't specified in the Content-Type header. */
char *base_url; /**< Base URL (may be a copy of content->url). */
+ char *base_target; /**< Base target */
struct box *layout; /**< Box tree, or 0. */
colour background_colour; /**< Document background colour. */
@@ -87,6 +141,12 @@ struct content_html_data {
/** Browser window containing this document, or 0 if not open. */
struct browser_window *bw;
+ /** Frameset information */
+ struct content_html_frames *frameset;
+
+ /** Inline frame information */
+ struct content_html_iframe *iframe;
+
/** Content of type CONTENT_HTML containing this, or 0 if not an object
* within a page. */
struct content *page;
@@ -108,7 +168,7 @@ void html_destroy(struct content *c);
bool html_fetch_object(struct content *c, char *url, struct box *box,
const content_type *permitted_types,
int available_width, int available_height,
- bool background, char *frame);
+ bool background);
bool html_replace_object(struct content *c, unsigned int i, char *url,
char *post_urlenc,
struct form_successful_control *post_multipart);
@@ -117,8 +177,6 @@ void html_open(struct content *c, struct browser_window *bw,
struct content *page, unsigned int index, struct box *box,
struct object_params *params);
void html_close(struct content *c);
-void html_find_target(struct content *c, const char *target,
- struct content **page, unsigned int *i);
/* in render/html_redraw.c */
bool html_redraw(struct content *c, int x, int y,
diff --git a/riscos/configure/con_content.c b/riscos/configure/con_content.c
index f0636ac08..7ad1dd0f5 100644
--- a/riscos/configure/con_content.c
+++ b/riscos/configure/con_content.c
@@ -20,9 +20,10 @@
#define CONTENT_BLOCK_ADVERTISEMENTS 2
#define CONTENT_BLOCK_POPUPS 3
#define CONTENT_NO_PLUGINS 4
-#define CONTENT_DEFAULT_BUTTON 5
-#define CONTENT_CANCEL_BUTTON 6
-#define CONTENT_OK_BUTTON 7
+#define CONTENT_TARGET_BLANK 7
+#define CONTENT_DEFAULT_BUTTON 8
+#define CONTENT_CANCEL_BUTTON 9
+#define CONTENT_OK_BUTTON 10
static void ro_gui_options_content_default(wimp_pointer *pointer);
static bool ro_gui_options_content_ok(wimp_w w);
@@ -35,11 +36,14 @@ bool ro_gui_options_content_initialise(wimp_w w) {
option_block_popups);
ro_gui_set_icon_selected_state(w, CONTENT_NO_PLUGINS,
option_no_plugins);
+ ro_gui_set_icon_selected_state(w, CONTENT_TARGET_BLANK,
+ option_target_blank);
/* initialise all functions for a newly created window */
ro_gui_wimp_event_register_checkbox(w, CONTENT_BLOCK_ADVERTISEMENTS);
ro_gui_wimp_event_register_checkbox(w, CONTENT_BLOCK_POPUPS);
ro_gui_wimp_event_register_checkbox(w, CONTENT_NO_PLUGINS);
+ ro_gui_wimp_event_register_checkbox(w, CONTENT_TARGET_BLANK);
ro_gui_wimp_event_register_button(w, CONTENT_DEFAULT_BUTTON,
ro_gui_options_content_default);
ro_gui_wimp_event_register_cancel(w, CONTENT_CANCEL_BUTTON);
@@ -59,6 +63,8 @@ void ro_gui_options_content_default(wimp_pointer *pointer) {
false);
ro_gui_set_icon_selected_state(pointer->w, CONTENT_NO_PLUGINS,
false);
+ ro_gui_set_icon_selected_state(pointer->w, CONTENT_TARGET_BLANK,
+ true);
}
bool ro_gui_options_content_ok(wimp_w w) {
@@ -68,6 +74,8 @@ bool ro_gui_options_content_ok(wimp_w w) {
CONTENT_BLOCK_POPUPS);
option_no_plugins = ro_gui_get_icon_selected_state(w,
CONTENT_NO_PLUGINS);
+ option_target_blank = ro_gui_get_icon_selected_state(w,
+ CONTENT_TARGET_BLANK);
ro_gui_save_options();
return true;
diff --git a/riscos/gui.c b/riscos/gui.c
index 876bce7a6..6dfe2657a 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -156,7 +156,7 @@ static bool gui_track = false;
/** Handle of window which the pointer is over. */
static wimp_w gui_track_wimp_w;
/** Browser window which the pointer is over, or 0 if none. */
-static struct gui_window *gui_track_gui_window;
+struct gui_window *gui_track_gui_window;
/** Some windows have been resized, and should be reformatted. */
bool gui_reformat_pending = false;
@@ -727,10 +727,6 @@ void gui_init2(int argc, char** argv)
option_language);
}
-#ifdef WITH_KIOSK_BROWSING
- open_window = true;
-#endif
-
if (open_window)
browser_window_create(url, NULL, 0, true);
@@ -754,7 +750,7 @@ void gui_quit(void)
rufl_quit();
free(gui_sprites);
xwimp_close_down(task_handle);
- free(default_stylesheet_url);
+ free(default_stylesheet_url);
free(adblock_stylesheet_url);
xhourglass_off();
}
@@ -1008,6 +1004,7 @@ void ro_gui_null_reason_code(void)
case GUI_DRAG_SELECTION:
case GUI_DRAG_SCROLL:
+ case GUI_DRAG_FRAME:
assert(gui_track_gui_window);
ro_gui_window_mouse_at(gui_track_gui_window, &pointer);
break;
@@ -1168,6 +1165,7 @@ void ro_gui_pointer_leaving_window(wimp_leaving *leaving)
case GUI_DRAG_SELECTION:
case GUI_DRAG_SCROLL:
case GUI_DRAG_SAVE:
+ case GUI_DRAG_FRAME:
/* ignore Pointer_Leaving_Window event that the Wimp mysteriously
issues when a Wimp_DragBox drag operation is started */
break;
@@ -1186,10 +1184,20 @@ void ro_gui_pointer_leaving_window(wimp_leaving *leaving)
void ro_gui_pointer_entering_window(wimp_entering *entering)
{
- gui_track_wimp_w = entering->w;
- gui_track_gui_window = ro_gui_window_lookup(entering->w);
- gui_track = gui_track_gui_window || gui_track_wimp_w == history_window ||
- gui_track_wimp_w == dialog_url_complete;
+ switch (gui_current_drag_type) {
+ case GUI_DRAG_SELECTION:
+ case GUI_DRAG_SCROLL:
+ case GUI_DRAG_SAVE:
+ case GUI_DRAG_FRAME:
+ /* ignore entering new windows/frames */
+ break;
+ default:
+ gui_track_wimp_w = entering->w;
+ gui_track_gui_window = ro_gui_window_lookup(entering->w);
+ gui_track = gui_track_gui_window || gui_track_wimp_w == history_window ||
+ gui_track_wimp_w == dialog_url_complete;
+ break;
+ }
}
@@ -1284,6 +1292,10 @@ void ro_gui_drag_end(wimp_dragged *drag)
ro_gui_theme_toolbar_editor_drag_end(drag);
break;
+ case GUI_DRAG_FRAME:
+ ro_gui_window_frame_resize_end(gui_track_gui_window, drag);
+ break;
+
default:
assert(gui_current_drag_type == GUI_DRAG_NONE);
break;
@@ -1500,6 +1512,8 @@ void ro_msg_dataload(wimp_message *message)
g = ro_gui_window_lookup(message->data.data_xfer.w);
if (g) {
+ while (g->bw->parent)
+ g = g->bw->parent->window;
if (ro_gui_window_dataload(g, message))
return;
}
diff --git a/riscos/gui.h b/riscos/gui.h
index 7ffeb5194..de4866f3b 100644
--- a/riscos/gui.h
+++ b/riscos/gui.h
@@ -42,6 +42,7 @@ extern wimp_w dialog_info, dialog_saveas, dialog_zoom, dialog_pageinfo,
dialog_objinfo, dialog_tooltip, dialog_warning, dialog_openurl,
dialog_debug, dialog_folder, dialog_entry, dialog_url_complete,
dialog_search, dialog_print, dialog_theme_install;
+extern struct gui_window *gui_track_gui_window;
extern wimp_w current_menu_window;
extern bool current_menu_open;
extern wimp_menu *font_menu; /* font.c */
@@ -58,7 +59,7 @@ extern struct tree *hotlist_tree, *global_history_tree, *cookies_tree;
typedef enum { GUI_DRAG_NONE, GUI_DRAG_SELECTION, GUI_DRAG_DOWNLOAD_SAVE,
GUI_DRAG_SAVE, GUI_DRAG_SCROLL, GUI_DRAG_STATUS_RESIZE,
GUI_DRAG_TREE_SELECT, GUI_DRAG_TREE_MOVE,
- GUI_DRAG_TOOLBAR_CONFIG } gui_drag_type;
+ GUI_DRAG_TOOLBAR_CONFIG, GUI_DRAG_FRAME } gui_drag_type;
extern gui_drag_type gui_current_drag_type;
@@ -88,6 +89,8 @@ struct gui_window {
int throbtime; /**< Time of last throbber frame. */
int iconise_icon; /**< ID number of icon when window is iconised */
+
+ char validation[12]; /**< Validation string for colours */
/** Options. */
struct {
@@ -164,6 +167,7 @@ browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons);
bool ro_gui_shift_pressed(void);
bool ro_gui_ctrl_pressed(void);
void ro_gui_window_scroll_end(struct gui_window *g, wimp_dragged *drag);
+void ro_gui_window_frame_resize_end(struct gui_window *g, wimp_dragged *drag);
void ro_gui_window_set_scale(struct gui_window *g, float scale);
void ro_gui_window_iconise(struct gui_window *g,
wimp_full_message_window_info *wi);
diff --git a/riscos/theme.c b/riscos/theme.c
index 2c7f44f2b..f78337319 100644
--- a/riscos/theme.c
+++ b/riscos/theme.c
@@ -1375,6 +1375,7 @@ bool ro_gui_theme_process_toolbar(struct toolbar *toolbar, int width) {
int xeig, yeig;
os_coord pixel = {1, 1};
int top, bottom, right;
+ bool parent_hscroll;
/* calculate 1px in OS units */
ro_convert_pixels_to_os_units(&pixel, (os_mode)-1);
@@ -1411,7 +1412,7 @@ bool ro_gui_theme_process_toolbar(struct toolbar *toolbar, int width) {
warn_user("WimpError", error->errmess);
return false;
}
-
+ parent_hscroll = state.flags & wimp_WINDOW_HSCROLL;
height = state.visible.y1 - state.visible.y0 + 2;
/* We can't obscure the height of the scroll bar as we
@@ -1677,7 +1678,7 @@ bool ro_gui_theme_process_toolbar(struct toolbar *toolbar, int width) {
/* Open or close the window
*/
- if (!toolbar->display_status) {
+ if ((!toolbar->display_status) || (!parent_hscroll)) {
if (state.flags & wimp_WINDOW_OPEN)
xwimp_close_window(toolbar->status_handle);
} else {
diff --git a/riscos/window.c b/riscos/window.c
index 8386df8ee..2fd369665 100644
--- a/riscos/window.c
+++ b/riscos/window.c
@@ -120,6 +120,7 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
os_error *error;
bool open_centred = true;
struct gui_window *g;
+ struct browser_window *top;
g = malloc(sizeof *g);
if (!g) {
@@ -138,7 +139,21 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
/* Set the window position
*/
- if (clone && clone->window && option_window_size_clone) {
+ if (bw->parent) {
+ /* fill the parent window until it's reformatted */
+ state.w = clone->window->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ window.visible.x0 = 0;
+ window.visible.x1 = 64;
+ window.visible.y0 = 0;
+ window.visible.y1 = 64;
+ open_centred = false;
+ } else if (clone && clone->window && option_window_size_clone) {
state.w = clone->window->window;
error = xwimp_get_window_state(&state);
if (error) {
@@ -179,16 +194,10 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
/* Base how we define the window height/width
on the compile time options set */
-#ifdef WITH_KIOSK_BROWSING
- /* We're going fullscreen, forget the iconbar! */
- win_width = screen_width;
- win_height = screen_height;
-#else
win_width = screen_width * 3 / 4;
if (1600 < win_width)
win_width = 1600;
win_height = win_width * 3 / 4;
-#endif
window.visible.x0 = (screen_width - win_width) / 2;
window.visible.y0 = ((screen_height - win_height) / 2) +
@@ -203,31 +212,15 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
window.xscroll = 0;
window.yscroll = 0;
window.next = wimp_TOP;
-
- /* Base how we define the window characteristics
- on the compile time options set */
-#ifdef WITH_KIOSK_BROWSING
- window.flags = wimp_WINDOW_NEW_FORMAT |
- wimp_WINDOW_VSCROLL |
- wimp_WINDOW_HSCROLL |
- wimp_WINDOW_IGNORE_XEXTENT |
- wimp_WINDOW_IGNORE_YEXTENT |
- wimp_WINDOW_SCROLL_REPEAT;
-#else
- window.flags = wimp_WINDOW_MOVEABLE |
+
+ /* General flags for a non-movable, non-resizable, no-title bar window */
+ window.flags = wimp_WINDOW_MOVEABLE |
wimp_WINDOW_NEW_FORMAT |
- wimp_WINDOW_BACK_ICON |
- wimp_WINDOW_CLOSE_ICON |
- wimp_WINDOW_TITLE_ICON |
wimp_WINDOW_VSCROLL |
wimp_WINDOW_HSCROLL |
- wimp_WINDOW_SIZE_ICON |
- wimp_WINDOW_TOGGLE_ICON |
wimp_WINDOW_IGNORE_XEXTENT |
wimp_WINDOW_IGNORE_YEXTENT |
wimp_WINDOW_SCROLL_REPEAT;
-#endif
-
window.title_fg = wimp_COLOUR_BLACK;
window.title_bg = wimp_COLOUR_LIGHT_GREY;
window.work_fg = wimp_COLOUR_LIGHT_GREY;
@@ -252,6 +245,39 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
window.title_data.indirected_text.validation = (char *) -1;
window.title_data.indirected_text.size = 255;
window.icon_count = 0;
+
+ /* Add in flags for our window type */
+ switch (bw->browser_window_type) {
+ case BROWSER_WINDOW_FRAMESET:
+ window.flags &= ~(wimp_WINDOW_VSCROLL |
+ wimp_WINDOW_HSCROLL);
+ window.title_fg = 0xff;
+ break;
+ case BROWSER_WINDOW_FRAME:
+ case BROWSER_WINDOW_IFRAME:
+ if (bw->scrolling == SCROLLING_NO)
+ window.flags &= ~(wimp_WINDOW_VSCROLL |
+ wimp_WINDOW_HSCROLL);
+ if (!bw->border)
+ window.title_fg = 0xff;
+ else {
+ /* set the correct border colour */
+ unsigned int col;
+ col = bw->border_colour & 0xffffff;
+ sprintf(g->validation, "C%.6x", col);
+ window.extra_flags |= wimp_WINDOW_USE_TITLE_VALIDATION_STRING;
+ window.title_data.indirected_text.validation = g->validation;
+ }
+ break;
+ case BROWSER_WINDOW_NORMAL:
+ window.flags |= wimp_WINDOW_SIZE_ICON |
+ wimp_WINDOW_BACK_ICON |
+ wimp_WINDOW_CLOSE_ICON |
+ wimp_WINDOW_TITLE_ICON |
+ wimp_WINDOW_TOGGLE_ICON;
+ break;
+ }
+
if (open_centred) {
scroll_width = ro_get_vscroll_width(NULL);
window.visible.x0 -= scroll_width;
@@ -275,8 +301,12 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
/* Add in a toolbar
*/
- g->toolbar = ro_gui_theme_create_toolbar(NULL, THEME_BROWSER_TOOLBAR);
- ro_gui_theme_attach_toolbar(g->toolbar, g->window);
+ if (bw->browser_window_type == BROWSER_WINDOW_NORMAL) {
+ g->toolbar = ro_gui_theme_create_toolbar(NULL, THEME_BROWSER_TOOLBAR);
+ ro_gui_theme_attach_toolbar(g->toolbar, g->window);
+ } else {
+ g->toolbar = NULL;
+ }
/* Set the window options
*/
@@ -295,12 +325,22 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
return g;
}
- /* Open the window at the top of the stack
+ /* Open the window at the top/back of the stack
*/
- state.next = wimp_TOP;
+ if (bw->browser_window_type == BROWSER_WINDOW_NORMAL)
+ state.next = wimp_TOP;
+ else
+ state.next = wimp_HIDDEN;
+ if (bw->parent) {
+ top = browser_window_owner(bw);
+ error = xwimp_open_window_nested((wimp_open *)&state, top->window->window,
+ wimp_CHILD_LINKS_PARENT_WORK_AREA
+ << wimp_CHILD_XORIGIN_SHIFT |
+ wimp_CHILD_LINKS_PARENT_WORK_AREA
+ << wimp_CHILD_YORIGIN_SHIFT);
+ }
ro_gui_window_open(g, (wimp_open*)&state);
-
/* Set the caret position to the URL bar
*/
if (g->toolbar && g->toolbar->display_url) {
@@ -322,9 +362,9 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
/* and register event handlers */
ro_gui_wimp_event_register_keypress(g->window,
ro_gui_window_keypress);
- ro_gui_wimp_event_register_keypress(g->toolbar->toolbar_handle,
- ro_gui_window_keypress);
-
+ if (g->toolbar)
+ ro_gui_wimp_event_register_keypress(g->toolbar->toolbar_handle,
+ ro_gui_window_keypress);
ro_gui_wimp_event_register_mouse_click(g->window,
ro_gui_window_click);
@@ -352,7 +392,8 @@ void gui_window_destroy(struct gui_window *g)
if (g->next)
g->next->prev = g->prev;
- ro_gui_theme_destroy_toolbar(g->toolbar);
+ if (g->toolbar)
+ ro_gui_theme_destroy_toolbar(g->toolbar);
/* delete window */
error = xwimp_delete_window(g->window);
@@ -372,8 +413,16 @@ void gui_window_destroy(struct gui_window *g)
void ro_gui_window_quit(void)
{
- while (window_list)
- browser_window_destroy(window_list->bw);
+ struct gui_window *cur;
+
+ while (window_list) {
+ cur = window_list;
+ window_list = window_list->next;
+
+ /* framesets and iframes are destroyed by their parents */
+ if (!cur->bw->parent)
+ browser_window_destroy(cur->bw);
+ }
}
@@ -392,8 +441,8 @@ void gui_window_set_title(struct gui_window *g, const char *title)
assert(title);
if (g->option.scale != 1.0) {
- scale_disp = g->option.scale * 100;
- if (ABS((float)scale_disp - g->option.scale * 100) >= 0.05)
+ scale_disp = g->option.scale * 100;
+ if (ABS((float)scale_disp - g->option.scale * 100) >= 0.05)
snprintf(g->title, sizeof g->title, "%s (%.1f%%)", title,
g->option.scale * 100);
else
@@ -402,7 +451,9 @@ void gui_window_set_title(struct gui_window *g, const char *title)
strncpy(g->title, title, sizeof g->title);
}
- ro_gui_set_window_title(g->window, g->title);
+ /* only top-level parents have titlebars */
+ if (!g->bw->parent)
+ ro_gui_set_window_title(g->window, g->title);
}
@@ -415,9 +466,9 @@ void gui_window_set_title(struct gui_window *g, const char *title)
void gui_window_save_as_link(struct gui_window *g, struct content *c)
{
- if (!c)
- return;
- ro_gui_save_prepare(GUI_SAVE_LINK_URL, c);
+ if (!c)
+ return;
+ ro_gui_save_prepare(GUI_SAVE_LINK_URL, c);
ro_gui_dialog_open_persistent(g->window, dialog_saveas, true);
}
@@ -507,8 +558,8 @@ void ro_gui_window_redraw(struct gui_window *g, wimp_draw *redraw)
/* Handle no content quickly
*/
if (!c) {
- ro_gui_user_redraw(redraw, true, os_COLOUR_WHITE);
- return;
+ ro_gui_user_redraw(redraw, true, os_COLOUR_WHITE);
+ return;
}
plot = ro_plotters;
@@ -547,8 +598,8 @@ void ro_gui_window_redraw(struct gui_window *g, wimp_draw *redraw)
if (knockout) {
knockout_plot_start(&plot);
- plot.clip(clip_x0, clip_y0, clip_x1, clip_y1);
- plot.clg(0x00ffffff);
+ plot.clip(clip_x0, clip_y0, clip_x1, clip_y1);
+ plot.clg(0x00ffffff);
}
content_redraw(c, 0, 0,
@@ -599,10 +650,10 @@ void ro_gui_window_update_boxes(void) {
const union content_msg_data *data;
for (cur = pending_updates; cur != NULL; cur = cur->next) {
- g = cur->g;
- c = g->bw->current_content;
- data = &cur->data;
- use_buffer = cur->use_buffer;
+ g = cur->g;
+ c = g->bw->current_content;
+ data = &cur->data;
+ use_buffer = cur->use_buffer;
if (!c)
continue;
@@ -704,9 +755,9 @@ void ro_gui_window_update_boxes(void) {
current_redraw_browser = NULL;
}
while (pending_updates) {
- cur = pending_updates;
- pending_updates = pending_updates->next;
- free(cur);
+ cur = pending_updates;
+ pending_updates = pending_updates->next;
+ free(cur);
}
}
@@ -738,24 +789,24 @@ void gui_window_update_box(struct gui_window *g,
/* try to optimise buffered redraws */
if (use_buffer) {
for (cur = pending_updates; cur != NULL; cur = cur->next) {
- if ((cur->g != g) || (!cur->use_buffer))
- continue;
- if ((((cur->x0 - x1) < MARGIN) || ((cur->x1 - x0) < MARGIN)) &&
- (((cur->y0 - y1) < MARGIN) || ((cur->y1 - y0) < MARGIN))) {
- cur->x0 = min(cur->x0, x0);
- cur->y0 = min(cur->y0, y0);
- cur->x1 = max(cur->x1, x1);
- cur->y1 = max(cur->y1, y1);
- return;
- }
-
- }
+ if ((cur->g != g) || (!cur->use_buffer))
+ continue;
+ if ((((cur->x0 - x1) < MARGIN) || ((cur->x1 - x0) < MARGIN)) &&
+ (((cur->y0 - y1) < MARGIN) || ((cur->y1 - y0) < MARGIN))) {
+ cur->x0 = min(cur->x0, x0);
+ cur->y0 = min(cur->y0, y0);
+ cur->x1 = max(cur->x1, x1);
+ cur->y1 = max(cur->y1, y1);
+ return;
+ }
+
+ }
}
cur = malloc(sizeof(struct update_box));
if (!cur) {
- LOG(("No memory for malloc."));
- warn_user("NoMemory", 0);
- return;
+ LOG(("No memory for malloc."));
+ warn_user("NoMemory", 0);
+ return;
}
cur->x0 = x0;
cur->y0 = y0;
@@ -843,9 +894,9 @@ void gui_window_set_scroll(struct gui_window *g, int sx, int sy)
*
* \param g gui_window to scroll
* \param x0 left point to ensure visible
- * \param y0 top-left point to ensure visible
- * \param x1 left point to ensure visible
- * \param y1 top-left point to ensure visible
+ * \param y0 bottom point to ensure visible
+ * \param x1 right point to ensure visible
+ * \param y1 top point to ensure visible
*/
void gui_window_scroll_visible(struct gui_window *g, int x0, int y0, int x1, int y1)
{
@@ -868,7 +919,7 @@ void gui_window_scroll_visible(struct gui_window *g, int x0, int y0, int x1, int
}
if (g->toolbar)
- toolbar_height = ro_gui_theme_toolbar_full_height(g->toolbar);
+ toolbar_height = ro_gui_theme_toolbar_full_height(g->toolbar);
x0 = x0 * 2 * g->option.scale;
y0 = y0 * 2 * g->option.scale;
@@ -895,26 +946,26 @@ void gui_window_scroll_visible(struct gui_window *g, int x0, int y0, int x1, int
/* try to give a SCROLL_VISIBLE_PADDING border of space around us */
padding_available = (width - x1 + x0) / 2;
if (padding_available > 0) {
- if (padding_available > SCROLL_VISIBLE_PADDING)
- padding_available = SCROLL_VISIBLE_PADDING;
- correction = (cx0 + width - x1);
- if (correction < padding_available)
- cx0 += padding_available;
- correction = (x0 - cx0);
- if (correction < padding_available)
- cx0 -= padding_available;
+ if (padding_available > SCROLL_VISIBLE_PADDING)
+ padding_available = SCROLL_VISIBLE_PADDING;
+ correction = (cx0 + width - x1);
+ if (correction < padding_available)
+ cx0 += padding_available;
+ correction = (x0 - cx0);
+ if (correction < padding_available)
+ cx0 -= padding_available;
}
padding_available = (height - y1 + y0) / 2;
LOG(("Padding available: %i", padding_available));
if (padding_available > 0) {
- if (padding_available > SCROLL_VISIBLE_PADDING)
- padding_available = SCROLL_VISIBLE_PADDING;
- correction = (cy0 + height - y1);
- if (correction < padding_available)
- cy0 += padding_available;
- correction = (y0 - cy0);
- if (correction < padding_available)
- cy0 -= padding_available;
+ if (padding_available > SCROLL_VISIBLE_PADDING)
+ padding_available = SCROLL_VISIBLE_PADDING;
+ correction = (cy0 + height - y1);
+ if (correction < padding_available)
+ cy0 += padding_available;
+ correction = (y0 - cy0);
+ if (correction < padding_available)
+ cy0 -= padding_available;
}
state.xscroll = cx0;
@@ -924,7 +975,128 @@ void gui_window_scroll_visible(struct gui_window *g, int x0, int y0, int x1, int
/**
- * Find the current width of a browser window.
+ * Opens a frame at a specified position.
+ *
+ * \param g child gui_window to open
+ * \param x0 left point to open at
+ * \param y0 bottom point to open at
+ * \param x1 right point to open at
+ * \param y1 top point to open at
+ */
+void gui_window_position_frame(struct gui_window *g, int x0, int y0, int x1, int y1)
+{
+ wimp_window_state state;
+ os_error *error;
+ int px0, py1;
+ int toolbar_height = 0;
+ struct browser_window *bw;
+ struct browser_window *parent;
+ struct browser_window *top;
+
+ assert(g);
+ bw = g->bw;
+ assert(bw);
+ parent = bw->parent;
+ assert(parent);
+ top = browser_window_owner(bw);
+
+ /* store position for children */
+ if (parent->browser_window_type == BROWSER_WINDOW_IFRAME) {
+ x0 = bw->x0 = x0;
+ y0 = bw->y0 = y0;
+ x1 = bw->x1 = x1;
+ y1 = bw->y1 = y1;
+ } else {
+ x0 = bw->x0 = parent->x0 + x0;
+ y0 = bw->y0 = parent->y0 + y0;
+ x1 = bw->x1 = parent->x0 + x1;
+ y1 = bw->y1 = parent->y0 + y1;
+ }
+
+ /* get the position of the top level window */
+ state.w = top->window->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+ if (top->window->toolbar)
+ toolbar_height = ro_gui_theme_toolbar_full_height(top->window->toolbar);
+ px0 = state.visible.x0;
+ py1 = state.visible.y1 - toolbar_height;
+
+ /* get our current window state */
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+ if (!g->bw->border) {
+ x0 -= 1;
+ y0 -= 1;
+ x1 += 1;
+ y1 += 1;
+ }
+
+ x1 *= 2;
+ y1 *= 2;
+
+ /* scrollbars must go inside */
+ if (state.flags & wimp_WINDOW_HSCROLL) {
+ y1 -= ro_get_hscroll_height(NULL);
+ if (g->bw->border)
+ y1 += 2;
+ }
+ if (state.flags & wimp_WINDOW_VSCROLL) {
+ x1 -= ro_get_vscroll_width(NULL);
+ if (g->bw->border)
+ x1 += 2;
+ }
+ state.visible.x0 = px0 + x0 * 2;
+ state.visible.y0 = py1 - y1;
+ state.visible.x1 = px0 + x1;
+ state.visible.y1 = py1 - y0 * 2;
+
+ ro_gui_window_open(g, (wimp_open *)&state);
+}
+
+
+/**
+ * Find the current unscaled dimensions of a browser window's content area.
+ *
+ * \param g gui_window to measure
+ */
+
+void gui_window_get_dimensions(struct gui_window *g, int *width, int *height)
+{
+ wimp_window_state state;
+ os_error *error;
+
+ /* get the dimensions */
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ *width = 0;
+ *height = 0;
+ return;
+ }
+
+ *width = (state.visible.x1 - state.visible.x0) / 2;
+ *height = (state.visible.y1 - state.visible.y0 - (g->toolbar ?
+ ro_gui_theme_toolbar_full_height(g->toolbar) : 0)) / 2;
+}
+
+
+/**
+ * Find the current scaled width of a browser window.
*
* \param g gui_window to measure
* \return width of window
@@ -948,7 +1120,7 @@ int gui_window_get_width(struct gui_window *g)
/**
- * Find the current height of a browser window.
+ * Find the current scaled height of a browser window.
*
* \param g gui_window to measure
* \return height of window
@@ -974,23 +1146,30 @@ int gui_window_get_height(struct gui_window *g)
/**
- * Set the extent of the inside of a browser window.
+ * Update the extent of the inside of a browser window to that of the current content.
*
* \param g gui_window to resize
- * \param width new extent
- * \param height new extent
*/
-void gui_window_set_extent(struct gui_window *g, int width, int height)
+void gui_window_update_extent(struct gui_window *g)
{
- os_box extent = { 0, 0, 0, 0 };
- wimp_window_state state;
- int toolbar_height = 0;
- os_error *error;
+ ro_gui_window_update_dimensions(g, 0);
+}
- width *= 2 * g->option.scale;
- height *= 2 * g->option.scale;
+/**
+ * Forces the windows extent to be updated
+ *
+ * /param g the gui window to update
+ * /param yscroll an amount to scroll the vertical scroll bar by
+ */
+void ro_gui_window_update_dimensions(struct gui_window *g, int yscroll) {
+ os_error *error;
+ wimp_window_state state;
+ bool update;
+ unsigned int flags;
+
+ if (!g) return;
state.w = g->window;
error = xwimp_get_window_state(&state);
if (error) {
@@ -999,33 +1178,24 @@ void gui_window_set_extent(struct gui_window *g, int width, int height)
warn_user("WimpError", error->errmess);
return;
}
-
- /* account for toolbar height, if present */
- if (g->toolbar)
- toolbar_height = ro_gui_theme_toolbar_full_height(g->toolbar);
-
- if (width < state.visible.x1 - state.visible.x0)
- width = state.visible.x1 - state.visible.x0;
- if (height < state.visible.y1 - state.visible.y0 - toolbar_height)
- height = state.visible.y1 - state.visible.y0 - toolbar_height;
-
- extent.y0 = -height;
- extent.x1 = width;
- extent.y1 = toolbar_height;
- error = xwimp_set_extent(g->window, &extent);
+ state.yscroll -= yscroll;
+ g->old_height = -1;
+
+ /* only allow a further reformat if we've gained/lost scrollbars */
+ flags = state.flags & (wimp_WINDOW_HSCROLL | wimp_WINDOW_VSCROLL);
+ update = g->reformat_pending;
+ ro_gui_window_open(g, (wimp_open *)&state);
+
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
if (error) {
- LOG(("xwimp_set_extent: 0x%x: %s",
+ LOG(("xwimp_get_window_state: 0x%x: %s",
error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
return;
}
-
- error = xwimp_open_window((wimp_open *) &state);
- if (error) {
- LOG(("xwimp_open_window: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("WimpError", error->errmess);
- }
+ if (flags == (state.flags & (wimp_WINDOW_HSCROLL | wimp_WINDOW_VSCROLL)))
+ g->reformat_pending = update;
}
@@ -1096,7 +1266,7 @@ void gui_window_set_url(struct gui_window *g, const char *url)
/**
* Launch a new url in the given window.
*
- * \param g gui_window to update
+ * \param g gui_window to update
* \param url url to be launched
*/
@@ -1174,31 +1344,6 @@ void ro_gui_window_update_theme(void) {
}
}
-
-/**
- * Forces the windows extent to be updated
- *
- * /param g the gui window to update
- * /param yscroll an amount to scroll the vertical scroll bar by
- */
-void ro_gui_window_update_dimensions(struct gui_window *g, int yscroll) {
- os_error *error;
- wimp_window_state state;
- if (!g) return;
- state.w = g->window;
- error = xwimp_get_window_state(&state);
- if (error) {
- LOG(("xwimp_get_window_state: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("WimpError", error->errmess);
- return;
- }
- state.yscroll -= yscroll;
- g->old_height = -1;
- ro_gui_window_open(g, (wimp_open *)&state);
-/* gui_window_redraw_window(g); */
-}
-
/**
* Open a window using the given wimp_open, handling toolbars and resizing.
*/
@@ -1210,13 +1355,13 @@ void ro_gui_window_open(struct gui_window *g, wimp_open *open)
int toolbar_height = 0;
struct content *content;
wimp_window_state state;
- bool toggle_hack = false;
- int screen_height, screen_width;
os_error *error;
int key_down = 0;
- int inset = 0;
- int iconbar_cmos = 0;
- bool iconbar_clear;
+ wimp_w parent;
+ bits linkage;
+ int size;
+ bool no_vscroll, no_hscroll;
+ int fheight, fwidth;
if (open->next == wimp_TOP && g->iconise_icon >= 0) {
/* window is no longer iconised, release its sprite number */
@@ -1226,61 +1371,121 @@ void ro_gui_window_open(struct gui_window *g, wimp_open *open)
content = g->bw->current_content;
- /* check for toggle to full size so we can force to full height for short contents */
+ /* get the current flags/nesting state */
state.w = g->window;
- error = xwimp_get_window_state(&state);
+ error = xwimp_get_window_state_and_nesting(&state, &parent, &linkage);
if (error) {
LOG(("xwimp_get_window_state: 0x%x: %s",
error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
return;
}
- if ((state.flags & wimp_WINDOW_TOGGLED) && // bit 19
- (state.flags & wimp_WINDOW_BOUNDED_ONCE) && // bit 21
- !(state.flags & wimp_WINDOW_FULL_SIZE)) { // not bit 18
- ro_gui_screen_size(&screen_width, &screen_height);
- /* i can see no way of easily discovering if we were the result of a shift-
- * toggle as wimp_WINDOW_PARTIAL_SIZE does not seem to be what we need. As
- * such we do the really horrible thing of testing for Shift directly and
- * decreasing the value accordingly. Yuck. */
- xosbyte1(osbyte_SCAN_KEYBOARD, 0 ^ 0x80, 0, &key_down);
- iconbar_clear = (key_down != 0);
- xosbyte2(osbyte_READ_CMOS, 28, 0, &iconbar_cmos);
- if (iconbar_cmos & (1 << 4))
- iconbar_clear = !iconbar_clear;
- if (iconbar_clear)
- inset = 160 + ro_get_hscroll_height(0);
- if ((content->height * 2 * g->option.scale) < screen_height - inset) {
- open->visible.y0 = inset;
- open->visible.y1 = screen_height;
- height = screen_height - inset;
- toggle_hack = true;
- }
- }
/* account for toolbar height, if present */
if (g->toolbar)
toolbar_height = ro_gui_theme_toolbar_full_height(g->toolbar);
height -= toolbar_height;
+
+ /* work with the state from now on so we can modify flags */
+ state.visible.x0 = open->visible.x0;
+ state.visible.y0 = open->visible.y0;
+ state.visible.x1 = open->visible.x1;
+ state.visible.y1 = open->visible.y1;
+ state.xscroll = open->xscroll;
+ state.yscroll = open->yscroll;
+ state.next = open->next;
+
+ /* frameset windows shouldn't be shown */
+ if ((g->bw->parent) && (g->bw->children))
+ state.next = wimp_HIDDEN;
+
+ /* handle 'auto' scroll bars' and non-fitting scrollbar removal */
+ if ((g->bw->scrolling == SCROLLING_AUTO) || (g->bw->scrolling == SCROLLING_YES)) {
+ /* windows lose scrollbars when containing a frameset */
+ no_hscroll = (g->bw->children &&
+ (g->bw->browser_window_type != BROWSER_WINDOW_NORMAL));
+ no_vscroll = g->bw->children;
+
+ /* hscroll */
+ size = ro_get_hscroll_height(NULL);
+ if (g->bw->border)
+ size -= 2;
+ fheight = height;
+ if (state.flags & wimp_WINDOW_HSCROLL)
+ fheight += size;
+ if ((!no_hscroll) &&
+ ((fheight > size) && ((g->bw->scrolling == SCROLLING_YES) ||
+ (content && width < content->width * 2 * g->option.scale)))) {
+ if (!(state.flags & wimp_WINDOW_HSCROLL)) {
+ height -= size;
+ state.visible.y0 += size;
+ if (content) {
+ g->reformat_pending = true;
+ gui_reformat_pending = true;
+ }
+ }
+ state.flags |= wimp_WINDOW_HSCROLL;
+ } else {
+ if (state.flags & wimp_WINDOW_HSCROLL) {
+ height += size;
+ state.visible.y0 -= size;
+ if (content) {
+ g->reformat_pending = true;
+ gui_reformat_pending = true;
+ }
+ }
+ state.flags &= ~wimp_WINDOW_HSCROLL;
+ }
- /* The height should be no less than the content height
- */
- if (content && height < content->height * 2 * g->option.scale)
- height = content->height * 2 * g->option.scale;
+ /* vscroll */
+ size = ro_get_vscroll_width(NULL);
+ if (g->bw->border)
+ size -= 2;
+ fwidth = width;
+ if (state.flags & wimp_WINDOW_VSCROLL)
+ fwidth += size;
+ if ((!no_vscroll) &&
+ ((fwidth >= size) && ((g->bw->scrolling == SCROLLING_YES) ||
+ (content && height < content->height * 2 * g->option.scale)))) {
+ if (!(state.flags & wimp_WINDOW_VSCROLL)) {
+ width -= size;
+ state.visible.x1 -= size;
+ if (content) {
+ g->reformat_pending = true;
+ gui_reformat_pending = true;
+ }
+ }
+ state.flags |= wimp_WINDOW_VSCROLL;
+ } else {
+ if (state.flags & wimp_WINDOW_VSCROLL) {
+ width += size;
+ state.visible.x1 += size;
+ if (content) {
+ g->reformat_pending = true;
+ gui_reformat_pending = true;
+ }
+ }
+ state.flags &= ~wimp_WINDOW_VSCROLL;
+ }
+ }
/* change extent if necessary */
if (g->old_width != width || g->old_height != height) {
- if (content && g->old_width != width) {
- xosbyte1(osbyte_SCAN_KEYBOARD, 1 ^ 0x80, 0, &key_down);
- if (key_down)
- g->option.scale = (g->option.scale * width) / g->old_width;
+ if (content) {
+ if (g->old_width != width) {
+ xosbyte1(osbyte_SCAN_KEYBOARD, 1 ^ 0x80, 0, &key_down);
+ if (key_down)
+ g->option.scale = (g->option.scale * width) / g->old_width;
+ };
g->reformat_pending = true;
gui_reformat_pending = true;
}
g->old_width = width;
g->old_height = height;
-
+
+ if (content && height < content->height * 2 * g->option.scale)
+ height = content->height * 2 * g->option.scale;
if (content && width < content->width * 2 * g->option.scale)
width = content->width * 2 * g->option.scale;
os_box extent = { 0, -height, width, toolbar_height };
@@ -1295,9 +1500,9 @@ void ro_gui_window_open(struct gui_window *g, wimp_open *open)
}
/* first resize stops any flickering by making the URL window on top */
- ro_gui_url_complete_resize(g, open);
+ ro_gui_url_complete_resize(g, (wimp_open *)&state);
- error = xwimp_open_window(open);
+ error = xwimp_open_window_nested_with_flags(&state, parent, linkage);
if (error) {
LOG(("xwimp_open_window: 0x%x: %s",
error->errnum, error->errmess));
@@ -1305,26 +1510,6 @@ void ro_gui_window_open(struct gui_window *g, wimp_open *open)
return;
}
- /* update extent to actual size if toggled */
- if (toggle_hack) {
- width = open->visible.x1 - open->visible.x0;
- height = open->visible.y1 - open->visible.y0 - toolbar_height;
- if (content && height < content->height * 2 * g->option.scale)
- height = content->height * 2 * g->option.scale;
- {
- os_box extent = { 0, -height, width, toolbar_height };
- error = xwimp_set_extent(g->window, &extent);
- if (error) {
- LOG(("xwimp_set_extent: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("WimpError", error->errmess);
- return;
- }
- }
- g->old_width = width;
- g->old_height = height;
- }
-
if (g->toolbar) {
ro_gui_theme_process_toolbar(g->toolbar, -1);
/* second resize updates to the new URL bar width */
@@ -1340,25 +1525,31 @@ void ro_gui_window_open(struct gui_window *g, wimp_open *open)
void ro_gui_throb(void)
{
os_t t;
- struct gui_window *g;
+ struct gui_window *g, *top_g;
+ struct browser_window *top;
char throb_buf[12];
xos_read_monotonic_time(&t);
for (g = window_list; g; g = g->next) {
- if (!g->bw->throbbing || !g->toolbar || !g->toolbar->display_throbber ||
- !g->toolbar->descriptor ||!g->toolbar->descriptor->theme ||
- (t < g->throbtime + 10))
+ if (!g->bw->throbbing)
continue;
- g->throbtime = t;
- g->throbber++;
- if (g->toolbar->descriptor->theme->throbber_frames < g->throbber)
- g->throbber = 1;
- sprintf(throb_buf, "throbber%i", g->throbber);
- ro_gui_set_icon_string(g->toolbar->toolbar_handle,
+ for (top = g->bw; top->parent; top = top->parent);
+ top_g = top->window;
+ if (!top_g->toolbar || !top_g->toolbar->display_throbber ||
+ !top_g->toolbar->descriptor ||
+ !top_g->toolbar->descriptor->theme ||
+ (t < top_g->throbtime + 10))
+ continue;
+ top_g->throbtime = t;
+ top_g->throbber++;
+ if (top_g->toolbar->descriptor->theme->throbber_frames < top_g->throbber)
+ top_g->throbber = 1;
+ sprintf(throb_buf, "throbber%i", top_g->throbber);
+ ro_gui_set_icon_string(top_g->toolbar->toolbar_handle,
ICON_TOOLBAR_THROBBER, throb_buf);
- if (g->toolbar->descriptor->throbber_redraw)
- ro_gui_force_redraw_icon(g->toolbar->toolbar_handle,
+ if (top_g->toolbar->descriptor->throbber_redraw)
+ ro_gui_force_redraw_icon(top_g->toolbar->toolbar_handle,
ICON_TOOLBAR_THROBBER);
}
}
@@ -1491,11 +1682,11 @@ bool ro_gui_toolbar_click(wimp_pointer *pointer)
if (pointer->buttons == wimp_CLICK_ADJUST) {
new_bw = browser_window_create(NULL,
g->bw, NULL, false);
- ro_gui_menu_handle_action(new_bw->window->window,
- BROWSER_NAVIGATE_BACK, true);
+ ro_gui_menu_handle_action(new_bw->window->window,
+ BROWSER_NAVIGATE_BACK, true);
} else {
- ro_gui_menu_handle_action(g->window,
- BROWSER_NAVIGATE_BACK, true);
+ ro_gui_menu_handle_action(g->window,
+ BROWSER_NAVIGATE_BACK, true);
}
break;
@@ -1503,39 +1694,39 @@ bool ro_gui_toolbar_click(wimp_pointer *pointer)
if (pointer->buttons == wimp_CLICK_ADJUST) {
new_bw = browser_window_create(NULL,
g->bw, NULL, false);
- ro_gui_menu_handle_action(new_bw->window->window,
- BROWSER_NAVIGATE_FORWARD, true);
+ ro_gui_menu_handle_action(new_bw->window->window,
+ BROWSER_NAVIGATE_FORWARD, true);
} else {
- ro_gui_menu_handle_action(g->window,
- BROWSER_NAVIGATE_FORWARD, true);
- }
+ ro_gui_menu_handle_action(g->window,
+ BROWSER_NAVIGATE_FORWARD, true);
+ }
break;
case ICON_TOOLBAR_STOP:
- ro_gui_menu_handle_action(g->window,
- BROWSER_NAVIGATE_STOP, true);
+ ro_gui_menu_handle_action(g->window,
+ BROWSER_NAVIGATE_STOP, true);
break;
case ICON_TOOLBAR_RELOAD:
if (pointer->buttons == wimp_CLICK_SELECT)
- ro_gui_menu_handle_action(g->window,
- BROWSER_NAVIGATE_RELOAD, true);
+ ro_gui_menu_handle_action(g->window,
+ BROWSER_NAVIGATE_RELOAD, true);
else if (pointer->buttons == wimp_CLICK_ADJUST)
- ro_gui_menu_handle_action(g->window,
- BROWSER_NAVIGATE_RELOAD_ALL, true);
+ ro_gui_menu_handle_action(g->window,
+ BROWSER_NAVIGATE_RELOAD_ALL, true);
break;
case ICON_TOOLBAR_HISTORY:
if (pointer->buttons == wimp_CLICK_SELECT)
- ro_gui_menu_handle_action(g->window,
- HISTORY_SHOW_LOCAL, true);
+ ro_gui_menu_handle_action(g->window,
+ HISTORY_SHOW_LOCAL, true);
else
- ro_gui_menu_handle_action(g->window,
- HISTORY_SHOW_GLOBAL, true);
+ ro_gui_menu_handle_action(g->window,
+ HISTORY_SHOW_GLOBAL, true);
break;
case ICON_TOOLBAR_HOME:
- ro_gui_menu_handle_action(g->window,
- BROWSER_NAVIGATE_HOME, true);
+ ro_gui_menu_handle_action(g->window,
+ BROWSER_NAVIGATE_HOME, true);
break;
#ifdef WITH_SEARCH
case ICON_TOOLBAR_SEARCH:
@@ -1566,22 +1757,22 @@ bool ro_gui_toolbar_click(wimp_pointer *pointer)
BROWSER_SAVE, true);
break;
case ICON_TOOLBAR_PRINT:
- ro_gui_menu_handle_action(g->window,
- BROWSER_PRINT, true);
+ ro_gui_menu_handle_action(g->window,
+ BROWSER_PRINT, true);
break;
case ICON_TOOLBAR_UP:
if (pointer->buttons == wimp_CLICK_ADJUST) {
- if (g->bw && g->bw->current_content) {
+ if (g->bw && g->bw->current_content) {
new_bw = browser_window_create(NULL,
g->bw, NULL, false);
- /* do it without loading the content into the new window */
- ro_gui_window_navigate_up(new_bw->window,
- g->bw->current_content->url);
- }
+ /* do it without loading the content into the new window */
+ ro_gui_window_navigate_up(new_bw->window,
+ g->bw->current_content->url);
+ }
} else {
- ro_gui_menu_handle_action(g->window,
- BROWSER_NAVIGATE_UP, true);
- }
+ ro_gui_menu_handle_action(g->window,
+ BROWSER_NAVIGATE_UP, true);
+ }
break;
case ICON_TOOLBAR_URL:
if (pointer->buttons & (wimp_DRAG_SELECT | wimp_DRAG_ADJUST)) {
@@ -1618,7 +1809,7 @@ bool ro_gui_toolbar_click(wimp_pointer *pointer)
bool ro_gui_status_click(wimp_pointer *pointer)
{
- struct gui_window *g = ro_gui_status_lookup(pointer->w);
+ struct gui_window *g = ro_gui_status_lookup(pointer->w);
wimp_drag drag;
os_error *error;
@@ -1710,7 +1901,7 @@ bool ro_gui_window_click(wimp_pointer *pointer)
void gui_window_start_throbber(struct gui_window *g)
{
- ro_gui_menu_objects_moved();
+ ro_gui_menu_objects_moved();
ro_gui_prepare_navigate(g);
xos_read_monotonic_time(&g->throbtime);
g->throbber = 0;
@@ -1860,12 +2051,12 @@ bool ro_gui_window_keypress(wimp_key *key)
c = KEY_DELETE_RIGHT;
break;
case wimp_KEY_CONTROL | wimp_KEY_RIGHT: c = KEY_LINE_END; break;
- case wimp_KEY_CONTROL | wimp_KEY_UP: c = KEY_TEXT_START; break;
+ case wimp_KEY_CONTROL | wimp_KEY_UP: c = KEY_TEXT_START; break;
case wimp_KEY_CONTROL | wimp_KEY_DOWN: c = KEY_TEXT_END; break;
- case wimp_KEY_SHIFT | wimp_KEY_LEFT: c = KEY_WORD_LEFT ; break;
- case wimp_KEY_SHIFT | wimp_KEY_RIGHT: c = KEY_WORD_RIGHT; break;
- case wimp_KEY_SHIFT | wimp_KEY_UP: c = KEY_PAGE_UP; break;
- case wimp_KEY_SHIFT | wimp_KEY_DOWN: c = KEY_PAGE_DOWN; break;
+ case wimp_KEY_SHIFT | wimp_KEY_LEFT: c = KEY_WORD_LEFT ; break;
+ case wimp_KEY_SHIFT | wimp_KEY_RIGHT: c = KEY_WORD_RIGHT; break;
+ case wimp_KEY_SHIFT | wimp_KEY_UP: c = KEY_PAGE_UP; break;
+ case wimp_KEY_SHIFT | wimp_KEY_DOWN: c = KEY_PAGE_DOWN; break;
case wimp_KEY_LEFT: c = KEY_LEFT; break;
case wimp_KEY_RIGHT: c = KEY_RIGHT; break;
case wimp_KEY_UP: c = KEY_UP; break;
@@ -2016,7 +2207,7 @@ bool ro_gui_window_keypress(wimp_key *key)
case wimp_KEY_ESCAPE:
if (ro_gui_url_complete_close(NULL, 0)) {
- ro_gui_url_complete_start(g);
+ ro_gui_url_complete_start(g);
return true;
}
return ro_gui_menu_handle_action(g->window,
@@ -2071,7 +2262,7 @@ bool ro_gui_window_keypress(wimp_key *key)
g->option.scale = scale_snap_to[i];
break;
}
- }
+ }
if (g->option.scale < scale_snap_to[0])
g->option.scale = scale_snap_to[0];
if (g->option.scale > scale_snap_to[SCALE_SNAP_TO_SIZE - 1])
@@ -2236,9 +2427,9 @@ int window_y_units(int y, wimp_window_state *state) {
/**
* Convert x,y window co-ordinates into screen co-ordinates.
*
- * \param g gui window
- * \param x x ordinate
- * \param y y ordinate
+ * \param g gui window
+ * \param x x ordinate
+ * \param y y ordinate
* \param pos receives position in screen co-ordinatates
* \return true iff conversion successful
*/
@@ -2386,7 +2577,7 @@ bool ro_gui_window_dataload(struct gui_window *g, wimp_message *message)
/**
* Handle Message_DataLoad (file dragged in) for a toolbar
*
- * \param g window
+ * \param g window
* \param message Message_DataLoad block
* \return true if the load was processed
*/
@@ -2421,15 +2612,15 @@ void ro_gui_window_process_reformats(void)
{
struct gui_window *g;
+ gui_reformat_pending = false;
for (g = window_list; g; g = g->next) {
if (!g->reformat_pending)
continue;
+ g->reformat_pending = false;
content_reformat(g->bw->current_content,
g->old_width / 2 / g->option.scale,
gui_window_get_height(g));
- g->reformat_pending = false;
}
- gui_reformat_pending = false;
}
@@ -2631,11 +2822,11 @@ void gui_window_new_content(struct gui_window *g)
/**
* Updates the navigation controls for all toolbars;
*
- * \param g the gui_window to launch the URL into
+ * \param g the gui_window to launch the URL into
* \param url the URL to launch, or NULL to simply update the suggestion icon
*/
void ro_gui_window_prepare_navigate_all(void) {
- struct gui_window *g;
+ struct gui_window *g;
for (g = window_list; g; g = g->next)
ro_gui_prepare_navigate(g);
@@ -2826,6 +3017,8 @@ void ro_gui_window_scroll_end(struct gui_window *g, wimp_dragged *drag)
int x, y;
gui_current_drag_type = GUI_DRAG_NONE;
+ if (!g)
+ return;
error = xwimp_drag_box((wimp_drag*)-1);
if (error) {
@@ -2867,9 +3060,117 @@ void ro_gui_window_scroll_end(struct gui_window *g, wimp_dragged *drag)
/**
+ * Starts drag resizing of a browser frame
+ *
+ * \param gw gui window
+ */
+
+bool gui_window_frame_resize_start(struct gui_window *g)
+{
+ wimp_pointer pointer;
+ os_error *error;
+ wimp_drag drag;
+ int x0, y0, x1, y1;
+ int row = -1, col = -1, i;
+ struct browser_window *top, *bw;
+ wimp_window_state state;
+
+ /* get the maximum drag box (collapse all surrounding frames */
+ bw = g->bw;
+ x0 = bw->x0;
+ y0 = bw->y0;
+ x1 = bw->x1;
+ y1 = bw->y1;
+ for (i = 0; i < (bw->parent->cols * bw->parent->rows); i++) {
+ if (&bw->parent->children[i] == bw) {
+ col = i % bw->parent->cols;
+ row = i / bw->parent->cols;
+ }
+ }
+ assert((row >= 0) && (col >= 0));
+
+ if (g->bw->drag_resize_left)
+ x0 = bw->parent->children[row * bw->parent->cols + (col - 1)].x0;
+ if (g->bw->drag_resize_right)
+ x1 = bw->parent->children[row * bw->parent->cols + (col + 1)].x1;
+ if (g->bw->drag_resize_up)
+ y0 = bw->parent->children[(row - 1) * bw->parent->cols + col].y0;
+ if (g->bw->drag_resize_down)
+ y1 = bw->parent->children[(row + 1) * bw->parent->cols + col].y1;
+
+ /* convert to screen co-ordinates */
+ top = browser_window_owner(bw);
+ state.w = top->window->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+ x0 = state.visible.x0 + x0 * 2;
+ y0 = state.visible.y0 + y0 * 2;
+ x1 = state.visible.x0 + x1 * 2 - 1;
+ y1 = state.visible.y0 + y1 * 2 - 1;
+
+ /* get the pointer position */
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG(("xwimp_get_pointer_info 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* stop dragging in directions we can't extend */
+ if (!(g->bw->drag_resize_left || g->bw->drag_resize_right)) {
+ x0 = pointer.pos.x;
+ x1 = pointer.pos.x;
+ }
+ if (!(g->bw->drag_resize_up || g->bw->drag_resize_down)) {
+ y0 = pointer.pos.y;
+ y1 = pointer.pos.y;
+ }
+
+ /* start the drag */
+ drag.type = wimp_DRAG_USER_POINT;
+ drag.bbox.x0 = x0;
+ drag.bbox.y0 = y0;
+ drag.bbox.x1 = x1;
+ drag.bbox.y1 = y1;
+
+ error = xwimp_drag_box(&drag);
+ if (error) {
+ LOG(("xwimp_drag_box: 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ /* we may not be the window the pointer is currently over */
+ gui_track_gui_window = bw->window;
+ gui_current_drag_type = GUI_DRAG_FRAME;
+ return true;
+}
+
+
+/**
+ * Completes resizing of a browser frame
+ *
+ * \param g gui window
+ */
+
+void ro_gui_window_frame_resize_end(struct gui_window *g, wimp_dragged *drag)
+{
+ /* our clean-up is the same as for page scrolling */
+ ro_gui_window_scroll_end(g, drag);
+}
+
+
+/**
* Alter the scale setting of a window
*
- * \param g gui window
+ * \param g gui window
* \param scale scale value (1.0 == normal scale)
*/
@@ -2888,7 +3189,7 @@ void ro_gui_window_set_scale(struct gui_window *g, float scale)
/**
* Import text file into window or its toolbar
*
- * \param g gui window containing textarea
+ * \param g gui window containing textarea
* \param filename pathname of file to be imported
* \param toolbar true iff imported to toolbar rather than main window
* \return true iff successful
@@ -3018,8 +3319,8 @@ void ro_gui_window_iconise(struct gui_window *g, wimp_full_message_window_info *
return;
}
thumbnail_create(c, bitmap, NULL);
- if (overlay) bitmap_overlay_sprite(bitmap, overlay);
-
+ if (overlay)
+ bitmap_overlay_sprite(bitmap, overlay);
area = thumbnail_convert_8bpp(bitmap);
bitmap_destroy(bitmap);
if (!area) {
@@ -3094,7 +3395,7 @@ void ro_gui_window_iconise(struct gui_window *g, wimp_full_message_window_info *
/**
* Navigate up one level
*
- * \param g the gui_window to open the parent link in
+ * \param g the gui_window to open the parent link in
* \param url the URL to open the parent of
*/
bool ro_gui_window_navigate_up(struct gui_window *g, const char *url) {
@@ -3107,10 +3408,10 @@ bool ro_gui_window_navigate_up(struct gui_window *g, const char *url) {
res = url_parent(url, &parent);
if (res == URL_FUNC_OK) {
- res = url_compare(url, parent, &compare);
- if (!compare && (res == URL_FUNC_OK))
- browser_window_go(g->bw, parent, 0, true);
- free(parent);
- }
+ res = url_compare(url, parent, &compare);
+ if (!compare && (res == URL_FUNC_OK))
+ browser_window_go(g->bw, parent, 0, true);
+ free(parent);
+ }
return true;
}
diff --git a/utils/filename.c b/utils/filename.c
index 82a0c9965..8b64ccfc8 100644
--- a/utils/filename.c
+++ b/utils/filename.c
@@ -19,6 +19,7 @@
#include <sys/stat.h>
#include "netsurf/utils/filename.h"
#include "netsurf/utils/log.h"
+#include "netsurf/utils/url.h"
#include "netsurf/utils/utils.h"
#define FULL_WORD (unsigned int)4294967295
@@ -422,3 +423,26 @@ static struct directory *filename_create_directory(const char *prefix) {
return new_dir;
}
+
+
+/**
+ * Converts a filename into a local URL
+ *
+ * \param filename the filename to convert
+ * \return a local URL allocated on heap, or NULL on failure.
+ */
+char *filename_as_url(const char *filename) {
+ char *temp, *url;
+ int length;
+
+ length = strlen(TEMP_FILENAME_PREFIX) + strlen(filename) + 2;
+ temp = malloc(length);
+ if (!temp) {
+ LOG(("No memory for malloc()"));
+ return NULL;
+ }
+ sprintf(temp, "%s/%s", TEMP_FILENAME_PREFIX, filename);
+ url = path_to_url(temp);
+ free(temp);
+ return url;
+}
diff --git a/utils/filename.h b/utils/filename.h
index dab072b08..f38a29cb8 100644
--- a/utils/filename.h
+++ b/utils/filename.h
@@ -21,5 +21,6 @@ bool filename_claim(const char *filename);
void filename_release(const char *filename);
bool filename_initialise(void);
void filename_flush(void);
+char *filename_as_url(const char *filename);
#endif