css_error set_libcss_node_data(void *pw, void *node, void *libcss_node_data) { dom_node *n = node; dom_exception err; void *old_node_data; /* Set this node's node data */ err = dom_node_set_user_data(n, corestring_dom___ns_key_libcss_node_data, libcss_node_data, nscss_dom_user_data_handler, (void *) &old_node_data); if (err != DOM_NO_ERR) { return CSS_NOMEM; } assert(old_node_data == NULL); return CSS_OK; }
/** * Helper for file gadgets to store their filename. * * Stores the filename unencoded on the dom node associated with the * gadget. * * \todo Get rid of this crap eventually * * \param operation DOM operation * \param key DOM node key being considerd * \param _data The data assocated with the key * \param src The source DOM node. * \param dst The destination DOM node. */ static void html__image_coords_dom_user_data_handler(dom_node_operation operation, dom_string *key, void *_data, struct dom_node *src, struct dom_node *dst) { struct image_input_coords *oldcoords, *coords = _data, *newcoords; if (!dom_string_isequal(corestring_dom___ns_key_image_coords_node_data, key) || coords == NULL) { return; } switch (operation) { case DOM_NODE_CLONED: newcoords = calloc(1, sizeof(*newcoords)); if (newcoords != NULL) { *newcoords = *coords; if (dom_node_set_user_data(dst, corestring_dom___ns_key_image_coords_node_data, newcoords, html__image_coords_dom_user_data_handler, &oldcoords) == DOM_NO_ERR) { free(oldcoords); } } break; case DOM_NODE_DELETED: free(coords); break; case DOM_NODE_RENAMED: case DOM_NODE_IMPORTED: case DOM_NODE_ADOPTED: break; default: LOG("User data operation not handled."); assert(0); } }
void html_mouse_action(struct content *c, struct browser_window *bw, browser_mouse_state mouse, int x, int y) { html_content *html = (html_content *) c; enum { ACTION_NONE, ACTION_SUBMIT, ACTION_GO } action = ACTION_NONE; const char *title = 0; nsurl *url = 0; char *url_s = NULL; size_t url_l = 0; const char *target = 0; char status_buffer[200]; const char *status = 0; browser_pointer_shape pointer = BROWSER_POINTER_DEFAULT; bool imagemap = false; int box_x = 0, box_y = 0; int gadget_box_x = 0, gadget_box_y = 0; int html_object_pos_x = 0, html_object_pos_y = 0; int text_box_x = 0; struct box *url_box = 0; struct box *gadget_box = 0; struct box *text_box = 0; struct box *box; struct form_control *gadget = 0; hlcache_handle *object = NULL; struct box *html_object_box = NULL; struct browser_window *iframe = NULL; struct box *drag_candidate = NULL; struct scrollbar *scrollbar = NULL; plot_font_style_t fstyle; int scroll_mouse_x = 0, scroll_mouse_y = 0; int padding_left, padding_right, padding_top, padding_bottom; browser_drag_type drag_type = browser_window_get_drag_type(bw); union content_msg_data msg_data; struct dom_node *node = NULL; union html_drag_owner drag_owner; union html_selection_owner sel_owner; bool click = mouse & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2 | BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2); if (drag_type != DRAGGING_NONE && !mouse && html->visible_select_menu != NULL) { /* drag end: select menu */ form_select_mouse_drag_end(html->visible_select_menu, mouse, x, y); } if (html->visible_select_menu != NULL) { box = html->visible_select_menu->box; box_coords(box, &box_x, &box_y); box_x -= box->border[LEFT].width; box_y += box->height + box->border[BOTTOM].width + box->padding[BOTTOM] + box->padding[TOP]; status = form_select_mouse_action(html->visible_select_menu, mouse, x - box_x, y - box_y); if (status != NULL) { msg_data.explicit_status_text = status; content_broadcast(c, CONTENT_MSG_STATUS, msg_data); } else { int width, height; form_select_get_dimensions(html->visible_select_menu, &width, &height); html->visible_select_menu = NULL; browser_window_redraw_rect(bw, box_x, box_y, width, height); } return; } if (html->drag_type == HTML_DRAG_SELECTION) { /* Selection drag */ struct box *box; int dir = -1; int dx, dy; if (!mouse) { /* End of selection drag */ int dir = -1; size_t idx; if (selection_dragging_start(&html->sel)) dir = 1; idx = html_selection_drag_end(html, mouse, x, y, dir); if (idx != 0) selection_track(&html->sel, mouse, idx); drag_owner.no_owner = true; html_set_drag_type(html, HTML_DRAG_NONE, drag_owner, NULL); return; } if (selection_dragging_start(&html->sel)) dir = 1; box = box_pick_text_box(html, x, y, dir, &dx, &dy); if (box != NULL) { int pixel_offset; size_t idx; plot_font_style_t fstyle; font_plot_style_from_css(box->style, &fstyle); guit->layout->position(&fstyle, box->text, box->length, dx, &idx, &pixel_offset); selection_track(&html->sel, mouse, box->byte_offset + idx); } return; } if (html->drag_type == HTML_DRAG_SCROLLBAR) { struct scrollbar *scr = html->drag_owner.scrollbar; struct html_scrollbar_data *data = scrollbar_get_data(scr); if (!mouse) { /* drag end: scrollbar */ html_overflow_scroll_drag_end(scr, mouse, x, y); } box = data->box; box_coords(box, &box_x, &box_y); if (scrollbar_is_horizontal(scr)) { scroll_mouse_x = x - box_x ; scroll_mouse_y = y - (box_y + box->padding[TOP] + box->height + box->padding[BOTTOM] - SCROLLBAR_WIDTH); status = scrollbar_mouse_status_to_message( scrollbar_mouse_action(scr, mouse, scroll_mouse_x, scroll_mouse_y)); } else { scroll_mouse_x = x - (box_x + box->padding[LEFT] + box->width + box->padding[RIGHT] - SCROLLBAR_WIDTH); scroll_mouse_y = y - box_y; status = scrollbar_mouse_status_to_message( scrollbar_mouse_action(scr, mouse, scroll_mouse_x, scroll_mouse_y)); } msg_data.explicit_status_text = status; content_broadcast(c, CONTENT_MSG_STATUS, msg_data); return; } if (html->drag_type == HTML_DRAG_TEXTAREA_SELECTION || html->drag_type == HTML_DRAG_TEXTAREA_SCROLLBAR) { box = html->drag_owner.textarea; assert(box->gadget != NULL); assert(box->gadget->type == GADGET_TEXTAREA || box->gadget->type == GADGET_PASSWORD || box->gadget->type == GADGET_TEXTBOX); box_coords(box, &box_x, &box_y); textarea_mouse_action(box->gadget->data.text.ta, mouse, x - box_x, y - box_y); /* TODO: Set appropriate statusbar message */ return; } if (html->drag_type == HTML_DRAG_CONTENT_SELECTION || html->drag_type == HTML_DRAG_CONTENT_SCROLL) { box = html->drag_owner.content; assert(box->object != NULL); box_coords(box, &box_x, &box_y); content_mouse_track(box->object, bw, mouse, x - box_x, y - box_y); return; } if (html->drag_type == HTML_DRAG_CONTENT_SELECTION) { box = html->drag_owner.content; assert(box->object != NULL); box_coords(box, &box_x, &box_y); content_mouse_track(box->object, bw, mouse, x - box_x, y - box_y); return; } /* Content related drags handled by now */ assert(html->drag_type == HTML_DRAG_NONE); /* search the box tree for a link, imagemap, form control, or * box with scrollbars */ box = html->layout; /* Consider the margins of the html page now */ box_x = box->margin[LEFT]; box_y = box->margin[TOP]; /* descend through visible boxes setting more specific values for: * box - deepest box at point * html_object_box - html object * html_object_pos_x - html object * html_object_pos_y - html object * object - non html object * iframe - iframe * url - href or imagemap * target - href or imagemap or gadget * url_box - href or imagemap * imagemap - imagemap * gadget - gadget * gadget_box - gadget * gadget_box_x - gadget * gadget_box_y - gadget * title - title * pointer * * drag_candidate - first box with scroll * padding_left - box with scroll * padding_right * padding_top * padding_bottom * scrollbar - inside padding box stops decent * scroll_mouse_x - inside padding box stops decent * scroll_mouse_y - inside padding box stops decent * * text_box - text box * text_box_x - text_box */ do { if ((box->style != NULL) && (css_computed_visibility(box->style) == CSS_VISIBILITY_HIDDEN)) { continue; } if (box->node != NULL) { node = box->node; } if (box->object) { if (content_get_type(box->object) == CONTENT_HTML) { html_object_box = box; html_object_pos_x = box_x; html_object_pos_y = box_y; } else { object = box->object; } } if (box->iframe) { iframe = box->iframe; } if (box->href) { url = box->href; target = box->target; url_box = box; } if (box->usemap) { url = imagemap_get(html, box->usemap, box_x, box_y, x, y, &target); if (url) { imagemap = true; url_box = box; } } if (box->gadget) { gadget = box->gadget; gadget_box = box; gadget_box_x = box_x; gadget_box_y = box_y; if (gadget->form) target = gadget->form->target; } if (box->title) { title = box->title; } pointer = get_pointer_shape(box, false); if ((box->scroll_x != NULL) || (box->scroll_y != NULL)) { if (drag_candidate == NULL) { drag_candidate = box; } padding_left = box_x + scrollbar_get_offset(box->scroll_x); padding_right = padding_left + box->padding[LEFT] + box->width + box->padding[RIGHT]; padding_top = box_y + scrollbar_get_offset(box->scroll_y); padding_bottom = padding_top + box->padding[TOP] + box->height + box->padding[BOTTOM]; if ((x > padding_left) && (x < padding_right) && (y > padding_top) && (y < padding_bottom)) { /* mouse inside padding box */ if ((box->scroll_y != NULL) && (x > (padding_right - SCROLLBAR_WIDTH))) { /* mouse above vertical box scroll */ scrollbar = box->scroll_y; scroll_mouse_x = x - (padding_right - SCROLLBAR_WIDTH); scroll_mouse_y = y - padding_top; break; } else if ((box->scroll_x != NULL) && (y > (padding_bottom - SCROLLBAR_WIDTH))) { /* mouse above horizontal box scroll */ scrollbar = box->scroll_x; scroll_mouse_x = x - padding_left; scroll_mouse_y = y - (padding_bottom - SCROLLBAR_WIDTH); break; } } } if (box->text && !box->object) { text_box = box; text_box_x = box_x; } } while ((box = box_at_point(box, x, y, &box_x, &box_y)) != NULL); /* use of box_x, box_y, or content below this point is probably a * mistake; they will refer to the last box returned by box_at_point */ assert(node != NULL); if (scrollbar) { status = scrollbar_mouse_status_to_message( scrollbar_mouse_action(scrollbar, mouse, scroll_mouse_x, scroll_mouse_y)); pointer = BROWSER_POINTER_DEFAULT; } else if (gadget) { textarea_mouse_status ta_status; switch (gadget->type) { case GADGET_SELECT: status = messages_get("FormSelect"); pointer = BROWSER_POINTER_MENU; if (mouse & BROWSER_MOUSE_CLICK_1 && nsoption_bool(core_select_menu)) { html->visible_select_menu = gadget; form_open_select_menu(c, gadget, form_select_menu_callback, c); pointer = BROWSER_POINTER_DEFAULT; } else if (mouse & BROWSER_MOUSE_CLICK_1) { msg_data.select_menu.gadget = gadget; content_broadcast(c, CONTENT_MSG_SELECTMENU, msg_data); } break; case GADGET_CHECKBOX: status = messages_get("FormCheckbox"); if (mouse & BROWSER_MOUSE_CLICK_1) { gadget->selected = !gadget->selected; dom_html_input_element_set_checked( (dom_html_input_element *)(gadget->node), gadget->selected); html__redraw_a_box(html, gadget_box); } break; case GADGET_RADIO: status = messages_get("FormRadio"); if (mouse & BROWSER_MOUSE_CLICK_1) form_radio_set(gadget); break; case GADGET_IMAGE: if (mouse & BROWSER_MOUSE_CLICK_1) { struct image_input_coords *coords, *oldcoords; /** \todo Find a way to not ignore errors */ coords = calloc(1, sizeof(*coords)); if (coords == NULL) { return; } coords->x = x - gadget_box_x; coords->y = y - gadget_box_y; if (dom_node_set_user_data( gadget->node, corestring_dom___ns_key_image_coords_node_data, coords, html__image_coords_dom_user_data_handler, &oldcoords) != DOM_NO_ERR) return; free(oldcoords); } /* drop through */ case GADGET_SUBMIT: if (gadget->form) { snprintf(status_buffer, sizeof status_buffer, messages_get("FormSubmit"), gadget->form->action); status = status_buffer; pointer = get_pointer_shape(gadget_box, false); if (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)) action = ACTION_SUBMIT; } else { status = messages_get("FormBadSubmit"); } break; case GADGET_TEXTBOX: case GADGET_PASSWORD: case GADGET_TEXTAREA: if (gadget->type == GADGET_TEXTAREA) status = messages_get("FormTextarea"); else status = messages_get("FormTextbox"); if (click && (html->selection_type != HTML_SELECTION_TEXTAREA || html->selection_owner.textarea != gadget_box)) { sel_owner.none = true; html_set_selection(html, HTML_SELECTION_NONE, sel_owner, true); } ta_status = textarea_mouse_action(gadget->data.text.ta, mouse, x - gadget_box_x, y - gadget_box_y); if (ta_status & TEXTAREA_MOUSE_EDITOR) { pointer = get_pointer_shape(gadget_box, false); } else { pointer = BROWSER_POINTER_DEFAULT; status = scrollbar_mouse_status_to_message( ta_status >> 3); } break; case GADGET_HIDDEN: /* not possible: no box generated */ break; case GADGET_RESET: status = messages_get("FormReset"); break; case GADGET_FILE: status = messages_get("FormFile"); if (mouse & BROWSER_MOUSE_CLICK_1) { msg_data.gadget_click.gadget = gadget; content_broadcast(c, CONTENT_MSG_GADGETCLICK, msg_data); } break; case GADGET_BUTTON: /* This gadget cannot be activated */ status = messages_get("FormButton"); break; } } else if (object && (mouse & BROWSER_MOUSE_MOD_2)) {