diff --git a/src/chat.c b/src/chat.c index 376700f..27567c4 100644 --- a/src/chat.c +++ b/src/chat.c @@ -17,6 +17,7 @@ #include "toxic_windows.h" #include "friendlist.h" #include "chat.h" +#include "commands.h" extern char *DATA_FILE; extern int store_data(Tox *m, char *path); diff --git a/src/commands.c b/src/commands.c new file mode 100644 index 0000000..55e1fdb --- /dev/null +++ b/src/commands.c @@ -0,0 +1,516 @@ +/* + * Toxic -- Tox Curses Client + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "toxic_windows.h" +#include "prompt.h" +#include "commands.h" + +extern char *DATA_FILE; + +extern uint8_t pending_frnd_requests[MAX_FRIENDS_NUM][TOX_CLIENT_ID_SIZE]; +extern uint8_t num_frnd_requests; + +extern uint8_t pending_grp_requests[MAX_GROUPCHAT_NUM][TOX_CLIENT_ID_SIZE]; +extern uint8_t num_grp_requests; + +/* command functions */ +void cmd_accept(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + /* check arguments */ + if (argc != 1) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + int num = atoi(argv[1]); + + if (num < 0 || num >= num_frnd_requests) { + wprintw(window, "No pending friend request with that number.\n"); + return; + } + + int friendnum = tox_addfriend_norequest(m, pending_frnd_requests[num]); + + if (friendnum == -1) + wprintw(window, "Failed to add friend.\n"); + else { + wprintw(window, "Friend request accepted.\n"); + on_friendadded(m, friendnum); + } +} + +void cmd_add(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + if (argc < 1 || argc > 2) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + char *id = argv[1]; + + if (id == NULL) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + uint8_t *msg; + + if (argc == 2) { + msg = argv[2]; + + if (msg == NULL) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + if (msg[0] != '\"') { + wprintw(window, "Messages must be enclosed in quotes.\n"); + return; + } + + msg[strlen(++msg)-1] = L'\0'; + + } else + msg = "Let's tox."; + + if (strlen(id) != 2 * TOX_FRIEND_ADDRESS_SIZE) { + wprintw(window, "Invalid ID length.\n"); + return; + } + + size_t i; + char xx[3]; + uint32_t x; + uint8_t id_bin[TOX_FRIEND_ADDRESS_SIZE]; + + for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) { + xx[0] = id[2 * i]; + xx[1] = id[2 * i + 1]; + xx[2] = '\0'; + + if (sscanf(xx, "%02x", &x) != 1) { + wprintw(window, "Invalid ID.\n"); + return; + } + + id_bin[i] = x; + } + + for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) { + id[i] = toupper(id[i]); + } + + int num = tox_addfriend(m, id_bin, msg, strlen(msg) + 1); + + switch (num) { + case TOX_FAERR_TOOLONG: + wprintw(window, "Message is too long.\n"); + break; + + case TOX_FAERR_NOMESSAGE: + wprintw(window, "Please add a message to your request.\n"); + break; + + case TOX_FAERR_OWNKEY: + wprintw(window, "That appears to be your own ID.\n"); + break; + + case TOX_FAERR_ALREADYSENT: + wprintw(window, "Friend request already sent.\n"); + break; + + case TOX_FAERR_UNKNOWN: + wprintw(window, "Undefined error when adding friend.\n"); + break; + + case TOX_FAERR_BADCHECKSUM: + wprintw(window, "Bad checksum in address.\n"); + break; + + case TOX_FAERR_SETNEWNOSPAM: + wprintw(window, "Nospam was different.\n"); + break; + + default: + wprintw(window, "Friend added as %d.\n", num); + on_friendadded(m, num); + break; + } +} + +void cmd_clear(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + wclear(window); + wprintw(window, "\n\n"); +} + +void cmd_connect(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + /* check arguments */ + if (argc != 3) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + tox_IP_Port dht; + char *ip = argv[1]; + char *port = argv[2]; + char *key = argv[3]; + + if (ip == NULL || port == NULL || key == NULL) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + if (atoi(port) == 0) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + uint8_t *binary_string = hex_string_to_bin(key); + tox_bootstrap_from_address(m, ip, TOX_ENABLE_IPV6_DEFAULT, + htons(atoi(port)), binary_string); + free(binary_string); +} + +void cmd_groupchat(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + int ngc = get_num_groupchats(); + + if (ngc < 0 || ngc > MAX_GROUPCHAT_NUM) { + wprintw(window, "\nMaximum number of group chats has been reached.\n"); + return; + } + + int groupnum = tox_add_groupchat(m); + + if (groupnum == -1) { + wprintw(window, "Group chat failed to initialize.\n"); + return; + } + + if (init_groupchat_win(prompt, m, groupnum) == -1) { + wprintw(window, "Group chat failed to initialize.\n"); + tox_del_groupchat(m, groupnum); + return; + } + + wprintw(window, "Group chat created as %d.\n", groupnum); +} + +void cmd_invite(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + if (argc != 2) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + if (argv[1] == NULL || argv[2] == NULL) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + uint8_t *friendname = argv[1]; + int groupnum = atoi(argv[2]); + + if (friendname[0] == '\"') + friendname[strlen(++friendname)-1] = L'\0'; + + int friendnum = get_friendnum(friendname); + + if (friendnum == -1) { + wprintw(window, "Friend '%s' not found.\n", friendname); + return; + } + + if (tox_invite_friend(m, friendnum, groupnum) == -1) { + wprintw(window, "Failed to invite friend.\n"); + return; + } + + wprintw(window, "Invited friend %s to group chat %d.\n", friendname, groupnum); +} + +void cmd_join(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + if (argc != 1) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + if (argv[1] == NULL) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + int num = atoi(argv[1]); + + if (num < 0 || num >= num_grp_requests) { + wprintw(window, "No pending group chat invites with that number.\n"); + return; + } + + int groupnum = tox_join_groupchat(m, num, pending_grp_requests[num]); + + if (groupnum == -1) { + wprintw(window, "Group chat failed to initialize.\n"); + return; + } + + if (init_groupchat_win(prompt, m, groupnum) == -1) { + wprintw(window, "Group chat window failed to initialize.\n"); + tox_del_groupchat(m, groupnum); + return; + } +} + +void cmd_msg(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + /* check arguments */ + if (argc != 2) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + char *id = argv[1]; + uint8_t *msg = argv[2]; + + if (id == NULL || msg == NULL) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + msg[strlen(++msg)-1] = L'\0'; + + if (tox_sendmessage(m, atoi(id), msg, strlen(msg) + 1) == 0) + wprintw(window, "Failed to send message.\n"); + else + wprintw(window, "Message successfully sent.\n"); +} + +void cmd_myid(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + char id[TOX_FRIEND_ADDRESS_SIZE * 2 + 1] = {0}; + uint8_t address[TOX_FRIEND_ADDRESS_SIZE]; + tox_getaddress(m, address); + + size_t i; + + for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) { + char xx[3]; + snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); + strcat(id, xx); + } + + wprintw(window, "%s\n", id); +} + +void cmd_nick(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + /* check arguments */ + if (argc != 1) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + uint8_t *nick = argv[1]; + + if (nick == NULL) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + int len = strlen(nick); + + if (nick[0] == '\"') { + ++nick; + len -= 2; + nick[len] = L'\0'; + } + + if (len > TOXIC_MAX_NAME_LENGTH) { + nick[TOXIC_MAX_NAME_LENGTH] = L'\0'; + len = TOXIC_MAX_NAME_LENGTH; + } + + tox_setname(m, nick, len+1); + prompt_update_nick(prompt, nick, len+1); + + store_data(m, DATA_FILE); +} + +void cmd_note(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + if (argc != 1) { + wprintw(window, "Wrong number of arguments.\n"); + return; + } + + uint8_t *msg = argv[1]; + + if (msg == NULL) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + if (msg[0] != '\"') { + wprintw(window, "Messages must be enclosed in quotes.\n"); + return; + } + + msg[strlen(++msg)-1] = L'\0'; + uint16_t len = strlen(msg) + 1; + tox_set_statusmessage(m, msg, len); + prompt_update_statusmessage(prompt, msg, len); +} + +void cmd_quit(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + exit_toxic(m); +} + +void cmd_status(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +{ + uint8_t *msg = NULL; + + if (argc == 2) { + + msg = argv[2]; + + if (msg == NULL) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + if (msg[0] != '\"') { + wprintw(window, "Messages must be enclosed in quotes.\n"); + return; + } + } else if (argc != 1) { + wprintw(window, "Wrong number of arguments.\n"); + return; + } + + char *status = argv[1]; + + if (status == NULL) { + wprintw(window, "Invalid syntax.\n"); + return; + } + + TOX_USERSTATUS status_kind; + + if (!strncmp(status, "online", strlen("online"))) + status_kind = TOX_USERSTATUS_NONE; + + else if (!strncmp(status, "away", strlen("away"))) + status_kind = TOX_USERSTATUS_AWAY; + + else if (!strncmp(status, "busy", strlen("busy"))) + status_kind = TOX_USERSTATUS_BUSY; + + else + wprintw(window, "Invalid status.\n"); + + tox_set_userstatus(m, status_kind); + prompt_update_status(prompt, status_kind); + + if (msg != NULL) { + msg[strlen(++msg)-1] = L'\0'; /* remove opening and closing quotes */ + uint16_t len = strlen(msg) + 1; + tox_set_statusmessage(m, msg, len); + prompt_update_statusmessage(prompt, msg, len); + } +} + +void execute(WINDOW *window, ToxWindow *prompt, Tox *m, char *u_cmd, int buf_len) +{ + int newlines = 0; + char cmd[MAX_STR_SIZE] = {'\0'}; + size_t i; + + for (i = 0; i < buf_len; ++i) { + if (u_cmd[i] == '\n') + ++newlines; + else + cmd[i - newlines] = u_cmd[i]; + } + + int leading_spc = 0; + + for (i = 0; i < MAX_STR_SIZE && isspace(cmd[i]); ++i) + leading_spc++; + + memmove(cmd, cmd + leading_spc, MAX_STR_SIZE - leading_spc); + + int cmd_end = strlen(cmd); + + while (cmd_end > 0 && cmd_end--) + if (!isspace(cmd[cmd_end])) + break; + + cmd[cmd_end + 1] = '\0'; + + /* insert \0 at argument boundaries */ + int numargs = 0; + for (i = 0; i < MAX_STR_SIZE; i++) { + if (cmd[i] == ' ') { + cmd[i] = '\0'; + numargs++; + } + /* skip over strings */ + else if (cmd[i] == '\"') { + while (cmd[++i] != '\"') { + if (cmd[i] == '\0') { + wprintw(window, "Invalid command: did you forget an opening or closing \"?\n"); + return; + } + } + } + } + + /* read arguments into array */ + char **cmdargs = malloc((numargs + 1) * sizeof(char *)); + if (!cmdargs) { + wprintw(window, "Invalid command: too many arguments.\n"); + return; + } + + int pos = 0; + + for (i = 0; i < numargs + 1; i++) { + cmdargs[i] = cmd + pos; + pos += strlen(cmdargs[i]) + 1; + /* replace empty strings with NULL for easier error checking */ + if (strlen(cmdargs[i]) == 0) + cmdargs[i] = NULL; + } + + /* no input */ + if (!cmdargs[0]) { + free(cmdargs); + return; + } + + /* match input to command list */ + for (i = 0; i < NUM_COMMANDS; i++) { + if (!strcmp(cmdargs[0], commands[i].name)) { + (commands[i].func)(window, prompt, m, numargs, cmdargs); + free(cmdargs); + return; + } + } + + /* no match */ + free(cmdargs); + wprintw(window, "Invalid command.\n"); +} \ No newline at end of file diff --git a/src/commands.h b/src/commands.h new file mode 100644 index 0000000..a6ad45e --- /dev/null +++ b/src/commands.h @@ -0,0 +1,43 @@ +/* + * Toxic -- Tox Curses Client + */ + +/* commands */ +void cmd_accept(WINDOW *, ToxWindow *, Tox *m, int, char **); +void cmd_add(WINDOW *, ToxWindow *, Tox *m, int, char **); +void cmd_clear(WINDOW *, ToxWindow *, Tox *m, int, char **); +void cmd_connect(WINDOW *, ToxWindow *, Tox *m, int, char **); +void cmd_groupchat(WINDOW *, ToxWindow *, Tox *m, int, char **); +void cmd_invite(WINDOW *, ToxWindow *, Tox *m, int, char **); +void cmd_join(WINDOW *, ToxWindow *, Tox *m, int, char **); +void cmd_msg(WINDOW *, ToxWindow *, Tox *m, int, char **); +void cmd_myid(WINDOW *, ToxWindow *, Tox *m, int, char **); +void cmd_nick(WINDOW *, ToxWindow *, Tox *m, int, char **); +void cmd_note(WINDOW *, ToxWindow *, Tox *m, int, char **); +void cmd_quit(WINDOW *, ToxWindow *, Tox *m, int, char **); +void cmd_status(WINDOW *, ToxWindow *, Tox *m, int, char **); + +void execute(WINDOW *window, ToxWindow *prompt, Tox *m, char *u_cmd, int buf_len); + +#define NUM_COMMANDS 15 + +static struct { + char *name; + void (*func)(WINDOW *, ToxWindow *, Tox *m, int, char **); +} commands[] = { + { "/accept", cmd_accept }, + { "/add", cmd_add }, + { "/clear", cmd_clear }, + { "/connect", cmd_connect }, + { "/exit", cmd_quit }, + { "/groupchat", cmd_groupchat }, + { "/invite", cmd_invite }, + { "/join", cmd_join }, + { "/msg", cmd_msg }, + { "/myid", cmd_myid }, + { "/nick", cmd_nick }, + { "/note", cmd_note }, + { "/q", cmd_quit }, + { "/quit", cmd_quit }, + { "/status", cmd_status }, +}; diff --git a/src/groupchat.c b/src/groupchat.c index 1c25c1d..28d4515 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -15,7 +15,7 @@ #include "toxic_windows.h" #include "chat.h" -#include "prompt.h" +#include "commands.h" static GroupChat groupchats[MAX_GROUPCHAT_NUM]; static int group_chat_index = 0; diff --git a/src/prompt.c b/src/prompt.c index efc8590..7a09e1f 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -11,9 +11,7 @@ #include #include "prompt.h" -#include "groupchat.h" - -extern char *DATA_FILE; +#include "commands.h" uint8_t pending_frnd_requests[MAX_FRIENDS_NUM][TOX_CLIENT_ID_SIZE]; uint8_t num_frnd_requests = 0; @@ -24,46 +22,6 @@ uint8_t num_grp_requests = 0; static char prompt_buf[MAX_STR_SIZE] = {'\0'}; static int prompt_buf_pos = 0; -/* commands */ -void cmd_accept(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_add(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_clear(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_connect(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_groupchat(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_help(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_invite(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_join(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_msg(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_myid(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_nick(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_quit(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_status(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_note(WINDOW *, ToxWindow *, Tox *m, int, char **); - -#define NUM_COMMANDS 16 - -static struct { - char *name; - void (*func)(WINDOW *, ToxWindow *, Tox *m, int, char **); -} commands[] = { - { "/accept", cmd_accept }, - { "/add", cmd_add }, - { "/clear", cmd_clear }, - { "/connect", cmd_connect }, - { "/exit", cmd_quit }, - { "/groupchat", cmd_groupchat }, - { "/help", cmd_help }, - { "/invite", cmd_invite }, - { "/join", cmd_join }, - { "/msg", cmd_msg }, - { "/myid", cmd_myid }, - { "/nick", cmd_nick }, - { "/q", cmd_quit }, - { "/quit", cmd_quit }, - { "/status", cmd_status }, - { "/note", cmd_note }, -}; - /* Updates own nick in prompt statusbar */ void prompt_update_nick(ToxWindow *prompt, uint8_t *nick, uint16_t len) { @@ -139,526 +97,32 @@ unsigned char *hex_string_to_bin(char hex_string[]) return val; } -/* command functions */ -void cmd_accept(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) +void print_prompt_help(ToxWindow *self) { - /* check arguments */ - if (argc != 1) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - int num = atoi(argv[1]); - - if (num < 0 || num >= num_frnd_requests) { - wprintw(window, "No pending friend request with that number.\n"); - return; - } - - int friendnum = tox_addfriend_norequest(m, pending_frnd_requests[num]); - - if (friendnum == -1) - wprintw(window, "Failed to add friend.\n"); - else { - wprintw(window, "Friend request accepted.\n"); - on_friendadded(m, friendnum); - } -} - -void cmd_add(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - if (argc < 1 || argc > 2) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - char *id = argv[1]; - - if (id == NULL) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - uint8_t *msg; - - if (argc == 2) { - msg = argv[2]; - - if (msg == NULL) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - if (msg[0] != '\"') { - wprintw(window, "Messages must be enclosed in quotes.\n"); - return; - } - - msg[strlen(++msg)-1] = L'\0'; - - } else - msg = "Let's tox."; - - if (strlen(id) != 2 * TOX_FRIEND_ADDRESS_SIZE) { - wprintw(window, "Invalid ID length.\n"); - return; - } - - size_t i; - char xx[3]; - uint32_t x; - uint8_t id_bin[TOX_FRIEND_ADDRESS_SIZE]; - - for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) { - xx[0] = id[2 * i]; - xx[1] = id[2 * i + 1]; - xx[2] = '\0'; - - if (sscanf(xx, "%02x", &x) != 1) { - wprintw(window, "Invalid ID.\n"); - return; - } - - id_bin[i] = x; - } - - for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) { - id[i] = toupper(id[i]); - } - - int num = tox_addfriend(m, id_bin, msg, strlen(msg) + 1); - - switch (num) { - case TOX_FAERR_TOOLONG: - wprintw(window, "Message is too long.\n"); - break; - - case TOX_FAERR_NOMESSAGE: - wprintw(window, "Please add a message to your request.\n"); - break; - - case TOX_FAERR_OWNKEY: - wprintw(window, "That appears to be your own ID.\n"); - break; - - case TOX_FAERR_ALREADYSENT: - wprintw(window, "Friend request already sent.\n"); - break; - - case TOX_FAERR_UNKNOWN: - wprintw(window, "Undefined error when adding friend.\n"); - break; - - case TOX_FAERR_BADCHECKSUM: - wprintw(window, "Bad checksum in address.\n"); - break; - - case TOX_FAERR_SETNEWNOSPAM: - wprintw(window, "Nospam was different.\n"); - break; - - default: - wprintw(window, "Friend added as %d.\n", num); - on_friendadded(m, num); - break; - } -} - -void cmd_clear(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - wclear(window); - wprintw(window, "\n\n"); -} - -void cmd_connect(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - /* check arguments */ - if (argc != 3) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - tox_IP_Port dht; - char *ip = argv[1]; - char *port = argv[2]; - char *key = argv[3]; - - if (ip == NULL || port == NULL || key == NULL) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - if (atoi(port) == 0) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - uint8_t *binary_string = hex_string_to_bin(key); - tox_bootstrap_from_address(m, ip, TOX_ENABLE_IPV6_DEFAULT, - htons(atoi(port)), binary_string); - free(binary_string); -} - -void cmd_quit(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - exit_toxic(m); -} - -void cmd_groupchat(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - int ngc = get_num_groupchats(); - - if (ngc < 0 || ngc > MAX_GROUPCHAT_NUM) { - wprintw(window, "\nMaximum number of group chats has been reached.\n"); - return; - } - - int groupnum = tox_add_groupchat(m); - - if (groupnum == -1) { - wprintw(window, "Group chat failed to initialize.\n"); - return; - } - - if (init_groupchat_win(prompt, m, groupnum) == -1) { - wprintw(window, "Group chat failed to initialize.\n"); - tox_del_groupchat(m, groupnum); - return; - } - - wprintw(window, "Group chat created as %d.\n", groupnum); -} - -void cmd_help(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - wclear(window); - wattron(window, COLOR_PAIR(CYAN) | A_BOLD); - wprintw(window, "\n\nCommands:\n"); - wattroff(window, A_BOLD); - - wprintw(window, " /connect : Connect to DHT server\n"); - wprintw(window, " /add : Add friend with optional message\n"); - wprintw(window, " /accept : Accept friend request\n"); - wprintw(window, " /status : Set your status with optional note\n"); - wprintw(window, " /note : Set a personal note\n"); - wprintw(window, " /nick : Set your nickname\n"); - wprintw(window, " /join : Join a group chat\n"); - wprintw(window, " /invite : Invite friend to a groupchat\n"); - wprintw(window, " /groupchat : Create a group chat\n"); - wprintw(window, " /myid : Print your ID\n"); - wprintw(window, " /quit or /exit : Exit Toxic\n"); - wprintw(window, " /help : Print this message again\n"); - wprintw(window, " /clear : Clear this window\n"); - - wattron(window, A_BOLD); - wprintw(window, "\n * Messages must be enclosed in quotation marks.\n"); - wprintw(window, " * Use the TAB key to navigate through the tabs.\n\n"); - wattroff(window, A_BOLD); - - wattroff(window, COLOR_PAIR(CYAN)); -} - -void cmd_invite(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - if (argc != 2) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - if (argv[1] == NULL || argv[2] == NULL) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - uint8_t *friendname = argv[1]; - int groupnum = atoi(argv[2]); - - if (friendname[0] == '\"') - friendname[strlen(++friendname)-1] = L'\0'; - - int friendnum = get_friendnum(friendname); - - if (friendnum == -1) { - wprintw(window, "Friend '%s' not found.\n", friendname); - return; - } - - if (tox_invite_friend(m, friendnum, groupnum) == -1) { - wprintw(window, "Failed to invite friend.\n"); - return; - } - - wprintw(window, "Invited friend %s to group chat %d.\n", friendname, groupnum); -} - -void cmd_join(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - if (argc != 1) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - if (argv[1] == NULL) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - int num = atoi(argv[1]); - - if (num < 0 || num >= num_grp_requests) { - wprintw(window, "No pending group chat invites with that number.\n"); - return; - } - - int groupnum = tox_join_groupchat(m, num, pending_grp_requests[num]); - - if (groupnum == -1) { - wprintw(window, "Group chat failed to initialize.\n"); - return; - } - - if (init_groupchat_win(prompt, m, groupnum) == -1) { - wprintw(window, "Group chat window failed to initialize.\n"); - tox_del_groupchat(m, groupnum); - return; - } -} - -void cmd_msg(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - /* check arguments */ - if (argc != 2) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - char *id = argv[1]; - uint8_t *msg = argv[2]; - - if (id == NULL || msg == NULL) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - msg[strlen(++msg)-1] = L'\0'; - - if (tox_sendmessage(m, atoi(id), msg, strlen(msg) + 1) == 0) - wprintw(window, "Failed to send message.\n"); - else - wprintw(window, "Message successfully sent.\n"); -} - -void cmd_myid(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - char id[TOX_FRIEND_ADDRESS_SIZE * 2 + 1] = {0}; - uint8_t address[TOX_FRIEND_ADDRESS_SIZE]; - tox_getaddress(m, address); - - size_t i; - - for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) { - char xx[3]; - snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); - strcat(id, xx); - } - - wprintw(window, "%s\n", id); -} - -void cmd_nick(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - /* check arguments */ - if (argc != 1) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - uint8_t *nick = argv[1]; - - if (nick == NULL) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - int len = strlen(nick); - - if (nick[0] == '\"') { - ++nick; - len -= 2; - nick[len] = L'\0'; - } - - if (len > TOXIC_MAX_NAME_LENGTH) { - nick[TOXIC_MAX_NAME_LENGTH] = L'\0'; - len = TOXIC_MAX_NAME_LENGTH; - } - - tox_setname(m, nick, len+1); - prompt_update_nick(prompt, nick, len+1); - - store_data(m, DATA_FILE); -} - -void cmd_status(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - uint8_t *msg = NULL; - - if (argc == 2) { - - msg = argv[2]; - - if (msg == NULL) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - if (msg[0] != '\"') { - wprintw(window, "Messages must be enclosed in quotes.\n"); - return; - } - } else if (argc != 1) { - wprintw(window, "Wrong number of arguments.\n"); - return; - } - - char *status = argv[1]; - - if (status == NULL) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - TOX_USERSTATUS status_kind; - - if (!strncmp(status, "online", strlen("online"))) - status_kind = TOX_USERSTATUS_NONE; - - else if (!strncmp(status, "away", strlen("away"))) - status_kind = TOX_USERSTATUS_AWAY; - - else if (!strncmp(status, "busy", strlen("busy"))) - status_kind = TOX_USERSTATUS_BUSY; - - else - wprintw(window, "Invalid status.\n"); - - tox_set_userstatus(m, status_kind); - prompt_update_status(prompt, status_kind); - - if (msg != NULL) { - msg[strlen(++msg)-1] = L'\0'; /* remove opening and closing quotes */ - uint16_t len = strlen(msg) + 1; - tox_set_statusmessage(m, msg, len); - prompt_update_statusmessage(prompt, msg, len); - } -} - -void cmd_note(WINDOW *window, ToxWindow *prompt, Tox *m, int argc, char **argv) -{ - if (argc != 1) { - wprintw(window, "Wrong number of arguments.\n"); - return; - } - - uint8_t *msg = argv[1]; - - if (msg == NULL) { - wprintw(window, "Invalid syntax.\n"); - return; - } - - if (msg[0] != '\"') { - wprintw(window, "Messages must be enclosed in quotes.\n"); - return; - } - - msg[strlen(++msg)-1] = L'\0'; - uint16_t len = strlen(msg) + 1; - tox_set_statusmessage(m, msg, len); - prompt_update_statusmessage(prompt, msg, len); -} - -void execute(WINDOW *window, ToxWindow *prompt, Tox *m, char *u_cmd, int buf_len) -{ - int newlines = 0; - char cmd[MAX_STR_SIZE] = {'\0'}; - size_t i; - - for (i = 0; i < buf_len; ++i) { - if (u_cmd[i] == '\n') - ++newlines; - else - cmd[i - newlines] = u_cmd[i]; - } - - int leading_spc = 0; - - for (i = 0; i < MAX_STR_SIZE && isspace(cmd[i]); ++i) - leading_spc++; - - memmove(cmd, cmd + leading_spc, MAX_STR_SIZE - leading_spc); - - int cmd_end = strlen(cmd); - - while (cmd_end > 0 && cmd_end--) - if (!isspace(cmd[cmd_end])) - break; - - cmd[cmd_end + 1] = '\0'; - - /* insert \0 at argument boundaries */ - int numargs = 0; - for (i = 0; i < MAX_STR_SIZE; i++) { - if (cmd[i] == ' ') { - cmd[i] = '\0'; - numargs++; - } - /* skip over strings */ - else if (cmd[i] == '\"') { - while (cmd[++i] != '\"') { - if (cmd[i] == '\0') { - wprintw(window, "Invalid command: did you forget an opening or closing \"?\n"); - return; - } - } - } - } - - /* read arguments into array */ - char **cmdargs = malloc((numargs + 1) * sizeof(char *)); - if (!cmdargs) { - wprintw(window, "Invalid command: too many arguments.\n"); - return; - } - - int pos = 0; - - for (i = 0; i < numargs + 1; i++) { - cmdargs[i] = cmd + pos; - pos += strlen(cmdargs[i]) + 1; - /* replace empty strings with NULL for easier error checking */ - if (strlen(cmdargs[i]) == 0) - cmdargs[i] = NULL; - } - - /* no input */ - if (!cmdargs[0]) { - free(cmdargs); - return; - } - - /* match input to command list */ - for (i = 0; i < NUM_COMMANDS; i++) { - if (!strcmp(cmdargs[0], commands[i].name)) { - (commands[i].func)(window, prompt, m, numargs, cmdargs); - free(cmdargs); - return; - } - } - - /* no match */ - free(cmdargs); - wprintw(window, "Invalid command.\n"); + wclear(self->window); + wattron(self->window, COLOR_PAIR(CYAN) | A_BOLD); + wprintw(self->window, "\n\nCommands:\n"); + wattroff(self->window, A_BOLD); + + wprintw(self->window, " /add : Add friend with optional message\n"); + wprintw(self->window, " /accept : Accept friend request\n"); + wprintw(self->window, " /status : Set your status with optional note\n"); + wprintw(self->window, " /note : Set a personal note\n"); + wprintw(self->window, " /nick : Set your nickname\n"); + wprintw(self->window, " /join : Join a group chat\n"); + wprintw(self->window, " /invite : Invite friend to a groupchat\n"); + wprintw(self->window, " /groupchat : Create a group chat\n"); + wprintw(self->window, " /myid : Print your ID\n"); + wprintw(self->window, " /quit or /exit : Exit Toxic\n"); + wprintw(self->window, " /help : Print this message again\n"); + wprintw(self->window, " /clear : Clear this window\n"); + + wattron(self->window, A_BOLD); + wprintw(self->window, " * Messages must be enclosed in quotation marks.\n"); + wprintw(self->window, " * Use the TAB key to navigate through the tabs.\n"); + wattroff(self->window, A_BOLD); + + wattroff(self->window, COLOR_PAIR(CYAN)); } static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key) @@ -684,7 +148,12 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key) /* RETURN key: execute command */ else if (key == '\n') { wprintw(self->window, "\n"); - execute(self->window, self, m, prompt_buf, prompt_buf_pos); + + if (!strncmp(prompt_buf, "/help", strlen("/help"))) + print_prompt_help(self); + else + execute(self->window, self, m, prompt_buf, prompt_buf_pos); + prompt_buf_pos = 0; prompt_buf[0] = 0; } @@ -762,7 +231,7 @@ static void prompt_onDraw(ToxWindow *self, Tox *m) static void prompt_onInit(ToxWindow *self, Tox *m) { scrollok(self->window, 1); - cmd_help(self->window, self, m, 0, NULL); + print_prompt_help(self); wclrtoeol(self->window); } @@ -846,7 +315,7 @@ void prompt_init_statusbar(ToxWindow *self, Tox *m) statusbar->topline = subwin(self->window, 2, x, 0, 0); } -ToxWindow new_prompt() +ToxWindow new_prompt(void) { ToxWindow ret; memset(&ret, 0, sizeof(ret)); diff --git a/src/prompt.h b/src/prompt.h index ba89120..4ea4762 100644 --- a/src/prompt.h +++ b/src/prompt.h @@ -1,9 +1,13 @@ +/* + * Toxic -- Tox Curses Client + */ + #ifndef PROMPT_H_UZYGWFFL #define PROMPT_H_UZYGWFFL #include "toxic_windows.h" -ToxWindow new_prompt(); +ToxWindow new_prompt(void); int add_req(uint8_t *public_key); unsigned char *hex_string_to_bin(char hex_string[]); void prompt_init_statusbar(ToxWindow *self, Tox *m); @@ -12,22 +16,4 @@ void prompt_update_statusmessage(ToxWindow *prompt, uint8_t *statusmsg, uint16_t void prompt_update_status(ToxWindow *prompt, TOX_USERSTATUS status); void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected); -/* commands */ -void cmd_accept(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_add(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_clear(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_connect(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_groupchat(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_help(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_invite(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_join(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_msg(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_myid(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_nick(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_quit(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_status(WINDOW *, ToxWindow *, Tox *m, int, char **); -void cmd_note(WINDOW *, ToxWindow *, Tox *m, int, char **); - -void execute(WINDOW *window, ToxWindow *prompt, Tox *m, char *u_cmd, int buf_len); - #endif /* end of include guard: PROMPT_H_UZYGWFFL */