summaryrefslogtreecommitdiff
path: root/render/html_interaction.c
diff options
context:
space:
mode:
Diffstat (limited to 'render/html_interaction.c')
-rw-r--r--render/html_interaction.c1434
1 files changed, 0 insertions, 1434 deletions
diff --git a/render/html_interaction.c b/render/html_interaction.c
deleted file mode 100644
index 2d14ed2ae..000000000
--- a/render/html_interaction.c
+++ /dev/null
@@ -1,1434 +0,0 @@
-/*
- * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2006 Richard Wilson <info@tinct.net>
- * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
- * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * User interaction with a CONTENT_HTML (implementation).
- */
-
-#include <assert.h>
-#include <stdbool.h>
-
-#include <dom/dom.h>
-
-#include "utils/corestrings.h"
-#include "utils/messages.h"
-#include "utils/utils.h"
-#include "utils/log.h"
-#include "utils/nsoption.h"
-#include "netsurf/content.h"
-#include "netsurf/browser_window.h"
-#include "netsurf/mouse.h"
-#include "netsurf/misc.h"
-#include "netsurf/layout.h"
-#include "netsurf/keypress.h"
-#include "content/hlcache.h"
-#include "desktop/frames.h"
-#include "desktop/scrollbar.h"
-#include "desktop/selection.h"
-#include "desktop/textarea.h"
-#include "javascript/js.h"
-#include "desktop/gui_internal.h"
-
-#include "render/box.h"
-#include "render/box_textarea.h"
-#include "render/font.h"
-#include "render/form_internal.h"
-#include "render/html_internal.h"
-#include "render/imagemap.h"
-#include "render/search.h"
-
-/**
- * Get pointer shape for given box
- *
- * \param box box in question
- * \param imagemap whether an imagemap applies to the box
- */
-
-static browser_pointer_shape get_pointer_shape(struct box *box, bool imagemap)
-{
- browser_pointer_shape pointer;
- css_computed_style *style;
- enum css_cursor_e cursor;
- lwc_string **cursor_uris;
-
- if (box->type == BOX_FLOAT_LEFT || box->type == BOX_FLOAT_RIGHT)
- style = box->children->style;
- else
- style = box->style;
-
- if (style == NULL)
- return BROWSER_POINTER_DEFAULT;
-
- cursor = css_computed_cursor(style, &cursor_uris);
-
- switch (cursor) {
- case CSS_CURSOR_AUTO:
- if (box->href || (box->gadget &&
- (box->gadget->type == GADGET_IMAGE ||
- box->gadget->type == GADGET_SUBMIT)) ||
- imagemap) {
- /* link */
- pointer = BROWSER_POINTER_POINT;
- } else if (box->gadget &&
- (box->gadget->type == GADGET_TEXTBOX ||
- box->gadget->type == GADGET_PASSWORD ||
- box->gadget->type == GADGET_TEXTAREA)) {
- /* text input */
- pointer = BROWSER_POINTER_CARET;
- } else {
- /* html content doesn't mind */
- pointer = BROWSER_POINTER_AUTO;
- }
- break;
- case CSS_CURSOR_CROSSHAIR:
- pointer = BROWSER_POINTER_CROSS;
- break;
- case CSS_CURSOR_POINTER:
- pointer = BROWSER_POINTER_POINT;
- break;
- case CSS_CURSOR_MOVE:
- pointer = BROWSER_POINTER_MOVE;
- break;
- case CSS_CURSOR_E_RESIZE:
- pointer = BROWSER_POINTER_RIGHT;
- break;
- case CSS_CURSOR_W_RESIZE:
- pointer = BROWSER_POINTER_LEFT;
- break;
- case CSS_CURSOR_N_RESIZE:
- pointer = BROWSER_POINTER_UP;
- break;
- case CSS_CURSOR_S_RESIZE:
- pointer = BROWSER_POINTER_DOWN;
- break;
- case CSS_CURSOR_NE_RESIZE:
- pointer = BROWSER_POINTER_RU;
- break;
- case CSS_CURSOR_SW_RESIZE:
- pointer = BROWSER_POINTER_LD;
- break;
- case CSS_CURSOR_SE_RESIZE:
- pointer = BROWSER_POINTER_RD;
- break;
- case CSS_CURSOR_NW_RESIZE:
- pointer = BROWSER_POINTER_LU;
- break;
- case CSS_CURSOR_TEXT:
- pointer = BROWSER_POINTER_CARET;
- break;
- case CSS_CURSOR_WAIT:
- pointer = BROWSER_POINTER_WAIT;
- break;
- case CSS_CURSOR_PROGRESS:
- pointer = BROWSER_POINTER_PROGRESS;
- break;
- case CSS_CURSOR_HELP:
- pointer = BROWSER_POINTER_HELP;
- break;
- default:
- pointer = BROWSER_POINTER_DEFAULT;
- break;
- }
-
- return pointer;
-}
-
-
-/**
- * Start drag scrolling the contents of a box
- *
- * \param box the box to be scrolled
- * \param x x ordinate of initial mouse position
- * \param y y ordinate
- */
-
-static void html_box_drag_start(struct box *box, int x, int y)
-{
- int box_x, box_y;
- int scroll_mouse_x, scroll_mouse_y;
-
- box_coords(box, &box_x, &box_y);
-
- if (box->scroll_x != NULL) {
- scroll_mouse_x = x - box_x ;
- scroll_mouse_y = y - (box_y + box->padding[TOP] +
- box->height + box->padding[BOTTOM] -
- SCROLLBAR_WIDTH);
- scrollbar_start_content_drag(box->scroll_x,
- scroll_mouse_x, scroll_mouse_y);
- } else if (box->scroll_y != NULL) {
- scroll_mouse_x = x - (box_x + box->padding[LEFT] +
- box->width + box->padding[RIGHT] -
- SCROLLBAR_WIDTH);
- scroll_mouse_y = y - box_y;
-
- scrollbar_start_content_drag(box->scroll_y,
- scroll_mouse_x, scroll_mouse_y);
- }
-}
-
-
-/**
- * End overflow scroll scrollbar drags
- *
- * \param html html content
- * \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- * \param dir Direction of drag
- */
-static size_t html_selection_drag_end(struct html_content *html,
- browser_mouse_state mouse, int x, int y, int dir)
-{
- int pixel_offset;
- struct box *box;
- int dx, dy;
- size_t idx = 0;
-
- box = box_pick_text_box(html, x, y, dir, &dx, &dy);
- if (box) {
- plot_font_style_t fstyle;
-
- font_plot_style_from_css(&html->len_ctx, box->style, &fstyle);
-
- guit->layout->position(&fstyle, box->text, box->length,
- dx, &idx, &pixel_offset);
-
- idx += box->byte_offset;
- }
-
- return idx;
-}
-
-
-/**
- * Handle mouse tracking (including drags) in an HTML content window.
- *
- * \param c content of type html
- * \param bw browser window
- * \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- */
-
-void html_mouse_track(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y)
-{
- html_mouse_action(c, bw, mouse, x, y);
-}
-
-/**
- * Helper for file gadgets to store their filename.
- *
- * Stores the filename unencoded on the dom node associated with the
- * gadget.
- *
- * \todo Get rid of this crap eventually
- *
- * \param operation DOM operation
- * \param key DOM node key being considerd
- * \param _data The data assocated with the key
- * \param src The source DOM node.
- * \param dst The destination DOM node.
- */
-static void
-html__image_coords_dom_user_data_handler(dom_node_operation operation,
- dom_string *key,
- void *_data,
- struct dom_node *src,
- struct dom_node *dst)
-{
- struct image_input_coords *oldcoords, *coords = _data, *newcoords;
-
- if (!dom_string_isequal(corestring_dom___ns_key_image_coords_node_data,
- key) || coords == NULL) {
- return;
- }
-
- switch (operation) {
- case DOM_NODE_CLONED:
- newcoords = calloc(1, sizeof(*newcoords));
- if (newcoords != NULL) {
- *newcoords = *coords;
- if (dom_node_set_user_data(dst,
- corestring_dom___ns_key_image_coords_node_data,
- newcoords,
- html__image_coords_dom_user_data_handler,
- &oldcoords) == DOM_NO_ERR) {
- free(oldcoords);
- }
- }
- break;
-
- case DOM_NODE_DELETED:
- free(coords);
- break;
-
- case DOM_NODE_RENAMED:
- case DOM_NODE_IMPORTED:
- case DOM_NODE_ADOPTED:
- break;
-
- default:
- NSLOG(netsurf, INFO, "User data operation not handled.");
- assert(0);
- }
-}
-
-/**
- * Handle mouse clicks and movements in an HTML content window.
- *
- * \param c content of type html
- * \param bw browser window
- * \param mouse state of mouse buttons and modifier keys
- * \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),
- * so that the status bar reflects exactly what will happen. Having separate
- * code paths opens the possibility that an attacker will make the status bar
- * show some harmless action where clicking will be harmful.
- */
-
-void html_mouse_action(struct content *c, struct browser_window *bw,
- browser_mouse_state mouse, int x, int y)
-{
- html_content *html = (html_content *) c;
- enum { ACTION_NONE, ACTION_SUBMIT, ACTION_GO } action = ACTION_NONE;
- const char *title = 0;
- nsurl *url = 0;
- char *url_s = NULL;
- size_t url_l = 0;
- const char *target = 0;
- char status_buffer[200];
- const char *status = 0;
- browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT;
- bool imagemap = false;
- int box_x = 0, box_y = 0;
- int gadget_box_x = 0, gadget_box_y = 0;
- int html_object_pos_x = 0, html_object_pos_y = 0;
- int text_box_x = 0;
- struct box *url_box = 0;
- struct box *gadget_box = 0;
- struct box *text_box = 0;
- struct box *box;
- struct form_control *gadget = 0;
- hlcache_handle *object = NULL;
- struct box *html_object_box = NULL;
- struct browser_window *iframe = NULL;
- struct box *drag_candidate = NULL;
- struct scrollbar *scrollbar = NULL;
- plot_font_style_t fstyle;
- int scroll_mouse_x = 0, scroll_mouse_y = 0;
- int padding_left, padding_right, padding_top, padding_bottom;
- browser_drag_type drag_type = browser_window_get_drag_type(bw);
- union content_msg_data msg_data;
- struct dom_node *node = NULL;
- union html_drag_owner drag_owner;
- union html_selection_owner sel_owner;
- bool click = mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2 |
- BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2 |
- BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2);
-
- if (drag_type != DRAGGING_NONE && !mouse &&
- html->visible_select_menu != NULL) {
- /* drag end: select menu */
- form_select_mouse_drag_end(html->visible_select_menu,
- mouse, x, y);
- }
-
- if (html->visible_select_menu != NULL) {
- box = html->visible_select_menu->box;
- box_coords(box, &box_x, &box_y);
-
- box_x -= box->border[LEFT].width;
- box_y += box->height + box->border[BOTTOM].width +
- box->padding[BOTTOM] + box->padding[TOP];
- status = form_select_mouse_action(html->visible_select_menu,
- mouse, x - box_x, y - box_y);
- if (status != NULL) {
- msg_data.explicit_status_text = status;
- content_broadcast(c, CONTENT_MSG_STATUS, &msg_data);
- } else {
- int width, height;
- form_select_get_dimensions(html->visible_select_menu,
- &width, &height);
- html->visible_select_menu = NULL;
- browser_window_redraw_rect(bw, box_x, box_y,
- width, height);
- }
- return;
- }
-
- if (html->drag_type == HTML_DRAG_SELECTION) {
- /* Selection drag */
- struct box *box;
- int dir = -1;
- int dx, dy;
-
- if (!mouse) {
- /* End of selection drag */
- int dir = -1;
- size_t idx;
-
- if (selection_dragging_start(&html->sel))
- dir = 1;
-
- idx = html_selection_drag_end(html, mouse, x, y, dir);
-
- if (idx != 0)
- selection_track(&html->sel, mouse, idx);
-
- drag_owner.no_owner = true;
- html_set_drag_type(html, HTML_DRAG_NONE,
- drag_owner, NULL);
- return;
- }
-
- if (selection_dragging_start(&html->sel))
- dir = 1;
-
- box = box_pick_text_box(html, x, y, dir, &dx, &dy);
-
- if (box != NULL) {
- int pixel_offset;
- size_t idx;
- plot_font_style_t fstyle;
-
- font_plot_style_from_css(&html->len_ctx,
- box->style, &fstyle);
-
- guit->layout->position(&fstyle,
- box->text, box->length,
- dx, &idx, &pixel_offset);
-
- selection_track(&html->sel, mouse,
- box->byte_offset + idx);
- }
- return;
- }
-
- if (html->drag_type == HTML_DRAG_SCROLLBAR) {
- struct scrollbar *scr = html->drag_owner.scrollbar;
- struct html_scrollbar_data *data = scrollbar_get_data(scr);
-
- if (!mouse) {
- /* drag end: scrollbar */
- html_overflow_scroll_drag_end(scr, mouse, x, y);
- }
-
- box = data->box;
- box_coords(box, &box_x, &box_y);
- if (scrollbar_is_horizontal(scr)) {
- scroll_mouse_x = x - box_x ;
- scroll_mouse_y = y - (box_y + box->padding[TOP] +
- box->height + box->padding[BOTTOM] -
- SCROLLBAR_WIDTH);
- status = scrollbar_mouse_status_to_message(
- scrollbar_mouse_action(scr, mouse,
- scroll_mouse_x,
- scroll_mouse_y));
- } else {
- scroll_mouse_x = x - (box_x + box->padding[LEFT] +
- box->width + box->padding[RIGHT] -
- SCROLLBAR_WIDTH);
- scroll_mouse_y = y - box_y;
- status = scrollbar_mouse_status_to_message(
- scrollbar_mouse_action(scr, mouse,
- scroll_mouse_x,
- scroll_mouse_y));
- }
-
- msg_data.explicit_status_text = status;
- content_broadcast(c, CONTENT_MSG_STATUS, &msg_data);
- return;
- }
-
- if (html->drag_type == HTML_DRAG_TEXTAREA_SELECTION ||
- html->drag_type == HTML_DRAG_TEXTAREA_SCROLLBAR) {
- box = html->drag_owner.textarea;
- assert(box->gadget != NULL);
- assert(box->gadget->type == GADGET_TEXTAREA ||
- box->gadget->type == GADGET_PASSWORD ||
- box->gadget->type == GADGET_TEXTBOX);
-
- box_coords(box, &box_x, &box_y);
- textarea_mouse_action(box->gadget->data.text.ta, mouse,
- x - box_x, y - box_y);
-
- /* TODO: Set appropriate statusbar message */
- return;
- }
-
- if (html->drag_type == HTML_DRAG_CONTENT_SELECTION ||
- html->drag_type == HTML_DRAG_CONTENT_SCROLL) {
- box = html->drag_owner.content;
- assert(box->object != NULL);
-
- box_coords(box, &box_x, &box_y);
- content_mouse_track(box->object, bw, mouse,
- x - box_x, y - box_y);
- return;
- }
-
- if (html->drag_type == HTML_DRAG_CONTENT_SELECTION) {
- box = html->drag_owner.content;
- assert(box->object != NULL);
-
- box_coords(box, &box_x, &box_y);
- content_mouse_track(box->object, bw, mouse,
- x - box_x, y - box_y);
- return;
- }
-
- /* Content related drags handled by now */
- assert(html->drag_type == HTML_DRAG_NONE);
-
- /* search the box tree for a link, imagemap, form control, or
- * box with scrollbars
- */
-
- box = html->layout;
-
- /* Consider the margins of the html page now */
- box_x = box->margin[LEFT];
- box_y = box->margin[TOP];
-
- /* descend through visible boxes setting more specific values for:
- * box - deepest box at point
- * html_object_box - html object
- * html_object_pos_x - html object
- * html_object_pos_y - html object
- * object - non html object
- * iframe - iframe
- * url - href or imagemap
- * target - href or imagemap or gadget
- * url_box - href or imagemap
- * imagemap - imagemap
- * gadget - gadget
- * gadget_box - gadget
- * gadget_box_x - gadget
- * gadget_box_y - gadget
- * title - title
- * pointer
- *
- * drag_candidate - first box with scroll
- * padding_left - box with scroll
- * padding_right
- * padding_top
- * padding_bottom
- * scrollbar - inside padding box stops decent
- * scroll_mouse_x - inside padding box stops decent
- * scroll_mouse_y - inside padding box stops decent
- *
- * text_box - text box
- * text_box_x - text_box
- */
- do {
- if ((box->style != NULL) &&
- (css_computed_visibility(box->style) ==
- CSS_VISIBILITY_HIDDEN)) {
- continue;
- }
-
- if (box->node != NULL) {
- node = box->node;
- }
-
- if (box->object) {
- if (content_get_type(box->object) == CONTENT_HTML) {
- html_object_box = box;
- html_object_pos_x = box_x;
- html_object_pos_y = box_y;
- } else {
- object = box->object;
- }
- }
-
- if (box->iframe) {
- iframe = box->iframe;
- }
-
- if (box->href) {
- url = box->href;
- target = box->target;
- url_box = box;
- }
-
- if (box->usemap) {
- url = imagemap_get(html, box->usemap,
- box_x, box_y, x, y, &target);
- if (url) {
- imagemap = true;
- url_box = box;
- }
- }
-
- if (box->gadget) {
- gadget = box->gadget;
- gadget_box = box;
- gadget_box_x = box_x;
- gadget_box_y = box_y;
- if (gadget->form)
- target = gadget->form->target;
- }
-
- if (box->title) {
- title = box->title;
- }
-
- pointer = get_pointer_shape(box, false);
-
- if ((box->scroll_x != NULL) ||
- (box->scroll_y != NULL)) {
-
- if (drag_candidate == NULL) {
- drag_candidate = box;
- }
-
- padding_left = box_x +
- scrollbar_get_offset(box->scroll_x);
- padding_right = padding_left + box->padding[LEFT] +
- box->width + box->padding[RIGHT];
- padding_top = box_y +
- scrollbar_get_offset(box->scroll_y);
- padding_bottom = padding_top + box->padding[TOP] +
- box->height + box->padding[BOTTOM];
-
- if ((x > padding_left) &&
- (x < padding_right) &&
- (y > padding_top) &&
- (y < padding_bottom)) {
- /* mouse inside padding box */
-
- if ((box->scroll_y != NULL) &&
- (x > (padding_right -
- SCROLLBAR_WIDTH))) {
- /* mouse above vertical box scroll */
-
- scrollbar = box->scroll_y;
- scroll_mouse_x = x - (padding_right -
- SCROLLBAR_WIDTH);
- scroll_mouse_y = y - padding_top;
- break;
-
- } else if ((box->scroll_x != NULL) &&
- (y > (padding_bottom -
- SCROLLBAR_WIDTH))) {
- /* mouse above horizontal box scroll */
-
- scrollbar = box->scroll_x;
- scroll_mouse_x = x - padding_left;
- scroll_mouse_y = y - (padding_bottom -
- SCROLLBAR_WIDTH);
- break;
- }
- }
- }
-
- if (box->text && !box->object) {
- text_box = box;
- text_box_x = box_x;
- }
- } while ((box = box_at_point(&html->len_ctx, box, x, y,
- &box_x, &box_y)) != NULL);
-
- /* use of box_x, box_y, or content below this point is probably a
- * mistake; they will refer to the last box returned by box_at_point */
- assert(node != NULL);
-
- if (scrollbar) {
- status = scrollbar_mouse_status_to_message(
- scrollbar_mouse_action(scrollbar, mouse,
- scroll_mouse_x,
- scroll_mouse_y));
- pointer = BROWSER_POINTER_DEFAULT;
- } else if (gadget) {
- textarea_mouse_status ta_status;
-
- switch (gadget->type) {
- case GADGET_SELECT:
- status = messages_get("FormSelect");
- pointer = BROWSER_POINTER_MENU;
- if (mouse & BROWSER_MOUSE_CLICK_1 &&
- nsoption_bool(core_select_menu)) {
- html->visible_select_menu = gadget;
- form_open_select_menu(c, gadget,
- form_select_menu_callback,
- c);
- pointer = BROWSER_POINTER_DEFAULT;
- } else if (mouse & BROWSER_MOUSE_CLICK_1) {
- msg_data.select_menu.gadget = gadget;
- content_broadcast(c, CONTENT_MSG_SELECTMENU,
- &msg_data);
- }
- break;
- case GADGET_CHECKBOX:
- status = messages_get("FormCheckbox");
- if (mouse & BROWSER_MOUSE_CLICK_1) {
- gadget->selected = !gadget->selected;
- dom_html_input_element_set_checked(
- (dom_html_input_element *)(gadget->node),
- gadget->selected);
- html__redraw_a_box(html, gadget_box);
- }
- break;
- case GADGET_RADIO:
- status = messages_get("FormRadio");
- if (mouse & BROWSER_MOUSE_CLICK_1)
- form_radio_set(gadget);
- break;
- case GADGET_IMAGE:
- /* This falls through to SUBMIT */
- if (mouse & BROWSER_MOUSE_CLICK_1) {
- struct image_input_coords *coords, *oldcoords;
- /** \todo Find a way to not ignore errors */
- coords = calloc(1, sizeof(*coords));
- if (coords == NULL) {
- return;
- }
- coords->x = x - gadget_box_x;
- coords->y = y - gadget_box_y;
- if (dom_node_set_user_data(
- gadget->node,
- corestring_dom___ns_key_image_coords_node_data,
- coords, html__image_coords_dom_user_data_handler,
- &oldcoords) != DOM_NO_ERR)
- return;
- free(oldcoords);
- }
- /* Fall through */
- case GADGET_SUBMIT:
- if (gadget->form) {
- snprintf(status_buffer, sizeof status_buffer,
- messages_get("FormSubmit"),
- gadget->form->action);
- status = status_buffer;
- pointer = get_pointer_shape(gadget_box, false);
- if (mouse & (BROWSER_MOUSE_CLICK_1 |
- BROWSER_MOUSE_CLICK_2))
- action = ACTION_SUBMIT;
- } else {
- status = messages_get("FormBadSubmit");
- }
- break;
- case GADGET_TEXTBOX:
- case GADGET_PASSWORD:
- case GADGET_TEXTAREA:
- if (gadget->type == GADGET_TEXTAREA)
- status = messages_get("FormTextarea");
- else
- status = messages_get("FormTextbox");
-
- if (click && (html->selection_type !=
- HTML_SELECTION_TEXTAREA ||
- html->selection_owner.textarea !=
- gadget_box)) {
- sel_owner.none = true;
- html_set_selection(html, HTML_SELECTION_NONE,
- sel_owner, true);
- }
-
- ta_status = textarea_mouse_action(gadget->data.text.ta,
- mouse, x - gadget_box_x,
- y - gadget_box_y);
-
- if (ta_status & TEXTAREA_MOUSE_EDITOR) {
- pointer = get_pointer_shape(gadget_box, false);
- } else {
- pointer = BROWSER_POINTER_DEFAULT;
- status = scrollbar_mouse_status_to_message(
- ta_status >> 3);
- }
- break;
- case GADGET_HIDDEN:
- /* not possible: no box generated */
- break;
- case GADGET_RESET:
- status = messages_get("FormReset");
- break;
- case GADGET_FILE:
- status = messages_get("FormFile");
- if (mouse & BROWSER_MOUSE_CLICK_1) {
- msg_data.gadget_click.gadget = gadget;
- content_broadcast(c, CONTENT_MSG_GADGETCLICK,
- &msg_data);
- }
- break;
- case GADGET_BUTTON:
- /* This gadget cannot be activated */
- status = messages_get("FormButton");
- break;
- }
-
- } else if (object && (mouse & BROWSER_MOUSE_MOD_2)) {
-
- if (mouse & BROWSER_MOUSE_DRAG_2) {
- msg_data.dragsave.type = CONTENT_SAVE_NATIVE;
- msg_data.dragsave.content = object;
- content_broadcast(c, CONTENT_MSG_DRAGSAVE, &msg_data);
-
- } else if (mouse & BROWSER_MOUSE_DRAG_1) {
- msg_data.dragsave.type = CONTENT_SAVE_ORIG;
- msg_data.dragsave.content = object;
- content_broadcast(c, CONTENT_MSG_DRAGSAVE, &msg_data);
- }
-
- /* \todo should have a drag-saving object msg */
-
- } else if (iframe) {
- int pos_x, pos_y;
- float scale = browser_window_get_scale(bw);
-
- browser_window_get_position(iframe, false, &pos_x, &pos_y);
-
- pos_x /= scale;
- pos_y /= scale;
-
- if (mouse & BROWSER_MOUSE_CLICK_1 ||
- mouse & BROWSER_MOUSE_CLICK_2) {
- browser_window_mouse_click(iframe, mouse,
- x - pos_x, y - pos_y);
- } else {
- browser_window_mouse_track(iframe, mouse,
- x - pos_x, y - pos_y);
- }
- } else if (html_object_box) {
-
- if (click && (html->selection_type != HTML_SELECTION_CONTENT ||
- html->selection_owner.content !=
- html_object_box)) {
- sel_owner.none = true;
- html_set_selection(html, HTML_SELECTION_NONE,
- sel_owner, true);
- }
- if (mouse & BROWSER_MOUSE_CLICK_1 ||
- mouse & BROWSER_MOUSE_CLICK_2) {
- content_mouse_action(html_object_box->object,
- bw, mouse,
- x - html_object_pos_x,
- y - html_object_pos_y);
- } else {
- content_mouse_track(html_object_box->object,
- bw, mouse,
- x - html_object_pos_x,
- y - html_object_pos_y);
- }
- } else if (url) {
- if (nsoption_bool(display_decoded_idn) == true) {
- if (nsurl_get_utf8(url, &url_s, &url_l) != NSERROR_OK) {
- /* Unable to obtain a decoded IDN. This is not a fatal error.
- * Ensure the string pointer is NULL so we use the encoded version. */
- url_s = NULL;
- }
- }
-
- if (title) {
- snprintf(status_buffer, sizeof status_buffer, "%s: %s",
- url_s ? url_s : nsurl_access(url), title);
- } else {
- snprintf(status_buffer, sizeof status_buffer, "%s",
- url_s ? url_s : nsurl_access(url));
- }
-
- status = status_buffer;
-
- if (url_s != NULL)
- free(url_s);
-
- pointer = get_pointer_shape(url_box, imagemap);
-
- if (mouse & BROWSER_MOUSE_CLICK_1 &&
- mouse & BROWSER_MOUSE_MOD_1) {
- /* force download of link */
- browser_window_navigate(bw,
- url,
- content_get_url(c),
- BW_NAVIGATE_DOWNLOAD,
- NULL,
- NULL,
- NULL);
-
- } else if (mouse & BROWSER_MOUSE_CLICK_2 &&
- mouse & BROWSER_MOUSE_MOD_1) {
- msg_data.savelink.url = url;
- msg_data.savelink.title = title;
- content_broadcast(c, CONTENT_MSG_SAVELINK, &msg_data);
-
- } else if (mouse & (BROWSER_MOUSE_CLICK_1 |
- BROWSER_MOUSE_CLICK_2))
- action = ACTION_GO;
- } else {
- bool done = false;
-
- /* frame resizing */
- if (browser_window_frame_resize_start(bw, mouse, x, y,
- &pointer)) {
- if (mouse & (BROWSER_MOUSE_DRAG_1 |
- BROWSER_MOUSE_DRAG_2)) {
- status = messages_get("FrameDrag");
- }
- done = true;
- }
-
- /* if clicking in the main page, remove the selection from any
- * text areas */
- if (!done) {
-
- if (click && html->focus_type != HTML_FOCUS_SELF) {
- union html_focus_owner fo;
- fo.self = true;
- html_set_focus(html, HTML_FOCUS_SELF, fo,
- true, 0, 0, 0, NULL);
- }
- if (click && html->selection_type !=
- HTML_SELECTION_SELF) {
- sel_owner.none = true;
- html_set_selection(html, HTML_SELECTION_NONE,
- sel_owner, true);
- }
-
- if (text_box) {
- int pixel_offset;
- size_t idx;
-
- font_plot_style_from_css(&html->len_ctx,
- text_box->style, &fstyle);
-
- guit->layout->position(&fstyle,
- text_box->text,
- text_box->length,
- x - text_box_x,
- &idx,
- &pixel_offset);
-
- if (selection_click(&html->sel, mouse,
- text_box->byte_offset + idx)) {
- /* key presses must be directed at the
- * main browser window, paste text
- * operations ignored */
- html_drag_type drag_type;
- union html_drag_owner drag_owner;
-
- if (selection_dragging(&html->sel)) {
- drag_type = HTML_DRAG_SELECTION;
- drag_owner.no_owner = true;
- html_set_drag_type(html,
- drag_type,
- drag_owner,
- NULL);
- status = messages_get(
- "Selecting");
- }
-
- done = true;
- }
-
- } else if (mouse & BROWSER_MOUSE_PRESS_1) {
- sel_owner.none = true;
- selection_clear(&html->sel, true);
- }
-
- if (selection_defined(&html->sel)) {
- sel_owner.none = false;
- html_set_selection(html, HTML_SELECTION_SELF,
- sel_owner, true);
- } else if (click && html->selection_type !=
- HTML_SELECTION_NONE) {
- sel_owner.none = true;
- html_set_selection(html, HTML_SELECTION_NONE,
- sel_owner, true);
- }
- }
-
- if (!done) {
- if (title)
- status = title;
-
- if (mouse & BROWSER_MOUSE_DRAG_1) {
- if (mouse & BROWSER_MOUSE_MOD_2) {
- msg_data.dragsave.type =
- CONTENT_SAVE_COMPLETE;
- msg_data.dragsave.content = NULL;
- content_broadcast(c,
- CONTENT_MSG_DRAGSAVE,
- &msg_data);
- } else {
- if (drag_candidate == NULL) {
- browser_window_page_drag_start(
- bw, x, y);
- } else {
- html_box_drag_start(
- drag_candidate,
- x, y);
- }
- pointer = BROWSER_POINTER_MOVE;
- }
- }
- else if (mouse & BROWSER_MOUSE_DRAG_2) {
- if (mouse & BROWSER_MOUSE_MOD_2) {
- msg_data.dragsave.type =
- CONTENT_SAVE_SOURCE;
- msg_data.dragsave.content = NULL;
- content_broadcast(c,
- CONTENT_MSG_DRAGSAVE,
- &msg_data);
- } else {
- if (drag_candidate == NULL) {
- browser_window_page_drag_start(
- bw, x, y);
- } else {
- html_box_drag_start(
- drag_candidate,
- x, y);
- }
- pointer = BROWSER_POINTER_MOVE;
- }
- }
- }
- if (mouse && mouse < BROWSER_MOUSE_MOD_1) {
- /* ensure key presses still act on the browser window */
- union html_focus_owner fo;
- fo.self = true;
- html_set_focus(html, HTML_FOCUS_SELF, fo,
- true, 0, 0, 0, NULL);
- }
- }
-
- if (!iframe && !html_object_box) {
- msg_data.explicit_status_text = status;
- content_broadcast(c, CONTENT_MSG_STATUS, &msg_data);
-
- msg_data.pointer = pointer;
- content_broadcast(c, CONTENT_MSG_POINTER, &msg_data);
- }
-
- /* fire dom click event */
- if (mouse & BROWSER_MOUSE_CLICK_1) {
- fire_dom_event(corestring_dom_click, node, true, true);
- }
-
- /* deferred actions that can cause this browser_window to be destroyed
- * and must therefore be done after set_status/pointer
- */
- switch (action) {
- case ACTION_SUBMIT:
- form_submit(content_get_url(c),
- browser_window_find_target(bw, target, mouse),
- gadget->form, gadget);
- break;
- case ACTION_GO:
- browser_window_navigate(browser_window_find_target(bw, target, mouse),
- url,
- content_get_url(c),
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
- break;
- case ACTION_NONE:
- break;
- }
-}
-
-
-/**
- * Handle keypresses.
- *
- * \param c content of type HTML
- * \param key The UCS4 character codepoint
- * \return true if key handled, false otherwise
- */
-
-bool html_keypress(struct content *c, uint32_t key)
-{
- html_content *html = (html_content *) c;
- struct selection *sel = &html->sel;
- struct box *box;
-
- switch (html->focus_type) {
- case HTML_FOCUS_CONTENT:
- box = html->focus_owner.content;
- return content_keypress(box->object, key);
-
- case HTML_FOCUS_TEXTAREA:
- box = html->focus_owner.textarea;
- return box_textarea_keypress(html, box, key);
-
- default:
- /* Deal with it below */
- break;
- }
-
- switch (key) {
- case NS_KEY_COPY_SELECTION:
- selection_copy_to_clipboard(sel);
- return true;
-
- case NS_KEY_CLEAR_SELECTION:
- selection_clear(sel, true);
- return true;
-
- case NS_KEY_SELECT_ALL:
- selection_select_all(sel);
- return true;
-
- case NS_KEY_ESCAPE:
- if (selection_defined(sel)) {
- selection_clear(sel, true);
- return true;
- }
-
- /* if there's no selection, leave Escape for the caller */
- return false;
- }
-
- return false;
-}
-
-
-/**
- * Handle search.
- *
- * \param c content of type HTML
- * \param context front end private data
- * \param flags search flags
- * \param string search string
- */
-void html_search(struct content *c, void *context,
- search_flags_t flags, const char *string)
-{
- html_content *html = (html_content *)c;
-
- assert(c != NULL);
-
- if (string != NULL && html->search_string != NULL &&
- strcmp(string, html->search_string) == 0 &&
- html->search != NULL) {
- /* Continue prev. search */
- search_step(html->search, flags, string);
-
- } else if (string != NULL) {
- /* New search */
- free(html->search_string);
- html->search_string = strdup(string);
- if (html->search_string == NULL)
- return;
-
- if (html->search != NULL) {
- search_destroy_context(html->search);
- html->search = NULL;
- }
-
- html->search = search_create_context(c, CONTENT_HTML, context);
-
- if (html->search == NULL)
- return;
-
- search_step(html->search, flags, string);
-
- } else {
- /* Clear search */
- html_search_clear(c);
-
- free(html->search_string);
- html->search_string = NULL;
- }
-}
-
-
-/**
- * Terminate a search.
- *
- * \param c content of type HTML
- */
-void html_search_clear(struct content *c)
-{
- html_content *html = (html_content *)c;
-
- assert(c != NULL);
-
- free(html->search_string);
- html->search_string = NULL;
-
- if (html->search != NULL) {
- search_destroy_context(html->search);
- }
- html->search = NULL;
-}
-
-
-/**
- * Callback for in-page scrollbars.
- */
-void html_overflow_scroll_callback(void *client_data,
- struct scrollbar_msg_data *scrollbar_data)
-{
- struct html_scrollbar_data *data = client_data;
- html_content *html = (html_content *)data->c;
- struct box *box = data->box;
- union content_msg_data msg_data;
- html_drag_type drag_type;
- union html_drag_owner drag_owner;
-
- switch(scrollbar_data->msg) {
- case SCROLLBAR_MSG_MOVED:
-
- if (html->reflowing == true) {
- /* Can't redraw during layout, and it will
- * be redrawn after layout anyway. */
- break;
- }
-
- html__redraw_a_box(html, box);
- break;
- case SCROLLBAR_MSG_SCROLL_START:
- {
- struct rect rect = {
- .x0 = scrollbar_data->x0,
- .y0 = scrollbar_data->y0,
- .x1 = scrollbar_data->x1,
- .y1 = scrollbar_data->y1
- };
- drag_type = HTML_DRAG_SCROLLBAR;
- drag_owner.scrollbar = scrollbar_data->scrollbar;
- html_set_drag_type(html, drag_type, drag_owner, &rect);
- }
- break;
- case SCROLLBAR_MSG_SCROLL_FINISHED:
- drag_type = HTML_DRAG_NONE;
- drag_owner.no_owner = true;
- html_set_drag_type(html, drag_type, drag_owner, NULL);
-
- msg_data.pointer = BROWSER_POINTER_AUTO;
- content_broadcast(data->c, CONTENT_MSG_POINTER, &msg_data);
- break;
- }
-}
-
-
-/**
- * End overflow scroll scrollbar drags
- *
- * \param scrollbar scrollbar widget
- * \param mouse state of mouse buttons and modifier keys
- * \param x coordinate of mouse
- * \param y coordinate of mouse
- */
-void html_overflow_scroll_drag_end(struct scrollbar *scrollbar,
- browser_mouse_state mouse, int x, int y)
-{
- int scroll_mouse_x, scroll_mouse_y, box_x, box_y;
- struct html_scrollbar_data *data = scrollbar_get_data(scrollbar);
- struct box *box;
-
- box = data->box;
- box_coords(box, &box_x, &box_y);
-
- if (scrollbar_is_horizontal(scrollbar)) {
- scroll_mouse_x = x - box_x;
- scroll_mouse_y = y - (box_y + box->padding[TOP] +
- box->height + box->padding[BOTTOM] -
- SCROLLBAR_WIDTH);
- scrollbar_mouse_drag_end(scrollbar, mouse,
- scroll_mouse_x, scroll_mouse_y);
- } else {
- scroll_mouse_x = x - (box_x + box->padding[LEFT] +
- box->width + box->padding[RIGHT] -
- SCROLLBAR_WIDTH);
- scroll_mouse_y = y - box_y;
- scrollbar_mouse_drag_end(scrollbar, mouse,
- scroll_mouse_x, scroll_mouse_y);
- }
-}
-
-/* Documented in html_internal.h */
-void html_set_drag_type(html_content *html, html_drag_type drag_type,
- union html_drag_owner drag_owner, const struct rect *rect)
-{
- union content_msg_data msg_data;
-
- assert(html != NULL);
-
- html->drag_type = drag_type;
- html->drag_owner = drag_owner;
-
- switch (drag_type) {
- case HTML_DRAG_NONE:
- assert(drag_owner.no_owner == true);
- msg_data.drag.type = CONTENT_DRAG_NONE;
- break;
-
- case HTML_DRAG_SCROLLBAR:
- case HTML_DRAG_TEXTAREA_SCROLLBAR:
- case HTML_DRAG_CONTENT_SCROLL:
- msg_data.drag.type = CONTENT_DRAG_SCROLL;
- break;
-
- case HTML_DRAG_SELECTION:
- assert(drag_owner.no_owner == true);
- /* Fall through */
- case HTML_DRAG_TEXTAREA_SELECTION:
- case HTML_DRAG_CONTENT_SELECTION:
- msg_data.drag.type = CONTENT_DRAG_SELECTION;
- break;
- }
- msg_data.drag.rect = rect;
-
- /* Inform of the content's drag status change */
- content_broadcast((struct content *)html, CONTENT_MSG_DRAG, &msg_data);
-}
-
-/* Documented in html_internal.h */
-void html_set_focus(html_content *html, html_focus_type focus_type,
- union html_focus_owner focus_owner, bool hide_caret,
- int x, int y, int height, const struct rect *clip)
-{
- union content_msg_data msg_data;
- int x_off = 0;
- int y_off = 0;
- struct rect cr;
- bool textarea_lost_focus = html->focus_type == HTML_FOCUS_TEXTAREA &&
- focus_type != HTML_FOCUS_TEXTAREA;
-
- assert(html != NULL);
-
- switch (focus_type) {
- case HTML_FOCUS_SELF:
- assert(focus_owner.self == true);
- if (html->focus_type == HTML_FOCUS_SELF)
- /* Don't need to tell anyone anything */
- return;
- break;
-
- case HTML_FOCUS_CONTENT:
- box_coords(focus_owner.content, &x_off, &y_off);
- break;
-
- case HTML_FOCUS_TEXTAREA:
- box_coords(focus_owner.textarea, &x_off, &y_off);
- break;
- }
-
- html->focus_type = focus_type;
- html->focus_owner = focus_owner;
-
- if (textarea_lost_focus) {
- msg_data.caret.type = CONTENT_CARET_REMOVE;
- } else if (focus_type != HTML_FOCUS_SELF && hide_caret) {
- msg_data.caret.type = CONTENT_CARET_HIDE;
- } else {
- if (clip != NULL) {
- cr = *clip;
- cr.x0 += x_off;
- cr.y0 += y_off;
- cr.x1 += x_off;
- cr.y1 += y_off;
- }
-
- msg_data.caret.type = CONTENT_CARET_SET_POS;
- msg_data.caret.pos.x = x + x_off;
- msg_data.caret.pos.y = y + y_off;
- msg_data.caret.pos.height = height;
- msg_data.caret.pos.clip = (clip == NULL) ? NULL : &cr;
- }
-
- /* Inform of the content's drag status change */
- content_broadcast((struct content *)html, CONTENT_MSG_CARET, &msg_data);
-}
-
-/* Documented in html_internal.h */
-void html_set_selection(html_content *html, html_selection_type selection_type,
- union html_selection_owner selection_owner, bool read_only)
-{
- union content_msg_data msg_data;
- struct box *box;
- bool changed = false;
- bool same_type = html->selection_type == selection_type;
-
- assert(html != NULL);
-
- if ((selection_type == HTML_SELECTION_NONE &&
- html->selection_type != HTML_SELECTION_NONE) ||
- (selection_type != HTML_SELECTION_NONE &&
- html->selection_type == HTML_SELECTION_NONE))
- /* Existance of selection has changed, and we'll need to
- * inform our owner */
- changed = true;
-
- /* Clear any existing selection */
- if (html->selection_type != HTML_SELECTION_NONE) {
- switch (html->selection_type) {
- case HTML_SELECTION_SELF:
- if (same_type)
- break;
- selection_clear(&html->sel, true);
- break;
- case HTML_SELECTION_TEXTAREA:
- if (same_type && html->selection_owner.textarea ==
- selection_owner.textarea)
- break;
- box = html->selection_owner.textarea;
- textarea_clear_selection(box->gadget->data.text.ta);
- break;
- case HTML_SELECTION_CONTENT:
- if (same_type && html->selection_owner.content ==
- selection_owner.content)
- break;
- box = html->selection_owner.content;
- content_clear_selection(box->object);
- break;
- default:
- break;
- }
- }
-
- html->selection_type = selection_type;
- html->selection_owner = selection_owner;
-
- if (!changed)
- /* Don't need to report lack of change to owner */
- return;
-
- /* Prepare msg */
- switch (selection_type) {
- case HTML_SELECTION_NONE:
- assert(selection_owner.none == true);
- msg_data.selection.selection = false;
- break;
- case HTML_SELECTION_SELF:
- assert(selection_owner.none == false);
- /* fall through */
- case HTML_SELECTION_TEXTAREA:
- case HTML_SELECTION_CONTENT:
- msg_data.selection.selection = true;
- break;
- default:
- break;
- }
- msg_data.selection.read_only = read_only;
-
- /* Inform of the content's selection status change */
- content_broadcast((struct content *)html, CONTENT_MSG_SELECTION,
- &msg_data);
-}