mirror of
				https://github.com/Tha14/toxic.git
				synced 2025-11-04 16:16:52 +01:00 
			
		
		
		
	Compare commits
	
		
			94 Commits
		
	
	
		
			add_fix
			...
			new_groupc
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					9dfa455561 | ||
| 
						 | 
					372fcb0a67 | ||
| 
						 | 
					c760ffc563 | ||
| 
						 | 
					c6f2a9cb59 | ||
| 
						 | 
					76bfa34c45 | ||
| 
						 | 
					43d9623877 | ||
| 
						 | 
					60b431459c | ||
| 
						 | 
					6e7b0a5430 | ||
| 
						 | 
					86b36d7a13 | ||
| 
						 | 
					7e122ceec6 | ||
| 
						 | 
					fe0eba9107 | ||
| 
						 | 
					1d1c051a44 | ||
| 
						 | 
					fbd22003a8 | ||
| 
						 | 
					3cfda32b5e | ||
| 
						 | 
					9b1592b335 | ||
| 
						 | 
					fbf50ecc8c | ||
| 
						 | 
					7025a33097 | ||
| 
						 | 
					171024428b | ||
| 
						 | 
					2e4c86be4b | ||
| 
						 | 
					97d5fb84fc | ||
| 
						 | 
					b2c512687a | ||
| 
						 | 
					8526d4d77e | ||
| 
						 | 
					ed1429afa1 | ||
| 
						 | 
					1270f34596 | ||
| 
						 | 
					6eef188d3c | ||
| 
						 | 
					8e23ce1b83 | ||
| 
						 | 
					15ef50e46c | ||
| 
						 | 
					0597152352 | ||
| 
						 | 
					23bb980173 | ||
| 
						 | 
					a846c38695 | ||
| 
						 | 
					1f7f4490b2 | ||
| 
						 | 
					40b220c821 | ||
| 
						 | 
					cb4a631df0 | ||
| 
						 | 
					35718db46f | ||
| 
						 | 
					1ba0891f71 | ||
| 
						 | 
					b36ada0f5b | ||
| 
						 | 
					9cd2158c72 | ||
| 
						 | 
					928134da7a | ||
| 
						 | 
					52a3367b5e | ||
| 
						 | 
					7e7087e94e | ||
| 
						 | 
					9cd8afe90a | ||
| 
						 | 
					526bd02189 | ||
| 
						 | 
					3826fd793d | ||
| 
						 | 
					a6d7e9b839 | ||
| 
						 | 
					29d0384a90 | ||
| 
						 | 
					0481f43746 | ||
| 
						 | 
					f021908f8b | ||
| 
						 | 
					f82d58bbfc | ||
| 
						 | 
					9385f1145f | ||
| 
						 | 
					2acd99b04c | ||
| 
						 | 
					6cd7fb9e5b | ||
| 
						 | 
					540bf4a5c4 | ||
| 
						 | 
					a360afe08a | ||
| 
						 | 
					b66a1f6ba1 | ||
| 
						 | 
					b66932fcec | ||
| 
						 | 
					de38df32c2 | ||
| 
						 | 
					bdfbda7cda | ||
| 
						 | 
					0c49ab392d | ||
| 
						 | 
					b2c0753fdf | ||
| 
						 | 
					c97095be68 | ||
| 
						 | 
					c2b9967691 | ||
| 
						 | 
					ee074f334e | ||
| 
						 | 
					23429d8da4 | ||
| 
						 | 
					e34ac70a72 | ||
| 
						 | 
					77d45334ac | ||
| 
						 | 
					88719c4ccc | ||
| 
						 | 
					386c5a8fa5 | ||
| 
						 | 
					5caa9bed51 | ||
| 
						 | 
					59b90b1328 | ||
| 
						 | 
					05c05868c6 | ||
| 
						 | 
					88d6d907d8 | ||
| 
						 | 
					6cc8fdf215 | ||
| 
						 | 
					02a0cac85a | ||
| 
						 | 
					0976804fdf | ||
| 
						 | 
					f8ff5df2f3 | ||
| 
						 | 
					22acba5aa8 | ||
| 
						 | 
					2bcce234a8 | ||
| 
						 | 
					5859763f04 | ||
| 
						 | 
					4cc0805036 | ||
| 
						 | 
					830ddb21b5 | ||
| 
						 | 
					b31bd93e7d | ||
| 
						 | 
					a89e6b2cdc | ||
| 
						 | 
					dd3ea3dab5 | ||
| 
						 | 
					c3179b3b22 | ||
| 
						 | 
					5c98c1c51e | ||
| 
						 | 
					ff69cdd253 | ||
| 
						 | 
					38e55d55b3 | ||
| 
						 | 
					6f45085d86 | ||
| 
						 | 
					0348f81ba8 | ||
| 
						 | 
					7ee858110c | ||
| 
						 | 
					89637e7d2f | ||
| 
						 | 
					ff3da5f657 | ||
| 
						 | 
					b3ab0bde05 | ||
| 
						 | 
					26dda8dbf9 | 
@@ -3,7 +3,7 @@
 | 
				
			|||||||
       src="https://scan.coverity.com/projects/4975/badge.svg"/>
 | 
					       src="https://scan.coverity.com/projects/4975/badge.svg"/>
 | 
				
			||||||
