diff options
Diffstat (limited to 'riscos')
-rw-r--r-- | riscos/bitmap.c | 18 | ||||
-rw-r--r-- | riscos/dialog.c | 26 | ||||
-rw-r--r-- | riscos/download.c | 4 | ||||
-rw-r--r-- | riscos/gui.c | 97 | ||||
-rw-r--r-- | riscos/gui.h | 37 | ||||
-rw-r--r-- | riscos/print.c | 1 | ||||
-rw-r--r-- | riscos/save.c | 396 | ||||
-rw-r--r-- | riscos/save_draw.c | 2 | ||||
-rw-r--r-- | riscos/textselection.c | 378 | ||||
-rw-r--r-- | riscos/thumbnail.c | 2 | ||||
-rw-r--r-- | riscos/uri.c | 2 | ||||
-rw-r--r-- | riscos/window.c | 251 |
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); +} + |