diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c
index e4c8199d9..61ec3b92b 100644
--- a/src/document/html/renderer.c
+++ b/src/document/html/renderer.c
@@ -154,14 +154,16 @@ realloc_line(struct html_context *html_context, struct document *document,
{
struct screen_char *pos, *end;
struct line *line;
+ int orig_length;
if (!realloc_lines(document, y))
return -1;
line = &document->data[y];
-
- if (length < line->length)
- return 0;
+ orig_length = line->length;
+
+ if (length < orig_length)
+ return orig_length;
if (!ALIGN_LINE(&line->chars, line->length, length + 1))
return -1;
@@ -181,7 +183,7 @@ realloc_line(struct html_context *html_context, struct document *document,
line->length = length + 1;
- return 0;
+ return orig_length;
}
void
@@ -244,7 +246,7 @@ clear_hchars(struct html_context *html_context, int x, int y, int width)
assert(part && part->document && width > 0);
if_assert_failed return;
- if (realloc_line(html_context, part->document, Y(y), X(x) + width - 1))
+ if (realloc_line(html_context, part->document, Y(y), X(x) + width - 1) < 0)
return;
assert(part->document->data);
@@ -277,7 +279,7 @@ get_frame_char(struct html_context *html_context, struct part *part,
assert(part && part->document && x >= 0 && y >= 0);
if_assert_failed return NULL;
- if (realloc_line(html_context, part->document, Y(y), X(x)))
+ if (realloc_line(html_context, part->document, Y(y), X(x)) < 0)
return NULL;
assert(part->document->data);
@@ -325,7 +327,7 @@ draw_frame_vchars(struct part *part, int x, int y, int height,
/* The template char is the first vertical char to be drawn. So
* copy it to the rest. */
for (height -= 1, y += 1; height; height--, y++) {
- if (realloc_line(html_context, part->document, Y(y), X(x)))
+ if (realloc_line(html_context, part->document, Y(y), X(x)) < 0)
return;
copy_screen_chars(&POS(x, y), template, 1);
@@ -386,14 +388,15 @@ static inline int
set_hline(struct html_context *html_context, unsigned char *chars, int charslen,
enum link_state link_state)
{
- struct part *part = html_context->part;
- struct screen_char *schar = get_format_screen_char(html_context,
- link_state);
+ struct part *const part = html_context->part;
+ struct screen_char *const schar = get_format_screen_char(html_context,
+ link_state);
int x = part->cx;
- int y = part->cy;
- int x2 = x;
+ const int y = part->cy;
+ const int x2 = x;
int len = charslen;
- int utf8 = html_context->options->utf8;
+ const int utf8 = html_context->options->utf8;
+ int orig_length;
assert(part);
if_assert_failed return len;
@@ -416,8 +419,9 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen,
* incomplete character in part->document->buf, then
* the first byte of input can result in a double-cell
* character, so we must reserve one extra element. */
- if (realloc_line(html_context, part->document,
- Y(y), X(x) + charslen))
+ orig_length = realloc_line(html_context, part->document,
+ Y(y), X(x) + charslen);
+ if (orig_length < 0) /* error */
return 0;
if (utf8) {
unsigned char *end = chars + charslen;
@@ -436,10 +440,21 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen,
part->document->buf[i] = '\0';
data = utf8_to_unicode(&buf_ptr, buf_ptr + i);
if (data != UCS_NO_CHAR) {
+ /* FIXME: If there was invalid
+ * UTF-8 in the buffer,
+ * @utf8_to_unicode may have left
+ * some bytes unused. Those
+ * bytes should be pulled back
+ * into @chars, rather than
+ * discarded. This is not
+ * trivial to implement because
+ * each byte may have arrived in
+ * a separate call. */
part->document->buf_length = 0;
goto good_char;
} else {
/* Still not full char */
+ LINE(y).length = orig_length;
return 0;
}
}
@@ -511,6 +526,13 @@ good_char:
* before each @copy_screen_chars call above, but
* those are in an inner loop that should be fast. */
assert(X(x) <= LINE(y).length);
+ /* Some part of the code is apparently using LINE(y).length
+ * for line-wrapping decisions. It may currently be too
+ * large because it was allocated above based on @charslen
+ * which is the number of bytes, not the number of cells.
+ * Change the length to the correct size, but dont let it
+ * get smaller than it was on entry to this function. */
+ LINE(y).length = int_max(orig_length, X(x));
len = x - x2;
} else {
if (utf8) {
@@ -564,7 +586,7 @@ set_hline(struct html_context *html_context, unsigned char *chars, int charslen,
if (part->document) {
if (realloc_line(html_context, part->document,
- Y(y), X(x) + charslen - 1))
+ Y(y), X(x) + charslen - 1) < 0)
return;
for (; charslen > 0; charslen--, x++, chars++) {
@@ -713,7 +735,7 @@ copy_chars(struct html_context *html_context, int x, int y, int width, struct sc
assert(width > 0 && part && part->document && part->document->data);
if_assert_failed return;
- if (realloc_line(html_context, part->document, Y(y), X(x) + width - 1))
+ if (realloc_line(html_context, part->document, Y(y), X(x) + width - 1) < 0)
return;
copy_screen_chars(&POS(x, y), d, width);