diff --git a/src/chat.c b/src/chat.c index 5a4e283..5b99f70 100644 --- a/src/chat.c +++ b/src/chat.c @@ -52,8 +52,8 @@ static void chat_onMessage(ToxWindow *self, Tox *m, int num, uint8_t *msg, uint1 return; tox_getname(m, num, (uint8_t *) &nick); - msg[len - 1] = '\0'; - nick[TOX_MAX_NAME_LENGTH - 1] = '\0'; + msg[len-1] = '\0'; + nick[TOX_MAX_NAME_LENGTH-1] = '\0'; wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); @@ -67,6 +67,24 @@ static void chat_onMessage(ToxWindow *self, Tox *m, int num, uint8_t *msg, uint1 beep(); } +void chat_onConnectionChange(ToxWindow *self, Tox *m, int num, uint8_t status) +{ + ChatContext *ctx = (ChatContext *) self->x; + struct tm *timeinfo = get_time(); + + if (ctx->friendnum != num) + return; + + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); + + if (status == 1) + wprintw(ctx->history, "* Chat partner has come online\n"); + else + wprintw(ctx->history, "* Chat partner went offline\n"); +} + static void chat_onAction(ToxWindow *self, Tox *m, int num, uint8_t *action, uint16_t len) { ChatContext *ctx = (ChatContext *) self->x; @@ -110,7 +128,7 @@ static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t wprintw(ctx->history, "* Chat partner changed nick to '%s'\n", nick); } -static void chat_onStatusMessageChange(ToxWindow *self, int num, uint8_t *status, uint16_t len) +static void chat_onStatusChange(ToxWindow *self, Tox *m, int num, TOX_USERSTATUS status) { ChatContext *ctx = (ChatContext *) self->x; struct tm *timeinfo = get_time(); @@ -122,9 +140,47 @@ static void chat_onStatusMessageChange(ToxWindow *self, int num, uint8_t *status wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattroff(ctx->history, COLOR_PAIR(2)); + switch(status) { + + case TOX_USERSTATUS_NONE: + wprintw(ctx->history, "* Chat partner set status to "); + wattron(ctx->history, COLOR_PAIR(1)); + wprintw(ctx->history, "[Online]\n"); + wattroff(ctx->history, COLOR_PAIR(1)); + break; + + case TOX_USERSTATUS_BUSY: + wprintw(ctx->history, "* Chat partner set status to "); + wattron(ctx->history, COLOR_PAIR(3)); + wprintw(ctx->history, "[Busy]\n"); + wattroff(ctx->history, COLOR_PAIR(3)); + break; + + case TOX_USERSTATUS_AWAY: + wprintw(ctx->history, "* Chat partner set status to "); + wattron(ctx->history, COLOR_PAIR(5)); + wprintw(ctx->history, "[Away]\n"); + wattroff(ctx->history, COLOR_PAIR(5)); + break; + } +} + +static void chat_onStatusMessageChange(ToxWindow *self, int num, uint8_t *status, uint16_t len) +{ + ChatContext *ctx = (ChatContext *) self->x; + struct tm *timeinfo = get_time(); + + if (ctx->friendnum != num) + return; + status[len - 1] = '\0'; - wprintw(ctx->history, "* Chat partner changed personal note to: %s\n", status); + if (strncmp(status, "Online", strlen("status"))) { /* Ignore default "Online" message */ + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "* Chat partner changed personal note to: %s\n", status); + } } /* check that the string has one non-space character */ @@ -322,17 +378,26 @@ void execute(ToxWindow *self, ChatContext *ctx, Tox *m, char *cmd) if (!strncmp(status, "online", strlen("online"))) { status_kind = TOX_USERSTATUS_NONE; - status_text = "Online"; + wprintw(ctx->history, "Status set to "); + wattron(ctx->history, COLOR_PAIR(1)); + wprintw(ctx->history, "[Online]\n"); + wattroff(ctx->history, COLOR_PAIR(1)); } else if (!strncmp(status, "away", strlen("away"))) { status_kind = TOX_USERSTATUS_AWAY; - status_text = "Away"; + wprintw(ctx->history, "Status set to "); + wattron(ctx->history, COLOR_PAIR(5)); + wprintw(ctx->history, "[Away]\n"); + wattroff(ctx->history, COLOR_PAIR(5)); } else if (!strncmp(status, "busy", strlen("busy"))) { status_kind = TOX_USERSTATUS_BUSY; - status_text = "Busy"; + wprintw(ctx->history, "Status set to "); + wattron(ctx->history, COLOR_PAIR(3)); + wprintw(ctx->history, "[Busy]\n"); + wattroff(ctx->history, COLOR_PAIR(3)); } else { @@ -340,7 +405,6 @@ void execute(ToxWindow *self, ChatContext *ctx, Tox *m, char *cmd) return; } - wprintw(ctx->history, "Status set to: %s\n", status_text); tox_set_userstatus(m, status_kind); msg = strchr(status, ' '); @@ -442,7 +506,9 @@ ToxWindow new_chat(Tox *m, int friendnum) ret.onDraw = &chat_onDraw; ret.onInit = &chat_onInit; ret.onMessage = &chat_onMessage; + ret.onConnectionChange = &chat_onConnectionChange; ret.onNickChange = &chat_onNickChange; + ret.onStatusChange = &chat_onStatusChange; ret.onStatusMessageChange = &chat_onStatusMessageChange; ret.onAction = &chat_onAction; diff --git a/src/friendlist.c b/src/friendlist.c index 9073420..a5befb4 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -24,7 +24,9 @@ typedef struct { uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH]; int num; int chatwin; - bool active; + bool active; + bool online; + TOX_USERSTATUS status; } friend_t; static friend_t friends[MAX_FRIENDS_NUM]; @@ -34,25 +36,44 @@ static int num_selected = 0; void friendlist_onMessage(ToxWindow *self, Tox *m, int num, uint8_t *str, uint16_t len) { - if (num >= num_friends) + if (num < 0 || num >= num_friends) return; if (friends[num].chatwin == -1) friends[num].chatwin = add_window(m, new_chat(m, friends[num].num)); } +void friendlist_onConnectionChange(ToxWindow *self, Tox *m, int num, uint8_t status) +{ + if (num < 0 || num >= num_friends) + return; + + if (status == 1) + friends[num].online = true; + else + friends[num].online = false; +} + void friendlist_onNickChange(ToxWindow *self, int num, uint8_t *str, uint16_t len) { - if (len >= TOX_MAX_NAME_LENGTH || num >= num_friends) + if (len >= TOX_MAX_NAME_LENGTH || num < 0 || num >= num_friends) return; memcpy((char *) &friends[num].name, (char *) str, len); friends[num].name[len] = 0; } +void friendlist_onStatusChange(ToxWindow *self, Tox *m, int num, TOX_USERSTATUS status) +{ + if (num < 0 || num >= num_friends) + return; + + friends[num].status = status; +} + void friendlist_onStatusMessageChange(ToxWindow *self, int num, uint8_t *str, uint16_t len) { - if (len >= TOX_MAX_STATUSMESSAGE_LENGTH || num >= num_friends) + if (len >= TOX_MAX_STATUSMESSAGE_LENGTH || num < 0 || num >= num_friends) return; memcpy((char *) &friends[num].statusmsg, (char *) str, len); @@ -71,6 +92,8 @@ int friendlist_onFriendAdded(Tox *m, int num) friends[i].num = num; friends[i].active = true; friends[i].chatwin = -1; + friends[i].online = false; + friends[i].status = TOX_USERSTATUS_INVALID; if (tox_getname(m, num, friends[i].name) != 0 || friends[i].name[0] == '\0') strcpy((char *) friends[i].name, "unknown"); @@ -172,8 +195,8 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) else wprintw(self->window, " "); - if (tox_friendstatus(m, friends[i].num) == TOX_FRIEND_ONLINE) { - TOX_USERSTATUS status = tox_get_userstatus(m, friends[i].num); + if (friends[i].online) { + TOX_USERSTATUS status = friends[i].status; int colour = 7; /* Invalid or other errors default to black */ switch(status) { @@ -203,7 +226,7 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m) } } } - + wrefresh(self->window); } @@ -226,8 +249,10 @@ ToxWindow new_friendlist() ret.onDraw = &friendlist_onDraw; ret.onInit = &friendlist_onInit; ret.onMessage = &friendlist_onMessage; + ret.onConnectionChange = &friendlist_onConnectionChange; ret.onAction = &friendlist_onMessage; // Action has identical behaviour to message ret.onNickChange = &friendlist_onNickChange; + ret.onStatusChange = &friendlist_onStatusChange; ret.onStatusMessageChange = &friendlist_onStatusMessageChange; strcpy(ret.title, "[friends]"); diff --git a/src/main.c b/src/main.c index eaf3618..77bcee2 100644 --- a/src/main.c +++ b/src/main.c @@ -91,9 +91,11 @@ static Tox *init_tox() Tox *m = tox_new(); /* Callbacks */ + tox_callback_connectionstatus(m, on_connectionchange, NULL); tox_callback_friendrequest(m, on_request, NULL); tox_callback_friendmessage(m, on_message, NULL); tox_callback_namechange(m, on_nickchange, NULL); + tox_callback_userstatus(m, on_statuschange, NULL); tox_callback_statusmessage(m, on_statusmessagechange, NULL); tox_callback_action(m, on_action, NULL); #ifdef __linux__ diff --git a/src/prompt.c b/src/prompt.c index 2865654..cc62a1d 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -314,6 +314,7 @@ void cmd_nick(ToxWindow *self, Tox *m, int argc, char **argv) } nick = argv[1]; + nick[strlen(++nick)-1] = L'\0'; tox_setname(m, (uint8_t *) nick, strlen(nick) + 1); wprintw(self->window, "Nickname set to: %s\n", nick); diff --git a/src/toxic_windows.h b/src/toxic_windows.h index ecff396..ec188cb 100644 --- a/src/toxic_windows.h +++ b/src/toxic_windows.h @@ -31,8 +31,10 @@ struct ToxWindow_ { void(*onDraw)(ToxWindow *, Tox *); void(*onInit)(ToxWindow *, Tox *); void(*onFriendRequest)(ToxWindow *, uint8_t *, uint8_t *, uint16_t); + void(*onConnectionChange)(ToxWindow *, Tox *, int, uint8_t); void(*onMessage)(ToxWindow *, Tox *, int, uint8_t *, uint16_t); void(*onNickChange)(ToxWindow *, int, uint8_t *, uint16_t); + void(*onStatusChange)(ToxWindow *, Tox *, int, TOX_USERSTATUS); void(*onStatusMessageChange)(ToxWindow *, int, uint8_t *, uint16_t); void(*onAction)(ToxWindow *, Tox *, int, uint8_t *, uint16_t); char title[256]; @@ -44,9 +46,11 @@ struct ToxWindow_ { }; 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); void on_action(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata); void on_nickchange(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata); +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); ToxWindow *init_windows(); diff --git a/src/windows.c b/src/windows.c index 1e28667..71feecd 100644 --- a/src/windows.c +++ b/src/windows.c @@ -17,6 +17,8 @@ static ToxWindow *active_window; static ToxWindow *prompt; static Tox *m; +#define unknown_name "Unknown" + /* CALLBACKS START */ void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata) { @@ -38,6 +40,27 @@ void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void *userd } } +void on_connectionchange(Tox *m, int friendnumber, uint8_t status, void *userdata) +{ + uint8_t nick[TOX_MAX_NAME_LENGTH] = {0}; + tox_getname(m, friendnumber, (uint8_t *) &nick); + + if (!nick[0]) + snprintf(nick, sizeof(nick), "%s", unknown_name); + + if (status == 1) + wprintw(prompt->window, "\n%s has come online\n", nick, friendnumber); + else + wprintw(prompt->window, "\n%s went offline\n", nick, friendnumber); + + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onConnectionChange != NULL) + windows[i].onConnectionChange(&windows[i], m, friendnumber, status); + } +} + void on_message(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata) { int i; @@ -60,7 +83,6 @@ void on_action(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void void on_nickchange(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata) { - wprintw(prompt->window, "\n(nick change) %d: %s\n", friendnumber, string); int i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { @@ -71,7 +93,17 @@ void on_nickchange(Tox *m, int friendnumber, uint8_t *string, uint16_t length, v void on_statusmessagechange(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata) { - wprintw(prompt->window, "\n(note change) %d: %s\n", friendnumber, string); + /* Don't show default "Online" status message */ + if (strncmp(string, "Online", strlen(string))) { + uint8_t nick[TOX_MAX_NAME_LENGTH] = {0}; + tox_getname(m, friendnumber, (uint8_t *) &nick); + + if (!nick[0]) + snprintf(nick, sizeof(nick), "%s", unknown_name); + + wprintw(prompt->window, "\n%s set note to: %s\n", nick, string); + } + int i; for (i = 0; i < MAX_WINDOWS_NUM; ++i) { @@ -80,6 +112,42 @@ void on_statusmessagechange(Tox *m, int friendnumber, uint8_t *string, uint16_t } } +void on_statuschange(Tox *m, int friendnumber, TOX_USERSTATUS status, void *userdata) +{ + uint8_t nick[TOX_MAX_NAME_LENGTH] = {0}; + tox_getname(m, friendnumber, (uint8_t *) &nick); + + if (!nick[0]) + snprintf(nick, sizeof(nick), "%s", unknown_name); + + switch(status) { + case TOX_USERSTATUS_NONE: + /* Disabled because it spams a second messages when user comes online */ + break; + + case TOX_USERSTATUS_BUSY: + wprintw(prompt->window, "\n%s set status to ", nick); + wattron(prompt->window, COLOR_PAIR(3)); + wprintw(prompt->window, "[Busy]\n"); + wattroff(prompt->window, COLOR_PAIR(3)); + break; + + case TOX_USERSTATUS_AWAY: + wprintw(prompt->window, "\n%s set status to ", nick); + wattron(prompt->window, COLOR_PAIR(5)); + wprintw(prompt->window, "[Away]\n"); + wattroff(prompt->window, COLOR_PAIR(5)); + break; + } + + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onStatusChange != NULL) + windows[i].onStatusChange(&windows[i], m, friendnumber, status); + } +} + void on_friendadded(Tox *m, int friendnumber) { friendlist_onFriendAdded(m, friendnumber);