2003-06-30 16:44:03 +04:00
|
|
|
/*
|
|
|
|
* This file is part of NetSurf, http://netsurf.sourceforge.net/
|
|
|
|
* Licensed under the GNU General Public License,
|
|
|
|
* http://www.opensource.org/licenses/gpl-license
|
|
|
|
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
|
2004-02-25 18:12:58 +03:00
|
|
|
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
|
2004-07-27 00:13:45 +04:00
|
|
|
* Copyright 2004 Andrew Timmins <atimmins@blueyonder.co.uk>
|
2004-08-14 16:16:45 +04:00
|
|
|
* Copyright 2004 John Tytgat <John.Tytgat@aaug.net>
|
2004-02-25 18:12:58 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
* Browser window creation and manipulation (implementation).
|
2002-09-11 18:24:02 +04:00
|
|
|
*/
|
|
|
|
|
2003-07-18 03:01:02 +04:00
|
|
|
#include <assert.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <limits.h>
|
2003-10-09 19:23:10 +04:00
|
|
|
#include <stdbool.h>
|
2003-07-18 03:01:02 +04:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
2004-01-05 05:10:59 +03:00
|
|
|
#include "netsurf/utils/config.h"
|
2004-04-02 19:16:15 +04:00
|
|
|
#include "netsurf/content/fetch.h"
|
2003-02-09 15:58:15 +03:00
|
|
|
#include "netsurf/content/fetchcache.h"
|
2005-02-03 16:18:22 +03:00
|
|
|
#include "netsurf/content/url_store.h"
|
2003-10-11 18:33:35 +04:00
|
|
|
#include "netsurf/css/css.h"
|
2004-01-05 05:10:59 +03:00
|
|
|
#ifdef WITH_AUTH
|
2003-10-25 23:20:13 +04:00
|
|
|
#include "netsurf/desktop/401login.h"
|
2004-01-05 05:10:59 +03:00
|
|
|
#endif
|
2003-02-09 15:58:15 +03:00
|
|
|
#include "netsurf/desktop/browser.h"
|
2004-05-05 02:23:44 +04:00
|
|
|
#include "netsurf/desktop/gui.h"
|
2004-03-27 01:16:31 +03:00
|
|
|
#include "netsurf/desktop/imagemap.h"
|
2004-10-02 01:31:55 +04:00
|
|
|
#include "netsurf/desktop/options.h"
|
2005-04-15 09:52:25 +04:00
|
|
|
#include "netsurf/desktop/selection.h"
|
2005-04-15 22:00:21 +04:00
|
|
|
#include "netsurf/desktop/textinput.h"
|
2002-09-11 18:24:02 +04:00
|
|
|
#include "netsurf/render/box.h"
|
2003-10-25 04:35:49 +04:00
|
|
|
#include "netsurf/render/form.h"
|
2003-09-23 22:35:44 +04:00
|
|
|
#include "netsurf/render/layout.h"
|
2002-12-23 23:06:21 +03:00
|
|
|
#include "netsurf/utils/log.h"
|
2003-10-02 02:48:39 +04:00
|
|
|
#include "netsurf/utils/messages.h"
|
2005-04-09 13:47:37 +04:00
|
|
|
#include "netsurf/utils/talloc.h"
|
2004-03-02 21:02:41 +03:00
|
|
|
#include "netsurf/utils/url.h"
|
2003-02-09 15:58:15 +03:00
|
|
|
#include "netsurf/utils/utils.h"
|
2005-06-08 01:29:26 +04:00
|
|
|
#include "netsurf/utils/utf8.h"
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
/** browser window which is being redrawn. Valid only during redraw. */
|
|
|
|
struct browser_window *current_redraw_browser;
|
|
|
|
|
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
static void browser_window_callback(content_msg msg, struct content *c,
|
2004-04-25 03:42:32 +04:00
|
|
|
void *p1, void *p2, union content_msg_data data);
|
2004-06-28 03:24:11 +04:00
|
|
|
static void browser_window_convert_to_download(struct browser_window *bw);
|
2004-02-25 18:12:58 +03:00
|
|
|
static void browser_window_start_throbber(struct browser_window *bw);
|
|
|
|
static void browser_window_stop_throbber(struct browser_window *bw);
|
|
|
|
static void browser_window_set_status(struct browser_window *bw,
|
|
|
|
const char *text);
|
2004-04-01 04:26:05 +04:00
|
|
|
static void browser_window_set_pointer(gui_pointer_shape shape);
|
2004-06-28 03:24:11 +04:00
|
|
|
static void download_window_callback(fetch_msg msg, void *p, const char *data,
|
|
|
|
unsigned long size);
|
2005-04-15 09:52:25 +04:00
|
|
|
static void browser_window_mouse_action_html(struct browser_window *bw,
|
|
|
|
browser_mouse_state mouse, int x, int y);
|
|
|
|
static void browser_window_mouse_track_html(struct browser_window *bw,
|
|
|
|
browser_mouse_state mouse, int x, int y);
|
2004-11-20 03:02:56 +03:00
|
|
|
static const char *browser_window_scrollbar_click(struct browser_window *bw,
|
2005-04-15 09:52:25 +04:00
|
|
|
browser_mouse_state mouse, struct box *box,
|
2004-11-20 03:02:56 +03:00
|
|
|
int box_x, int box_y, int x, int y);
|
2004-07-18 21:38:01 +04:00
|
|
|
static void browser_radio_set(struct content *content,
|
|
|
|
struct form_control *radio);
|
2004-04-03 03:12:26 +04:00
|
|
|
static gui_pointer_shape get_pointer_shape(css_cursor cursor);
|
2005-04-15 22:00:21 +04:00
|
|
|
|
2005-07-24 10:13:25 +04:00
|
|
|
static struct box *browser_window_nearest_text_box(struct box *box, int x, int y);
|
2005-04-15 09:52:25 +04:00
|
|
|
static struct box *browser_window_pick_text_box(struct browser_window *bw,
|
|
|
|
browser_mouse_state mouse, int x, int y, int *dx, int *dy);
|
|
|
|
static void browser_window_page_drag_start(struct browser_window *bw, int x, int y);
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2005-07-21 03:27:28 +04:00
|
|
|
static void browser_window_scroll_box(struct browser_window *bw, struct box *box,
|
|
|
|
int scroll_x, int scroll_y);
|
|
|
|
|
2003-02-09 15:58:15 +03:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
/**
|
|
|
|
* Create and open a new browser window with the given page.
|
|
|
|
*
|
2005-01-03 05:09:20 +03:00
|
|
|
* \param url URL to start fetching in the new window (copied)
|
|
|
|
* \param clone The browser window to clone
|
|
|
|
* \param referer The referring uri
|
2004-02-25 18:12:58 +03:00
|
|
|
*/
|
2002-10-15 14:41:12 +04:00
|
|
|
|
2004-10-02 01:31:55 +04:00
|
|
|
void browser_window_create(const char *url, struct browser_window *clone,
|
|
|
|
char *referer)
|
2002-10-15 14:41:12 +04:00
|
|
|
{
|
2004-02-25 18:12:58 +03:00
|
|
|
struct browser_window *bw;
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-08-14 16:16:45 +04:00
|
|
|
if ((bw = malloc(sizeof *bw)) == NULL) {
|
2004-05-07 23:14:54 +04:00
|
|
|
warn_user("NoMemory", 0);
|
2004-05-05 04:19:51 +04:00
|
|
|
return;
|
2004-02-25 18:12:58 +03:00
|
|
|
}
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-08-14 16:16:45 +04:00
|
|
|
bw->current_content = NULL;
|
|
|
|
bw->loading_content = NULL;
|
2004-02-25 18:12:58 +03:00
|
|
|
bw->history = history_create();
|
2005-04-15 09:52:25 +04:00
|
|
|
bw->sel = selection_create(bw);
|
2004-02-25 18:12:58 +03:00
|
|
|
bw->throbbing = false;
|
2004-08-14 16:16:45 +04:00
|
|
|
bw->caret_callback = NULL;
|
2005-04-20 16:24:41 +04:00
|
|
|
bw->paste_callback = NULL;
|
2004-08-14 16:16:45 +04:00
|
|
|
bw->frag_id = NULL;
|
2004-10-18 01:11:29 +04:00
|
|
|
bw->drag_type = DRAGGING_NONE;
|
2004-08-26 03:56:49 +04:00
|
|
|
bw->scrolling_box = NULL;
|
2004-10-02 03:19:08 +04:00
|
|
|
bw->referer = NULL;
|
2005-01-03 05:09:20 +03:00
|
|
|
bw->download = false;
|
2004-08-14 16:16:45 +04:00
|
|
|
if ((bw->window = gui_create_browser_window(bw, clone)) == NULL) {
|
2004-02-25 18:12:58 +03:00
|
|
|
free(bw);
|
2004-05-05 04:19:51 +04:00
|
|
|
return;
|
2004-02-25 18:12:58 +03:00
|
|
|
}
|
2005-04-08 00:46:22 +04:00
|
|
|
gui_window_set_url(bw->window, url);
|
2005-01-25 01:14:59 +03:00
|
|
|
browser_window_go(bw, url, referer);
|
2002-09-11 18:24:02 +04:00
|
|
|
}
|
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Start fetching a page in a browser window.
|
|
|
|
*
|
2005-01-03 05:09:20 +03:00
|
|
|
* \param bw browser window
|
|
|
|
* \param url URL to start fetching (copied)
|
|
|
|
* \param referer the referring uri
|
2004-02-25 18:12:58 +03:00
|
|
|
*
|
|
|
|
* Any existing fetches in the window are aborted.
|
|
|
|
*/
|
|
|
|
|
2004-10-01 04:06:49 +04:00
|
|
|
void browser_window_go(struct browser_window *bw, const char *url,
|
2005-01-25 01:14:59 +03:00
|
|
|
char* referer)
|
2002-10-15 14:41:12 +04:00
|
|
|
{
|
2005-01-25 01:14:59 +03:00
|
|
|
browser_window_go_post(bw, url, 0, 0, true, referer, false);
|
2002-10-15 14:41:12 +04:00
|
|
|
}
|
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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 post_multipart multipart post data, or 0 if none
|
|
|
|
* \param history_add add to window history
|
2004-10-02 01:31:55 +04:00
|
|
|
* \param referer the referring uri
|
2005-01-03 05:09:20 +03:00
|
|
|
* \param download download, rather than render the uri
|
2004-02-25 18:12:58 +03:00
|
|
|
*
|
|
|
|
* Any existing fetches in the window are aborted.
|
|
|
|
*
|
|
|
|
* If post_urlenc and post_multipart are 0 the url is fetched using GET.
|
|
|
|
*
|
|
|
|
* The page is not added to the window history if add_history is false. This
|
|
|
|
* should be used when returning to a page in the window history.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void browser_window_go_post(struct browser_window *bw, const char *url,
|
|
|
|
char *post_urlenc,
|
|
|
|
struct form_successful_control *post_multipart,
|
2005-01-03 05:09:20 +03:00
|
|
|
bool history_add, char *referer, bool download)
|
2002-10-15 14:41:12 +04:00
|
|
|
{
|
2004-02-25 18:12:58 +03:00
|
|
|
struct content *c;
|
2004-03-10 23:45:27 +03:00
|
|
|
char *url2;
|
2004-08-07 02:19:13 +04:00
|
|
|
char *hash;
|
2004-08-09 20:11:58 +04:00
|
|
|
url_func_result res;
|
2005-02-03 16:18:22 +03:00
|
|
|
struct url_content *url_content;
|
2005-03-21 00:13:38 +03:00
|
|
|
char url_buf[256];
|
2004-06-11 03:55:23 +04:00
|
|
|
|
|
|
|
LOG(("bw %p, url %s", bw, url));
|
2004-03-10 23:45:27 +03:00
|
|
|
|
2004-08-09 20:11:58 +04:00
|
|
|
res = url_normalize(url, &url2);
|
|
|
|
if (res != URL_FUNC_OK) {
|
2004-03-10 23:45:27 +03:00
|
|
|
LOG(("failed to normalize url %s", url));
|
|
|
|
return;
|
|
|
|
}
|
2004-02-25 18:12:58 +03:00
|
|
|
|
2004-11-23 02:29:50 +03:00
|
|
|
/* check we can actually handle this URL */
|
|
|
|
if (!fetch_can_fetch(url2)) {
|
|
|
|
gui_launch_url(url2);
|
|
|
|
free(url2);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-04-15 22:00:21 +04:00
|
|
|
/* find any fragment identifier on end of URL */
|
2004-08-07 02:19:13 +04:00
|
|
|
hash = strchr(url2, '#');
|
|
|
|
if (bw->frag_id) {
|
|
|
|
free(bw->frag_id);
|
|
|
|
bw->frag_id = 0;
|
|
|
|
}
|
|
|
|
if (hash) {
|
|
|
|
bw->frag_id = strdup(hash+1);
|
2005-03-20 06:35:50 +03:00
|
|
|
/* if we're simply moving to another ID on the same page,
|
|
|
|
* don't bother to fetch, just update the window
|
|
|
|
*/
|
2005-04-15 22:00:21 +04:00
|
|
|
if (bw->current_content && bw->current_content->url &&
|
2005-03-20 19:34:20 +03:00
|
|
|
strncasecmp(bw->current_content->url,
|
2005-03-20 23:38:40 +03:00
|
|
|
url2, hash - url2) == 0 &&
|
|
|
|
strlen(bw->current_content->url) ==
|
|
|
|
(unsigned int)(hash - url2)) {
|
2005-03-20 06:35:50 +03:00
|
|
|
free(url2);
|
|
|
|
browser_window_update(bw, false);
|
2005-03-21 00:13:38 +03:00
|
|
|
snprintf(url_buf, sizeof url_buf, "%s#%s",
|
|
|
|
bw->current_content->url, bw->frag_id);
|
|
|
|
url_buf[sizeof url_buf - 1] = 0;
|
|
|
|
gui_window_set_url(bw->window, url_buf);
|
2005-03-20 06:35:50 +03:00
|
|
|
return;
|
|
|
|
}
|
2004-08-07 02:19:13 +04:00
|
|
|
}
|
|
|
|
|
2005-03-21 02:42:23 +03:00
|
|
|
browser_window_stop(bw);
|
|
|
|
browser_window_remove_caret(bw);
|
|
|
|
|
2005-03-20 06:35:50 +03:00
|
|
|
url_content = url_store_find(url2);
|
|
|
|
if (url_content)
|
|
|
|
url_content->visits++;
|
2005-02-03 16:18:22 +03:00
|
|
|
|
2004-02-27 20:45:19 +03:00
|
|
|
browser_window_set_status(bw, messages_get("Loading"));
|
2004-02-25 18:12:58 +03:00
|
|
|
bw->history_add = history_add;
|
|
|
|
bw->time0 = clock();
|
2004-06-11 03:55:23 +04:00
|
|
|
c = fetchcache(url2, browser_window_callback, bw, 0,
|
2005-07-02 22:17:51 +04:00
|
|
|
gui_window_get_width(bw->window),
|
|
|
|
gui_window_get_height(bw->window),
|
2004-06-11 03:55:23 +04:00
|
|
|
false,
|
2005-01-03 05:09:20 +03:00
|
|
|
post_urlenc, post_multipart, true, download);
|
2004-03-10 23:45:27 +03:00
|
|
|
free(url2);
|
2004-02-25 18:12:58 +03:00
|
|
|
if (!c) {
|
2004-06-11 03:55:23 +04:00
|
|
|
browser_window_set_status(bw, messages_get("NoMemory"));
|
|
|
|
warn_user("NoMemory", 0);
|
2004-02-25 18:12:58 +03:00
|
|
|
return;
|
|
|
|
}
|
2004-08-07 02:19:13 +04:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
bw->loading_content = c;
|
|
|
|
browser_window_start_throbber(bw);
|
|
|
|
|
2004-10-02 03:19:08 +04:00
|
|
|
if (referer && referer != bw->referer) {
|
|
|
|
free(bw->referer);
|
|
|
|
bw->referer = strdup(referer);
|
|
|
|
}
|
|
|
|
|
2005-01-03 05:09:20 +03:00
|
|
|
bw->download = download;
|
|
|
|
|
2004-10-02 01:31:55 +04:00
|
|
|
fetchcache_go(c, option_send_referer ? referer : 0,
|
2004-10-01 04:06:49 +04:00
|
|
|
browser_window_callback, bw, 0,
|
2005-07-02 22:17:51 +04:00
|
|
|
gui_window_get_width(bw->window),
|
|
|
|
gui_window_get_height(bw->window),
|
2004-06-11 03:55:23 +04:00
|
|
|
post_urlenc, post_multipart, true);
|
2002-09-11 18:24:02 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
/**
|
|
|
|
* Callback for fetchcache() for browser window fetches.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void browser_window_callback(content_msg msg, struct content *c,
|
2004-07-20 00:40:11 +04:00
|
|
|
void *p1, void *p2, union content_msg_data data)
|
2002-09-11 18:24:02 +04:00
|
|
|
{
|
2004-02-25 18:12:58 +03:00
|
|
|
struct browser_window *bw = p1;
|
|
|
|
char status[40];
|
2005-03-21 00:13:38 +03:00
|
|
|
char url[256];
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
switch (msg) {
|
|
|
|
case CONTENT_MSG_LOADING:
|
2004-06-28 03:24:11 +04:00
|
|
|
assert(bw->loading_content == c);
|
|
|
|
|
|
|
|
if (c->type == CONTENT_OTHER)
|
|
|
|
browser_window_convert_to_download(bw);
|
2005-01-14 01:42:39 +03:00
|
|
|
#ifdef WITH_THEME_INSTALL
|
|
|
|
else if (c->type == CONTENT_THEME) {
|
|
|
|
theme_install_start(c);
|
|
|
|
bw->loading_content = 0;
|
|
|
|
content_remove_user(c, browser_window_callback,
|
|
|
|
bw, 0);
|
|
|
|
browser_window_stop_throbber(bw);
|
|
|
|
}
|
|
|
|
#endif
|
2005-03-21 00:13:38 +03:00
|
|
|
else {
|
|
|
|
if (bw->frag_id)
|
|
|
|
snprintf(url, sizeof url, "%s#%s",
|
|
|
|
c->url, bw->frag_id);
|
|
|
|
else
|
|
|
|
snprintf(url, sizeof url, "%s",
|
|
|
|
c->url);
|
|
|
|
url[sizeof url - 1] = 0;
|
|
|
|
gui_window_set_url(bw->window, url);
|
|
|
|
}
|
2004-02-25 18:12:58 +03:00
|
|
|
break;
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
case CONTENT_MSG_READY:
|
|
|
|
assert(bw->loading_content == c);
|
|
|
|
|
|
|
|
if (bw->current_content) {
|
|
|
|
if (bw->current_content->status ==
|
2004-08-12 02:08:26 +04:00
|
|
|
CONTENT_STATUS_READY ||
|
|
|
|
bw->current_content->status ==
|
2004-02-25 18:12:58 +03:00
|
|
|
CONTENT_STATUS_DONE)
|
2004-08-12 02:08:26 +04:00
|
|
|
content_close(bw->current_content);
|
2004-02-25 18:12:58 +03:00
|
|
|
content_remove_user(bw->current_content,
|
|
|
|
browser_window_callback,
|
|
|
|
bw, 0);
|
|
|
|
}
|
|
|
|
bw->current_content = c;
|
2004-08-14 16:16:45 +04:00
|
|
|
bw->loading_content = NULL;
|
|
|
|
bw->caret_callback = NULL;
|
2005-04-20 16:24:41 +04:00
|
|
|
bw->paste_callback = NULL;
|
2004-08-26 03:56:49 +04:00
|
|
|
bw->scrolling_box = NULL;
|
2004-07-16 20:33:45 +04:00
|
|
|
gui_window_new_content(bw->window);
|
2005-03-21 00:13:38 +03:00
|
|
|
if (bw->frag_id)
|
|
|
|
snprintf(url, sizeof url, "%s#%s",
|
|
|
|
c->url, bw->frag_id);
|
|
|
|
else
|
|
|
|
snprintf(url, sizeof url, "%s", c->url);
|
|
|
|
url[sizeof url - 1] = 0;
|
|
|
|
gui_window_set_url(bw->window, url);
|
2004-02-25 18:12:58 +03:00
|
|
|
browser_window_update(bw, true);
|
2004-08-12 02:08:26 +04:00
|
|
|
content_open(c, bw, 0, 0, 0);
|
2004-02-25 18:12:58 +03:00
|
|
|
browser_window_set_status(bw, c->status_message);
|
2005-02-07 17:28:43 +03:00
|
|
|
if (bw->history_add) {
|
2004-08-07 02:19:13 +04:00
|
|
|
history_add(bw->history, c, bw->frag_id);
|
2005-02-07 17:28:43 +03:00
|
|
|
global_history_add(bw->window);
|
|
|
|
}
|
2005-04-15 09:52:25 +04:00
|
|
|
if (c->type == CONTENT_HTML)
|
|
|
|
selection_init(bw->sel, bw->current_content->data.html.layout);
|
2004-02-25 18:12:58 +03:00
|
|
|
break;
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
case CONTENT_MSG_DONE:
|
|
|
|
assert(bw->current_content == c);
|
|
|
|
|
|
|
|
browser_window_update(bw, false);
|
2004-02-27 20:45:19 +03:00
|
|
|
sprintf(status, messages_get("Complete"),
|
2004-02-25 18:12:58 +03:00
|
|
|
((float) (clock() - bw->time0)) /
|
|
|
|
CLOCKS_PER_SEC);
|
|
|
|
browser_window_set_status(bw, status);
|
|
|
|
browser_window_stop_throbber(bw);
|
|
|
|
history_update(bw->history, c);
|
2004-07-03 21:30:28 +04:00
|
|
|
hotlist_visited(c);
|
2005-04-09 13:47:37 +04:00
|
|
|
free(bw->referer);
|
2004-10-02 03:19:08 +04:00
|
|
|
bw->referer = 0;
|
2004-02-25 18:12:58 +03:00
|
|
|
break;
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
case CONTENT_MSG_ERROR:
|
2004-04-25 03:42:32 +04:00
|
|
|
browser_window_set_status(bw, data.error);
|
2004-06-11 00:41:26 +04:00
|
|
|
warn_user(data.error, 0);
|
2004-02-25 18:12:58 +03:00
|
|
|
if (c == bw->loading_content)
|
|
|
|
bw->loading_content = 0;
|
2004-08-26 03:56:49 +04:00
|
|
|
else if (c == bw->current_content) {
|
2004-02-25 18:12:58 +03:00
|
|
|
bw->current_content = 0;
|
2004-08-26 03:56:49 +04:00
|
|
|
bw->caret_callback = NULL;
|
2005-04-20 16:24:41 +04:00
|
|
|
bw->paste_callback = NULL;
|
2004-08-26 03:56:49 +04:00
|
|
|
bw->scrolling_box = NULL;
|
2005-04-15 09:52:25 +04:00
|
|
|
selection_init(bw->sel, NULL);
|
2004-08-26 03:56:49 +04:00
|
|
|
}
|
2004-02-25 18:12:58 +03:00
|
|
|
browser_window_stop_throbber(bw);
|
2005-01-14 01:42:39 +03:00
|
|
|
free(bw->referer);
|
2004-10-02 03:19:08 +04:00
|
|
|
bw->referer = 0;
|
2004-02-25 18:12:58 +03:00
|
|
|
break;
|
2003-12-22 01:10:15 +03:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
case CONTENT_MSG_STATUS:
|
|
|
|
browser_window_set_status(bw, c->status_message);
|
|
|
|
break;
|
2003-12-22 01:10:15 +03:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
case CONTENT_MSG_REDIRECT:
|
|
|
|
bw->loading_content = 0;
|
2004-02-27 20:45:19 +03:00
|
|
|
browser_window_set_status(bw,
|
|
|
|
messages_get("Redirecting"));
|
2004-10-02 01:31:55 +04:00
|
|
|
/* the spec says nothing about referrers and
|
|
|
|
* redirects => follow Mozilla and preserve the
|
2004-10-02 03:19:08 +04:00
|
|
|
* referer across the redirect */
|
2005-01-25 01:14:59 +03:00
|
|
|
browser_window_go_post(bw, data.redirect, 0, 0,
|
|
|
|
bw->history_add, bw->referer,
|
2005-01-03 05:09:20 +03:00
|
|
|
bw->download);
|
2004-02-25 18:12:58 +03:00
|
|
|
break;
|
2003-12-30 02:09:39 +03:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
case CONTENT_MSG_REFORMAT:
|
2005-04-15 09:52:25 +04:00
|
|
|
if (c == bw->current_content &&
|
|
|
|
c->type == CONTENT_HTML) {
|
|
|
|
/* box tree may have changed, need to relabel */
|
|
|
|
selection_reinit(bw->sel, c->data.html.layout);
|
|
|
|
}
|
2004-02-25 18:12:58 +03:00
|
|
|
browser_window_update(bw, false);
|
|
|
|
break;
|
2003-12-30 02:09:39 +03:00
|
|
|
|
2004-03-21 15:50:10 +03:00
|
|
|
case CONTENT_MSG_REDRAW:
|
2004-04-25 03:42:32 +04:00
|
|
|
gui_window_update_box(bw->window, &data);
|
2004-03-21 15:50:10 +03:00
|
|
|
break;
|
|
|
|
|
2004-08-11 23:02:32 +04:00
|
|
|
case CONTENT_MSG_NEWPTR:
|
|
|
|
bw->loading_content = c;
|
|
|
|
break;
|
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
#ifdef WITH_AUTH
|
|
|
|
case CONTENT_MSG_AUTH:
|
2004-04-25 03:42:32 +04:00
|
|
|
gui_401login_open(bw, c, data.auth_realm);
|
2004-02-25 18:12:58 +03:00
|
|
|
if (c == bw->loading_content)
|
|
|
|
bw->loading_content = 0;
|
2004-08-26 03:56:49 +04:00
|
|
|
else if (c == bw->current_content) {
|
2004-02-25 18:12:58 +03:00
|
|
|
bw->current_content = 0;
|
2004-08-26 03:56:49 +04:00
|
|
|
bw->caret_callback = NULL;
|
2005-04-20 16:24:41 +04:00
|
|
|
bw->paste_callback = NULL;
|
2004-08-26 03:56:49 +04:00
|
|
|
bw->scrolling_box = NULL;
|
2005-04-15 09:52:25 +04:00
|
|
|
selection_init(bw->sel, NULL);
|
2004-08-26 03:56:49 +04:00
|
|
|
}
|
2004-02-25 18:12:58 +03:00
|
|
|
browser_window_stop_throbber(bw);
|
2005-04-09 13:47:37 +04:00
|
|
|
free(bw->referer);
|
2004-10-02 03:19:08 +04:00
|
|
|
bw->referer = 0;
|
2004-02-25 18:12:58 +03:00
|
|
|
break;
|
2003-12-30 02:09:39 +03:00
|
|
|
#endif
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
}
|
2002-09-11 18:24:02 +04:00
|
|
|
}
|
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Transfer the loading_content to a new download window.
|
|
|
|
*/
|
|
|
|
|
2004-06-28 03:24:11 +04:00
|
|
|
void browser_window_convert_to_download(struct browser_window *bw)
|
2002-09-11 18:24:02 +04:00
|
|
|
{
|
2004-06-28 03:24:11 +04:00
|
|
|
struct gui_download_window *download_window;
|
2004-02-25 18:12:58 +03:00
|
|
|
struct content *c = bw->loading_content;
|
2004-06-28 03:24:11 +04:00
|
|
|
struct fetch *fetch;
|
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
assert(c);
|
|
|
|
|
2004-06-28 03:24:11 +04:00
|
|
|
fetch = c->fetch;
|
|
|
|
|
|
|
|
if (fetch) {
|
|
|
|
/* create download window */
|
|
|
|
download_window = gui_download_window_create(c->url,
|
|
|
|
c->mime_type, fetch, c->total_size);
|
2004-02-25 18:12:58 +03:00
|
|
|
|
2004-06-28 03:24:11 +04:00
|
|
|
if (download_window) {
|
|
|
|
/* extract fetch from content */
|
|
|
|
c->fetch = 0;
|
|
|
|
c->fresh = false;
|
|
|
|
fetch_change_callback(fetch, download_window_callback,
|
|
|
|
download_window);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* must already be a download window for this fetch */
|
|
|
|
/** \todo open it at top of stack */
|
|
|
|
}
|
2004-02-25 18:12:58 +03:00
|
|
|
|
|
|
|
/* remove content from browser window */
|
|
|
|
bw->loading_content = 0;
|
|
|
|
content_remove_user(c, browser_window_callback, bw, 0);
|
|
|
|
browser_window_stop_throbber(bw);
|
2002-09-11 18:24:02 +04:00
|
|
|
}
|
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Start the busy indicator.
|
|
|
|
*
|
|
|
|
* \param bw browser window
|
|
|
|
*/
|
|
|
|
|
|
|
|
void browser_window_start_throbber(struct browser_window *bw)
|
2002-09-11 18:24:02 +04:00
|
|
|
{
|
2004-02-25 18:12:58 +03:00
|
|
|
bw->throbbing = true;
|
|
|
|
gui_window_start_throbber(bw->window);
|
|
|
|
}
|
2003-12-22 01:10:15 +03:00
|
|
|
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
/**
|
|
|
|
* Stop the busy indicator.
|
|
|
|
*
|
|
|
|
* \param bw browser window
|
|
|
|
*/
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
void browser_window_stop_throbber(struct browser_window *bw)
|
|
|
|
{
|
|
|
|
bw->throbbing = false;
|
|
|
|
gui_window_stop_throbber(bw->window);
|
|
|
|
}
|
2004-01-05 05:10:59 +03:00
|
|
|
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
/**
|
|
|
|
* Redraw browser window, set extent to content, and update title.
|
|
|
|
*
|
|
|
|
* \param bw browser_window
|
|
|
|
* \param scroll_to_top move view to top of page
|
|
|
|
*/
|
2004-01-05 05:10:59 +03:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
void browser_window_update(struct browser_window *bw,
|
|
|
|
bool scroll_to_top)
|
|
|
|
{
|
2004-08-07 02:19:13 +04:00
|
|
|
struct box *pos;
|
|
|
|
int x, y;
|
2004-07-06 00:19:52 +04:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
if (!bw->current_content)
|
|
|
|
return;
|
2004-01-05 05:10:59 +03:00
|
|
|
|
2005-06-08 01:29:26 +04:00
|
|
|
if (bw->current_content->title != NULL) {
|
2005-07-16 18:35:25 +04:00
|
|
|
gui_window_set_title(bw->window, bw->current_content->title);
|
2004-07-06 00:19:52 +04:00
|
|
|
} else
|
2004-02-25 18:12:58 +03:00
|
|
|
gui_window_set_title(bw->window, bw->current_content->url);
|
2004-01-05 05:10:59 +03:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
gui_window_set_extent(bw->window, bw->current_content->width,
|
|
|
|
bw->current_content->height);
|
2004-01-05 05:10:59 +03:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
if (scroll_to_top)
|
|
|
|
gui_window_set_scroll(bw->window, 0, 0);
|
|
|
|
|
2004-08-07 02:19:13 +04:00
|
|
|
/* if frag_id exists, then try to scroll to it */
|
|
|
|
if (bw->frag_id && bw->current_content->type == CONTENT_HTML) {
|
2004-10-18 01:11:29 +04:00
|
|
|
if ((pos = box_find_by_id(bw->current_content->data.html.layout, bw->frag_id)) != 0) {
|
2004-08-07 02:19:13 +04:00
|
|
|
box_coords(pos, &x, &y);
|
|
|
|
gui_window_set_scroll(bw->window, x, y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
gui_window_redraw_window(bw->window);
|
2002-09-11 18:24:02 +04:00
|
|
|
}
|
|
|
|
|
2002-12-23 23:06:21 +03:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
/**
|
|
|
|
* Stop all fetching activity in a browser window.
|
|
|
|
*
|
|
|
|
* \param bw browser window
|
|
|
|
*/
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
void browser_window_stop(struct browser_window *bw)
|
|
|
|
{
|
|
|
|
if (bw->loading_content) {
|
|
|
|
content_remove_user(bw->loading_content,
|
|
|
|
browser_window_callback, bw, 0);
|
|
|
|
bw->loading_content = 0;
|
|
|
|
}
|
2003-12-28 19:17:31 +03:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
if (bw->current_content &&
|
|
|
|
bw->current_content->status != CONTENT_STATUS_DONE) {
|
|
|
|
assert(bw->current_content->status == CONTENT_STATUS_READY);
|
2004-06-21 03:09:52 +04:00
|
|
|
content_stop(bw->current_content,
|
|
|
|
browser_window_callback, bw, 0);
|
2004-02-25 18:12:58 +03:00
|
|
|
}
|
2003-12-22 01:10:15 +03:00
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
browser_window_stop_throbber(bw);
|
|
|
|
}
|
2003-10-25 23:20:13 +04:00
|
|
|
|
|
|
|
|
2004-06-23 00:39:16 +04:00
|
|
|
/**
|
|
|
|
* Reload the page in a browser window.
|
|
|
|
*
|
|
|
|
* \param bw browser window
|
2004-06-29 23:08:19 +04:00
|
|
|
* \param all whether to reload all objects associated with the page
|
2004-06-23 00:39:16 +04:00
|
|
|
*/
|
|
|
|
|
2004-06-29 23:08:19 +04:00
|
|
|
void browser_window_reload(struct browser_window *bw, bool all)
|
2004-06-23 00:39:16 +04:00
|
|
|
{
|
2004-06-29 23:08:19 +04:00
|
|
|
struct content *c;
|
|
|
|
unsigned int i;
|
|
|
|
|
2004-06-23 00:39:16 +04:00
|
|
|
if (!bw->current_content || bw->loading_content)
|
|
|
|
return;
|
|
|
|
|
2004-06-29 23:08:19 +04:00
|
|
|
if (all && bw->current_content->type == CONTENT_HTML) {
|
|
|
|
c = bw->current_content;
|
|
|
|
/* invalidate objects */
|
|
|
|
for (i=0; i!=c->data.html.object_count; i++) {
|
|
|
|
if (c->data.html.object[i].content != 0)
|
|
|
|
c->data.html.object[i].content->fresh = false;
|
|
|
|
}
|
|
|
|
/* invalidate stylesheets */
|
2004-07-31 03:40:01 +04:00
|
|
|
for (i=STYLESHEET_START;
|
|
|
|
i!=c->data.html.stylesheet_count; i++) {
|
2004-06-29 23:08:19 +04:00
|
|
|
if (c->data.html.stylesheet_content[i] != 0)
|
|
|
|
c->data.html.stylesheet_content[i]->fresh = false;
|
|
|
|
}
|
|
|
|
}
|
2004-06-23 00:39:16 +04:00
|
|
|
bw->current_content->fresh = false;
|
2005-01-03 05:09:20 +03:00
|
|
|
browser_window_go_post(bw, bw->current_content->url, 0, 0,
|
2005-01-25 01:14:59 +03:00
|
|
|
false, 0, false);
|
2004-06-23 00:39:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
/**
|
|
|
|
* Change the status bar of a browser window.
|
|
|
|
*
|
|
|
|
* \param bw browser window
|
|
|
|
* \param text new status text (copied)
|
|
|
|
*/
|
|
|
|
|
|
|
|
void browser_window_set_status(struct browser_window *bw, const char *text)
|
|
|
|
{
|
|
|
|
gui_window_set_status(bw->window, text);
|
2002-09-11 18:24:02 +04:00
|
|
|
}
|
|
|
|
|
2004-07-18 21:38:01 +04:00
|
|
|
|
2004-04-01 04:26:05 +04:00
|
|
|
/**
|
|
|
|
* Change the shape of the mouse pointer
|
|
|
|
*
|
|
|
|
* \param shape shape to use
|
|
|
|
*/
|
|
|
|
|
|
|
|
void browser_window_set_pointer(gui_pointer_shape shape)
|
|
|
|
{
|
|
|
|
gui_window_set_pointer(shape);
|
|
|
|
}
|
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Close and destroy a browser window.
|
|
|
|
*
|
|
|
|
* \param bw browser window
|
|
|
|
*/
|
|
|
|
|
|
|
|
void browser_window_destroy(struct browser_window *bw)
|
2003-10-25 18:13:49 +04:00
|
|
|
{
|
2004-02-25 18:12:58 +03:00
|
|
|
if (bw->loading_content) {
|
|
|
|
content_remove_user(bw->loading_content,
|
|
|
|
browser_window_callback, bw, 0);
|
|
|
|
bw->loading_content = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bw->current_content) {
|
2004-08-12 02:08:26 +04:00
|
|
|
if (bw->current_content->status == CONTENT_STATUS_READY ||
|
|
|
|
bw->current_content->status ==
|
|
|
|
CONTENT_STATUS_DONE)
|
|
|
|
content_close(bw->current_content);
|
2004-02-25 18:12:58 +03:00
|
|
|
content_remove_user(bw->current_content,
|
|
|
|
browser_window_callback, bw, 0);
|
|
|
|
}
|
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
selection_destroy(bw->sel);
|
2004-02-25 18:12:58 +03:00
|
|
|
history_destroy(bw->history);
|
|
|
|
gui_window_destroy(bw->window);
|
|
|
|
|
2004-08-07 02:19:13 +04:00
|
|
|
free(bw->frag_id);
|
2004-02-25 18:12:58 +03:00
|
|
|
free(bw);
|
2003-10-25 18:13:49 +04:00
|
|
|
}
|
|
|
|
|
2004-02-25 18:12:58 +03:00
|
|
|
|
|
|
|
/**
|
2004-06-28 03:24:11 +04:00
|
|
|
* Callback for fetch for download window fetches.
|
2004-02-25 18:12:58 +03:00
|
|
|
*/
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2004-06-28 03:24:11 +04:00
|
|
|
void download_window_callback(fetch_msg msg, void *p, const char *data,
|
|
|
|
unsigned long size)
|
2003-08-28 23:21:27 +04:00
|
|
|
{
|
2004-06-28 03:24:11 +04:00
|
|
|
struct gui_download_window *download_window = p;
|
2003-08-28 23:21:27 +04:00
|
|
|
|
|
|
|
switch (msg) {
|
2004-07-10 06:35:31 +04:00
|
|
|
case FETCH_PROGRESS:
|
|
|
|
break;
|
2004-06-28 03:24:11 +04:00
|
|
|
case FETCH_DATA:
|
|
|
|
gui_download_window_data(download_window, data, size);
|
2003-08-28 23:21:27 +04:00
|
|
|
break;
|
|
|
|
|
2004-06-28 03:24:11 +04:00
|
|
|
case FETCH_FINISHED:
|
2003-08-28 23:21:27 +04:00
|
|
|
gui_download_window_done(download_window);
|
|
|
|
break;
|
|
|
|
|
2004-06-28 03:24:11 +04:00
|
|
|
case FETCH_ERROR:
|
|
|
|
gui_download_window_error(download_window, data);
|
2003-08-28 23:21:27 +04:00
|
|
|
break;
|
|
|
|
|
2004-06-28 03:24:11 +04:00
|
|
|
case FETCH_TYPE:
|
|
|
|
case FETCH_REDIRECT:
|
|
|
|
case FETCH_AUTH:
|
|
|
|
default:
|
|
|
|
/* not possible */
|
2003-08-28 23:21:27 +04:00
|
|
|
assert(0);
|
|
|
|
break;
|
2004-07-20 00:40:11 +04:00
|
|
|
}
|
2003-08-28 23:21:27 +04:00
|
|
|
}
|
|
|
|
|
2004-06-28 03:24:11 +04:00
|
|
|
|
2004-07-18 03:32:09 +04:00
|
|
|
/**
|
|
|
|
* Handle mouse clicks in a browser window.
|
|
|
|
*
|
|
|
|
* \param bw browser window
|
2005-04-15 09:52:25 +04:00
|
|
|
* \param mouse state of mouse buttons and modifier keys
|
2004-07-18 03:32:09 +04:00
|
|
|
* \param x coordinate of mouse
|
|
|
|
* \param y coordinate of mouse
|
|
|
|
*/
|
|
|
|
|
|
|
|
void browser_window_mouse_click(struct browser_window *bw,
|
2005-04-15 09:52:25 +04:00
|
|
|
browser_mouse_state mouse, int x, int y)
|
2004-07-18 03:32:09 +04:00
|
|
|
{
|
2005-04-15 09:52:25 +04:00
|
|
|
struct content *c = bw->current_content;
|
|
|
|
if (!c) return;
|
2004-07-18 03:32:09 +04:00
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
switch (c->type) {
|
|
|
|
case CONTENT_HTML:
|
|
|
|
browser_window_mouse_action_html(bw, mouse, x, y);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONTENT_CSS:
|
|
|
|
case CONTENT_TEXTPLAIN: {
|
|
|
|
struct box *box;
|
|
|
|
int dx, dy;
|
|
|
|
|
|
|
|
box = browser_window_pick_text_box(bw, mouse, x, y, &dx, &dy);
|
|
|
|
if (box && !(mouse & BROWSER_MOUSE_MOD_2)) {
|
|
|
|
selection_click(bw->sel, box, mouse, dx, dy);
|
|
|
|
if (selection_dragging(bw->sel))
|
|
|
|
bw->drag_type = DRAGGING_SELECTION;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* no break */
|
|
|
|
default:
|
|
|
|
if (mouse & BROWSER_MOUSE_MOD_2) {
|
|
|
|
if (mouse & BROWSER_MOUSE_DRAG_2)
|
2005-04-18 15:52:26 +04:00
|
|
|
gui_drag_save_object(GUI_SAVE_OBJECT_NATIVE, c, bw->window);
|
2005-04-15 09:52:25 +04:00
|
|
|
else if (mouse & BROWSER_MOUSE_DRAG_1)
|
2005-04-18 15:52:26 +04:00
|
|
|
gui_drag_save_object(GUI_SAVE_OBJECT_ORIG, c, bw->window);
|
2005-04-15 09:52:25 +04:00
|
|
|
}
|
2005-04-17 01:44:37 +04:00
|
|
|
else if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2)) {
|
2005-04-15 09:52:25 +04:00
|
|
|
browser_window_page_drag_start(bw, x, y);
|
|
|
|
browser_window_set_pointer(GUI_POINTER_MOVE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2004-07-18 03:32:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2005-04-15 09:52:25 +04:00
|
|
|
* Handle mouse clicks and movements in an HTML content window.
|
2004-07-18 03:32:09 +04:00
|
|
|
*
|
|
|
|
* \param bw browser window
|
|
|
|
* \param click type of mouse click
|
|
|
|
* \param x coordinate of mouse
|
|
|
|
* \param y coordinate of mouse
|
|
|
|
*/
|
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
void browser_window_mouse_action_html(struct browser_window *bw,
|
|
|
|
browser_mouse_state mouse, int x, int y)
|
2004-07-18 03:32:09 +04:00
|
|
|
{
|
|
|
|
char *base_url = 0;
|
|
|
|
char *title = 0;
|
2005-04-15 09:52:25 +04:00
|
|
|
char *url = 0;
|
2004-07-18 03:32:09 +04:00
|
|
|
char status_buffer[200];
|
2004-07-18 21:38:01 +04:00
|
|
|
const char *status = 0;
|
2004-07-18 03:32:09 +04:00
|
|
|
gui_pointer_shape pointer = GUI_POINTER_DEFAULT;
|
2004-07-18 21:38:01 +04:00
|
|
|
int box_x = 0, box_y = 0;
|
2004-07-19 18:31:31 +04:00
|
|
|
int gadget_box_x = 0, gadget_box_y = 0;
|
2004-11-20 03:02:56 +03:00
|
|
|
int scroll_box_x = 0, scroll_box_y = 0;
|
2004-07-18 21:38:01 +04:00
|
|
|
struct box *gadget_box = 0;
|
2004-11-20 03:02:56 +03:00
|
|
|
struct box *scroll_box = 0;
|
2005-04-15 09:52:25 +04:00
|
|
|
struct box *text_box = 0;
|
2004-07-18 21:38:01 +04:00
|
|
|
struct content *c = bw->current_content;
|
2004-08-26 03:56:49 +04:00
|
|
|
struct box *box;
|
2004-07-18 21:38:01 +04:00
|
|
|
struct content *content = c;
|
|
|
|
struct content *gadget_content = c;
|
|
|
|
struct form_control *gadget = 0;
|
2005-04-15 09:52:25 +04:00
|
|
|
struct content *object = NULL;
|
2004-08-09 20:11:58 +04:00
|
|
|
url_func_result res;
|
2005-07-24 10:13:25 +04:00
|
|
|
struct box *next_box;
|
2004-07-18 03:32:09 +04:00
|
|
|
|
2004-10-18 01:11:29 +04:00
|
|
|
bw->drag_type = DRAGGING_NONE;
|
2004-08-26 03:56:49 +04:00
|
|
|
bw->scrolling_box = NULL;
|
2005-04-15 09:52:25 +04:00
|
|
|
|
2004-08-26 03:56:49 +04:00
|
|
|
/* search the box tree for a link, imagemap, form control, or
|
2004-10-18 01:11:29 +04:00
|
|
|
* box with scrollbars */
|
2005-04-15 09:52:25 +04:00
|
|
|
|
2004-08-26 03:56:49 +04:00
|
|
|
box = c->data.html.layout;
|
2005-07-24 10:13:25 +04:00
|
|
|
while ((next_box = box_at_point(box, x, y, &box_x, &box_y, &content)) !=
|
2004-08-26 03:56:49 +04:00
|
|
|
NULL) {
|
2005-07-24 10:13:25 +04:00
|
|
|
box = next_box;
|
|
|
|
|
2004-07-18 03:32:09 +04:00
|
|
|
if (box->style &&
|
|
|
|
box->style->visibility == CSS_VISIBILITY_HIDDEN)
|
|
|
|
continue;
|
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
if (box->object)
|
|
|
|
object = box->object;
|
|
|
|
|
2005-07-02 22:17:51 +04:00
|
|
|
if (box->href)
|
|
|
|
url = box->href;
|
2004-07-18 03:32:09 +04:00
|
|
|
|
2005-07-02 22:17:51 +04:00
|
|
|
if (box->usemap)
|
|
|
|
url = imagemap_get(content, box->usemap,
|
2004-07-18 03:32:09 +04:00
|
|
|
box_x, box_y, x, y);
|
|
|
|
|
|
|
|
if (box->gadget) {
|
|
|
|
gadget_content = content;
|
|
|
|
base_url = content->data.html.base_url;
|
|
|
|
gadget = box->gadget;
|
2004-07-18 04:12:18 +04:00
|
|
|
gadget_box = box;
|
2004-07-19 18:31:31 +04:00
|
|
|
gadget_box_x = box_x;
|
|
|
|
gadget_box_y = box_y;
|
2004-07-18 03:32:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (box->title)
|
|
|
|
title = box->title;
|
|
|
|
|
|
|
|
if (box->style && box->style->cursor != CSS_CURSOR_UNKNOWN)
|
|
|
|
pointer = get_pointer_shape(box->style->cursor);
|
2004-08-26 03:56:49 +04:00
|
|
|
|
2004-11-20 03:02:56 +03:00
|
|
|
if (box->style && box->type != BOX_BR &&
|
|
|
|
box->type != BOX_INLINE &&
|
2005-07-02 22:17:51 +04:00
|
|
|
box->type != BOX_TEXT &&
|
2004-11-20 03:02:56 +03:00
|
|
|
(box->style->overflow == CSS_OVERFLOW_SCROLL ||
|
|
|
|
box->style->overflow == CSS_OVERFLOW_AUTO) &&
|
|
|
|
((box_vscrollbar_present(box) &&
|
|
|
|
box_x + box->scroll_x + box->padding[LEFT] +
|
|
|
|
box->width < x) ||
|
|
|
|
(box_hscrollbar_present(box) &&
|
|
|
|
box_y + box->scroll_y + box->padding[TOP] +
|
|
|
|
box->height < y))) {
|
|
|
|
scroll_box = box;
|
|
|
|
scroll_box_x = box_x + box->scroll_x;
|
|
|
|
scroll_box_y = box_y + box->scroll_y;
|
2004-08-26 03:56:49 +04:00
|
|
|
}
|
2005-04-15 09:52:25 +04:00
|
|
|
|
|
|
|
if (box->text && !box->object)
|
|
|
|
text_box = box;
|
2004-07-18 03:32:09 +04:00
|
|
|
}
|
|
|
|
|
2004-11-20 03:02:56 +03:00
|
|
|
if (scroll_box) {
|
2005-04-15 09:52:25 +04:00
|
|
|
status = browser_window_scrollbar_click(bw, mouse, scroll_box,
|
2004-11-20 03:02:56 +03:00
|
|
|
scroll_box_x, scroll_box_y,
|
|
|
|
x - scroll_box_x, y - scroll_box_y);
|
2004-10-18 01:11:29 +04:00
|
|
|
|
|
|
|
} else if (gadget) {
|
2004-07-18 03:32:09 +04:00
|
|
|
switch (gadget->type) {
|
|
|
|
case GADGET_SELECT:
|
|
|
|
status = messages_get("FormSelect");
|
|
|
|
pointer = GUI_POINTER_MENU;
|
2005-04-15 09:52:25 +04:00
|
|
|
if (mouse & BROWSER_MOUSE_CLICK_1)
|
2004-07-18 03:32:09 +04:00
|
|
|
gui_create_form_select_menu(bw, gadget);
|
|
|
|
break;
|
|
|
|
case GADGET_CHECKBOX:
|
|
|
|
status = messages_get("FormCheckbox");
|
2005-04-15 09:52:25 +04:00
|
|
|
if (mouse & BROWSER_MOUSE_CLICK_1) {
|
2004-07-18 03:32:09 +04:00
|
|
|
gadget->selected = !gadget->selected;
|
2004-07-18 21:38:01 +04:00
|
|
|
browser_redraw_box(gadget_content, gadget_box);
|
2004-07-18 03:32:09 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GADGET_RADIO:
|
|
|
|
status = messages_get("FormRadio");
|
2005-04-15 09:52:25 +04:00
|
|
|
if (mouse & BROWSER_MOUSE_CLICK_1)
|
2004-07-18 21:38:01 +04:00
|
|
|
browser_radio_set(gadget_content, gadget);
|
2004-07-18 03:32:09 +04:00
|
|
|
break;
|
|
|
|
case GADGET_IMAGE:
|
2005-04-15 09:52:25 +04:00
|
|
|
if (mouse & BROWSER_MOUSE_CLICK_1) {
|
2004-07-19 18:31:31 +04:00
|
|
|
gadget->data.image.mx = x - gadget_box_x;
|
|
|
|
gadget->data.image.my = y - gadget_box_y;
|
2004-07-18 03:32:09 +04:00
|
|
|
}
|
|
|
|
/* drop through */
|
|
|
|
case GADGET_SUBMIT:
|
|
|
|
if (gadget->form) {
|
2004-11-20 03:02:56 +03:00
|
|
|
res = url_join(gadget->form->action, base_url,
|
|
|
|
&url);
|
2004-07-18 03:32:09 +04:00
|
|
|
snprintf(status_buffer, sizeof status_buffer,
|
|
|
|
messages_get("FormSubmit"),
|
2004-08-09 20:11:58 +04:00
|
|
|
(res == URL_FUNC_OK) ? url :
|
2004-07-18 03:32:09 +04:00
|
|
|
gadget->form->action);
|
|
|
|
status = status_buffer;
|
|
|
|
pointer = GUI_POINTER_POINT;
|
2005-04-15 09:52:25 +04:00
|
|
|
if (mouse & BROWSER_MOUSE_CLICK_1)
|
2004-07-18 03:32:09 +04:00
|
|
|
browser_form_submit(bw, gadget->form,
|
|
|
|
gadget);
|
|
|
|
} else {
|
|
|
|
status = messages_get("FormBadSubmit");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GADGET_TEXTAREA:
|
|
|
|
status = messages_get("FormTextarea");
|
|
|
|
pointer = GUI_POINTER_CARET;
|
2005-07-21 03:27:28 +04:00
|
|
|
if (mouse & (BROWSER_MOUSE_MOD_1 | BROWSER_MOUSE_MOD_2)) {
|
|
|
|
if (text_box) {
|
|
|
|
selection_click(bw->sel, text_box, mouse, x - box_x, y - box_y);
|
|
|
|
if (selection_dragging(bw->sel))
|
|
|
|
bw->drag_type = DRAGGING_SELECTION;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (mouse & BROWSER_MOUSE_CLICK_1) {
|
|
|
|
browser_window_textarea_click(bw,
|
|
|
|
mouse,
|
|
|
|
gadget_box,
|
|
|
|
gadget_box_x,
|
|
|
|
gadget_box_y,
|
|
|
|
x - gadget_box_x,
|
|
|
|
y - gadget_box_y);
|
|
|
|
}
|
|
|
|
else if (text_box) {
|
|
|
|
if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2))
|
|
|
|
selection_init(bw->sel, gadget_box);
|
|
|
|
|
|
|
|
selection_click(bw->sel, text_box, mouse, x - box_x, y - box_y);
|
|
|
|
if (selection_dragging(bw->sel))
|
|
|
|
bw->drag_type = DRAGGING_SELECTION;
|
|
|
|
}
|
|
|
|
}
|
2004-07-18 03:32:09 +04:00
|
|
|
break;
|
|
|
|
case GADGET_TEXTBOX:
|
|
|
|
case GADGET_PASSWORD:
|
|
|
|
status = messages_get("FormTextbox");
|
|
|
|
pointer = GUI_POINTER_CARET;
|
2005-04-15 09:52:25 +04:00
|
|
|
if ((mouse & BROWSER_MOUSE_CLICK_1) &&
|
|
|
|
!(mouse & (BROWSER_MOUSE_MOD_1 | BROWSER_MOUSE_MOD_2))) {
|
2004-07-18 03:32:09 +04:00
|
|
|
browser_window_input_click(bw,
|
2004-07-19 18:31:31 +04:00
|
|
|
gadget_box,
|
|
|
|
gadget_box_x,
|
|
|
|
gadget_box_y,
|
|
|
|
x - gadget_box_x,
|
|
|
|
y - gadget_box_y);
|
2005-04-15 09:52:25 +04:00
|
|
|
}
|
2005-07-21 03:27:28 +04:00
|
|
|
else if (text_box) {
|
|
|
|
if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2))
|
|
|
|
selection_init(bw->sel, gadget_box);
|
|
|
|
|
|
|
|
selection_click(bw->sel, text_box, mouse, x - box_x, y - box_y);
|
|
|
|
if (selection_dragging(bw->sel))
|
|
|
|
bw->drag_type = DRAGGING_SELECTION;
|
2005-04-15 09:52:25 +04:00
|
|
|
}
|
2004-07-18 03:32:09 +04:00
|
|
|
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");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
} else if (object && (mouse & BROWSER_MOUSE_MOD_2)) {
|
|
|
|
|
|
|
|
if (mouse & BROWSER_MOUSE_DRAG_2)
|
2005-04-18 15:52:26 +04:00
|
|
|
gui_drag_save_object(GUI_SAVE_OBJECT_NATIVE, object, bw->window);
|
2005-04-15 09:52:25 +04:00
|
|
|
else if (mouse & BROWSER_MOUSE_DRAG_1)
|
2005-04-18 15:52:26 +04:00
|
|
|
gui_drag_save_object(GUI_SAVE_OBJECT_ORIG, object, bw->window);
|
2005-04-15 09:52:25 +04:00
|
|
|
|
|
|
|
/* \todo should have a drag-saving object msg */
|
|
|
|
status = c->status_message;
|
|
|
|
|
2005-07-02 22:17:51 +04:00
|
|
|
} else if (url) {
|
2004-07-18 03:32:09 +04:00
|
|
|
if (title) {
|
|
|
|
snprintf(status_buffer, sizeof status_buffer, "%s: %s",
|
2005-07-02 22:17:51 +04:00
|
|
|
url, title);
|
2004-07-18 03:32:09 +04:00
|
|
|
status = status_buffer;
|
|
|
|
} else
|
|
|
|
status = url;
|
|
|
|
|
|
|
|
pointer = GUI_POINTER_POINT;
|
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
if (mouse & BROWSER_MOUSE_CLICK_1) {
|
|
|
|
|
|
|
|
if (mouse & BROWSER_MOUSE_MOD_1)
|
|
|
|
browser_window_go_post(bw, url, 0, 0, false, c->url,
|
|
|
|
true);
|
|
|
|
else
|
|
|
|
browser_window_go(bw, url, c->url);
|
2004-11-23 02:29:50 +03:00
|
|
|
}
|
2005-04-15 09:52:25 +04:00
|
|
|
else if (mouse & BROWSER_MOUSE_CLICK_2) {
|
|
|
|
|
|
|
|
if (mouse & BROWSER_MOUSE_MOD_1) {
|
|
|
|
/* \todo saving of links as URL files */
|
|
|
|
//ro_gui_save_prepare(GUI_SAVE_LINK_URL, c);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
browser_window_create(url, bw, c->url);
|
2004-07-18 03:32:09 +04:00
|
|
|
}
|
2005-04-15 09:52:25 +04:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (text_box && selection_click(bw->sel, text_box, mouse, x - box_x, y - box_y)) {
|
|
|
|
|
2005-04-20 16:24:41 +04:00
|
|
|
/* key presses must be directed at the main browser window,
|
|
|
|
paste text operations ignored */
|
|
|
|
if (bw->caret_callback) bw->caret_callback = NULL;
|
|
|
|
if (bw->paste_callback) bw->paste_callback = NULL;
|
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
if (selection_dragging(bw->sel)) {
|
|
|
|
bw->drag_type = DRAGGING_SELECTION;
|
|
|
|
status = messages_get("Selecting");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
status = c->status_message;
|
2005-01-03 05:09:20 +03:00
|
|
|
}
|
2005-04-15 09:52:25 +04:00
|
|
|
else {
|
2004-07-18 03:32:09 +04:00
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
if (title)
|
|
|
|
status = title;
|
|
|
|
else if (bw->loading_content)
|
|
|
|
status = bw->loading_content->status_message;
|
|
|
|
else
|
|
|
|
status = c->status_message;
|
2004-07-18 03:32:09 +04:00
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
if (mouse & BROWSER_MOUSE_DRAG_1) {
|
|
|
|
if (mouse & BROWSER_MOUSE_MOD_2) {
|
2005-04-18 15:52:26 +04:00
|
|
|
gui_drag_save_object(GUI_SAVE_COMPLETE, c, bw->window);
|
2005-04-15 09:52:25 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
browser_window_page_drag_start(bw, x, y);
|
|
|
|
pointer = GUI_POINTER_MOVE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (mouse & BROWSER_MOUSE_DRAG_2) {
|
|
|
|
if (mouse & BROWSER_MOUSE_MOD_2) {
|
2005-04-18 15:52:26 +04:00
|
|
|
gui_drag_save_object(GUI_SAVE_SOURCE, c, bw->window);
|
2005-04-15 09:52:25 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
browser_window_page_drag_start(bw, x, y);
|
|
|
|
pointer = GUI_POINTER_MOVE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-07-18 03:32:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
assert(status);
|
|
|
|
|
|
|
|
browser_window_set_status(bw, status);
|
|
|
|
browser_window_set_pointer(pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-18 01:11:29 +04:00
|
|
|
/**
|
2005-04-15 09:52:25 +04:00
|
|
|
* Handle mouse movements in a browser window.
|
2004-10-18 01:11:29 +04:00
|
|
|
*
|
|
|
|
* \param bw browser window
|
2005-04-15 09:52:25 +04:00
|
|
|
* \param mouse state of mouse buttons and modifier keys
|
2004-10-18 01:11:29 +04:00
|
|
|
* \param x coordinate of mouse
|
|
|
|
* \param y coordinate of mouse
|
|
|
|
*/
|
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
void browser_window_mouse_track(struct browser_window *bw,
|
|
|
|
browser_mouse_state mouse, int x, int y)
|
2004-10-18 01:11:29 +04:00
|
|
|
{
|
2005-04-15 09:52:25 +04:00
|
|
|
struct content *c = bw->current_content;
|
|
|
|
if (!c) return;
|
2004-10-18 01:11:29 +04:00
|
|
|
|
2005-04-18 15:52:26 +04:00
|
|
|
/* detect end of drag operation in case the platform-specific code
|
|
|
|
doesn't call browser_mouse_drag_end() (RISC OS code does) */
|
2005-04-15 09:52:25 +04:00
|
|
|
|
|
|
|
if (bw->drag_type != DRAGGING_NONE && !mouse) {
|
|
|
|
browser_window_mouse_drag_end(bw, mouse, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bw->drag_type == DRAGGING_PAGE_SCROLL) {
|
|
|
|
|
|
|
|
int scrollx = bw->scrolling_start_x - x; /* mouse movement since drag started */
|
|
|
|
int scrolly = bw->scrolling_start_y - y;
|
|
|
|
|
|
|
|
scrollx += bw->scrolling_start_scroll_x; /* new scroll offsets */
|
|
|
|
scrolly += bw->scrolling_start_scroll_y;
|
|
|
|
|
|
|
|
bw->scrolling_start_scroll_x = scrollx;
|
|
|
|
bw->scrolling_start_scroll_y = scrolly;
|
|
|
|
|
|
|
|
gui_window_set_scroll(bw->window, scrollx, scrolly);
|
2004-10-18 01:11:29 +04:00
|
|
|
}
|
2005-04-15 09:52:25 +04:00
|
|
|
else switch (c->type) {
|
|
|
|
case CONTENT_HTML:
|
|
|
|
browser_window_mouse_track_html(bw, mouse, x, y);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONTENT_CSS:
|
|
|
|
case CONTENT_TEXTPLAIN:
|
|
|
|
if (bw->drag_type == DRAGGING_SELECTION) {
|
|
|
|
struct box *box;
|
|
|
|
int dx, dy;
|
|
|
|
|
|
|
|
box = browser_window_pick_text_box(bw, mouse, x, y, &dx, &dy);
|
|
|
|
if (box)
|
|
|
|
selection_track(bw->sel, box, mouse, dx, dy);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle mouse tracking (including drags) in an HTML content window.
|
|
|
|
*
|
|
|
|
* \param bw browser window
|
|
|
|
* \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) {
|
|
|
|
|
2005-07-21 03:27:28 +04:00
|
|
|
case DRAGGING_HSCROLL:
|
|
|
|
case DRAGGING_VSCROLL:
|
|
|
|
case DRAGGING_2DSCROLL: {
|
2005-04-15 09:52:25 +04:00
|
|
|
struct box *box = bw->scrolling_box;
|
2005-07-21 03:27:28 +04:00
|
|
|
int scroll_y;
|
|
|
|
int scroll_x;
|
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
assert(box);
|
2005-07-21 03:27:28 +04:00
|
|
|
|
|
|
|
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 *
|
|
|
|
(float) (box->descendant_y1 -
|
|
|
|
box->descendant_y0);
|
|
|
|
if (scroll_y < box->descendant_y0)
|
|
|
|
scroll_y = box->descendant_y0;
|
|
|
|
else if (box->descendant_y1 - box->height < scroll_y)
|
|
|
|
scroll_y = box->descendant_y1 - box->height;
|
|
|
|
if (scroll_y == box->scroll_y)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 *
|
|
|
|
(float) (box->descendant_x1 -
|
|
|
|
box->descendant_x0);
|
|
|
|
if (scroll_x < box->descendant_x0)
|
|
|
|
scroll_x = box->descendant_x0;
|
|
|
|
else if (box->descendant_x1 - box->width < scroll_x)
|
|
|
|
scroll_x = box->descendant_x1 - box->width;
|
|
|
|
}
|
|
|
|
|
|
|
|
browser_window_scroll_box(bw, box, scroll_x, scroll_y);
|
2005-04-15 09:52:25 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DRAGGING_SELECTION: {
|
|
|
|
struct box *box;
|
|
|
|
int dx, dy;
|
|
|
|
|
|
|
|
box = browser_window_pick_text_box(bw, mouse, x, y, &dx, &dy);
|
|
|
|
if (box)
|
|
|
|
selection_track(bw->sel, box, mouse, dx, dy);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
browser_window_mouse_action_html(bw, mouse, x, y);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles the end of a drag operation in a 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
void browser_window_mouse_drag_end(struct browser_window *bw,
|
|
|
|
browser_mouse_state mouse, int x, int y)
|
|
|
|
{
|
|
|
|
switch (bw->drag_type) {
|
|
|
|
case DRAGGING_SELECTION: {
|
|
|
|
int dx, dy;
|
|
|
|
struct box *box = browser_window_pick_text_box(bw, mouse, x, y,
|
|
|
|
&dx, &dy);
|
2005-04-16 00:46:25 +04:00
|
|
|
selection_drag_end(bw->sel, box, mouse, dx, dy);
|
2005-04-15 09:52:25 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-07-21 03:27:28 +04:00
|
|
|
case DRAGGING_2DSCROLL:
|
2005-04-17 01:44:37 +04:00
|
|
|
case DRAGGING_PAGE_SCROLL:
|
|
|
|
browser_window_set_pointer(GUI_POINTER_DEFAULT);
|
|
|
|
break;
|
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
bw->drag_type = DRAGGING_NONE;
|
2004-10-18 01:11:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-20 03:02:56 +03:00
|
|
|
/**
|
|
|
|
* Handle mouse clicks in a box scrollbar.
|
|
|
|
*
|
|
|
|
* \param bw browser window
|
2005-04-15 09:52:25 +04:00
|
|
|
* \param mouse state of mouse buttons and modifier keys
|
2004-11-20 03:02:56 +03:00
|
|
|
* \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
|
|
|
|
* \return status bar message
|
|
|
|
*/
|
|
|
|
|
|
|
|
const char *browser_window_scrollbar_click(struct browser_window *bw,
|
2005-04-15 09:52:25 +04:00
|
|
|
browser_mouse_state mouse, struct box *box,
|
2004-11-20 03:02:56 +03:00
|
|
|
int box_x, int box_y, int x, int y)
|
|
|
|
{
|
|
|
|
const int w = SCROLLBAR_WIDTH;
|
|
|
|
bool vscroll, hscroll;
|
|
|
|
int well_height, bar_top, bar_height;
|
|
|
|
int well_width, bar_left, bar_width;
|
|
|
|
const char *status = 0;
|
|
|
|
bool vert;
|
|
|
|
int z, scroll, bar_start, bar_size, well_size, page;
|
|
|
|
|
|
|
|
box_scrollbar_dimensions(box,
|
|
|
|
box->padding[LEFT] + box->width + box->padding[RIGHT],
|
|
|
|
box->padding[TOP] + box->height + box->padding[BOTTOM],
|
|
|
|
w,
|
|
|
|
&vscroll, &hscroll,
|
|
|
|
&well_height, &bar_top, &bar_height,
|
|
|
|
&well_width, &bar_left, &bar_width);
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
|
|
/* determine which scrollbar was clicked */
|
|
|
|
if (box_vscrollbar_present(box) &&
|
|
|
|
box->padding[LEFT] + box->width < x) {
|
|
|
|
vert = true;
|
|
|
|
z = y;
|
|
|
|
scroll = box->scroll_y;
|
|
|
|
well_size = well_height;
|
|
|
|
bar_start = bar_top;
|
|
|
|
bar_size = bar_height;
|
|
|
|
page = box->height;
|
|
|
|
} else {
|
|
|
|
vert = false;
|
|
|
|
z = x;
|
|
|
|
scroll = box->scroll_x;
|
|
|
|
well_size = well_width;
|
|
|
|
bar_start = bar_left;
|
|
|
|
bar_size = bar_width;
|
|
|
|
page = box->width;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* find icon in scrollbar and calculate scroll */
|
|
|
|
if (z < w) {
|
|
|
|
status = messages_get(vert ? "ScrollUp" : "ScrollLeft");
|
2005-04-15 09:52:25 +04:00
|
|
|
if (mouse & BROWSER_MOUSE_CLICK_1)
|
2004-11-20 03:02:56 +03:00
|
|
|
scroll -= 16;
|
2005-04-15 09:52:25 +04:00
|
|
|
else if (mouse & BROWSER_MOUSE_CLICK_2)
|
2004-11-20 03:02:56 +03:00
|
|
|
scroll += 16;
|
|
|
|
} else if (z < w + bar_start + w / 4) {
|
|
|
|
status = messages_get(vert ? "ScrollPUp" : "ScrollPLeft");
|
2005-04-15 09:52:25 +04:00
|
|
|
if (mouse & BROWSER_MOUSE_CLICK_1)
|
2004-11-20 03:02:56 +03:00
|
|
|
scroll -= page;
|
2005-04-15 09:52:25 +04:00
|
|
|
else if (mouse & BROWSER_MOUSE_CLICK_2)
|
2004-11-20 03:02:56 +03:00
|
|
|
scroll += page;
|
|
|
|
} else if (z < w + bar_start + bar_size - w / 4) {
|
|
|
|
status = messages_get(vert ? "ScrollV" : "ScrollH");
|
2005-07-21 03:27:28 +04:00
|
|
|
|
|
|
|
/* respond on the click rather than the drag because it gives
|
|
|
|
the scrollbars a more solid, RISC OS feel */
|
|
|
|
if (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)) {
|
|
|
|
int x0 = 0, x1 = 0;
|
|
|
|
int y0 = 0, y1 = 0;
|
|
|
|
|
|
|
|
if (mouse & BROWSER_MOUSE_CLICK_1) {
|
|
|
|
bw->drag_type = vert ? DRAGGING_VSCROLL :
|
|
|
|
DRAGGING_HSCROLL;
|
|
|
|
} else
|
|
|
|
bw->drag_type = DRAGGING_2DSCROLL;
|
|
|
|
|
|
|
|
/* \todo - some proper numbers please! */
|
|
|
|
if (bw->drag_type != DRAGGING_VSCROLL) {
|
|
|
|
x0 = -1024;
|
|
|
|
x1 = 1024;
|
|
|
|
}
|
|
|
|
if (bw->drag_type != DRAGGING_HSCROLL) {
|
|
|
|
y0 = -1024;
|
|
|
|
y1 = 1024;
|
|
|
|
}
|
|
|
|
gui_window_box_scroll_start(bw->window, x0, y0, x1, y1);
|
|
|
|
if (bw->drag_type == DRAGGING_2DSCROLL)
|
|
|
|
gui_window_hide_pointer();
|
|
|
|
}
|
2004-11-20 03:02:56 +03:00
|
|
|
} else if (z < w + well_size) {
|
|
|
|
status = messages_get(vert ? "ScrollPDown" : "ScrollPRight");
|
2005-04-15 09:52:25 +04:00
|
|
|
if (mouse & BROWSER_MOUSE_CLICK_1)
|
2004-11-20 03:02:56 +03:00
|
|
|
scroll += page;
|
2005-04-15 09:52:25 +04:00
|
|
|
else if (mouse & BROWSER_MOUSE_CLICK_2)
|
2004-11-20 03:02:56 +03:00
|
|
|
scroll -= page;
|
|
|
|
} else {
|
|
|
|
status = messages_get(vert ? "ScrollDown" : "ScrollRight");
|
2005-04-15 09:52:25 +04:00
|
|
|
if (mouse & BROWSER_MOUSE_CLICK_1)
|
2004-11-20 03:02:56 +03:00
|
|
|
scroll += 16;
|
2005-04-15 09:52:25 +04:00
|
|
|
else if (mouse & BROWSER_MOUSE_CLICK_2)
|
2004-11-20 03:02:56 +03:00
|
|
|
scroll -= 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* update box and redraw */
|
|
|
|
if (vert) {
|
|
|
|
if (scroll < box->descendant_y0)
|
|
|
|
scroll = box->descendant_y0;
|
|
|
|
else if (box->descendant_y1 - box->height < scroll)
|
|
|
|
scroll = box->descendant_y1 - box->height;
|
2005-07-21 03:27:28 +04:00
|
|
|
if (scroll != box->scroll_y)
|
|
|
|
browser_window_scroll_box(bw, box, box->scroll_x, scroll);
|
|
|
|
|
2004-11-20 03:02:56 +03:00
|
|
|
} else {
|
|
|
|
if (scroll < box->descendant_x0)
|
|
|
|
scroll = box->descendant_x0;
|
|
|
|
else if (box->descendant_x1 - box->width < scroll)
|
|
|
|
scroll = box->descendant_x1 - box->width;
|
2005-07-21 03:27:28 +04:00
|
|
|
if (scroll != box->scroll_x)
|
|
|
|
browser_window_scroll_box(bw, box, scroll, box->scroll_y);
|
2004-11-20 03:02:56 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-18 21:38:01 +04:00
|
|
|
/**
|
|
|
|
* Set a radio form control and clear the others in the group.
|
|
|
|
*
|
|
|
|
* \param content content containing the form, of type CONTENT_TYPE
|
|
|
|
* \param radio form control of type GADGET_RADIO
|
|
|
|
*/
|
2004-07-18 03:32:09 +04:00
|
|
|
|
2004-07-18 21:38:01 +04:00
|
|
|
void browser_radio_set(struct content *content,
|
|
|
|
struct form_control *radio)
|
2002-12-31 01:56:30 +03:00
|
|
|
{
|
2004-07-18 21:38:01 +04:00
|
|
|
struct form_control *control;
|
|
|
|
|
2004-11-20 03:02:56 +03:00
|
|
|
assert(content);
|
|
|
|
assert(radio);
|
|
|
|
if (!radio->form)
|
2004-09-30 20:48:04 +04:00
|
|
|
return;
|
|
|
|
|
2004-07-18 21:38:01 +04:00
|
|
|
if (radio->selected)
|
2002-12-31 01:56:30 +03:00
|
|
|
return;
|
2004-07-18 21:38:01 +04:00
|
|
|
|
|
|
|
for (control = radio->form->controls; control;
|
|
|
|
control = control->next) {
|
|
|
|
if (control->type != GADGET_RADIO)
|
|
|
|
continue;
|
|
|
|
if (control == radio)
|
|
|
|
continue;
|
|
|
|
if (strcmp(control->name, radio->name) != 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (control->selected) {
|
|
|
|
control->selected = false;
|
|
|
|
browser_redraw_box(content, control->box);
|
2002-12-31 01:56:30 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-18 21:38:01 +04:00
|
|
|
radio->selected = true;
|
|
|
|
browser_redraw_box(content, radio->box);
|
2002-12-31 01:56:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
/**
|
|
|
|
* 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 width width of rectangle
|
|
|
|
* \param height height of rectangle
|
|
|
|
*/
|
|
|
|
|
|
|
|
void browser_window_redraw_rect(struct browser_window *bw, int x, int y, int width, int height)
|
|
|
|
{
|
|
|
|
struct content *c = bw->current_content;
|
|
|
|
|
|
|
|
if (c && c->type == CONTENT_HTML) {
|
|
|
|
union content_msg_data data;
|
2005-04-15 22:00:21 +04:00
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
data.redraw.x = x;
|
|
|
|
data.redraw.y = y;
|
|
|
|
data.redraw.width = width;
|
|
|
|
data.redraw.height = height;
|
2005-04-15 22:00:21 +04:00
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
data.redraw.full_redraw = true;
|
2005-04-15 22:00:21 +04:00
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
data.redraw.object = c;
|
|
|
|
data.redraw.object_x = 0;
|
|
|
|
data.redraw.object_y = 0;
|
|
|
|
data.redraw.object_width = c->width;
|
|
|
|
data.redraw.object_height = c->height;
|
2005-04-15 22:00:21 +04:00
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
content_broadcast(c, CONTENT_MSG_REDRAW, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-18 21:38:01 +04:00
|
|
|
/**
|
|
|
|
* Redraw a box.
|
|
|
|
*
|
|
|
|
* \param c content containing the box, of type CONTENT_HTML
|
|
|
|
* \param box box to redraw
|
|
|
|
*/
|
2003-04-12 16:38:32 +04:00
|
|
|
|
2004-07-18 21:38:01 +04:00
|
|
|
void browser_redraw_box(struct content *c, struct box *box)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
union content_msg_data data;
|
2002-12-31 01:56:30 +03:00
|
|
|
|
2004-07-18 21:38:01 +04:00
|
|
|
box_coords(box, &x, &y);
|
2002-12-31 01:56:30 +03:00
|
|
|
|
2004-07-18 21:38:01 +04:00
|
|
|
data.redraw.x = x;
|
|
|
|
data.redraw.y = y;
|
2004-10-18 01:11:29 +04:00
|
|
|
data.redraw.width = box->padding[LEFT] + box->width +
|
|
|
|
box->padding[RIGHT];
|
|
|
|
data.redraw.height = box->padding[TOP] + box->height +
|
|
|
|
box->padding[BOTTOM];
|
2004-07-18 21:38:01 +04:00
|
|
|
|
|
|
|
data.redraw.full_redraw = true;
|
2002-12-31 01:56:30 +03:00
|
|
|
|
2004-07-18 21:38:01 +04:00
|
|
|
data.redraw.object = c;
|
|
|
|
data.redraw.object_x = 0;
|
|
|
|
data.redraw.object_y = 0;
|
|
|
|
data.redraw.object_width = c->width;
|
|
|
|
data.redraw.object_height = c->height;
|
2002-12-31 01:56:30 +03:00
|
|
|
|
2004-07-18 21:38:01 +04:00
|
|
|
content_broadcast(c, CONTENT_MSG_REDRAW, data);
|
|
|
|
}
|
2002-12-31 01:56:30 +03:00
|
|
|
|
2003-09-23 01:55:08 +04:00
|
|
|
|
2005-07-21 03:27:28 +04:00
|
|
|
/**
|
|
|
|
* 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 scroll_x new horizontal scroll offset
|
|
|
|
* \param scroll_y new vertical scroll offset
|
|
|
|
*/
|
|
|
|
|
|
|
|
void browser_window_scroll_box(struct browser_window *bw, struct box *box, int scroll_x, int scroll_y)
|
|
|
|
{
|
|
|
|
box->scroll_x = scroll_x;
|
|
|
|
box->scroll_y = scroll_y;
|
|
|
|
|
|
|
|
/* fall back to redrawing the whole box */
|
|
|
|
browser_redraw_box(bw->current_content, box);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-18 03:32:09 +04:00
|
|
|
/**
|
|
|
|
* Process a selection from a form select menu.
|
|
|
|
*
|
|
|
|
* \param bw browser window with menu
|
|
|
|
* \param control form control with menu
|
|
|
|
* \param item index of item selected from the menu
|
|
|
|
*/
|
|
|
|
|
|
|
|
void browser_window_form_select(struct browser_window *bw,
|
|
|
|
struct form_control *control, int item)
|
2002-09-11 18:24:02 +04:00
|
|
|
{
|
2004-07-18 03:32:09 +04:00
|
|
|
struct form_option *o;
|
|
|
|
int count;
|
2005-04-09 13:57:19 +04:00
|
|
|
|
2005-04-08 00:46:22 +04:00
|
|
|
assert(bw);
|
|
|
|
assert(control);
|
2005-04-09 13:57:19 +04:00
|
|
|
|
2004-07-18 03:32:09 +04:00
|
|
|
struct box *inline_box = control->box->children->children;
|
|
|
|
|
|
|
|
for (count = 0, o = control->data.select.items;
|
|
|
|
o != NULL;
|
|
|
|
count++, o = o->next) {
|
|
|
|
if (!control->data.select.multiple)
|
|
|
|
o->selected = false;
|
|
|
|
if (count == item) {
|
|
|
|
if (control->data.select.multiple) {
|
|
|
|
if (o->selected) {
|
|
|
|
o->selected = false;
|
|
|
|
control->data.select.num_selected--;
|
|
|
|
} else {
|
|
|
|
o->selected = true;
|
|
|
|
control->data.select.num_selected++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
o->selected = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (o->selected)
|
|
|
|
control->data.select.current = o;
|
2004-02-25 18:12:58 +03:00
|
|
|
}
|
2004-07-18 03:32:09 +04:00
|
|
|
|
2005-04-09 13:47:37 +04:00
|
|
|
talloc_free(inline_box->text);
|
2004-07-18 03:32:09 +04:00
|
|
|
inline_box->text = 0;
|
|
|
|
if (control->data.select.num_selected == 0)
|
2005-04-09 13:47:37 +04:00
|
|
|
inline_box->text = talloc_strdup(bw->current_content,
|
|
|
|
messages_get("Form_None"));
|
2004-07-18 03:32:09 +04:00
|
|
|
else if (control->data.select.num_selected == 1)
|
2005-04-09 13:47:37 +04:00
|
|
|
inline_box->text = talloc_strdup(bw->current_content,
|
|
|
|
control->data.select.current->text);
|
2004-07-18 03:32:09 +04:00
|
|
|
else
|
2005-04-09 13:47:37 +04:00
|
|
|
inline_box->text = talloc_strdup(bw->current_content,
|
|
|
|
messages_get("Form_Many"));
|
2004-07-18 03:32:09 +04:00
|
|
|
if (!inline_box->text) {
|
|
|
|
warn_user("NoMemory", 0);
|
|
|
|
inline_box->length = 0;
|
|
|
|
} else
|
|
|
|
inline_box->length = strlen(inline_box->text);
|
|
|
|
inline_box->width = control->box->width;
|
|
|
|
|
2004-07-19 19:02:22 +04:00
|
|
|
browser_redraw_box(bw->current_content, control->box);
|
2002-09-11 18:24:02 +04:00
|
|
|
}
|
|
|
|
|
2004-07-18 03:32:09 +04:00
|
|
|
|
2004-07-20 00:40:11 +04:00
|
|
|
gui_pointer_shape get_pointer_shape(css_cursor cursor)
|
|
|
|
{
|
|
|
|
gui_pointer_shape pointer;
|
|
|
|
|
|
|
|
switch (cursor) {
|
|
|
|
case CSS_CURSOR_CROSSHAIR:
|
|
|
|
pointer = GUI_POINTER_CROSS;
|
|
|
|
break;
|
|
|
|
case CSS_CURSOR_POINTER:
|
|
|
|
pointer = GUI_POINTER_POINT;
|
|
|
|
break;
|
|
|
|
case CSS_CURSOR_MOVE:
|
|
|
|
pointer = GUI_POINTER_MOVE;
|
|
|
|
break;
|
|
|
|
case CSS_CURSOR_E_RESIZE:
|
|
|
|
case CSS_CURSOR_W_RESIZE:
|
|
|
|
pointer = GUI_POINTER_LR;
|
|
|
|
break;
|
|
|
|
case CSS_CURSOR_N_RESIZE:
|
|
|
|
case CSS_CURSOR_S_RESIZE:
|
|
|
|
pointer = GUI_POINTER_UD;
|
|
|
|
break;
|
|
|
|
case CSS_CURSOR_NE_RESIZE:
|
|
|
|
case CSS_CURSOR_SW_RESIZE:
|
|
|
|
pointer = GUI_POINTER_LD;
|
|
|
|
break;
|
|
|
|
case CSS_CURSOR_SE_RESIZE:
|
|
|
|
case CSS_CURSOR_NW_RESIZE:
|
|
|
|
pointer = GUI_POINTER_RD;
|
|
|
|
break;
|
|
|
|
case CSS_CURSOR_TEXT:
|
|
|
|
pointer = GUI_POINTER_CARET;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
pointer = GUI_POINTER_DEFAULT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pointer;
|
2004-04-03 03:12:26 +04:00
|
|
|
}
|
|
|
|
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2003-10-25 18:13:49 +04:00
|
|
|
/**
|
|
|
|
* Collect controls and submit a form.
|
|
|
|
*/
|
|
|
|
|
2003-10-25 04:35:49 +04:00
|
|
|
void browser_form_submit(struct browser_window *bw, struct form *form,
|
|
|
|
struct form_control *submit_button)
|
2003-05-22 17:21:45 +04:00
|
|
|
{
|
2003-12-26 03:17:55 +03:00
|
|
|
char *data = 0, *url = 0, *url1 = 0, *base;
|
2003-10-25 04:35:49 +04:00
|
|
|
struct form_successful_control *success;
|
2004-08-09 20:11:58 +04:00
|
|
|
url_func_result res;
|
2003-05-22 17:21:45 +04:00
|
|
|
|
2003-12-11 22:06:39 +03:00
|
|
|
assert(form);
|
2003-12-26 03:17:55 +03:00
|
|
|
assert(bw->current_content->type == CONTENT_HTML);
|
2003-12-11 22:06:39 +03:00
|
|
|
|
2004-08-08 23:13:40 +04:00
|
|
|
if (!form_successful_controls(form, submit_button, &success)) {
|
|
|
|
warn_user("NoMemory", 0);
|
|
|
|
return;
|
|
|
|
}
|
2003-12-26 03:17:55 +03:00
|
|
|
base = bw->current_content->data.html.base_url;
|
2003-10-25 04:35:49 +04:00
|
|
|
|
2003-10-25 18:13:49 +04:00
|
|
|
switch (form->method) {
|
|
|
|
case method_GET:
|
2005-04-16 09:09:33 +04:00
|
|
|
data = form_url_encode(form, success);
|
2004-08-08 23:13:40 +04:00
|
|
|
if (!data) {
|
|
|
|
form_free_successful(success);
|
|
|
|
warn_user("NoMemory", 0);
|
|
|
|
return;
|
|
|
|
}
|
2004-12-08 03:31:11 +03:00
|
|
|
url = calloc(1, strlen(form->action) + strlen(data) + 2);
|
|
|
|
if (!url) {
|
|
|
|
form_free_successful(success);
|
|
|
|
warn_user("NoMemory", 0);
|
|
|
|
return;
|
|
|
|
}
|
2004-02-03 02:38:02 +03:00
|
|
|
if(form->action[strlen(form->action)-1] == '?') {
|
2004-07-20 00:40:11 +04:00
|
|
|
sprintf(url, "%s%s", form->action, data);
|
2004-02-03 02:38:02 +03:00
|
|
|
}
|
|
|
|
else {
|
2004-07-20 00:40:11 +04:00
|
|
|
sprintf(url, "%s?%s", form->action, data);
|
2004-02-03 02:38:02 +03:00
|
|
|
}
|
2004-08-09 20:11:58 +04:00
|
|
|
res = url_join(url, base, &url1);
|
|
|
|
if (res != URL_FUNC_OK)
|
2003-12-26 03:17:55 +03:00
|
|
|
break;
|
2005-01-25 01:14:59 +03:00
|
|
|
browser_window_go(bw, url1, bw->current_content->url);
|
2004-07-20 00:40:11 +04:00
|
|
|
break;
|
2004-02-25 18:12:58 +03:00
|
|
|
|
2004-07-20 00:40:11 +04:00
|
|
|
case method_POST_URLENC:
|
2005-04-16 09:09:33 +04:00
|
|
|
data = form_url_encode(form, success);
|
2004-08-08 23:13:40 +04:00
|
|
|
if (!data) {
|
|
|
|
form_free_successful(success);
|
|
|
|
warn_user("NoMemory", 0);
|
|
|
|
return;
|
|
|
|
}
|
2004-08-09 20:11:58 +04:00
|
|
|
res = url_join(form->action, base, &url);
|
|
|
|
if (res != URL_FUNC_OK)
|
2003-12-26 03:17:55 +03:00
|
|
|
break;
|
2004-10-02 01:31:55 +04:00
|
|
|
browser_window_go_post(bw, url, data, 0, true,
|
2005-01-03 05:09:20 +03:00
|
|
|
bw->current_content->url, false);
|
2004-07-20 00:40:11 +04:00
|
|
|
break;
|
2003-10-25 18:13:49 +04:00
|
|
|
|
2004-07-20 00:40:11 +04:00
|
|
|
case method_POST_MULTIPART:
|
2004-08-09 20:11:58 +04:00
|
|
|
res = url_join(form->action, base, &url);
|
|
|
|
if (res != URL_FUNC_OK)
|
2004-03-02 21:02:41 +03:00
|
|
|
break;
|
2004-10-02 01:31:55 +04:00
|
|
|
browser_window_go_post(bw, url, 0, success, true,
|
2005-01-03 05:09:20 +03:00
|
|
|
bw->current_content->url, false);
|
2004-07-20 00:40:11 +04:00
|
|
|
break;
|
2004-02-25 18:12:58 +03:00
|
|
|
|
2004-07-20 00:40:11 +04:00
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
}
|
2003-05-22 17:21:45 +04:00
|
|
|
|
2003-10-25 04:35:49 +04:00
|
|
|
form_free_successful(success);
|
2003-12-26 03:17:55 +03:00
|
|
|
free(data);
|
|
|
|
free(url);
|
|
|
|
free(url1);
|
2003-05-22 17:21:45 +04:00
|
|
|
}
|
2005-04-15 09:52:25 +04:00
|
|
|
|
|
|
|
|
2005-07-24 10:13:25 +04:00
|
|
|
/**
|
|
|
|
* Pick the text box child of 'box' that is closest to and above left 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
|
|
|
|
* \return ptr to the nearest box, or NULL if none found
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct box *browser_window_nearest_text_box(struct box *box, int x, int y)
|
|
|
|
{
|
|
|
|
struct box *child = box->children;
|
|
|
|
struct box *nearest = NULL;
|
|
|
|
int nr_yd = INT_MAX;
|
|
|
|
int nr_xd = INT_MAX;
|
|
|
|
|
|
|
|
while (child) {
|
|
|
|
if (child->text && !child->object && child->y <= y && child->x <= x) {
|
|
|
|
int yd = y - (child->y + child->padding[TOP] + child->height + child->padding[BOTTOM]);
|
|
|
|
int xd = x - (child->x + child->padding[LEFT] + child->width + child->padding[RIGHT]);
|
|
|
|
|
|
|
|
/* give y displacement precedence of x */
|
|
|
|
if (yd < nr_yd || (yd == nr_yd && xd <= nr_xd)) {
|
|
|
|
nr_yd = yd;
|
|
|
|
nr_xd = xd;
|
|
|
|
nearest = child;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
child = child->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nearest;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-15 09:52:25 +04:00
|
|
|
/**
|
|
|
|
* Peform pick text on browser window contents to locate the box under
|
|
|
|
* the mouse pointer
|
|
|
|
*
|
|
|
|
* \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
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct box *browser_window_pick_text_box(struct browser_window *bw,
|
|
|
|
browser_mouse_state mouse, int x, int y, int *dx, int *dy)
|
|
|
|
{
|
|
|
|
struct content *c = bw->current_content;
|
|
|
|
struct box *text_box = NULL;
|
|
|
|
|
2005-07-24 10:13:25 +04:00
|
|
|
if (c && c->type == CONTENT_HTML) {
|
|
|
|
struct box *box = c->data.html.layout;
|
|
|
|
int box_x = 0, box_y = 0;
|
|
|
|
struct content *content;
|
|
|
|
struct box *next_box;
|
2005-04-15 09:52:25 +04:00
|
|
|
|
2005-07-24 10:13:25 +04:00
|
|
|
while ((next_box = box_at_point(box, x, y, &box_x, &box_y, &content)) !=
|
|
|
|
NULL) {
|
|
|
|
box = next_box;
|
2005-04-15 22:00:21 +04:00
|
|
|
|
2005-07-24 10:13:25 +04:00
|
|
|
if (box->text && !box->object)
|
|
|
|
text_box = box;
|
|
|
|
}
|
2005-04-15 09:52:25 +04:00
|
|
|
|
2005-07-24 10:13:25 +04:00
|
|
|
if (!text_box) {
|
|
|
|
box = browser_window_nearest_text_box(box, x - box_x, y - box_y);
|
2005-04-15 09:52:25 +04:00
|
|
|
|
2005-07-24 10:13:25 +04:00
|
|
|
if (box->text && !box->object) {
|
|
|
|
|
|
|
|
box_x += box->x - box->scroll_x;
|
|
|
|
box_y += box->y - box->scroll_y;
|
|
|
|
|
|
|
|
int y1 = box_y + (box->padding[TOP] + box->height + box->padding[BOTTOM]);
|
|
|
|
int x1 = box_x + (box->padding[LEFT] + box->width + box->padding[RIGHT]);
|
|
|
|
|
|
|
|
if (y > y1) y = y1;
|
|
|
|
if (x > x1) x = x1;
|
|
|
|
|
|
|
|
text_box = box;
|
|
|
|
}
|
2005-04-15 09:52:25 +04:00
|
|
|
}
|
2005-07-24 10:13:25 +04:00
|
|
|
|
|
|
|
/* return coordinates relative to box */
|
|
|
|
*dx = x - box_x;
|
|
|
|
*dy = y - box_y;
|
2005-04-15 09:52:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return text_box;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Start drag scrolling the contents of the browser window
|
|
|
|
*
|
|
|
|
* \param bw browser window
|
|
|
|
* \param x x ordinate of initial mouse position
|
|
|
|
* \param y y ordinate
|
|
|
|
*/
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
gui_window_get_scroll(bw->window, &bw->scrolling_start_scroll_x, &bw->scrolling_start_scroll_y);
|
|
|
|
|
|
|
|
gui_window_scroll_start(bw->window);
|
|
|
|
}
|
|
|
|
|