summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riscos/bitmap.c18
-rw-r--r--riscos/dialog.c26
-rw-r--r--riscos/download.c4
-rw-r--r--riscos/gui.c97
-rw-r--r--riscos/gui.h37
-rw-r--r--riscos/print.c1
-rw-r--r--riscos/save.c396
-rw-r--r--riscos/save_draw.c2
-rw-r--r--riscos/textselection.c378
-rw-r--r--riscos/thumbnail.c2
-rw-r--r--riscos/uri.c2
-rw-r--r--riscos/window.c251
12 files changed, 1000 insertions, 214 deletions
diff --git a/riscos/bitmap.c b/riscos/bitmap.c
index f30f43957..7bdf1bde4 100644
--- a/riscos/bitmap.c
+++ b/riscos/bitmap.c
@@ -102,9 +102,23 @@ bool bitmap_test_opaque(struct bitmap *bitmap)
(osspriteop_header *) (&(bitmap->sprite_area) + 1);
unsigned int height = (sprite_header->height + 1);
unsigned int size = width * height;
- for (unsigned int i = 3; i < size; i += 4)
- if (sprite[i] != 0xff)
+ unsigned *p = (unsigned*)sprite;
+ unsigned *ep;
+
+ ep = (unsigned*)(sprite + (size & ~31));
+ while (p < ep) {
+ /* \todo prefetch(p, 128)? */
+ if (((p[0] & p[1] & p[2] & p[3] & p[4] & p[5] & p[6] & p[7])
+ & 0xff000000U) != 0xff000000U)
return false;
+ p += 8;
+ }
+ ep = (unsigned*)(sprite + size);
+ while (p < ep) {
+ if ((*p & 0xff000000U) != 0xff000000U) return false;
+ p++;
+ }
+
return true;
}
diff --git a/riscos/dialog.c b/riscos/dialog.c
index 039246c65..1775d616c 100644
--- a/riscos/dialog.c
+++ b/riscos/dialog.c
@@ -297,23 +297,24 @@ void ro_gui_dialog_open(wimp_w w)
void ro_gui_dialog_open_persistant(wimp_w parent, wimp_w w, bool pointer) {
int dx, dy, i;
- wimp_pointer ptr;
wimp_window_state open;
os_error *error;
- /* Get the pointer position
- */
- error = xwimp_get_pointer_info(&ptr);
- if (error) {
- LOG(("xwimp_get_pointer_info: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("WimpError", error->errmess);
- return;
- }
-
/* Move and open
*/
if (pointer) {
+ wimp_pointer ptr;
+
+ /* Get the pointer position
+ */
+ error = xwimp_get_pointer_info(&ptr);
+ if (error) {
+ LOG(("xwimp_get_pointer_info: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+
open.w = w;
error = xwimp_get_window_state(&open);
if (error) {
@@ -417,7 +418,8 @@ bool ro_gui_dialog_keypress(wimp_key *key)
pointer.buttons = wimp_CLICK_SELECT;
ro_gui_hotlist_dialog_click(&pointer);
return true;
- }
+ } else if (key->w == dialog_saveas)
+ ro_gui_save_ok(key->w);
}
#ifdef WITH_AUTH
if (key->w == dialog_401li)
diff --git a/riscos/download.c b/riscos/download.c
index c036c13bb..2aad93013 100644
--- a/riscos/download.c
+++ b/riscos/download.c
@@ -472,9 +472,10 @@ void ro_gui_download_window_click(struct gui_download_window *dw,
if (pointer->i == ICON_DOWNLOAD_ICON && !dw->error &&
!dw->saved) {
+ const char *sprite = ro_gui_get_icon_string(pointer->w, pointer->i);
gui_current_drag_type = GUI_DRAG_DOWNLOAD_SAVE;
download_window_current = dw;
- ro_gui_drag_icon(pointer);
+ ro_gui_drag_icon(pointer->pos.x, pointer->pos.y, sprite);
} else if (pointer->i == ICON_DOWNLOAD_DESTINATION) {
strncpy(command + 14, dw->path, 242);
@@ -527,6 +528,7 @@ void ro_gui_download_drag_end(wimp_dragged *drag)
dw->received;
message.data.data_xfer.file_type = dw->file_type;
strncpy(message.data.data_xfer.file_name, dw->path, 212);
+ message.data.data_xfer.file_name[211] = 0;
message.size = 44 + ((strlen(message.data.data_xfer.file_name) + 4) &
(~3u));
diff --git a/riscos/gui.c b/riscos/gui.c
index 881443277..59589040f 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -133,7 +133,7 @@ static clock_t gui_last_poll; /**< Time of last wimp_poll. */
osspriteop_area *gui_sprites; /**< Sprite area containing pointer and hotlist sprites */
/** Accepted wimp user messages. */
-static wimp_MESSAGE_LIST(34) task_messages = { {
+static wimp_MESSAGE_LIST(36) task_messages = { {
message_HELP_REQUEST,
message_DATA_SAVE,
message_DATA_SAVE_ACK,
@@ -143,6 +143,8 @@ static wimp_MESSAGE_LIST(34) task_messages = { {
message_MENU_WARNING,
message_MENUS_DELETED,
message_MODE_CHANGE,
+ message_CLAIM_ENTITY,
+ message_DATA_REQUEST,
#ifdef WITH_URI
message_URI_PROCESS,
message_URI_RETURN_RESULT,
@@ -635,16 +637,27 @@ void gui_poll(bool active)
xhourglass_off();
if (active) {
event = wimp_poll(mask, &block, 0);
- } else if (sched_active && (gui_track || gui_reformat_pending)) {
- os_t t = os_read_monotonic_time() + 10;
- if (sched_time < t)
+ } else if (sched_active || gui_track || gui_reformat_pending) {
+ os_t t = os_read_monotonic_time();
+
+ if (gui_track)
+ switch (gui_current_drag_type) {
+ case GUI_DRAG_SELECTION:
+ case GUI_DRAG_SCROLL:
+ t += 4; /* for smoother update */
+ break;
+
+ default:
+ t += 10;
+ break;
+ }
+ else
+ t += 10;
+
+ if (sched_active && (sched_time - t) < 0)
t = sched_time;
+
event = wimp_poll_idle(mask, &block, t, 0);
- } else if (sched_active) {
- event = wimp_poll_idle(mask, &block, sched_time, 0);
- } else if (gui_track || gui_reformat_pending) {
- os_t t = os_read_monotonic_time();
- event = wimp_poll_idle(mask, &block, t + 10, 0);
} else {
event = wimp_poll(wimp_MASK_NULL | mask, &block, 0);
}
@@ -814,17 +827,31 @@ void ro_gui_null_reason_code(void)
error = xwimp_get_pointer_info(&pointer);
if (error) {
LOG(("xwimp_get_pointer_info: 0x%x: %s",
- error->errnum, error->errmess));
+ error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
return;
}
- if (gui_track_wimp_w == history_window)
- ro_gui_history_mouse_at(&pointer);
- if (gui_track_wimp_w == dialog_url_complete)
- ro_gui_url_complete_mouse_at(&pointer, false);
- else if (gui_track_gui_window)
- ro_gui_window_mouse_at(gui_track_gui_window, &pointer);
+ switch (gui_current_drag_type) {
+
+ /* pointer is allowed to wander outside the initiating window
+ for certain drag types */
+
+ case GUI_DRAG_SELECTION:
+ case GUI_DRAG_SCROLL:
+ assert(gui_track_gui_window);
+ ro_gui_window_mouse_at(gui_track_gui_window, &pointer);
+ break;
+
+ default:
+ if (gui_track_wimp_w == history_window)
+ ro_gui_history_mouse_at(&pointer);
+ if (gui_track_wimp_w == dialog_url_complete)
+ ro_gui_url_complete_mouse_at(&pointer, false);
+ else if (gui_track_gui_window)
+ ro_gui_window_mouse_at(gui_track_gui_window, &pointer);
+ break;
+ }
}
@@ -938,10 +965,8 @@ void ro_gui_close_window_request(wimp_close *close)
void ro_gui_pointer_leaving_window(wimp_leaving *leaving)
{
- os_error *error;
-
if (gui_track_wimp_w == history_window) {
- error = xwimp_close_window(dialog_tooltip);
+ os_error *error = xwimp_close_window(dialog_tooltip);
if (error) {
LOG(("xwimp_close_window: 0x%x: %s",
error->errnum, error->errmess));
@@ -949,8 +974,18 @@ void ro_gui_pointer_leaving_window(wimp_leaving *leaving)
}
}
- gui_track = false;
- gui_window_set_pointer(GUI_POINTER_DEFAULT);
+ switch (gui_current_drag_type) {
+ case GUI_DRAG_SELECTION:
+ case GUI_DRAG_SCROLL:
+ /* ignore Pointer_Leaving_Window event that the Wimp mysteriously
+ issues when a Wimp_DragBox drag operations is started */
+ break;
+
+ default:
+ gui_track = false;
+ gui_window_set_pointer(GUI_POINTER_DEFAULT);
+ break;
+ }
}
@@ -1057,7 +1092,11 @@ void ro_gui_drag_end(wimp_dragged *drag)
{
switch (gui_current_drag_type) {
case GUI_DRAG_SELECTION:
- ro_gui_selection_drag_end(drag);
+ ro_gui_selection_drag_end(gui_track_gui_window, drag);
+ break;
+
+ case GUI_DRAG_SCROLL:
+ ro_gui_window_scroll_end(gui_track_gui_window, drag);
break;
case GUI_DRAG_DOWNLOAD_SAVE:
@@ -1082,6 +1121,10 @@ void ro_gui_drag_end(wimp_dragged *drag)
case GUI_DRAG_TOOLBAR_CONFIG:
ro_gui_theme_toolbar_editor_drag_end(drag);
break;
+
+ default:
+ assert(gui_current_drag_type == GUI_DRAG_NONE);
+ break;
}
}
@@ -1163,14 +1206,24 @@ void ro_gui_user_message(wimp_event_no event, wimp_message *message)
ro_gui_menu_warning((wimp_message_menu_warning *)
&message->data);
break;
+
case message_MENUS_DELETED:
ro_gui_menu_closed();
break;
+
case message_MODE_CHANGE:
ro_gui_history_mode_change();
rufl_invalidate_cache();
break;
+ case message_CLAIM_ENTITY:
+ ro_gui_selection_claim_entity((wimp_full_message_claim_entity*)message);
+ break;
+
+ case message_DATA_REQUEST:
+ ro_gui_selection_data_request((wimp_full_message_data_request*)message);
+ break;
+
#ifdef WITH_URI
case message_URI_PROCESS:
if (event != wimp_USER_MESSAGE_ACKNOWLEDGE)
diff --git a/riscos/gui.h b/riscos/gui.h
index 4a392e6d9..875a7450b 100644
--- a/riscos/gui.h
+++ b/riscos/gui.h
@@ -26,6 +26,8 @@ extern const char * NETSURF_DIR;
struct toolbar;
struct plotter_table;
+extern wimp_t task_handle; /**< RISC OS wimp task handle. */
+
extern wimp_w dialog_info, dialog_saveas, dialog_config, dialog_config_br,
dialog_config_prox, dialog_config_th, dialog_zoom, dialog_pageinfo,
dialog_objinfo, dialog_tooltip, dialog_warning, dialog_openurl,
@@ -42,24 +44,11 @@ extern bool dialog_folder_add, dialog_entry_add, hotlist_insert;
extern bool print_active, print_text_black;
extern struct tree *hotlist_tree, *global_history_tree;
-typedef enum {
- GUI_SAVE_SOURCE,
- GUI_SAVE_DRAW,
- GUI_SAVE_TEXT,
- GUI_SAVE_COMPLETE,
- GUI_SAVE_OBJECT_ORIG,
- GUI_SAVE_OBJECT_NATIVE,
- GUI_SAVE_LINK_URI,
- GUI_SAVE_LINK_URL,
- GUI_SAVE_LINK_TEXT,
- GUI_SAVE_HOTLIST_EXPORT_HTML,
- GUI_SAVE_HISTORY_EXPORT_HTML,
-} gui_save_type;
-
-typedef enum { GUI_DRAG_SELECTION, GUI_DRAG_DOWNLOAD_SAVE,
- GUI_DRAG_SAVE, GUI_DRAG_STATUS_RESIZE,
+typedef enum { GUI_DRAG_NONE, GUI_DRAG_SELECTION, GUI_DRAG_DOWNLOAD_SAVE,
+ GUI_DRAG_SAVE, GUI_DRAG_SCROLL, GUI_DRAG_STATUS_RESIZE,
GUI_DRAG_TREE_SELECT, GUI_DRAG_TREE_MOVE,
GUI_DRAG_TOOLBAR_CONFIG } gui_drag_type;
+
extern gui_drag_type gui_current_drag_type;
@@ -139,10 +128,10 @@ void ro_gui_download_window_destroy(struct gui_download_window *dw);
void ro_gui_mouse_action(struct gui_window *g);
/* in textselection.c */
-void ro_gui_start_selection(wimp_pointer *pointer, wimp_window_state *state,
- struct gui_window *g);
-void ro_gui_selection_drag_end(wimp_dragged *drag);
-void ro_gui_copy_selection(struct gui_window *g);
+void ro_gui_selection_drag_end(struct gui_window *g, wimp_dragged *drag);
+void ro_gui_selection_claim_entity(wimp_full_message_claim_entity *claim);
+void ro_gui_selection_data_request(wimp_full_message_data_request *req);
+bool ro_gui_save_clipboard(const char *path);
/* in 401login.c */
#ifdef WITH_AUTH
@@ -177,6 +166,10 @@ void ro_gui_window_process_reformats(void);
void ro_gui_window_default_options(struct browser_window *bw);
void ro_gui_window_redraw_all(void);
void ro_gui_window_prepare_navigate_all(void);
+browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons);
+bool ro_gui_shift_pressed(void);
+bool ro_gui_ctrl_pressed(void);
+void ro_gui_window_scroll_end(struct gui_window *g, wimp_dragged *drag);
/* in history.c */
void ro_gui_history_init(void);
@@ -199,9 +192,11 @@ int ro_gui_hotlist_help(int x, int y);
/* in save.c */
void ro_gui_save_prepare(gui_save_type save_type, struct content *c);
void ro_gui_save_click(wimp_pointer *pointer);
-void ro_gui_drag_icon(wimp_pointer *pointer);
+void ro_gui_drag_icon(int x, int y, const char *sprite);
void ro_gui_save_drag_end(wimp_dragged *drag);
+void ro_gui_send_datasave(gui_save_type save_type, const wimp_full_message_data_xfer *message, wimp_t to);
void ro_gui_save_datasave_ack(wimp_message *message);
+void ro_gui_save_ok(wimp_w w);
/* in filetype.c */
int ro_content_filetype(struct content *content);
diff --git a/riscos/print.c b/riscos/print.c
index f136fe100..94f067783 100644
--- a/riscos/print.c
+++ b/riscos/print.c
@@ -541,6 +541,7 @@ bool print_document(struct gui_window *g, const char *filename)
plot = ro_plotters;
ro_plot_set_scale(print_scale);
ro_gui_current_redraw_gui = g;
+ current_redraw_browser = NULL; /* we don't want to print the selection */
/* print is now active */
print_active = true;
diff --git a/riscos/save.c b/riscos/save.c
index 977bbe139..1714a7e14 100644
--- a/riscos/save.c
+++ b/riscos/save.c
@@ -16,10 +16,12 @@
#include <stdlib.h>
#include <string.h>
#include "oslib/dragasprite.h"
+#include "oslib/osbyte.h"
#include "oslib/osfile.h"
#include "oslib/osspriteop.h"
#include "oslib/wimp.h"
#include "netsurf/desktop/save_text.h"
+#include "netsurf/desktop/selection.h"
#include "netsurf/image/bitmap.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/menus.h"
@@ -33,13 +35,19 @@
#include "netsurf/utils/url.h"
#include "netsurf/utils/utils.h"
+
static gui_save_type gui_save_current_type;
-static struct content *gui_save_content = 0;
+static struct content *gui_save_content = NULL;
+static struct selection *gui_save_selection = NULL;
static int gui_save_filetype;
+static bool using_dragasprite = true;
+static wimp_w gui_save_dialogw = (wimp_w)-1;
+
typedef enum { LINK_ACORN, LINK_ANT, LINK_TEXT } link_format;
static bool ro_gui_save_complete(struct content *c, char *path);
+static bool ro_gui_save_content(struct content *c, char *path);
static void ro_gui_save_object_native(struct content *c, char *path);
static bool ro_gui_save_link(struct content *c, link_format format, char *path);
@@ -65,6 +73,7 @@ struct gui_save_table_entry gui_save_table[] = {
/* GUI_SAVE_LINK_TEXT, */ { 0xfff, "SaveLink" },
/* GUI_SAVE_HOTLIST_EXPORT_HTML, */ { 0xfaf, "Hotlist" },
/* GUI_SAVE_HISTORY_EXPORT_HTML, */ { 0xfaf, "History" },
+ /* GUI_SAVE_TEXT_SELECTION, */ { 0xfff, "SaveText" },
};
@@ -105,10 +114,11 @@ void ro_gui_save_prepare(gui_save_type save_type, struct content *c)
/* filename */
name = gui_save_table[save_type].name;
- if (c) {
- if ((res = url_nice(c->url, (char **)&nice)) == URL_FUNC_OK)
- name = nice;
- }
+ if (c && (res = url_nice(c->url, (char **)&nice)) == URL_FUNC_OK)
+ name = nice;
+ else
+ name = messages_get(name);
+
ro_gui_set_icon_string(dialog_saveas, ICON_SAVE_PATH, name);
}
@@ -119,21 +129,23 @@ void ro_gui_save_prepare(gui_save_type save_type, struct content *c)
void ro_gui_save_click(wimp_pointer *pointer)
{
switch (pointer->i) {
- case ICON_SAVE_OK:
- /* Todo: Try save, and report error NoPathError if needed */
- break;
- case ICON_SAVE_CANCEL:
- if (pointer->buttons == wimp_CLICK_SELECT) {
- xwimp_create_menu((wimp_menu *)-1, 0, 0);
- ro_gui_dialog_close(pointer->w);
- } else if (pointer->buttons == wimp_CLICK_ADJUST) {
+ case ICON_SAVE_OK:
+ ro_gui_save_ok(pointer->w);
+ break;
+ case ICON_SAVE_CANCEL:
+ if (pointer->buttons == wimp_CLICK_SELECT) {
+ xwimp_create_menu((wimp_menu *)-1, 0, 0);
+ ro_gui_dialog_close(pointer->w);
+ } else if (pointer->buttons == wimp_CLICK_ADJUST) {
/* ro_gui_menu_prepare_save(gui_save_content); */
}
break;
case ICON_SAVE_ICON:
if (pointer->buttons == wimp_DRAG_SELECT) {
+ const char *sprite = ro_gui_get_icon_string(pointer->w, pointer->i);
gui_current_drag_type = GUI_DRAG_SAVE;
- ro_gui_drag_icon(pointer);
+ gui_save_dialogw = pointer->w;
+ ro_gui_drag_icon(pointer->pos.x, pointer->pos.y, sprite);
}
break;
}
@@ -141,51 +153,188 @@ void ro_gui_save_click(wimp_pointer *pointer)
/**
- * Start drag of icon under the pointer.
+ * Handle OK click/keypress in the save dialog.
+ */
+
+void ro_gui_save_ok(wimp_w w)
+{
+ char *name = ro_gui_get_icon_string(w, ICON_SAVE_PATH);
+ if (!strrchr(name, '.'))
+ {
+ warn_user("NoPathError", NULL);
+ return;
+ }
+ gui_save_dialogw = w;
+ if (ro_gui_save_content(gui_save_content, name)) {
+ xwimp_create_menu((wimp_menu *)-1, 0, 0);
+ ro_gui_dialog_close(w);
+ }
+}
+
+
+/**
+ * Initiates drag saving of an object directly from a browser window
+ *
+ * \param save_type type of save
+ * \param c content to save
*/
-void ro_gui_drag_icon(wimp_pointer *pointer)
+void gui_drag_save_object(gui_save_type save_type, struct content *c)
{
- char *sprite;
- os_box box = { pointer->pos.x - 34, pointer->pos.y - 34,
- pointer->pos.x + 34, pointer->pos.y + 34 };
+ wimp_pointer pointer;
+ char icon_buf[20];
+ const char *icon = icon_buf;
os_error *error;
- if (pointer->i == -1)
+ /* Close the save window because otherwise we need two contexts
+ */
+ if (gui_save_dialogw != (wimp_w)-1)
+ ro_gui_dialog_close(gui_save_dialogw);
+
+ gui_save_dialogw = (wimp_w)-1;
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG(("xwimp_get_pointer_info: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
return;
+ }
+
+ gui_save_current_type = save_type;
+ gui_save_content = c;
+ gui_save_filetype = gui_save_table[save_type].filetype;
+ if (!gui_save_filetype)
+ gui_save_filetype = ro_content_filetype(c);
+
+ /* sprite to use */
+ sprintf(icon_buf, "file_%.3x", gui_save_filetype);
+ if (!ro_gui_wimp_sprite_exists(icon_buf))
+ icon = "file_xxx";
+
+ gui_current_drag_type = GUI_DRAG_SAVE;
+
+ ro_gui_drag_icon(pointer.pos.x, pointer.pos.y, icon);
+}
+
+
+void gui_drag_save_selection(struct selection *s)
+{
+ wimp_pointer pointer;
+ char icon_buf[20];
+ const char *icon = icon_buf;
+ os_error *error;
- sprite = ro_gui_get_icon_string(pointer->w, pointer->i);
+ /* Close the save window because otherwise we need two contexts
+ */
+ if (gui_save_dialogw != (wimp_w)-1)
+ ro_gui_dialog_close(gui_save_dialogw);
- error = xdragasprite_start(dragasprite_HPOS_CENTRE |
- dragasprite_VPOS_CENTRE |
- dragasprite_BOUND_POINTER |
- dragasprite_DROP_SHADOW,
- (osspriteop_area *) 1, sprite, &box, 0);
+ gui_save_dialogw = (wimp_w)-1;
+
+ error = xwimp_get_pointer_info(&pointer);
if (error) {
+ LOG(("xwimp_get_pointer_info: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ gui_save_current_type = GUI_SAVE_TEXT_SELECTION;
+ gui_save_content = NULL;
+ gui_save_selection = s;
+ gui_save_filetype = gui_save_table[GUI_SAVE_TEXT_SELECTION].filetype;
+
+ /* sprite to use */
+ sprintf(icon_buf, "file_%.3x", gui_save_filetype);
+ if (!ro_gui_wimp_sprite_exists(icon_buf))
+ icon = "file_xxx";
+
+ gui_current_drag_type = GUI_DRAG_SAVE;
+
+ ro_gui_drag_icon(pointer.pos.x, pointer.pos.y, icon);
+}
+
+
+/**
+ * Start drag of icon under the pointer.
+ */
+
+void ro_gui_drag_icon(int x, int y, const char *sprite)
+{
+ os_error *error;
+ wimp_drag drag;
+ int r2;
+
+ drag.initial.x0 = x - 34;
+ drag.initial.y0 = y - 34;
+ drag.initial.x1 = x + 34;
+ drag.initial.y1 = y + 34;
+
+ if (sprite && (xosbyte2(osbyte_READ_CMOS, 28, 0, &r2) || (r2 & 2))) {
+ error = xdragasprite_start(dragasprite_HPOS_CENTRE |
+ dragasprite_VPOS_CENTRE |
+ dragasprite_BOUND_POINTER |
+ dragasprite_DROP_SHADOW,
+ (osspriteop_area *) 1, sprite, &drag.initial, 0);
+
+ if (!error) {
+ using_dragasprite = true;
+ return;
+ }
+
LOG(("xdragasprite_start: 0x%x: %s",
error->errnum, error->errmess));
+ }
+
+ drag.type = wimp_DRAG_USER_FIXED;
+ drag.bbox.x0 = -0x8000;
+ drag.bbox.y0 = -0x8000;
+ drag.bbox.x1 = 0x7fff;
+ drag.bbox.y1 = 0x7fff;
+
+ using_dragasprite = false;
+ error = xwimp_drag_box(&drag);
+
+ if (error) {
+ LOG(("xwimp_drag_box: 0x%x: %s",
+ error->errnum, error->errmess));
warn_user("DragError", error->errmess);
}
}
/**
- * Handle User_Drag_Box event for a drag from the save dialog.
+ * Handle User_Drag_Box event for a drag from the save dialog or browser window.
*/
void ro_gui_save_drag_end(wimp_dragged *drag)
{
- char *name;
- char *dot;
+ const char *name;
wimp_pointer pointer;
wimp_message message;
wimp_get_pointer_info(&pointer);
- name = ro_gui_get_icon_string(dialog_saveas, ICON_SAVE_PATH);
- dot = strrchr(name, '.');
- if (dot)
- name = dot + 1;
+ if (gui_save_dialogw == (wimp_w)-1) {
+ /* saving directly from browser window, choose a name based upon the URL */
+ struct content *c = gui_save_content;
+ const char *nice;
+ name = gui_save_table[gui_save_current_type].name;
+ if (c) {
+ url_func_result res;
+ if ((res = url_nice(c->url, (char **)&nice)) == URL_FUNC_OK)
+ name = nice;
+ }
+ }
+ else {
+ /* saving from dialog, grab leafname from icon */
+ char *dot;
+ name = ro_gui_get_icon_string(gui_save_dialogw, ICON_SAVE_PATH);
+ dot = strrchr(name, '.');
+ if (dot)
+ name = dot + 1;
+ }
message.your_ref = 0;
message.action = message_DATA_SAVE;
@@ -215,49 +364,110 @@ void ro_gui_save_drag_end(wimp_dragged *drag)
}
+
/**
- * Handle Message_DataSaveAck for a drag from the save dialog.
+ * Send DataSave message on behalf of clipboard code and remember that it's the
+ * clipboard contents we're being asked for when the DataSaveAck reply arrives
*/
-void ro_gui_save_datasave_ack(wimp_message *message)
+void ro_gui_send_datasave(gui_save_type save_type, const wimp_full_message_data_xfer *message, wimp_t to)
{
- char *path = message->data.data_xfer.file_name;
- struct content *c = gui_save_content;
os_error *error;
- if (!gui_save_content &&
- (gui_save_current_type != GUI_SAVE_HOTLIST_EXPORT_HTML) &&
- (gui_save_current_type != GUI_SAVE_HISTORY_EXPORT_HTML)) {
- LOG(("unexpected DataSaveAck: gui_save_content not set"));
- return;
+ /* Close the save window because otherwise we need two contexts
+ */
+ if (gui_save_dialogw != (wimp_w)-1)
+ ro_gui_dialog_close(gui_save_dialogw);
+
+ error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)message, to);
+ if (error) {
+ LOG(("xwimp_send_message: 0x%x: %s", error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
}
+ else {
+ gui_save_current_type = save_type;
+ gui_save_dialogw = (wimp_w)-1;
+ gui_current_drag_type = GUI_DRAG_SAVE;
+ }
+}
+
- ro_gui_set_icon_string(dialog_saveas, ICON_SAVE_PATH, path);
+/**
+ * Handle Message_DataSaveAck for a drag from the save dialog or browser window.
+ */
+
+void ro_gui_save_datasave_ack(wimp_message *message)
+{
+ char *path = message->data.data_xfer.file_name;
+ struct content *c = gui_save_content;
switch (gui_save_current_type) {
- case GUI_SAVE_SOURCE:
- error = xosfile_save_stamped(path,
- ro_content_filetype(c),
- c->source_data,
- c->source_data + c->source_size);
- if (error) {
- LOG(("xosfile_save_stamped: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("SaveError", error->errmess);
- return;
- }
+ case GUI_SAVE_HOTLIST_EXPORT_HTML:
+ case GUI_SAVE_HISTORY_EXPORT_HTML:
+ case GUI_SAVE_TEXT_SELECTION:
+ case GUI_SAVE_CLIPBOARD_CONTENTS:
break;
-#ifdef WITH_SAVE_COMPLETE
- case GUI_SAVE_COMPLETE:
- if (!ro_gui_save_complete(c, path))
+
+ default:
+ if (!gui_save_content) {
+ LOG(("unexpected DataSaveAck: gui_save_content not set"));
return;
+ }
break;
-#endif
+ }
+
+ if (gui_save_dialogw != (wimp_w)-1)
+ ro_gui_set_icon_string(gui_save_dialogw, ICON_SAVE_PATH, path);
+
+ if (ro_gui_save_content(c, path)) {
+ os_error *error;
+
+ if (gui_save_dialogw != (wimp_w)-1) {
+ /* Close the save window
+ */
+ ro_gui_dialog_close(gui_save_dialogw);
+ }
+
+ /* Ack successful save with message_DATA_LOAD */
+ message->action = message_DATA_LOAD;
+ message->your_ref = message->my_ref;
+ error = xwimp_send_message_to_window(wimp_USER_MESSAGE, message,
+ message->data.data_xfer.w, message->data.data_xfer.i, 0);
+ if (error) {
+ LOG(("xwimp_send_message_to_window: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("SaveError", error->errmess);
+ }
+
+ error = xwimp_create_menu(wimp_CLOSE_MENU, 0, 0);
+ if (error) {
+ LOG(("xwimp_create_menu: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("MenuError", error->errmess);
+ }
+
+ gui_save_content = 0;
+ }
+}
+
+
+
+/**
+ * Does the actual saving
+ *
+ * \param c content to save (or 0 for other)
+ * \param path path to save as
+ * \return true on success, false on error and error reported
+ */
+
+bool ro_gui_save_content(struct content *c, char *path)
+{
+ os_error *error;
+
+ switch (gui_save_current_type) {
#ifdef WITH_DRAW_EXPORT
case GUI_SAVE_DRAW:
- if (!save_as_draw(c, path))
- return;
- break;
+ return save_as_draw(c, path);
#endif
#ifdef WITH_TEXT_EXPORT
case GUI_SAVE_TEXT:
@@ -265,6 +475,22 @@ void ro_gui_save_datasave_ack(wimp_message *message)
xosfile_set_type(path, 0xfff);
break;
#endif
+#ifdef WITH_SAVE_COMPLETE
+ case GUI_SAVE_COMPLETE:
+ assert(c);
+ if (c->type == CONTENT_HTML) {
+ if (strcmp(path, "<Wimp$Scrap>"))
+ return ro_gui_save_complete(c, path);
+
+ /* we can't send a whole directory to another application,
+ * so just send the HTML source */
+ gui_save_current_type = GUI_SAVE_SOURCE;
+ }
+ else
+ gui_save_current_type = GUI_SAVE_OBJECT_ORIG; /* \todo do this earlier? */
+ /* no break */
+#endif
+ case GUI_SAVE_SOURCE:
case GUI_SAVE_OBJECT_ORIG:
error = xosfile_save_stamped(path,
ro_content_filetype(c),
@@ -274,7 +500,7 @@ void ro_gui_save_datasave_ack(wimp_message *message)
LOG(("xosfile_save_stamped: 0x%x: %s",
error->errnum, error->errmess));
warn_user("SaveError", error->errmess);
- return;
+ return false;
}
break;
@@ -283,22 +509,17 @@ void ro_gui_save_datasave_ack(wimp_message *message)
break;
case GUI_SAVE_LINK_URI:
- if (!ro_gui_save_link(c, LINK_ACORN, path))
- return;
- break;
+ return ro_gui_save_link(c, LINK_ACORN, path);
case GUI_SAVE_LINK_URL:
- if (!ro_gui_save_link(c, LINK_ANT, path))
- return;
- break;
+ return ro_gui_save_link(c, LINK_ANT, path);
case GUI_SAVE_LINK_TEXT:
- if (!ro_gui_save_link(c, LINK_TEXT, path))
- return;
- break;
+ return ro_gui_save_link(c, LINK_TEXT, path);
+
case GUI_SAVE_HOTLIST_EXPORT_HTML:
if (!options_save_tree(hotlist_tree, path, "NetSurf hotlist"))
- return;
+ return false;
error = xosfile_set_type(path, 0xfaf);
if (error)
LOG(("xosfile_set_type: 0x%x: %s",
@@ -306,29 +527,26 @@ void ro_gui_save_datasave_ack(wimp_message *message)
break;
case GUI_SAVE_HISTORY_EXPORT_HTML:
if (!options_save_tree(global_history_tree, path, "NetSurf history"))
- return;
+ return false;
error = xosfile_set_type(path, 0xfaf);
if (error)
LOG(("xosfile_set_type: 0x%x: %s",
error->errnum, error->errmess));
break;
- }
- /* Close the save window
- */
- ro_gui_dialog_close(dialog_saveas);
- ro_gui_menu_closed();
-
- /* Ack successful save with message_DATA_LOAD */
- message->action = message_DATA_LOAD;
- message->your_ref = message->my_ref;
- error = xwimp_send_message_to_window(wimp_USER_MESSAGE, message,
- message->data.data_xfer.w, message->data.data_xfer.i, 0);
- if (error) {
- LOG(("xwimp_send_message_to_window: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("SaveError", error->errmess);
+ case GUI_SAVE_TEXT_SELECTION:
+ selection_save_text(gui_save_selection, path);
+ xosfile_set_type(path, 0xfff);
+ break;
+
+ case GUI_SAVE_CLIPBOARD_CONTENTS:
+ return ro_gui_save_clipboard(path);
+
+ default:
+ LOG(("Unexpected content type: %d, path %s", gui_save_current_type, path));
+ return false;
}
+ return true;
}
@@ -459,7 +677,7 @@ void ro_gui_save_object_native(struct content *c, char *path)
bool ro_gui_save_link(struct content *c, link_format format, char *path)
{
- FILE *fp = fopen(path, "w");
+ FILE *fp = fopen(path, "w");
if (!fp) {
warn_user("SaveError", strerror(errno));
diff --git a/riscos/save_draw.c b/riscos/save_draw.c
index 05ef8defb..5d06d508f 100644
--- a/riscos/save_draw.c
+++ b/riscos/save_draw.c
@@ -167,6 +167,8 @@ bool save_as_draw(struct content *c, const char *path)
draw_clip_x1 = A4PAGEWIDTH;
draw_clip_y1 = draw_plot_origin_y;
+ current_redraw_browser = NULL; /* we don't want to save the selection */
+
if (!drawbuf_group_begin("page"))
goto draw_save_error;
diff --git a/riscos/textselection.c b/riscos/textselection.c
index 7d6e18090..67779bf6e 100644
--- a/riscos/textselection.c
+++ b/riscos/textselection.c
@@ -2,72 +2,362 @@
* 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>
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
*/
+/** \file
+ * Text selection code (platform-dependent implementation)
+ */
+
+#include <assert.h>
+#include <stdio.h>
#include <string.h>
+#include "oslib/osfile.h"
#include "oslib/wimp.h"
+#include "netsurf/desktop/selection.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/utils/log.h"
+#include "netsurf/utils/talloc.h"
#include "netsurf/utils/utils.h"
-void ro_gui_start_selection(wimp_pointer *pointer, wimp_window_state *state,
- struct gui_window *g)
+static bool owns_clipboard = false;
+static bool owns_caret_and_selection = false;
+
+/* current clipboard contents if we own the clipboard */
+static char *clipboard = NULL;
+static size_t clip_alloc = 0;
+static size_t clip_length = 0;
+
+static bool copy_handler(struct box *box, int offset, size_t length, void *handle);
+static void ro_gui_discard_clipboard_contents(void);
+
+
+/**
+ * Start drag-selecting text within a browser window (RO-dependent part)
+ *
+ * \param g gui window
+ */
+
+void gui_start_selection(struct gui_window *g)
{
-/* wimp_drag drag;
+ wimp_full_message_claim_entity msg;
+ wimp_auto_scroll_info scroll;
+ wimp_window_state state;
+ wimp_drag drag;
+ os_error *error;
+
+ LOG(("starting text_selection drag"));
+
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* claim caret and selection */
+ msg.size = sizeof(msg);
+ msg.your_ref = 0;
+ msg.action = message_CLAIM_ENTITY;
+ msg.flags = wimp_CLAIM_CARET_OR_SELECTION;
+
+ error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)&msg, wimp_BROADCAST);
+ if (error) {
+ LOG(("xwimp_send_message: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ owns_caret_and_selection = true;
+
+ scroll.w = g->window;
+ scroll.pause_zone_sizes.x0 = 80;
+ scroll.pause_zone_sizes.y0 = 80;
+ scroll.pause_zone_sizes.x1 = 80;
+ scroll.pause_zone_sizes.y1 = 80;
+ scroll.pause_duration = 0;
+ scroll.state_change = (void *)0;
+ error = xwimp_auto_scroll(wimp_AUTO_SCROLL_ENABLE_VERTICAL |
+ wimp_AUTO_SCROLL_ENABLE_HORIZONTAL,
+ &scroll, 0);
+ if (error)
+ LOG(("xwimp_auto_scroll: 0x%x: %s",
+ error->errnum, error->errmess));
gui_current_drag_type = GUI_DRAG_SELECTION;
- current_gui = g;
drag.type = wimp_DRAG_USER_POINT;
- drag.initial.x0 = pointer->pos.x;
- drag.initial.y0 = pointer->pos.y;
- drag.initial.x1 = pointer->pos.x;
- drag.initial.y1 = pointer->pos.y;
- drag.bbox.x0 = state->visible.x0;
- drag.bbox.y0 = state->visible.y0;
- drag.bbox.x1 = state->visible.x1;
- drag.bbox.y1 = state->visible.y1;
- wimp_drag_box(&drag);
-*/
+ drag.bbox.x0 = state.visible.x0;
+ drag.bbox.y0 = state.visible.y0;
+ drag.bbox.x1 = state.visible.x1;
+ drag.bbox.y1 = state.visible.y1;
+
+ error = xwimp_drag_box(&drag);
+ if (error) {
+ LOG(("xwimp_drag_box: 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
}
-void ro_gui_selection_drag_end(wimp_dragged *drag)
+/**
+ * End of text selection drag operation
+ *
+ * \param g gui window
+ * \param dragged position of pointer at conclusion of drag
+ */
+
+void ro_gui_selection_drag_end(struct gui_window *g, wimp_dragged *drag)
{
-/* struct browser_action msg; */
-/* int final_x0, final_y0;
- wimp_window_state state;
-
- state.w = current_gui->window;
- wimp_get_window_state(&state);
-
- final_x0 = window_x_units(drag->final.x0, &state) / 2;
- final_y0 = window_y_units(drag->final.y0, &state) / 2;
-*/
-/* msg.data.mouse.x = final_x0;
- msg.data.mouse.y = final_y0;
- msg.type = act_ALTER_SELECTION;
- browser_window_action(current_gui->bw, &msg);*/
-
-/* if (box_position_eq(&(current_gui->bw->current_content->data.html.text_selection.start), */
-/* &(current_gui->bw->current_content->data.html.text_selection.end))) */
- {
-/* msg.type = act_CLEAR_SELECTION;
- browser_window_action(current_gui->bw, &msg);*/
- }
-/* current_gui->bw->current_content->data.html.text_selection.altering = alter_UNKNOWN; */
+ wimp_auto_scroll_info scroll;
+ wimp_window_state state;
+ wimp_pointer pointer;
+ os_error *error;
+ int x, y;
+
+ gui_current_drag_type = GUI_DRAG_NONE;
+
+ scroll.w = g->window;
+ error = xwimp_auto_scroll(0, &scroll, 0);
+ if (error)
+ LOG(("xwimp_auto_scroll: 0x%x: %s", error->errnum, error->errmess));
+
+ error = xwimp_drag_box((wimp_drag*)-1);
+ if (error) {
+ LOG(("xwimp_drag_box: 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG(("xwimp_get_pointer_info 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ x = window_x_units(drag->final.x0, &state) / 2 / g->option.scale;
+ y = -window_y_units(drag->final.y0, &state) / 2 / g->option.scale;
+
+ browser_window_mouse_drag_end(g->bw,
+ ro_gui_mouse_click_state(pointer.buttons), x, y);
}
-void ro_gui_copy_selection(struct gui_window* g)
+/**
+ * Selection traversal routine for appending text to the current contents
+ * of the clipboard.
+
+ * \param box pointer to text box being (partially) added
+ * \param offset start offset of text within box (bytes)
+ * \param length length of text to be appended (bytes)
+ * \param handle unused handle, we don't need one
+ * \return true iff successful and traversal should continue
+ */
+
+bool copy_handler(struct box *box, int offset, size_t length, void *handle)
{
- {
-// if (g->bw->text_selection->selected == 1)
-// {
-// }
- }
+ size_t new_length;
+ const char *text;
+ int space = 0;
+
+ if (box) {
+ text = box->text + offset;
+ if (box->space) space = 1;
+ }
+ else {
+ text = "\n";
+ length = 1;
+ }
+
+ new_length = clip_length + length + space;
+
+ if (new_length > clip_alloc) {
+ size_t new_alloc = clip_alloc + (clip_alloc / 4);
+ char *new_cb;
+
+ if (new_alloc < new_length) new_alloc = new_length;
+
+ new_cb = talloc_realloc(NULL, clipboard, char, new_alloc);
+ if (!new_cb) return false;
+
+ clipboard = new_cb;
+ clip_alloc = new_alloc;
+ }
+
+ memcpy(clipboard + clip_length, text, length);
+ clip_length += length;
+ if (space) clipboard[clip_length++] = ' ';
+
+ return true;
}
+/**
+ * Copy the selected contents to the global clipboard,
+ * and claim ownership of the clipboard from other apps.
+ *
+ * \param s selection
+ * \return true iff successful, ie. cut operation can proceed without losing data
+ */
+
+bool gui_copy_to_clipboard(struct selection *s)
+{
+ const int init_size = 1024;
+
+ if (!clip_alloc) {
+ clipboard = talloc_array(NULL, char, init_size);
+ if (!clipboard) {
+ LOG(("out of memory"));
+ warn_user("NoMemory", 0);
+ return false;
+ }
+ clip_alloc = init_size;
+ }
+
+ clip_length = 0;
+ selection_traverse(s, copy_handler, NULL);
+
+ if (!owns_clipboard) {
+ wimp_full_message_claim_entity msg;
+ os_error *error;
+
+ LOG(("claiming clipboard"));
+
+ msg.size = sizeof(msg);
+ msg.your_ref = 0;
+ msg.action = message_CLAIM_ENTITY;
+ msg.flags = wimp_CLAIM_CLIPBOARD;
+
+ error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)&msg,
+ wimp_BROADCAST);
+ if (error) {
+ LOG(("xwimp_send_message: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ owns_clipboard = true;
+ }
+
+ LOG(("clipboard now holds %d bytes", clip_length));
+
+ return true;
+}
+
+
+/**
+ * Discard the current contents of the clipboard, if any, releasing the
+ * memory it uses.
+ */
+
+void ro_gui_discard_clipboard_contents(void)
+{
+ if (clip_alloc) talloc_free(clipboard);
+ clip_alloc = 0;
+ clip_length = 0;
+}
+
+
+/**
+ * Responds to CLAIM_ENTITY message notifying us that the caret
+ * and selection or clipboard have been claimed by another application.
+ *
+ * \param claim CLAIM_ENTITY message
+ */
+
+void ro_gui_selection_claim_entity(wimp_full_message_claim_entity *claim)
+{
+ /* ignore our own broadcasts! */
+ if (claim->sender != task_handle) {
+
+ LOG(("%x", claim->flags));
+
+ if (claim->flags & wimp_CLAIM_CARET_OR_SELECTION) {
+ owns_caret_and_selection = false;
+ }
+
+ if (claim->flags & wimp_CLAIM_CLIPBOARD) {
+ ro_gui_discard_clipboard_contents();
+ owns_clipboard = false;
+ }
+ }
+}
+
+
+/**
+ * Responds to DATA_REQUEST message, returning information about the
+ * clipboard contents if we own the clipboard.
+ *
+ * \param req DATA_REQUEST message
+ */
+
+void ro_gui_selection_data_request(wimp_full_message_data_request *req)
+{
+ LOG(("%x owns %d size %d", req->flags, owns_clipboard, req->size));
+
+ if (owns_clipboard && clip_length > 0 &&
+ (req->flags & wimp_DATA_REQUEST_CLIPBOARD)) {
+ wimp_full_message_data_xfer message;
+ int size;
+// int i;
+
+// for(i = 0; i < NOF_ELEMENTS(req->file_types); i++) {
+// bits ftype = req->file_types[i];
+// if (ftype == ~0U) break; /* list terminator */
+//
+// LOG(("type %x", ftype));
+// i++;
+// }
+
+ /* we can only supply text at the moment, so that's what you're getting! */
+ size = offsetof(wimp_full_message_data_xfer, file_name) + 9;
+ message.size = (size + 3) & ~3;
+ message.your_ref = req->my_ref;
+ message.action = message_DATA_SAVE;
+ message.w = req->w;
+ message.i = req->i;
+ message.pos = req->pos;
+ message.file_type = osfile_TYPE_TEXT;
+ message.est_size = clip_length;
+ memcpy(message.file_name, "TextFile", 9);
+
+ ro_gui_send_datasave(GUI_SAVE_CLIPBOARD_CONTENTS, &message, req->sender);
+ }
+}
+
+
+/**
+ * Save the clipboard contents to a file.
+ *
+ * \param path the pathname of the file
+ * \return true iff success, otherwise reporting the error before returning false
+ */
+
+bool ro_gui_save_clipboard(const char *path)
+{
+ os_error *error;
+
+ assert(clip_length > 0 && clipboard);
+ error = xosfile_save_stamped(path, osfile_TYPE_TEXT,
+ (byte*)clipboard,
+ (byte*)clipboard + clip_length);
+ if (error) {
+ LOG(("xosfile_save_stamped: 0x%x: %s", error->errnum, error->errmess));
+ warn_user("SaveError", error->errmess);
+ return false;
+ }
+ return true;
+}
diff --git a/riscos/thumbnail.c b/riscos/thumbnail.c
index e28cdf7e5..c0c667a1d 100644
--- a/riscos/thumbnail.c
+++ b/riscos/thumbnail.c
@@ -103,6 +103,8 @@ void thumbnail_create(struct content *content, osspriteop_area *area,
ro_plot_origin_y = height * 2;
ro_plot_set_scale(scale);
+ current_redraw_browser = NULL; /* no selection */
+
/* Switch output and redraw
*/
save_area = thumbnail_switch_output(render_area, render_sprite);
diff --git a/riscos/uri.c b/riscos/uri.c
index 4c0790398..a396cc3f4 100644
--- a/riscos/uri.c
+++ b/riscos/uri.c
@@ -27,8 +27,6 @@ void ro_uri_message_received(uri_full_message_process*);
bool ro_uri_launch(char *uri);
void ro_uri_bounce(uri_full_message_return_result*);
-extern wimp_t task_handle;
-
void ro_uri_message_received(uri_full_message_process* uri_message)
{
diff --git a/riscos/window.c b/riscos/window.c
index 8cdfbc116..fcd0c3206 100644
--- a/riscos/window.c
+++ b/riscos/window.c
@@ -58,6 +58,7 @@ static float scale_snap_to[] = {0.10, 0.125, 0.25, 0.333, 0.5, 0.75,
static void ro_gui_window_clone_options(struct browser_window *new_bw,
struct browser_window *old_bw);
+static browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons);
@@ -456,6 +457,7 @@ void ro_gui_window_redraw(struct gui_window *g, wimp_draw *redraw)
plot = ro_plotters;
ro_plot_set_scale(g->option.scale);
ro_gui_current_redraw_gui = g;
+ current_redraw_browser = g->bw;
/* We should clear the background, except for HTML.
*/
@@ -572,10 +574,12 @@ void ro_gui_window_redraw(struct gui_window *g, wimp_draw *redraw)
error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
ro_gui_current_redraw_gui = NULL;
+ current_redraw_browser = NULL;
return;
}
}
ro_gui_current_redraw_gui = NULL;
+ current_redraw_browser = NULL;
}
@@ -621,6 +625,7 @@ void gui_window_update_box(struct gui_window *g,
/* Set the current redraw gui_window to get options from
*/
ro_gui_current_redraw_gui = g;
+ current_redraw_browser = g->bw;
use_buffer = (data->redraw.full_redraw) &&
(g->option.buffer_everything || g->option.buffer_animations);
@@ -691,6 +696,7 @@ void gui_window_update_box(struct gui_window *g,
error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
ro_gui_current_redraw_gui = NULL;
+ current_redraw_browser = NULL;
return;
}
}
@@ -699,6 +705,44 @@ void gui_window_update_box(struct gui_window *g,
retaining options
*/
ro_gui_current_redraw_gui = NULL;
+ current_redraw_browser = NULL;
+}
+
+
+/**
+ * Get the scroll position of a browser window.
+ *
+ * \param g gui_window
+ * \param sx receives x ordinate of point at top-left of window
+ * \param sy receives y ordinate of point at top-left of window
+ * \return true iff successful
+ */
+
+bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
+{
+ wimp_window_state state;
+ os_error *error;
+
+ assert(g);
+
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+ else {
+ int toolbar_height = 0;
+
+ if (g->toolbar)
+ toolbar_height = ro_gui_theme_toolbar_full_height(g->toolbar);
+
+ *sx = state.xscroll / (2 * g->option.scale);
+ *sy = -(state.yscroll - toolbar_height) / (2 * g->option.scale);
+ return true;
+ }
}
@@ -1177,7 +1221,7 @@ void ro_gui_window_mouse_at(struct gui_window *g, wimp_pointer *pointer)
assert(g);
- state.w = pointer->w;
+ state.w = g->window;
error = xwimp_get_window_state(&state);
if (error) {
LOG(("xwimp_get_window_state: 0x%x: %s",
@@ -1189,10 +1233,7 @@ void ro_gui_window_mouse_at(struct gui_window *g, wimp_pointer *pointer)
x = window_x_units(pointer->pos.x, &state) / 2 / g->option.scale;
y = -window_y_units(pointer->pos.y, &state) / 2 / g->option.scale;
- if (pointer->buttons)
- browser_window_mouse_click(g->bw, BROWSER_MOUSE_DRAG, x, y);
- else
- browser_window_mouse_click(g->bw, BROWSER_MOUSE_HOVER, x, y);
+ browser_window_mouse_track(g->bw, ro_gui_mouse_drag_state(pointer->buttons), x, y);
}
@@ -1202,7 +1243,6 @@ void ro_gui_window_mouse_at(struct gui_window *g, wimp_pointer *pointer)
void ro_gui_toolbar_click(struct gui_window *g, wimp_pointer *pointer)
{
-
/* try to close url-completion */
ro_gui_url_complete_close(g, pointer->i);
@@ -1344,17 +1384,15 @@ void ro_gui_status_click(struct gui_window *g, wimp_pointer *pointer)
void ro_gui_window_click(struct gui_window *g, wimp_pointer *pointer)
{
- int x, y, shift;
wimp_window_state state;
os_error *error;
+ int x, y;
assert(g);
/* try to close url-completion */
ro_gui_url_complete_close(g, pointer->i);
- xosbyte1(osbyte_SCAN_KEYBOARD, 0 ^ 0x80, 0, &shift);
-
state.w = pointer->w;
error = xwimp_get_window_state(&state);
if (error) {
@@ -1380,17 +1418,14 @@ void ro_gui_window_click(struct gui_window *g, wimp_pointer *pointer)
}
}
+LOG(("%d %d", pointer->buttons, ro_gui_mouse_click_state(pointer->buttons)));
+
if (pointer->buttons == wimp_CLICK_MENU)
ro_gui_menu_create(browser_menu, pointer->pos.x,
pointer->pos.y, pointer->w);
- else if (pointer->buttons == wimp_CLICK_SELECT)
- browser_window_mouse_click(g->bw,
- (shift == 0xff) ? BROWSER_MOUSE_CLICK_1_MOD
- : BROWSER_MOUSE_CLICK_1, x, y);
- else if (pointer->buttons == wimp_CLICK_ADJUST)
+ else
browser_window_mouse_click(g->bw,
- (shift == 0xff) ? BROWSER_MOUSE_CLICK_2_MOD
- : BROWSER_MOUSE_CLICK_2, x, y);
+ ro_gui_mouse_click_state(pointer->buttons), x, y);
}
@@ -1520,13 +1555,13 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar)
if (!toolbar) {
wchar_t c = (wchar_t)key;
/* Munge cursor keys into unused control chars */
- /* We can't map on to any of: 3,8,10,13,17,18,21,22,23 or 24
- * That leaves 1,2,4-7,11,12,14-16,18-20,25-31 and 129-159
- */
+ /* We can't map onto 1->26 (reserved for ctrl+<qwerty>
+ That leaves 27->31 and 128->159 */
+
if (c == 394) c = 9; /* Tab */
else if (c == 410) c = 11; /* Shift+Tab */
- else if (c == 428) c = 26; /* Ctrl+Left */
- else if (c == 429) c = 27; /* Ctrl+Right*/
+ else if (c == 428) c = 128; /* Ctrl+Left */
+ else if (c == 429) c = 129; /* Ctrl+Right*/
else if (c == 396) c = 29; /* Left */
else if (c == 397) c = 28; /* Right */
else if (c == 398) c = 31; /* Down */
@@ -2111,3 +2146,177 @@ void ro_gui_window_prepare_navigate_all(void) {
for (g = window_list; g; g = g->next)
ro_gui_prepare_navigate(g);
}
+
+
+/**
+ * Returns the state of the mouse buttons and modifiers keys for a
+ * click/release action, suitable for passing to the OS-independent
+ * browser window code
+ */
+
+browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons)
+{
+ browser_mouse_state state = 0;
+
+ if (buttons & (wimp_CLICK_SELECT)) state |= BROWSER_MOUSE_CLICK_1;
+ if (buttons & (wimp_CLICK_ADJUST)) state |= BROWSER_MOUSE_CLICK_2;
+
+ if (buttons & (wimp_DRAG_SELECT)) state |= BROWSER_MOUSE_DRAG_1;
+ if (buttons & (wimp_DRAG_ADJUST)) state |= BROWSER_MOUSE_DRAG_2;
+
+ if (ro_gui_shift_pressed()) state |= BROWSER_MOUSE_MOD_1;
+ if (ro_gui_ctrl_pressed()) state |= BROWSER_MOUSE_MOD_2;
+
+ return state;
+}
+
+
+/**
+ * Returns the state of the mouse buttons and modifiers keys whilst
+ * dragging, for passing to the OS-independent browser window code
+ */
+
+browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons)
+{
+ browser_mouse_state state = 0;
+
+ if (buttons & (wimp_CLICK_SELECT)) state |= BROWSER_MOUSE_HOLDING_1;
+ if (buttons & (wimp_CLICK_ADJUST)) state |= BROWSER_MOUSE_HOLDING_2;
+
+ if (ro_gui_shift_pressed()) state |= BROWSER_MOUSE_MOD_1;
+ if (ro_gui_ctrl_pressed()) state |= BROWSER_MOUSE_MOD_2;
+
+ return state;
+}
+
+
+/**
+ * Returns true iff one or more Shift keys is held down
+ */
+
+bool ro_gui_shift_pressed(void)
+{
+ int shift = 0;
+ xosbyte1(osbyte_SCAN_KEYBOARD, 0 ^ 0x80, 0, &shift);
+ return (shift == 0xff);
+}
+
+
+/**
+ * Returns true iff one or more Ctrl keys is held down
+ */
+
+bool ro_gui_ctrl_pressed(void)
+{
+ int ctrl = 0;
+ xosbyte1(osbyte_SCAN_KEYBOARD, 1 ^ 0x80, 0, &ctrl);
+ return (ctrl == 0xff);
+}
+
+
+/**
+ * Starts drag scrolling of a browser window
+ *
+ * \param gw gui window
+ */
+
+bool gui_window_scroll_start(struct gui_window *g)
+{
+ wimp_window_info_base info;
+ wimp_pointer pointer;
+ os_error *error;
+ wimp_drag drag;
+ int height;
+ int width;
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG(("xwimp_get_pointer_info 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ info.w = g->window;
+ error = xwimp_get_window_info_header_only((wimp_window_info*)&info);
+ if (error) {
+ LOG(("xwimp_get_window_state: 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ width = info.extent.x1 - info.extent.x0;
+ height = info.extent.y1 - info.extent.y0;
+
+ drag.type = wimp_DRAG_USER_POINT;
+ drag.bbox.x1 = pointer.pos.x + info.xscroll;
+ drag.bbox.y0 = pointer.pos.y + info.yscroll;
+ drag.bbox.x0 = drag.bbox.x1 - (width - (info.visible.x1 - info.visible.x0));
+ drag.bbox.y1 = drag.bbox.y0 + (height - (info.visible.y1 - info.visible.y0));
+
+ if (g->toolbar) {
+ int tbar_height = ro_gui_theme_toolbar_full_height(g->toolbar);
+ drag.bbox.y0 -= tbar_height;
+ drag.bbox.y1 -= tbar_height;
+ }
+
+ error = xwimp_drag_box(&drag);
+ if (error) {
+ LOG(("xwimp_drag_box: 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return false;
+ }
+
+ gui_current_drag_type = GUI_DRAG_SCROLL;
+ return true;
+}
+
+
+/**
+ * Completes scrolling of a browser window
+ *
+ * \param g gui window
+ */
+
+void ro_gui_window_scroll_end(struct gui_window *g, wimp_dragged *drag)
+{
+ wimp_window_state state;
+ wimp_pointer pointer;
+ os_error *error;
+ int x, y;
+
+ gui_current_drag_type = GUI_DRAG_NONE;
+
+ error = xwimp_drag_box((wimp_drag*)-1);
+ if (error) {
+ LOG(("xwimp_drag_box: 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+
+ error = xwimp_get_pointer_info(&pointer);
+ if (error) {
+ LOG(("xwimp_get_pointer_info 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ state.w = g->window;
+ error = xwimp_get_window_state(&state);
+ if (error) {
+ LOG(("xwimp_get_window_state 0x%x : %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ x = window_x_units(drag->final.x0, &state) / 2 / g->option.scale;
+ y = -window_y_units(drag->final.y0, &state) / 2 / g->option.scale;
+
+ browser_window_mouse_drag_end(g->bw,
+ ro_gui_mouse_click_state(pointer.buttons), x, y);
+}
+