diff --git a/build/Makefile b/build/Makefile index df197c3..9131137 100644 --- a/build/Makefile +++ b/build/Makefile @@ -14,6 +14,7 @@ LDFLAGS = $(USER_LDFLAGS) OBJ = chat.o chat_commands.o configdir.o dns.o execute.o file_senders.o notify.o OBJ += friendlist.o global_commands.o groupchat.o line_info.o input.o help.o autocomplete.o OBJ += log.o misc_tools.o prompt.o settings.o toxic.o toxic_strings.o windows.o message_queue.o +OBJ += group_commands.o # Check on wich system we are running UNAME_S = $(shell uname -s) diff --git a/src/chat.c b/src/chat.c index 1a9e4b1..666eed7 100644 --- a/src/chat.c +++ b/src/chat.c @@ -116,19 +116,6 @@ static void set_self_typingstatus(ToxWindow *self, Tox *m, uint8_t is_typing) ctx->self_is_typing = is_typing; } -static void chat_set_window_name(ToxWindow *self, const char *nick, int len) -{ - char nick_cpy[TOXIC_MAX_NAME_LENGTH + 1]; - snprintf(nick_cpy, sizeof(nick_cpy), "%s", nick); - - if (len > MAX_WINDOW_NAME_LENGTH) { - strcpy(&nick_cpy[MAX_WINDOW_NAME_LENGTH - 3], "..."); - nick_cpy[MAX_WINDOW_NAME_LENGTH] = '\0'; - } - - snprintf(self->name, sizeof(self->name), "%s", nick_cpy); -} - static void close_all_file_receivers(Tox *m, int friendnum); void kill_chat_window(ToxWindow *self, Tox *m) @@ -264,7 +251,7 @@ static void chat_onNickChange(ToxWindow *self, Tox *m, int32_t num, const char * len = strlen(statusbar->nick); statusbar->nick_len = len; - chat_set_window_name(self, statusbar->nick, len); + set_window_title(self, statusbar->nick, len); } static void chat_onStatusChange(ToxWindow *self, Tox *m, int32_t num, uint8_t status) @@ -1172,7 +1159,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum) char nick[TOX_MAX_NAME_LENGTH]; int n_len = get_nick_truncate(m, nick, friendnum); - chat_set_window_name(&ret, nick, n_len); + set_window_title(&ret, nick, n_len); ChatContext *chatwin = calloc(1, sizeof(ChatContext)); StatusBar *stb = calloc(1, sizeof(StatusBar)); diff --git a/src/execute.c b/src/execute.c index 0be70a3..9e83a83 100644 --- a/src/execute.c +++ b/src/execute.c @@ -29,6 +29,7 @@ #include "execute.h" #include "chat_commands.h" #include "global_commands.h" +#include "group_commands.h" #include "line_info.h" #include "misc_tools.h" #include "notify.h" @@ -81,6 +82,8 @@ static struct cmd_func chat_commands[] = { }; static struct cmd_func group_commands[] = { + { "/title", cmd_set_title }, + #ifdef AUDIO { "/mute", cmd_mute }, { "/sense", cmd_sense }, diff --git a/src/group_commands.c b/src/group_commands.c new file mode 100644 index 0000000..d0aad45 --- /dev/null +++ b/src/group_commands.c @@ -0,0 +1,70 @@ +/* group_commands.c + * + * + * Copyright (C) 2014 Toxic All Rights Reserved. + * + * This file is part of Toxic. + * + * Toxic is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Toxic is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Toxic. If not, see . + * + */ + +#include + +#include "toxic.h" +#include "windows.h" +#include "line_info.h" +#include "misc_tools.h" +#include "log.h" + +void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + char title[MAX_STR_SIZE]; + + if (argc < 1) { + snprintf(title, sizeof(title), "Group title: %s", self->name); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, MAGENTA, title); + return; + } + + if (argv[1][0] != '\"') { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title must be enclosed in quotes."); + return; + } + + /* remove opening and closing quotes */ + 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) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set title."); + return; + } + + set_window_title(self, title, len); + + char timefrmt[TIME_STR_SIZE]; + char selfnick[TOX_MAX_NAME_LENGTH]; + + get_time_str(timefrmt, sizeof(timefrmt)); + uint16_t sn_len = tox_get_self_name(m, (uint8_t *) selfnick); + selfnick[sn_len] = '\0'; + + line_info_add(self, timefrmt, selfnick, title, NAME_CHANGE, 0, 0, " changed the group title to "); + + char tmp_event[MAX_STR_SIZE]; + snprintf(tmp_event, sizeof(tmp_event), "set title to %s", title); + write_to_log(tmp_event, selfnick, self->chatwin->log, true); +} diff --git a/src/group_commands.h b/src/group_commands.h new file mode 100644 index 0000000..5d9a1b6 --- /dev/null +++ b/src/group_commands.h @@ -0,0 +1,31 @@ +/* group_commands.h + * + * + * Copyright (C) 2014 Toxic All Rights Reserved. + * + * This file is part of Toxic. + * + * Toxic is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Toxic is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Toxic. If not, see . + * + */ + +#ifndef GROUP_COMMANDS_H +#define GROUP_COMMANDS_H + +#include "windows.h" +#include "toxic.h" + +void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); + +#endif /* GROUP_COMMANDS_H */ diff --git a/src/groupchat.c b/src/groupchat.c index 99d102a..bc8695f 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -55,9 +55,9 @@ extern struct user_settings *user_settings; extern struct Winthread Winthread; #ifdef AUDIO -#define AC_NUM_GROUP_COMMANDS 21 +#define AC_NUM_GROUP_COMMANDS 22 #else -#define AC_NUM_GROUP_COMMANDS 17 +#define AC_NUM_GROUP_COMMANDS 18 #endif /* AUDIO */ /* Array of groupchat command names used for tab completion. */ @@ -79,6 +79,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/quit" }, { "/requests" }, { "/status" }, + { "/title" }, #ifdef AUDIO @@ -274,6 +275,36 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p write_to_log(action, nick, ctx->log, true); } +static void groupchat_onGroupTitleChange(ToxWindow *self, Tox *m, int groupnum, int peernum, const char *title, + uint8_t length) +{ + ChatContext *ctx = self->chatwin; + + if (self->num != groupnum) + return; + + set_window_title(self, title, length); + + char event[MAX_STR_SIZE]; + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); + + /* announce title when we join the room */ + if (!timed_out(groupchats[self->num].start_time, get_unix_time(), GROUP_EVENT_WAIT)) { + snprintf(event, sizeof(event), "Title set to: %s", title); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, MAGENTA, event); + return; + } + + char nick[TOX_MAX_NAME_LENGTH]; + get_group_nick_truncate(m, nick, peernum, groupnum); + line_info_add(self, timefrmt, nick, title, NAME_CHANGE, 0, 0, (char *) "changed the group title to"); + + char tmp_event[MAX_STR_SIZE]; + snprintf(tmp_event, sizeof(tmp_event), "set title to %s", title); + write_to_log(tmp_event, nick, ctx->log, true); +} + /* Puts two copies of peerlist/lengths in chat instance */ static void copy_peernames(int gnum, uint8_t peerlist[][TOX_MAX_NAME_LENGTH], uint16_t lengths[], int npeers) { @@ -326,8 +357,6 @@ struct group_add_thrd { pthread_attr_t attr; }; -#define GROUP_EVENT_WAIT 2 - /* Waits GROUP_EVENT_WAIT seconds for a new peer to set their name before announcing them */ void *group_add_wait(void *data) { @@ -708,6 +737,7 @@ ToxWindow new_group_chat(Tox *m, int groupnum) ret.onGroupMessage = &groupchat_onGroupMessage; ret.onGroupNamelistChange = &groupchat_onGroupNamelistChange; ret.onGroupAction = &groupchat_onGroupAction; + ret.onGroupTitleChange = &groupchat_onGroupTitleChange; #ifdef AUDIO ret.onWriteDevice = &groupchat_onWriteDevice; diff --git a/src/groupchat.h b/src/groupchat.h index 42f8c09..7cfa95a 100644 --- a/src/groupchat.h +++ b/src/groupchat.h @@ -30,6 +30,7 @@ #define SIDEBAR_WIDTH 16 #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 GROUP_EVENT_WAIT 2 #ifdef AUDIO #define MAX_GROUP_PEERS 256 /* arbitrary limit, only used for audio */ diff --git a/src/help.c b/src/help.c index 88efe58..0a97697 100644 --- a/src/help.c +++ b/src/help.c @@ -240,9 +240,15 @@ static void help_draw_group(ToxWindow *self) wmove(win, 1, 1); wattron(win, A_BOLD | COLOR_PAIR(RED)); - wprintw(win, "Group audio commands:\n"); + wprintw(win, "Group commands:\n"); wattroff(win, A_BOLD | COLOR_PAIR(RED)); + wprintw(win, " /title : Set group title (show current title if no msg)\n\n"); + + wattron(win, A_BOLD); + wprintw(win, " Audio commands:\n"); + wattroff(win, A_BOLD); + wprintw(win, " /mute : Mute active device where type: in | out\n"); wprintw(win, " /sense : VAD sensitivity threshold\n\n"); @@ -302,7 +308,7 @@ void help_onKey(ToxWindow *self, wint_t key) #ifdef AUDIO /* remove if/when we add non-audio group commands */ case 'r': - help_init_window(self, 7, 80); + help_init_window(self, 10, 80); self->help->type = HELP_GROUP; break; #endif diff --git a/src/line_info.c b/src/line_info.c index f2058d7..6c6f872 100644 --- a/src/line_info.c +++ b/src/line_info.c @@ -130,8 +130,8 @@ static struct line_info *line_info_ret_queue(struct history *hst) } /* creates new line_info line and puts it in the queue. */ -void line_info_add(ToxWindow *self, char *timestr, char *name1, char *name2, uint8_t type, uint8_t bold, - uint8_t colour, const char *msg, ...) +void line_info_add(ToxWindow *self, const char *timestr, const char *name1, const char *name2, uint8_t type, + uint8_t bold, uint8_t colour, const char *msg, ...) { struct history *hst = self->chatwin->hst; diff --git a/src/line_info.h b/src/line_info.h index f2590ff..cb91365 100644 --- a/src/line_info.h +++ b/src/line_info.h @@ -74,8 +74,8 @@ struct history { }; /* creates new line_info line and puts it in the queue. */ -void line_info_add(ToxWindow *self, char *timestr, char *name1, char *name2, uint8_t type, uint8_t bold, - uint8_t colour, const char *msg, ...); +void line_info_add(ToxWindow *self, const char *timestr, const char *name1, const char *name2, uint8_t type, + uint8_t bold, uint8_t colour, const char *msg, ...); /* Prints a section of history starting at line_start */ void line_info_print(ToxWindow *self); diff --git a/src/misc_tools.c b/src/misc_tools.c index 76191ac..36690b4 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -377,3 +377,21 @@ int check_file_signature(const char *signature, size_t size, FILE *fp) return ret == 0 ? 0 : 1; } + +/* sets window title in tab bar. */ +void set_window_title(ToxWindow *self, const char *title, int len) +{ + char cpy[TOXIC_MAX_NAME_LENGTH + 1]; + + if (self->is_groupchat) /* keep groupnumber in title */ + snprintf(cpy, sizeof(cpy), "%d-%s", self->num, title); + else + snprintf(cpy, sizeof(cpy), "%s", title); + + if (len > MAX_WINDOW_NAME_LENGTH) { + strcpy(&cpy[MAX_WINDOW_NAME_LENGTH - 3], "..."); + cpy[MAX_WINDOW_NAME_LENGTH] = '\0'; + } + + snprintf(self->name, sizeof(self->name), "%s", cpy); +} diff --git a/src/misc_tools.h b/src/misc_tools.h index 3699a6c..20fd17e 100644 --- a/src/misc_tools.h +++ b/src/misc_tools.h @@ -134,4 +134,7 @@ off_t file_size(const char *path); On success this function will seek back to the beginning of fp */ int check_file_signature(const char *signature, size_t size, FILE *fp); +/* sets window title in tab bar. */ +void set_window_title(ToxWindow *self, const char *title, int len); + #endif /* #define MISC_TOOLS_H */ diff --git a/src/toxic.c b/src/toxic.c index f808639..d4c6236 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -313,6 +313,7 @@ static Tox *init_tox(void) tox_callback_file_control(m, on_file_control, NULL); tox_callback_file_data(m, on_file_data, NULL); tox_callback_read_receipt(m, on_read_receipt, NULL); + tox_callback_group_title(m, on_group_titlechange, NULL); tox_set_name(m, (uint8_t *) "Toxic User", strlen("Toxic User")); diff --git a/src/toxic.h b/src/toxic.h index ee4bbe8..706efa7 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -107,6 +107,7 @@ void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *mes void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *action, uint16_t length, void *userdata); void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t type, const uint8_t *group_pub_key, uint16_t length, 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 *userdata); void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *pathname, uint16_t pathname_length, void *userdata); void on_file_control(Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, diff --git a/src/windows.c b/src/windows.c index e62a83a..a6b624b 100644 --- a/src/windows.c +++ b/src/windows.c @@ -209,6 +209,20 @@ void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t ch } } +void on_group_titlechange(Tox *m, int groupnumber, int peernumber, const uint8_t *title, uint8_t length, + void *userdata) +{ + char data[MAX_STR_SIZE + 1]; + length = copy_tox_str(data, sizeof(data), (const char *) title, length); + + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupTitleChange != NULL) + windows[i].onGroupTitleChange(&windows[i], m, groupnumber, peernumber, data, length); + } +} + void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *filename, uint16_t filename_length, void *userdata) { diff --git a/src/windows.h b/src/windows.h index 2e596e4..02da7c1 100644 --- a/src/windows.h +++ b/src/windows.h @@ -37,7 +37,7 @@ #include "toxic.h" #define MAX_WINDOWS_NUM 32 -#define MAX_WINDOW_NAME_LENGTH 16 +#define MAX_WINDOW_NAME_LENGTH 20 #define CURS_Y_OFFSET 1 /* y-axis cursor offset for chat contexts */ #define CHATBOX_HEIGHT 2 @@ -117,6 +117,7 @@ struct ToxWindow { 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(*onFileSendRequest)(ToxWindow *, Tox *, int32_t, uint8_t, uint64_t, const char *, uint16_t); void(*onFileControl)(ToxWindow *, Tox *, int32_t, uint8_t, uint8_t, uint8_t, const char *, uint16_t); void(*onFileData)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t);