</a>
 | 
					</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Toxic is a [Tox](https://tox.chat)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/irungentoo/toxcore), and is now available as a standalone application.
 | 
					Toxic is a [Tox](https://tox.im)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/irungentoo/toxcore), and is now available as a standalone application.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[](https://i.imgur.com/san99Z2.png)
 | 
					[](https://i.imgur.com/san99Z2.png)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,5 @@ BINDIR = $(PREFIX)/bin
 | 
				
			|||||||
DATADIR = $(PREFIX)/share/toxic
 | 
					DATADIR = $(PREFIX)/share/toxic
 | 
				
			||||||
MANDIR = $(PREFIX)/share/man
 | 
					MANDIR = $(PREFIX)/share/man
 | 
				
			||||||
APPDIR = $(PREFIX)/share/applications
 | 
					APPDIR = $(PREFIX)/share/applications
 | 
				
			||||||
 | 
					 | 
				
			||||||
# Platform tools
 | 
					# Platform tools
 | 
				
			||||||
PKG_CONFIG = pkg-config
 | 
					PKG_CONFIG = pkg-config
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -148,6 +148,11 @@ Indicator for alert messages\&.
 | 
				
			|||||||
Indicator for normal messages\&.
 | 
					Indicator for normal messages\&.
 | 
				
			||||||
.RE
 | 
					.RE
 | 
				
			||||||
.PP
 | 
					.PP
 | 
				
			||||||
 | 
					\fBline_special\fR
 | 
				
			||||||
 | 
					.RS 4
 | 
				
			||||||
 | 
					Indicator for special messages\&.
 | 
				
			||||||
 | 
					.RE
 | 
				
			||||||
 | 
					.PP
 | 
				
			||||||
\fBmplex_away\fR
 | 
					\fBmplex_away\fR
 | 
				
			||||||
.RS 4
 | 
					.RS 4
 | 
				
			||||||
Set user status when attaching and detaching from GNU screen or tmux\&. true or false
 | 
					Set user status when attaching and detaching from GNU screen or tmux\&. true or false
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,6 +94,9 @@ OPTIONS
 | 
				
			|||||||
    *line_normal*;;
 | 
					    *line_normal*;;
 | 
				
			||||||
        Indicator for normal messages.
 | 
					        Indicator for normal messages.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *line_special*;;
 | 
				
			||||||
 | 
					        Indicator for special messages.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *mplex_away*;;
 | 
					    *mplex_away*;;
 | 
				
			||||||
        Set user status when attaching and detaching from GNU screen or tmux.
 | 
					        Set user status when attaching and detaching from GNU screen or tmux.
 | 
				
			||||||
        true or false
 | 
					        true or false
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,6 +62,9 @@ ui = {
 | 
				
			|||||||
  // Indicator for normal messages.
 | 
					  // Indicator for normal messages.
 | 
				
			||||||
  line_normal="---";
 | 
					  line_normal="---";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Indicator for special messages (currently only used for private group messages)
 | 
				
			||||||
 | 
					  line_special=">>>";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // true to change status based on screen/tmux attach/detach, false to disable
 | 
					  // true to change status based on screen/tmux attach/detach, false to disable
 | 
				
			||||||
  mplex_away=true;
 | 
					  mplex_away=true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								src/chat.c
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								src/chat.c
									
									
									
									
									
								
							@@ -66,9 +66,9 @@ static void kill_infobox(ToxWindow *self);
 | 
				
			|||||||
#endif  /* AUDIO */
 | 
					#endif  /* AUDIO */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef AUDIO
 | 
					#ifdef AUDIO
 | 
				
			||||||
#define AC_NUM_CHAT_COMMANDS 30
 | 
					#define AC_NUM_CHAT_COMMANDS 31
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#define AC_NUM_CHAT_COMMANDS 22
 | 
					#define AC_NUM_CHAT_COMMANDS 23
 | 
				
			||||||
#endif /* AUDIO */
 | 
					#endif /* AUDIO */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Array of chat command names used for tab completion. */
 | 
					/* Array of chat command names used for tab completion. */
 | 
				
			||||||
@@ -81,6 +81,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
 | 
				
			|||||||
    { "/close"      },
 | 
					    { "/close"      },
 | 
				
			||||||
    { "/connect"    },
 | 
					    { "/connect"    },
 | 
				
			||||||
    { "/exit"       },
 | 
					    { "/exit"       },
 | 
				
			||||||
 | 
					    { "/gaccept"    },
 | 
				
			||||||
    { "/group"      },
 | 
					    { "/group"      },
 | 
				
			||||||
    { "/help"       },
 | 
					    { "/help"       },
 | 
				
			||||||
    { "/invite"     },
 | 
					    { "/invite"     },
 | 
				
			||||||
@@ -609,25 +610,18 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
 | 
				
			|||||||
                   &self->active_box, self->name, "Incoming file: %s", filename );
 | 
					                   &self->active_box, self->name, "Incoming file: %s", filename );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, uint8_t type, const char *group_pub_key,
 | 
					static void chat_onGroupInvite(ToxWindow *self, Tox *m, uint32_t friendnumber, const char *invite_data,
 | 
				
			||||||
                               uint16_t length)
 | 
					                               size_t length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (self->num != friendnumber)
 | 
					    if (self->num != friendnumber)
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (Friends.list[friendnumber].group_invite.key != NULL)
 | 
					    if (Friends.list[friendnumber].group_invite.data)
 | 
				
			||||||
        free(Friends.list[friendnumber].group_invite.key);
 | 
					        free(Friends.list[friendnumber].group_invite.data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char *k = malloc(length);
 | 
					    Friends.list[friendnumber].group_invite.data = malloc(length * sizeof(uint8_t));
 | 
				
			||||||
 | 
					    memcpy(Friends.list[friendnumber].group_invite.data, invite_data, length);
 | 
				
			||||||
    if (k == NULL)
 | 
					 | 
				
			||||||
        exit_toxic_err("Failed in chat_onGroupInvite", FATALERR_MEMORY);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    memcpy(k, group_pub_key, length);
 | 
					 | 
				
			||||||
    Friends.list[friendnumber].group_invite.key = k;
 | 
					 | 
				
			||||||
    Friends.list[friendnumber].group_invite.pending = true;
 | 
					 | 
				
			||||||
    Friends.list[friendnumber].group_invite.length = length;
 | 
					    Friends.list[friendnumber].group_invite.length = length;
 | 
				
			||||||
    Friends.list[friendnumber].group_invite.type = type;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sound_notify(self, generic_message, NT_WNDALERT_2 | user_settings->bell_on_invite, NULL);
 | 
					    sound_notify(self, generic_message, NT_WNDALERT_2 | user_settings->bell_on_invite, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -640,7 +634,7 @@ static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, ui
 | 
				
			|||||||
        box_silent_notify(self, NT_WNDALERT_2 | NT_NOFOCUS, &self->active_box, name, "invites you to join group chat");
 | 
					        box_silent_notify(self, NT_WNDALERT_2 | NT_NOFOCUS, &self->active_box, name, "invites you to join group chat");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to a group chat.", name);
 | 
					    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to a group chat.", name);
 | 
				
			||||||
    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat.");
 | 
					    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/gaccept\" to join the chat.");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* AV Stuff */
 | 
					/* AV Stuff */
 | 
				
			||||||
@@ -1206,7 +1200,6 @@ ToxWindow new_chat(Tox *m, uint32_t friendnum)
 | 
				
			|||||||
    ret.onMessage = &chat_onMessage;
 | 
					    ret.onMessage = &chat_onMessage;
 | 
				
			||||||
    ret.onConnectionChange = &chat_onConnectionChange;
 | 
					    ret.onConnectionChange = &chat_onConnectionChange;
 | 
				
			||||||
    ret.onTypingChange = & chat_onTypingChange;
 | 
					    ret.onTypingChange = & chat_onTypingChange;
 | 
				
			||||||
    ret.onGroupInvite = &chat_onGroupInvite;
 | 
					 | 
				
			||||||
    ret.onNickChange = &chat_onNickChange;
 | 
					    ret.onNickChange = &chat_onNickChange;
 | 
				
			||||||
    ret.onStatusChange = &chat_onStatusChange;
 | 
					    ret.onStatusChange = &chat_onStatusChange;
 | 
				
			||||||
    ret.onStatusMessageChange = &chat_onStatusMessageChange;
 | 
					    ret.onStatusMessageChange = &chat_onStatusMessageChange;
 | 
				
			||||||
@@ -1215,6 +1208,7 @@ ToxWindow new_chat(Tox *m, uint32_t friendnum)
 | 
				
			|||||||
    ret.onFileControl = &chat_onFileControl;
 | 
					    ret.onFileControl = &chat_onFileControl;
 | 
				
			||||||
    ret.onFileRecv = &chat_onFileRecv;
 | 
					    ret.onFileRecv = &chat_onFileRecv;
 | 
				
			||||||
    ret.onReadReceipt = &chat_onReadReceipt;
 | 
					    ret.onReadReceipt = &chat_onReadReceipt;
 | 
				
			||||||
 | 
					    ret.onGroupInvite = &chat_onGroupInvite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef AUDIO
 | 
					#ifdef AUDIO
 | 
				
			||||||
    ret.onInvite = &chat_onInvite;
 | 
					    ret.onInvite = &chat_onInvite;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -78,6 +78,47 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
 | 
				
			|||||||
    close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, silent);
 | 
					    close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, silent);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_groupaccept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (Friends.list[self->num].group_invite.length == 0) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending group invite");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *passwd = NULL;
 | 
				
			||||||
 | 
					    uint16_t passwd_len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (argc > 0) {
 | 
				
			||||||
 | 
					        passwd = argv[1];
 | 
				
			||||||
 | 
					        passwd_len = strlen(passwd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_INVITE_ACCEPT err;
 | 
				
			||||||
 | 
					    uint32_t groupnumber = tox_group_invite_accept(m, Friends.list[self->num].group_invite.data,
 | 
				
			||||||
 | 
					                           Friends.list[self->num].group_invite.length,
 | 
				
			||||||
 | 
					                           (uint8_t *) passwd, passwd_len, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (err != TOX_ERR_GROUP_INVITE_ACCEPT_OK) {
 | 
				
			||||||
 | 
					        if (err == TOX_ERR_GROUP_INVITE_ACCEPT_TOO_LONG)
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to joing group: Password too long.");
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to joing group (error %d).", err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (init_groupchat_win(m, groupnumber, NULL, 0) == -1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
 | 
				
			||||||
 | 
					        tox_group_leave(m, groupnumber, NULL, 0, NULL);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
					void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (argc < 1) {
 | 
					    if (argc < 1) {
 | 
				
			||||||
@@ -85,61 +126,24 @@ void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    long int groupnum = strtol(argv[1], NULL, 10);
 | 
					    int groupnum = atoi(argv[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((groupnum == 0 && strcmp(argv[1], "0")) || groupnum < 0 || groupnum == LONG_MAX) {
 | 
					
 | 
				
			||||||
 | 
					    if (groupnum == 0 && strcmp(argv[1], "0")) {    /* atoi returns 0 value on invalid input */
 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid group number.");
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid group number.");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (tox_invite_friend(m, self->num, groupnum) == -1) {
 | 
					    TOX_ERR_GROUP_INVITE_FRIEND err;
 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to group.");
 | 
					
 | 
				
			||||||
 | 
					    if (!tox_group_invite_friend(m, groupnum, self->num, &err)) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to group (error %d).", err);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invited contact to Group %d.", groupnum);
 | 
					    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invited contact to Group %d.", groupnum);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
 | 
					 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const char *groupkey = Friends.list[self->num].group_invite.key;
 | 
					 | 
				
			||||||
    uint16_t length = Friends.list[self->num].group_invite.length;
 | 
					 | 
				
			||||||
    uint8_t type = Friends.list[self->num].group_invite.type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!Friends.list[self->num].group_invite.pending) {
 | 
					 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending group chat invite.");
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    int groupnum = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (type == TOX_GROUPCHAT_TYPE_TEXT)
 | 
					 | 
				
			||||||
        groupnum = tox_join_groupchat(m, self->num, (uint8_t *) groupkey, length);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /*#ifdef AUDIO
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            groupnum = toxav_join_av_groupchat(m, self->num, (uint8_t *) groupkey, length,
 | 
					 | 
				
			||||||
                                               NULL, NULL);
 | 
					 | 
				
			||||||
    #endif*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (groupnum == -1) {
 | 
					 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize.");
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (init_groupchat_win(prompt, m, groupnum, type) == -1) {
 | 
					 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
 | 
					 | 
				
			||||||
        tox_del_groupchat(m, groupnum);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
					void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (argc < 1) {
 | 
					    if (argc < 1) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,9 +26,9 @@
 | 
				
			|||||||
#include "windows.h"
 | 
					#include "windows.h"
 | 
				
			||||||
#include "toxic.h"
 | 
					#include "toxic.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_groupaccept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
void cmd_groupinvite(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					 | 
				
			||||||
void cmd_join_group(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					 | 
				
			||||||
void cmd_savefile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					void cmd_savefile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
void cmd_sendfile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					void cmd_sendfile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										105
									
								
								src/execute.c
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								src/execute.c
									
									
									
									
									
								
							@@ -34,6 +34,8 @@
 | 
				
			|||||||
#include "misc_tools.h"
 | 
					#include "misc_tools.h"
 | 
				
			||||||
#include "notify.h"
 | 
					#include "notify.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_NUM_ARGS 10     /* Includes command */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct cmd_func {
 | 
					struct cmd_func {
 | 
				
			||||||
    const char *name;
 | 
					    const char *name;
 | 
				
			||||||
    void (*func)(WINDOW *w, ToxWindow *, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					    void (*func)(WINDOW *w, ToxWindow *, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
@@ -49,6 +51,7 @@ static struct cmd_func global_commands[] = {
 | 
				
			|||||||
    { "/exit",      cmd_quit          },
 | 
					    { "/exit",      cmd_quit          },
 | 
				
			||||||
    { "/group",     cmd_groupchat     },
 | 
					    { "/group",     cmd_groupchat     },
 | 
				
			||||||
    { "/help",      cmd_prompt_help   },
 | 
					    { "/help",      cmd_prompt_help   },
 | 
				
			||||||
 | 
					    { "/join",      cmd_join          },
 | 
				
			||||||
    { "/log",       cmd_log           },
 | 
					    { "/log",       cmd_log           },
 | 
				
			||||||
    { "/myid",      cmd_myid          },
 | 
					    { "/myid",      cmd_myid          },
 | 
				
			||||||
    { "/myqr",      cmd_myqr          },
 | 
					    { "/myqr",      cmd_myqr          },
 | 
				
			||||||
@@ -72,8 +75,8 @@ static struct cmd_func global_commands[] = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static struct cmd_func chat_commands[] = {
 | 
					static struct cmd_func chat_commands[] = {
 | 
				
			||||||
    { "/cancel",    cmd_cancelfile  },
 | 
					    { "/cancel",    cmd_cancelfile  },
 | 
				
			||||||
 | 
					    { "/gaccept",   cmd_groupaccept },
 | 
				
			||||||
    { "/invite",    cmd_groupinvite },
 | 
					    { "/invite",    cmd_groupinvite },
 | 
				
			||||||
    { "/join",      cmd_join_group  },
 | 
					 | 
				
			||||||
    { "/savefile",  cmd_savefile    },
 | 
					    { "/savefile",  cmd_savefile    },
 | 
				
			||||||
    { "/sendfile",  cmd_sendfile    },
 | 
					    { "/sendfile",  cmd_sendfile    },
 | 
				
			||||||
#ifdef AUDIO
 | 
					#ifdef AUDIO
 | 
				
			||||||
@@ -91,8 +94,23 @@ static struct cmd_func chat_commands[] = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct cmd_func group_commands[] = {
 | 
					static struct cmd_func group_commands[] = {
 | 
				
			||||||
    { "/title",     cmd_set_title   },
 | 
					    { "/ban",       cmd_ban            },
 | 
				
			||||||
 | 
					    { "/chatid",    cmd_chatid         },
 | 
				
			||||||
 | 
					    { "/ignore",    cmd_ignore         },
 | 
				
			||||||
 | 
					    { "/kick",      cmd_kick           },
 | 
				
			||||||
 | 
					    { "/mod",       cmd_mod            },
 | 
				
			||||||
 | 
					    { "/mykey",     cmd_mykey          },
 | 
				
			||||||
 | 
					    { "/passwd",    cmd_set_passwd     },
 | 
				
			||||||
 | 
					    { "/peerlimit", cmd_set_peerlimit  },
 | 
				
			||||||
 | 
					    { "/privacy",   cmd_set_privacy    },
 | 
				
			||||||
 | 
					    { "/rejoin",    cmd_rejoin         },
 | 
				
			||||||
 | 
					    { "/silence",   cmd_silence        },
 | 
				
			||||||
 | 
					    { "/topic",     cmd_set_topic      },
 | 
				
			||||||
 | 
					    { "/unban",     cmd_unban          },
 | 
				
			||||||
 | 
					    { "/unignore",  cmd_unignore       },
 | 
				
			||||||
 | 
					    { "/unmod",     cmd_unmod          },
 | 
				
			||||||
 | 
					    { "/unsilence", cmd_unsilence      },
 | 
				
			||||||
 | 
					    { "/whois",     cmd_whois          },
 | 
				
			||||||
#ifdef AUDIO
 | 
					#ifdef AUDIO
 | 
				
			||||||
    { "/mute",      cmd_mute           },
 | 
					    { "/mute",      cmd_mute           },
 | 
				
			||||||
    { "/sense",     cmd_sense          },
 | 
					    { "/sense",     cmd_sense          },
 | 
				
			||||||
@@ -100,10 +118,75 @@ static struct cmd_func group_commands[] = {
 | 
				
			|||||||
    { NULL,         NULL               },
 | 
					    { NULL,         NULL               },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Parses input command and puts args into arg array.
 | 
					#define NUM_SPECIAL_COMMANDS 15
 | 
				
			||||||
   Returns number of arguments on success, -1 on failure. */
 | 
					static const char special_commands[NUM_SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = {
 | 
				
			||||||
 | 
					    "/ban",
 | 
				
			||||||
 | 
					    "/gaccept",
 | 
				
			||||||
 | 
					    "/group",
 | 
				
			||||||
 | 
					    "/ignore",
 | 
				
			||||||
 | 
					    "/kick",
 | 
				
			||||||
 | 
					    "/mod",
 | 
				
			||||||
 | 
					    "/nick",
 | 
				
			||||||
 | 
					    "/note",
 | 
				
			||||||
 | 
					    "/passwd",
 | 
				
			||||||
 | 
					    "/silence",
 | 
				
			||||||
 | 
					    "/topic",
 | 
				
			||||||
 | 
					    "/unignore",
 | 
				
			||||||
 | 
					    "/unmod",
 | 
				
			||||||
 | 
					    "/unsilence",
 | 
				
			||||||
 | 
					    "/whois",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* return true if input command is in the special_commands array. False otherwise.*/
 | 
				
			||||||
 | 
					static bool is_special_command(const char *input)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int s = char_find(0, input, ' ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (s == strlen(input))
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < NUM_SPECIAL_COMMANDS; ++i) {
 | 
				
			||||||
 | 
					        if (strncmp(input, special_commands[i], s) == 0)
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Parses commands in the special_commands array which take exactly one argument that may contain spaces.
 | 
				
			||||||
 | 
					 * Unlike parse_command, this function does not split the input string at spaces.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns number of arguments on success
 | 
				
			||||||
 | 
					 * Returns -1 on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int parse_special_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int len = strlen(input);
 | 
				
			||||||
 | 
					    int s = char_find(0, input, ' ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (s + 1 >= len)
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memcpy(args[0], input, s);
 | 
				
			||||||
 | 
					    args[0][s++] = '\0';    /* increment to remove space after /command */
 | 
				
			||||||
 | 
					    memcpy(args[1], input + s, len - s);
 | 
				
			||||||
 | 
					    args[1][len - s] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Parses input command and puts args (split by spaces) into args array.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns number of arguments on success
 | 
				
			||||||
 | 
					 * Returns -1 on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
 | 
					static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    if (is_special_command(input))
 | 
				
			||||||
 | 
					        return parse_special_command(w, self, input, args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char *cmd = strdup(input);
 | 
					    char *cmd = strdup(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (cmd == NULL)
 | 
					    if (cmd == NULL)
 | 
				
			||||||
@@ -141,11 +224,19 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a
 | 
				
			|||||||
        strcpy(cmd, tmp);    /* tmp will always fit inside cmd */
 | 
					        strcpy(cmd, tmp);    /* tmp will always fit inside cmd */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Ugly special case concatinates all args after arg1 for multi-word group passwords */
 | 
				
			||||||
 | 
					    if (num_args > 2 && strcmp(args[0], "/join") == 0)
 | 
				
			||||||
 | 
					        strcpy(args[2], input + strlen(args[0]) + 1 + strlen(args[1]) + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    free(cmd);
 | 
					    free(cmd);
 | 
				
			||||||
    return num_args;
 | 
					    return num_args;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Matches command to respective function. Returns 0 on match, 1 on no match */
 | 
					/* Matches command to respective function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns 0 on match,
 | 
				
			||||||
 | 
					 * Returns -1 on no match
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct cmd_func *commands,
 | 
					static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct cmd_func *commands,
 | 
				
			||||||
                      char (*args)[MAX_STR_SIZE])
 | 
					                      char (*args)[MAX_STR_SIZE])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -158,7 +249,7 @@ static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct c
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 1;
 | 
					    return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
 | 
					void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,13 +26,11 @@
 | 
				
			|||||||
#include "toxic.h"
 | 
					#include "toxic.h"
 | 
				
			||||||
#include "windows.h"
 | 
					#include "windows.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_NUM_ARGS 4     /* Includes command */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
    GLOBAL_COMMAND_MODE,
 | 
					    GLOBAL_COMMAND_MODE,
 | 
				
			||||||
    CHAT_COMMAND_MODE,
 | 
					    CHAT_COMMAND_MODE,
 | 
				
			||||||
    GROUPCHAT_COMMAND_MODE,
 | 
					    GROUPCHAT_COMMAND_MODE,
 | 
				
			||||||
};
 | 
					} COMMAND_MODE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode);
 | 
					void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -113,11 +113,11 @@ static void realloc_blocklist(int n)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void kill_friendlist(void)
 | 
					void kill_friendlist(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int i;
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < Friends.max_idx; ++i) {
 | 
					    for (i = 0; i < Friends.max_idx; ++i) {
 | 
				
			||||||
        if (Friends.list[i].active && Friends.list[i].group_invite.key != NULL)
 | 
					        if (Friends.list[i].group_invite.data != NULL)
 | 
				
			||||||
            free(Friends.list[i].group_invite.key);
 | 
					            free(Friends.list[i].group_invite.data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    realloc_blocklist(0);
 | 
					    realloc_blocklist(0);
 | 
				
			||||||
@@ -520,8 +520,7 @@ static void friendlist_onFileRecv(ToxWindow *self, Tox *m, uint32_t num, uint32_
 | 
				
			|||||||
    sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
 | 
					    sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, uint8_t type, const char *group_pub_key,
 | 
					static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, uint32_t num, const char *data, size_t length)
 | 
				
			||||||
                                     uint16_t length)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (num >= Friends.max_idx)
 | 
					    if (num >= Friends.max_idx)
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
@@ -581,9 +580,6 @@ static void delete_friend(Tox *m, uint32_t f_num)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (Friends.list[f_num].group_invite.key != NULL)
 | 
					 | 
				
			||||||
        free(Friends.list[f_num].group_invite.key);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    memset(&Friends.list[f_num], 0, sizeof(ToxicFriend));
 | 
					    memset(&Friends.list[f_num], 0, sizeof(ToxicFriend));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,11 +35,9 @@ struct LastOnline {
 | 
				
			|||||||
    char hour_min_str[TIME_STR_SIZE];    /* holds 12/24-hour time string e.g. "10:43 PM" */
 | 
					    char hour_min_str[TIME_STR_SIZE];    /* holds 12/24-hour time string e.g. "10:43 PM" */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct GroupChatInvite {
 | 
					struct GroupInvite {
 | 
				
			||||||
    char *key;
 | 
					    uint8_t *data;
 | 
				
			||||||
    uint16_t length;
 | 
					    uint16_t length;
 | 
				
			||||||
    uint8_t type;
 | 
					 | 
				
			||||||
    bool pending;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
@@ -57,7 +55,7 @@ typedef struct {
 | 
				
			|||||||
    uint8_t status;
 | 
					    uint8_t status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct LastOnline last_online;
 | 
					    struct LastOnline last_online;
 | 
				
			||||||
    struct GroupChatInvite group_invite;
 | 
					    struct GroupInvite group_invite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct FileTransfer file_receiver[MAX_FILES];
 | 
					    struct FileTransfer file_receiver[MAX_FILES];
 | 
				
			||||||
    struct FileTransfer file_sender[MAX_FILES];
 | 
					    struct FileTransfer file_sender[MAX_FILES];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -329,43 +329,133 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (argc < 1) {
 | 
					    if (argc < 1) {
 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Please specify group type: text | audio");
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group name required");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t type;
 | 
					    const char *tmp_name = argv[1];
 | 
				
			||||||
 | 
					    int len = strlen(tmp_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!strcasecmp(argv[1], "audio"))
 | 
					    if (len == 0 || len > TOX_GROUP_MAX_GROUP_NAME_LENGTH) {
 | 
				
			||||||
        type = TOX_GROUPCHAT_TYPE_AV;
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid group name.");
 | 
				
			||||||
    else if (!strcasecmp(argv[1], "text"))
 | 
					 | 
				
			||||||
        type = TOX_GROUPCHAT_TYPE_TEXT;
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Valid group types are: text | audio");
 | 
					 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int groupnum = -1;
 | 
					    char name[TOX_GROUP_MAX_GROUP_NAME_LENGTH];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (type == TOX_GROUPCHAT_TYPE_TEXT)
 | 
					    if (argv[1][0] == '\"') {    /* remove opening and closing quotes */
 | 
				
			||||||
        groupnum = tox_add_groupchat(m);
 | 
					        snprintf(name, sizeof(name), "%s", &argv[1][1]);
 | 
				
			||||||
 | 
					        len -= 2;
 | 
				
			||||||
 | 
					        name[len] = '\0';
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        snprintf(name, sizeof(name), "%s", argv[1]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*#ifdef AUDIO
 | 
					    TOX_ERR_GROUP_NEW err;
 | 
				
			||||||
        else
 | 
					    uint32_t groupnum = tox_group_new(m, TOX_GROUP_PRIVACY_STATE_PUBLIC, (uint8_t *) name, len, &err);
 | 
				
			||||||
            groupnum = toxav_add_av_groupchat(m, NULL, NULL);
 | 
					
 | 
				
			||||||
    #endif*/
 | 
					    if (err != TOX_ERR_GROUP_NEW_OK) {
 | 
				
			||||||
 | 
					        switch (err) {
 | 
				
			||||||
 | 
					            case TOX_ERR_GROUP_NEW_TOO_LONG: {
 | 
				
			||||||
 | 
					                line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group name length cannot exceed %d.",
 | 
				
			||||||
 | 
					                              TOX_GROUP_MAX_GROUP_NAME_LENGTH);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            case TOX_ERR_GROUP_NEW_EMPTY: {
 | 
				
			||||||
 | 
					                line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group name cannot be empty.");
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            default: {
 | 
				
			||||||
 | 
					                line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize (error %d).", err);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (groupnum == -1) {
 | 
					 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize.");
 | 
					 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (init_groupchat_win(prompt, m, groupnum, type) == -1) {
 | 
					    int init = init_groupchat_win(m, groupnum, name, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (init == -1) {
 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
 | 
				
			||||||
        tox_del_groupchat(m, groupnum);
 | 
					        tox_group_leave(m, groupnum, NULL, 0, NULL);
 | 
				
			||||||
 | 
					    } else if (init == -2) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,
 | 
				
			||||||
 | 
					                      "You have been kicked from a group. Close the window and try again.");
 | 
				
			||||||
 | 
					        tox_group_leave(m, groupnum, NULL, 0, NULL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat [%d] created.", groupnum);
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Chat ID is required.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *chat_id = argv[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (strlen(chat_id) != TOX_GROUP_CHAT_ID_SIZE * 2) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid chat ID");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char id_bin[TOX_GROUP_CHAT_ID_SIZE] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					    char xch[3];
 | 
				
			||||||
 | 
					    uint32_t x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < TOX_GROUP_CHAT_ID_SIZE; ++i) {
 | 
				
			||||||
 | 
					        xch[0] = chat_id[2 * i];
 | 
				
			||||||
 | 
					        xch[1] = chat_id[2 * i + 1];
 | 
				
			||||||
 | 
					        xch[2] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (sscanf(xch, "%02x", &x) != 1) {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid chat ID.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        id_bin[i] = x;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *passwd = NULL;
 | 
				
			||||||
 | 
					    uint16_t passwd_len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (argc > 1) {
 | 
				
			||||||
 | 
					        passwd = argv[2];
 | 
				
			||||||
 | 
					        passwd_len = strlen(passwd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_JOIN err;
 | 
				
			||||||
 | 
					    uint32_t groupnum = tox_group_join(m, (uint8_t *) id_bin, (uint8_t *) passwd, passwd_len, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (err != TOX_ERR_GROUP_JOIN_OK) {
 | 
				
			||||||
 | 
					        if (err == TOX_ERR_GROUP_JOIN_TOO_LONG)
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password length cannot exceed %d.", TOX_GROUP_MAX_PASSWORD_SIZE);
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to join group (error %d).", err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int init = init_groupchat_win(m, groupnum, NULL, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (init == -1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
 | 
				
			||||||
 | 
					        tox_group_leave(m, groupnum, NULL, 0, NULL);
 | 
				
			||||||
 | 
					    } else if (init == -2) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,
 | 
				
			||||||
 | 
					                      "You have been kicked from a group. Close the window and try again.");
 | 
				
			||||||
 | 
					        tox_group_leave(m, groupnum, NULL, 0, NULL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
					void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
@@ -519,6 +609,7 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    tox_self_set_name(m, (uint8_t *) nick, len, NULL);
 | 
					    tox_self_set_name(m, (uint8_t *) nick, len, NULL);
 | 
				
			||||||
    prompt_update_nick(prompt, nick);
 | 
					    prompt_update_nick(prompt, nick);
 | 
				
			||||||
 | 
					    set_nick_all_groups(m, nick, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    store_data(m, DATA_FILE);
 | 
					    store_data(m, DATA_FILE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -530,19 +621,7 @@ void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (argv[1][0] != '\"') {
 | 
					    prompt_update_statusmessage(prompt, m, argv[1]);
 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Note must be enclosed in quotes.");
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* remove opening and closing quotes and replace linebreaks with spaces */
 | 
					 | 
				
			||||||
    char msg[MAX_STR_SIZE];
 | 
					 | 
				
			||||||
    snprintf(msg, sizeof(msg), "%s", &argv[1][1]);
 | 
					 | 
				
			||||||
    int len = strlen(msg) - 1;
 | 
					 | 
				
			||||||
    msg[len] = '\0';
 | 
					 | 
				
			||||||
    strsubst(msg, '\n', ' ');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    prompt_update_statusmessage(prompt, m, msg);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void cmd_nospam(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
					void cmd_nospam(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
@@ -642,6 +721,7 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    tox_self_set_status(m, status);
 | 
					    tox_self_set_status(m, status);
 | 
				
			||||||
    prompt_update_status(prompt, status);
 | 
					    prompt_update_status(prompt, status);
 | 
				
			||||||
 | 
					    set_status_all_groups(m, status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (have_note) {
 | 
					    if (have_note) {
 | 
				
			||||||
        if (argv[2][0] != '\"') {
 | 
					        if (argv[2][0] != '\"') {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,6 +33,7 @@ void cmd_clear(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE
 | 
				
			|||||||
void cmd_connect(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					void cmd_connect(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
void cmd_groupchat(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					void cmd_groupchat(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
void cmd_log(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					void cmd_log(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
void cmd_myid(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					void cmd_myid(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,59 +21,707 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include "toxic.h"
 | 
					#include "toxic.h"
 | 
				
			||||||
#include "windows.h"
 | 
					#include "windows.h"
 | 
				
			||||||
#include "line_info.h"
 | 
					#include "line_info.h"
 | 
				
			||||||
#include "misc_tools.h"
 | 
					#include "misc_tools.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					#include "groupchat.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
					extern GroupChat groupchats[MAX_GROUPCHAT_NUM];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    char title[MAX_STR_SIZE];
 | 
					    char chatid[TOX_GROUP_CHAT_ID_SIZE * 2 + 1] = {0};
 | 
				
			||||||
 | 
					    char chat_public_key[TOX_GROUP_CHAT_ID_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_STATE_QUERIES err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!tox_group_get_chat_id(m, self->num, (uint8_t *) chat_public_key, &err)) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve the Chat ID (error %d).", err);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < TOX_GROUP_CHAT_ID_SIZE; ++i) {
 | 
				
			||||||
 | 
					        char xx[3];
 | 
				
			||||||
 | 
					        snprintf(xx, sizeof(xx), "%02X", chat_public_key[i] & 0xff);
 | 
				
			||||||
 | 
					        strcat(chatid, xx);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", chatid);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    if (argc < 1) {
 | 
					    if (argc < 1) {
 | 
				
			||||||
        int tlen = tox_group_get_title(m, self->num, (uint8_t *) title, TOX_MAX_NAME_LENGTH);
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified.");
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (tlen != -1) {
 | 
					 | 
				
			||||||
            title[tlen] = '\0';
 | 
					 | 
				
			||||||
            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is set to: %s", title);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is not set");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (argv[1][0] != '\"') {
 | 
					    const char *nick = argv[1];
 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title must be enclosed in quotes.");
 | 
					    uint32_t peer_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "Invalid peer name '%s'.", nick);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* remove opening and closing quotes */
 | 
					    TOX_ERR_GROUP_TOGGLE_IGNORE err;
 | 
				
			||||||
    snprintf(title, sizeof(title), "%s", &argv[1][1]);
 | 
					 | 
				
			||||||
    int len = strlen(title) - 1;
 | 
					 | 
				
			||||||
    title[len] = '\0';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (tox_group_set_title(m, self->num, (uint8_t *) title, len) != 0) {
 | 
					    if (!tox_group_toggle_ignore(m, self->num, peer_id, true, &err)) {
 | 
				
			||||||
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set title.");
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to ignore %s (error %d).", nick, err);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    set_window_title(self, title, len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    char timefrmt[TIME_STR_SIZE];
 | 
					    char timefrmt[TIME_STR_SIZE];
 | 
				
			||||||
    char selfnick[TOX_MAX_NAME_LENGTH];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    get_time_str(timefrmt, sizeof(timefrmt));
 | 
					    get_time_str(timefrmt, sizeof(timefrmt));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_self_get_name(m, (uint8_t *) selfnick);
 | 
					    line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- Ignoring %s", nick);
 | 
				
			||||||
    size_t sn_len = tox_self_get_name_size(m);
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void cmd_kickban_helper(ToxWindow *self, Tox *m, const char *nick, bool set_ban)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t peer_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "Invalid peer name '%s'.", nick);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *type_str = set_ban ? "ban" : "kick";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_MOD_REMOVE_PEER err;
 | 
				
			||||||
 | 
					    tox_group_mod_remove_peer(m, self->num, peer_id, set_ban, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (err) {
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_REMOVE_PEER_OK: {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_REMOVE_PEER_PERMISSIONS: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "You do not have permission to %s %s.", type_str, nick);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "Failed to %s %s from the group (error %d).", type_str, nick,
 | 
				
			||||||
 | 
					                          err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cmd_kickban_helper(self, m, argv[1], false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_ban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_BAN_QUERY err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        size_t num_banned = tox_group_ban_get_list_size(m, self->num, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (err != TOX_ERR_GROUP_BAN_QUERY_OK) {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to get the ban list size (error %d).", err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (num_banned == 0) {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban list is empty.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint32_t ban_list[num_banned];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!tox_group_ban_get_list(m, self->num, ban_list, &err)) {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to get the ban list (error %d).", err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint16_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (i = 0; i < num_banned; ++i) {
 | 
				
			||||||
 | 
					            uint32_t id = ban_list[i];
 | 
				
			||||||
 | 
					            size_t len = tox_group_ban_get_name_size(m, self->num, id, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (err != TOX_ERR_GROUP_BAN_QUERY_OK) {
 | 
				
			||||||
 | 
					                line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve name length for ban %d (error %d).", id, err);
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            char tmp_nick[len];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!tox_group_ban_get_name(m, self->num, id, (uint8_t *) tmp_nick, &err)) {
 | 
				
			||||||
 | 
					                line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve name for ban %d (error %d).", id, err);
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            char nick[len + 1];
 | 
				
			||||||
 | 
					            copy_tox_str(nick, sizeof(nick), tmp_nick, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uint64_t time_set = tox_group_ban_get_time_set(m, self->num, id, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (err != TOX_ERR_GROUP_BAN_QUERY_OK) {
 | 
				
			||||||
 | 
					                line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve timestamp for ban %d (error %d).", id, err);
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            struct tm tm_set = *localtime((const time_t *) &time_set);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            char time_str[64];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            strftime(time_str, sizeof(time_str), "%e %b %Y %H:%M:%S%p", &tm_set);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "ID %d : %s [Set:%s]", id, nick, time_str);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cmd_kickban_helper(self, m, argv[1], true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_unban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID must be specified.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int ban_id = atoi(argv[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ban_id == 0 && strcmp(argv[1], "0")) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID must be a non-negative interger.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_MOD_REMOVE_BAN err;
 | 
				
			||||||
 | 
					    tox_group_mod_remove_ban(m, self->num, ban_id, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (err) {
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_REMOVE_BAN_OK: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban list entry with id %d has been removed.", ban_id);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_REMOVE_BAN_PERMISSIONS: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to unban peers.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_REMOVE_BAN_FAIL_ACTION: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID does not exist.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to remove ban list entry (error %d).", err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *nick = argv[1];
 | 
				
			||||||
 | 
					    uint32_t peer_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "Invalid peer name '%s'.", nick);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_MOD_SET_ROLE err;
 | 
				
			||||||
 | 
					    tox_group_mod_set_role(m, self->num, peer_id, TOX_GROUP_ROLE_MODERATOR, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (err) {
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_SET_ROLE_OK: {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "You do not have permission to promote moderators.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "This peer is already a moderator.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "Failed to promote peer to moderator (error %d).", err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *nick = argv[1];
 | 
				
			||||||
 | 
					    uint32_t peer_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "Invalid peer name '%s'.", nick);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (tox_group_peer_get_role(m, self->num, peer_id, NULL) != TOX_GROUP_ROLE_MODERATOR) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s is not a moderator", nick);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_MOD_SET_ROLE err;
 | 
				
			||||||
 | 
					    tox_group_mod_set_role(m, self->num, peer_id, TOX_GROUP_ROLE_USER, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (err) {
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_SET_ROLE_OK: {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "Nice try.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "Failed to revoke moderator powers from %s (error %d).", nick,
 | 
				
			||||||
 | 
					                          err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_mykey(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char pk_string[TOX_GROUP_PEER_PUBLIC_KEY_SIZE * 2 + 1] = {0};
 | 
				
			||||||
 | 
					    char pk[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_SELF_QUERY err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!tox_group_self_get_public_key(m, self->num, (uint8_t *) pk, &err)) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to fetch your public key (error %d)", err);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < TOX_GROUP_PEER_PUBLIC_KEY_SIZE; ++i) {
 | 
				
			||||||
 | 
					        char d[3];
 | 
				
			||||||
 | 
					        snprintf(d, sizeof(d), "%02X", pk[i] & 0xff);
 | 
				
			||||||
 | 
					        strcat(pk_string, d);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", pk_string);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const char *passwd = NULL;
 | 
				
			||||||
 | 
					    size_t len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (argc > 0) {
 | 
				
			||||||
 | 
					        passwd = argv[1];
 | 
				
			||||||
 | 
					        len = strlen(passwd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_FOUNDER_SET_PASSWORD err;
 | 
				
			||||||
 | 
					    tox_group_founder_set_password(m, self->num, (uint8_t *) passwd, len, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (err) {
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK: {
 | 
				
			||||||
 | 
					            if (len > 0)
 | 
				
			||||||
 | 
					                line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password has been set to %s.", passwd);
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password has been unset.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password length must not exceed %d.",
 | 
				
			||||||
 | 
					                          TOX_GROUP_MAX_PASSWORD_SIZE);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the password.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set password (error %d).", err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int maxpeers = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        TOX_ERR_GROUP_STATE_QUERIES err;
 | 
				
			||||||
 | 
					        uint32_t maxpeers = tox_group_get_peer_limit(m, self->num, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve peer limit (error %d).", err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer limit is set to %d", maxpeers);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    maxpeers = atoi(argv[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (maxpeers <= 0) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer limit must be a value greater than 0.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT err;
 | 
				
			||||||
 | 
					    tox_group_founder_set_peer_limit(m, self->num, maxpeers, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (err) {
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer limit has been set to %d.", maxpeers);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the peer limit.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set the peer limit (error %d).", err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const char *pstate_str = NULL;
 | 
				
			||||||
 | 
					    TOX_GROUP_PRIVACY_STATE privacy_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        TOX_ERR_GROUP_STATE_QUERIES err;
 | 
				
			||||||
 | 
					        privacy_state = tox_group_get_privacy_state(m, self->num, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve privacy state (error %d).", err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        pstate_str = privacy_state == TOX_GROUP_PRIVACY_STATE_PRIVATE ? "private" : "public";
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Privacy state is set to %s.", pstate_str);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pstate_str = argv[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (strcasecmp(pstate_str, "private") != 0 && strcasecmp(pstate_str, "public") != 0) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Privacy state must be \"private\" or \"public\".");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    privacy_state = strcasecmp(pstate_str,
 | 
				
			||||||
 | 
					                               "private") == 0 ? TOX_GROUP_PRIVACY_STATE_PRIVATE : TOX_GROUP_PRIVACY_STATE_PUBLIC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE err;
 | 
				
			||||||
 | 
					    tox_group_founder_set_privacy_state(m, self->num, privacy_state, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (err) {
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Privacy state has been set to %s.", pstate_str);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the privacy state.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error setting privacy state (error %d).", err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_silence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *nick = argv[1];
 | 
				
			||||||
 | 
					    uint32_t peer_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "Invalid peer name '%s'.", nick);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_MOD_SET_ROLE err;
 | 
				
			||||||
 | 
					    tox_group_mod_set_role(m, self->num, peer_id, TOX_GROUP_ROLE_OBSERVER, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (err) {
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_SET_ROLE_OK: {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to silence %s.", nick);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to silence %s (error %d).", nick, err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_unsilence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer name must be specified.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *nick = argv[1];
 | 
				
			||||||
 | 
					    uint32_t peer_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "Invalid peer name '%s'.", nick);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (tox_group_peer_get_role(m, self->num, peer_id, NULL) != TOX_GROUP_ROLE_OBSERVER) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s is not silenced.", nick);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_MOD_SET_ROLE err;
 | 
				
			||||||
 | 
					    tox_group_mod_set_role(m, self->num, peer_id, TOX_GROUP_ROLE_USER, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (err) {
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_SET_ROLE_OK: {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to unsilence %s.", nick);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unsilence %s (error %d).", nick, err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_RECONNECT err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!tox_group_reconnect(m, self->num, &err)) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to rejoin group (error %d).", err);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Reconnecting to group...");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        TOX_ERR_GROUP_STATE_QUERIES err;
 | 
				
			||||||
 | 
					        size_t tlen = tox_group_get_topic_size(m, self->num, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve topic length (error %d).", err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (tlen > 0) {
 | 
				
			||||||
 | 
					            char cur_topic[tlen];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!tox_group_get_topic(m, self->num, (uint8_t *) cur_topic, &err)) {
 | 
				
			||||||
 | 
					                line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve topic (error %d).", err);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            cur_topic[tlen] = '\0';
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is set to: %s", cur_topic);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is not set.");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *topic = argv[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_TOPIC_SET err;
 | 
				
			||||||
 | 
					    tox_group_set_topic(m, self->num, (uint8_t *) topic, strlen(topic), &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (err) {
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_TOPIC_SET_OK: {
 | 
				
			||||||
 | 
					            /* handled below switch */
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_TOPIC_SET_TOO_LONG: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic length must not exceed %d.", TOX_GROUP_MAX_TOPIC_LENGTH);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the topic.");
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default: {
 | 
				
			||||||
 | 
					            line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set the topic (error %d).", err);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char timefrmt[TIME_STR_SIZE];
 | 
				
			||||||
 | 
					    get_time_str(timefrmt, sizeof(timefrmt));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_SELF_QUERY sn_err;
 | 
				
			||||||
 | 
					    size_t sn_len = tox_group_self_get_name_size(m, self->num, &sn_err);
 | 
				
			||||||
 | 
					    char selfnick[sn_len];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!tox_group_self_get_name(m, self->num, (uint8_t *) selfnick, &sn_err)) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve your own name (error %d).", sn_err);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    selfnick[sn_len] = '\0';
 | 
					    selfnick[sn_len] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    line_info_add(self, timefrmt, selfnick, NULL, NAME_CHANGE, 0, 0, " set the group title to: %s", title);
 | 
					    line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, MAGENTA, "-!- You set the topic to: %s", topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char tmp_event[MAX_STR_SIZE];
 | 
					    char tmp_event[MAX_STR_SIZE];
 | 
				
			||||||
    snprintf(tmp_event, sizeof(tmp_event), "set title to %s", title);
 | 
					    snprintf(tmp_event, sizeof(tmp_event), "set topic to %s", topic);
 | 
				
			||||||
    write_to_log(tmp_event, selfnick, self->chatwin->log, true);
 | 
					    write_to_log(tmp_event, selfnick, self->chatwin->log, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer must be specified.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *nick = argv[1];
 | 
				
			||||||
 | 
					    uint32_t peer_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "Invalid peer name '%s'.", nick);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOX_ERR_GROUP_TOGGLE_IGNORE err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!tox_group_toggle_ignore(m, self->num, peer_id, false, &err)) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unignore %s (error %d).", nick, err);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char timefrmt[TIME_STR_SIZE];
 | 
				
			||||||
 | 
					    get_time_str(timefrmt, sizeof(timefrmt));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- You are no longer ignoring %s", nick);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmd_whois(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (argc < 1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer must be specified.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GroupChat *chat = &groupchats[self->num];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!chat) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Whois failed.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *nick = argv[1];
 | 
				
			||||||
 | 
					    uint32_t peer_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (group_get_nick_peer_id(self->num, nick, &peer_id) == -1) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,  "Invalid peer name '%s'.", nick);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int peer_index = get_peer_index(self->num, peer_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (peer_index < 0) {
 | 
				
			||||||
 | 
					        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Whois failed.");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *status_str = "Online";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (chat->peer_list[peer_index].status == TOX_USER_STATUS_BUSY)
 | 
				
			||||||
 | 
					        status_str = "Busy";
 | 
				
			||||||
 | 
					    else if (chat->peer_list[peer_index].status == TOX_USER_STATUS_AWAY)
 | 
				
			||||||
 | 
					        status_str = "Away";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char *role_str = "User";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (chat->peer_list[peer_index].role == TOX_GROUP_ROLE_FOUNDER)
 | 
				
			||||||
 | 
					        role_str = "Founder";
 | 
				
			||||||
 | 
					    else if (chat->peer_list[peer_index].role == TOX_GROUP_ROLE_MODERATOR)
 | 
				
			||||||
 | 
					        role_str = "Moderator";
 | 
				
			||||||
 | 
					    else if (chat->peer_list[peer_index].role == TOX_GROUP_ROLE_OBSERVER)
 | 
				
			||||||
 | 
					        role_str = "Observer";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char last_seen_str[128];
 | 
				
			||||||
 | 
					    get_elapsed_time_str_2(last_seen_str, sizeof(last_seen_str), get_unix_time() - chat->peer_list[peer_index].last_active);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char pk_string[TOX_GROUP_PEER_PUBLIC_KEY_SIZE * 2 + 1] = {0};
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < TOX_GROUP_PEER_PUBLIC_KEY_SIZE; ++i) {
 | 
				
			||||||
 | 
					        char d[3];
 | 
				
			||||||
 | 
					        snprintf(d, sizeof(d), "%02X", chat->peer_list[peer_index].public_key[i] & 0xff);
 | 
				
			||||||
 | 
					        strcat(pk_string, d);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Whois for %s", nick);
 | 
				
			||||||
 | 
					    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Role: %s", role_str);
 | 
				
			||||||
 | 
					    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Status: %s", status_str);
 | 
				
			||||||
 | 
					    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Last active: %s", last_seen_str);
 | 
				
			||||||
 | 
					    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Public key: %s", pk_string);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,6 +26,23 @@
 | 
				
			|||||||
#include "windows.h"
 | 
					#include "windows.h"
 | 
				
			||||||
#include "toxic.h"
 | 
					#include "toxic.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
					void cmd_ban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_mykey(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_prune(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_silence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_unsilence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_unban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					void cmd_whois(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif  /* GROUP_COMMANDS_H */
 | 
					#endif  /* GROUP_COMMANDS_H */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1361
									
								
								src/groupchat.c
									
									
									
									
									
								
							
							
						
						
									
										1361
									
								
								src/groupchat.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -26,61 +26,42 @@
 | 
				
			|||||||
#include "toxic.h"
 | 
					#include "toxic.h"
 | 
				
			||||||
#include "windows.h"
 | 
					#include "windows.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef AUDIO
 | 
					 | 
				
			||||||
#include "audio_call.h"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef AUDIO
 | 
					 | 
				
			||||||
#ifdef __APPLE__
 | 
					 | 
				
			||||||
#include <OpenAL/al.h>
 | 
					 | 
				
			||||||
#include <OpenAL/alc.h>
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#include <AL/al.h>
 | 
					 | 
				
			||||||
#include <AL/alc.h>
 | 
					 | 
				
			||||||
/* compatibility with older versions of OpenAL */
 | 
					 | 
				
			||||||
#ifndef ALC_ALL_DEVICES_SPECIFIER
 | 
					 | 
				
			||||||
#include <AL/alext.h>
 | 
					 | 
				
			||||||
#endif  /* ALC_ALL_DEVICES_SPECIFIER */
 | 
					 | 
				
			||||||
#endif  /* __APPLE__ */
 | 
					 | 
				
			||||||
#endif  /* AUDIO */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define SIDEBAR_WIDTH 16
 | 
					#define SIDEBAR_WIDTH 16
 | 
				
			||||||
#define SDBAR_OFST 2    /* Offset for the peer number box at the top of the statusbar */
 | 
					#define SDBAR_OFST 2    /* Offset for the peer number box at the top of the statusbar */
 | 
				
			||||||
#define MAX_GROUPCHAT_NUM MAX_WINDOWS_NUM - 2
 | 
					#define MAX_GROUPCHAT_NUM MAX_WINDOWS_NUM - 2
 | 
				
			||||||
#define GROUP_EVENT_WAIT 3
 | 
					#define GROUP_EVENT_WAIT 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef AUDIO
 | 
					struct GroupPeer {
 | 
				
			||||||
struct GAudio {
 | 
					    bool       active;
 | 
				
			||||||
    ALCdevice  *dvhandle;    /* Handle of device selected/opened */
 | 
					    char       name[TOX_MAX_NAME_LENGTH];
 | 
				
			||||||
    ALCcontext *dvctx;
 | 
					    size_t     name_length;
 | 
				
			||||||
    ALuint source;
 | 
					    uint32_t   peer_id;
 | 
				
			||||||
    ALuint buffers[OPENAL_BUFS];
 | 
					    uint8_t    public_key[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
 | 
				
			||||||
 | 
					    TOX_USER_STATUS status;
 | 
				
			||||||
 | 
					    TOX_GROUP_ROLE  role;
 | 
				
			||||||
 | 
					    uint64_t   last_active;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#endif  /* AUDIO */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    struct GroupPeer *peer_list;
 | 
				
			||||||
 | 
					    char       *name_list;    /* List of peer names, needed for tab completion */
 | 
				
			||||||
 | 
					    uint32_t   num_peers;     /* Number of peers in the chat/name_list array */
 | 
				
			||||||
 | 
					    uint32_t   max_idx;       /* Maximum peer list index - 1 */
 | 
				
			||||||
 | 
					    uint32_t   groupnumber;
 | 
				
			||||||
    int        chatwin;
 | 
					    int        chatwin;
 | 
				
			||||||
    bool       active;
 | 
					    bool       active;
 | 
				
			||||||
    uint8_t type;
 | 
					    uint64_t   time_connected;    /* The time we successfully connected to the group */
 | 
				
			||||||
    int num_peers;
 | 
					 | 
				
			||||||
    int        side_pos;     /* current position of the sidebar - used for scrolling up and down */
 | 
					    int        side_pos;     /* current position of the sidebar - used for scrolling up and down */
 | 
				
			||||||
    time_t start_time;
 | 
					 | 
				
			||||||
    uint8_t  *peer_names;
 | 
					 | 
				
			||||||
    uint8_t  *oldpeer_names;
 | 
					 | 
				
			||||||
    uint16_t *peer_name_lengths;
 | 
					 | 
				
			||||||
    uint16_t *oldpeer_name_lengths;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef AUDIO
 | 
					 | 
				
			||||||
    struct GAudio audio;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
} GroupChat;
 | 
					} GroupChat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void close_groupchat(ToxWindow *self, Tox *m, int groupnum);
 | 
					void close_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum);
 | 
				
			||||||
int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, uint8_t type);
 | 
					int init_groupchat_win(Tox *m, uint32_t groupnum, const char *groupname, size_t length);
 | 
				
			||||||
 | 
					void set_nick_all_groups(Tox *m, const char *nick, size_t length);
 | 
				
			||||||
 | 
					void set_status_all_groups(Tox *m, uint8_t status);
 | 
				
			||||||
 | 
					int group_get_nick_peer_id(uint32_t groupnum, const char *nick, uint32_t *peer_id);
 | 
				
			||||||
 | 
					int get_peer_index(uint32_t groupnum, uint32_t peer_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* destroys and re-creates groupchat window with or without the peerlist */
 | 
					/* destroys and re-creates groupchat window */
 | 
				
			||||||
void redraw_groupchat_win(ToxWindow *self);
 | 
					void redraw_groupchat_win(ToxWindow *self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ToxWindow new_group_chat(Tox *m, int groupnum);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* #define GROUPCHAT_H */
 | 
					#endif /* #define GROUPCHAT_H */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										39
									
								
								src/help.c
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								src/help.c
									
									
									
									
									
								
							@@ -153,10 +153,11 @@ static void help_draw_global(ToxWindow *self)
 | 
				
			|||||||
    wprintw(win, "  /connect <ip> <port> <key> : Manually connect to a DHT node\n");
 | 
					    wprintw(win, "  /connect <ip> <port> <key> : Manually connect to a DHT node\n");
 | 
				
			||||||
    wprintw(win, "  /status <type> <msg>       : Set status with optional note\n");
 | 
					    wprintw(win, "  /status <type> <msg>       : Set status with optional note\n");
 | 
				
			||||||
    wprintw(win, "  /note <msg>                : Set a personal note\n");
 | 
					    wprintw(win, "  /note <msg>                : Set a personal note\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /group                     : Create a group chat\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /join <chat id> <passwd>   : Join a group chat with optional password\n");
 | 
				
			||||||
    wprintw(win, "  /nick <nick>               : Set your nickname\n");
 | 
					    wprintw(win, "  /nick <nick>               : Set your nickname\n");
 | 
				
			||||||
    wprintw(win, "  /nospam <value>            : Change part of your Tox ID to stop spam\n");
 | 
					    wprintw(win, "  /nospam <value>            : Change part of your Tox ID to stop spam\n");
 | 
				
			||||||
    wprintw(win, "  /log <on> or <off>         : Enable/disable logging\n");
 | 
					    wprintw(win, "  /log <on> or <off>         : Enable/disable logging\n");
 | 
				
			||||||
    wprintw(win, "  /group <type>              : Create a group chat where type: text | audio\n");
 | 
					 | 
				
			||||||
    wprintw(win, "  /myid                      : Print your Tox ID\n");
 | 
					    wprintw(win, "  /myid                      : Print your Tox ID\n");
 | 
				
			||||||
#ifdef QRPNG
 | 
					#ifdef QRPNG
 | 
				
			||||||
    wprintw(win, "  /myqr <txt> or <png>       : Print your Tox ID's QR code to a file.\n");
 | 
					    wprintw(win, "  /myqr <txt> or <png>       : Print your Tox ID's QR code to a file.\n");
 | 
				
			||||||
@@ -201,8 +202,7 @@ static void help_draw_chat(ToxWindow *self)
 | 
				
			|||||||
    wprintw(win, "Chat Commands:\n");
 | 
					    wprintw(win, "Chat Commands:\n");
 | 
				
			||||||
    wattroff(win, A_BOLD | COLOR_PAIR(RED));
 | 
					    wattroff(win, A_BOLD | COLOR_PAIR(RED));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    wprintw(win, "  /invite <n>                : Invite contact to a group chat\n");
 | 
					    wprintw(win, "  /gaccept <password>        : Accept a group invite with optional password\n");
 | 
				
			||||||
    wprintw(win, "  /join                      : Join a pending group chat\n");
 | 
					 | 
				
			||||||
    wprintw(win, "  /sendfile <path>           : Send a file\n");
 | 
					    wprintw(win, "  /sendfile <path>           : Send a file\n");
 | 
				
			||||||
    wprintw(win, "  /savefile <id>             : Receive a file\n");
 | 
					    wprintw(win, "  /savefile <id>             : Receive a file\n");
 | 
				
			||||||
    wprintw(win, "  /cancel <type> <id>        : Cancel file transfer where type: in|out\n");
 | 
					    wprintw(win, "  /cancel <type> <id>        : Cancel file transfer where type: in|out\n");
 | 
				
			||||||
@@ -270,7 +270,32 @@ static void help_draw_group(ToxWindow *self)
 | 
				
			|||||||
    wprintw(win, "Group commands:\n");
 | 
					    wprintw(win, "Group commands:\n");
 | 
				
			||||||
    wattroff(win, A_BOLD | COLOR_PAIR(RED));
 | 
					    wattroff(win, A_BOLD | COLOR_PAIR(RED));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    wprintw(win, "  /title <msg>               : Set group title (show current title if no msg)\n\n");
 | 
					    wprintw(win, "  /chatid                    : Print the group chat id to share with others\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /mykey                     : Print your group public key\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /ignore <nick>             : Ignore peer\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /unignore <nick>           : Unignore peer \n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /rejoin                    : Rejoin the group\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /topic <msg>               : Set group topic (show current topic if no msg)\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /whisper <nick> <msg>      : Send private message to nick\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /whois <nick>              : Display info about nick.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wattron(win, A_BOLD);
 | 
				
			||||||
 | 
					    wprintw(win, " Moderator commands:\n");
 | 
				
			||||||
 | 
					    wattroff(win, A_BOLD);
 | 
				
			||||||
 | 
					    wprintw(win, "  /kick <nick>               : Kick peer\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /ban <nick>                : Ban peer (leave nick blank to see ban list)\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /unban <Ban ID>            : Unban entry\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /silence <nick>            : Silences peer for the entire group\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /unsilence <nick>          : Unsilences peer\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wattron(win, A_BOLD);
 | 
				
			||||||
 | 
					    wprintw(win, " Founder commands:\n");
 | 
				
			||||||
 | 
					    wattroff(win, A_BOLD);
 | 
				
			||||||
 | 
					    wprintw(win, "  /mod <nick>                : Promote peer to moderator\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /unmod <nick>              : Demote moderator to normal user\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /passwd <password>         : Set group password (leave blank to unset)\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /peerlimit <num>           : Set group peer limit\n");
 | 
				
			||||||
 | 
					    wprintw(win, "  /privacy <state>           : Set group privacy state: private|public\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    help_draw_bottom_menu(win);
 | 
					    help_draw_bottom_menu(win);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -310,9 +335,9 @@ void help_onKey(ToxWindow *self, wint_t key)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        case 'c':
 | 
					        case 'c':
 | 
				
			||||||
#ifdef VIDEO
 | 
					#ifdef VIDEO
 | 
				
			||||||
            help_init_window(self, 22, 80);
 | 
					            help_init_window(self, 21, 80);
 | 
				
			||||||
#elif AUDIO
 | 
					#elif AUDIO
 | 
				
			||||||
            help_init_window(self, 19, 80);
 | 
					            help_init_window(self, 18, 80);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
            help_init_window(self, 10, 80);
 | 
					            help_init_window(self, 10, 80);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -331,7 +356,7 @@ void help_onKey(ToxWindow *self, wint_t key)
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case 'r':
 | 
					        case 'r':
 | 
				
			||||||
            help_init_window(self, 6, 80);
 | 
					            help_init_window(self, 25, 80);
 | 
				
			||||||
            self->help->type = HELP_GROUP;
 | 
					            self->help->type = HELP_GROUP;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -171,6 +171,11 @@ void line_info_add(ToxWindow *self, const char *timestr, const char *name1, cons
 | 
				
			|||||||
            len += strlen(user_settings->line_normal) + 3;
 | 
					            len += strlen(user_settings->line_normal) + 3;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case IN_PRVT_MSG:
 | 
				
			||||||
 | 
					        case OUT_PRVT_MSG:
 | 
				
			||||||
 | 
					            len += strlen(user_settings->line_special) + 3;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case CONNECTION:
 | 
					        case CONNECTION:
 | 
				
			||||||
            len += strlen(user_settings->line_join) + 2;
 | 
					            len += strlen(user_settings->line_join) + 2;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@@ -312,6 +317,8 @@ void line_info_print(ToxWindow *self)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            /* fallthrough */
 | 
					            /* fallthrough */
 | 
				
			||||||
            case IN_MSG:
 | 
					            case IN_MSG:
 | 
				
			||||||
 | 
					            case IN_PRVT_MSG:
 | 
				
			||||||
 | 
					            case OUT_PRVT_MSG:
 | 
				
			||||||
                wattron(win, COLOR_PAIR(BLUE));
 | 
					                wattron(win, COLOR_PAIR(BLUE));
 | 
				
			||||||
                wprintw(win, "%s ", line->timestr);
 | 
					                wprintw(win, "%s ", line->timestr);
 | 
				
			||||||
                wattroff(win, COLOR_PAIR(BLUE));
 | 
					                wattroff(win, COLOR_PAIR(BLUE));
 | 
				
			||||||
@@ -324,7 +331,10 @@ void line_info_print(ToxWindow *self)
 | 
				
			|||||||
                    nameclr = CYAN;
 | 
					                    nameclr = CYAN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                wattron(win, COLOR_PAIR(nameclr));
 | 
					                wattron(win, COLOR_PAIR(nameclr));
 | 
				
			||||||
                wprintw(win, "%s %s: ", user_settings->line_normal, line->name1);
 | 
					                wprintw(win, "%s %s: ", (type != OUT_PRVT_MSG && type != IN_PRVT_MSG) ?
 | 
				
			||||||
 | 
					                        user_settings->line_normal :
 | 
				
			||||||
 | 
					                        user_settings->line_special,
 | 
				
			||||||
 | 
					                        line->name1);
 | 
				
			||||||
                wattroff(win, COLOR_PAIR(nameclr));
 | 
					                wattroff(win, COLOR_PAIR(nameclr));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                char *msg = line->msg;
 | 
					                char *msg = line->msg;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,10 +35,12 @@ enum {
 | 
				
			|||||||
    SYS_MSG,
 | 
					    SYS_MSG,
 | 
				
			||||||
    IN_MSG,
 | 
					    IN_MSG,
 | 
				
			||||||
    OUT_MSG,
 | 
					    OUT_MSG,
 | 
				
			||||||
    OUT_MSG_READ,    /* for sent messages that have received a read reply. don't set this with line_info_add */
 | 
					    OUT_MSG_READ,    /* for sent messages that have received a read reply. */
 | 
				
			||||||
    IN_ACTION,
 | 
					    IN_ACTION,
 | 
				
			||||||
    OUT_ACTION,
 | 
					    OUT_ACTION,
 | 
				
			||||||
    OUT_ACTION_READ,     /* same as OUT_MSG_READ but for actions */
 | 
					    OUT_ACTION_READ,     /* same as OUT_MSG_READ but for actions */
 | 
				
			||||||
 | 
					    IN_PRVT_MSG,   /* PRVT should only be used for groups */
 | 
				
			||||||
 | 
					    OUT_PRVT_MSG,
 | 
				
			||||||
    PROMPT,
 | 
					    PROMPT,
 | 
				
			||||||
    CONNECTION,
 | 
					    CONNECTION,
 | 
				
			||||||
    DISCONNECTION,
 | 
					    DISCONNECTION,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -108,6 +108,24 @@ void get_elapsed_time_str(char *buf, int bufsize, time_t secs)
 | 
				
			|||||||
        snprintf(buf, bufsize, "%ld:%.2ld:%.2ld", hours, minutes, seconds);
 | 
					        snprintf(buf, bufsize, "%ld:%.2ld:%.2ld", hours, minutes, seconds);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Converts seconds to string in format H hours, m minutes, s seconds */
 | 
				
			||||||
 | 
					void get_elapsed_time_str_2(char *buf, int bufsize, uint64_t secs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!secs)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    long int seconds = secs % 60;
 | 
				
			||||||
 | 
					    long int minutes = (secs % 3600) / 60;
 | 
				
			||||||
 | 
					    long int hours = secs / 3600;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!minutes && !hours)
 | 
				
			||||||
 | 
					        snprintf(buf, bufsize, "%ld seconds", seconds);
 | 
				
			||||||
 | 
					    else if (!hours)
 | 
				
			||||||
 | 
					        snprintf(buf, bufsize, "%ld minutes, %ld seconds", minutes, seconds);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        snprintf(buf, bufsize, "%ld hours, %ld minutes, %ld seconds", hours, minutes, seconds);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Converts a hexidecimal string of length hex_len to binary format and puts the result in output.
 | 
					 * Converts a hexidecimal string of length hex_len to binary format and puts the result in output.
 | 
				
			||||||
 * output_size must be exactly half of hex_len.
 | 
					 * output_size must be exactly half of hex_len.
 | 
				
			||||||
@@ -339,13 +357,21 @@ size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* same as get_nick_truncate but for groupchats */
 | 
					/* same as get_nick_truncate but for groupchats */
 | 
				
			||||||
int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum)
 | 
					int get_group_nick_truncate(Tox *m, char *buf, uint32_t peer_id, int groupnum)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int len = tox_group_peername(m, groupnum, peernum, (uint8_t *) buf);
 | 
					    TOX_ERR_GROUP_PEER_QUERY err;
 | 
				
			||||||
 | 
					    size_t len = tox_group_peer_get_name_size(m, groupnum, peer_id, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (len == -1) {
 | 
					    if (err != TOX_ERR_GROUP_PEER_QUERY_OK) {
 | 
				
			||||||
        strcpy(buf, UNKNOWN_NAME);
 | 
					        strcpy(buf, UNKNOWN_NAME);
 | 
				
			||||||
        len = strlen(UNKNOWN_NAME);
 | 
					        len = strlen(UNKNOWN_NAME);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        tox_group_peer_get_name(m, groupnum, peer_id, (uint8_t *) buf, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (err != TOX_ERR_GROUP_PEER_QUERY_OK) {
 | 
				
			||||||
 | 
					            strcpy(buf, UNKNOWN_NAME);
 | 
				
			||||||
 | 
					            len = strlen(UNKNOWN_NAME);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
 | 
					    len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
 | 
				
			||||||
@@ -355,13 +381,18 @@ int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* copies data to msg buffer.
 | 
					/* copies data to msg buffer.
 | 
				
			||||||
   returns length of msg, which will be no larger than size-1 */
 | 
					   returns length of msg.
 | 
				
			||||||
 | 
					   returns 0 and nulls msg if length is too big for buffer size */
 | 
				
			||||||
size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length)
 | 
					size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    size_t len = MIN(length, size - 1);
 | 
					    if (length > size - 1) {
 | 
				
			||||||
    memcpy(msg, data, len);
 | 
					        msg[0] = '\0';
 | 
				
			||||||
    msg[len] = '\0';
 | 
					        return 0;
 | 
				
			||||||
    return len;
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memcpy(msg, data, length);
 | 
				
			||||||
 | 
					    msg[length] = '\0';
 | 
				
			||||||
 | 
					    return length;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* returns index of the first instance of ch in s starting at idx.
 | 
					/* returns index of the first instance of ch in s starting at idx.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,6 +69,9 @@ void get_time_str(char *buf, int bufsize);
 | 
				
			|||||||
/* Converts seconds to string in format HH:mm:ss; truncates hours and minutes when necessary */
 | 
					/* Converts seconds to string in format HH:mm:ss; truncates hours and minutes when necessary */
 | 
				
			||||||
void get_elapsed_time_str(char *buf, int bufsize, time_t secs);
 | 
					void get_elapsed_time_str(char *buf, int bufsize, time_t secs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Converts seconds to string in format H hours, m minutes, s seconds */
 | 
				
			||||||
 | 
					void get_elapsed_time_str_2(char *buf, int bufsize, uint64_t secs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* get the current local time (not thread safe) */
 | 
					/* get the current local time (not thread safe) */
 | 
				
			||||||
struct tm *get_time(void);
 | 
					struct tm *get_time(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -126,10 +129,11 @@ void str_to_lower(char *str);
 | 
				
			|||||||
size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum);
 | 
					size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* same as get_nick_truncate but for groupchats */
 | 
					/* same as get_nick_truncate but for groupchats */
 | 
				
			||||||
int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum);
 | 
					int get_group_nick_truncate(Tox *m, char *buf, uint32_t peer_id, int groupnum);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* copies data to msg buffer.
 | 
					/* copies data to msg buffer.
 | 
				
			||||||
   returns length of msg, which will be no larger than size-1 */
 | 
					   returns length of msg.
 | 
				
			||||||
 | 
					   returns 0 and nulls msg if length is too big for buffer size */
 | 
				
			||||||
size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length);
 | 
					size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* returns index of the first instance of ch in s starting at idx.
 | 
					/* returns index of the first instance of ch in s starting at idx.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,11 +50,11 @@ extern struct Winthread Winthread;
 | 
				
			|||||||
extern FriendsList Friends;
 | 
					extern FriendsList Friends;
 | 
				
			||||||
FriendRequests FrndRequests;
 | 
					FriendRequests FrndRequests;
 | 
				
			||||||
#ifdef VIDEO
 | 
					#ifdef VIDEO
 | 
				
			||||||
#define AC_NUM_GLOB_COMMANDS 22
 | 
					#define AC_NUM_GLOB_COMMANDS 23
 | 
				
			||||||
#elif AUDIO
 | 
					#elif AUDIO
 | 
				
			||||||
#define AC_NUM_GLOB_COMMANDS 20
 | 
					#define AC_NUM_GLOB_COMMANDS 21
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#define AC_NUM_GLOB_COMMANDS 18
 | 
					#define AC_NUM_GLOB_COMMANDS 19
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Array of global command names used for tab completion. */
 | 
					/* Array of global command names used for tab completion. */
 | 
				
			||||||
@@ -68,6 +68,7 @@ static const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
 | 
				
			|||||||
    { "/exit"       },
 | 
					    { "/exit"       },
 | 
				
			||||||
    { "/group"      },
 | 
					    { "/group"      },
 | 
				
			||||||
    { "/help"       },
 | 
					    { "/help"       },
 | 
				
			||||||
 | 
					    { "/join"       },
 | 
				
			||||||
    { "/log"        },
 | 
					    { "/log"        },
 | 
				
			||||||
    { "/myid"       },
 | 
					    { "/myid"       },
 | 
				
			||||||
    { "/myqr"       },
 | 
					    { "/myqr"       },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,6 +68,7 @@ static struct ui_strings {
 | 
				
			|||||||
    const char *line_quit;
 | 
					    const char *line_quit;
 | 
				
			||||||
    const char *line_alert;
 | 
					    const char *line_alert;
 | 
				
			||||||
    const char *line_normal;
 | 
					    const char *line_normal;
 | 
				
			||||||
 | 
					    const char *line_special;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const char *mplex_away;
 | 
					    const char *mplex_away;
 | 
				
			||||||
    const char *mplex_away_note;
 | 
					    const char *mplex_away_note;
 | 
				
			||||||
@@ -94,6 +95,7 @@ static struct ui_strings {
 | 
				
			|||||||
    "line_quit",
 | 
					    "line_quit",
 | 
				
			||||||
    "line_alert",
 | 
					    "line_alert",
 | 
				
			||||||
    "line_normal",
 | 
					    "line_normal",
 | 
				
			||||||
 | 
					    "line_special",
 | 
				
			||||||
    "mplex_away",
 | 
					    "mplex_away",
 | 
				
			||||||
    "mplex_away_note",
 | 
					    "mplex_away_note",
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -122,6 +124,7 @@ static void ui_defaults(struct user_settings *settings)
 | 
				
			|||||||
    snprintf(settings->line_quit, LINE_HINT_MAX + 1, "%s", LINE_QUIT);
 | 
					    snprintf(settings->line_quit, LINE_HINT_MAX + 1, "%s", LINE_QUIT);
 | 
				
			||||||
    snprintf(settings->line_alert, LINE_HINT_MAX + 1, "%s", LINE_ALERT);
 | 
					    snprintf(settings->line_alert, LINE_HINT_MAX + 1, "%s", LINE_ALERT);
 | 
				
			||||||
    snprintf(settings->line_normal, LINE_HINT_MAX + 1, "%s", LINE_NORMAL);
 | 
					    snprintf(settings->line_normal, LINE_HINT_MAX + 1, "%s", LINE_NORMAL);
 | 
				
			||||||
 | 
					    snprintf(settings->line_special, LINE_HINT_MAX + 1, "%s", LINE_SPECIAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    settings->mplex_away = MPLEX_ON;
 | 
					    settings->mplex_away = MPLEX_ON;
 | 
				
			||||||
    snprintf (settings->mplex_away_note,
 | 
					    snprintf (settings->mplex_away_note,
 | 
				
			||||||
@@ -380,6 +383,10 @@ int settings_load(struct user_settings *s, const char *patharg)
 | 
				
			|||||||
            snprintf(s->line_normal, sizeof(s->line_normal), "%s", str);
 | 
					            snprintf(s->line_normal, sizeof(s->line_normal), "%s", str);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ( config_setting_lookup_string(setting, ui_strings.line_special, &str) ) {
 | 
				
			||||||
 | 
					            snprintf(s->line_special, sizeof(s->line_special), "%s", str);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        config_setting_lookup_bool (setting, ui_strings.mplex_away, &s->mplex_away);
 | 
					        config_setting_lookup_bool (setting, ui_strings.mplex_away, &s->mplex_away);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (config_setting_lookup_string (setting, ui_strings.mplex_away_note, &str)) {
 | 
					        if (config_setting_lookup_string (setting, ui_strings.mplex_away_note, &str)) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,6 +59,7 @@ struct user_settings {
 | 
				
			|||||||
    char line_quit[LINE_HINT_MAX + 1];
 | 
					    char line_quit[LINE_HINT_MAX + 1];
 | 
				
			||||||
    char line_alert[LINE_HINT_MAX + 1];
 | 
					    char line_alert[LINE_HINT_MAX + 1];
 | 
				
			||||||
    char line_normal[LINE_HINT_MAX + 1];
 | 
					    char line_normal[LINE_HINT_MAX + 1];
 | 
				
			||||||
 | 
					    char line_special[LINE_HINT_MAX + 1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char download_path[PATH_MAX];
 | 
					    char download_path[PATH_MAX];
 | 
				
			||||||
    char chatlogs_path[PATH_MAX];
 | 
					    char chatlogs_path[PATH_MAX];
 | 
				
			||||||
@@ -119,6 +120,7 @@ enum {
 | 
				
			|||||||
#define LINE_QUIT    "<--"
 | 
					#define LINE_QUIT    "<--"
 | 
				
			||||||
#define LINE_ALERT   "-!-"
 | 
					#define LINE_ALERT   "-!-"
 | 
				
			||||||
#define LINE_NORMAL  "---"
 | 
					#define LINE_NORMAL  "---"
 | 
				
			||||||
 | 
					#define LINE_SPECIAL ">>>"
 | 
				
			||||||
#define TIMESTAMP_DEFAULT      "%H:%M:%S"
 | 
					#define TIMESTAMP_DEFAULT      "%H:%M:%S"
 | 
				
			||||||
#define LOG_TIMESTAMP_DEFAULT  "%Y/%m/%d [%H:%M:%S]"
 | 
					#define LOG_TIMESTAMP_DEFAULT  "%Y/%m/%d [%H:%M:%S]"
 | 
				
			||||||
#define MPLEX_AWAY_NOTE "Detached from screen"
 | 
					#define MPLEX_AWAY_NOTE "Detached from screen"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								src/toxic.c
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								src/toxic.c
									
									
									
									
									
								
							@@ -49,6 +49,7 @@
 | 
				
			|||||||
#include "toxic.h"
 | 
					#include "toxic.h"
 | 
				
			||||||
#include "windows.h"
 | 
					#include "windows.h"
 | 
				
			||||||
#include "friendlist.h"
 | 
					#include "friendlist.h"
 | 
				
			||||||
 | 
					#include "groupchat.h"
 | 
				
			||||||
#include "prompt.h"
 | 
					#include "prompt.h"
 | 
				
			||||||
#include "misc_tools.h"
 | 
					#include "misc_tools.h"
 | 
				
			||||||
#include "file_transfers.h"
 | 
					#include "file_transfers.h"
 | 
				
			||||||
@@ -282,6 +283,17 @@ static void print_init_messages(ToxWindow *toxwin)
 | 
				
			|||||||
        line_info_add(toxwin, NULL, NULL, NULL, SYS_MSG, 0, 0, init_messages.msgs[i]);
 | 
					        line_info_add(toxwin, NULL, NULL, NULL, SYS_MSG, 0, 0, init_messages.msgs[i]);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void load_groups(Tox *m)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					    size_t numgroups = tox_group_get_number_groups(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < numgroups; ++i) {
 | 
				
			||||||
 | 
					        if (init_groupchat_win(m, i, NULL, 0) == -1)
 | 
				
			||||||
 | 
					            tox_group_leave(m, i, NULL, 0, NULL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void load_friendlist(Tox *m)
 | 
					static void load_friendlist(Tox *m)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    size_t i;
 | 
					    size_t i;
 | 
				
			||||||
@@ -529,15 +541,24 @@ static void init_tox_callbacks(Tox *m)
 | 
				
			|||||||
    tox_callback_friend_status(m, on_statuschange, NULL);
 | 
					    tox_callback_friend_status(m, on_statuschange, NULL);
 | 
				
			||||||
    tox_callback_friend_status_message(m, on_statusmessagechange, NULL);
 | 
					    tox_callback_friend_status_message(m, on_statusmessagechange, NULL);
 | 
				
			||||||
    tox_callback_friend_read_receipt(m, on_read_receipt, NULL);
 | 
					    tox_callback_friend_read_receipt(m, on_read_receipt, NULL);
 | 
				
			||||||
    tox_callback_group_invite(m, on_groupinvite, NULL);
 | 
					 | 
				
			||||||
    tox_callback_group_message(m, on_groupmessage, NULL);
 | 
					 | 
				
			||||||
    tox_callback_group_action(m, on_groupaction, NULL);
 | 
					 | 
				
			||||||
    tox_callback_group_namelist_change(m, on_group_namelistchange, NULL);
 | 
					 | 
				
			||||||
    tox_callback_group_title(m, on_group_titlechange, NULL);
 | 
					 | 
				
			||||||
    tox_callback_file_recv(m, on_file_recv, NULL);
 | 
					    tox_callback_file_recv(m, on_file_recv, NULL);
 | 
				
			||||||
    tox_callback_file_chunk_request(m, on_file_chunk_request, NULL);
 | 
					    tox_callback_file_chunk_request(m, on_file_chunk_request, NULL);
 | 
				
			||||||
    tox_callback_file_recv_control(m, on_file_control, NULL);
 | 
					    tox_callback_file_recv_control(m, on_file_control, NULL);
 | 
				
			||||||
    tox_callback_file_recv_chunk(m, on_file_recv_chunk, NULL);
 | 
					    tox_callback_file_recv_chunk(m, on_file_recv_chunk, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_invite(m, on_group_invite, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_message(m, on_group_message, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_private_message(m, on_group_private_message, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_peer_join(m, on_group_peer_join, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_peer_exit(m, on_group_peer_exit, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_peer_name(m, on_group_nick_change, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_peer_status(m, on_group_status_change, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_topic(m, on_group_topic_change, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_peer_limit(m, on_group_peer_limit, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_privacy_state(m, on_group_privacy_state, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_password(m, on_group_password, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_self_join(m, on_group_self_join, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_join_fail(m, on_group_rejected, NULL);
 | 
				
			||||||
 | 
					    tox_callback_group_moderation(m, on_group_moderation, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void init_tox_options(struct Tox_Options *tox_opts)
 | 
					static void init_tox_options(struct Tox_Options *tox_opts)
 | 
				
			||||||
@@ -1211,6 +1232,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pthread_mutex_lock(&Winthread.lock);
 | 
					    pthread_mutex_lock(&Winthread.lock);
 | 
				
			||||||
 | 
					    load_groups(m);
 | 
				
			||||||
    print_init_messages(prompt);
 | 
					    print_init_messages(prompt);
 | 
				
			||||||
    pthread_mutex_unlock(&Winthread.lock);
 | 
					    pthread_mutex_unlock(&Winthread.lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								src/toxic.h
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								src/toxic.h
									
									
									
									
									
								
							@@ -114,11 +114,10 @@ void on_nickchange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t
 | 
				
			|||||||
void on_statuschange(Tox *m, uint32_t friendnumber, TOX_USER_STATUS status, void *userdata);
 | 
					void on_statuschange(Tox *m, uint32_t friendnumber, TOX_USER_STATUS status, void *userdata);
 | 
				
			||||||
void on_statusmessagechange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata);
 | 
					void on_statusmessagechange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata);
 | 
				
			||||||
void on_friendadded(Tox *m, uint32_t friendnumber, bool sort);
 | 
					void on_friendadded(Tox *m, uint32_t friendnumber, bool sort);
 | 
				
			||||||
void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *message, uint16_t length, void *userdata);
 | 
					void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length,
 | 
				
			||||||
void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *action, uint16_t length, void *userdata);
 | 
					                           void *userdata);
 | 
				
			||||||
void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t type, const uint8_t *group_pub_key, uint16_t length,
 | 
					void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t type, const uint8_t *group_pub_key, uint16_t length,
 | 
				
			||||||
                    void *userdata);
 | 
					                    void *userdata);
 | 
				
			||||||
void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t change, void *userdata);
 | 
					 | 
				
			||||||
void on_group_titlechange(Tox *m, int groupnumber, int peernumber, const uint8_t *title, uint8_t length,
 | 
					void on_group_titlechange(Tox *m, int groupnumber, int peernumber, const uint8_t *title, uint8_t length,
 | 
				
			||||||
                          void *userdata);
 | 
					                          void *userdata);
 | 
				
			||||||
void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length,
 | 
					void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length,
 | 
				
			||||||
@@ -130,5 +129,25 @@ void on_file_recv(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint32_t k
 | 
				
			|||||||
                  const uint8_t *filename, size_t filename_length, void *userdata);
 | 
					                  const uint8_t *filename, size_t filename_length, void *userdata);
 | 
				
			||||||
void on_typing_change(Tox *m, uint32_t friendnumber, bool is_typing, void *userdata);
 | 
					void on_typing_change(Tox *m, uint32_t friendnumber, bool is_typing, void *userdata);
 | 
				
			||||||
void on_read_receipt(Tox *m, uint32_t friendnumber, uint32_t receipt, void *userdata);
 | 
					void on_read_receipt(Tox *m, uint32_t friendnumber, uint32_t receipt, void *userdata);
 | 
				
			||||||
 | 
					void on_group_invite(Tox *m, uint32_t friendnumber, const uint8_t *invite_data, size_t length, void *userdata);
 | 
				
			||||||
 | 
					void on_group_message(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_MESSAGE_TYPE type,
 | 
				
			||||||
 | 
					                      const uint8_t *message, size_t length, void *userdata);
 | 
				
			||||||
 | 
					void on_group_private_message(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *message, size_t length,
 | 
				
			||||||
 | 
					                              void *userdata);
 | 
				
			||||||
 | 
					void on_group_peer_join(Tox *m, uint32_t groupnumber, uint32_t peernumber, void *userdata);
 | 
				
			||||||
 | 
					void on_group_peer_exit(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *partmsg, size_t length,
 | 
				
			||||||
 | 
					                        void *userdata);
 | 
				
			||||||
 | 
					void on_group_topic_change(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *topic, size_t length,
 | 
				
			||||||
 | 
					                           void *userdata);
 | 
				
			||||||
 | 
					void on_group_peer_limit(Tox *m, uint32_t groupnumber, uint32_t peer_limit, void *userdata);
 | 
				
			||||||
 | 
					void on_group_privacy_state(Tox *m, uint32_t groupnumber, TOX_GROUP_PRIVACY_STATE privacy_state, void *userdata);
 | 
				
			||||||
 | 
					void on_group_password(Tox *m, uint32_t groupnumber, const uint8_t *password, size_t length, void *userdata);
 | 
				
			||||||
 | 
					void on_group_nick_change(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *newname, size_t length,
 | 
				
			||||||
 | 
					                          void *userdata);
 | 
				
			||||||
 | 
					void on_group_status_change(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_USER_STATUS status, void *userdata);
 | 
				
			||||||
 | 
					void on_group_self_join(Tox *m, uint32_t groupnumber, void *userdata);
 | 
				
			||||||
 | 
					void on_group_rejected(Tox *m, uint32_t groupnumber, TOX_GROUP_JOIN_FAIL type, void *userdata);
 | 
				
			||||||
 | 
					void on_group_moderation(Tox *m, uint32_t groupnumber, uint32_t source_peernum, uint32_t target_peernum,
 | 
				
			||||||
 | 
					                         TOX_GROUP_MOD_EVENT type, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif  /* #define TOXIC_H */
 | 
					#endif  /* #define TOXIC_H */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										172
									
								
								src/windows.c
									
									
									
									
									
								
							
							
						
						
									
										172
									
								
								src/windows.c
									
									
									
									
									
								
							@@ -151,8 +151,18 @@ void on_friendadded(Tox *m, uint32_t friendnumber, bool sort)
 | 
				
			|||||||
    store_data(m, DATA_FILE);
 | 
					    store_data(m, DATA_FILE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *message, uint16_t length,
 | 
					void on_group_invite(Tox *m, uint32_t friendnumber, const uint8_t *invite_data, size_t length, void *userdata)
 | 
				
			||||||
                     void *userdata)
 | 
					{
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
 | 
					        if (windows[i].onGroupInvite != NULL)
 | 
				
			||||||
 | 
					            windows[i].onGroupInvite(&windows[i], m, friendnumber, (char *) invite_data, length);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void on_group_message(Tox *m, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
 | 
				
			||||||
 | 
					                      const uint8_t *message, size_t length, void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    char msg[MAX_STR_SIZE + 1];
 | 
					    char msg[MAX_STR_SIZE + 1];
 | 
				
			||||||
    length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
 | 
					    length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
 | 
				
			||||||
@@ -161,56 +171,151 @@ void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *mes
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
        if (windows[i].onGroupMessage != NULL)
 | 
					        if (windows[i].onGroupMessage != NULL)
 | 
				
			||||||
            windows[i].onGroupMessage(&windows[i], m, groupnumber, peernumber, msg, length);
 | 
					            windows[i].onGroupMessage(&windows[i], m, groupnumber, peer_id, type, msg, length);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *action, uint16_t length,
 | 
					void on_group_private_message(Tox *m, uint32_t groupnumber, uint32_t peer_id, const uint8_t *message,
 | 
				
			||||||
 | 
					                              size_t length, void *userdata)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char msg[MAX_STR_SIZE + 1];
 | 
				
			||||||
 | 
					    length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
 | 
					        if (windows[i].onGroupPrivateMessage != NULL)
 | 
				
			||||||
 | 
					            windows[i].onGroupPrivateMessage(&windows[i], m, groupnumber, peer_id, msg, length);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void on_group_status_change(Tox *m, uint32_t groupnumber, uint32_t peer_id, TOX_USER_STATUS status, void *userdata)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
 | 
					        if (windows[i].onGroupStatusChange != NULL)
 | 
				
			||||||
 | 
					            windows[i].onGroupStatusChange(&windows[i], m, groupnumber, peer_id, status);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void on_group_peer_join(Tox *m, uint32_t groupnumber, uint32_t peer_id, void *userdata)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
 | 
					        if (windows[i].onGroupPeerJoin != NULL)
 | 
				
			||||||
 | 
					            windows[i].onGroupPeerJoin(&windows[i], m, groupnumber, peer_id);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void on_group_peer_exit(Tox *m, uint32_t groupnumber, uint32_t peer_id, const uint8_t *partmsg, size_t length,
 | 
				
			||||||
                        void *userdata)
 | 
					                        void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    char msg[MAX_STR_SIZE + 1];
 | 
					    char msg[MAX_STR_SIZE + 1];
 | 
				
			||||||
    length = copy_tox_str(msg, sizeof(msg), (const char *) action, length);
 | 
					
 | 
				
			||||||
 | 
					    if (length == 0 || !partmsg) {
 | 
				
			||||||
 | 
					        strcpy(msg, "Quit");
 | 
				
			||||||
 | 
					        length = strlen(msg);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        length = copy_tox_str(msg, sizeof(msg), (const char *) partmsg, length);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t i;
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
        if (windows[i].onGroupAction != NULL)
 | 
					        if (windows[i].onGroupPeerExit != NULL)
 | 
				
			||||||
            windows[i].onGroupAction(&windows[i], m, groupnumber, peernumber, msg, length);
 | 
					            windows[i].onGroupPeerExit(&windows[i], m, groupnumber, peer_id, msg, length);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t type, const uint8_t *group_pub_key, uint16_t length,
 | 
					void on_group_topic_change(Tox *m, uint32_t groupnumber, uint32_t peer_id, const uint8_t *topic, size_t length,
 | 
				
			||||||
                    void *userdata)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    size_t i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
					 | 
				
			||||||
        if (windows[i].onGroupInvite != NULL)
 | 
					 | 
				
			||||||
            windows[i].onGroupInvite(&windows[i], m, friendnumber, type, (char *) group_pub_key, length);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t change, void *userdata)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    size_t i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
					 | 
				
			||||||
        if (windows[i].onGroupNamelistChange != NULL)
 | 
					 | 
				
			||||||
            windows[i].onGroupNamelistChange(&windows[i], m, groupnumber, peernumber, change);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void on_group_titlechange(Tox *m, int groupnumber, int peernumber, const uint8_t *title, uint8_t length,
 | 
					 | 
				
			||||||
                           void *userdata)
 | 
					                           void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    char data[MAX_STR_SIZE + 1];
 | 
					    char data[MAX_STR_SIZE + 1];
 | 
				
			||||||
    length = copy_tox_str(data, sizeof(data), (const char *) title, length);
 | 
					    length = copy_tox_str(data, sizeof(data), (const char *) topic, length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t i;
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
        if (windows[i].onGroupTitleChange != NULL)
 | 
					        if (windows[i].onGroupTopicChange != NULL)
 | 
				
			||||||
            windows[i].onGroupTitleChange(&windows[i], m, groupnumber, peernumber, data, length);
 | 
					            windows[i].onGroupTopicChange(&windows[i], m, groupnumber, peer_id, data, length);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void on_group_peer_limit(Tox *m, uint32_t groupnumber, uint32_t peer_limit, void *userdata)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
 | 
					        if (windows[i].onGroupPeerLimit != NULL)
 | 
				
			||||||
 | 
					            windows[i].onGroupPeerLimit(&windows[i], m, groupnumber, peer_limit);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void on_group_privacy_state(Tox *m, uint32_t groupnumber, TOX_GROUP_PRIVACY_STATE privacy_state, void *userdata)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
 | 
					        if (windows[i].onGroupPrivacyState != NULL)
 | 
				
			||||||
 | 
					            windows[i].onGroupPrivacyState(&windows[i], m, groupnumber, privacy_state);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void on_group_password(Tox *m, uint32_t groupnumber, const uint8_t *password, size_t length, void *userdata)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
 | 
					        if (windows[i].onGroupPassword != NULL)
 | 
				
			||||||
 | 
					            windows[i].onGroupPassword(&windows[i], m, groupnumber, (char *) password, length);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void on_group_nick_change(Tox *m, uint32_t groupnumber, uint32_t peer_id, const uint8_t *newname, size_t length,
 | 
				
			||||||
 | 
					                          void *userdata)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char name[TOXIC_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
 | 
					    length = copy_tox_str(name, sizeof(name), (const char *) newname, length);
 | 
				
			||||||
 | 
					    filter_str(name, length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
 | 
					        if (windows[i].onGroupNickChange != NULL)
 | 
				
			||||||
 | 
					            windows[i].onGroupNickChange(&windows[i], m, groupnumber, peer_id, name, length);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void on_group_self_join(Tox *m, uint32_t groupnumber, void *userdata)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
 | 
					        if (windows[i].onGroupSelfJoin != NULL)
 | 
				
			||||||
 | 
					            windows[i].onGroupSelfJoin(&windows[i], m, groupnumber);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void on_group_rejected(Tox *m, uint32_t groupnumber, TOX_GROUP_JOIN_FAIL type, void *userdata)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
 | 
					        if (windows[i].onGroupRejected != NULL)
 | 
				
			||||||
 | 
					            windows[i].onGroupRejected(&windows[i], m, groupnumber, type);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void on_group_moderation(Tox *m, uint32_t groupnumber, uint32_t source_peer_id, uint32_t target_peer_id,
 | 
				
			||||||
 | 
					                         TOX_GROUP_MOD_EVENT type, void *userdata)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
 | 
				
			||||||
 | 
					        if (windows[i].onGroupModeration != NULL)
 | 
				
			||||||
 | 
					            windows[i].onGroupModeration(&windows[i], m, groupnumber, source_peer_id, target_peer_id, type);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -527,9 +632,8 @@ static void draw_bar(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void draw_active_window(Tox *m)
 | 
					void draw_active_window(Tox *m)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ToxWindow *a = active_window;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pthread_mutex_lock(&Winthread.lock);
 | 
					    pthread_mutex_lock(&Winthread.lock);
 | 
				
			||||||
 | 
					    ToxWindow *a = active_window;
 | 
				
			||||||
    a->alert = WINDOW_ALERT_NONE;
 | 
					    a->alert = WINDOW_ALERT_NONE;
 | 
				
			||||||
    pthread_mutex_unlock(&Winthread.lock);
 | 
					    pthread_mutex_unlock(&Winthread.lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -121,11 +121,6 @@ struct ToxWindow {
 | 
				
			|||||||
    void(*onNickChange)(ToxWindow *, Tox *, uint32_t, const char *, size_t);
 | 
					    void(*onNickChange)(ToxWindow *, Tox *, uint32_t, const char *, size_t);
 | 
				
			||||||
    void(*onStatusChange)(ToxWindow *, Tox *, uint32_t, TOX_USER_STATUS);
 | 
					    void(*onStatusChange)(ToxWindow *, Tox *, uint32_t, TOX_USER_STATUS);
 | 
				
			||||||
    void(*onStatusMessageChange)(ToxWindow *, uint32_t, const char *, size_t);
 | 
					    void(*onStatusMessageChange)(ToxWindow *, uint32_t, const char *, size_t);
 | 
				
			||||||
    void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t);
 | 
					 | 
				
			||||||
    void(*onGroupAction)(ToxWindow *, Tox *, int, int, const char *, uint16_t);
 | 
					 | 
				
			||||||
    void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t);
 | 
					 | 
				
			||||||
    void(*onGroupNamelistChange)(ToxWindow *, Tox *, int, int, uint8_t);
 | 
					 | 
				
			||||||
    void(*onGroupTitleChange)(ToxWindow *, Tox *, int, int, const char *, uint8_t);
 | 
					 | 
				
			||||||
    void(*onFileChunkRequest)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, size_t);
 | 
					    void(*onFileChunkRequest)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, size_t);
 | 
				
			||||||
    void(*onFileRecvChunk)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t);
 | 
					    void(*onFileRecvChunk)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t);
 | 
				
			||||||
    void(*onFileControl)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_FILE_CONTROL);
 | 
					    void(*onFileControl)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_FILE_CONTROL);
 | 
				
			||||||
@@ -133,6 +128,21 @@ struct ToxWindow {
 | 
				
			|||||||
    void(*onTypingChange)(ToxWindow *, Tox *, uint32_t, bool);
 | 
					    void(*onTypingChange)(ToxWindow *, Tox *, uint32_t, bool);
 | 
				
			||||||
    void(*onReadReceipt)(ToxWindow *, Tox *, uint32_t, uint32_t);
 | 
					    void(*onReadReceipt)(ToxWindow *, Tox *, uint32_t, uint32_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void(*onGroupInvite)(ToxWindow *, Tox *, uint32_t, const char *, size_t);
 | 
				
			||||||
 | 
					    void(*onGroupMessage)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_MESSAGE_TYPE, const char *, size_t);
 | 
				
			||||||
 | 
					    void(*onGroupPrivateMessage)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
 | 
				
			||||||
 | 
					    void(*onGroupPeerJoin)(ToxWindow *, Tox *, uint32_t, uint32_t);
 | 
				
			||||||
 | 
					    void(*onGroupPeerExit)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
 | 
				
			||||||
 | 
					    void(*onGroupNickChange)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
 | 
				
			||||||
 | 
					    void(*onGroupStatusChange)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_USER_STATUS);
 | 
				
			||||||
 | 
					    void(*onGroupTopicChange)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
 | 
				
			||||||
 | 
					    void(*onGroupPeerLimit)(ToxWindow *, Tox *, uint32_t, uint32_t);
 | 
				
			||||||
 | 
					    void(*onGroupPrivacyState)(ToxWindow *, Tox *, uint32_t, TOX_GROUP_PRIVACY_STATE);
 | 
				
			||||||
 | 
					    void(*onGroupPassword)(ToxWindow *, Tox *, uint32_t, const char *, size_t);
 | 
				
			||||||
 | 
					    void(*onGroupSelfJoin)(ToxWindow *, Tox *, uint32_t);
 | 
				
			||||||
 | 
					    void(*onGroupRejected)(ToxWindow *, Tox *, uint32_t, TOX_GROUP_JOIN_FAIL);
 | 
				
			||||||
 | 
					    void(*onGroupModeration)(ToxWindow *, Tox *, uint32_t, uint32_t, uint32_t, TOX_GROUP_MOD_EVENT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef AUDIO
 | 
					#ifdef AUDIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void(*onInvite)(ToxWindow *, ToxAV *, uint32_t, int);
 | 
					    void(*onInvite)(ToxWindow *, ToxAV *, uint32_t, int);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user