From a31f6306f96e963a61cfd320e329071af3e281b7 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sat, 20 Nov 2004 00:02:56 +0000 Subject: [PATCH] [project @ 2004-11-20 00:02:56 by bursa] Improvements to overflow and scrolling: scrollbars now have most of the usual RISC OS behaviour. Better rendering of dotted and dashed borders. svn path=/import/netsurf/; revision=1363 --- !NetSurf/Resources/de/Messages | 11 ++ !NetSurf/Resources/en/Messages | 11 ++ !NetSurf/Resources/fr/Messages | 11 ++ desktop/browser.c | 194 ++++++++++++++++++++++++++---- desktop/browser.h | 12 +- desktop/plotters.h | 2 +- render/box.c | 3 +- render/box.h | 10 ++ render/html_redraw.c | 213 +++++++++++++++++++++++++++++---- render/layout.c | 10 +- riscos/plotters.c | 114 +++++++++--------- 11 files changed, 470 insertions(+), 121 deletions(-) diff --git a/!NetSurf/Resources/de/Messages b/!NetSurf/Resources/de/Messages index 502eccdc9..3f26a2c47 100644 --- a/!NetSurf/Resources/de/Messages +++ b/!NetSurf/Resources/de/Messages @@ -242,6 +242,17 @@ SaveText:Webpage SaveObject:Object SaveLink:Link +ScrollUp:Click the arrow to scroll up +ScrollPUp:Click to scroll up one page +ScrollV:Drag the bar to scroll vertically +ScrollPDown:Click to scroll down one page +ScrollDown:Click the arrow to scroll down +ScrollLeft:Click the arrow to scroll left +ScrollPLeft:Click to scroll left one page +ScrollH:Drag the bar to scroll horizontally +ScrollPRight:Click to scroll right one page +ScrollRight:Click the arrow to scroll right + # Interactive help HelpToolbar0:Schaltet zurück auf die zuvor dargestellte Seite.|MDer Inhalt wird dabei nicht aktualisiert. HelpToolbar1:Schaltet vorwärts auf die nächste Seite.|MDer Inhalt wird dabei nicht aktualisiert. diff --git a/!NetSurf/Resources/en/Messages b/!NetSurf/Resources/en/Messages index 1b9dde9b1..dd3bb0b80 100644 --- a/!NetSurf/Resources/en/Messages +++ b/!NetSurf/Resources/en/Messages @@ -242,6 +242,17 @@ SaveText:Webpage SaveObject:Object SaveLink:Link +ScrollUp:Click the arrow to scroll up +ScrollPUp:Click to scroll up one page +ScrollV:Drag the bar to scroll vertically +ScrollPDown:Click to scroll down one page +ScrollDown:Click the arrow to scroll down +ScrollLeft:Click the arrow to scroll left +ScrollPLeft:Click to scroll left one page +ScrollH:Drag the bar to scroll horizontally +ScrollPRight:Click to scroll right one page +ScrollRight:Click the arrow to scroll right + # Interactive help HelpToolbar0:\Tback button.|M\Straverse back one page in the history tree.|MDoes not resubmit form information. HelpToolbar1:\Tforward button.|M\Straverse forward one page in the history tree.|MDoes not resubmit form information. diff --git a/!NetSurf/Resources/fr/Messages b/!NetSurf/Resources/fr/Messages index a61cb2194..14c9bb6e4 100644 --- a/!NetSurf/Resources/fr/Messages +++ b/!NetSurf/Resources/fr/Messages @@ -242,6 +242,17 @@ SaveText:PageWeb SaveObject:Objet SaveLink:Lien +ScrollUp:Click the arrow to scroll up +ScrollPUp:Click to scroll up one page +ScrollV:Drag the bar to scroll vertically +ScrollPDown:Click to scroll down one page +ScrollDown:Click the arrow to scroll down +ScrollLeft:Click the arrow to scroll left +ScrollPLeft:Click to scroll left one page +ScrollH:Drag the bar to scroll horizontally +ScrollPRight:Click to scroll right one page +ScrollRight:Click the arrow to scroll right + # Interactive help HelpToolbar0:\Tle bouton de retour.|M\Srevenir d'une page en arrière dans l'historique.|MNe renvoie pas l'information de formulaire. HelpToolbar1:\Tle bouton d'avance.|M\Savancer d'une page dans l'historique.|MNe renvoie pas l'information de formulaire. diff --git a/desktop/browser.c b/desktop/browser.c index 8d589863f..640e2d8ea 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -56,6 +56,9 @@ static void browser_window_mouse_click_html(struct browser_window *bw, browser_mouse_click click, int x, int y); static void browser_window_mouse_drag_html(struct browser_window *bw, int x, int y); +static const char *browser_window_scrollbar_click(struct browser_window *bw, + browser_mouse_click click, struct box *box, + int box_x, int box_y, int x, int y); static void browser_radio_set(struct content *content, struct form_control *radio); static void browser_redraw_box(struct content *c, struct box *box); @@ -631,7 +634,9 @@ void browser_window_mouse_click_html(struct browser_window *bw, gui_pointer_shape pointer = GUI_POINTER_DEFAULT; int box_x = 0, box_y = 0; int gadget_box_x = 0, gadget_box_y = 0; + int scroll_box_x = 0, scroll_box_y = 0; struct box *gadget_box = 0; + struct box *scroll_box = 0; struct content *c = bw->current_content; struct box *box; struct content *content = c; @@ -681,24 +686,26 @@ void browser_window_mouse_click_html(struct browser_window *bw, if (box->style && box->style->cursor != CSS_CURSOR_UNKNOWN) pointer = get_pointer_shape(box->style->cursor); - if ((box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK || - box->type == BOX_FLOAT_LEFT || - box->type == BOX_FLOAT_RIGHT) && - box->style && - box->style->overflow == CSS_OVERFLOW_SCROLL) { - if (box_x + box->padding[LEFT] + box->width < x) { - /* vertical scrollbar */ - bw->drag_type = DRAGGING_VSCROLL; - bw->scrolling_box = box; - bw->scrolling_last_x = x; - bw->scrolling_last_y = y; - } + if (box->style && box->type != BOX_BR && + box->type != BOX_INLINE && + (box->style->overflow == CSS_OVERFLOW_SCROLL || + box->style->overflow == CSS_OVERFLOW_AUTO) && + ((box_vscrollbar_present(box) && + box_x + box->scroll_x + box->padding[LEFT] + + box->width < x) || + (box_hscrollbar_present(box) && + box_y + box->scroll_y + box->padding[TOP] + + box->height < y))) { + scroll_box = box; + scroll_box_x = box_x + box->scroll_x; + scroll_box_y = box_y + box->scroll_y; } } - if (bw->drag_type == DRAGGING_VSCROLL || - bw->drag_type == DRAGGING_HSCROLL) { - status = messages_get("Scrollbar"); + if (scroll_box) { + status = browser_window_scrollbar_click(bw, click, scroll_box, + scroll_box_x, scroll_box_y, + x - scroll_box_x, y - scroll_box_y); } else if (gadget) { switch (gadget->type) { @@ -728,7 +735,8 @@ void browser_window_mouse_click_html(struct browser_window *bw, /* drop through */ case GADGET_SUBMIT: if (gadget->form) { - res = url_join(gadget->form->action, base_url, &url); + res = url_join(gadget->form->action, base_url, + &url); snprintf(status_buffer, sizeof status_buffer, messages_get("FormSubmit"), (res == URL_FUNC_OK) ? url : @@ -830,32 +838,165 @@ void browser_window_mouse_click_html(struct browser_window *bw, void browser_window_mouse_drag_html(struct browser_window *bw, int x, int y) { - int scroll_y; + int scroll_x, scroll_y; struct box *box; if (bw->drag_type == DRAGGING_VSCROLL) { box = bw->scrolling_box; assert(box); - if (y == bw->scrolling_last_y) - return; - - scroll_y = box->scroll_y + (y - bw->scrolling_last_y); - bw->scrolling_last_y = y; - + scroll_y = bw->scrolling_start_scroll_y + + (float) (y - bw->scrolling_start_y) / + (float) bw->scrolling_well_height * + (float) (box->descendant_y1 - + box->descendant_y0); if (scroll_y < box->descendant_y0) scroll_y = box->descendant_y0; else if (box->descendant_y1 - box->height < scroll_y) scroll_y = box->descendant_y1 - box->height; - if (scroll_y == box->scroll_y) return; box->scroll_y = scroll_y; + browser_redraw_box(bw->current_content, bw->scrolling_box); + } else if (bw->drag_type == DRAGGING_HSCROLL) { + box = bw->scrolling_box; + assert(box); + scroll_x = bw->scrolling_start_scroll_x + + (float) (x - bw->scrolling_start_x) / + (float) bw->scrolling_well_width * + (float) (box->descendant_x1 - + box->descendant_x0); + if (scroll_x < box->descendant_x0) + scroll_x = box->descendant_x0; + else if (box->descendant_x1 - box->width < scroll_x) + scroll_x = box->descendant_x1 - box->width; + if (scroll_x == box->scroll_x) + return; + box->scroll_x = scroll_x; browser_redraw_box(bw->current_content, bw->scrolling_box); } } +/** + * Handle mouse clicks in a box scrollbar. + * + * \param bw browser window + * \param click type of mouse click + * \param box scrolling box + * \param box_x position of box in global document coordinates + * \param box_y position of box in global document coordinates + * \param x coordinate of click relative to box position + * \param y coordinate of click relative to box position + * \return status bar message + */ + +const char *browser_window_scrollbar_click(struct browser_window *bw, + browser_mouse_click click, struct box *box, + int box_x, int box_y, int x, int y) +{ + const int w = SCROLLBAR_WIDTH; + bool vscroll, hscroll; + int well_height, bar_top, bar_height; + int well_width, bar_left, bar_width; + const char *status = 0; + bool vert; + int z, scroll, bar_start, bar_size, well_size, page; + + box_scrollbar_dimensions(box, + box->padding[LEFT] + box->width + box->padding[RIGHT], + box->padding[TOP] + box->height + box->padding[BOTTOM], + w, + &vscroll, &hscroll, + &well_height, &bar_top, &bar_height, + &well_width, &bar_left, &bar_width); + + /* store some data for scroll drags */ + bw->scrolling_box = box; + bw->scrolling_start_x = box_x + x; + bw->scrolling_start_y = box_y + y; + bw->scrolling_start_scroll_x = box->scroll_x; + bw->scrolling_start_scroll_y = box->scroll_y; + bw->scrolling_well_width = well_width; + bw->scrolling_well_height = well_height; + + /* determine which scrollbar was clicked */ + if (box_vscrollbar_present(box) && + box->padding[LEFT] + box->width < x) { + vert = true; + z = y; + scroll = box->scroll_y; + well_size = well_height; + bar_start = bar_top; + bar_size = bar_height; + page = box->height; + } else { + vert = false; + z = x; + scroll = box->scroll_x; + well_size = well_width; + bar_start = bar_left; + bar_size = bar_width; + page = box->width; + } + + /* find icon in scrollbar and calculate scroll */ + if (z < w) { + status = messages_get(vert ? "ScrollUp" : "ScrollLeft"); + if (click == BROWSER_MOUSE_CLICK_1) + scroll -= 16; + else if (click == BROWSER_MOUSE_CLICK_2) + scroll += 16; + } else if (z < w + bar_start + w / 4) { + status = messages_get(vert ? "ScrollPUp" : "ScrollPLeft"); + if (click == BROWSER_MOUSE_CLICK_1) + scroll -= page; + else if (click == BROWSER_MOUSE_CLICK_2) + scroll += page; + } else if (z < w + bar_start + bar_size - w / 4) { + status = messages_get(vert ? "ScrollV" : "ScrollH"); + if (click == BROWSER_MOUSE_CLICK_1) + bw->drag_type = vert ? DRAGGING_VSCROLL : + DRAGGING_HSCROLL; + } else if (z < w + well_size) { + status = messages_get(vert ? "ScrollPDown" : "ScrollPRight"); + if (click == BROWSER_MOUSE_CLICK_1) + scroll += page; + else if (click == BROWSER_MOUSE_CLICK_2) + scroll -= page; + } else { + status = messages_get(vert ? "ScrollDown" : "ScrollRight"); + if (click == BROWSER_MOUSE_CLICK_1) + scroll += 16; + else if (click == BROWSER_MOUSE_CLICK_2) + scroll -= 16; + } + + /* update box and redraw */ + if (vert) { + if (scroll < box->descendant_y0) + scroll = box->descendant_y0; + else if (box->descendant_y1 - box->height < scroll) + scroll = box->descendant_y1 - box->height; + if (scroll != box->scroll_y) { + box->scroll_y = scroll; + browser_redraw_box(bw->current_content, box); + } + } else { + if (scroll < box->descendant_x0) + scroll = box->descendant_x0; + else if (box->descendant_x1 - box->width < scroll) + scroll = box->descendant_x1 - box->width; + if (scroll != box->scroll_x) { + box->scroll_x = scroll; + browser_redraw_box(bw->current_content, box); + } + } + + return status; +} + + /** * Set a radio form control and clear the others in the group. * @@ -868,8 +1009,9 @@ void browser_radio_set(struct content *content, { struct form_control *control; - /* some sanity checking */ - if (content == NULL || radio == NULL || radio->form == NULL) + assert(content); + assert(radio); + if (!radio->form) return; if (radio->selected) diff --git a/desktop/browser.h b/desktop/browser.h index c77a5d13f..750cf329b 100644 --- a/desktop/browser.h +++ b/desktop/browser.h @@ -58,9 +58,15 @@ struct browser_window { /** Box currently being scrolled, or 0. */ struct box *scrolling_box; - /** Mouse position last scroll movement. */ - int scrolling_last_x; - int scrolling_last_y; + /** Mouse position at start of current scroll drag. */ + int scrolling_start_x; + int scrolling_start_y; + /** Scroll offsets at start of current scroll draw. */ + int scrolling_start_scroll_x; + int scrolling_start_scroll_y; + /** Well dimensions for current scroll drag. */ + int scrolling_well_width; + int scrolling_well_height; /** Referer for current fetch, or 0. */ char *referer; diff --git a/desktop/plotters.h b/desktop/plotters.h index 0be1213a6..60465f3e8 100644 --- a/desktop/plotters.h +++ b/desktop/plotters.h @@ -24,7 +24,7 @@ struct font_data; struct plotter_table { bool (*clg)(colour c); bool (*rectangle)(int x0, int y0, int width, int height, - colour c, bool dotted); + int line_width, colour c, bool dotted, bool dashed); bool (*line)(int x0, int y0, int x1, int y1, int width, colour c, bool dotted, bool dashed); bool (*polygon)(int *p, unsigned int n, colour fill); diff --git a/render/box.c b/render/box.c index d9fcb6233..cdca6c66f 100644 --- a/render/box.c +++ b/render/box.c @@ -3064,8 +3064,7 @@ siblings: bool box_contains_point(struct box *box, int x, int y) { - if (box->style && (box->style->overflow == CSS_OVERFLOW_HIDDEN || - box->style->overflow == CSS_OVERFLOW_SCROLL)) { + if (box->style && box->style->overflow != CSS_OVERFLOW_VISIBLE) { if (box->x <= x && x < box->x + box->padding[LEFT] + box->width + box->padding[RIGHT] && diff --git a/render/box.h b/render/box.h index c50c7ef00..b401799fa 100644 --- a/render/box.h +++ b/render/box.h @@ -249,4 +249,14 @@ struct box *box_at_point(struct box *box, int x, int y, struct box *box_object_at_point(struct content *c, int x, int y); struct box *box_find_by_id(struct box *box, const char *id); +bool box_vscrollbar_present(const struct box *box); +bool box_hscrollbar_present(const struct box *box); +void box_scrollbar_dimensions(const struct box *box, + int padding_width, int padding_height, int w, + bool *vscroll, bool *hscroll, + int *well_height, + int *bar_top, int *bar_height, + int *well_width, + int *bar_left, int *bar_width); + #endif diff --git a/render/html_redraw.c b/render/html_redraw.c index 28796d1a0..a46edbd47 100644 --- a/render/html_redraw.c +++ b/render/html_redraw.c @@ -43,7 +43,8 @@ static bool html_redraw_file(int x, int y, int width, int height, static bool html_redraw_background(int x, int y, struct box *box, float scale, colour background_colour); static bool html_redraw_scrollbars(struct box *box, float scale, - int x, int y, int padding_width, int padding_height); + int x, int y, int padding_width, int padding_height, + colour background_colour); bool html_redraw_debug = false; @@ -161,10 +162,10 @@ bool html_redraw_box(struct box *box, /* dotted debug outlines */ if (html_redraw_debug) { if (!plot.rectangle(x, y, padding_width, padding_height, - 0x0000ff, true)) + 1, 0x0000ff, true, false)) return false; if (!plot.rectangle(x + padding_left, y + padding_top, - width, height, 0xff0000, true)) + width, height, 1, 0xff0000, true, false)) return false; if (!plot.rectangle(x - (box->border[LEFT] + box->margin[LEFT]) * scale, @@ -176,7 +177,7 @@ bool html_redraw_box(struct box *box, padding_height + (box->border[TOP] + box->margin[TOP] + box->border[BOTTOM] + box->margin[BOTTOM]) * scale, - 0x00ffff, true)) + 1, 0x00ffff, true, false)) return false; } @@ -259,14 +260,6 @@ bool html_redraw_box(struct box *box, if (!plot.clip(x0, y0, x1, y1)) return false; } - - /* scrollbars */ - if (box->style->overflow == CSS_OVERFLOW_SCROLL) { - if (!html_redraw_scrollbars(box, scale, x, y, - padding_width, padding_height)) - return false; - } - } if (box->object) { @@ -350,6 +343,15 @@ bool html_redraw_box(struct box *box, return false; } + /* scrollbars */ + if (box->style && box->type != BOX_BR && box->type != BOX_INLINE && + (box->style->overflow == CSS_OVERFLOW_SCROLL || + box->style->overflow == CSS_OVERFLOW_AUTO)) + if (!html_redraw_scrollbars(box, scale, x, y, + padding_width, padding_height, + current_background_color)) + return false; + if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK || box->type == BOX_TABLE_CELL || box->object) if (!plot.clip(clip_x0, clip_y0, clip_x1, clip_y1)) @@ -750,27 +752,186 @@ bool html_redraw_background(int x, int y, */ bool html_redraw_scrollbars(struct box *box, float scale, - int x, int y, int padding_width, int padding_height) + int x, int y, int padding_width, int padding_height, + colour background_colour) { - int w = SCROLLBAR_WIDTH * scale; + const int w = SCROLLBAR_WIDTH * scale; + bool vscroll, hscroll; + int well_height, bar_top, bar_height; + int well_width, bar_left, bar_width; + const colour vcolour = box->style->border[RIGHT].color; + const colour hcolour = box->style->border[BOTTOM].color; - /* vertical scrollbar */ - if (box->descendant_y0 < box->descendant_y1) { - int bar_top = (float) padding_height * (float) box->scroll_y / - (float) (box->descendant_y1 - - box->descendant_y0); - int bar_height = (float) padding_height * (float) box->height / - (float) (box->descendant_y1 - - box->descendant_y0); + box_scrollbar_dimensions(box, padding_width, padding_height, w, + &vscroll, &hscroll, + &well_height, &bar_top, &bar_height, + &well_width, &bar_left, &bar_width); + +#define TRIANGLE(x0, y0, x1, y1, x2, y2, c) \ + if (!plot.line(x0, y0, x1, y1, scale, c, false, false)) \ + return false; \ + if (!plot.line(x0, y0, x2, y2, scale, c, false, false)) \ + return false; \ + if (!plot.line(x1, y1, x2, y2, scale, c, false, false)) \ + return false; + + /* fill scrollbar well(s) with background colour */ + if (vscroll) if (!plot.fill(x + padding_width - w, y, x + padding_width, y + padding_height, - 0x777777)) + background_colour)) return false; - if (!plot.fill(x + padding_width - w + 4, y + bar_top, - x + padding_width - 4, y + bar_top + bar_height, - 0xbbbbbb)) + if (hscroll) + if (!plot.fill(x, y + padding_height - w, + x + padding_width, y + padding_height, + background_colour)) return false; + + /* vertical scrollbar */ + if (vscroll) { + /* left line */ + if (!plot.line(x + padding_width - w, y, + x + padding_width - w, y + padding_height, + scale, vcolour, false, false)) + return false; + /* up arrow */ + TRIANGLE(x + padding_width - w / 2, y + w / 4, + x + padding_width - w * 3 / 4, y + w * 3 / 4, + x + padding_width - w / 4, y + w * 3 / 4, + vcolour); + /* separator */ + if (!plot.line(x + padding_width - w, y + w, + x + padding_width, y + w, + scale, vcolour, false, false)) + return false; + /* bar */ + if (!plot.rectangle(x + padding_width - w * 3 / 4, + y + w + bar_top + w / 4, + w / 2, bar_height - w / 2, + scale, vcolour, false, false)) + return false; + /* separator */ + if (!plot.line(x + padding_width - w, y + w + well_height, + x + padding_width, y + w + well_height, + scale, vcolour, false, false)) + return false; + /* down arrow */ + TRIANGLE(x + padding_width - w / 2, + y + w + well_height + w * 3 / 4, + x + padding_width - w * 3 / 4, + y + w + well_height + w / 4, + x + padding_width - w / 4, + y + w + well_height + w / 4, + vcolour); + } + + /* horizontal scrollbar */ + if (hscroll) { + /* top line */ + if (!plot.line(x, y + padding_height - w, + x + well_width + w + w, y + padding_height - w, + scale, hcolour, false, false)) + return false; + /* left arrow */ + TRIANGLE(x + w / 4, y + padding_height - w / 2, + x + w * 3 / 4, y + padding_height - w * 3 / 4, + x + w * 3 / 4, y + padding_height - w / 4, + hcolour); + /* separator */ + if (!plot.line(x + w, y + padding_height - w, + x + w, y + padding_height, + scale, hcolour, false, false)) + return false; + /* bar */ + if (!plot.rectangle(x + w + bar_left + w / 4, + y + padding_height - w * 3 / 4, + bar_width - w / 2, w / 2, + scale, hcolour, false, false)) + return false; + /* separator */ + if (!plot.line(x + w + well_width, y + padding_height - w, + x + w + well_width, y + padding_height, + scale, hcolour, false, false)) + return false; + /* right arrow */ + TRIANGLE(x + w + well_width + w * 3 / 4, + y + padding_height - w / 2, + x + w + well_width + w / 4, + y + padding_height - w * 3 / 4, + x + w + well_width + w / 4, + y + padding_height - w / 4, + hcolour); } return true; } + + +/** + * Determine if a box has a vertical scrollbar. + * + * \param box scrolling box + * \return the box has a vertical scrollbar + */ + +bool box_vscrollbar_present(const struct box * const box) +{ + return box->descendant_y0 < -box->border[TOP] || + box->padding[TOP] + box->height + box->padding[BOTTOM] + + box->border[BOTTOM] < box->descendant_y1; +} + + +/** + * Determine if a box has a horizontal scrollbar. + * + * \param box scrolling box + * \return the box has a horizontal scrollbar + */ + +bool box_hscrollbar_present(const struct box * const box) +{ + return box->descendant_x0 < -box->border[LEFT] || + box->padding[LEFT] + box->width + box->padding[RIGHT] + + box->border[RIGHT] < box->descendant_x1; +} + + +/** + * Calculate scrollbar dimensions and positions for a box. + * + * \param box scrolling box + * \param padding_width scaled width of padding box + * \param padding_height scaled height of padding box + * \param w scaled scrollbar width + * \param vscroll updated to vertical scrollbar present + * \param hscroll updated to horizontal scrollbar present + * \param well_height updated to vertical well height + * \param bar_top updated to top position of vertical scrollbar + * \param bar_height updated to height of vertical scrollbar + * \param well_width updated to horizontal well width + * \param bar_left updated to left position of horizontal scrollbar + * \param bar_width updated to width of horizontal scrollbar + */ + +void box_scrollbar_dimensions(const struct box * const box, + const int padding_width, const int padding_height, const int w, + bool * const vscroll, bool * const hscroll, + int * const well_height, + int * const bar_top, int * const bar_height, + int * const well_width, + int * const bar_left, int * const bar_width) +{ + *vscroll = box_vscrollbar_present(box); + *hscroll = box_hscrollbar_present(box); + *well_height = padding_height - w - w; + *bar_top = (float) *well_height * (float) box->scroll_y / + (float) (box->descendant_y1 - box->descendant_y0); + *bar_height = (float) *well_height * (float) box->height / + (float) (box->descendant_y1 - box->descendant_y0); + *well_width = padding_width - w - w - (*vscroll ? w : 0); + *bar_left = (float) *well_width * (float) box->scroll_x / + (float) (box->descendant_x1 - box->descendant_x0); + *bar_width = (float) *well_width * (float) box->width / + (float) (box->descendant_x1 - box->descendant_x0); +} diff --git a/render/layout.c b/render/layout.c index 253ce648a..96255b540 100644 --- a/render/layout.c +++ b/render/layout.c @@ -355,10 +355,12 @@ void layout_block_find_dimensions(int available_width, struct box *box) box->width = layout_solve_width(available_width, width, margin, padding, border); - if (style->overflow == CSS_OVERFLOW_SCROLL) { - /* make space for vertical scrollbar */ + if (style->overflow == CSS_OVERFLOW_SCROLL || + style->overflow == CSS_OVERFLOW_AUTO) { + /* make space for scrollbars */ box->width -= SCROLLBAR_WIDTH; box->padding[RIGHT] += SCROLLBAR_WIDTH; + box->padding[BOTTOM] += SCROLLBAR_WIDTH; } if (box->object && box->object->type == CONTENT_HTML && @@ -423,7 +425,8 @@ int layout_solve_width(int available_width, int width, void layout_float_find_dimensions(int available_width, struct css_style *style, struct box *box) { - int scrollbar_width = style->overflow == CSS_OVERFLOW_SCROLL ? + int scrollbar_width = (style->overflow == CSS_OVERFLOW_SCROLL || + style->overflow == CSS_OVERFLOW_AUTO) ? SCROLLBAR_WIDTH : 0; layout_find_dimensions(available_width, style, @@ -461,6 +464,7 @@ void layout_float_find_dimensions(int available_width, } box->padding[RIGHT] += scrollbar_width; + box->padding[BOTTOM] += scrollbar_width; if (box->object) { /* floating replaced element, see 10.3.6 and 10.6.2 */ diff --git a/riscos/plotters.c b/riscos/plotters.c index 33a618cac..e25c5ddcc 100644 --- a/riscos/plotters.c +++ b/riscos/plotters.c @@ -22,9 +22,11 @@ static bool ro_plot_clg(colour c); static bool ro_plot_rectangle(int x0, int y0, int width, int height, - colour c, bool dotted); + int line_width, colour c, bool dotted, bool dashed); static bool ro_plot_line(int x0, int y0, int x1, int y1, int width, colour c, bool dotted, bool dashed); +static bool ro_plot_path(const draw_path * const path, int width, + colour c, bool dotted, bool dashed); static bool ro_plot_polygon(int *p, unsigned int n, colour fill); static bool ro_plot_fill(int x0, int y0, int x1, int y1, colour c); static bool ro_plot_clip(int clip_x0, int clip_y0, @@ -88,82 +90,74 @@ bool ro_plot_clg(colour c) bool ro_plot_rectangle(int x0, int y0, int width, int height, - colour c, bool dotted) + int line_width, colour c, bool dotted, bool dashed) { - os_plot_code plot_code = (dotted ? os_PLOT_DOTTED : os_PLOT_SOLID) | - os_PLOT_BY; - os_error *error; + const int path[] = { draw_MOVE_TO, + (ro_plot_origin_x + x0 * 2) * 256, + (ro_plot_origin_y - y0 * 2 - 1) * 256, + draw_LINE_TO, + (ro_plot_origin_x + (x0 + width) * 2) * 256, + (ro_plot_origin_y - y0 * 2 - 1) * 256, + draw_LINE_TO, + (ro_plot_origin_x + (x0 + width) * 2) * 256, + (ro_plot_origin_y - (y0 + height) * 2 - 1) * 256, + draw_LINE_TO, + (ro_plot_origin_x + x0 * 2) * 256, + (ro_plot_origin_y - (y0 + height) * 2 - 1) * 256, + draw_CLOSE_LINE, + (ro_plot_origin_x + x0 * 2) * 256, + (ro_plot_origin_y - y0 * 2 - 1) * 256, + draw_END_PATH }; - error = xcolourtrans_set_gcol(c << 8, 0, os_ACTION_OVERWRITE, 0, 0); - if (error) { - LOG(("xcolourtrans_set_gcol: 0x%x: %s", - error->errnum, error->errmess)); - return false; - } - error = xos_plot(os_MOVE_TO, - ro_plot_origin_x + x0 * 2, - ro_plot_origin_y - y0 * 2); - if (error) { - LOG(("xos_plot: 0x%x: %s", error->errnum, error->errmess)); - return false; - } - error = xos_plot(plot_code, width * 2, 0); - if (error) { - LOG(("xos_plot: 0x%x: %s", error->errnum, error->errmess)); - return false; - } - error = xos_plot(plot_code, 0, -height * 2); - if (error) { - LOG(("xos_plot: 0x%x: %s", error->errnum, error->errmess)); - return false; - } - error = xos_plot(plot_code, -width * 2, 0); - if (error) { - LOG(("xos_plot: 0x%x: %s", error->errnum, error->errmess)); - return false; - } - error = xos_plot(plot_code, 0, height * 2); - if (error) { - LOG(("xos_plot: 0x%x: %s", error->errnum, error->errmess)); - return false; - } - - return true; + return ro_plot_path((const draw_path *) path, line_width, c, + dotted, dashed); } -static int path[] = { draw_MOVE_TO, 0, 0, draw_LINE_TO, 0, 0, - draw_END_PATH, 0 }; -static const draw_line_style line_style = { draw_JOIN_MITRED, - draw_CAP_BUTT, draw_CAP_BUTT, 0, 0x7fffffff, - 0, 0, 0, 0 }; -static const int dash_pattern_dotted[] = { 0, 1, 512 }; -static const int dash_pattern_dashed[] = { 0, 1, 2048 }; - bool ro_plot_line(int x0, int y0, int x1, int y1, int width, colour c, bool dotted, bool dashed) { - const draw_dash_pattern *dash_pattern; + const int path[] = { draw_MOVE_TO, + (ro_plot_origin_x + x0 * 2) * 256, + (ro_plot_origin_y - y0 * 2 - 1) * 256, + draw_LINE_TO, + (ro_plot_origin_x + x1 * 2) * 256, + (ro_plot_origin_y - y1 * 2 - 1) * 256, + draw_END_PATH }; + + return ro_plot_path((const draw_path *) path, width, c, dotted, dashed); +} + + +bool ro_plot_path(const draw_path * const path, int width, + colour c, bool dotted, bool dashed) +{ + static const draw_line_style line_style = { draw_JOIN_MITRED, + draw_CAP_BUTT, draw_CAP_BUTT, 0, 0x7fffffff, + 0, 0, 0, 0 }; + draw_dash_pattern dash = { 0, 1, { 512 } }; + const draw_dash_pattern *dash_pattern = 0; os_error *error; - if (dotted) - dash_pattern = (const draw_dash_pattern *) &dash_pattern_dotted; - else if (dashed) - dash_pattern = (const draw_dash_pattern *) &dash_pattern_dashed; - else - dash_pattern = NULL; + if (width < 1) + width = 1; + + if (dotted) { + dash.elements[0] = 512 * width; + dash_pattern = ‐ + } else if (dashed) { + dash.elements[0] = 1536 * width; + dash_pattern = ‐ + } - path[1] = (ro_plot_origin_x + x0 * 2) * 256; - path[2] = (ro_plot_origin_y - y0 * 2 - 1) * 256; - path[4] = (ro_plot_origin_x + x1 * 2) * 256; - path[5] = (ro_plot_origin_y - y1 * 2 - 1) * 256; error = xcolourtrans_set_gcol(c << 8, 0, os_ACTION_OVERWRITE, 0, 0); if (error) { LOG(("xcolourtrans_set_gcol: 0x%x: %s", error->errnum, error->errmess)); return false; } - error = xdraw_stroke((draw_path *) path, 0, 0, 0, width * 2 * 256, + + error = xdraw_stroke(path, 0, 0, 0, width * 2 * 256, &line_style, dash_pattern); if (error) { LOG(("xdraw_stroke: 0x%x: %s",