From 77793c9d9b58d00896e844d6deea8954f59dc9ce Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Sat, 25 May 2013 11:28:12 -0400 Subject: [PATCH] Initial multibyte string output. Message dialogs (for calculating the width of the dialog) and tag editing (multubyte characters) needs to be fixed. --- src/cboard.c | 72 +++++++++++++++++++++++++---------------------------------- src/message.c | 25 ++++++++------------- src/misc.c | 53 +++++++++++++++++++++++++++++-------------- src/misc.h | 5 ++++- src/window.c | 23 +++++++++---------- src/window.h | 4 ++-- 6 files changed, 92 insertions(+), 90 deletions(-) diff --git a/src/cboard.c b/src/cboard.c index c614d3d..2093bfa 100644 --- a/src/cboard.c +++ b/src/cboard.c @@ -129,7 +129,7 @@ static int macro_match; // Status window. static struct { - char *notify; // The status window notification line buffer. + wchar_t *notify; // The status window notification line buffer. } status; static int curses_initialized; @@ -581,39 +581,22 @@ static int castling_state(GAME g, BOARD b, int row, int col, int piece, int mod) #define IS_ENPASSANT(c) (c == 'x') ? CP_BOARD_ENPASSANT : isupper(c) ? CP_BOARD_WHITE : CP_BOARD_BLACK #define ATTRS(cp) (cp & (A_BOLD|A_STANDOUT|A_BLINK|A_DIM|A_UNDERLINE|A_INVIS|A_REVERSE)) -static wchar_t * -init_wchar_piece (const char *p) -{ - wchar_t *wc; - const char *c; - mbstate_t ps; - - memset (&ps, 0, sizeof(mbstate_t)); - c = p; - size_t len = mbsrtowcs (NULL, &c, strlen (p), &ps); - wc = Calloc (1, len+1 * sizeof(wchar_t)); - c = p; - memset (&ps, 0, sizeof(mbstate_t)); - len = mbsrtowcs (wc, &c, strlen (p), &ps); - return wc; -} - static void init_wchar_pieces () { - w_pawn_wchar = init_wchar_piece ("♙"); - w_rook_wchar = init_wchar_piece ("♖"); - w_bishop_wchar = init_wchar_piece ("♗"); - w_knight_wchar = init_wchar_piece ("♘"); - w_queen_wchar = init_wchar_piece ("♕"); - w_king_wchar = init_wchar_piece ("♔"); - b_pawn_wchar = init_wchar_piece ("♟"); - b_rook_wchar = init_wchar_piece ("♜"); - b_bishop_wchar = init_wchar_piece ("♝"); - b_knight_wchar = init_wchar_piece ("♞"); - b_queen_wchar = init_wchar_piece ("♛"); - b_king_wchar = init_wchar_piece ("♚"); - empty_wchar = init_wchar_piece (" "); + w_pawn_wchar = str_to_wchar ("♙"); + w_rook_wchar = str_to_wchar ("♖"); + w_bishop_wchar = str_to_wchar ("♗"); + w_knight_wchar = str_to_wchar ("♘"); + w_queen_wchar = str_to_wchar ("♕"); + w_king_wchar = str_to_wchar ("♔"); + b_pawn_wchar = str_to_wchar ("♟"); + b_rook_wchar = str_to_wchar ("♜"); + b_bishop_wchar = str_to_wchar ("♝"); + b_knight_wchar = str_to_wchar ("♞"); + b_queen_wchar = str_to_wchar ("♛"); + b_king_wchar = str_to_wchar ("♚"); + empty_wchar = str_to_wchar (" "); } static wchar_t * @@ -1145,8 +1128,9 @@ void update_status_window(GAME g) buf = Malloc(len); y = 2; - mvwprintw(statusw, y++, 1, "%*s %-*s", 7, _("File:"), w, - (loadfile[0]) ? str_etc(loadfile, w, 1) : _("not available")); + wchar_t *loadfilew = loadfile[0] ? str_etc (loadfile, w, 1) : str_to_wchar (_ ("not available")); + mvwprintw(statusw, y++, 1, "%*s %-*ls", 7, _("File:"), w, loadfilew); + free (loadfilew); snprintf(buf, len, "%i %s %i", gindex + 1, _("of"), gtotal); mvwprintw(statusw, y++, 1, "%*s %-*s", 7, _("Game:"), w, buf); @@ -1277,18 +1261,18 @@ void update_status_window(GAME g) time_control_status(&d->bclock)); mvwprintw(statusw, y++, 1, "%*s: %-*s", 6, tmp, w, t); - mvwprintw(statusw, y++, 1, "%*s %-*s", 7, _("Total:"), w, + mvwprintw(statusw, y++, 1, "%*s %-*s", 7, _("Total:"), w, clock_to_char(d->elapsed.tv_sec)); for (i = 0; i < STATUS_WIDTH; i++) mvwprintw(stdscr, STATUS_HEIGHT, i, " "); if (!status.notify) - status.notify = strdup(_("Type F1 for help")); + status.notify = str_to_wchar(_("Type F1 for help")); wattron(stdscr, CP_STATUS_NOTIFY); - mvwprintw(stdscr, STATUS_HEIGHT, CENTERX(STATUS_WIDTH, status.notify), "%s", - status.notify); + mvwprintw(stdscr, STATUS_HEIGHT, CENTERX(STATUS_WIDTH, status.notify), + "%ls", status.notify); wattroff(stdscr, CP_STATUS_NOTIFY); } @@ -1311,9 +1295,13 @@ void update_tag_window(TAG **t) w = TAG_WIDTH - namel - 4; + /* FIXME unicode tag pairs */ for (i = 0; t[i] && i < TAG_HEIGHT - 3; i++) - mvwprintw(tagw, (i + 2), 1, "%*s: %-*s", namel, t[i]->name, w, - str_etc(t[i]->value, w, 0)); + { + wchar_t *s = str_etc(t[i]->value, w, 0); + mvwprintw(tagw, (i + 2), 1, "%*s: %-*ls", namel, t[i]->name, w, s); + free (s); + } for (; i < TAG_HEIGHT - 3; i++) mvwprintw(tagw, (i + 2), 1, "%*s", namel + w + 2, " "); @@ -1649,7 +1637,7 @@ void update_status_notify(GAME g, char *fmt, ...) if (status.notify) free(status.notify); - status.notify = strdup(line); + status.notify = str_to_wchar(line); #ifdef HAVE_VASPRINTF free(line); @@ -1700,7 +1688,7 @@ static void draw_window_decor() window_draw_title(statusw, _("Game Status"), STATUS_WIDTH, CP_STATUS_TITLE, CP_STATUS_BORDER); wbkgd(tagw, CP_TAG_WINDOW); - window_draw_title(tagw, _("Roster Tags"), TAG_WIDTH, CP_TAG_TITLE, + window_draw_title(tagw, _("Roster Tags"), TAG_WIDTH, CP_TAG_TITLE, CP_TAG_BORDER); wbkgd(historyw, CP_HISTORY_WINDOW); window_draw_title(historyw, _("Move History"), HISTORY_WIDTH, @@ -4145,7 +4133,7 @@ again: } void game_loop() -{ +{ struct userdata_s *d; macro_match = -1; diff --git a/src/message.c b/src/message.c index 834a808..9fc4be0 100644 --- a/src/message.c +++ b/src/message.c @@ -146,11 +146,11 @@ static int display_message(WIN *win) void *p = NULL; keypad(win->w, TRUE); - window_draw_title(win->w, win->title, m->w, CP_MESSAGE_TITLE, + window_draw_title(win->w, win->title, m->w, CP_MESSAGE_TITLE, CP_MESSAGE_BORDER); for (i = 0; m->lines[i]; i++) - mvwprintw(win->w, (win->title) ? 2 + i: 1 + i, + mvwprintw(win->w, (win->title) ? 2 + i: 1 + i, (m->center || (!i && !m->lines[i+1])) ? CENTERX(m->w, m->lines[i]) : 1, "%s", m->lines[i]); @@ -171,16 +171,9 @@ static int display_message(WIN *win) free(m->lines[i]); free(m->lines); - - if (m->prompt) - free(m->prompt); - - if (m->extra) - free(m->extra); - - if (m->arg) - p = m->arg; - + free(m->prompt); + free(m->extra); + p = m->arg; free(m); win->data = p; return 0; @@ -202,7 +195,7 @@ WIN *construct_message(const char *title, const char *prompt, int center, struct message_s *m = NULL; WIN *win = NULL; int h, w; - + va_start(ap, fmt); build_message_lines(title, prompt, force_trim, extra_help, &h, &w, &lines, fmt, ap); va_end(ap); @@ -222,9 +215,9 @@ WIN *construct_message(const char *title, const char *prompt, int center, if (extra_help) m->extra = strdup(extra_help); - win = window_create(title, h, w, CALCPOSY(h), CALCPOSX(w), display_message, m, - efunc); - + win = window_create(title, h, w, CALCPOSY(h), CALCPOSX(w), display_message, + m, efunc); + win->freedata = freedata; wbkgd(win->w, CP_MESSAGE_WINDOW); (*win->func)(win); diff --git a/src/misc.c b/src/misc.c index b1fadf0..25b6a88 100644 --- a/src/misc.c +++ b/src/misc.c @@ -39,6 +39,8 @@ #include #endif +#include "misc.h" + void *Malloc(size_t size) { void *ptr; @@ -160,37 +162,38 @@ char *pathfix(const char *str) return buf; } -char *str_etc(const char *str, int maxlen, int rev) +wchar_t *str_etc(const char *str, int maxlen, int rev) { int len; - static char buf[LINE_MAX], *p = buf; - int i; + wchar_t *p; + wchar_t *buf; if (!str) return NULL; - len = strlen(str); - strncpy(buf, str, sizeof(buf)); + p = str_to_wchar (str); + len = wcslen(p); if (len > maxlen) { - if (rev) { - p = buf; - *p++ = '.'; - *p++ = '.'; - *p++ = '.'; + wchar_t *dot = str_to_wchar ("..."); - for (i = 0; i < maxlen + 3; i++) - *p++ = buf[(len - maxlen) + i + 3]; + buf = Malloc (maxlen+4*sizeof(wchar_t)); + buf[0] = 0; + + if (rev) { + wcsncat (buf, dot, maxlen); + wcsncat (buf, p, maxlen); } else { - p = buf + maxlen - 4; - *p++ = '.'; - *p++ = '.'; - *p++ = '.'; + wcsncat (buf, p, maxlen); + wcsncat (buf, dot, maxlen); } - *p = '\0'; + free (dot); + free (p); } + else + buf = p; return buf; } @@ -230,3 +233,19 @@ char **split_str(char *str, char *delim, int *n, int *width, int force_trim) return lines; } + +wchar_t * +str_to_wchar (const char *str) +{ + wchar_t *wc; + mbstate_t ps; + const char *p = str; + + memset (&ps, 0, sizeof(mbstate_t)); + size_t len = mbsrtowcs (NULL, &p, 0, &ps)+1; + wc = Calloc (1, len * sizeof(wchar_t)); + p = str; + memset (&ps, 0, sizeof(mbstate_t)); + len = mbsrtowcs (wc, &p, len, &ps); + return wc; +} diff --git a/src/misc.h b/src/misc.h index 17036d1..70211e4 100644 --- a/src/misc.h +++ b/src/misc.h @@ -19,6 +19,8 @@ #ifndef MISC_H #define MISC_H +#include + void *Malloc(size_t size); void *Realloc(void *ptr, size_t size); void *Calloc(size_t n, size_t size); @@ -30,7 +32,8 @@ int isinteger(const char *str); FILE *open_file(const char *filename); char *pathfix(const char *); char *trim_multi(char *); -char *str_etc(const char *str, int maxlen, int rev); +wchar_t *str_etc(const char *str, int maxlen, int rev); char **split_str(char *str, char *delim, int *n, int *w, int force_trim); +wchar_t *str_to_wchar (const char *p); #endif diff --git a/src/window.c b/src/window.c index 3fd45b1..bcdde60 100644 --- a/src/window.c +++ b/src/window.c @@ -41,7 +41,7 @@ * structure. The 'func' parameter is a function pointer that is called from * game_loop(). 'efunc' is called just before the window is destroyed. */ -WIN *window_create(const char *title, int h, int w, int y, int x, +WIN *window_create(const char *title, int h, int w, int y, int x, window_func func, void *data, window_exit_func efunc) { int i = 0; @@ -77,9 +77,7 @@ void window_destroy(WIN *win) if (win && memcmp(win, wins[i], sizeof(WIN)) == 0) win = NULL; - if (wins[i]->title) - free(wins[i]->title); - + free(wins[i]->title); if (wins[i]->p) del_panel(wins[i]->p); @@ -97,9 +95,7 @@ void window_destroy(WIN *win) if (win->p) del_panel(win->p); - if (win->title) - free(win->title); - + free(win->title); delwin(win->w); free(win); continue; @@ -134,21 +130,22 @@ void window_draw_title(WINDOW *win, const char *title, int width, chtype attr, int i; if (title) { - const char *p; + wchar_t *p; wattron(win, attr); for (i = 1; i < width - 1; i++) mvwaddch(win, 1, i, ' '); - if (strlen(title) > width) { + if (mblen (title, strlen(title)) > width) { p = str_etc(title, width - 2, 1); } else - p = title; + p = str_to_wchar (title); - mvwprintw(win, 1, CENTERX(width, p), "%s", p); + mvwaddwstr(win, 1, CENTERX(width, p), p); wattroff(win, attr); + free (p); } wattron(win, battr); @@ -166,6 +163,8 @@ void window_draw_prompt(WINDOW *win, int y, int width, const char *str, for (i = 1; i < width - 1; i++) mvwaddch(win, y, i, ' '); - mvwprintw(win, y, CENTERX(width, str), "%s", str); + wchar_t *promptw = str_to_wchar (str); + mvwprintw(win, y, CENTERX(width, promptw), "%ls", promptw); + free (promptw); wattroff(win, attr); } diff --git a/src/window.h b/src/window.h index 07d4544..7fff1b0 100644 --- a/src/window.h +++ b/src/window.h @@ -24,7 +24,7 @@ #define KEY_ESCAPE CTRL('[') #define CALCPOSY(y) ((y > LINES - 1) ? 0 : LINES / 2 - y / 2) #define CALCPOSX(x) (COLS / 2 - x / 2) -#define CENTERX(x, str) abs((x / 2 - strlen(str) / 2)) +#define CENTERX(x, str) abs((x / 2 - wcslen (str) / 2)) #define CENTER_INT(x, n) abs((x / 2 - n / 2)) typedef struct window_s WIN; @@ -39,7 +39,7 @@ struct window_s { int posy; int posx; char *title; - /* + /* * Function that is called when a key is pressed from game_loop(). This is * the only place where a key is gotten from. This is for the top window * (LIFO). When the function returns -1, the window is destroyed and the -- 2.11.4.GIT