ui/ncurses: Display multibyte strings correctly in textscreens
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>
Tue, 10 Oct 2017 04:36:27 +0000 (15:36 +1100)
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>
Wed, 11 Oct 2017 00:53:26 +0000 (11:53 +1100)
In nc-textscreen each line of text is capped at a certain length to
avoid running off the side of the viewable screen. However it appears
the ncurses function mvwaddnstr() counts by byte instead of actual
character, causing strings which contain multibyte characters to be cut
short.

To avoid this check the displayed length of each string against the
screen width, and if under instruct mvwaddnstr() to print the whole
string.

Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
ui/ncurses/nc-textscreen.c

index a460188180ab10621d2dca5176ee6f6b139cecce..0be201644fac26a6ec57f301f719858e0d4a4624 100644 (file)
@@ -41,15 +41,17 @@ struct text_screen *text_screen_from_scr(struct nc_scr *scr)
 
 void text_screen_draw(struct text_screen *screen)
 {
-       int max_y, max_x, i;
+       int max_y, max_x, i, len;
 
        max_y = getmaxy(screen->scr.sub_ncw);
        max_x = getmaxx(screen->scr.sub_ncw) - 1;
 
        max_y = min(max_y, screen->scroll_y + screen->n_lines);
 
-       for (i = screen->scroll_y; i < max_y; i++)
-               mvwaddnstr(screen->scr.sub_ncw, i, 1, screen->lines[i], max_x);
+       for (i = screen->scroll_y; i < max_y; i++) {
+               len = strncols(screen->lines[i]) > max_x ? max_x : -1;
+               mvwaddnstr(screen->scr.sub_ncw, i, 1, screen->lines[i], len);
+       }
 
        wrefresh(screen->scr.sub_ncw);
 }
@@ -58,7 +60,7 @@ static void text_screen_scroll(struct text_screen *screen, int key)
 {
        int win_lines = getmaxy(screen->scr.sub_ncw);
        int win_cols = getmaxx(screen->scr.sub_ncw) - 1;
-       int delta;
+       int delta, len, i;
 
        if (key == KEY_UP)
                delta = -1;
@@ -75,13 +77,16 @@ static void text_screen_scroll(struct text_screen *screen, int key)
        screen->scroll_y += delta;
        wscrl(screen->scr.sub_ncw, delta);
 
+
        if (delta > 0) {
+               i = screen->scroll_y + win_lines - 1;
+               len = strncols(screen->lines[i]) > win_cols ? win_cols : -1;
                mvwaddnstr(screen->scr.sub_ncw, win_lines - 1, 1,
-                               screen->lines[screen->scroll_y+win_lines-1],
-                               win_cols);
+                               screen->lines[i], len);
        } else if (delta < 0) {
-               mvwaddnstr(screen->scr.sub_ncw, 0, 1,
-                               screen->lines[screen->scroll_y], win_cols);
+               i = screen->scroll_y;
+               len = strncols(screen->lines[i]) > win_cols ? win_cols : -1;
+               mvwaddnstr(screen->scr.sub_ncw, 0, 1, screen->lines[i], len);
        }
 
        wrefresh(screen->scr.sub_ncw);