mirror of
				https://github.com/Tha14/toxic.git
				synced 2025-11-01 15:26:51 +01:00 
			
		
		
		
	added groupchats
This commit is contained in:
		
							
								
								
									
										47
									
								
								src/chat.c
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								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; | ||||
| } | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
							
								
								
									
										233
									
								
								src/groupchat.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								src/groupchat.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,233 @@ | ||||
| /* | ||||
|  * Toxic -- Tox Curses Client | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #include "config.h" | ||||
| #endif | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
| #include <ctype.h> | ||||
| #include <time.h> | ||||
|  | ||||
| #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; | ||||
| } | ||||
							
								
								
									
										6
									
								
								src/groupchat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/groupchat.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| /* | ||||
|  * Toxic -- Tox Curses Client | ||||
|  */ | ||||
|  | ||||
| int init_groupchat_win(ToxWindow *prompt, Tox *m); | ||||
| int get_num_groupchats(void); | ||||
| @@ -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) | ||||
|   | ||||
							
								
								
									
										179
									
								
								src/prompt.c
									
									
									
									
									
								
							
							
						
						
									
										179
									
								
								src/prompt.c
									
									
									
									
									
								
							| @@ -11,11 +11,15 @@ | ||||
| #include <ctype.h> | ||||
|  | ||||
| #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)); | ||||
|   | ||||
| @@ -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 <curses.h> | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user