diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gdisp/mcufont/mf_wordwrap.c | 80 |
1 files changed, 42 insertions, 38 deletions
diff --git a/src/gdisp/mcufont/mf_wordwrap.c b/src/gdisp/mcufont/mf_wordwrap.c index d89b567d..6402ae8d 100644 --- a/src/gdisp/mcufont/mf_wordwrap.c +++ b/src/gdisp/mcufont/mf_wordwrap.c @@ -31,7 +31,7 @@ static bool get_wordlen(const struct mf_font_s *font, mf_str *text, struct wordlen_s *result) { mf_char c; - mf_str prev; + mf_str prev = *text; result->word = 0; result->space = 0; @@ -42,31 +42,35 @@ static bool get_wordlen(const struct mf_font_s *font, mf_str *text, { result->chars++; result->word += mf_character_width(font, c); + + prev = *text; c = mf_getchar(text); } - - prev = *text; + while (c && is_wrap_space(c)) { result->chars++; - + if (c == ' ') result->space += mf_character_width(font, c); else if (c == '-') result->space += mf_character_width(font, '-'); else if (c == '\t') result->space += mf_character_width(font, 'm') * MF_TABSIZE; - else if (c == '\n') + else if (c == '\n') { + /* Special case for newlines, skip the character then break. */ + prev = *text; break; - + } + prev = *text; c = mf_getchar(text); } - + /* The last loop reads the first character of next word, put it back. */ if (c) *text = prev; - + return (c == '\0' || c == '\n'); } @@ -89,9 +93,9 @@ static bool append_word(const struct mf_font_s *font, int16_t width, mf_str tmp = *text; struct wordlen_s wordlen; bool linebreak; - + linebreak = get_wordlen(font, &tmp, &wordlen); - + if (current->width + wordlen.word <= width) { *text = tmp; @@ -115,10 +119,10 @@ static bool append_char(const struct mf_font_s *font, int16_t width, mf_str tmp = *text; mf_char c; uint16_t w; - + c = mf_getchar(&tmp); w = mf_character_width(font, c); - + if (current->width + w <= width) { *text = tmp; @@ -142,31 +146,31 @@ static void tune_lines(struct linelen_s *current, struct linelen_s *previous, int16_t curw1, prevw1; int16_t curw2, prevw2; int32_t delta1, delta2; - + /* If the lines are rendered as is */ curw1 = current->width - current->last_word.space; prevw1 = previous->width - previous->last_word.space; delta1 = sq16(max_width - prevw1) + sq16(max_width - curw1); - + /* If the last word is moved */ curw2 = current->width + previous->last_word.word; prevw2 = previous->width - previous->last_word.word - previous->last_word.space - previous->last_word_2.space; delta2 = sq16(max_width - prevw2) + sq16(max_width - curw2); - + if (delta1 > delta2 && curw2 <= max_width) { /* Do the change. */ uint16_t chars; - + chars = previous->last_word.chars; previous->chars -= chars; current->chars += chars; previous->width -= previous->last_word.word + previous->last_word.space; current->width += previous->last_word.word + previous->last_word.space; previous->last_word = previous->last_word_2; - + while (chars--) mf_rewind(¤t->start); } } @@ -177,13 +181,13 @@ void mf_wordwrap(const struct mf_font_s *font, int16_t width, struct linelen_s current = { 0 }; struct linelen_s previous = { 0 }; bool full; - + current.start = text; - + while (*text) { full = !append_word(font, width, ¤t, &text); - + if (full || current.linebreak) { if (!current.chars) @@ -192,17 +196,17 @@ void mf_wordwrap(const struct mf_font_s *font, int16_t width, * point. */ while (append_char(font, width, ¤t, &text)); } - + if (previous.chars) { /* Tune the length and dispatch the previous line. */ if (!previous.linebreak && !current.linebreak) tune_lines(¤t, &previous, width); - + if (!callback(previous.start, previous.chars, state)) return; } - + previous = current; current.start = text; current.chars = 0; @@ -213,14 +217,14 @@ void mf_wordwrap(const struct mf_font_s *font, int16_t width, current.last_word.chars = 0; } } - + /* Dispatch the last lines. */ if (previous.chars) { if (!callback(previous.start, previous.chars, state)) return; } - + if (current.chars) callback(current.start, current.chars, state); } @@ -231,64 +235,64 @@ void mf_wordwrap(const struct mf_font_s *font, int16_t width, mf_str text, mf_line_callback_t callback, void *state) { mf_str linestart; - + /* Current line width and character count */ int16_t lw_cur = 0, cc_cur = 0; - + /* Previous wrap point */ int16_t cc_prev; mf_str ls_prev; - + linestart = text; - + while (*text) { cc_prev = 0; ls_prev = text; - + while (*text) { mf_char c; int16_t new_width; mf_str tmp; - + tmp = text; c = mf_getchar(&text); new_width = lw_cur + mf_character_width(font, c); - + if (c == '\n') { cc_prev = cc_cur + 1; ls_prev = text; break; } - + if (new_width > width) { text = tmp; break; } - + cc_cur++; lw_cur = new_width; - + if (is_wrap_space(c)) { cc_prev = cc_cur; ls_prev = text; } } - + /* Handle unbreakable words */ if (cc_prev == 0) { cc_prev = cc_cur; ls_prev = text; } - + if (!callback(linestart, cc_prev, state)) return; - + linestart = ls_prev; text = linestart; lw_cur = 0; |