UTF-8 support for para_gui.
[paraslash.git] / gui.c
diff --git a/gui.c b/gui.c
index a8a7fc9fb22c44aee4ec310467abba0fcade2e78..ac9ee19ffe91df4f865dbe80f1b7ac38aa192a91 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -10,6 +10,7 @@
 #include <signal.h>
 #include <sys/types.h>
 #include <curses.h>
+#include <locale.h>
 
 #include "gui.cmdline.h"
 #include "para.h"
@@ -305,11 +306,18 @@ static void add_spaces(WINDOW* win, unsigned int num)
 static int align_str(WINDOW* win, char *str, unsigned int len,
                unsigned int align)
 {
-       int i, num; /* of spaces */
+       int ret, i, num; /* of spaces */
+       size_t width;
 
        if (!win || !str)
-               return -1;
-       num = len - strlen(str);
+               return 0;
+       ret = strwidth(str, &width);
+       if (ret < 0) {
+               PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+               width = 0;
+               str[0] = '\0';
+       }
+       num = len - width;
        if (num < 0) {
                str[len] = '\0';
                num = 0;
@@ -391,11 +399,14 @@ static int first_visible_rbe(unsigned *lines)
        return RINGBUFFER_SIZE - 1;
 }
 
+/*
+returns number of first visible rbe, *lines is the number of lines drawn.
+ */
 static int draw_top_rbe(unsigned *lines)
 {
-       unsigned len;
-       int offset, fvr = first_visible_rbe(lines);
+       int ret, fvr = first_visible_rbe(lines);
        struct rb_entry *rbe;
+       size_t bytes_to_skip, cells_to_skip, width;
 
        if (fvr < 0)
                return -1;
@@ -403,16 +414,22 @@ static int draw_top_rbe(unsigned *lines)
        rbe = ringbuffer_get(bot_win_rb, fvr);
        if (!rbe)
                return -1;
-       len = strlen(rbe->msg);
        if (*lines > bot.lines) {
-               /* first rbe is only partially visible */
-               offset = (*lines - bot.lines) * bot.cols;
-               assert(offset <= len);
-       } else
-               offset = 0;
+               /* rbe is partially visible multi-line */
+               cells_to_skip = (*lines - bot.lines) * bot.cols;
+               ret = skip_cells(rbe->msg, cells_to_skip, &bytes_to_skip);
+               if (ret < 0)
+                       return ret;
+               ret = strwidth(rbe->msg + bytes_to_skip, &width);
+               if (ret < 0)
+                       return ret;
+       } else {
+               bytes_to_skip = 0;
+               width = rbe->len;
+       }
        wattron(bot.win, COLOR_PAIR(rbe->color));
-       waddstr(bot.win, rbe->msg + offset);
-       *lines = NUM_LINES(len - offset);
+       waddstr(bot.win, rbe->msg + bytes_to_skip);
+       *lines = NUM_LINES(width);
        return fvr;
 }
 
@@ -444,10 +461,15 @@ out:
 
 static void rb_add_entry(int color, char *msg)
 {
-       struct rb_entry *old, *new = para_malloc(sizeof(struct rb_entry));
+       struct rb_entry *old, *new;
        int x, y;
+       size_t len;
+
+       if (strwidth(msg, &len) < 0)
+               return;
+       new = para_malloc(sizeof(struct rb_entry));
        new->color = color;
-       new->len = strlen(msg);
+       new->len = len;
        new->msg = msg;
        old = ringbuffer_add(bot_win_rb, new);
 //     fprintf(stderr, "added: %s\n", new->msg);
@@ -1162,7 +1184,7 @@ static void com_scroll_top(void)
                struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i);
                if (!rbe)
                        break;
-               lines += NUM_LINES(strlen(rbe->msg));
+               lines += NUM_LINES(rbe->len);
        }
        i++;
        if (lines > 0 && scroll_position != i) {
@@ -1193,7 +1215,7 @@ static void com_page_down(void)
                struct rb_entry *rbe = ringbuffer_get(bot_win_rb, i);
                if (!rbe)
                        break;
-               lines += NUM_LINES(strlen(rbe->msg));
+               lines += NUM_LINES(rbe->len);
        }
        if (lines) {
                scroll_position = i;
@@ -1514,6 +1536,7 @@ int main(int argc, char *argv[])
        top.lines = theme.top_lines_default;
        setup_signal_handling();
        bot_win_rb = ringbuffer_new(RINGBUFFER_SIZE);
+       setlocale(LC_CTYPE, "");
        initscr(); /* needed only once, always successful */
        init_curses();
        print_welcome();