diff --git a/src/chat_commands.c b/src/chat_commands.c index 4270343..3348f23 100644 --- a/src/chat_commands.c +++ b/src/chat_commands.c @@ -53,22 +53,19 @@ void cmd_chat_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN); #ifdef _SUPPORT_AUDIO - #define NUMLINES 11 + #define NUMLINES 12 #else - #define NUMLINES 7 + #define NUMLINES 8 #endif uint8_t lines[NUMLINES][MAX_STR_SIZE] = { #ifdef _SUPPORT_AUDIO - { " /call : Audio call" }, { " /cancel : Cancel call" }, { " /answer : Answer incomming call" }, { " /hangup : Hangup active call" }, - #endif /* _SUPPORT_AUDIO */ - { " /invite : Invite friend to a group chat" }, { " /join : Join a pending group chat" }, { " /log or : Enable/disable logging" }, @@ -76,7 +73,7 @@ void cmd_chat_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg { " /savefile : Receive a file" }, { " /close : Close the current chat window" }, { " /help : Print this message again" }, - //{ " /help global : Show a list of global commands" }, + { " /help global : Show a list of global commands" }, }; int i; @@ -84,7 +81,7 @@ void cmd_chat_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg for (i = 0; i < NUMLINES; ++i) line_info_add(self, NULL, NULL, NULL, lines[i], SYS_MSG, 0, 0); - msg = " * Use ESC key to toggle history scroll mode"; + msg = " * Use ESC key to toggle history scroll mode\n"; line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN); } diff --git a/src/execute.c b/src/execute.c index 71e5958..53e2407 100644 --- a/src/execute.c +++ b/src/execute.c @@ -32,6 +32,7 @@ #include "execute.h" #include "chat_commands.h" #include "global_commands.h" +#include "line_info.h" struct cmd_func { const char *name; @@ -76,7 +77,7 @@ static struct cmd_func chat_commands[] = { /* Parses input command and puts args into arg array. Returns number of arguments on success, -1 on failure. */ -static int parse_command(WINDOW *w, char *cmd, char (*args)[MAX_STR_SIZE]) +static int parse_command(WINDOW *w, ToxWindow *self, char *cmd, char (*args)[MAX_STR_SIZE]) { int num_args = 0; bool cmd_end = false; /* flags when we get to the end of cmd */ @@ -88,7 +89,8 @@ static int parse_command(WINDOW *w, char *cmd, char (*args)[MAX_STR_SIZE]) end = strchr(cmd+1, '\"'); if (end++ == NULL) { /* Increment past the end quote */ - wprintw(w, "Invalid argument. Did you forget a closing \"?\n"); + uint8_t *errmsg = "Invalid argument. Did you forget a closing \"?"; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return -1; } @@ -131,7 +133,7 @@ void execute(WINDOW* w, ToxWindow *self, Tox *m, char *cmd, int mode) return; char args[MAX_NUM_ARGS][MAX_STR_SIZE] = {0}; - int num_args = parse_command(w, cmd, args); + int num_args = parse_command(w, self, cmd, args); if (num_args == -1) return; @@ -153,5 +155,6 @@ void execute(WINDOW* w, ToxWindow *self, Tox *m, char *cmd, int mode) if (do_command(w, self, m, num_args, GLOBAL_NUM_COMMANDS, global_commands, args) == 0) return; - wprintw(w, "Invalid command.\n"); + uint8_t *errmsg = "Invalid command."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); } diff --git a/src/friendlist.c b/src/friendlist.c index 538f803..57c73ea 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -106,7 +106,6 @@ static void friendlist_onMessage(ToxWindow *self, Tox *m, int32_t num, uint8_t * nick[TOXIC_MAX_NAME_LENGTH] = '\0'; wprintw(prompt->window, "%s: %s\n", nick, str); - prep_prompt_win(); wattron(prompt->window, COLOR_PAIR(RED)); wprintw(prompt->window, "* Warning: Too many windows are open.\n"); wattron(prompt->window, COLOR_PAIR(RED)); @@ -211,7 +210,6 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u tox_get_name(m, num, nick); nick[TOXIC_MAX_NAME_LENGTH] = '\0'; - prep_prompt_win(); wattron(prompt->window, COLOR_PAIR(RED)); wprintw(prompt->window, "* File transfer from %s failed: too many windows are open.\n", nick); wattron(prompt->window, COLOR_PAIR(RED)); @@ -234,7 +232,6 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, uint8 tox_get_name(m, num, nick); nick[TOXIC_MAX_NAME_LENGTH] = '\0'; - prep_prompt_win(); wattron(prompt->window, COLOR_PAIR(RED)); wprintw(prompt->window, "* Group chat invite from %s failed: too many windows are open.\n", nick); wattron(prompt->window, COLOR_PAIR(RED)); @@ -343,7 +340,6 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key) friends[f].chatwin = add_window(m, new_chat(m, friends[f].num)); set_active_window(friends[f].chatwin); } else { - prep_prompt_win(); wattron(prompt->window, COLOR_PAIR(RED)); wprintw(prompt->window, "* Warning: Too many windows are open.\n"); wattron(prompt->window, COLOR_PAIR(RED)); @@ -539,8 +535,7 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av) tox_get_name(m, id, nick); nick[TOXIC_MAX_NAME_LENGTH] = '\0'; wprintw(prompt->window, "Audio action from: %s!\n", nick); - - prep_prompt_win(); + wattron(prompt->window, COLOR_PAIR(RED)); wprintw(prompt->window, "* Warning: Too many windows are open.\n"); wattron(prompt->window, COLOR_PAIR(RED)); diff --git a/src/global_commands.c b/src/global_commands.c index 7459548..084f424 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -30,6 +30,7 @@ #include "toxic_windows.h" #include "misc_tools.h" #include "friendlist.h" +#include "line_info.h" extern char *DATA_FILE; extern ToxWindow *prompt; @@ -42,30 +43,34 @@ extern uint8_t num_frnd_requests; /* command functions */ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { - /* check arguments */ + uint8_t *msg; + if (argc != 1) { - wprintw(window, "Invalid syntax.\n"); - return; + msg = "Invalid syntax."; + line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); + return; } int req = atoi(argv[1]); if ((req == 0 && strcmp(argv[1], "0"))|| req >= MAX_FRIENDS_NUM) { - wprintw(window, "No pending friend request with that number.\n"); + msg = "No pending friend request with that number."; + line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); return; } if (!strlen(pending_frnd_requests[req])) { - wprintw(window, "No pending friend request with that number.\n"); + msg = "No pending friend request with that number."; + line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); return; } int32_t friendnum = tox_add_friend_norequest(m, pending_frnd_requests[req]); if (friendnum == -1) - wprintw(window, "Failed to add friend.\n"); + msg = "Failed to add friend."; else { - wprintw(window, "Friend request accepted.\n"); + msg = "Friend request accepted."; on_friendadded(m, friendnum, true); } @@ -79,12 +84,16 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ } num_frnd_requests = i; + line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); } void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { + uint8_t *errmsg; + if (argc < 1) { - wprintw(window, "Invalid syntax.\n"); + errmsg = "Invalid syntax."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } @@ -95,7 +104,8 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX uint8_t *temp = argv[2]; if (temp[0] != '\"') { - wprintw(window, "Message must be enclosed in quotes.\n"); + errmsg = "Message must be enclosed in quotes."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } @@ -108,7 +118,8 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX } if (strlen(id) != 2 * TOX_FRIEND_ADDRESS_SIZE) { - wprintw(window, "Invalid ID length.\n"); + errmsg = "Invalid ID length."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } @@ -123,7 +134,8 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX xx[2] = '\0'; if (sscanf(xx, "%02x", &x) != 1) { - wprintw(window, "Invalid ID.\n"); + errmsg = "Invalid ID."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } @@ -138,31 +150,33 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX switch (f_num) { case TOX_FAERR_TOOLONG: - wprintw(window, "Message is too long.\n"); + errmsg = "Message is too long."; break; case TOX_FAERR_NOMESSAGE: - wprintw(window, "Please add a message to your request.\n"); + errmsg = "Please add a message to your request."; break; case TOX_FAERR_OWNKEY: - wprintw(window, "That appears to be your own ID.\n"); + errmsg = "That appears to be your own ID."; break; case TOX_FAERR_ALREADYSENT: - wprintw(window, "Friend request has already been sent.\n"); + errmsg = "Friend request has already been sent."; break; case TOX_FAERR_UNKNOWN: - wprintw(window, "Undefined error when adding friend.\n"); + errmsg = "Undefined error when adding friend."; break; case TOX_FAERR_BADCHECKSUM: - wprintw(window, "Bad checksum in address.\n"); + errmsg = "Bad checksum in address."; break; case TOX_FAERR_SETNEWNOSPAM: - wprintw(window, "Nospam was different (is this contact already added?)\n"); + errmsg = "Nospam was different (is this contact already added?"; break; default: - wprintw(window, "Friend request sent.\n"); + errmsg = "Friend request sent."; on_friendadded(m, f_num, true); break; } + + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); } void cmd_clear(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) @@ -173,9 +187,12 @@ void cmd_clear(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[M void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { + uint8_t *errmsg; + /* check arguments */ if (argc != 3) { - wprintw(window, "Invalid syntax.\n"); + errmsg = "Invalid syntax."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } @@ -185,7 +202,8 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv) char *key = argv[3]; if (atoi(port) == 0) { - wprintw(window, "Invalid syntax.\n"); + errmsg = "Invalid syntax."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } @@ -197,48 +215,46 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv) void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { + uint8_t *errmsg; + if (get_num_active_windows() >= MAX_WINDOWS_NUM) { - wattron(window, COLOR_PAIR(RED)); - wprintw(window, " * Warning: Too many windows are open.\n"); - wattron(window, COLOR_PAIR(RED)); + errmsg = " * Warning: Too many windows are open."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED); return; } int groupnum = tox_add_groupchat(m); if (groupnum == -1) { - wprintw(window, "Group chat instance failed to initialize.\n"); + errmsg = "Group chat instance failed to initialize."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } if (init_groupchat_win(prompt, m, groupnum) == -1) { - wprintw(window, "Group chat window failed to initialize.\n"); + errmsg = "Group chat window failed to initialize."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); tox_del_groupchat(m, groupnum); return; } - wprintw(window, "Group chat created as %d.\n", groupnum); + uint8_t msg[MAX_STR_SIZE]; + snprintf(msg, sizeof(msg), "Group chat created as %d.", groupnum); + line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); } void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { + uint8_t *msg; struct chatlog *log = self->chatwin->log; if (argc == 0) { - if (log->log_on) { - wprintw(window, "Logging for this window is "); - wattron(window, COLOR_PAIR(GREEN) | A_BOLD); - wprintw(window, "[on]"); - wattroff(window, COLOR_PAIR(GREEN) | A_BOLD); - wprintw(window, ". Type \"/log off\" to disable.\n"); - } else { - wprintw(window, "Logging for this window is "); - wattron(window, COLOR_PAIR(RED) | A_BOLD); - wprintw(window, "[off]"); - wattroff(window, COLOR_PAIR(RED) | A_BOLD); - wprintw(window, ". Type \"/log on\" to enable.\n"); - } + if (log->log_on) + msg = "Logging for this window is ON. Type \"/log off\" to disable."; + else + msg = "Logging for this window is OFF. Type \"/log on\" to enable."; + line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); return; } @@ -257,10 +273,8 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX log_enable(self->name, NULL, log); } - wprintw(window, "Logging "); - wattron(window, COLOR_PAIR(GREEN) | A_BOLD); - wprintw(window, "[on]\n"); - wattroff(window, COLOR_PAIR(GREEN) | A_BOLD); + msg = "Logging enabled"; + line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); return; } else if (!strcmp(swch, "0") || !strcmp(swch, "off")) { if (self->is_chat) @@ -268,14 +282,13 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX log_disable(log); - wprintw(window, "Logging "); - wattron(window, COLOR_PAIR(RED) | A_BOLD); - wprintw(window, "[off]\n"); - wattroff(window, COLOR_PAIR(RED) | A_BOLD); + msg = "Logging disabled"; + line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); return; } - wprintw(window, "Invalid option. Use \"/log on\" and \"/log off\" to toggle logging.\n"); + msg = "Invalid option. Use \"/log on\" and \"/log off\" to toggle logging."; + line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); } void cmd_myid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) @@ -292,14 +305,17 @@ void cmd_myid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA strcat(id, xx); } - wprintw(window, "%s\n", id); + line_info_add(self, NULL, NULL, NULL, id, SYS_MSG, 0, 0); } void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { + uint8_t *errmsg; + /* check arguments */ if (argc < 1) { - wprintw(window, "Invalid name.\n"); + errmsg = "Invalid name."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } @@ -313,7 +329,8 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA } if (!valid_nick(nick)) { - wprintw(window, "Invalid name.\n"); + errmsg = "Invalid name."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } @@ -330,15 +347,19 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { + uint8_t *errmsg; + if (argc < 1) { - wprintw(window, "Wrong number of arguments.\n"); + errmsg = "Wrong number of arguments."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } uint8_t *msg = argv[1]; if (msg[0] != '\"') { - wprintw(window, "Note must be enclosed in quotes.\n"); + errmsg = "Note must be enclosed in quotes."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } @@ -351,33 +372,43 @@ void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA void cmd_prompt_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { - wclear(window); - wattron(window, COLOR_PAIR(CYAN) | A_BOLD); - wprintw(window, "\n\nGlobal commands:\n"); - wattroff(window, COLOR_PAIR(CYAN) | A_BOLD); + uint8_t *msg = "Global commands:"; + line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN); - wprintw(window, " /add : Add friend with optional message\n"); - wprintw(window, " /accept : Accept friend request\n"); - wprintw(window, " /connect : Manually connect to a DHT node\n"); - wprintw(window, " /status : Set status with optional note\n"); - wprintw(window, " /note : Set a personal note\n"); - wprintw(window, " /nick : Set your nickname\n"); - wprintw(window, " /log or : Enable/disable logging\n"); - wprintw(window, " /groupchat : Create a group chat\n"); - wprintw(window, " /myid : Print your ID\n"); - wprintw(window, " /help : Print this message again\n"); - wprintw(window, " /clear : Clear the window\n"); - wprintw(window, " /quit or /exit : Exit Toxic\n"); - #ifdef _SUPPORT_AUDIO - wprintw(window, " /lsdev : List devices where type: in|out\n"); - wprintw(window, " /sdev : Set active device\n"); + #define NUMLINES 14 +#else + #define NUMLINES 12 +#endif + + uint8_t lines[NUMLINES][MAX_STR_SIZE] = { + + { " /add : Add friend with optional message" }, + { " /accept : Accept friend request" }, + { " /connect : Manually connect to a DHT node" }, + { " /status : Set status with optional note" }, + { " /note : Set a personal note" }, + { " /nick : Set your nickname" }, + { " /log or : Enable/disable logging" }, + { " /groupchat : Create a group chat" }, + { " /myid : Print your ID" }, + { " /help : Print this message again" }, + { " /clear : Clear the window" }, + { " /quit or /exit : Exit Toxic" }, +#ifdef _SUPPORT_AUDIO + { " /lsdev : List devices where type: in|out" }, + { " /sdev : Set active device" }, #endif /* _SUPPORT_AUDIO */ - - wattron(window, COLOR_PAIR(CYAN) | A_BOLD); - wprintw(window, " * Argument messages must be enclosed in quotation marks.\n"); - wprintw(window, " * Use ctrl-o and ctrl-p to navigate through the tabs.\n\n"); - wattroff(window, COLOR_PAIR(CYAN) | A_BOLD); + +}; + int i; + + for (i = 0; i < NUMLINES; ++i) + line_info_add(self, NULL, NULL, NULL, lines[i], SYS_MSG, 0, 0); + + msg = " * Argument messages must be enclosed in quotation marks.\n" + " * Use ctrl-o and ctrl-p to navigate through the tabs.\n"; + line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN); } void cmd_quit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) @@ -388,16 +419,19 @@ void cmd_quit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { uint8_t *msg = NULL; + uint8_t *errmsg; if (argc >= 2) { msg = argv[2]; if (msg[0] != '\"') { - wprintw(window, "Note must be enclosed in quotes.\n"); + errmsg = "Note must be enclosed in quotes."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } } else if (argc != 1) { - wprintw(window, "Wrong number of arguments.\n"); + errmsg = "Wrong number of arguments."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } @@ -418,7 +452,8 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[ else if (!strcmp(l_status, "busy")) status_kind = TOX_USERSTATUS_BUSY; else { - wprintw(window, "Invalid status. Valid statuses are: online, busy and away.\n"); + errmsg = "Invalid status. Valid statuses are: online, busy and away."; + line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); return; } diff --git a/src/line_info.c b/src/line_info.c index 9f9d626..f140569 100644 --- a/src/line_info.c +++ b/src/line_info.c @@ -34,7 +34,6 @@ void line_info_init(struct history *hst) { hst->line_root = malloc(sizeof(struct line_info)); - memset(hst->line_root, 0, sizeof(struct line_info)); if (hst->line_root == NULL) { endwin(); @@ -42,6 +41,7 @@ void line_info_init(struct history *hst) exit(EXIT_FAILURE); } + memset(hst->line_root, 0, sizeof(struct line_info)); hst->line_start = hst->line_root; hst->line_end = hst->line_start; } @@ -64,8 +64,7 @@ static void line_info_reset_start(struct history *hst) void line_info_toggle_scroll(ToxWindow *self, bool scroll) { - ChatContext *ctx = self->chatwin; - WINDOW *win = self->is_prompt ? self->window : ctx->history; + WINDOW *win = self->chatwin->history; struct history *hst = self->chatwin->hst; if (scroll) { @@ -94,10 +93,8 @@ void line_info_cleanup(struct history *hst) void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *name2, uint8_t *msg, uint8_t msgtype, uint8_t bold, uint8_t colour) { - WINDOW *win = self->is_prompt ? self->window : self->chatwin->history; struct history *hst = self->chatwin->hst; struct line_info *new_line = malloc(sizeof(struct line_info)); - memset(new_line, 0, sizeof(struct line_info)); if (new_line == NULL) { endwin(); @@ -105,17 +102,18 @@ void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *na exit(EXIT_FAILURE); } + memset(new_line, 0, sizeof(struct line_info)); + int len = 1; /* there will always be a newline */ /* for type-specific formatting in print function */ switch (msgtype) { - case OUT_MSG: - case IN_MSG: - len += 2; - break; case ACTION: len += 3; break; + default: + len += 2; + break; } if (msg) { @@ -143,7 +141,7 @@ void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *na hst->line_end = new_line; /* If chat history exceeds limit move root forward and free old root */ - if (++(hst->line_items) >= MAX_HISTORY) { + if (++hst->line_items > MAX_HISTORY) { --hst->line_items; struct line_info *tmp = hst->line_root->next; tmp->prev = NULL; @@ -159,10 +157,12 @@ void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *na int y, y2, x, x2; getmaxyx(self->window, y2, x2); - getyx(win, y, x); + getyx(self->chatwin->history, y, x); + + int n = self->is_prompt ? 0 : CHATBOX_HEIGHT; /* move line_start forward proportionate to the number of new rows */ - if (y >= y2 - CHATBOX_HEIGHT) { + if (y >= y2 - n) { int i; int lines = 1 + (len / x2); @@ -177,7 +177,8 @@ void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *na void line_info_print(ToxWindow *self) { ChatContext *ctx = self->chatwin; - WINDOW *win = self->is_prompt ? self->window : win; + WINDOW *win = ctx->history; + wclear(win); wmove(win, 1, 0); int y2, x2; @@ -186,7 +187,7 @@ void line_info_print(ToxWindow *self) struct line_info *line = ctx->hst->line_start; int numlines = 0; - while(line && numlines <= x2) { + while(line && numlines <= y2) { uint8_t type = line->msgtype; numlines += line->len / x2; @@ -199,10 +200,10 @@ void line_info_print(ToxWindow *self) int nameclr = GREEN; - if (type == IN_MSG) - nameclr = CYAN; if (line->colour) nameclr = line->colour; + else if (type == IN_MSG) + nameclr = CYAN; wattron(win, COLOR_PAIR(nameclr)); wprintw(win, "%s: ", line->name1); @@ -249,6 +250,31 @@ void line_info_print(ToxWindow *self) wattroff(win, COLOR_PAIR(line->colour)); break; + + case PROMPT: + wattron(win, COLOR_PAIR(GREEN)); + wprintw(win, "$ "); + wattroff(win, COLOR_PAIR(GREEN)); + + if (line->msg[0]) + wprintw(win, "%s", line->msg); + + wprintw(win, "\n"); + break; + + case CONNECTION: + wattron(win, COLOR_PAIR(BLUE)); + wprintw(win, "%s", line->timestamp); + wattroff(win, COLOR_PAIR(BLUE)); + + wattron(win, COLOR_PAIR(line->colour)); + wattron(win, A_BOLD); + wprintw(win, "* %s ", line->name1); + wattroff(win, A_BOLD); + wprintw(win, "%s\n", line->msg); + wattroff(win, COLOR_PAIR(line->colour)); + + break; } line = line->next; diff --git a/src/line_info.h b/src/line_info.h index 51fd5b0..ea2e1e7 100644 --- a/src/line_info.h +++ b/src/line_info.h @@ -26,6 +26,7 @@ enum { SYS_MSG, IN_MSG, OUT_MSG, + PROMPT, ACTION, CONNECTION, } LINE_TYPE; diff --git a/src/main.c b/src/main.c index 47793d9..0125b3b 100644 --- a/src/main.c +++ b/src/main.c @@ -60,6 +60,7 @@ #include "prompt.h" #include "misc_tools.h" #include "file_senders.h" +#include "line_info.h" #ifdef _SUPPORT_AUDIO #include "audio_call.h" @@ -272,6 +273,8 @@ int init_connection(Tox *m) static void do_connection(Tox *m, ToxWindow *prompt) { + uint8_t msg[MAX_STR_SIZE] = {0}; + static int conn_try = 0; static int conn_err = 0; static bool dht_on = false; @@ -281,21 +284,21 @@ static void do_connection(Tox *m, ToxWindow *prompt) if (!dht_on && !is_connected && !(conn_try++ % 100)) { if (!conn_err) { if ((conn_err = init_connection(m))) { - prep_prompt_win(); - wprintw(prompt->window, "\nAuto-connect failed with error code %d\n", conn_err); + snprintf(msg, sizeof(msg), "\nAuto-connect failed with error code %d", conn_err); } } } else if (!dht_on && is_connected) { dht_on = true; prompt_update_connectionstatus(prompt, dht_on); - prep_prompt_win(); - wprintw(prompt->window, "DHT connected.\n"); + snprintf(msg, sizeof(msg), "DHT connected."); } else if (dht_on && !is_connected) { dht_on = false; prompt_update_connectionstatus(prompt, dht_on); - prep_prompt_win(); - wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n"); + snprintf(msg, sizeof(msg), "\nDHT disconnected. Attempting to reconnect."); } + + if (msg[0]) + line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); } static void load_friendlist(Tox *m) diff --git a/src/prompt.c b/src/prompt.c index b2a8521..6d54481 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -65,25 +65,6 @@ const uint8_t glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = { #endif /* _SUPPORT_AUDIO */ }; -/* prevents input string from eating system messages: call this prior to printing a prompt message - TODO: This is only a partial fix */ -void prep_prompt_win(void) -{ - ChatContext *ctx = prompt->chatwin; - - if (ctx->len <= 0) - return; - - wprintw(prompt->window, "\n"); - - if (!ctx->at_bottom) { - wmove(prompt->window, ctx->orig_y - 1, X_OFST); - ++ctx->orig_y; - } else { - wmove(prompt->window, ctx->orig_y - 2, X_OFST); - } -} - /* Updates own nick in prompt statusbar */ void prompt_update_nick(ToxWindow *prompt, uint8_t *nick, uint16_t len) { @@ -142,14 +123,26 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key) ChatContext *ctx = self->chatwin; int x, y, y2, x2; - getyx(self->window, y, x); - getmaxyx(self->window, y2, x2); + getyx(ctx->history, y, x); + getmaxyx(ctx->history, y2, x2); + + /* this is buggy */ + //if (key == T_KEY_ESC) { /* ESC key: Toggle history scroll mode */ + // bool scroll = ctx->hst->scroll_mode ? false : true; + // line_info_toggle_scroll(self, scroll); + //} + + /* If we're in scroll mode ignore rest of function */ + if (ctx->hst->scroll_mode) { + line_info_onKey(self, key); + return; + } /* BACKSPACE key: Remove one character from line */ if (key == 0x107 || key == 0x8 || key == 0x7f) { if (ctx->pos > 0) { del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len); - wmove(self->window, y, x-1); /* not necessary but fixes a display glitch */ + wmove(ctx->history, y, x-1); /* not necessary but fixes a display glitch */ ctx->scroll = false; } else { beep(); @@ -167,8 +160,8 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key) else if (key == T_KEY_DISCARD) { /* CTRL-U: Delete entire line behind pos */ if (ctx->pos > 0) { - wmove(self->window, ctx->orig_y, X_OFST); - wclrtobot(self->window); + wmove(ctx->history, ctx->orig_y, X_OFST); + wclrtobot(ctx->history); discard_buf(ctx->line, &ctx->pos, &ctx->len); } else { beep(); @@ -207,7 +200,7 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key) } else if (key == KEY_UP) { /* fetches previous item in history */ - wmove(self->window, ctx->orig_y, X_OFST); + wmove(ctx->history, ctx->orig_y, X_OFST); fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot, &ctx->hst_pos, MOVE_UP); @@ -222,14 +215,14 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key) int k = ctx->orig_y + ((ctx->len + p_ofst) / px2); if (k >= y2) { - wprintw(self->window, "\n"); + wprintw(ctx->history, "\n"); --ctx->orig_y; } } } else if (key == KEY_DOWN) { /* fetches next item in history */ - wmove(self->window, ctx->orig_y, X_OFST); + wmove(ctx->history, ctx->orig_y, X_OFST); fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot, &ctx->hst_pos, MOVE_DOWN); } @@ -258,8 +251,8 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key) } /* RETURN key: execute command */ else if (key == '\n') { - wprintw(self->window, "\n"); - uint8_t line[MAX_STR_SIZE]; + wprintw(ctx->history, "\n"); + uint8_t line[MAX_STR_SIZE] = {0}; if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) memset(&line, 0, sizeof(line)); @@ -267,7 +260,8 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key) if (!string_is_empty(line)) add_line_to_hist(ctx->line, ctx->len, ctx->ln_history, &ctx->hst_tot, &ctx->hst_pos); - execute(self->window, self, m, line, GLOBAL_COMMAND_MODE); + line_info_add(self, NULL, NULL, NULL, line, PROMPT, 0, 0); + execute(ctx->history, self, m, line, GLOBAL_COMMAND_MODE); reset_buf(ctx->line, &ctx->pos, &ctx->len); } } @@ -277,9 +271,8 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) ChatContext *ctx = self->chatwin; int x, y, x2, y2; - getyx(self->window, y, x); - getmaxyx(self->window, y2, x2); - wclrtobot(self->window); + getyx(ctx->history, y, x); + getmaxyx(ctx->history, y2, x2); line_info_print(self); /* if len is >= screen width offset max x by X_OFST to account for prompt char */ @@ -297,7 +290,7 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) reset_buf(ctx->line, &ctx->pos, &ctx->len); else - mvwprintw(self->window, ctx->orig_y, X_OFST, line); + mvwprintw(ctx->history, ctx->orig_y, X_OFST, line); int k = ctx->orig_y + ((ctx->len + p_ofst) / px2); @@ -315,9 +308,9 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) ctx->orig_y = y; } - wattron(self->window, COLOR_PAIR(GREEN)); - mvwprintw(self->window, ctx->orig_y, 0, "$ "); - wattroff(self->window, COLOR_PAIR(GREEN)); + wattron(ctx->history, COLOR_PAIR(GREEN)); + mvwprintw(ctx->history, ctx->orig_y, 0, "$ "); + wattroff(ctx->history, COLOR_PAIR(GREEN)); StatusBar *statusbar = self->stb; werase(statusbar->topline); @@ -363,43 +356,18 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) if (statusbar->statusmsg[0]) wprintw(statusbar->topline, " - %s", statusbar->statusmsg); - wprintw(statusbar->topline, "\n"); - /* put cursor back in correct spot */ int y_m = ctx->orig_y + ((ctx->pos + p_ofst) / px2); int x_m = (ctx->pos + X_OFST) % x2; wmove(self->window, y_m, x_m); } -static void prompt_onInit(ToxWindow *self, Tox *m) -{ - curs_set(1); - scrollok(self->window, true); - ChatContext *ctx = self->chatwin; - - ctx->log = malloc(sizeof(struct chatlog)); - ctx->hst = malloc(sizeof(struct history)); - - if (ctx->log == NULL || ctx->hst == NULL) { - endwin(); - fprintf(stderr, "malloc() failed. Aborting...\n"); - exit(EXIT_FAILURE); - } - - memset(ctx->log, 0, sizeof(struct chatlog)); - memset(ctx->hst, 0, sizeof(struct history)); - - execute(self->window, self, m, "/help", GLOBAL_COMMAND_MODE); - wclrtoeol(self->window); -} - static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum , uint8_t status) { if (friendnum < 0) return; ChatContext *ctx = self->chatwin; - prep_prompt_win(); uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'}; @@ -409,31 +377,18 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum if (!nick[0]) snprintf(nick, sizeof(nick), "%s", UNKNOWN_NAME); - wprintw(self->window, "\n"); - print_time(self->window); - - const uint8_t *msg; + uint8_t timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt); + uint8_t *msg; if (status == 1) { msg = "has come online"; - wattron(self->window, COLOR_PAIR(GREEN)); - wattron(self->window, A_BOLD); - wprintw(self->window, "* %s ", nick); - wattroff(self->window, A_BOLD); - wprintw(self->window, "%s\n", msg); - wattroff(self->window, COLOR_PAIR(GREEN)); - + line_info_add(self, timefrmt, nick, NULL, msg, CONNECTION, 0, GREEN); write_to_log(msg, nick, ctx->log, true); alert_window(self, WINDOW_ALERT_2, false); } else { msg = "has gone offline"; - wattron(self->window, COLOR_PAIR(RED)); - wattron(self->window, A_BOLD); - wprintw(self->window, "* %s ", nick); - wattroff(self->window, A_BOLD); - wprintw(self->window, "%s\n", msg); - wattroff(self->window, COLOR_PAIR(RED)); - + line_info_add(self, timefrmt, nick, NULL, msg, CONNECTION, 0, RED); write_to_log(msg, nick, ctx->log, true); } } @@ -443,33 +398,32 @@ static void prompt_onFriendRequest(ToxWindow *self, Tox *m, uint8_t *key, uint8_ /* make sure message data is null-terminated */ data[length - 1] = 0; ChatContext *ctx = self->chatwin; - prep_prompt_win(); - wprintw(self->window, "\n"); - print_time(self->window); + wprintw(ctx->history, "\n"); + print_time(ctx->history); uint8_t msg[MAX_STR_SIZE]; snprintf(msg, sizeof(msg), "Friend request with the message '%s'\n", data); - wprintw(self->window, "%s", msg); + wprintw(ctx->history, "%s", msg); write_to_log(msg, "", ctx->log, true); int n = add_friend_request(key); if (n == -1) { const uint8_t *errmsg = "Friend request queue is full. Discarding request.\n"; - wprintw(self->window, "%s", errmsg); + wprintw(ctx->history, "%s", errmsg); write_to_log(errmsg, "", ctx->log, true); return; } - wprintw(self->window, "Type \"/accept %d\" to accept it.\n", n); + wprintw(ctx->history, "Type \"/accept %d\" to accept it.\n", n); alert_window(self, WINDOW_ALERT_1, true); } void prompt_init_statusbar(ToxWindow *self, Tox *m) { - int x, y; - getmaxyx(self->window, y, x); + int x2, y2; + getmaxyx(self->window, y2, x2); /* Init statusbar info */ StatusBar *statusbar = self->stb; @@ -499,7 +453,36 @@ void prompt_init_statusbar(ToxWindow *self, Tox *m) prompt_update_status(prompt, status); /* Init statusbar subwindow */ - statusbar->topline = subwin(self->window, 2, x, 0, 0); + statusbar->topline = subwin(self->window, 2, x2, 0, 0); +} + +static void prompt_onInit(ToxWindow *self, Tox *m) +{ + ChatContext *ctx = self->chatwin; + + curs_set(1); + int y2, x2; + getmaxyx(self->window, y2, x2); + + ctx->history = subwin(self->window, y2, x2, 0, 0); + scrollok(ctx->history, 1); + + ctx->log = malloc(sizeof(struct chatlog)); + ctx->hst = malloc(sizeof(struct history)); + + if (ctx->log == NULL || ctx->hst == NULL) { + endwin(); + fprintf(stderr, "malloc() failed. Aborting...\n"); + exit(EXIT_FAILURE); + } + + memset(ctx->log, 0, sizeof(struct chatlog)); + memset(ctx->hst, 0, sizeof(struct history)); + + line_info_init(ctx->hst); + execute(ctx->history, self, m, "/help", GLOBAL_COMMAND_MODE); + + wmove(ctx->history, y2-1, 2); } ToxWindow new_prompt(void)