diff --git a/src/chat.c b/src/chat.c index 7d2e684..82df211 100644 --- a/src/chat.c +++ b/src/chat.c @@ -124,11 +124,14 @@ static void chat_set_window_name(ToxWindow *self, char *nick, int len) snprintf(self->name, sizeof(self->name), "%s", nick); } -void kill_chat_window(ToxWindow *self) +static void close_all_file_receivers(Tox *m, int friendnum); + +void kill_chat_window(ToxWindow *self, Tox *m) { ChatContext *ctx = self->chatwin; StatusBar *statusbar = self->stb; + close_all_file_receivers(m, self->num); log_disable(ctx->log); line_info_cleanup(ctx->hst); @@ -293,7 +296,7 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t len += strlen(user_settings_->download_path); } - if (len >= sizeof(friends[num].file_receiver.filenames[filenum])) { + if (len >= sizeof(friends[num].file_receiver[filenum].filename)) { errmsg = "File name too long; discarding."; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg); return; @@ -333,9 +336,9 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type '/savefile %d' to accept the file transfer.", filenum); - friends[num].file_receiver.pending[filenum] = true; - friends[num].file_receiver.size[filenum] = filesize; - strcpy(friends[num].file_receiver.filenames[filenum], filename); + friends[num].file_receiver[filenum].pending = true; + friends[num].file_receiver[filenum].size = filesize; + strcpy(friends[num].file_receiver[filenum].filename, filename); if (self->active_box != -1) box_notify2(self, transfer_pending, NT_WNDALERT_2 | NT_NOFOCUS, self->active_box, @@ -352,13 +355,21 @@ void chat_close_file_receiver(Tox *m, int filenum, int friendnum, int CTRL) if (CTRL > 0) tox_file_send_control(m, friendnum, 1, filenum, CTRL, 0, 0); - friends[friendnum].file_receiver.active[filenum] = false; - friends[friendnum].file_receiver.pending[filenum] = false; - FILE *file = friends[friendnum].file_receiver.files[filenum]; + FILE *file = friends[friendnum].file_receiver[filenum].file; - if (file != NULL) { + if (file != NULL) fclose(file); - friends[friendnum].file_receiver.files[filenum] = NULL; + + memset(&friends[friendnum].file_receiver[filenum], 0, sizeof(struct FileReceiver)); +} + +static void close_all_file_receivers(Tox *m, int friendnum) +{ + int i; + + for (i = 0; i < MAX_FILES; ++i) { + if (friends[friendnum].file_receiver[i].active) + chat_close_file_receiver(m, i, friendnum, TOX_FILECONTROL_KILL); } } @@ -373,7 +384,7 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec int i = 0; /* file_sender index */ if (receive_send == 0) { - filename = friends[num].file_receiver.filenames[filenum]; + filename = friends[num].file_receiver[filenum].filename; } else { for (i = 0; i < MAX_FILES; ++i) { if (file_senders[i].active && file_senders[i].filenum == filenum) @@ -446,7 +457,7 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenu if (self->num != num) return; - FILE *fp = friends[num].file_receiver.files[filenum]; + FILE *fp = friends[num].file_receiver[filenum].file; if (fp) { if (fwrite(data, length, 1, fp) != 1) { @@ -455,17 +466,17 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenu } } - friends[num].file_receiver.bps[filenum] += length; + friends[num].file_receiver[filenum].bps += length; double remain = (double) tox_file_data_remaining(m, num, filenum, 1); uint64_t curtime = get_unix_time(); /* refresh line with percentage complete and transfer speed (must be called once per second) */ - if (!remain || timed_out(friends[num].file_receiver.last_progress[filenum], curtime, 1)) { - friends[num].file_receiver.last_progress[filenum] = curtime; - uint64_t size = friends[num].file_receiver.size[filenum]; + if (!remain || timed_out(friends[num].file_receiver[filenum].last_progress, curtime, 1)) { + friends[num].file_receiver[filenum].last_progress = curtime; + uint64_t size = friends[num].file_receiver[filenum].size; double pct_done = remain > 0 ? (1 - (remain / size)) * 100 : 100; print_progress_bar(self, filenum, num, pct_done); - friends[num].file_receiver.bps[filenum] = 0; + friends[num].file_receiver[filenum].bps = 0; } } @@ -819,7 +830,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) if (line[0] == '/') { if (strcmp(line, "/close") == 0) { - kill_chat_window(self); + kill_chat_window(self, m); return; } else if (strncmp(line, "/me ", strlen("/me ")) == 0) { send_action(self, ctx, m, line + strlen("/me ")); diff --git a/src/chat.h b/src/chat.h index f7fa779..b8f6e88 100644 --- a/src/chat.h +++ b/src/chat.h @@ -29,7 +29,7 @@ /* set CTRL to -1 if we don't want to send a control signal. set msg to NULL if we don't want to display a message */ void chat_close_file_receiver(Tox *m, int filenum, int friendnum, int CTRL); -void kill_chat_window(ToxWindow *self); +void kill_chat_window(ToxWindow *self, Tox *m); ToxWindow new_chat(Tox *m, int32_t friendnum); #endif /* end of include guard: CHAT_H_6489PZ13 */ diff --git a/src/chat_commands.c b/src/chat_commands.c index 056d54e..9347474 100644 --- a/src/chat_commands.c +++ b/src/chat_commands.c @@ -57,12 +57,12 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar } if (strcasecmp(inoutstr, "in") == 0) { /* cancel an incoming file transfer */ - if (!friends[self->num].file_receiver.active[filenum]) { + if (!friends[self->num].file_receiver[filenum].active) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID."); return; } - const char *filepath = friends[self->num].file_receiver.filenames[filenum]; + const char *filepath = friends[self->num].file_receiver[filenum].filename; char name[MAX_STR_SIZE]; get_file_name(name, sizeof(name), filepath); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer for '%s' canceled.", name); @@ -159,12 +159,12 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv return; } - if (!friends[self->num].file_receiver.pending[filenum]) { + if (!friends[self->num].file_receiver[filenum].pending) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID."); return; } - const char *filename = friends[self->num].file_receiver.filenames[filenum]; + const char *filename = friends[self->num].file_receiver[filenum].filename; if (tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_ACCEPT, 0, 0) == 0) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Saving file [%d] as: '%s'", filenum, filename); @@ -173,9 +173,9 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv char progline[MAX_STR_SIZE]; prep_prog_line(progline); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline); - friends[self->num].file_receiver.line_id[filenum] = self->chatwin->hst->line_end->id + 2; + friends[self->num].file_receiver[filenum].line_id = self->chatwin->hst->line_end->id + 2; - if ((friends[self->num].file_receiver.files[filenum] = fopen(filename, "a")) == NULL) { + if ((friends[self->num].file_receiver[filenum].file = fopen(filename, "a")) == NULL) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "* Error writing to file."); tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0); } @@ -183,8 +183,8 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed."); } - friends[self->num].file_receiver.pending[filenum] = false; - friends[self->num].file_receiver.active[filenum] = true; + friends[self->num].file_receiver[filenum].pending = false; + friends[self->num].file_receiver[filenum].active = true; } void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) @@ -241,7 +241,6 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv for (i = 0; i < MAX_FILES; ++i) { if (!file_senders[i].active) { - file_senders[i].queue_pos = num_active_file_senders; memcpy(file_senders[i].filename, filename, namelen + 1); file_senders[i].active = true; file_senders[i].toxwin = self; @@ -252,7 +251,6 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv file_senders[i].size = filesize; file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1, tox_file_data_size(m, self->num), file_to_send); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Sending file [%d]: '%s'", filenum, filename); ++num_active_file_senders; @@ -260,6 +258,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv if (i == max_file_senders_index) ++max_file_senders_index; + reset_file_sender_queue(); return; } } diff --git a/src/file_senders.c b/src/file_senders.c index 283bf03..50eb62b 100644 --- a/src/file_senders.c +++ b/src/file_senders.c @@ -66,8 +66,8 @@ void print_progress_bar(ToxWindow *self, int idx, int friendnum, double pct_done bps = file_senders[idx].bps; line_id = file_senders[idx].line_id; } else { - bps = friends[friendnum].file_receiver.bps[idx]; - line_id = friends[friendnum].file_receiver.line_id[idx]; + bps = friends[friendnum].file_receiver[idx].bps; + line_id = friends[friendnum].file_receiver[idx].line_id; } const char *unit; @@ -120,6 +120,18 @@ static void set_max_file_senders_index(void) max_file_senders_index = j; } +/* called whenever a file sender is opened or closed */ +void reset_file_sender_queue(void) +{ + int i; + int pos = 0; + + for (i = 0; i < max_file_senders_index; ++i) { + if (file_senders[i].active) + file_senders[i].queue_pos = pos++; + } +} + /* set CTRL to -1 if we don't want to send a control signal. set msg to NULL if we don't want to display a message */ void close_file_sender(ToxWindow *self, Tox *m, int i, const char *msg, int CTRL, int filenum, int32_t friendnum) @@ -133,6 +145,7 @@ void close_file_sender(ToxWindow *self, Tox *m, int i, const char *msg, int CTRL fclose(file_senders[i].file); memset(&file_senders[i], 0, sizeof(FileSender)); set_max_file_senders_index(); + reset_file_sender_queue(); --num_active_file_senders; } @@ -170,8 +183,7 @@ static void send_file_data(ToxWindow *self, Tox *m, int i, int32_t friendnum, in double remain = (double) tox_file_data_remaining(m, friendnum, filenum, 0); /* refresh line with percentage complete and transfer speed (must be called once per second) */ - if ( (self->chatwin != NULL && timed_out(file_senders[i].last_progress, curtime, 1)) - || (!remain && !file_senders[i].finished) ) { + if (timed_out(file_senders[i].last_progress, curtime, 1) || (!remain && !file_senders[i].finished)) { file_senders[i].last_progress = curtime; double pct_done = remain > 0 ? (1 - (remain / file_senders[i].size)) * 100 : 100; print_progress_bar(self, i, -1, pct_done); @@ -218,15 +230,13 @@ void do_file_senders(Tox *m) sound_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, NULL); if (self->active_box != -1) - box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, - self->active_box, "File transfer for '%s' timed out.", filename ); + box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", msg); else - box_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, - self->name, "File transfer for '%s' timed out.", filename ); + box_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, self->name, "%s", msg); continue; } - file_senders[i].queue_pos = num_active_file_senders - 1; send_file_data(self, m, i, friendnum, filenum, filename); + file_senders[i].queue_pos = num_active_file_senders - 1; } } diff --git a/src/file_senders.h b/src/file_senders.h index 3ee5fc4..8d307f0 100644 --- a/src/file_senders.h +++ b/src/file_senders.h @@ -61,6 +61,9 @@ void print_progress_bar(ToxWindow *self, int idx, int friendnum, double pct_rema set msg to NULL if we don't want to display a message */ void close_file_sender(ToxWindow *self, Tox *m, int i, const char *msg, int CTRL, int filenum, int32_t friendnum); +/* called whenever a file sender is opened or closed */ +void reset_file_sender_queue(void); + void close_all_file_senders(Tox *m); void do_file_senders(Tox *m); diff --git a/src/friendlist.c b/src/friendlist.c index 48408ab..a52c989 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -456,7 +456,7 @@ static void delete_friend(Tox *m, int32_t f_num) ToxWindow *toxwin = get_window_ptr(friends[f_num].chatwin); if (toxwin != NULL) { - kill_chat_window(toxwin); + kill_chat_window(toxwin, m); set_active_window(1); /* keep friendlist focused */ } } diff --git a/src/friendlist.h b/src/friendlist.h index f7770e2..4f17fcf 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -30,15 +30,15 @@ #include "file_senders.h" struct FileReceiver { - char filenames[MAX_FILES][MAX_STR_SIZE]; - FILE *files[MAX_FILES]; - bool pending[MAX_FILES]; - bool active[MAX_FILES]; - uint64_t size[MAX_FILES]; - double bps[MAX_FILES]; - uint64_t last_progress[MAX_FILES]; - uint32_t line_id[MAX_FILES]; - int filenums[MAX_FILES]; + char filename[MAX_STR_SIZE]; + int filenum; + FILE *file; + bool pending; + bool active; + uint64_t size; + double bps; + uint64_t last_progress; + uint32_t line_id; }; struct LastOnline { @@ -63,7 +63,7 @@ typedef struct { bool logging_on; /* saves preference for friend irrespective of chat windows */ uint8_t status; struct LastOnline last_online; - struct FileReceiver file_receiver; + struct FileReceiver file_receiver[MAX_FILES]; } ToxicFriend; typedef struct { diff --git a/src/toxic.c b/src/toxic.c index 6e4ddbf..3386d12 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -105,7 +105,7 @@ void exit_toxic_success(Tox *m) { store_data(m, DATA_FILE); close_all_file_senders(m); - kill_all_windows(); + kill_all_windows(m); free(DATA_FILE); free(BLOCK_FILE); diff --git a/src/windows.c b/src/windows.c index 64c3155..7dee27d 100644 --- a/src/windows.c +++ b/src/windows.c @@ -497,7 +497,7 @@ int get_num_active_windows(void) } /* destroys all chat and groupchat windows (should only be called on shutdown) */ -void kill_all_windows(void) +void kill_all_windows(Tox *m) { kill_prompt_window(prompt); @@ -505,7 +505,7 @@ void kill_all_windows(void) for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].is_chat) - kill_chat_window(&windows[i]); + kill_chat_window(&windows[i], m); else if (windows[i].is_groupchat) kill_groupchat_window(&windows[i]); } diff --git a/src/windows.h b/src/windows.h index f1438ad..cbe18d6 100644 --- a/src/windows.h +++ b/src/windows.h @@ -223,7 +223,7 @@ int add_window(Tox *m, ToxWindow w); void del_window(ToxWindow *w); void set_active_window(int ch); int get_num_active_windows(void); -void kill_all_windows(void); /* should only be called on shutdown */ +void kill_all_windows(Tox *m); /* should only be called on shutdown */ void on_window_resize(void); ToxWindow *get_window_ptr(int i);