From 89993a5bf2e2a326af47cf5c34c75d7f39ae34a3 Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Fri, 15 Apr 2005 05:54:44 +0000 Subject: [project @ 2005-04-15 05:54:44 by adrianl] Text selection, page drag scrolling, drag-saving images and a few SaveAs improvements svn path=/import/netsurf/; revision=1640 --- riscos/textselection.c | 378 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 334 insertions(+), 44 deletions(-) (limited to 'riscos/textselection.c') 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 + * Copyright 2005 Adrian Lees */ +/** \file + * Text selection code (platform-dependent implementation) + */ + +#include +#include #include +#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; +} -- cgit v1.2.3