diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ee7020..53316af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,9 @@ add_executable(${exe_name} chat.c configdir.c) +include_directories(${CURSES_INCLUDE_DIR}) + target_link_libraries(${exe_name} - curses) + ${CURSES_LIBRARIES}) linkCoreLibraries(${exe_name}) diff --git a/chat.c b/chat.c index c797984..c7a0f98 100644 --- a/chat.c +++ b/chat.c @@ -2,12 +2,12 @@ * Toxic -- Tox Curses Client */ -#include #include #include #include #include #include +#include #include "../../core/Messenger.h" #include "../../core/network.h" @@ -20,7 +20,7 @@ typedef struct { int friendnum; - char line[MAX_STR_SIZE]; + wchar_t line[MAX_STR_SIZE]; size_t pos; WINDOW *history; WINDOW *linewin; @@ -50,8 +50,6 @@ static void chat_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *msg, getname(m, num, (uint8_t *) &nick); msg[len - 1] = '\0'; nick[MAX_NAME_LENGTH - 1] = '\0'; - fix_name(msg); - fix_name(nick); wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); @@ -74,7 +72,6 @@ static void chat_onAction(ToxWindow *self, Messenger *m, int num, uint8_t *actio return; action[len - 1] = '\0'; - fix_name(action); wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); @@ -101,7 +98,6 @@ static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t wattroff(ctx->history, COLOR_PAIR(2)); nick[len - 1] = '\0'; - fix_name(nick); snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num); wattron(ctx->history, COLOR_PAIR(3)); @@ -122,7 +118,7 @@ static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint1 wattroff(ctx->history, COLOR_PAIR(2)); status[len - 1] = '\0'; - fix_name(status); + snprintf(self->title, sizeof(self->title), "[%s (%d)]", status, num); wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, "* Your partner changed status to '%s'\n", status); @@ -140,7 +136,43 @@ int string_is_empty(char *string) return rc; } -static void chat_onKey(ToxWindow *self, Messenger *m, int key) +/* convert wide characters to null terminated string */ +static char *wcs_to_char(wchar_t *string) +{ + size_t len = 0; + char *ret = NULL; + + len = wcstombs(NULL, string, 0); + if (len != (size_t) -1) { + len++; + ret = malloc(len); + wcstombs(ret, string, len); + } else { + ret = malloc(2); + ret[0] = ' '; + ret[1] = '\0'; + } + return ret; +} + +/* convert a wide char to null terminated string */ +static char *wc_to_char(wchar_t ch) +{ + int len = 0; + static char ret[MB_LEN_MAX + 1]; + + len = wctomb(ret, ch); + if (len == -1) { + ret[0] = ' '; + ret[1] = '\0'; + } else { + ret[len] = '\0'; + } + + return ret; +} + +static void chat_onKey(ToxWindow *self, Messenger *m, wint_t key) { ChatContext *ctx = (ChatContext *) self->x; struct tm *timeinfo = get_time(); @@ -150,18 +182,18 @@ static void chat_onKey(ToxWindow *self, Messenger *m, int key) getmaxyx(self->window, y2, x2); /* Add printable chars to buffer and print on input space */ - if (isprint(key)) { + if (iswprint(key)) { if (ctx->pos != sizeof(ctx->line) - 1) { - mvwaddch(self->window, y, x, key); + mvwaddstr(self->window, y, x, wc_to_char(key)); ctx->line[ctx->pos++] = key; - ctx->line[ctx->pos] = '\0'; + ctx->line[ctx->pos] = L'\0'; } } /* BACKSPACE key: Remove one character from line */ else if (key == 0x107 || key == 0x8 || key == 0x7f) { if (ctx->pos > 0) { - ctx->line[--ctx->pos] = '\0'; + ctx->line[--ctx->pos] = L'\0'; if (x == 0) mvwdelch(self->window, y - 1, x2 - 1); @@ -172,18 +204,18 @@ static void chat_onKey(ToxWindow *self, Messenger *m, int key) /* RETURN key: Execute command or print line */ else if (key == '\n') { + char *line = wcs_to_char(ctx->line); wclear(ctx->linewin); wmove(self->window, y2 - CURS_Y_OFFSET, 0); wclrtobot(self->window); - if (ctx->line[0] == '/') - execute(self, ctx, m, ctx->line); + if (line[0] == '/') + execute(self, ctx, m, line); else { /* make sure the string has at least non-space character */ - if (!string_is_empty(ctx->line)) { + if (!string_is_empty(line)) { uint8_t selfname[MAX_NAME_LENGTH]; getself_name(m, selfname, sizeof(selfname)); - fix_name(selfname); wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); @@ -191,9 +223,9 @@ static void chat_onKey(ToxWindow *self, Messenger *m, int key) wattron(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "%s: ", selfname); wattroff(ctx->history, COLOR_PAIR(1)); - wprintw(ctx->history, "%s\n", ctx->line); + wprintw(ctx->history, "%s\n", line); - if (m_sendmessage(m, ctx->friendnum, (uint8_t *) ctx->line, strlen(ctx->line) + 1) == 0) { + if (m_sendmessage(m, ctx->friendnum, (uint8_t *) line, strlen(line) + 1) == 0) { wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Failed to send message.\n"); wattroff(ctx->history, COLOR_PAIR(3)); @@ -201,8 +233,9 @@ static void chat_onKey(ToxWindow *self, Messenger *m, int key) } } - ctx->line[0] = '\0'; + ctx->line[0] = L'\0'; ctx->pos = 0; + free(line); } } @@ -331,7 +364,7 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) wprintw(ctx->history, "%s\n", id); } - else if (strcmp(ctx->line, "/close") == 0) { + else if (strcmp(cmd, "/close") == 0) { int f_num = ctx->friendnum; delwin(ctx->linewin); del_window(self); @@ -398,7 +431,6 @@ ToxWindow new_chat(Messenger *m, int friendnum) uint8_t nick[MAX_NAME_LENGTH] = {0}; getname(m, friendnum, (uint8_t *) &nick); - fix_name(nick); snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum); diff --git a/dhtstatus.c b/dhtstatus.c index 6c9f2a8..3330077 100644 --- a/dhtstatus.c +++ b/dhtstatus.c @@ -11,7 +11,7 @@ static void printip(ipbuf buf, IP ip) sprintf((char *)buf, "%u.%u.%u.%u", ip.c[0], ip.c[1], ip.c[2], ip.c[3]); } -static void dhtstatus_onKey(ToxWindow *self, Messenger *m, int key) +static void dhtstatus_onKey(ToxWindow *self, Messenger *m, wint_t key) { switch (key) { case KEY_UP: diff --git a/friendlist.c b/friendlist.c index 2e46f12..8fa3b47 100644 --- a/friendlist.c +++ b/friendlist.c @@ -2,7 +2,6 @@ * Toxic -- Tox Curses Client */ -#include #include #include #include @@ -25,21 +24,6 @@ static friend_t friends[MAX_FRIENDS_NUM]; static int num_friends = 0; static int num_selected = 0; -void fix_name(uint8_t *name) -{ - /* Remove all non alphanumeric characters */ - uint8_t *p = name; - uint8_t *q = name; - - while (*p != 0) { - if (isprint(*p)) - *q++ = *p; - - p++; - } - - *q = 0; -} void friendlist_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *str, uint16_t len) { @@ -58,7 +42,6 @@ void friendlist_onNickChange(ToxWindow *self, int num, uint8_t *str, uint16_t le memcpy((char *) &friends[num].name, (char *) str, len); friends[num].name[len] = 0; - fix_name(friends[num].name); } void friendlist_onStatusChange(ToxWindow *self, int num, uint8_t *str, uint16_t len) @@ -68,7 +51,6 @@ void friendlist_onStatusChange(ToxWindow *self, int num, uint8_t *str, uint16_t memcpy((char *) &friends[num].status, (char *) str, len); friends[num].status[len] = 0; - fix_name(friends[num].status); } int friendlist_onFriendAdded(Messenger *m, int num) @@ -84,7 +66,7 @@ int friendlist_onFriendAdded(Messenger *m, int num) return 0; } -static void friendlist_onKey(ToxWindow *self, Messenger *m, int key) +static void friendlist_onKey(ToxWindow *self, Messenger *m, wint_t key) { if (key == KEY_UP) { if (--num_selected < 0) diff --git a/friendlist.h b/friendlist.h index 91b917f..6f045d4 100644 --- a/friendlist.h +++ b/friendlist.h @@ -7,6 +7,5 @@ ToxWindow new_friendlist(); int friendlist_onFriendAdded(Messenger *m, int num); void disable_chatwin(int f_num); -void fix_name(uint8_t *name); #endif /* end of include guard: FRIENDLIST_H_53I41IM */ diff --git a/main.c b/main.c index e5525e9..12b529f 100644 --- a/main.c +++ b/main.c @@ -2,6 +2,7 @@ * Toxic -- Tox Curses Client */ +#define _XOPEN_SOURCE_EXTENDED #include #include #include @@ -9,6 +10,7 @@ #include #include #include +#include #ifdef _win32 #include @@ -40,6 +42,7 @@ static void init_term() { /* Setup terminal */ signal(SIGWINCH, on_window_resize); + setlocale(LC_ALL, ""); initscr(); cbreak(); keypad(stdscr, 1); diff --git a/prompt.c b/prompt.c index 6c762c8..b00dba2 100644 --- a/prompt.c +++ b/prompt.c @@ -5,7 +5,6 @@ #include #include #include -#include #include "../../core/Messenger.h" #include "../../core/network.h" @@ -434,7 +433,7 @@ static void execute(ToxWindow *self, Messenger *m, char *u_cmd) wprintw(self->window, "Invalid command.\n"); } -static void prompt_onKey(ToxWindow *self, Messenger *m, int key) +static void prompt_onKey(ToxWindow *self, Messenger *m, wint_t key) { /* Add printable characters to line */ if (isprint(key)) { diff --git a/windows.c b/windows.c index 8fdf4e1..f50bdc2 100644 --- a/windows.c +++ b/windows.c @@ -226,16 +226,18 @@ void draw_active_window(Messenger *m) { ToxWindow *a = active_window; + wint_t ch = 0; + prepare_window(a->window); a->blink = false; draw_bar(); a->onDraw(a, m); /* Handle input */ - int ch = getch(); + get_wch(&ch); if (ch == '\t' || ch == KEY_BTAB) - set_next_window(ch); + set_next_window((int) ch); else if (ch != ERR) a->onKey(a, m, ch); } diff --git a/windows.h b/windows.h index 86917db..227040b 100644 --- a/windows.h +++ b/windows.h @@ -4,9 +4,12 @@ #ifndef _windows_h #define _windows_h +#define _XOPEN_SOURCE_EXTENDED #include #include #include +#include +#include #include "../../core/Messenger.h" #define MAX_WINDOWS_NUM 32 #define MAX_FRIENDS_NUM 100 @@ -23,7 +26,7 @@ typedef struct ToxWindow_ ToxWindow; struct ToxWindow_ { - void(*onKey)(ToxWindow *, Messenger *, int); + void(*onKey)(ToxWindow *, Messenger *, wint_t); void(*onDraw)(ToxWindow *, Messenger *); void(*onInit)(ToxWindow *, Messenger *); void(*onFriendRequest)(ToxWindow *, uint8_t *, uint8_t *, uint16_t);