summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
authorRichard Wilson <rjw@netsurf-browser.org>2006-09-02 15:52:41 +0000
committerRichard Wilson <rjw@netsurf-browser.org>2006-09-02 15:52:41 +0000
commit74fa727509874983884a35b44b646be034b1fd69 (patch)
tree1daf083961efd039e318c7a1157b6aa2a83b9d54 /desktop
parentb51f807fe326f6d9aec0600cbf526f96db7577d0 (diff)
downloadnetsurf-74fa727509874983884a35b44b646be034b1fd69.tar.gz
netsurf-74fa727509874983884a35b44b646be034b1fd69.tar.bz2
Experimental new frames code.
svn path=/trunk/netsurf/; revision=2906
Diffstat (limited to 'desktop')
-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
7 files changed, 1097 insertions, 185 deletions
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;