mirror of
https://github.com/Tha14/toxic.git
synced 2024-11-14 17:23:03 +01:00
modularize string arrays for line completion
Instead of using various different forms of string arrays and having to handle them differently for string completion, we now always use char pointer arrays. This allows us to remove some large stack allocations, remove a bunch of confusing defines that keep track of global array sizes, and generally unclutters the code so it's easier to read.
This commit is contained in:
parent
2b43340c90
commit
7560bc9547
@ -437,6 +437,7 @@ inline__ DeviceError write_out(uint32_t device_idx, const int16_t *data, uint32_
|
||||
ALuint *bufids = malloc(processed * sizeof(ALuint));
|
||||
|
||||
if (bufids == NULL) {
|
||||
pthread_mutex_unlock(device->mutex);
|
||||
return de_InternalError;
|
||||
}
|
||||
|
||||
|
@ -51,21 +51,6 @@ static void print_ac_matches(ToxWindow *self, Tox *m, char **list, size_t n_matc
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
|
||||
}
|
||||
|
||||
static void print_dir_matches(ToxWindow *self, Tox *m, const void *list, size_t n_items, size_t size)
|
||||
{
|
||||
if (m) {
|
||||
execute(self->chatwin->history, self, m, "/clear", GLOBAL_COMMAND_MODE);
|
||||
}
|
||||
|
||||
const char *L = (char *)list;
|
||||
|
||||
for (size_t i = 0; i < n_items; ++i) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", &L[i * size]);
|
||||
}
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
|
||||
}
|
||||
|
||||
/* puts match in match buffer. if more than one match, add first n chars that are identical.
|
||||
* e.g. if matches contains: [foo, foobar, foe] we put fo in match.
|
||||
*
|
||||
@ -102,8 +87,7 @@ static size_t get_str_match(ToxWindow *self, char *match, size_t match_sz, char
|
||||
* then fills line with the complete word. e.g. "Hello jo" would complete the line
|
||||
* with "Hello john". If multiple matches, prints out all the matches and semi-completes line.
|
||||
*
|
||||
* list is a pointer to the list of strings being compared, n_items is the number of items
|
||||
* in the list, and size is the size of each item in the list.
|
||||
* `list` is a pointer to `n_items` strings. Each string in the list must be <= MAX_STR_SIZE.
|
||||
*
|
||||
* dir_search should be true if the line being completed is a file path.
|
||||
*
|
||||
@ -112,7 +96,7 @@ static size_t get_str_match(ToxWindow *self, char *match, size_t match_sz, char
|
||||
*
|
||||
* Note: This function should not be called directly. Use complete_line() and complete_path() instead.
|
||||
*/
|
||||
static int complete_line_helper(ToxWindow *self, const void *list, const size_t n_items, size_t size, bool dir_search)
|
||||
static int complete_line_helper(ToxWindow *self, const char **list, const size_t n_items, bool dir_search)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
@ -120,11 +104,10 @@ static int complete_line_helper(ToxWindow *self, const void *list, const size_t
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ctx->len >= MAX_STR_SIZE || size > MAX_STR_SIZE) {
|
||||
if (ctx->len >= MAX_STR_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *L = (const char *) list;
|
||||
const char *endchrs = " ";
|
||||
char ubuf[MAX_STR_SIZE] = {0};
|
||||
|
||||
@ -172,29 +155,24 @@ static int complete_line_helper(ToxWindow *self, const void *list, const size_t
|
||||
int s_len = strlen(sub);
|
||||
size_t n_matches = 0;
|
||||
|
||||
char **matches = (char **)malloc_ptr_array(n_items, MAX_STR_SIZE, sizeof(char *));
|
||||
char **matches = (char **) malloc_ptr_array(n_items, MAX_STR_SIZE);
|
||||
|
||||
if (matches == NULL) {
|
||||
free(sub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
|
||||
/* put all list matches in matches array */
|
||||
for (i = 0; i < n_items; ++i) {
|
||||
char str[MAX_CMDNAME_SIZE + 1];
|
||||
snprintf(str, sizeof(str), "%s", &L[i * size]);
|
||||
|
||||
if (strncasecmp(str, sub, s_len) == 0) {
|
||||
strcpy(matches[n_matches++], str);
|
||||
for (size_t i = 0; i < n_items; ++i) {
|
||||
if (strncasecmp(list[i], sub, s_len) == 0) {
|
||||
snprintf(matches[n_matches++], MAX_STR_SIZE, "%s", list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
free(sub);
|
||||
|
||||
if (!n_matches) {
|
||||
free_ptr_array((void **) matches, n_items);
|
||||
free_ptr_array((void **) matches);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -205,7 +183,7 @@ static int complete_line_helper(ToxWindow *self, const void *list, const size_t
|
||||
char match[MAX_STR_SIZE];
|
||||
size_t match_len = get_str_match(self, match, sizeof(match), matches, n_matches, MAX_STR_SIZE);
|
||||
|
||||
free_ptr_array((void **) matches, n_items);
|
||||
free_ptr_array((void **) matches);
|
||||
|
||||
if (match_len == 0) {
|
||||
return 0;
|
||||
@ -281,14 +259,14 @@ static int complete_line_helper(ToxWindow *self, const void *list, const size_t
|
||||
return diff;
|
||||
}
|
||||
|
||||
int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size)
|
||||
int complete_line(ToxWindow *self, const char **list, size_t n_items)
|
||||
{
|
||||
return complete_line_helper(self, list, n_items, size, false);
|
||||
return complete_line_helper(self, list, n_items, false);
|
||||
}
|
||||
|
||||
static int complete_path(ToxWindow *self, const void *list, size_t n_items, size_t size)
|
||||
static int complete_path(ToxWindow *self, const char **list, const size_t n_items)
|
||||
{
|
||||
return complete_line_helper(self, list, n_items, size, true);
|
||||
return complete_line_helper(self, list, n_items, true);
|
||||
}
|
||||
|
||||
/* Transforms a tab complete starting with the shorthand "~" into the full home directory. */
|
||||
@ -365,14 +343,21 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
char dirnames[MAX_DIRS][NAME_MAX + 1];
|
||||
char **dirnames = (char **) malloc_ptr_array(MAX_DIRS, NAME_MAX + 1);
|
||||
|
||||
if (dirnames == NULL) {
|
||||
closedir(dp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct dirent *entry;
|
||||
|
||||
int dircount = 0;
|
||||
|
||||
while ((entry = readdir(dp)) && dircount < MAX_DIRS) {
|
||||
if (strncmp(entry->d_name, b_name, b_name_len) == 0
|
||||
&& strcmp(".", entry->d_name) && strcmp("..", entry->d_name)) {
|
||||
snprintf(dirnames[dircount], sizeof(dirnames[dircount]), "%s", entry->d_name);
|
||||
snprintf(dirnames[dircount], NAME_MAX + 1, "%s", entry->d_name);
|
||||
++dircount;
|
||||
}
|
||||
}
|
||||
@ -380,13 +365,18 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)
|
||||
closedir(dp);
|
||||
|
||||
if (dircount == 0) {
|
||||
free_ptr_array((void **) dirnames);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dircount > 1) {
|
||||
qsort(dirnames, dircount, NAME_MAX + 1, qsort_strcasecmp_hlpr);
|
||||
print_dir_matches(self, m, dirnames, dircount, NAME_MAX + 1);
|
||||
qsort(dirnames, dircount, sizeof(char *), qsort_ptr_char_array_helper);
|
||||
print_ac_matches(self, m, dirnames, dircount);
|
||||
}
|
||||
|
||||
return complete_path(self, dirnames, dircount, NAME_MAX + 1);
|
||||
int ret = complete_path(self, (const char **) dirnames, dircount);
|
||||
|
||||
free_ptr_array((void **) dirnames);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -28,13 +28,16 @@
|
||||
* then fills line with the complete word. e.g. "Hello jo" would complete the line
|
||||
* with "Hello john". If multiple matches, prints out all the matches and semi-completes line.
|
||||
*
|
||||
* list is a pointer to the list of strings being compared, n_items is the number of items
|
||||
* in the list, and size is the size of each item in the list.
|
||||
* `list` is a pointer to `n_items` strings.
|
||||
*
|
||||
* dir_search should be true if the line being completed is a file path.
|
||||
*
|
||||
* Returns the difference between the old len and new len of line on success.
|
||||
* Returns -1 on error.
|
||||
*
|
||||
* Note: This function should not be called directly. Use complete_line() and complete_path() instead.
|
||||
*/
|
||||
int complete_line(ToxWindow *self, const void *list, size_t n_items, size_t size);
|
||||
int complete_line(ToxWindow *self, const char **list, size_t n_items);
|
||||
|
||||
/* Attempts to match /command "<incomplete-dir>" line to matching directories.
|
||||
* If there is only one match the line is auto-completed.
|
||||
|
97
src/chat.c
97
src/chat.c
@ -65,67 +65,50 @@ static void init_infobox(ToxWindow *self);
|
||||
static void kill_infobox(ToxWindow *self);
|
||||
#endif /* AUDIO */
|
||||
|
||||
#ifdef AUDIO
|
||||
#define AC_NUM_CHAT_COMMANDS_AUDIO 9
|
||||
#else
|
||||
#define AC_NUM_CHAT_COMMANDS_AUDIO 0
|
||||
#endif /* AUDIO */
|
||||
#ifdef PYTHON
|
||||
#define AC_NUM_CHAT_COMMANDS_PYTHON 1
|
||||
#else
|
||||
#define AC_NUM_CHAT_COMMANDS_PYTHON 0
|
||||
#endif /* PYTHON */
|
||||
#ifdef QRCODE
|
||||
#define AC_NUM_CHAT_COMMANDS_QRCODE 1
|
||||
#else
|
||||
#define AC_NUM_CHAT_COMMANDS_QRCODE 0
|
||||
#endif /* QRCODE */
|
||||
#define AC_NUM_CHAT_COMMANDS (21 + AC_NUM_CHAT_COMMANDS_AUDIO + AC_NUM_CHAT_COMMANDS_PYTHON + AC_NUM_CHAT_COMMANDS_QRCODE)
|
||||
|
||||
/* Array of chat command names used for tab completion. */
|
||||
static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
|
||||
{ "/accept" },
|
||||
{ "/add" },
|
||||
{ "/avatar" },
|
||||
{ "/cancel" },
|
||||
{ "/clear" },
|
||||
{ "/close" },
|
||||
{ "/connect" },
|
||||
{ "/exit" },
|
||||
{ "/group" },
|
||||
{ "/help" },
|
||||
{ "/invite" },
|
||||
{ "/join" },
|
||||
{ "/log" },
|
||||
{ "/myid" },
|
||||
static const char *chat_cmd_list[] = {
|
||||
"/accept",
|
||||
"/add",
|
||||
"/avatar",
|
||||
"/cancel",
|
||||
"/clear",
|
||||
"/close",
|
||||
"/connect",
|
||||
"/exit",
|
||||
"/group",
|
||||
"/help",
|
||||
"/invite",
|
||||
"/join",
|
||||
"/log",
|
||||
"/myid",
|
||||
#ifdef QRCODE
|
||||
{ "/myqr" },
|
||||
"/myqr",
|
||||
#endif /* QRCODE */
|
||||
{ "/nick" },
|
||||
{ "/note" },
|
||||
{ "/nospam" },
|
||||
{ "/quit" },
|
||||
{ "/savefile" },
|
||||
{ "/sendfile" },
|
||||
{ "/status" },
|
||||
"/nick",
|
||||
"/note",
|
||||
"/nospam",
|
||||
"/quit",
|
||||
"/savefile",
|
||||
"/sendfile",
|
||||
"/status",
|
||||
|
||||
#ifdef AUDIO
|
||||
|
||||
{ "/call" },
|
||||
{ "/answer" },
|
||||
{ "/reject" },
|
||||
{ "/hangup" },
|
||||
{ "/sdev" },
|
||||
{ "/mute" },
|
||||
{ "/sense" },
|
||||
{ "/video" },
|
||||
{ "/bitrate" },
|
||||
"/call",
|
||||
"/answer",
|
||||
"/reject",
|
||||
"/hangup",
|
||||
"/sdev",
|
||||
"/mute",
|
||||
"/sense",
|
||||
"/video",
|
||||
"/bitrate",
|
||||
|
||||
#endif /* AUDIO */
|
||||
|
||||
#ifdef PYTHON
|
||||
|
||||
{ "/run" },
|
||||
"/run",
|
||||
|
||||
#endif /* PYTHON */
|
||||
};
|
||||
@ -662,7 +645,7 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
|
||||
size_t d_len = strlen(d);
|
||||
|
||||
if (path_len + d_len >= file_path_buf_size) {
|
||||
path_len -= d_len;
|
||||
path_len = file_path_buf_size - d_len - 1;
|
||||
file_path[path_len] = '\0';
|
||||
}
|
||||
|
||||
@ -1090,14 +1073,14 @@ bool chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
#endif
|
||||
|
||||
else if (wcsncmp(ctx->line, L"/status ", wcslen(L"/status ")) == 0) {
|
||||
const char status_cmd_list[3][8] = {
|
||||
{"online"},
|
||||
{"away"},
|
||||
{"busy"},
|
||||
const char *status_cmd_list[] = {
|
||||
"online",
|
||||
"away",
|
||||
"busy",
|
||||
};
|
||||
diff = complete_line(self, status_cmd_list, 3, 8);
|
||||
diff = complete_line(self, status_cmd_list, sizeof(status_cmd_list) / sizeof(char *));
|
||||
} else {
|
||||
diff = complete_line(self, chat_cmd_list, AC_NUM_CHAT_COMMANDS, MAX_CMDNAME_SIZE);
|
||||
diff = complete_line(self, chat_cmd_list, sizeof(chat_cmd_list) / sizeof(char *));
|
||||
}
|
||||
|
||||
if (diff != -1) {
|
||||
|
@ -37,6 +37,7 @@ extern FriendsList Friends;
|
||||
|
||||
/* number of "#"'s in file transfer progress bar. Keep well below MAX_STR_SIZE */
|
||||
#define NUM_PROG_MARKS 50
|
||||
#define STR_BUF_SIZE 30
|
||||
|
||||
/* creates initial progress line that will be updated during file transfer.
|
||||
Assumes progline has room for at least MAX_STR_SIZE bytes */
|
||||
@ -59,10 +60,10 @@ void print_progress_bar(ToxWindow *self, double bps, double pct_done, uint32_t l
|
||||
return;
|
||||
}
|
||||
|
||||
char pct_str[24];
|
||||
char pct_str[STR_BUF_SIZE] = {0};
|
||||
snprintf(pct_str, sizeof(pct_str), "%.1f%%", pct_done);
|
||||
|
||||
char bps_str[24];
|
||||
char bps_str[STR_BUF_SIZE] = {0};
|
||||
bytes_convert_str(bps_str, sizeof(bps_str), bps);
|
||||
|
||||
char prog_line[NUM_PROG_MARKS + 1] = {0};
|
||||
|
@ -494,7 +494,7 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
} else if (!strcmp(argv[1], "txt")) {
|
||||
|
||||
#endif /* QRPNG */
|
||||
size_t qr_path_buf_size = dir_len + nick_len + strlen(QRCODE_FILENAME_EXT) + 1;
|
||||
size_t qr_path_buf_size = dir_len + nick_len + sizeof(QRCODE_FILENAME_EXT);
|
||||
char *qr_path = malloc(qr_path_buf_size);
|
||||
|
||||
if (qr_path == NULL) {
|
||||
@ -518,7 +518,7 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
|
||||
#ifdef QRPNG
|
||||
} else if (!strcmp(argv[1], "png")) {
|
||||
size_t qr_path_buf_size = dir_len + nick_len + strlen(QRCODE_FILENAME_EXT_PNG) + 1;
|
||||
size_t qr_path_buf_size = dir_len + nick_len + sizeof(QRCODE_FILENAME_EXT_PNG);
|
||||
char *qr_path = malloc(qr_path_buf_size);
|
||||
|
||||
if (qr_path == NULL) {
|
||||
|
122
src/groupchat.c
122
src/groupchat.c
@ -70,46 +70,34 @@ static int max_groupchat_index = 0;
|
||||
extern struct user_settings *user_settings;
|
||||
extern struct Winthread Winthread;
|
||||
|
||||
#ifdef PYTHON
|
||||
#define AC_NUM_GROUP_COMMANDS_PYTHON 1
|
||||
#else
|
||||
#define AC_NUM_GROUP_COMMANDS_PYTHON 0
|
||||
#endif /* PYTHON */
|
||||
#ifdef QRCODE
|
||||
#define AC_NUM_GROUP_COMMANDS_QRCODE 1
|
||||
#else
|
||||
#define AC_NUM_GROUP_COMMANDS_QRCODE 0
|
||||
#endif /* QRCODE */
|
||||
#define AC_NUM_GROUP_COMMANDS (19 + AC_NUM_GROUP_COMMANDS_PYTHON + AC_NUM_GROUP_COMMANDS_QRCODE)
|
||||
|
||||
/* Array of groupchat command names used for tab completion. */
|
||||
static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = {
|
||||
{ "/accept" },
|
||||
{ "/add" },
|
||||
{ "/avatar" },
|
||||
{ "/clear" },
|
||||
{ "/close" },
|
||||
{ "/connect" },
|
||||
{ "/decline" },
|
||||
{ "/exit" },
|
||||
{ "/group" },
|
||||
{ "/help" },
|
||||
{ "/log" },
|
||||
{ "/myid" },
|
||||
static const char *group_cmd_list[] = {
|
||||
"/accept",
|
||||
"/add",
|
||||
"/avatar",
|
||||
"/clear",
|
||||
"/close",
|
||||
"/connect",
|
||||
"/decline",
|
||||
"/exit",
|
||||
"/group",
|
||||
"/help",
|
||||
"/log",
|
||||
"/myid",
|
||||
#ifdef QRCODE
|
||||
{ "/myqr" },
|
||||
"/myqr",
|
||||
#endif /* QRCODE */
|
||||
{ "/nick" },
|
||||
{ "/note" },
|
||||
{ "/nospam" },
|
||||
{ "/quit" },
|
||||
{ "/requests" },
|
||||
{ "/status" },
|
||||
{ "/title" },
|
||||
"/nick",
|
||||
"/note",
|
||||
"/nospam",
|
||||
"/quit",
|
||||
"/requests",
|
||||
"/status",
|
||||
"/title",
|
||||
|
||||
#ifdef PYTHON
|
||||
|
||||
{ "/run" },
|
||||
"/run",
|
||||
|
||||
#endif /* PYTHON */
|
||||
};
|
||||
@ -166,7 +154,7 @@ int init_groupchat_win(Tox *m, uint32_t groupnum, uint8_t type, const char *titl
|
||||
|
||||
void free_groupchat(ToxWindow *self, uint32_t groupnum)
|
||||
{
|
||||
free(groupchats[groupnum].name_list);
|
||||
free_ptr_array((void **) groupchats[groupnum].name_list);
|
||||
free(groupchats[groupnum].peer_list);
|
||||
memset(&groupchats[groupnum], 0, sizeof(GroupChat));
|
||||
|
||||
@ -309,26 +297,26 @@ static void group_update_name_list(uint32_t groupnum)
|
||||
return;
|
||||
}
|
||||
|
||||
if (chat->name_list) {
|
||||
free(chat->name_list);
|
||||
if (!chat->name_list) {
|
||||
fprintf(stderr, "WARNING: name_list is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
chat->name_list = malloc(sizeof(char *) * chat->num_peers * TOX_MAX_NAME_LENGTH);
|
||||
size_t count = 0;
|
||||
|
||||
if (chat->name_list == NULL) {
|
||||
exit_toxic_err("failed in group_update_name_list", FATALERR_MEMORY);
|
||||
}
|
||||
|
||||
uint32_t i, count = 0;
|
||||
|
||||
for (i = 0; i < chat->max_idx; ++i) {
|
||||
for (uint32_t i = 0; i < chat->max_idx && count < chat->num_peers; ++i) {
|
||||
if (chat->peer_list[i].active) {
|
||||
memcpy(&chat->name_list[count * TOX_MAX_NAME_LENGTH], chat->peer_list[i].name, chat->peer_list[i].name_length + 1);
|
||||
memcpy(chat->name_list[count], chat->peer_list[i].name, chat->peer_list[i].name_length);
|
||||
chat->name_list[count][chat->peer_list[i].name_length] = 0;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
qsort(chat->name_list, count, TOX_MAX_NAME_LENGTH, qsort_strcasecmp_hlpr);
|
||||
if (count != chat->num_peers) {
|
||||
fprintf(stderr, "WARNING: count != chat->num_peers\n");
|
||||
}
|
||||
|
||||
qsort(chat->name_list, count, sizeof(char *), qsort_ptr_char_array_helper);
|
||||
}
|
||||
|
||||
/* Reallocates groupnum's peer list. Increase is true if the list needs to grow.
|
||||
@ -369,9 +357,7 @@ static void update_peer_list(Tox *m, uint32_t groupnum, uint32_t num_peers)
|
||||
|
||||
realloc_peer_list(chat, num_peers);
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < num_peers; ++i) {
|
||||
for (uint32_t i = 0; i < num_peers; ++i) {
|
||||
GroupPeer *peer = &chat->peer_list[i];
|
||||
|
||||
Tox_Err_Conference_Peer_Query err;
|
||||
@ -412,17 +398,29 @@ static void groupchat_onGroupNameListChange(ToxWindow *self, Tox *m, uint32_t gr
|
||||
return;
|
||||
}
|
||||
|
||||
if (chat->name_list) {
|
||||
free_ptr_array((void **) chat->name_list);
|
||||
chat->name_list = NULL;
|
||||
chat->num_peers = 0;
|
||||
}
|
||||
|
||||
Tox_Err_Conference_Peer_Query err;
|
||||
|
||||
uint32_t num_peers = tox_conference_peer_count(m, groupnum, &err);
|
||||
uint32_t old_num = chat->num_peers;
|
||||
|
||||
if (err == TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
|
||||
chat->num_peers = num_peers;
|
||||
} else {
|
||||
num_peers = old_num;
|
||||
if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
|
||||
fprintf(stderr, "groupchat_onGroupNameListChange() failed with error: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
chat->name_list = (char **) malloc_ptr_array(num_peers, TOX_MAX_NAME_LENGTH + 1);
|
||||
|
||||
if (chat->name_list == NULL) {
|
||||
fprintf(stderr, "groupchat_onGroupNameListChange(): Out of memory.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
chat->num_peers = num_peers;
|
||||
chat->max_idx = num_peers;
|
||||
update_peer_list(m, groupnum, num_peers);
|
||||
}
|
||||
@ -442,9 +440,7 @@ static void groupchat_onGroupPeerNameChange(ToxWindow *self, Tox *m, uint32_t gr
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < chat->max_idx; ++i) {
|
||||
for (uint32_t i = 0; i < chat->max_idx; ++i) {
|
||||
GroupPeer *peer = &chat->peer_list[i];
|
||||
|
||||
// Test against default tox name to prevent nick change spam on initial join (TODO: this is disgusting)
|
||||
@ -529,8 +525,7 @@ static bool groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
/* TODO: make this not suck */
|
||||
if (ctx->line[0] != L'/' || wcscmp(ctx->line, L"/me") == 0) {
|
||||
diff = complete_line(self, groupchats[self->num].name_list, groupchats[self->num].num_peers,
|
||||
TOX_MAX_NAME_LENGTH);
|
||||
diff = complete_line(self, (const char **) groupchats[self->num].name_list, groupchats[self->num].num_peers);
|
||||
} else if (wcsncmp(ctx->line, L"/avatar ", wcslen(L"/avatar ")) == 0) {
|
||||
diff = dir_match(self, m, ctx->line, L"/avatar");
|
||||
}
|
||||
@ -542,7 +537,7 @@ static bool groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
#endif
|
||||
else {
|
||||
diff = complete_line(self, group_cmd_list, AC_NUM_GROUP_COMMANDS, MAX_CMDNAME_SIZE);
|
||||
diff = complete_line(self, group_cmd_list, sizeof(group_cmd_list) / sizeof(char *));
|
||||
}
|
||||
|
||||
if (diff != -1) {
|
||||
@ -655,9 +650,8 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
mvwhline(ctx->sidebar, 1, 1, ACS_HLINE, SIDEBAR_WIDTH - 1);
|
||||
|
||||
int maxlines = y2 - SDBAR_OFST - CHATBOX_HEIGHT;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < num_peers && i < maxlines; ++i) {
|
||||
for (uint32_t i = 0; i < num_peers && i < maxlines; ++i) {
|
||||
wmove(ctx->sidebar, i + 2, 1);
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
@ -669,7 +663,7 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
int maxlen = SIDEBAR_WIDTH - 2;
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
memcpy(tmpnck, &groupchats[self->num].name_list[peer * TOX_MAX_NAME_LENGTH], maxlen);
|
||||
memcpy(tmpnck, groupchats[self->num].name_list[peer], maxlen);
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
tmpnck[maxlen] = '\0';
|
||||
|
@ -48,7 +48,7 @@ typedef struct {
|
||||
GroupPeer *peer_list;
|
||||
uint32_t max_idx;
|
||||
|
||||
char *name_list;
|
||||
char **name_list;
|
||||
uint32_t num_peers;
|
||||
|
||||
} GroupChat;
|
||||
|
@ -42,9 +42,7 @@ extern struct user_settings *user_settings;
|
||||
|
||||
void clear_screen(void)
|
||||
{
|
||||
if (system("clear") != 0) {
|
||||
fprintf(stderr, "Warning: system() failed to clear screen\n");
|
||||
}
|
||||
printf("\033[2J\033[1;1H");
|
||||
}
|
||||
|
||||
void hst_to_net(uint8_t *num, uint16_t numbytes)
|
||||
@ -241,6 +239,12 @@ int qsort_strcasecmp_hlpr(const void *str1, const void *str2)
|
||||
return strcasecmp((const char *) str1, (const char *) str2);
|
||||
}
|
||||
|
||||
/* case-insensitive string compare function for use with qsort */
|
||||
int qsort_ptr_char_array_helper(const void *str1, const void *str2)
|
||||
{
|
||||
return strcasecmp(*(char **)str1, *(char **)str2);
|
||||
}
|
||||
|
||||
/* Returns 1 if nick is valid, 0 if not. A valid toxic nick:
|
||||
- cannot be empty
|
||||
- cannot start with a space
|
||||
@ -620,30 +624,33 @@ bool is_ip6_address(const char *address)
|
||||
}
|
||||
|
||||
/*
|
||||
* Frees `length` members of pointer array `arr` and frees `arr`.
|
||||
* Frees all members of a pointer array plus `arr`.
|
||||
*/
|
||||
void free_ptr_array(void **arr, size_t length)
|
||||
void free_ptr_array(void **arr)
|
||||
{
|
||||
if (arr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
free(arr[i]);
|
||||
void **tmp = arr;
|
||||
|
||||
while (*arr) {
|
||||
free(*arr);
|
||||
++arr;
|
||||
}
|
||||
|
||||
free(arr);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a new array of `length` pointers of size `ptr_size`. Each pointer is allocated `bytes` bytes.
|
||||
* Returns a null terminated array of `length` pointers. Each pointer is allocated `bytes` bytes.
|
||||
* Returns NULL on failure.
|
||||
*
|
||||
* The caller is responsible for freeing the array with `free_ptr_array`.
|
||||
*/
|
||||
void **malloc_ptr_array(size_t length, size_t bytes, size_t ptr_size)
|
||||
void **malloc_ptr_array(size_t length, size_t bytes)
|
||||
{
|
||||
void **arr = malloc(length * ptr_size);
|
||||
void **arr = malloc((length + 1) * sizeof(void *));
|
||||
|
||||
if (arr == NULL) {
|
||||
return NULL;
|
||||
@ -653,10 +660,12 @@ void **malloc_ptr_array(size_t length, size_t bytes, size_t ptr_size)
|
||||
arr[i] = malloc(bytes);
|
||||
|
||||
if (arr[i] == NULL) {
|
||||
free_ptr_array(arr, i);
|
||||
free_ptr_array(arr);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
arr[length] = NULL;
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
@ -107,6 +107,9 @@ void alert_window(ToxWindow *self, int type, bool is_beep);
|
||||
/* case-insensitive string compare function for use with qsort */
|
||||
int qsort_strcasecmp_hlpr(const void *str1, const void *str2);
|
||||
|
||||
/* case-insensitive string compare function for use with qsort */
|
||||
int qsort_ptr_char_array_helper(const void *str1, const void *str2);
|
||||
|
||||
/* Returns 1 if nick is valid, 0 if not. A valid toxic nick:
|
||||
- cannot be empty
|
||||
- cannot start with a space
|
||||
@ -196,16 +199,16 @@ bool is_ip6_address(const char *address);
|
||||
|
||||
|
||||
/*
|
||||
* Frees `length` members of pointer array `arr` and frees `arr`.
|
||||
* Frees all members of a pointer array plus `arr`.
|
||||
*/
|
||||
void free_ptr_array(void **arr, size_t length);
|
||||
void free_ptr_array(void **arr);
|
||||
|
||||
/*
|
||||
* Returns a new array of `length` pointers of size `ptr_size`. Each pointer is allocated `bytes` bytes.
|
||||
* Returns a null terminated array of `length` pointers. Each pointer is allocated `bytes` bytes.
|
||||
* Returns NULL on failure.
|
||||
*
|
||||
* The caller is responsible for freeing the array with `free_ptr_array`.
|
||||
*/
|
||||
void **malloc_ptr_array(size_t length, size_t bytes, size_t ptr_size);
|
||||
void **malloc_ptr_array(size_t length, size_t bytes);
|
||||
|
||||
#endif /* MISC_TOOLS_H */
|
||||
|
81
src/prompt.c
81
src/prompt.c
@ -49,68 +49,47 @@ extern struct Winthread Winthread;
|
||||
|
||||
extern FriendsList Friends;
|
||||
FriendRequests FrndRequests;
|
||||
#ifdef AUDIO
|
||||
#define AC_NUM_GLOB_COMMANDS_AUDIO 2
|
||||
#else
|
||||
#define AC_NUM_GLOB_COMMANDS_AUDIO 0
|
||||
#endif /* AUDIO */
|
||||
#ifdef VIDEO
|
||||
#define AC_NUM_GLOB_COMMANDS_VIDEO 2
|
||||
#else
|
||||
#define AC_NUM_GLOB_COMMANDS_VIDEO 0
|
||||
#endif /* VIDEO */
|
||||
#ifdef PYTHON
|
||||
#define AC_NUM_GLOB_COMMANDS_PYTHON 1
|
||||
#else
|
||||
#define AC_NUM_GLOB_COMMANDS_PYTHON 0
|
||||
#endif /* PYTHON */
|
||||
#ifdef QRCODE
|
||||
#define AC_NUM_GLOB_COMMANDS_QRCODE 1
|
||||
#else
|
||||
#define AC_NUM_GLOB_COMMANDS_QRCODE 0
|
||||
#endif /* QRCODE */
|
||||
#define AC_NUM_GLOB_COMMANDS (17 + AC_NUM_GLOB_COMMANDS_AUDIO + AC_NUM_GLOB_COMMANDS_VIDEO + AC_NUM_GLOB_COMMANDS_PYTHON + AC_NUM_GLOB_COMMANDS_QRCODE)
|
||||
|
||||
/* Array of global command names used for tab completion. */
|
||||
static const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
|
||||
{ "/accept" },
|
||||
{ "/add" },
|
||||
{ "/avatar" },
|
||||
{ "/clear" },
|
||||
{ "/connect" },
|
||||
{ "/decline" },
|
||||
{ "/exit" },
|
||||
{ "/group" },
|
||||
{ "/help" },
|
||||
{ "/log" },
|
||||
{ "/myid" },
|
||||
static const char *glob_cmd_list[] = {
|
||||
"/accept",
|
||||
"/add",
|
||||
"/avatar",
|
||||
"/clear",
|
||||
"/connect",
|
||||
"/decline",
|
||||
"/exit",
|
||||
"/group",
|
||||
"/help",
|
||||
"/log",
|
||||
"/myid",
|
||||
#ifdef QRCODE
|
||||
{ "/myqr" },
|
||||
"/myqr",
|
||||
#endif /* QRCODE */
|
||||
{ "/nick" },
|
||||
{ "/note" },
|
||||
{ "/nospam" },
|
||||
{ "/quit" },
|
||||
{ "/requests" },
|
||||
{ "/status" },
|
||||
"/nick",
|
||||
"/note",
|
||||
"/nospam",
|
||||
"/quit",
|
||||
"/requests",
|
||||
"/status",
|
||||
|
||||
#ifdef AUDIO
|
||||
|
||||
{ "/lsdev" },
|
||||
{ "/sdev" },
|
||||
"/lsdev",
|
||||
"/sdev",
|
||||
|
||||
#endif /* AUDIO */
|
||||
|
||||
#ifdef VIDEO
|
||||
|
||||
{ "/lsvdev" },
|
||||
{ "/svdev" },
|
||||
"/lsvdev",
|
||||
"/svdev",
|
||||
|
||||
#endif /* VIDEO */
|
||||
|
||||
#ifdef PYTHON
|
||||
|
||||
{ "/run" },
|
||||
"/run",
|
||||
|
||||
#endif /* PYTHON */
|
||||
|
||||
@ -272,14 +251,14 @@ static bool prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
#endif
|
||||
|
||||
else if (wcsncmp(ctx->line, L"/status ", wcslen(L"/status ")) == 0) {
|
||||
const char status_cmd_list[3][8] = {
|
||||
{"online"},
|
||||
{"away"},
|
||||
{"busy"},
|
||||
const char *status_cmd_list[] = {
|
||||
"online",
|
||||
"away",
|
||||
"busy",
|
||||
};
|
||||
diff = complete_line(self, status_cmd_list, 3, 8);
|
||||
diff = complete_line(self, status_cmd_list, sizeof(status_cmd_list) / sizeof(char *));
|
||||
} else {
|
||||
diff = complete_line(self, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE);
|
||||
diff = complete_line(self, glob_cmd_list, sizeof(glob_cmd_list) / sizeof(char *));
|
||||
}
|
||||
|
||||
if (diff != -1) {
|
||||
|
@ -142,6 +142,7 @@ int ID_to_QRcode_png(const char *tox_id, const char *outfile)
|
||||
|
||||
if (row == NULL) {
|
||||
fclose(fp);
|
||||
QRcode_free(qr_obj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -794,6 +794,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
|
||||
|
||||
if (plain == NULL) {
|
||||
fclose(fp);
|
||||
free(data);
|
||||
exit_toxic_err("failed in load_tox", FATALERR_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
@ -812,6 +813,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
|
||||
if (strcasecmp(user_password.pass, "q") == 0) {
|
||||
fclose(fp);
|
||||
free(plain);
|
||||
free(data);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -1294,7 +1296,7 @@ static int rename_old_profile(const char *user_config_dir)
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(old_data_blocklist, sizeof(old_data_blocklist), "%s%s%s", user_config_dir, CONFIGDIR, OLD_DATA_BLOCKLIST_NAME);
|
||||
snprintf(old_data_blocklist, old_block_buf_size, "%s%s%s", user_config_dir, CONFIGDIR, OLD_DATA_BLOCKLIST_NAME);
|
||||
|
||||
if (!file_exists(old_data_blocklist)) {
|
||||
free(old_data_blocklist);
|
||||
|
Loading…
Reference in New Issue
Block a user