From 399b92c8e7cbca8d6e30184b0ccc8813bf0ad228 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 15 Sep 2013 16:38:38 -0400 Subject: [PATCH 1/9] added groupchats --- src/chat.c | 47 ++++----- src/chat.h | 4 + src/friendlist.c | 7 +- src/groupchat.c | 233 ++++++++++++++++++++++++++++++++++++++++++++ src/groupchat.h | 6 ++ src/main.c | 2 + src/prompt.c | 179 +++++++++++++++++++++++++++------- src/toxic_windows.h | 29 +++++- src/windows.c | 21 +++- 9 files changed, 452 insertions(+), 76 deletions(-) create mode 100644 src/groupchat.c create mode 100644 src/groupchat.h diff --git a/src/chat.c b/src/chat.c index 18f683b..1267a17 100644 --- a/src/chat.c +++ b/src/chat.c @@ -18,18 +18,9 @@ #include "friendlist.h" #include "chat.h" -#define CURS_Y_OFFSET 3 - extern char *DATA_FILE; extern int store_data(Tox *m, char *path); -typedef struct { - wchar_t line[MAX_STR_SIZE]; - size_t pos; - WINDOW *history; - WINDOW *linewin; -} ChatContext; - struct tm *get_time(void) { struct tm *timeinfo; @@ -41,11 +32,10 @@ struct tm *get_time(void) static void chat_onMessage(ToxWindow *self, Tox *m, int num, uint8_t *msg, uint16_t len) { - if (self->friendnum != num) + if (self->num != num) return; ChatContext *ctx = (ChatContext *) self->chatwin; - struct tm *timeinfo = get_time(); uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'}; @@ -65,7 +55,7 @@ static void chat_onMessage(ToxWindow *self, Tox *m, int num, uint8_t *msg, uint1 void chat_onConnectionChange(ToxWindow *self, Tox *m, int num, uint8_t status) { - if (self->friendnum != num) + if (self->num != num) return; StatusBar *statusbar = (StatusBar *) self->stb; @@ -74,7 +64,7 @@ void chat_onConnectionChange(ToxWindow *self, Tox *m, int num, uint8_t status) static void chat_onAction(ToxWindow *self, Tox *m, int num, uint8_t *action, uint16_t len) { - if (self->friendnum != num) + if (self->num != num) return; ChatContext *ctx = (ChatContext *) self->chatwin; @@ -97,7 +87,7 @@ static void chat_onAction(ToxWindow *self, Tox *m, int num, uint8_t *action, uin static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len) { - if (self->friendnum != num) + if (self->num != num) return; snprintf(self->name, sizeof(self->name), "%s", nick); @@ -105,7 +95,7 @@ static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t static void chat_onStatusChange(ToxWindow *self, Tox *m, int num, TOX_USERSTATUS status) { - if (self->friendnum != num) + if (self->num != num) return; StatusBar *statusbar = (StatusBar *) self->stb; @@ -114,7 +104,7 @@ static void chat_onStatusChange(ToxWindow *self, Tox *m, int num, TOX_USERSTATUS static void chat_onStatusMessageChange(ToxWindow *self, int num, uint8_t *status, uint16_t len) { - if (self->friendnum != num) + if (self->num != num) return; StatusBar *statusbar = (StatusBar *) self->stb; @@ -133,7 +123,7 @@ int string_is_empty(char *string) } /* convert wide characters to null terminated string */ -static uint8_t *wcs_to_char(wchar_t *string) +uint8_t *wcs_to_char(wchar_t *string) { size_t len = 0; char *ret = NULL; @@ -162,7 +152,7 @@ static uint8_t *wcs_to_char(wchar_t *string) } /* convert a wide char to null terminated string */ -static char *wc_to_char(wchar_t ch) +char *wc_to_char(wchar_t ch) { int len = 0; static char ret[MB_LEN_MAX + 1]; @@ -239,7 +229,7 @@ static void execute(ToxWindow *self, ChatContext *ctx, StatusBar *statusbar, Tox wattroff(ctx->history, COLOR_PAIR(YELLOW)); if (!statusbar->is_online - || tox_sendaction(m, self->friendnum, action, strlen(action) + 1) == 0) { + || tox_sendaction(m, self->num, action, strlen(action) + 1) == 0) { wattron(ctx->history, COLOR_PAIR(RED)); wprintw(ctx->history, " * Failed to send action\n"); wattroff(ctx->history, COLOR_PAIR(RED)); @@ -393,7 +383,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key) if (line[0] == '/') { if (close_win = !strncmp(line, "/close", strlen("/close"))) { - int f_num = self->friendnum; + int f_num = self->num; delwin(ctx->linewin); delwin(statusbar->topline); del_window(self); @@ -415,7 +405,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key) wprintw(ctx->history, "%s\n", line); if (!statusbar->is_online - || tox_sendmessage(m, self->friendnum, line, strlen(line) + 1) == 0) { + || tox_sendmessage(m, self->num, line, strlen(line) + 1) == 0) { wattron(ctx->history, COLOR_PAIR(RED)); wprintw(ctx->history, " * Failed to send message.\n"); wattroff(ctx->history, COLOR_PAIR(RED)); @@ -438,7 +428,6 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key) static void chat_onDraw(ToxWindow *self, Tox *m) { curs_set(1); - int x, y; getmaxyx(self->window, y, x); @@ -487,9 +476,9 @@ static void chat_onDraw(ToxWindow *self, Tox *m) /* Reset statusbar->statusmsg on window resize */ if (x != self->x) { uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'}; - tox_copy_statusmessage(m, self->friendnum, statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); + tox_copy_statusmessage(m, self->num, statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); - statusbar->statusmsg_len = tox_get_statusmessage_size(m, self->friendnum); + statusbar->statusmsg_len = tox_get_statusmessage_size(m, self->num); } self->x = x; @@ -520,13 +509,13 @@ static void chat_onInit(ToxWindow *self, Tox *m) /* Init statusbar info */ StatusBar *statusbar = (StatusBar *) self->stb; - statusbar->status = tox_get_userstatus(m, self->friendnum); - statusbar->is_online = tox_get_friend_connectionstatus(m, self->friendnum) == 1; + statusbar->status = tox_get_userstatus(m, self->num); + statusbar->is_online = tox_get_friend_connectionstatus(m, self->num) == 1; uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'}; - tox_copy_statusmessage(m, self->friendnum, statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); + tox_copy_statusmessage(m, self->num, statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); - statusbar->statusmsg_len = tox_get_statusmessage_size(m, self->friendnum); + statusbar->statusmsg_len = tox_get_statusmessage_size(m, self->num); /* Init subwindows */ ChatContext *ctx = (ChatContext *) self->chatwin; @@ -571,7 +560,7 @@ ToxWindow new_chat(Tox *m, ToxWindow *prompt, int friendnum) } ret.prompt = prompt; - ret.friendnum = friendnum; + ret.num = friendnum; return ret; } diff --git a/src/chat.h b/src/chat.h index 25e64b7..10405ec 100644 --- a/src/chat.h +++ b/src/chat.h @@ -1,6 +1,10 @@ #ifndef CHAT_H_6489PZ13 #define CHAT_H_6489PZ13 +struct tm *get_time(void); +char *wc_to_char(wchar_t ch); +uint8_t *wcs_to_char(wchar_t *string); +int string_is_empty(char *string); ToxWindow new_chat(Tox *m, ToxWindow *prompt, int friendnum); #endif /* end of include guard: CHAT_H_6489PZ13 */ diff --git a/src/friendlist.c b/src/friendlist.c index 9be6c30..8f01eb9 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -49,10 +49,7 @@ void friendlist_onConnectionChange(ToxWindow *self, Tox *m, int num, uint8_t sta if (num < 0 || num >= num_friends) return; - if (status == 1) - friends[num].online = true; - else - friends[num].online = false; + friends[num].online = status == 1 ? true : false; } void friendlist_onNickChange(ToxWindow *self, int num, uint8_t *str, uint16_t len) @@ -227,7 +224,7 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'}; tox_copy_statusmessage(m, friends[i].num, statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); snprintf(friends[i].statusmsg, sizeof(friends[i].statusmsg), "%s", statusmsg); - friends[i].statusmsg_len = tox_get_statusmessage_size(m, self->friendnum); + friends[i].statusmsg_len = tox_get_statusmessage_size(m, self->num); } self->x = x; diff --git a/src/groupchat.c b/src/groupchat.c new file mode 100644 index 0000000..d1db257 --- /dev/null +++ b/src/groupchat.c @@ -0,0 +1,233 @@ +/* + * Toxic -- Tox Curses Client + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include "toxic_windows.h" +#include "chat.h" + +static GroupChat groupchats[MAX_GROUPCHAT_NUM]; +static int group_chat_index = 0; + +ToxWindow new_groupchat(Tox *m, ToxWindow *prompt, int groupnum); + +extern char *DATA_FILE; +extern int store_data(Tox *m, char *path); + +int get_num_groupchats(void) +{ + int count = 0; + int i; + + for (i = 0; i < group_chat_index; ++i) { + if (groupchats[i].active) + ++count; + } + + return count; +} + +int init_groupchat_win(ToxWindow *prompt, Tox *m) +{ + int i; + + for (i = 0; i <= group_chat_index; ++i) { + if (!groupchats[i].active) { + groupchats[i].active = true; + groupchats[i].chatwin = add_window(m, new_groupchat(m, prompt, i)); + set_active_window(groupchats[i].chatwin); + + if (i == group_chat_index) + ++group_chat_index; + + return 0; + } + } + + return -1; +} + +static void close_groupchatwin(Tox *m, int groupnum) +{ + tox_del_groupchat(m, groupnum); + memset(&(groupchats[groupnum]), 0, sizeof(GroupChat)); + + int i; + + for (i = group_chat_index; i > 0; --i) { + if (groupchats[i-1].active) + break; + } + + group_chat_index = i; +} + +static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, uint8_t *msg, uint16_t len) +{ + if (self->num != groupnum) + return; + + ChatContext *ctx = (ChatContext *) self->chatwin; + struct tm *timeinfo = get_time(); + + // uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'}; + // tox_getname(m, num, nick); + + wattron(ctx->history, COLOR_PAIR(CYAN)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(CYAN)); + wattron(ctx->history, COLOR_PAIR(4)); + wprintw(ctx->history, "Toxicle: "); + wattroff(ctx->history, COLOR_PAIR(4)); + wprintw(ctx->history, "%s\n", msg); + + self->blink = true; + beep(); +} + +static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key) +{ + ChatContext *ctx = (ChatContext *) self->chatwin; + struct tm *timeinfo = get_time(); + + int x, y, y2, x2; + getyx(self->window, y, x); + getmaxyx(self->window, y2, x2); + + /* Add printable chars to buffer and print on input space */ +#if HAVE_WIDECHAR + if (iswprint(key)) { +#else + if (isprint(key)) { +#endif + if (ctx->pos < (MAX_STR_SIZE-1)) { + mvwaddstr(self->window, y, x, wc_to_char(key)); + ctx->line[ctx->pos++] = key; + 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] = L'\0'; + + if (x == 0) + mvwdelch(self->window, y - 1, x2 - 1); + else + mvwdelch(self->window, y, x - 1); + } + } + + /* RETURN key: Execute command or print line */ + else if (key == '\n') { + uint8_t *line = wcs_to_char(ctx->line); + wclear(ctx->linewin); + wmove(self->window, y2 - CURS_Y_OFFSET, 0); + wclrtobot(self->window); + bool close_win = false; + + if (line[0] == '/') { + if (close_win = !strncmp(line, "/close", strlen("/close"))) { + set_active_window(0); + int group_num = groupchats[self->num].chatwin; + delwin(ctx->linewin); + del_window(self); + close_groupchatwin(m, group_num); + } //else + //execute(self, ctx, statusbar, m, line); + } else { + /* make sure the string has at least non-space character */ + if (!string_is_empty(line)) { + uint8_t selfname[TOX_MAX_NAME_LENGTH]; + tox_getselfname(m, selfname, TOX_MAX_NAME_LENGTH); + + wattron(ctx->history, COLOR_PAIR(CYAN)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(CYAN)); + wattron(ctx->history, COLOR_PAIR(GREEN)); + wprintw(ctx->history, "%s: ", selfname); + wattroff(ctx->history, COLOR_PAIR(GREEN)); + wprintw(ctx->history, "%s\n", line); + + if (tox_group_message_send(m, self->num, line, strlen(line) + 1) == -1) { + wattron(ctx->history, COLOR_PAIR(RED)); + wprintw(ctx->history, " * Failed to send message.\n"); + wattroff(ctx->history, COLOR_PAIR(RED)); + } + } + } + + if (close_win) + free(ctx); + else { + ctx->line[0] = L'\0'; + ctx->pos = 0; + } + + free(line); + } +} + +static void groupchat_onDraw(ToxWindow *self, Tox *m) +{ + curs_set(1); + int x, y; + getmaxyx(self->window, y, x); + ChatContext *ctx = (ChatContext *) self->chatwin; + mvwhline(ctx->linewin, 0, 0, '_', x); + wrefresh(self->window); +} + +static void groupchat_onInit(ToxWindow *self, Tox *m) +{ + int x, y; + ChatContext *ctx = (ChatContext *) self->chatwin; + getmaxyx(self->window, y, x); + ctx->history = subwin(self->window, y-4, x, 0, 0); + scrollok(ctx->history, 1); + ctx->linewin = subwin(self->window, 2, x, y-4, 0); + // print_help(ctx); + wmove(self->window, y - CURS_Y_OFFSET, 0); +} + +ToxWindow new_groupchat(Tox *m, ToxWindow *prompt, int groupnum) +{ + ToxWindow ret; + memset(&ret, 0, sizeof(ret)); + + ret.onKey = &groupchat_onKey; + ret.onDraw = &groupchat_onDraw; + ret.onInit = &groupchat_onInit; + ret.onGroupMessage = &groupchat_onGroupMessage; + // ret.onNickChange = &groupchat_onNickChange; + // ret.onStatusChange = &groupchat_onStatusChange; + // ret.onAction = &groupchat_onAction; + + snprintf(ret.name, sizeof(ret.name), "Room #%d", groupnum); + + ChatContext *chatwin = calloc(1, sizeof(ChatContext)); + + if (chatwin != NULL) + ret.chatwin = chatwin; + else { + endwin(); + fprintf(stderr, "calloc() failed. Aborting...\n"); + exit(EXIT_FAILURE); + } + + ret.prompt = prompt; + ret.num = groupnum; + + return ret; +} diff --git a/src/groupchat.h b/src/groupchat.h new file mode 100644 index 0000000..851e4e4 --- /dev/null +++ b/src/groupchat.h @@ -0,0 +1,6 @@ +/* + * Toxic -- Tox Curses Client + */ + +int init_groupchat_win(ToxWindow *prompt, Tox *m); +int get_num_groupchats(void); \ No newline at end of file diff --git a/src/main.c b/src/main.c index 262b154..26fdb31 100644 --- a/src/main.c +++ b/src/main.c @@ -102,6 +102,8 @@ static Tox *init_tox() tox_callback_userstatus(m, on_statuschange, NULL); tox_callback_statusmessage(m, on_statusmessagechange, NULL); tox_callback_action(m, on_action, NULL); + tox_callback_group_invite(m, on_groupinvite, NULL); + tox_callback_group_message(m, on_groupmessage, NULL); #ifdef __linux__ tox_setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy")); #elif defined(_WIN32) diff --git a/src/prompt.c b/src/prompt.c index ed411a2..78705c9 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -11,11 +11,15 @@ #include #include "prompt.h" +#include "groupchat.h" extern char *DATA_FILE; -uint8_t pending_requests[MAX_STR_SIZE][TOX_CLIENT_ID_SIZE]; // XXX -uint8_t num_requests = 0; // XXX +uint8_t pending_frnd_requests[MAX_FRIENDS_NUM][TOX_CLIENT_ID_SIZE]; +uint8_t num_frnd_requests = 0; + +uint8_t pending_grp_requests[MAX_FRIENDS_NUM][TOX_CLIENT_ID_SIZE]; +uint8_t num_grp_requests = 0; static char prompt_buf[MAX_STR_SIZE] = {'\0'}; static int prompt_buf_pos = 0; @@ -25,7 +29,10 @@ void cmd_accept(ToxWindow *, Tox *m, int, char **); void cmd_add(ToxWindow *, Tox *m, int, char **); void cmd_clear(ToxWindow *, Tox *m, int, char **); void cmd_connect(ToxWindow *, Tox *m, int, char **); +void cmd_groupchat(ToxWindow *, Tox *m, int, char **); void cmd_help(ToxWindow *, Tox *m, int, char **); +void cmd_invite(ToxWindow *, Tox *m, int, char **); +void cmd_join(ToxWindow *, Tox *m, int, char **); void cmd_msg(ToxWindow *, Tox *m, int, char **); void cmd_myid(ToxWindow *, Tox *m, int, char **); void cmd_nick(ToxWindow *, Tox *m, int, char **); @@ -33,7 +40,7 @@ void cmd_quit(ToxWindow *, Tox *m, int, char **); void cmd_status(ToxWindow *, Tox *m, int, char **); void cmd_note(ToxWindow *, Tox *m, int, char **); -#define NUM_COMMANDS 13 +#define NUM_COMMANDS 16 static struct { char *name; @@ -44,7 +51,10 @@ static struct { { "clear", cmd_clear }, { "connect", cmd_connect }, { "exit", cmd_quit }, + { "groupchat", cmd_groupchat }, { "help", cmd_help }, + { "invite", cmd_invite }, + { "join", cmd_join }, { "msg", cmd_msg }, { "myid", cmd_myid }, { "nick", cmd_nick }, @@ -82,30 +92,18 @@ void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected) statusbar->is_online = is_connected; } -void prompt_onFriendRequest(ToxWindow *prompt, uint8_t *key, uint8_t *data, uint16_t length) +/* Adds friend request to pending friend requests. */ +int add_friend_req(uint8_t *public_key) { - int n = add_req(key); - wprintw(prompt->window, "\nFriend request from:\n"); - - int i; - - for (i = 0; i < KEY_SIZE_BYTES; ++i) { - wprintw(prompt->window, "%02x", key[i] & 0xff); - } - - wprintw(prompt->window, "\n\nWith the message: %s\n\n", data); - wprintw(prompt->window, "Type \"accept %d\" to accept it.\n", n); - - prompt->blink = true; - beep(); + memcpy(pending_frnd_requests[num_frnd_requests++], public_key, TOX_CLIENT_ID_SIZE); + return num_frnd_requests - 1; } -// XXX: -int add_req(uint8_t *public_key) +/* Adds group chat invite to pending group chat requests */ +int add_group_req(uint8_t *group_pub_key) { - memcpy(pending_requests[num_requests], public_key, TOX_CLIENT_ID_SIZE); - ++num_requests; - return num_requests - 1; + memcpy(pending_grp_requests[num_grp_requests++], group_pub_key, TOX_CLIENT_ID_SIZE); + return num_grp_requests - 1; } // XXX: FIX @@ -132,27 +130,25 @@ unsigned char *hex_string_to_bin(char hex_string[]) /* command functions */ void cmd_accept(ToxWindow *self, Tox *m, int argc, char **argv) { - int num; - /* check arguments */ if (argc != 1) { wprintw(self->window, "Invalid syntax.\n"); return; } - num = atoi(argv[1]); + int num = atoi(argv[1]); - if (num < 0 || num >= num_requests) { - wprintw(self->window, "No pending request with that number.\n"); + if (num < 0 || num >= num_frnd_requests) { + wprintw(self->window, "No pending friend request with that number.\n"); return; } - num = tox_addfriend_norequest(m, pending_requests[num]); + num = tox_addfriend_norequest(m, pending_frnd_requests[num]); if (num == -1) wprintw(self->window, "Failed to add friend.\n"); else { - wprintw(self->window, "Friend accepted as: %d.\n", num); + wprintw(self->window, "Friend accepted.\n"); on_friendadded(m, num); } } @@ -274,7 +270,7 @@ void cmd_connect(ToxWindow *self, Tox *m, int argc, char **argv) char *port = argv[2]; char *key = argv[3]; - if (!ip || !port || !key) { + if (ip == NULL || port == NULL || key == NULL) { wprintw(self->window, "Invalid syntax.\n"); return; } @@ -302,6 +298,31 @@ void cmd_quit(ToxWindow *self, Tox *m, int argc, char **argv) exit_toxic(m); } +void cmd_groupchat(ToxWindow *self, Tox *m, int argc, char **argv) +{ + int ngc = get_num_groupchats(); + + if (ngc < 0 || ngc >= MAX_GROUPCHAT_NUM) { + wprintw(self->window, "\nMaximum number of group chats has been reached.\n"); + return; + } + + int groupnum = tox_add_groupchat(m); + + if (groupnum == -1) { + wprintw(self->window, "Group chat failed to initialize.\n"); + return; + } + + if (init_groupchat_win(self, m) == -1) { + wprintw(self->window, "Group chat failed to initialize.\n"); + tox_del_groupchat(m, groupnum); + return; + } + + wprintw(self->window, "Group chat created as %d.\n", groupnum); +} + void cmd_help(ToxWindow *self, Tox *m, int argc, char **argv) { wclear(self->window); @@ -328,6 +349,55 @@ void cmd_help(ToxWindow *self, Tox *m, int argc, char **argv) wattroff(self->window, COLOR_PAIR(CYAN)); } +void cmd_invite(ToxWindow *self, Tox *m, int argc, char **argv) +{ + if (argc != 2) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + + if (argv[1] == NULL || argv[2] == NULL) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + + int friendnum = atoi(argv[1]); + int groupnum = atoi(argv[2]); + int n = tox_invite_friend(m, friendnum, groupnum); + + if (n == -1) { + wprintw(self->window, "Failed to invite friend.\n"); + return; + } + + wprintw(self->window, "Invited friend %d to group chat %d.\n", friendnum, groupnum); +} + +void cmd_join(ToxWindow *self, Tox *m, int argc, char **argv) +{ + if (argc != 1) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + + if (argv[1] == NULL) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + + int num = atoi(argv[1]); + + if (num < 0 || num >= num_grp_requests) { + wprintw(self->window, "No pending group chat invites with that number.\n"); + return; + } + + num = tox_join_groupchat(m, num, pending_grp_requests[num]); + + if (num == -1 || init_groupchat_win(self, m) == -1) + wprintw(self->window, "Group chat failed to initialize.\n"); +} + void cmd_msg(ToxWindow *self, Tox *m, int argc, char **argv) { /* check arguments */ @@ -405,11 +475,6 @@ void cmd_nick(ToxWindow *self, Tox *m, int argc, char **argv) void cmd_status(ToxWindow *self, Tox *m, int argc, char **argv) { - if (argc < 1 || argc > 2) { - wprintw(self->window, "Wrong number of arguments.\n"); - return; - } - uint8_t *msg = NULL; if (argc == 2) { @@ -425,6 +490,9 @@ void cmd_status(ToxWindow *self, Tox *m, int argc, char **argv) wprintw(self->window, "Messages must be enclosed in quotes.\n"); return; } + } else if (argc < 1 || argc > 2) { + wprintw(self->window, "Wrong number of arguments.\n"); + return; } char *status = argv[1]; @@ -671,6 +739,42 @@ static void prompt_onInit(ToxWindow *self, Tox *m) wclrtoeol(self->window); } +void prompt_onFriendRequest(ToxWindow *self, uint8_t *key, uint8_t *data, uint16_t length) +{ + int n = add_friend_req(key); + wprintw(self->window, "\nFriend request from:\n"); + + int i; + + for (i = 0; i < KEY_SIZE_BYTES; ++i) { + wprintw(self->window, "%02x", key[i] & 0xff); + } + + wprintw(self->window, "\n\nWith the message: %s\n\n", data); + wprintw(self->window, "Type \"accept %d\" to accept it.\n", n); + + self->blink = true; + beep(); +} + +void prompt_onGroupInvite(ToxWindow *self, Tox *m, int friendnumber, uint8_t *group_pub_key) +{ + int ngc = get_num_groupchats(); + if (ngc < 0 || ngc >= MAX_GROUPCHAT_NUM) { + wprintw(self->window, "\nGroup chat invite from: %d\n", friendnumber); + wprintw(self->window, "\nMaximum number of group chats has been reached. Discarding invite.\n"); + return; + } + + int n = add_group_req(group_pub_key); + + wprintw(self->window, "\nGroup chat invite from: %d\n", friendnumber); + wprintw(self->window, "Type \"join %d\" to join the chat.\n", n); + + self->blink = true; + beep(); +} + void prompt_init_statusbar(ToxWindow *self, Tox *m) { int x, y; @@ -698,10 +802,13 @@ ToxWindow new_prompt() { ToxWindow ret; memset(&ret, 0, sizeof(ret)); + ret.onKey = &prompt_onKey; ret.onDraw = &prompt_onDraw; ret.onInit = &prompt_onInit; ret.onFriendRequest = &prompt_onFriendRequest; + ret.onGroupInvite = &prompt_onGroupInvite; + strcpy(ret.name, "prompt"); StatusBar *stb = calloc(1, sizeof(StatusBar)); diff --git a/src/toxic_windows.h b/src/toxic_windows.h index 11d346e..5768e67 100644 --- a/src/toxic_windows.h +++ b/src/toxic_windows.h @@ -1,9 +1,14 @@ /* * Toxic -- Tox Curses Client */ + #ifndef _windows_h #define _windows_h +#ifndef TOXICVER +#define TOXICVER "NOVER" /* Use the -D flag to set this */ +#endif + #include #include #include @@ -14,6 +19,7 @@ #define MAX_WINDOWS_NUM 32 #define MAX_FRIENDS_NUM 100 +#define MAX_GROUPCHAT_NUM 32 #define MAX_STR_SIZE 256 #define KEY_SIZE_BYTES 32 #define TOXIC_MAX_NAME_LENGTH 30 /* Not to be confused with TOX_MAX_NAME_LENGTH */ @@ -21,10 +27,7 @@ #define UNKNOWN_NAME "Unknown" #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 - -#ifndef TOXICVER -#define TOXICVER "NOVER" //Use the -D flag to set this -#endif +#define CURS_Y_OFFSET 3 /* y-axis cursor offset for chat contexts */ /* Curses foreground colours (background is black) */ #define WHITE 0 @@ -49,9 +52,11 @@ struct ToxWindow_ { void(*onStatusChange)(ToxWindow *, Tox *, int, TOX_USERSTATUS); void(*onStatusMessageChange)(ToxWindow *, int, uint8_t *, uint16_t); void(*onAction)(ToxWindow *, Tox *, int, uint8_t *, uint16_t); + void(*onGroupMessage)(ToxWindow *, Tox *, int, uint8_t *, uint16_t); + void(*onGroupInvite)(ToxWindow *, Tox *, int, uint8_t *); char name[TOX_MAX_NAME_LENGTH]; - int friendnum; + int num; int x; void *chatwin; @@ -72,6 +77,18 @@ typedef struct { bool is_online; } StatusBar; +typedef struct { + wchar_t line[MAX_STR_SIZE]; + size_t pos; + WINDOW *history; + WINDOW *linewin; +} ChatContext; + +typedef struct { + int chatwin; + bool active; +} GroupChat; + void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata); void on_connectionchange(Tox *m, int friendnumber, uint8_t status, void *userdata); void on_message(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata); @@ -80,6 +97,8 @@ void on_nickchange(Tox *m, int friendnumber, uint8_t *string, uint16_t length, v void on_statuschange(Tox *m, int friendnumber, TOX_USERSTATUS status, void *userdata); void on_statusmessagechange(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata); void on_friendadded(Tox *m, int friendnumber); +void on_groupmessage(Tox *m, int groupnumber, uint8_t *message, uint16_t length, void *userdata); +void on_groupinvite(Tox *m, int friendnumber, uint8_t *group_pub_key, void *userdata); ToxWindow *init_windows(); void draw_active_window(Tox *m); int add_window(Tox *m, ToxWindow w); diff --git a/src/windows.c b/src/windows.c index f61768b..60d5d7c 100644 --- a/src/windows.c +++ b/src/windows.c @@ -124,6 +124,26 @@ void on_friendadded(Tox *m, int friendnumber) if (store_data(m, DATA_FILE)) wprintw(prompt->window, "\nCould not store Tox data\n"); } + +void on_groupmessage(Tox *m, int groupnumber, uint8_t *message, uint16_t length, void *userdata) +{ + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupMessage != NULL) + windows[i].onGroupMessage(&windows[i], m, groupnumber, message, length); + } +} + +void on_groupinvite(Tox *m, int friendnumber, uint8_t *group_pub_key, void *userdata) +{ + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupInvite != NULL) + windows[i].onGroupInvite(&windows[i], m, friendnumber, group_pub_key); + } +} /* CALLBACKS END */ int add_window(Tox *m, ToxWindow w) @@ -261,7 +281,6 @@ void prepare_window(WINDOW *w) void draw_active_window(Tox *m) { - ToxWindow *a = active_window; wint_t ch = 0; From 390cdc7b33006e116348957f8aee73370fa5deb6 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 15 Sep 2013 18:16:41 -0400 Subject: [PATCH 2/9] update makefile --- build/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build/Makefile.am b/build/Makefile.am index dc6a588..ccdf4f3 100644 --- a/build/Makefile.am +++ b/build/Makefile.am @@ -11,7 +11,9 @@ toxic_SOURCES = $(top_srcdir)/src/main.c \ $(top_srcdir)/src/friendlist.h \ $(top_srcdir)/src/friendlist.c \ $(top_srcdir)/src/toxic_windows.h \ - $(top_srcdir)/src/windows.c + $(top_srcdir)/src/windows.c \ + $(top_srcdir)/src/groupchat.c \ + $(top_srcdir)/src/groupchat.h toxic_CFLAGS = -I$(top_srcdir) \ $(NCURSES_CFLAGS) \ From b6bf0eb0a0cb542aa65e8899b44d26e51369cd3f Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 16 Sep 2013 00:28:28 -0400 Subject: [PATCH 3/9] fixes --- src/groupchat.c | 13 ++++----- src/groupchat.h | 2 +- src/prompt.c | 69 ++++++++++++++++++++++++++++++++------------- src/toxic_windows.h | 2 +- 4 files changed, 57 insertions(+), 29 deletions(-) diff --git a/src/groupchat.c b/src/groupchat.c index d1db257..40c77b3 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -26,15 +26,14 @@ extern int store_data(Tox *m, char *path); int get_num_groupchats(void) { - int count = 0; int i; - for (i = 0; i < group_chat_index; ++i) { - if (groupchats[i].active) - ++count; + for (i = 0; i <= group_chat_index; ++i) { + if (!groupchats[i].active) + return i; } - return count; + return -1; } int init_groupchat_win(ToxWindow *prompt, Tox *m) @@ -45,7 +44,7 @@ int init_groupchat_win(ToxWindow *prompt, Tox *m) if (!groupchats[i].active) { groupchats[i].active = true; groupchats[i].chatwin = add_window(m, new_groupchat(m, prompt, i)); - set_active_window(groupchats[i].chatwin); + //set_active_window(groupchats[i].chatwin); if (i == group_chat_index) ++group_chat_index; @@ -140,7 +139,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key) if (line[0] == '/') { if (close_win = !strncmp(line, "/close", strlen("/close"))) { set_active_window(0); - int group_num = groupchats[self->num].chatwin; + int group_num = self->num; delwin(ctx->linewin); del_window(self); close_groupchatwin(m, group_num); diff --git a/src/groupchat.h b/src/groupchat.h index 851e4e4..fe2f42c 100644 --- a/src/groupchat.h +++ b/src/groupchat.h @@ -3,4 +3,4 @@ */ int init_groupchat_win(ToxWindow *prompt, Tox *m); -int get_num_groupchats(void); \ No newline at end of file +int get_num_groupchats(void); diff --git a/src/prompt.c b/src/prompt.c index 15d286f..13c0b82 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -18,7 +18,7 @@ extern char *DATA_FILE; uint8_t pending_frnd_requests[MAX_FRIENDS_NUM][TOX_CLIENT_ID_SIZE]; uint8_t num_frnd_requests = 0; -uint8_t pending_grp_requests[MAX_FRIENDS_NUM][TOX_CLIENT_ID_SIZE]; +uint8_t pending_grp_requests[MAX_GROUPCHAT_NUM][TOX_CLIENT_ID_SIZE]; uint8_t num_grp_requests = 0; static char prompt_buf[MAX_STR_SIZE] = {'\0'}; @@ -92,18 +92,28 @@ void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected) statusbar->is_online = is_connected; } -/* Adds friend request to pending friend requests. */ +/* Adds friend request to pending friend requests. + Returns friend number on success, -1 if queue is full or other error. */ int add_friend_req(uint8_t *public_key) { - memcpy(pending_frnd_requests[num_frnd_requests++], public_key, TOX_CLIENT_ID_SIZE); - return num_frnd_requests - 1; + if (num_frnd_requests < MAX_FRIENDS_NUM) { + memcpy(pending_frnd_requests[num_frnd_requests++], public_key, TOX_CLIENT_ID_SIZE); + return num_frnd_requests - 1; + } + + return -1; } -/* Adds group chat invite to pending group chat requests */ +/* Adds group chat invite to pending group chat requests. + Returns group number on success, -1 if queue is full or other error. */ int add_group_req(uint8_t *group_pub_key) { - memcpy(pending_grp_requests[num_grp_requests++], group_pub_key, TOX_CLIENT_ID_SIZE); - return num_grp_requests - 1; + if (num_grp_requests < MAX_GROUPCHAT_NUM) { + memcpy(pending_grp_requests[num_grp_requests++], group_pub_key, TOX_CLIENT_ID_SIZE); + return num_grp_requests - 1; + } + + return -1; } // XXX: FIX @@ -143,13 +153,13 @@ void cmd_accept(ToxWindow *self, Tox *m, int argc, char **argv) return; } - num = tox_addfriend_norequest(m, pending_frnd_requests[num]); + int friendnum = tox_addfriend_norequest(m, pending_frnd_requests[num]); - if (num == -1) + if (friendnum == -1) wprintw(self->window, "Failed to add friend.\n"); else { - wprintw(self->window, "Friend accepted.\n"); - on_friendadded(m, num); + wprintw(self->window, "Friend request accepted.\n"); + on_friendadded(m, friendnum); } } @@ -296,7 +306,7 @@ void cmd_groupchat(ToxWindow *self, Tox *m, int argc, char **argv) { int ngc = get_num_groupchats(); - if (ngc < 0 || ngc >= MAX_GROUPCHAT_NUM) { + if (ngc < 0 || ngc > MAX_GROUPCHAT_NUM) { wprintw(self->window, "\nMaximum number of group chats has been reached.\n"); return; } @@ -357,9 +367,8 @@ void cmd_invite(ToxWindow *self, Tox *m, int argc, char **argv) int friendnum = atoi(argv[1]); int groupnum = atoi(argv[2]); - int n = tox_invite_friend(m, friendnum, groupnum); - if (n == -1) { + if (tox_invite_friend(m, friendnum, groupnum) == -1) { wprintw(self->window, "Failed to invite friend.\n"); return; } @@ -386,10 +395,18 @@ void cmd_join(ToxWindow *self, Tox *m, int argc, char **argv) return; } - num = tox_join_groupchat(m, num, pending_grp_requests[num]); + int groupnum = tox_join_groupchat(m, num, pending_grp_requests[num]); - if (num == -1 || init_groupchat_win(self, m) == -1) + if (groupnum == -1) { wprintw(self->window, "Group chat failed to initialize.\n"); + return; + } + + if (init_groupchat_win(self, m) == -1) { + wprintw(self->window, "Group chat failed to initialize.\n"); + tox_del_groupchat(m, groupnum); + return; + } } void cmd_msg(ToxWindow *self, Tox *m, int argc, char **argv) @@ -484,7 +501,7 @@ void cmd_status(ToxWindow *self, Tox *m, int argc, char **argv) wprintw(self->window, "Messages must be enclosed in quotes.\n"); return; } - } else if (argc < 1 || argc > 2) { + } else if (argc != 1) { wprintw(self->window, "Wrong number of arguments.\n"); return; } @@ -736,6 +753,12 @@ static void prompt_onInit(ToxWindow *self, Tox *m) void prompt_onFriendRequest(ToxWindow *self, uint8_t *key, uint8_t *data, uint16_t length) { int n = add_friend_req(key); + + if (n == -1) { + wprintw(self->window, "Friend request queue is full. Discarding request.\n"); + return; + } + wprintw(self->window, "\nFriend request from:\n"); int i; @@ -753,16 +776,22 @@ void prompt_onFriendRequest(ToxWindow *self, uint8_t *key, uint8_t *data, uint16 void prompt_onGroupInvite(ToxWindow *self, Tox *m, int friendnumber, uint8_t *group_pub_key) { + wprintw(self->window, "\nGroup chat invite from: %d\n", friendnumber); + int ngc = get_num_groupchats(); - if (ngc < 0 || ngc >= MAX_GROUPCHAT_NUM) { - wprintw(self->window, "\nGroup chat invite from: %d\n", friendnumber); + + if (ngc < 0 || ngc > MAX_GROUPCHAT_NUM) { wprintw(self->window, "\nMaximum number of group chats has been reached. Discarding invite.\n"); return; } int n = add_group_req(group_pub_key); - wprintw(self->window, "\nGroup chat invite from: %d\n", friendnumber); + if (n == -1) { + wprintw(self->window, "\nGroup chat queue is full. Discarding invite.\n"); + return; + } + wprintw(self->window, "Type \"join %d\" to join the chat.\n", n); self->blink = true; diff --git a/src/toxic_windows.h b/src/toxic_windows.h index 5768e67..e0c8e4e 100644 --- a/src/toxic_windows.h +++ b/src/toxic_windows.h @@ -19,7 +19,7 @@ #define MAX_WINDOWS_NUM 32 #define MAX_FRIENDS_NUM 100 -#define MAX_GROUPCHAT_NUM 32 +#define MAX_GROUPCHAT_NUM 30 #define MAX_STR_SIZE 256 #define KEY_SIZE_BYTES 32 #define TOXIC_MAX_NAME_LENGTH 30 /* Not to be confused with TOX_MAX_NAME_LENGTH */ From 6e0ac744cba1a147ff4d94b526513ac93a6515a6 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 17 Sep 2013 06:03:08 -0400 Subject: [PATCH 4/9] more fixes --- src/groupchat.c | 36 ++++++++++++++++++------------------ src/groupchat.h | 2 +- src/prompt.c | 9 ++++++--- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/groupchat.c b/src/groupchat.c index 40c77b3..64a726c 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -19,7 +19,7 @@ static GroupChat groupchats[MAX_GROUPCHAT_NUM]; static int group_chat_index = 0; -ToxWindow new_groupchat(Tox *m, ToxWindow *prompt, int groupnum); +ToxWindow new_group_chat(Tox *m, ToxWindow *prompt, int groupnum); extern char *DATA_FILE; extern int store_data(Tox *m, char *path); @@ -36,15 +36,15 @@ int get_num_groupchats(void) return -1; } -int init_groupchat_win(ToxWindow *prompt, Tox *m) +int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum) { int i; for (i = 0; i <= group_chat_index; ++i) { if (!groupchats[i].active) { + groupchats[i].chatwin = add_window(m, new_group_chat(m, prompt, groupnum)); groupchats[i].active = true; - groupchats[i].chatwin = add_window(m, new_groupchat(m, prompt, i)); - //set_active_window(groupchats[i].chatwin); + set_active_window(groupchats[i].chatwin); if (i == group_chat_index) ++group_chat_index; @@ -64,7 +64,7 @@ static void close_groupchatwin(Tox *m, int groupnum) int i; for (i = group_chat_index; i > 0; --i) { - if (groupchats[i-1].active) + if (groupchats[i-1].chatwin != -1) break; } @@ -139,25 +139,25 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key) if (line[0] == '/') { if (close_win = !strncmp(line, "/close", strlen("/close"))) { set_active_window(0); - int group_num = self->num; + int groupnum = self->num; delwin(ctx->linewin); del_window(self); - close_groupchatwin(m, group_num); + close_groupchatwin(m, groupnum); } //else //execute(self, ctx, statusbar, m, line); } else { /* make sure the string has at least non-space character */ if (!string_is_empty(line)) { - uint8_t selfname[TOX_MAX_NAME_LENGTH]; - tox_getselfname(m, selfname, TOX_MAX_NAME_LENGTH); + // uint8_t selfname[TOX_MAX_NAME_LENGTH]; + // tox_getselfname(m, selfname, TOX_MAX_NAME_LENGTH); - wattron(ctx->history, COLOR_PAIR(CYAN)); - wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); - wattroff(ctx->history, COLOR_PAIR(CYAN)); - wattron(ctx->history, COLOR_PAIR(GREEN)); - wprintw(ctx->history, "%s: ", selfname); - wattroff(ctx->history, COLOR_PAIR(GREEN)); - wprintw(ctx->history, "%s\n", line); + // wattron(ctx->history, COLOR_PAIR(CYAN)); + // wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + // wattroff(ctx->history, COLOR_PAIR(CYAN)); + // wattron(ctx->history, COLOR_PAIR(GREEN)); + // wprintw(ctx->history, "%s: ", selfname); + // wattroff(ctx->history, COLOR_PAIR(GREEN)); + // wprintw(ctx->history, "%s\n", line); if (tox_group_message_send(m, self->num, line, strlen(line) + 1) == -1) { wattron(ctx->history, COLOR_PAIR(RED)); @@ -193,14 +193,14 @@ static void groupchat_onInit(ToxWindow *self, Tox *m) int x, y; ChatContext *ctx = (ChatContext *) self->chatwin; getmaxyx(self->window, y, x); - ctx->history = subwin(self->window, y-4, x, 0, 0); + ctx->history = subwin(self->window, y-3, x, 0, 0); scrollok(ctx->history, 1); ctx->linewin = subwin(self->window, 2, x, y-4, 0); // print_help(ctx); wmove(self->window, y - CURS_Y_OFFSET, 0); } -ToxWindow new_groupchat(Tox *m, ToxWindow *prompt, int groupnum) +ToxWindow new_group_chat(Tox *m, ToxWindow *prompt, int groupnum) { ToxWindow ret; memset(&ret, 0, sizeof(ret)); diff --git a/src/groupchat.h b/src/groupchat.h index fe2f42c..c31b5f9 100644 --- a/src/groupchat.h +++ b/src/groupchat.h @@ -2,5 +2,5 @@ * Toxic -- Tox Curses Client */ -int init_groupchat_win(ToxWindow *prompt, Tox *m); +int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum); int get_num_groupchats(void); diff --git a/src/prompt.c b/src/prompt.c index 13c0b82..c470663 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -318,7 +318,7 @@ void cmd_groupchat(ToxWindow *self, Tox *m, int argc, char **argv) return; } - if (init_groupchat_win(self, m) == -1) { + if (init_groupchat_win(self, m, groupnum) == -1) { wprintw(self->window, "Group chat failed to initialize.\n"); tox_del_groupchat(m, groupnum); return; @@ -336,10 +336,13 @@ void cmd_help(ToxWindow *self, Tox *m, int argc, char **argv) wprintw(self->window, " connect : Connect to DHT server\n"); wprintw(self->window, " add : Add friend with optional message\n"); + wprintw(self->window, " accept : Accept friend request\n"); wprintw(self->window, " status : Set your status with optional note\n"); wprintw(self->window, " note : Set a personal note\n"); wprintw(self->window, " nick : Set your nickname\n"); - wprintw(self->window, " accept : Accept friend request\n"); + wprintw(self->window, " join : Join a group chat (must be invited)\n"); + wprintw(self->window, " invite : Invite friend f to groupchat g\n"); + wprintw(self->window, " groupchat : Create a group chat\n"); wprintw(self->window, " myid : Print your ID\n"); wprintw(self->window, " quit/exit : Exit Toxic\n"); wprintw(self->window, " help : Print this message again\n"); @@ -402,7 +405,7 @@ void cmd_join(ToxWindow *self, Tox *m, int argc, char **argv) return; } - if (init_groupchat_win(self, m) == -1) { + if (init_groupchat_win(self, m, groupnum) == -1) { wprintw(self->window, "Group chat failed to initialize.\n"); tox_del_groupchat(m, groupnum); return; From 84422b5845544ee3b6619829c187970e3ebb4db9 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 17 Sep 2013 06:05:31 -0400 Subject: [PATCH 5/9] fix --- src/groupchat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/groupchat.c b/src/groupchat.c index 64a726c..e8317e6 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -64,7 +64,7 @@ static void close_groupchatwin(Tox *m, int groupnum) int i; for (i = group_chat_index; i > 0; --i) { - if (groupchats[i-1].chatwin != -1) + if (groupchats[i-1].active) break; } From 42de821e3c365e6a957f904b00c07eae5d93be85 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 17 Sep 2013 19:11:23 -0400 Subject: [PATCH 6/9] use/display nicks instead of friend numbers for groupchat invites --- src/friendlist.c | 22 +++++++++++++++++++++- src/friendlist.h | 1 + src/prompt.c | 29 ++++++++++++++++++++++++----- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/friendlist.c b/src/friendlist.c index 8f01eb9..ce4b914 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -21,6 +21,7 @@ extern ToxWindow *prompt; typedef struct { uint8_t name[TOX_MAX_NAME_LENGTH]; + uint8_t namelength; uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH]; uint16_t statusmsg_len; int num; @@ -58,6 +59,7 @@ void friendlist_onNickChange(ToxWindow *self, int num, uint8_t *str, uint16_t le return; memcpy((char *) &friends[num].name, (char *) str, len); + friends[num].namelength = len; } void friendlist_onStatusChange(ToxWindow *self, Tox *m, int num, TOX_USERSTATUS status) @@ -91,9 +93,12 @@ int friendlist_onFriendAdded(Tox *m, int num) friends[i].chatwin = -1; friends[i].online = false; friends[i].status = TOX_USERSTATUS_NONE; + friends[i].namelength = tox_getname(m, num, friends[i].name); - if (tox_getname(m, num, friends[i].name) == -1 || friends[i].name[0] == '\0') + if (friends[i].namelength == -1 || friends[i].name[0] == '\0') { strcpy((char *) friends[i].name, UNKNOWN_NAME); + friends[i].namelength = strlen(UNKNOWN_NAME) + 1; + } if (i == num_friends) ++num_friends; @@ -251,6 +256,21 @@ void disable_chatwin(int f_num) friends[f_num].chatwin = -1; } +/* Returns the respective friend number of name. Returns -1 on no match + This should be used instead of tox_getname for retrieving */ +int get_friendnum(uint8_t *name) +{ + int i; + int len = strlen(name); + + for (i = 0; i < num_friends; ++i) { + if (strncmp(friends[i].name, name, len) == 0) + return friends[i].num; + } + + return -1; +} + static void friendlist_onInit(ToxWindow *self, Tox *m) { diff --git a/src/friendlist.h b/src/friendlist.h index 26c9106..d316838 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -7,5 +7,6 @@ ToxWindow new_friendlist(); int friendlist_onFriendAdded(Tox *m, int num); void disable_chatwin(int f_num); +int get_friendnum(uint8_t *name); #endif /* end of include guard: FRIENDLIST_H_53I41IM */ diff --git a/src/prompt.c b/src/prompt.c index c470663..53b297c 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -340,8 +340,8 @@ void cmd_help(ToxWindow *self, Tox *m, int argc, char **argv) wprintw(self->window, " status : Set your status with optional note\n"); wprintw(self->window, " note : Set a personal note\n"); wprintw(self->window, " nick : Set your nickname\n"); - wprintw(self->window, " join : Join a group chat (must be invited)\n"); - wprintw(self->window, " invite : Invite friend f to groupchat g\n"); + wprintw(self->window, " join : Join a group chat\n"); + wprintw(self->window, " invite : Invite friend to a groupchat\n"); wprintw(self->window, " groupchat : Create a group chat\n"); wprintw(self->window, " myid : Print your ID\n"); wprintw(self->window, " quit/exit : Exit Toxic\n"); @@ -368,15 +368,25 @@ void cmd_invite(ToxWindow *self, Tox *m, int argc, char **argv) return; } - int friendnum = atoi(argv[1]); + uint8_t *friendname = argv[1]; int groupnum = atoi(argv[2]); + if (friendname[0] == '\"') + friendname[strlen(++friendname)-1] = L'\0'; + + int friendnum = get_friendnum(friendname); + + if (friendnum == -1) { + wprintw(self->window, "Friend '%s' not found.\n", friendname); + return; + } + if (tox_invite_friend(m, friendnum, groupnum) == -1) { wprintw(self->window, "Failed to invite friend.\n"); return; } - wprintw(self->window, "Invited friend %d to group chat %d.\n", friendnum, groupnum); + wprintw(self->window, "Invited friend %s to group chat %d.\n", friendname, groupnum); } void cmd_join(ToxWindow *self, Tox *m, int argc, char **argv) @@ -779,7 +789,16 @@ void prompt_onFriendRequest(ToxWindow *self, uint8_t *key, uint8_t *data, uint16 void prompt_onGroupInvite(ToxWindow *self, Tox *m, int friendnumber, uint8_t *group_pub_key) { - wprintw(self->window, "\nGroup chat invite from: %d\n", friendnumber); + if (friendnumber < 0) + return; + + uint8_t name[TOX_MAX_NAME_LENGTH] = {'\0'}; + + if (tox_getname(m, friendnumber, name) == -1) + return; + + name[TOXIC_MAX_NAME_LENGTH] = '\0'; /* enforce client max name length */ + wprintw(self->window, "\nGroup chat invite from %s.\n", name); int ngc = get_num_groupchats(); From 4e5e3be95ffadfa1b1a6ff9a98fad40adcbd96d3 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 17 Sep 2013 19:15:29 -0400 Subject: [PATCH 7/9] misplaced comment --- src/friendlist.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/friendlist.c b/src/friendlist.c index ce4b914..8f722d5 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -256,8 +256,7 @@ void disable_chatwin(int f_num) friends[f_num].chatwin = -1; } -/* Returns the respective friend number of name. Returns -1 on no match - This should be used instead of tox_getname for retrieving */ +/* Returns the respective friend number of name. Returns -1 on no match */ int get_friendnum(uint8_t *name) { int i; From 49b78c9fd4c5b0fb923896f199d5d1f0309709d7 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 17 Sep 2013 20:54:25 -0400 Subject: [PATCH 8/9] api update fixes --- src/groupchat.c | 9 +++++---- src/toxic_windows.h | 10 +++++----- src/windows.c | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/groupchat.c b/src/groupchat.c index e8317e6..1c43135 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -71,7 +71,7 @@ static void close_groupchatwin(Tox *m, int groupnum) group_chat_index = i; } -static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, uint8_t *msg, uint16_t len) +static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, int peernum, uint8_t *msg, uint16_t len) { if (self->num != groupnum) return; @@ -79,14 +79,15 @@ static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, uint ChatContext *ctx = (ChatContext *) self->chatwin; struct tm *timeinfo = get_time(); - // uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'}; - // tox_getname(m, num, nick); + uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'}; + tox_group_peername(m, groupnum, peernum, nick); + nick[TOXIC_MAX_NAME_LENGTH] = '\0'; /* enforce client max name length */ wattron(ctx->history, COLOR_PAIR(CYAN)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattroff(ctx->history, COLOR_PAIR(CYAN)); wattron(ctx->history, COLOR_PAIR(4)); - wprintw(ctx->history, "Toxicle: "); + wprintw(ctx->history, "%s: ", nick); wattroff(ctx->history, COLOR_PAIR(4)); wprintw(ctx->history, "%s\n", msg); diff --git a/src/toxic_windows.h b/src/toxic_windows.h index e0c8e4e..cc29a2d 100644 --- a/src/toxic_windows.h +++ b/src/toxic_windows.h @@ -19,11 +19,11 @@ #define MAX_WINDOWS_NUM 32 #define MAX_FRIENDS_NUM 100 -#define MAX_GROUPCHAT_NUM 30 +#define MAX_GROUPCHAT_NUM MAX_WINDOWS_NUM - N_DEFAULT_WINS #define MAX_STR_SIZE 256 #define KEY_SIZE_BYTES 32 -#define TOXIC_MAX_NAME_LENGTH 30 /* Not to be confused with TOX_MAX_NAME_LENGTH */ -#define N_DEFAULT_WINS 3 /* number of permanent default windows */ +#define TOXIC_MAX_NAME_LENGTH 30 /* Must be <= TOX_MAX_NAME_LENGTH */ +#define N_DEFAULT_WINS 2 /* number of permanent default windows */ #define UNKNOWN_NAME "Unknown" #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 @@ -52,7 +52,7 @@ struct ToxWindow_ { void(*onStatusChange)(ToxWindow *, Tox *, int, TOX_USERSTATUS); void(*onStatusMessageChange)(ToxWindow *, int, uint8_t *, uint16_t); void(*onAction)(ToxWindow *, Tox *, int, uint8_t *, uint16_t); - void(*onGroupMessage)(ToxWindow *, Tox *, int, uint8_t *, uint16_t); + void(*onGroupMessage)(ToxWindow *, Tox *, int, int, uint8_t *, uint16_t); void(*onGroupInvite)(ToxWindow *, Tox *, int, uint8_t *); char name[TOX_MAX_NAME_LENGTH]; @@ -97,7 +97,7 @@ void on_nickchange(Tox *m, int friendnumber, uint8_t *string, uint16_t length, v void on_statuschange(Tox *m, int friendnumber, TOX_USERSTATUS status, void *userdata); void on_statusmessagechange(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata); void on_friendadded(Tox *m, int friendnumber); -void on_groupmessage(Tox *m, int groupnumber, uint8_t *message, uint16_t length, void *userdata); +void on_groupmessage(Tox *m, int groupnumber, int peernumber, uint8_t *message, uint16_t length, void *userdata); void on_groupinvite(Tox *m, int friendnumber, uint8_t *group_pub_key, void *userdata); ToxWindow *init_windows(); void draw_active_window(Tox *m); diff --git a/src/windows.c b/src/windows.c index 60d5d7c..754915f 100644 --- a/src/windows.c +++ b/src/windows.c @@ -125,13 +125,13 @@ void on_friendadded(Tox *m, int friendnumber) wprintw(prompt->window, "\nCould not store Tox data\n"); } -void on_groupmessage(Tox *m, int groupnumber, uint8_t *message, uint16_t length, void *userdata) +void on_groupmessage(Tox *m, int groupnumber, int peernumber, uint8_t *message, uint16_t length, void *userdata) { int i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onGroupMessage != NULL) - windows[i].onGroupMessage(&windows[i], m, groupnumber, message, length); + windows[i].onGroupMessage(&windows[i], m, groupnumber, peernumber, message, length); } } From b4512811ba9780dd83f5bff435920ee99dce51fb Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 18 Sep 2013 17:30:35 -0400 Subject: [PATCH 9/9] fixed prompt scroll bugs and statusbar struct issues --- src/chat.c | 2 +- src/friendlist.c | 2 +- src/prompt.c | 43 +++++++++++++++++++++++-------------------- src/prompt.h | 4 ++++ src/toxic_windows.h | 1 + 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/chat.c b/src/chat.c index a7760d9..67c3a86 100644 --- a/src/chat.c +++ b/src/chat.c @@ -314,7 +314,7 @@ static void execute(ToxWindow *self, ChatContext *ctx, StatusBar *statusbar, Tox } tox_setname(m, nick, len+1); - prompt_update_nick(self->prompt, nick); + prompt_update_nick(self->prompt, nick, len+1); wprintw(ctx->history, "Nickname set to: %s\n", nick); } diff --git a/src/friendlist.c b/src/friendlist.c index 8f722d5..c8c6377 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -21,7 +21,7 @@ extern ToxWindow *prompt; typedef struct { uint8_t name[TOX_MAX_NAME_LENGTH]; - uint8_t namelength; + uint16_t namelength; uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH]; uint16_t statusmsg_len; int num; diff --git a/src/prompt.c b/src/prompt.c index 53b297c..622abb6 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -65,17 +65,19 @@ static struct { }; /* Updates own nick in prompt statusbar */ -void prompt_update_nick(ToxWindow *prompt, uint8_t *nick) +void prompt_update_nick(ToxWindow *prompt, uint8_t *nick, uint16_t len) { StatusBar *statusbar = (StatusBar *) prompt->stb; snprintf(statusbar->nick, sizeof(statusbar->nick), "%s", nick); + statusbar->nick_len = len; } /* Updates own statusmessage in prompt statusbar */ -void prompt_update_statusmessage(ToxWindow *prompt, uint8_t *statusmsg) +void prompt_update_statusmessage(ToxWindow *prompt, uint8_t *statusmsg, uint16_t len) { StatusBar *statusbar = (StatusBar *) prompt->stb; snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg); + statusbar->statusmsg_len = len; } /* Updates own status in prompt statusbar */ @@ -170,13 +172,6 @@ void cmd_add(ToxWindow *self, Tox *m, int argc, char **argv) return; } - uint8_t id_bin[TOX_FRIEND_ADDRESS_SIZE]; - char xx[3]; - uint32_t x; - uint8_t *msg; - size_t i; - int num; - char *id = argv[1]; if (id == NULL) { @@ -184,6 +179,8 @@ void cmd_add(ToxWindow *self, Tox *m, int argc, char **argv) return; } + uint8_t *msg; + if (argc == 2) { msg = argv[2]; @@ -207,6 +204,11 @@ void cmd_add(ToxWindow *self, Tox *m, int argc, char **argv) return; } + size_t i; + char xx[3]; + uint32_t x; + uint8_t id_bin[TOX_FRIEND_ADDRESS_SIZE]; + for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) { xx[0] = id[2 * i]; xx[1] = id[2 * i + 1]; @@ -224,7 +226,7 @@ void cmd_add(ToxWindow *self, Tox *m, int argc, char **argv) id[i] = toupper(id[i]); } - num = tox_addfriend(m, id_bin, msg, strlen(msg) + 1); + int num = tox_addfriend(m, id_bin, msg, strlen(msg) + 1); switch (num) { case TOX_FAERR_TOOLONG: @@ -341,7 +343,7 @@ void cmd_help(ToxWindow *self, Tox *m, int argc, char **argv) wprintw(self->window, " note : Set a personal note\n"); wprintw(self->window, " nick : Set your nickname\n"); wprintw(self->window, " join : Join a group chat\n"); - wprintw(self->window, " invite : Invite friend to a groupchat\n"); + wprintw(self->window, " invite : Invite friend to a groupchat\n"); wprintw(self->window, " groupchat : Create a group chat\n"); wprintw(self->window, " myid : Print your ID\n"); wprintw(self->window, " quit/exit : Exit Toxic\n"); @@ -492,7 +494,7 @@ void cmd_nick(ToxWindow *self, Tox *m, int argc, char **argv) } tox_setname(m, nick, len+1); - prompt_update_nick(self, nick); + prompt_update_nick(self, nick, len+1); store_data(m, DATA_FILE); } @@ -545,8 +547,9 @@ void cmd_status(ToxWindow *self, Tox *m, int argc, char **argv) if (msg != NULL) { msg[strlen(++msg)-1] = L'\0'; /* remove opening and closing quotes */ - tox_set_statusmessage(m, msg, strlen(msg) + 1); - prompt_update_statusmessage(self, msg); + uint16_t len = strlen(msg) + 1; + tox_set_statusmessage(m, msg, len); + prompt_update_statusmessage(self, msg, len); } } @@ -570,9 +573,9 @@ void cmd_note(ToxWindow *self, Tox *m, int argc, char **argv) } msg[strlen(++msg)-1] = L'\0'; - - tox_set_statusmessage(m, msg, strlen(msg) + 1); - prompt_update_statusmessage(self, msg); + uint16_t len = strlen(msg) + 1; + tox_set_statusmessage(m, msg, len); + prompt_update_statusmessage(self, msg, len); } static void execute(ToxWindow *self, Tox *m, char *u_cmd) @@ -663,14 +666,14 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key) /* Add printable characters to line */ if (isprint(key)) { if (prompt_buf_pos == (sizeof(prompt_buf) - 1)) { - wprintw(self->window, "\nToo Long.\n"); - prompt_buf_pos = 0; - prompt_buf[0] = 0; + return; } else if (!(prompt_buf_pos == 0) && (prompt_buf_pos < COLS) && (prompt_buf_pos % (COLS - 3) == 0)) { + wprintw(self->window, "\n"); prompt_buf[prompt_buf_pos++] = '\n'; } else if (!(prompt_buf_pos == 0) && (prompt_buf_pos > COLS) && ((prompt_buf_pos - (COLS - 3)) % (COLS) == 0)) { + wprintw(self->window, "\n"); prompt_buf[prompt_buf_pos++] = '\n'; } diff --git a/src/prompt.h b/src/prompt.h index c4d51df..6f56b25 100644 --- a/src/prompt.h +++ b/src/prompt.h @@ -7,5 +7,9 @@ ToxWindow new_prompt(); int add_req(uint8_t *public_key); unsigned char *hex_string_to_bin(char hex_string[]); void prompt_init_statusbar(ToxWindow *self, Tox *m); +void prompt_update_nick(ToxWindow *prompt, uint8_t *nick, uint16_t len); +void prompt_update_statusmessage(ToxWindow *prompt, uint8_t *statusmsg, uint16_t len); +void prompt_update_status(ToxWindow *prompt, TOX_USERSTATUS status); +void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected); #endif /* end of include guard: PROMPT_H_UZYGWFFL */ diff --git a/src/toxic_windows.h b/src/toxic_windows.h index cc29a2d..ccd1d2c 100644 --- a/src/toxic_windows.h +++ b/src/toxic_windows.h @@ -73,6 +73,7 @@ typedef struct { uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH]; uint16_t statusmsg_len; uint8_t nick[TOX_MAX_NAME_LENGTH]; + uint16_t nick_len; TOX_USERSTATUS status; bool is_online; } StatusBar;