diff options
Diffstat (limited to 'riscos/textselection.c')
-rw-r--r-- | riscos/textselection.c | 271 |
1 files changed, 251 insertions, 20 deletions
diff --git a/riscos/textselection.c b/riscos/textselection.c index 5e2ddf750..603f645ea 100644 --- a/riscos/textselection.c +++ b/riscos/textselection.c @@ -14,12 +14,32 @@ #include <string.h> #include "oslib/osfile.h" #include "oslib/wimp.h" +#include "netsurf/desktop/gui.h" #include "netsurf/desktop/selection.h" +#include "netsurf/desktop/textinput.h" #include "netsurf/riscos/gui.h" +#include "netsurf/riscos/message.h" +#include "netsurf/riscos/save.h" +#include "netsurf/riscos/textselection.h" +#include "netsurf/render/form.h" #include "netsurf/utils/log.h" #include "netsurf/utils/utf8.h" #include "netsurf/utils/utils.h" +#ifndef wimp_DRAG_CLAIM_SUPPRESS_DRAGBOX +#define wimp_DRAG_CLAIM_SUPPRESS_DRAGBOX ((wimp_drag_claim_flags) 0x2u) +#endif + + + +/** Receive of Dragging message has claimed it */ +static bool dragging_claimed = false; +static wimp_t dragging_claimant; +static os_box dragging_box = { -34, -34, 34, 34 }; /* \todo - size properly */ +static wimp_drag_claim_flags last_claim_flags = 0; + + +static bool drag_claimed = false; static bool owns_clipboard = false; static bool owns_caret_and_selection = false; @@ -29,9 +49,10 @@ 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 bool copy_handler(const char *text, size_t length, bool space, + struct box *box, void *handle); static void ro_gui_discard_clipboard_contents(void); +static void ro_gui_dragging_bounced(wimp_message *message); /** @@ -166,30 +187,22 @@ void ro_gui_selection_drag_end(struct gui_window *g, wimp_dragged *drag) * Selection traversal routine for appending text to the current contents * of the clipboard. * - * \param box pointer to text box being (partially) added (or NULL for newline) - * \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 + * \param text pointer to text being added, or NULL for newline + * \param length length of text to be appended (bytes) + * \param space trailing space required after text + * \param box pointer to text box, or NULL if from textplain + * \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) +bool copy_handler(const char *text, size_t length, bool space, + struct box *box, void *handle) { - bool space = false; - const char *text; - size_t len; - - if (box) { - len = min(length, box->length - offset); - text = box->text + offset; - if (box->space && length > len) space = true; - } - else { + if (!text) { text = "\n"; - len = 1; + length = 1; } - - return gui_add_to_clipboard(text, len, space); + return gui_add_to_clipboard(text, length, space); } @@ -483,3 +496,221 @@ bool ro_gui_save_clipboard(const char *path) } return true; } + + +/** + * Handler for Message_Dragging, used to implement auto-scrolling and + * ghost caret when a drag is in progress. + */ + +void ro_gui_selection_dragging(wimp_message *message) +{ + wimp_full_message_dragging *drag = (wimp_full_message_dragging*)message; + struct box *textarea = NULL; + struct box *text_box = NULL; + struct browser_window *bw; + wimp_window_state state; + struct content *content; + int gadget_box_x = 0; + int gadget_box_y = 0; + struct gui_window *g; + os_error *error; + int box_x = 0; + int box_y = 0; + int x, y; + +/* with autoscrolling, we will probably need to remember the gui_window and + override the drag->w window handle which could be any window on the desktop */ + g = ro_gui_window_lookup(drag->w); + + if ((drag->flags & wimp_DRAGGING_TERMINATE_DRAG) || !g) { + + if (drag_claimed) { + /* make sure that we erase the ghost caret */ + caret_remove(&ghost_caret); + } + + drag_claimed = false; + return; + } + + state.w = drag->w; + error = xwimp_get_window_state(&state); + if (error) { + LOG(("xwimp_get_window_state: 0x%x: %s\n", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + drag_claimed = false; + return; + } + + x = window_x_units(drag->pos.x, &state) / 2 / + g->option.scale; + y = -window_y_units(drag->pos.y, &state) / 2 / + g->option.scale; + + bw = g->bw; + content = bw->current_content; + if (content && content->type == CONTENT_HTML && + content->data.html.layout) { + + struct box *box = content->data.html.layout; + + while ((box = box_at_point(box, x, y, &box_x, &box_y, &content))) { + if (box->style && + box->style->visibility == CSS_VISIBILITY_HIDDEN) + continue; + + if (box->gadget) { + switch (box->gadget->type) { + + case GADGET_TEXTAREA: + textarea = box; + gadget_box_x = box_x; + gadget_box_y = box_y; + case GADGET_TEXTBOX: + case GADGET_PASSWORD: + text_box = box; + break; + + default: /* appease compiler */ + break; + } + } + } + } + + if (textarea) { + int pixel_offset; + int char_offset; + + /* draw/move the ghost caret */ + if (drag_claimed) + caret_remove(&ghost_caret); + else + gui_window_set_pointer(GUI_POINTER_CARET); + + text_box = textarea_get_position(textarea, x - gadget_box_x, + y - gadget_box_y, &char_offset, &pixel_offset); + + caret_set_position(&ghost_caret, bw, text_box, char_offset, pixel_offset); + drag_claimed = true; + } + else { + if (drag_claimed) { + /* make sure that we erase the ghost caret */ + caret_remove(&ghost_caret); + } + drag_claimed = false; + } + + if (drag_claimed) { + wimp_full_message_drag_claim claim; + os_error *error; + + claim.size = offsetof(wimp_full_message_drag_claim, file_types) + 8; + claim.your_ref = drag->my_ref; + claim.action = message_DRAG_CLAIM; + claim.flags = wimp_DRAG_CLAIM_POINTER_CHANGED | wimp_DRAG_CLAIM_SUPPRESS_DRAGBOX; + claim.file_types[0] = osfile_TYPE_TEXT; + claim.file_types[1] = ~0; + + error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)&claim, + drag->sender); + if (error) { + LOG(("xwimp_send_message: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + drag_claimed = true; + } +} + + + +/** + * Reset drag-and-drop state when drag completes (DataSave received) + */ + +void ro_gui_selection_drag_reset(void) +{ + caret_remove(&ghost_caret); + drag_claimed = false; +} + + +/** + * + */ + +void ro_gui_selection_drag_claim(wimp_message *message) +{ + wimp_full_message_drag_claim *claim = (wimp_full_message_drag_claim*)message; + + dragging_claimant = message->sender; + dragging_claimed = true; + + /* have we been asked to remove the drag box/sprite? */ + if (claim->flags & wimp_DRAG_CLAIM_SUPPRESS_DRAGBOX) { + ro_gui_drag_box_cancel(); + } + else { + /* \todo - restore it here? */ + } + + /* do we need to restore the default pointer shape? */ + if ((last_claim_flags & wimp_DRAG_CLAIM_POINTER_CHANGED) && + !(claim->flags & wimp_DRAG_CLAIM_POINTER_CHANGED)) { + gui_window_set_pointer(GUI_POINTER_DEFAULT); + } + + last_claim_flags = claim->flags; +} + + +void ro_gui_selection_send_dragging(wimp_pointer *pointer) +{ + wimp_full_message_dragging dragmsg; + + LOG(("sending DRAGGING to %p, %d", pointer->w, pointer->i)); + + dragmsg.size = offsetof(wimp_full_message_dragging, file_types) + 8; + dragmsg.your_ref = 0; + dragmsg.action = message_DRAGGING; + dragmsg.w = pointer->w; + dragmsg.i = pointer->i; + dragmsg.pos = pointer->pos; +/* \todo - this is interesting because it depends upon not just the state of the + shift key, but also whether it /can/ be deleted, ie. from text area/input + rather than page contents */ + dragmsg.flags = wimp_DRAGGING_FROM_SELECTION; + dragmsg.box = dragging_box; + dragmsg.file_types[0] = osfile_TYPE_TEXT; + dragmsg.file_types[1] = ~0; + + /* if the message_dragmsg messages have been claimed we must address them + to the claimant task, which is not necessarily the task that owns whatever + window happens to be under the pointer */ + + if (dragging_claimed) { + ro_message_send_message(wimp_USER_MESSAGE_RECORDED, + (wimp_message*)&dragmsg, dragging_claimant, ro_gui_dragging_bounced); + } + else { + ro_message_send_message_to_window(wimp_USER_MESSAGE_RECORDED, + (wimp_message*)&dragmsg, pointer->w, pointer->i, + ro_gui_dragging_bounced, &dragging_claimant); + } +} + + +/** + * Our message_DRAGGING message was bounced, ie. the intended recipient does not + * support the drag-and-drop protocol or cannot receive the data at the pointer + * position. + */ + +void ro_gui_dragging_bounced(wimp_message *message) +{ + dragging_claimed = false; +} |