Esempio n. 1
0
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;
}
Esempio n. 2
0
/**
 * 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);
    }
}
Esempio n. 3
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)) {