diff --git a/amiga/gui.c b/amiga/gui.c index 5aadcc501..c10abed0e 100755 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -1961,7 +1961,6 @@ void ami_handle_msg(void) { if(gwin->redraw_required || gwin->bw->reformat_pending) { ami_do_redraw(gwin); - gwin->bw->window->deferred = false; } gui_window_update_box_deferred(gwin->bw->window); @@ -3904,6 +3903,7 @@ void ami_do_redraw(struct gui_window_2 *gwin) if(gwin->redraw_scroll) { + struct rect rect; int x0, y0, x1, y1; gwin->bw->window->c_h_temp = gwin->bw->window->c_h; @@ -3916,28 +3916,28 @@ void ami_do_redraw(struct gui_window_2 *gwin) if(vcurrent>oldv) /* Going down */ { - ami_spacebox_to_ns_coords(gwin, &x0, &y0, 0, height - (vcurrent - oldv) - 1); - ami_spacebox_to_ns_coords(gwin, &x1, &y1, width + 1, height + 1); - ami_do_redraw_limits(gwin->bw->window, gwin->bw, true, x0, y0, x1, y1); + ami_spacebox_to_ns_coords(gwin, &rect.x0, &rect.y0, 0, height - (vcurrent - oldv) - 1); + ami_spacebox_to_ns_coords(gwin, &rect.x1, &rect.y1, width + 1, height + 1); + gui_window_update_box(gwin->bw->window, &rect); } else if(vcurrentbw->window, gwin->bw, true, x0, y0, x1, y1); + ami_spacebox_to_ns_coords(gwin, &rect.x0, &rect.y0, 0, 0); + ami_spacebox_to_ns_coords(gwin, &rect.x1, &rect.y1, width + 1, oldv - vcurrent + 1); + gui_window_update_box(gwin->bw->window, &rect); } if(hcurrent>oldh) /* Going right */ { - ami_spacebox_to_ns_coords(gwin, &x0, &y0, width - (hcurrent - oldh), 0); - ami_spacebox_to_ns_coords(gwin, &x1, &y1, width + 1, height + 1); - ami_do_redraw_limits(gwin->bw->window, gwin->bw, true, x0, y0, x1, y1); + ami_spacebox_to_ns_coords(gwin, &rect.x0, &rect.y0, width - (hcurrent - oldh), 0); + ami_spacebox_to_ns_coords(gwin, &rect.x1, &rect.y1, width + 1, height + 1); + gui_window_update_box(gwin->bw->window, &rect); } else if(hcurrentbw->window, gwin->bw, true, x0, y0, x1, y1); + ami_spacebox_to_ns_coords(gwin, &rect.x0, &rect.y0, 0, 0); + ami_spacebox_to_ns_coords(gwin, &rect.x1, &rect.y1, oldh - hcurrent + 1, height + 1); + gui_window_update_box(gwin->bw->window, &rect); } } else @@ -3975,6 +3975,8 @@ void ami_do_redraw(struct gui_window_2 *gwin) ami_reset_pointer(gwin); } + /* Tell NetSurf not to bother with the next queued box redraw, as we've redrawn everything. */ + gwin->bw->window->deferred = false; } ami_update_buttons(gwin); diff --git a/atari/plot/font_freetype.c b/atari/plot/font_freetype.c index 8db7cc2c0..ed850bce2 100755 --- a/atari/plot/font_freetype.c +++ b/atari/plot/font_freetype.c @@ -443,8 +443,9 @@ static int str_split( FONT_PLOTTER self, const plot_font_style_t *fstyle, last_space_idx = nxtchr; } *actual_x += glyph->advance.x >> 16; - if (*actual_x > x) { - /* string has exceeded available width return previous space*/ + if (*actual_x > x && last_space_idx != 0) { + /* string has exceeded available width and we've + * found a space; return previous space */ *actual_x = last_space_x; *char_offset = last_space_idx; return true; diff --git a/atari/plot/font_internal.c b/atari/plot/font_internal.c index 3db29eba5..2b0025a71 100644 --- a/atari/plot/font_internal.c +++ b/atari/plot/font_internal.c @@ -118,7 +118,7 @@ static int str_split( FONT_PLOTTER self, const plot_font_style_t * fstyle, const size_t length,int x, size_t *char_offset, int *actual_x ) { const struct fb_font_desc* fb_font = fb_get_font(fstyle); - *char_offset = x / fb_font->width; + int c_off = *char_offset = x / fb_font->width; if (*char_offset > length) { *char_offset = length; } else { @@ -127,6 +127,13 @@ static int str_split( FONT_PLOTTER self, const plot_font_style_t * fstyle, const break; (*char_offset)--; } + if (*char_offset == 0) { + *char_offset = c_off; + while (*char_offset < length && + string[*char_offset] != ' ') { + (*char_offset)++; + } + } } *actual_x = *char_offset * fb_font->width; return( 1 ); diff --git a/atari/plot/font_vdi.c b/atari/plot/font_vdi.c index 4ebab24fb..340759f02 100755 --- a/atari/plot/font_vdi.c +++ b/atari/plot/font_vdi.c @@ -164,7 +164,7 @@ static int str_split( FONT_PLOTTER self, const plot_font_style_t * fstyle, const last_space_idx = nxtchr; } *actual_x += cellw; - if (*actual_x > x) { + if (*actual_x > x && last_space_idx != 0) { *actual_x = last_space_x; *char_offset = last_space_idx; //printf("at: %s\n", lstr); diff --git a/beos/font.cpp b/beos/font.cpp index a7b1a0c96..7d04c6857 100644 --- a/beos/font.cpp +++ b/beos/font.cpp @@ -157,17 +157,24 @@ bool nsfont_position_in_string(const plot_font_style_t *fstyle, /** * Find where to split a string to make it fit a width. * - * \param fstyle style for this text - * \param string UTF-8 string to measure - * \param length length of string - * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] - * \param actual_x updated to x coordinate of character closest to x + * \param fstyle style for this text + * \param string UTF-8 string to measure + * \param length length of string, in bytes + * \param x width available + * \param char_offset updated to offset in string of actual_x, [1..length] + * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ bool nsfont_split(const plot_font_style_t *fstyle, @@ -189,13 +196,13 @@ bool nsfont_split(const plot_font_style_t *fstyle, int i; int last_space = 0; font.GetEscapements(string, len, escapements); - // slow but it should work + // very slow but it should work for (i = 0; string[index] && i < len; i++) { if (string[index] == ' ') { last_x = current; last_space = index; } - if (x < current) { + if (x < current && last_space != 0) { *actual_x = (int)last_x; *char_offset = last_space; return true; diff --git a/framebuffer/font_freetype.c b/framebuffer/font_freetype.c index c2279a116..987b101c7 100644 --- a/framebuffer/font_freetype.c +++ b/framebuffer/font_freetype.c @@ -497,15 +497,22 @@ static bool nsfont_position_in_string(const plot_font_style_t *fstyle, * * \param fstyle style for this text * \param string UTF-8 string to measure - * \param length length of string + * \param length length of string, in bytes * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] + * \param char_offset updated to offset in string of actual_x, [1..length] * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ static bool nsfont_split(const plot_font_style_t *fstyle, @@ -532,10 +539,9 @@ static bool nsfont_split(const plot_font_style_t *fstyle, } *actual_x += glyph->advance.x >> 16; - if (*actual_x > x) { - /* string has exceeded available width return previous - * space - */ + if (*actual_x > x && last_space_idx != 0) { + /* string has exceeded available width and we've + * found a space; return previous space */ *actual_x = last_space_x; *char_offset = last_space_idx; return true; diff --git a/framebuffer/font_internal.c b/framebuffer/font_internal.c index 6535ac4d5..ff2bfa1ef 100644 --- a/framebuffer/font_internal.c +++ b/framebuffer/font_internal.c @@ -121,20 +121,28 @@ static bool nsfont_position_in_string(const plot_font_style_t *fstyle, } + /** * Find where to split a string to make it fit a width. * * \param fstyle style for this text * \param string UTF-8 string to measure - * \param length length of string + * \param length length of string, in bytes * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] + * \param char_offset updated to offset in string of actual_x, [1..length] * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ static bool nsfont_split(const plot_font_style_t *fstyle, @@ -143,7 +151,7 @@ static bool nsfont_split(const plot_font_style_t *fstyle, { const struct fb_font_desc* fb_font = fb_get_font(fstyle); - *char_offset = x / fb_font->width; + int c_off = *char_offset = x / fb_font->width; if (*char_offset > length) { *char_offset = length; } else { @@ -152,6 +160,13 @@ static bool nsfont_split(const plot_font_style_t *fstyle, break; (*char_offset)--; } + if (*char_offset == 0) { + *char_offset = c_off; + while (*char_offset < length && + string[*char_offset] != ' ') { + (*char_offset)++; + } + } } *actual_x = *char_offset * fb_font->width; return true; diff --git a/gtk/font_pango.c b/gtk/font_pango.c index 2c77f3015..de115fa64 100644 --- a/gtk/font_pango.c +++ b/gtk/font_pango.c @@ -153,17 +153,24 @@ bool nsfont_position_in_string(const plot_font_style_t *fstyle, /** * Find where to split a string to make it fit a width. * - * \param fstyle plot style for this text - * \param string UTF-8 string to measure - * \param length length of string - * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] - * \param actual_x updated to x coordinate of character closest to x + * \param fstyle style for this text + * \param string UTF-8 string to measure + * \param length length of string, in bytes + * \param x width available + * \param char_offset updated to offset in string of actual_x, [1..length] + * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ bool nsfont_split(const plot_font_style_t *fstyle, @@ -196,22 +203,7 @@ bool nsfont_split(const plot_font_style_t *fstyle, if (line != NULL) { /* Pango split the text. The line's start_index indicates the * start of the character after the line break. */ - int orig = index = line->start_index; - - /* We must ensure that the split character is a space so that - * we meet the API postcondition. Therefore, scan backwards - * through the string and stop when we hit the start of - * the string or find a space. */ - while (index > 0) { - if (string[--index] == ' ') - break; - } - - if (index == 0) { - index = orig; - while (index != (int)length && string[index] != ' ') - index++; - } + index = line->start_index; } g_object_unref(layout); diff --git a/monkey/font.c b/monkey/font.c index 759c3e935..7f390a49b 100644 --- a/monkey/font.c +++ b/monkey/font.c @@ -59,23 +59,29 @@ static bool nsfont_position_in_string(const plot_font_style_t *fstyle, * * \param fstyle style for this text * \param string UTF-8 string to measure - * \param length length of string + * \param length length of string, in bytes * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] + * \param char_offset updated to offset in string of actual_x, [1..length] * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ static bool nsfont_split(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x) { - - *char_offset = x / (fstyle->size / FONT_SIZE_SCALE); + int c_off = *char_offset = x / (fstyle->size / FONT_SIZE_SCALE); if (*char_offset > length) { *char_offset = length; } else { @@ -84,6 +90,12 @@ static bool nsfont_split(const plot_font_style_t *fstyle, break; (*char_offset)--; } + if (*char_offset == 0) { + *char_offset = c_off; + while (*char_offset < length && string[*char_offset] != ' ') { + (*char_offset)++; + } + } } *actual_x = *char_offset * (fstyle->size / FONT_SIZE_SCALE); return true; diff --git a/render/font.h b/render/font.h index bc7dc7fba..bc8df2335 100644 --- a/render/font.h +++ b/render/font.h @@ -73,13 +73,20 @@ struct font_functions * \param string UTF-8 string to measure * \param length length of string, in bytes * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] + * \param char_offset updated to offset in string of actual_x, [1..length] * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ bool (*font_split)(const plot_font_style_t *fstyle, const char *string, size_t length, diff --git a/render/layout.c b/render/layout.c index 86d27c54e..80d470c7a 100644 --- a/render/layout.c +++ b/render/layout.c @@ -2164,20 +2164,21 @@ static bool layout_text_box_split(html_content *content, int space_width = split_box->space; struct box *c2; const struct font_functions *font_func = content->font_func; + bool space = (split_box->text[new_length] == ' '); + int used_length = new_length + (space ? 1 : 0); - if (space_width == 0) { - /* Currently split_box has no space. */ - /* Get the space width because the split_box will need it */ - /* Don't set it in split_box yet, or it will get cloned. */ + if ((space && space_width == 0) || space_width == UNKNOWN_WIDTH) { + /* We're need to add a space, and we don't know how big + * it's to be, OR we have a space of unknown width anyway; + * Calculate space width */ font_func->font_width(fstyle, " ", 1, &space_width); - } else if (space_width == UNKNOWN_WIDTH) { - /* Split_box has a space but its width is unknown. */ - /* Get the space width because the split_box will need it */ - /* Set it in split_box, so it gets cloned. */ - font_func->font_width(fstyle, " ", 1, &space_width); - split_box->space = space_width; } + if (split_box->space == UNKNOWN_WIDTH) + split_box->space = space_width; + if (!space) + space_width = 0; + /* Create clone of split_box, c2 */ c2 = talloc_memdup(content->bctx, split_box, sizeof *c2); if (!c2) @@ -2190,18 +2191,18 @@ static bool layout_text_box_split(html_content *content, /* TODO: Move text inputs to core textarea widget and remove * this */ c2->text = talloc_strndup(content->bctx, - split_box->text + new_length + 1, - split_box->length - (new_length + 1)); + split_box->text + used_length, + split_box->length - used_length); if (!c2->text) return false; } else { - c2->text += new_length + 1; + c2->text += used_length; } /* Set c2 according to the remaining text */ c2->width -= new_width + space_width; c2->flags &= ~MEASURED; /* width has been estimated */ - c2->length = split_box->length - (new_length + 1); + c2->length = split_box->length - used_length; /* Update split_box for its reduced text */ split_box->width = new_width; @@ -2217,7 +2218,14 @@ static bool layout_text_box_split(html_content *content, c2->next->prev = c2; else c2->parent->last = c2; - +#ifdef LAYOUT_DEBUG + LOG(("split_box %p len: %u \"%.*s\"", + split_box, split_box->length, + split_box->length, split_box->text)); + LOG((" new_box %p len: %u \"%.*s\"", + c2, c2->length, + c2->length, c2->text)); +#endif return true; } @@ -2713,8 +2721,7 @@ bool layout_line(struct box *first, int *width, int *y, if (x1 - x0 < x && split_box) { /* the last box went over the end */ - unsigned int i; - size_t space = 0; + size_t split = 0; int w; bool no_wrap = css_computed_white_space( split_box->style) == CSS_WHITE_SPACE_NOWRAP || @@ -2723,56 +2730,45 @@ bool layout_line(struct box *first, int *width, int *y, x = x_previous; - if ((split_box->type == BOX_INLINE || + if (!no_wrap && (split_box->type == BOX_INLINE || split_box->type == BOX_TEXT) && !split_box->object && !(split_box->flags & REPLACE_DIM) && !(split_box->flags & IFRAME) && !split_box->gadget && split_box->text) { - /* skip leading spaces, otherwise code gets fooled into - * thinking it's all one long word */ - for (i = 0; i != split_box->length && - split_box->text[i] == ' '; i++) - ; - /* find end of word */ - for (; i != split_box->length && - split_box->text[i] != ' '; i++) - ; - if (i != split_box->length) - space = i; - } - /* space != 0 implies split_box->text != 0 */ - - if (space == 0 || no_wrap) - w = split_box->width; - else { font_plot_style_from_css(split_box->style, &fstyle); /** \todo handle errors */ - font_func->font_width(&fstyle, split_box->text, - space, &w); + font_func->font_split(&fstyle, + split_box->text, split_box->length, + x1 - x0 - x - space_before, &split, &w); } + /* split == 0 implies that text can't be split */ + + if (split == 0) + w = split_box->width; + #ifdef LAYOUT_DEBUG - LOG(("splitting: split_box %p \"%.*s\", space %zu, w %i, " + LOG(("splitting: split_box %p \"%.*s\", spilt %zu, w %i, " "left %p, right %p, inline_count %u", split_box, (int) split_box->length, - split_box->text, space, w, + split_box->text, split, w, left, right, inline_count)); #endif - if ((space == 0 || x1 - x0 <= x + space_before + w) && + if ((split == 0 || x1 - x0 <= x + space_before + w) && !left && !right && inline_count == 1) { /* first word of box doesn't fit, but no floats and * first box on line so force in */ - if (space == 0 || no_wrap) { + if (split == 0 || split == split_box->length) { /* only one word in this box, or not text * or white-space:nowrap */ b = split_box->next; } else { /* cut off first word for this line */ if (!layout_text_box_split(content, &fstyle, - split_box, space, w)) + split_box, split, w)) return false; b = split_box->next; } @@ -2780,7 +2776,7 @@ bool layout_line(struct box *first, int *width, int *y, #ifdef LAYOUT_DEBUG LOG(("forcing")); #endif - } else if ((space == 0 || x1 - x0 <= x + space_before + w) && + } else if ((split == 0 || x1 - x0 <= x + space_before + w) && inline_count == 1) { /* first word of first box doesn't fit, but a float is * taking some of the width so move below it */ @@ -2807,7 +2803,7 @@ bool layout_line(struct box *first, int *width, int *y, #ifdef LAYOUT_DEBUG LOG(("moving below float")); #endif - } else if (space == 0 || x1 - x0 <= x + space_before + w) { + } else if (split == 0 || x1 - x0 <= x + space_before + w) { /* first word of box doesn't fit so leave box for next * line */ b = split_box; @@ -2816,21 +2812,14 @@ bool layout_line(struct box *first, int *width, int *y, #endif } else { /* fit as many words as possible */ - assert(space != 0); - font_plot_style_from_css(split_box->style, &fstyle); - /** \todo handle errors */ - font_func->font_split(&fstyle, - split_box->text, split_box->length, - x1 - x0 - x - space_before, &space, &w); + assert(split != 0); #ifdef LAYOUT_DEBUG LOG(("'%.*s' %i %zu %i", (int) split_box->length, - split_box->text, x1 - x0, space, w)); + split_box->text, x1 - x0, split, w)); #endif - if (space == 0) - space = 1; - if (space != split_box->length) { + if (split != split_box->length) { if (!layout_text_box_split(content, &fstyle, - split_box, space, w)) + split_box, split, w)) return false; b = split_box->next; } diff --git a/resources/FatMessages b/resources/FatMessages index 047432a3a..28cb9d439 100644 --- a/resources/FatMessages +++ b/resources/FatMessages @@ -866,7 +866,7 @@ nl.all.ScaleNorm:Normal en.all.HotlistShowNS:Show hotlist... de.all.HotlistShowNS:Zeige Hotlist... fr.all.HotlistShowNS:Show hotlist... -it.all.HotlistShowNS:Mostra segnalibri... +it.all.HotlistShowNS:Mostra... nl.all.HotlistShowNS:Show hotlist... # Settings menu diff --git a/riscos/font.c b/riscos/font.c index 8d4c6d337..b949a570d 100644 --- a/riscos/font.c +++ b/riscos/font.c @@ -319,15 +319,22 @@ bool nsfont_position_in_string(const plot_font_style_t *fstyle, * * \param fstyle style for this text * \param string UTF-8 string to measure - * \param length length of string + * \param length length of string, in bytes * \param x width available - * \param char_offset updated to offset in string of actual_x, [0..length] + * \param char_offset updated to offset in string of actual_x, [1..length] * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported * - * On exit, [char_offset == 0 || - * string[char_offset] == ' ' || - * char_offset == length] + * On exit, char_offset indicates first character after split point. + * + * Note: char_offset of 0 should never be returned. + * + * Returns: + * char_offset giving split point closest to x, where actual_x <= x + * else + * char_offset giving split point closest to x, where actual_x > x + * + * Returning char_offset == length means no split possible */ bool nsfont_split(const plot_font_style_t *fstyle, diff --git a/windows/font.c b/windows/font.c index 9a5d9ebc6..564a7dec0 100644 --- a/windows/font.c +++ b/windows/font.c @@ -208,14 +208,22 @@ static bool nsfont_split(const plot_font_style_t *style, const char *string, size_t length, int x, size_t *char_offset, int *actual_x) { + int c_off; nsfont_position_in_string(style, string, length, x, char_offset, actual_x); + c_off = *char_offset; if (*char_offset == length) { printf("%s %d\n",string, (int)(*char_offset)); return true; } while ((string[*char_offset] != ' ') && (*char_offset > 0)) (*char_offset)--; + if (*char_offset == 0) { + *char_offset = c_off; + while (*char_offset < length && string[*char_offset] != ' ') { + (*char_offset)++; + } + } nsfont_position_in_string(style, string, *char_offset, x, char_offset, actual_x); return true;