From 1974fa23d21bedb672f1c0d77dfa85f73037f5c1 Mon Sep 17 00:00:00 2001 From: plutooo Date: Mon, 29 Jul 2013 16:32:39 -0700 Subject: [PATCH 001/172] Initial commit for Toxic, a new curses interface for Tox. Still a work-in-progress. --- main.c | 229 ++++++++++++++++++++++++++++++++++++++++++ prompt.c | 292 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ windows.h | 10 ++ 3 files changed, 531 insertions(+) create mode 100644 main.c create mode 100644 prompt.c create mode 100644 windows.h diff --git a/main.c b/main.c new file mode 100644 index 0000000..0aad677 --- /dev/null +++ b/main.c @@ -0,0 +1,229 @@ +/* + * Toxic -- Tox Curses Client + */ + +#include +#include +#include +#include +#include + +#include "../../core/Messenger.h" +#include "../../core/network.h" + +#include "windows.h" + +extern ToxWindow new_prompt(); +extern int add_req(uint8_t* public_key); // XXX + +#define TOXWINDOWS_MAX_NUM 32 + +static ToxWindow windows[TOXWINDOWS_MAX_NUM]; +static int w_num; +static int w_active; +static ToxWindow* prompt; + +// CALLBACKS START +void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) { + int n = add_req(public_key); + + wprintw(prompt->window, "\nFriend request.\nUse \"accept %d\" to accept it.\n", n); +} + +void on_message(int friendnumber, uint8_t* string, uint16_t length) { + wprintw(prompt->window, "\n(message) %d: %s!\n", friendnumber, string); +} + +void on_nickchange(int friendnumber, uint8_t* string, uint16_t length) { + wprintw(prompt->window, "\n(nick) %d: %s!\n", friendnumber, string); +} + +void on_statuschange(int friendnumber, uint8_t* string, uint16_t length) { + wprintw(prompt->window, "\n(status) %d: %s!\n", friendnumber, string); +} +// CALLBACKS END + +static void init_term() { + // Setup terminal. + initscr(); + cbreak(); + keypad(stdscr, 1); + noecho(); + timeout(2000); + + if(has_colors()) { + start_color(); + init_pair(1, COLOR_GREEN, COLOR_BLACK); + init_pair(2, COLOR_CYAN, COLOR_BLACK); + init_pair(3, COLOR_RED, COLOR_BLACK); + init_pair(4, COLOR_BLUE, COLOR_BLACK); + } + + refresh(); +} + +static void init_tox() { + // Init core. + initMessenger(); + + // Callbacks. + m_callback_friendrequest(on_request); + m_callback_friendmessage(on_message); + m_callback_namechange(on_nickchange); + m_callback_userstatus(on_statuschange); +} + +static int add_window(ToxWindow w) { + if(w_num == TOXWINDOWS_MAX_NUM) + return -1; + + if(LINES < 2) + return -1; + + w.window = newwin(LINES - 2, COLS, 0, 0); + + if(w.window == NULL) + return -1; + + windows[w_num++] = w; + w.onInit(&w); + + return w_num; +} + +static void init_windows() { + w_num = 0; + w_active = 0; + + if(add_window(new_prompt()) == -1) { + fprintf(stderr, "add_window() failed.\n"); + + endwin(); + exit(1); + } + + prompt = &windows[0]; +} + +static void do_tox() { + static bool dht_on = false; + + if(!dht_on && DHT_isconnected()) { + dht_on = true; + wprintw(prompt->window, "\nDHT connected!\n"); + } + else if(dht_on && !DHT_isconnected()) { + dht_on = false; + wprintw(prompt->window, "\nDHT disconnected!\n"); + } + + doMessenger(); +} + +static void load_data() { + FILE* fd; + size_t len; + uint8_t* buf; + + if((fd = fopen("data", "r")) != NULL) { + fseek(fd, 0, SEEK_END); + len = ftell(fd); + fseek(fd, 0, SEEK_SET); + + buf = malloc(len); + + if(buf == NULL) { + fprintf(stderr, "malloc() failed.\n"); + fclose(fd); + exit(1); + } + + if(fread(buf, len, 1, fd) != 1){ + fprintf(stderr, "fread() failed.\n"); + free(buf); + fclose(fd); + exit(1); + } + + Messenger_load(buf, len); + } + else { + len = Messenger_size(); + buf = malloc(len); + + if(buf == NULL) { + fprintf(stderr, "malloc() failed.\n"); + exit(1); + } + + Messenger_save(buf); + + fd = fopen("data", "w"); + if(fd == NULL) { + fprintf(stderr, "fopen() failed.\n"); + free(buf); + exit(1); + } + + if(fwrite(buf, len, 1, fd) != 1){ + fprintf(stderr, "fwrite() failed.\n"); + free(buf); + fclose(fd); + exit(1); + } + } + + free(buf); + fclose(fd); +} + +static void draw_bar() { + size_t i; + + attron(COLOR_PAIR(4)); + mvhline(LINES - 2, 0, '_', COLS); + attroff(COLOR_PAIR(4)); + + move(LINES - 1, 0); + + for(i=0; ionDraw(a); + draw_bar(); + + ch = getch(); + if(ch != ERR) { + a->onKey(a, ch); + } + + } + + return 0; +} + diff --git a/prompt.c b/prompt.c new file mode 100644 index 0000000..4a59cc7 --- /dev/null +++ b/prompt.c @@ -0,0 +1,292 @@ +/* + * Toxic -- Tox Curses Client + */ + +#include +#include +#include +#include + +#include "../../core/Messenger.h" +#include "../../core/network.h" + +#include "windows.h" + +uint8_t pending_requests[256][CLIENT_ID_SIZE]; // XXX +uint8_t num_requests=0; // XXX + +// XXX: +int add_req(uint8_t* public_key) { + memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE); + ++num_requests; + + return num_requests-1; +} + +// XXX: FIX +unsigned char * hex_string_to_bin(char hex_string[]) +{ + size_t len = strlen(hex_string); + unsigned char *val = malloc(len); + char *pos = hex_string; + int i; + for(i = 0; i < len; ++i, pos+=2) + sscanf(pos,"%2hhx",&val[i]); + return val; +} + +static char prompt_buf[256] = {0}; +static int prompt_buf_pos=0; + +static void execute(ToxWindow* self, char* cmd) { + + // quit/exit: Exit program. + if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit")) { + endwin(); + exit(0); + } + else if(!strncmp(cmd, "connect ", strlen("connect "))) { + char* ip; + char* port; + char* key; + IP_Port dht; + + ip = strchr(cmd, ' '); + if(ip == NULL) { + return; + } + + ip++; + + port = strchr(ip, ' '); + if(port == NULL) { + return; + } + + port[0] = 0; + port++; + + key = strchr(port, ' '); + if(key == NULL) { + return; + } + + key[0] = 0; + key++; + + if(atoi(port) == 0) { + return; + } + + wprintw(self->window, "ip=%s, port=%s, key=%s\n", ip, port, key); + + dht.port = htons(atoi(port)); + + int resolved_address = resolve_addr(ip); + if (resolved_address == -1) { + return; + } + + dht.ip.i = resolved_address; + DHT_bootstrap(dht, hex_string_to_bin(key)); + } + else if(!strncmp(cmd, "add ", strlen("add "))) { + char* id; + char* msg; + int num; + + id = strchr(cmd, ' '); + + if(id == NULL) { + return; + } + + id++; + + msg = strchr(id, ' '); + if(msg == NULL) { + return; + } + + msg[0] = 0; + msg++; + + num = m_addfriend((uint8_t*) id, (uint8_t*) msg, strlen(msg)+1); + wprintw(self->window, "Friend added as %d.\n", num); + } + else if(!strncmp(cmd, "status ", strlen("status "))) { + char* msg; + + msg = strchr(cmd, ' '); + if(msg == NULL) { + return; + } + + msg++; + m_set_userstatus((uint8_t*) msg, strlen(msg)+1); + wprintw(self->window, "Status set to: %s.\n", msg); + } + else if(!strncmp(cmd, "nick ", strlen("nick "))) { + char* nick; + + nick = strchr(cmd, ' '); + if(nick == NULL) { + return; + } + + nick++; + setname((uint8_t*) nick, strlen(nick)+1); + wprintw(self->window, "Nickname set to: %s.\n", nick); + } + else if(!strcmp(cmd, "myid")) { + // XXX: Clean this up + char idstring0[200]; + char idstring1[32][5]; + char idstring2[32][5]; + uint32_t i; + + for(i = 0; i < 32; i++) { + if(self_public_key[i] < 16) + strcpy(idstring1[i], "0"); + else + strcpy(idstring1[i], ""); + + sprintf(idstring2[i], "%hhX", self_public_key[i]); + } + + for (i=0; i<32; i++) { + strcat(idstring0, idstring1[i]); + strcat(idstring0, idstring2[i]); + } + + wprintw(self->window, "%s\n", idstring0); + } + else if(!strncmp(cmd, "accept ", strlen("accept "))) { + char* id; + int num; + + id = strchr(cmd, ' '); + if(id == NULL) { + return; + } + id++; + + num = atoi(id); + if(num >= num_requests) { + return; + } + + num = m_addfriend_norequest(pending_requests[num]); + wprintw(self->window, "Friend accepted as: %d.\n", num); + } + else if(!strncmp(cmd, "msg ", strlen("msg "))) { + char* id; + char* msg; + + id = strchr(cmd, ' '); + + if(id == NULL) { + return; + } + + id++; + + msg = strchr(id, ' '); + if(msg == NULL) { + return; + } + + msg[0] = 0; + msg++; + + if(m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) != 1) { + wprintw(self->window, "Error occurred while sending message.\n"); + } + else { + wprintw(self->window, "Message successfully sent.\n"); + } + } +} + +static void prompt_onKey(ToxWindow* self, int key) { + + // PRINTABLE characters: Add to line. + if(isprint(key)) { + + if(prompt_buf_pos == (sizeof(prompt_buf) - 1)) { + return; + } + + prompt_buf[prompt_buf_pos++] = key; + prompt_buf[prompt_buf_pos] = 0; + } + + // RETURN key: execute command. + else if(key == '\n') { + wprintw(self->window, "\n"); + execute(self, prompt_buf); + + prompt_buf_pos = 0; + prompt_buf[0] = 0; + } + + // BACKSPACE key: Remove one character from line. + else if(key == 0x107) { + + if(prompt_buf_pos != 0) { + prompt_buf[--prompt_buf_pos] = 0; + } + } +} + +static void prompt_onDraw(ToxWindow* self) { + int x, y; + + mvwin(self->window,0,0); + wresize(self->window, LINES-2, COLS); + + getyx(self->window, y, x); + (void) x; + + wattron(self->window, COLOR_PAIR(1)); + mvwprintw(self->window, y, 0, "# "); + wattroff(self->window, COLOR_PAIR(1)); + + mvwprintw(self->window, y, 2, "%s", prompt_buf); + wclrtoeol(self->window); + + wrefresh(self->window); +} + +static void print_usage(ToxWindow* self) { + wattron(self->window, COLOR_PAIR(2) | A_BOLD); + wprintw(self->window, "Usage:\n"); + wattroff(self->window, A_BOLD); + + wprintw(self->window, " connect : Connect to DHT server\n"); + wprintw(self->window, " add : Add friend\n"); + wprintw(self->window, " status : Set your status\n"); + wprintw(self->window, " nick : Set your nickname\n"); + wprintw(self->window, " accept : Accept friend request\n"); + wprintw(self->window, " myid : Print your ID\n"); + wprintw(self->window, " quit/exit : Exit program\n"); + wattroff(self->window, COLOR_PAIR(2)); +} + +static void prompt_onInit(ToxWindow* self) { + scrollok(self->window, 1); + + print_usage(self); + wclrtoeol(self->window); +} + +ToxWindow new_prompt() { + ToxWindow ret; + + ret.onKey = &prompt_onKey; + ret.onDraw = &prompt_onDraw; + ret.onInit = &prompt_onInit; + strcpy(ret.title, "[prompt]"); + + return ret; +} diff --git a/windows.h b/windows.h new file mode 100644 index 0000000..2e082ca --- /dev/null +++ b/windows.h @@ -0,0 +1,10 @@ +typedef struct ToxWindow_ ToxWindow; + +struct ToxWindow_ { + void(*onKey)(ToxWindow*, int); + void(*onDraw)(ToxWindow*); + void(*onInit)(ToxWindow*); + char title[256]; + + WINDOW* window; +}; From d6c53649402ea6655f58e77abb92136a902bf419 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Mon, 29 Jul 2013 20:45:53 -0400 Subject: [PATCH 002/172] Fixed formatting of some cmake files --- CMakeLists.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..43eb379 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 2.6.0) +project(toxic C) + +set(exe_name toxic) + +add_executable(${exe_name} + toxic/main.c + toxic/prompt.c) + +target_link_libraries(${exe_name} + curses) + +linkCoreLibraries(${exe_name}) From 4063f14f38bd6c548c57d278597b6a4ea765f40a Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Tue, 30 Jul 2013 11:55:46 -0400 Subject: [PATCH 003/172] Fixed cmake --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 43eb379..4f9785d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,8 +4,8 @@ project(toxic C) set(exe_name toxic) add_executable(${exe_name} - toxic/main.c - toxic/prompt.c) + main.c + prompt.c) target_link_libraries(${exe_name} curses) From 31e49e2ec5db8f2ed38fa12ea644faae246f48ec Mon Sep 17 00:00:00 2001 From: plutooo Date: Tue, 30 Jul 2013 12:47:40 -0700 Subject: [PATCH 004/172] Fixed a bunch of bugs in TOXIC, added friendlist and more. --- CMakeLists.txt | 3 +- friendlist.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 49 +++++++++++++++++-- prompt.c | 107 +++++++++++++++++++++++++++--------------- 4 files changed, 239 insertions(+), 45 deletions(-) create mode 100644 friendlist.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f9785d..c70babb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,8 @@ set(exe_name toxic) add_executable(${exe_name} main.c - prompt.c) + prompt.c + friendlist.c) target_link_libraries(${exe_name} curses) diff --git a/friendlist.c b/friendlist.c new file mode 100644 index 0000000..f8b8c84 --- /dev/null +++ b/friendlist.c @@ -0,0 +1,125 @@ +/* + * Toxic -- Tox Curses Client + */ + +#include +#include +#include +#include + +#include "../../core/Messenger.h" +#include "../../core/network.h" + +#include "windows.h" + +#define MAX_FRIENDS_NUM 100 + +typedef struct { + uint8_t name[MAX_NAME_LENGTH]; + uint8_t status[MAX_USERSTATUS_LENGTH]; + int num; + +} friend_t; + +static friend_t friends[MAX_FRIENDS_NUM]; +static int num_friends = 0; + + +void fix_name(uint8_t* name) { + + // Remove all non alphanumeric characters. + uint8_t* p = name; + uint8_t* q = name; + + while(*p != 0) { + if(isalnum(*p)) { + *q++ = *p; + } + + p++; + } + + *q = 0; +} + +int friendlist_nickchange(int num, uint8_t* str, uint16_t len) { + + if(len >= MAX_NAME_LENGTH || num >= num_friends) + return -1; + + memcpy((char*) &friends[num].name, (char*) str, len); + friends[num].name[len] = 0; + fix_name(friends[num].name); + + return 0; +} + +int friendlist_statuschange(int num, uint8_t* str, uint16_t len) { + + if(len >= MAX_USERSTATUS_LENGTH || num >= num_friends) + return -1; + + memcpy((char*) &friends[num].status, (char*) str, len); + friends[num].status[len] = 0; + fix_name(friends[num].status); + + return 0; +} + +int friendlist_addfriend(int num) { + + if(num_friends == MAX_FRIENDS_NUM) + return -1; + + friends[num_friends].num = num; + getname(num, friends[num_friends].name); + strcpy((char*) friends[num_friends].name, "unknown"); + strcpy((char*) friends[num_friends].status, "unknown"); + + num_friends++; + return 0; +} + +static void friendlist_onKey(ToxWindow* self, int key) { + +} + +static void friendlist_onDraw(ToxWindow* self) { + size_t i; + + wclear(self->window); + + if(num_friends == 0) { + wprintw(self->window, "Empty. Add some friends! :-)\n"); + } + + wprintw(self->window, "\n"); + + for(i=0; iwindow, "[%d] ", friends[i].num); + + attron(A_BOLD); + wprintw(self->window, "%s ", friends[i].name); + attroff(A_BOLD); + + wprintw(self->window, "(%s)\n", friends[i].status); + } + + wrefresh(self->window); +} + +static void friendlist_onInit(ToxWindow* self) { + +} + + +ToxWindow new_friendlist() { + ToxWindow ret; + + ret.onKey = &friendlist_onKey; + ret.onDraw = &friendlist_onDraw; + ret.onInit = &friendlist_onInit; + strcpy(ret.title, "[friends]"); + + return ret; +} diff --git a/main.c b/main.c index 0aad677..e1d1ebd 100644 --- a/main.c +++ b/main.c @@ -14,6 +14,12 @@ #include "windows.h" extern ToxWindow new_prompt(); +extern ToxWindow new_friendlist(); + +extern int friendlist_addfriend(int num); +extern int friendlist_nickchange(int num, uint8_t* str, uint16_t len); +extern int friendlist_statuschange(int num, uint8_t* str, uint16_t len); + extern int add_req(uint8_t* public_key); // XXX #define TOXWINDOWS_MAX_NUM 32 @@ -35,11 +41,19 @@ void on_message(int friendnumber, uint8_t* string, uint16_t length) { } void on_nickchange(int friendnumber, uint8_t* string, uint16_t length) { - wprintw(prompt->window, "\n(nick) %d: %s!\n", friendnumber, string); + wprintw(prompt->window, "\n(nickchange) %d: %s!\n", friendnumber, string); + + friendlist_nickchange(friendnumber, string, length); } void on_statuschange(int friendnumber, uint8_t* string, uint16_t length) { - wprintw(prompt->window, "\n(status) %d: %s!\n", friendnumber, string); + wprintw(prompt->window, "\n(statuschange) %d: %s!\n", friendnumber, string); + + friendlist_statuschange(friendnumber, string, length); +} + +void on_friendadded(int friendnumber) { + friendlist_addfriend(friendnumber); } // CALLBACKS END @@ -95,7 +109,7 @@ static void init_windows() { w_num = 0; w_active = 0; - if(add_window(new_prompt()) == -1) { + if(add_window(new_prompt()) == -1 || add_window(new_friendlist()) == -1) { fprintf(stderr, "add_window() failed.\n"); endwin(); @@ -134,14 +148,18 @@ static void load_data() { if(buf == NULL) { fprintf(stderr, "malloc() failed.\n"); + fclose(fd); + endwin(); exit(1); } if(fread(buf, len, 1, fd) != 1){ fprintf(stderr, "fread() failed.\n"); + free(buf); fclose(fd); + endwin(); exit(1); } @@ -153,6 +171,7 @@ static void load_data() { if(buf == NULL) { fprintf(stderr, "malloc() failed.\n"); + endwin(); exit(1); } @@ -161,14 +180,18 @@ static void load_data() { fd = fopen("data", "w"); if(fd == NULL) { fprintf(stderr, "fopen() failed.\n"); + free(buf); + endwin(); exit(1); } if(fwrite(buf, len, 1, fd) != 1){ fprintf(stderr, "fwrite() failed.\n"); + free(buf); fclose(fd); + endwin(); exit(1); } } @@ -186,12 +209,16 @@ static void draw_bar() { move(LINES - 1, 0); + attron(COLOR_PAIR(3) | A_BOLD); + printw(" TOXIC 1.0 |"); + attroff(COLOR_PAIR(3) | A_BOLD); + for(i=0; iwindow); a->onDraw(a); draw_bar(); + // Handle input. ch = getch(); - if(ch != ERR) { + if(ch == '\t') { + w_active = (w_active + 1) % w_num; + } + else if(ch != ERR) { a->onKey(a, ch); } diff --git a/prompt.c b/prompt.c index 4a59cc7..22d9eb9 100644 --- a/prompt.c +++ b/prompt.c @@ -15,6 +15,8 @@ uint8_t pending_requests[256][CLIENT_ID_SIZE]; // XXX uint8_t num_requests=0; // XXX +extern void on_friendadded(int friendnumber); + // XXX: int add_req(uint8_t* public_key) { memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE); @@ -40,7 +42,6 @@ static int prompt_buf_pos=0; static void execute(ToxWindow* self, char* cmd) { - // quit/exit: Exit program. if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit")) { endwin(); exit(0); @@ -53,33 +54,32 @@ static void execute(ToxWindow* self, char* cmd) { ip = strchr(cmd, ' '); if(ip == NULL) { + wprintw(self->window, "Invalid syntax.\n"); return; } - ip++; port = strchr(ip, ' '); if(port == NULL) { + wprintw(self->window, "Invalid syntax.\n"); return; } - port[0] = 0; port++; key = strchr(port, ' '); if(key == NULL) { + wprintw(self->window, "Invalid syntax.\n"); return; } - key[0] = 0; key++; if(atoi(port) == 0) { + wprintw(self->window, "Invalid syntax.\n"); return; } - wprintw(self->window, "ip=%s, port=%s, key=%s\n", ip, port, key); - dht.port = htons(atoi(port)); int resolved_address = resolve_addr(ip); @@ -91,38 +91,62 @@ static void execute(ToxWindow* self, char* cmd) { DHT_bootstrap(dht, hex_string_to_bin(key)); } else if(!strncmp(cmd, "add ", strlen("add "))) { + uint8_t id_bin[32]; + size_t i; + char xx[3]; + uint32_t x; + char* id; char* msg; int num; id = strchr(cmd, ' '); - if(id == NULL) { + wprintw(self->window, "Invalid syntax.\n"); return; } - id++; msg = strchr(id, ' '); - if(msg == NULL) { + if(msg != NULL) { + msg[0] = 0; + msg++; + } + else msg = ""; + + if(strlen(id) != 2*32) { + wprintw(self->window, "Invalid ID length.\n"); return; } - msg[0] = 0; - msg++; + for(i=0; i<32; i++) { + xx[0] = id[2*i]; + xx[1] = id[2*i+1]; + xx[2] = '\0'; + + if(sscanf(xx, "%02x", &x) != 1) { + wprintw(self->window, "Invalid ID.\n"); + return; + } + + id_bin[i] = x; + } + + num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); - num = m_addfriend((uint8_t*) id, (uint8_t*) msg, strlen(msg)+1); wprintw(self->window, "Friend added as %d.\n", num); + on_friendadded(num); } else if(!strncmp(cmd, "status ", strlen("status "))) { char* msg; msg = strchr(cmd, ' '); if(msg == NULL) { + wprintw(self->window, "Invalid syntax.\n"); return; } - msg++; + m_set_userstatus((uint8_t*) msg, strlen(msg)+1); wprintw(self->window, "Status set to: %s.\n", msg); } @@ -133,33 +157,22 @@ static void execute(ToxWindow* self, char* cmd) { if(nick == NULL) { return; } - nick++; + setname((uint8_t*) nick, strlen(nick)+1); wprintw(self->window, "Nickname set to: %s.\n", nick); } else if(!strcmp(cmd, "myid")) { - // XXX: Clean this up - char idstring0[200]; - char idstring1[32][5]; - char idstring2[32][5]; - uint32_t i; + char id[32*2 + 1] = {0}; + size_t i; - for(i = 0; i < 32; i++) { - if(self_public_key[i] < 16) - strcpy(idstring1[i], "0"); - else - strcpy(idstring1[i], ""); - - sprintf(idstring2[i], "%hhX", self_public_key[i]); + for(i=0; i<32; i++) { + char xx[3]; + snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); + strcat(id, xx); } - for (i=0; i<32; i++) { - strcat(idstring0, idstring1[i]); - strcat(idstring0, idstring2[i]); - } - - wprintw(self->window, "%s\n", idstring0); + wprintw(self->window, "%s\n", id); } else if(!strncmp(cmd, "accept ", strlen("accept "))) { char* id; @@ -167,17 +180,26 @@ static void execute(ToxWindow* self, char* cmd) { id = strchr(cmd, ' '); if(id == NULL) { + wprintw(self->window, "Invalid syntax.\n"); return; } id++; - + num = atoi(id); if(num >= num_requests) { + wprintw(self->window, "Invalid syntax.\n"); return; } num = m_addfriend_norequest(pending_requests[num]); - wprintw(self->window, "Friend accepted as: %d.\n", num); + + if(num == -1) { + wprintw(self->window, "Failed to add friend.\n"); + } + else { + wprintw(self->window, "Friend accepted as: %d.\n", num); + on_friendadded(num); + } } else if(!strncmp(cmd, "msg ", strlen("msg "))) { char* id; @@ -186,16 +208,16 @@ static void execute(ToxWindow* self, char* cmd) { id = strchr(cmd, ' '); if(id == NULL) { + wprintw(self->window, "Invalid syntax.\n"); return; } - id++; msg = strchr(id, ' '); if(msg == NULL) { + wprintw(self->window, "Invalid syntax.\n"); return; } - msg[0] = 0; msg++; @@ -206,6 +228,9 @@ static void execute(ToxWindow* self, char* cmd) { wprintw(self->window, "Message successfully sent.\n"); } } + else { + wprintw(self->window, "Invalid syntax.\n"); + } } static void prompt_onKey(ToxWindow* self, int key) { @@ -242,9 +267,6 @@ static void prompt_onKey(ToxWindow* self, int key) { static void prompt_onDraw(ToxWindow* self) { int x, y; - mvwin(self->window,0,0); - wresize(self->window, LINES-2, COLS); - getyx(self->window, y, x); (void) x; @@ -265,11 +287,18 @@ static void print_usage(ToxWindow* self) { wprintw(self->window, " connect : Connect to DHT server\n"); wprintw(self->window, " add : Add friend\n"); + wprintw(self->window, " msg : Send message\n"); wprintw(self->window, " status : Set your status\n"); wprintw(self->window, " nick : Set your nickname\n"); wprintw(self->window, " accept : Accept friend request\n"); wprintw(self->window, " myid : Print your ID\n"); wprintw(self->window, " quit/exit : Exit program\n"); + + + wattron(self->window, A_BOLD); + wprintw(self->window, "Use the TAB key to navigate through the tabs.\n"); + wattroff(self->window, A_BOLD); + wattroff(self->window, COLOR_PAIR(2)); } From 3f1729706458515ca0ef786f91b3cbf5cf5fa721 Mon Sep 17 00:00:00 2001 From: Marco Hinz Date: Wed, 31 Jul 2013 10:36:02 +0200 Subject: [PATCH 005/172] Fix space/tab indentation --- prompt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prompt.c b/prompt.c index 22d9eb9..0cd1073 100644 --- a/prompt.c +++ b/prompt.c @@ -125,8 +125,8 @@ static void execute(ToxWindow* self, char* cmd) { xx[2] = '\0'; if(sscanf(xx, "%02x", &x) != 1) { - wprintw(self->window, "Invalid ID.\n"); - return; + wprintw(self->window, "Invalid ID.\n"); + return; } id_bin[i] = x; From 7290527cdc6f8c17f89a47c73b3fd97679103929 Mon Sep 17 00:00:00 2001 From: plutooo Date: Wed, 31 Jul 2013 10:20:03 -0700 Subject: [PATCH 006/172] Added chat windows, and some clean up. --- CMakeLists.txt | 3 +- chat.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++ friendlist.c | 48 +++++++++++++++--- main.c | 45 ++++++++++++++--- prompt.c | 4 +- windows.h | 6 +++ 6 files changed, 222 insertions(+), 18 deletions(-) create mode 100644 chat.c diff --git a/CMakeLists.txt b/CMakeLists.txt index c70babb..f30d8e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,8 @@ set(exe_name toxic) add_executable(${exe_name} main.c prompt.c - friendlist.c) + friendlist.c + chat.c) target_link_libraries(${exe_name} curses) diff --git a/chat.c b/chat.c new file mode 100644 index 0000000..53cf331 --- /dev/null +++ b/chat.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include + +#include "../../core/Messenger.h" +#include "../../core/network.h" + +#include "windows.h" + +typedef struct { + int friendnum; + + char line[256]; + size_t pos; + + WINDOW* history; + WINDOW* linewin; + +} ChatContext; + +extern void fix_name(uint8_t* name); + + +static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) { + ChatContext* ctx = (ChatContext*) self->x; + uint8_t nick[MAX_NAME_LENGTH] = {0}; + + if(ctx->friendnum != num) + return; + + getname(num, (uint8_t*) &nick); + + msg[len-1] = '\0'; + nick[MAX_NAME_LENGTH-1] = '\0'; + + fix_name(msg); + fix_name(nick); + + wprintw(ctx->history, "%s: %s\n", nick, msg); +} + +static void chat_onNickChange(ToxWindow* self, int num, uint8_t* nick, uint16_t len) { + ChatContext* ctx = (ChatContext*) self->x; + + if(ctx->friendnum != num) + return; + + nick[len-1] = '\0'; + fix_name(nick); + + wattron(ctx->history, COLOR_PAIR(3)); + wprintw(ctx->history, " * Your partner changed nick to '%s'\n", nick); + wattroff(ctx->history, COLOR_PAIR(3)); +} + +static void chat_onStatusChange(ToxWindow* self, int num, uint8_t* status, uint16_t len) { + +} + +static void chat_onKey(ToxWindow* self, int key) { + ChatContext* ctx = (ChatContext*) self->x; + + if(isprint(key)) { + + if(ctx->pos != sizeof(ctx->line)-1) { + ctx->line[ctx->pos++] = key; + ctx->line[ctx->pos] = '\0'; + } + } + else if(key == '\n') { + wprintw(ctx->history, "you: %s\n", ctx->line); + + if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) { + wprintw(ctx->history, " * Failed to send message.\n"); + } + + ctx->line[0] = '\0'; + ctx->pos = 0; + } +} + +static void chat_onDraw(ToxWindow* self) { + int x, y; + ChatContext* ctx = (ChatContext*) self->x; + + getmaxyx(self->window, y, x); + + (void) x; + if(y < 3) + return; + + wclear(ctx->linewin); + mvwhline(ctx->linewin, 0, 0, '_', COLS); + mvwprintw(ctx->linewin, 1, 0, "%s\n", ctx->line); + + wrefresh(self->window); +} + +static void chat_onInit(ToxWindow* self) { + int x, y; + ChatContext* ctx = (ChatContext*) self->x; + + getmaxyx(self->window, y, x); + + ctx->history = subwin(self->window, y - 4, x, 0, 0); + wprintw(ctx->history, "Here goes chat\n"); + scrollok(ctx->history, 1); + + ctx->linewin = subwin(self->window, 2, x, y - 3, 0); +} + +ToxWindow new_chat(int friendnum) { + ToxWindow ret; + + memset(&ret, 0, sizeof(ret)); + + ret.onKey = &chat_onKey; + ret.onDraw = &chat_onDraw; + ret.onInit = &chat_onInit; + ret.onMessage = &chat_onMessage; + ret.onNickChange = &chat_onNickChange; + ret.onStatusChange = &chat_onStatusChange; + + snprintf(ret.title, sizeof(ret.title), "[chat %d]", friendnum); + + ChatContext* x = calloc(1, sizeof(ChatContext)); + x->friendnum = friendnum; + + ret.x = (void*) x; + + return ret; +} diff --git a/friendlist.c b/friendlist.c index f8b8c84..629adaf 100644 --- a/friendlist.c +++ b/friendlist.c @@ -12,6 +12,10 @@ #include "windows.h" +extern int add_window(ToxWindow w); +extern int focus_window(int num); +extern ToxWindow new_chat(int friendnum); + #define MAX_FRIENDS_NUM 100 typedef struct { @@ -23,6 +27,7 @@ typedef struct { static friend_t friends[MAX_FRIENDS_NUM]; static int num_friends = 0; +static int num_selected = 0; void fix_name(uint8_t* name) { @@ -42,31 +47,31 @@ void fix_name(uint8_t* name) { *q = 0; } -int friendlist_nickchange(int num, uint8_t* str, uint16_t len) { +void friendlist_onNickChange(ToxWindow* self, int num, uint8_t* str, uint16_t len) { if(len >= MAX_NAME_LENGTH || num >= num_friends) - return -1; + return; memcpy((char*) &friends[num].name, (char*) str, len); friends[num].name[len] = 0; fix_name(friends[num].name); - return 0; + return; } -int friendlist_statuschange(int num, uint8_t* str, uint16_t len) { +void friendlist_onStatusChange(ToxWindow* self, int num, uint8_t* str, uint16_t len) { if(len >= MAX_USERSTATUS_LENGTH || num >= num_friends) - return -1; + return; memcpy((char*) &friends[num].status, (char*) str, len); friends[num].status[len] = 0; fix_name(friends[num].status); - return 0; + return; } -int friendlist_addfriend(int num) { +int friendlist_onFriendAdded(int num) { if(num_friends == MAX_FRIENDS_NUM) return -1; @@ -82,6 +87,17 @@ int friendlist_addfriend(int num) { static void friendlist_onKey(ToxWindow* self, int key) { + if(key == KEY_UP) { + if(num_selected != 0) + num_selected--; + } + else if(key == KEY_DOWN) { + if(num_friends != 0) + num_selected = (num_selected+1) % num_friends; + } + else if(key == '\n') { + focus_window(add_window(new_chat(num_selected))); + } } static void friendlist_onDraw(ToxWindow* self) { @@ -92,11 +108,23 @@ static void friendlist_onDraw(ToxWindow* self) { if(num_friends == 0) { wprintw(self->window, "Empty. Add some friends! :-)\n"); } + else { + wattron(self->window, COLOR_PAIR(2) | A_BOLD); + wprintw(self->window, "Friend list:\n"); + wattroff(self->window, A_BOLD); + + wprintw(self->window, " ENTER: start a chat\n"); + wprintw(self->window, " UP/DOWN: navigate list\n"); + wattroff(self->window, COLOR_PAIR(2)); + } wprintw(self->window, "\n"); for(i=0; iwindow, "[%d] ", friends[i].num); + + if(i == num_selected) wattron(self->window, COLOR_PAIR(3)); + wprintw(self->window, " [%d] ", friends[i].num); + if(i == num_selected) wattroff(self->window, COLOR_PAIR(3)); attron(A_BOLD); wprintw(self->window, "%s ", friends[i].name); @@ -116,9 +144,13 @@ static void friendlist_onInit(ToxWindow* self) { ToxWindow new_friendlist() { ToxWindow ret; + memset(&ret, 0, sizeof(ret)); + ret.onKey = &friendlist_onKey; ret.onDraw = &friendlist_onDraw; ret.onInit = &friendlist_onInit; + ret.onNickChange = &friendlist_onNickChange; + ret.onStatusChange = &friendlist_onStatusChange; strcpy(ret.title, "[friends]"); return ret; diff --git a/main.c b/main.c index e1d1ebd..1c095c5 100644 --- a/main.c +++ b/main.c @@ -16,9 +16,7 @@ extern ToxWindow new_prompt(); extern ToxWindow new_friendlist(); -extern int friendlist_addfriend(int num); -extern int friendlist_nickchange(int num, uint8_t* str, uint16_t len); -extern int friendlist_statuschange(int num, uint8_t* str, uint16_t len); +extern int friendlist_onFriendAdded(int num); extern int add_req(uint8_t* public_key); // XXX @@ -31,29 +29,52 @@ static ToxWindow* prompt; // CALLBACKS START void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) { + size_t i; int n = add_req(public_key); wprintw(prompt->window, "\nFriend request.\nUse \"accept %d\" to accept it.\n", n); + + for(i=0; iwindow, "\n(message) %d: %s!\n", friendnumber, string); + + for(i=0; iwindow, "\n(nickchange) %d: %s!\n", friendnumber, string); - friendlist_nickchange(friendnumber, string, length); + for(i=0; iwindow, "\n(statuschange) %d: %s!\n", friendnumber, string); - friendlist_statuschange(friendnumber, string, length); + for(i=0; i= w_num || num < 0) + return -1; + + w_active = num; + return 0; } static void init_windows() { diff --git a/prompt.c b/prompt.c index 22d9eb9..52e9bde 100644 --- a/prompt.c +++ b/prompt.c @@ -221,7 +221,7 @@ static void execute(ToxWindow* self, char* cmd) { msg[0] = 0; msg++; - if(m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) != 1) { + if(m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) < 0) { wprintw(self->window, "Error occurred while sending message.\n"); } else { @@ -312,6 +312,8 @@ static void prompt_onInit(ToxWindow* self) { ToxWindow new_prompt() { ToxWindow ret; + memset(&ret, 0, sizeof(ret)); + ret.onKey = &prompt_onKey; ret.onDraw = &prompt_onDraw; ret.onInit = &prompt_onInit; diff --git a/windows.h b/windows.h index 2e082ca..480fd65 100644 --- a/windows.h +++ b/windows.h @@ -4,7 +4,13 @@ struct ToxWindow_ { void(*onKey)(ToxWindow*, int); void(*onDraw)(ToxWindow*); void(*onInit)(ToxWindow*); + void(*onFriendRequest)(ToxWindow*, uint8_t*, uint8_t*, uint16_t); + void(*onMessage)(ToxWindow*, int, uint8_t*, uint16_t); + void(*onNickChange)(ToxWindow*, int, uint8_t*, uint16_t); + void(*onStatusChange)(ToxWindow*, int, uint8_t*, uint16_t); char title[256]; + void* x; + WINDOW* window; }; From 9559e37cfbb0d2763a27c2a576e4f2c45b45e827 Mon Sep 17 00:00:00 2001 From: plutooo Date: Wed, 31 Jul 2013 11:20:16 -0700 Subject: [PATCH 007/172] toxic: Made everything 1000x more userfriendly. --- chat.c | 27 ++++++++++++++++++++++++--- friendlist.c | 37 +++++++++++++++++++++++-------------- main.c | 25 ++++++++++++++++++++++--- prompt.c | 7 +++---- windows.h | 7 +++++++ 5 files changed, 79 insertions(+), 24 deletions(-) diff --git a/chat.c b/chat.c index 53cf331..da9ad02 100644 --- a/chat.c +++ b/chat.c @@ -1,3 +1,7 @@ +/* + * Toxic -- Tox Curses Client + */ + #include #include #include @@ -38,7 +42,13 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) fix_name(msg); fix_name(nick); - wprintw(ctx->history, "%s: %s\n", nick, msg); + wattron(ctx->history, COLOR_PAIR(4)); + wprintw(ctx->history, "%s: ", nick); + wattroff(ctx->history, COLOR_PAIR(4)); + + wprintw(ctx->history, "%s\n", msg); + + self->blink = true; } static void chat_onNickChange(ToxWindow* self, int num, uint8_t* nick, uint16_t len) { @@ -70,15 +80,27 @@ static void chat_onKey(ToxWindow* self, int key) { } } else if(key == '\n') { - wprintw(ctx->history, "you: %s\n", ctx->line); + wattron(ctx->history, COLOR_PAIR(1)); + wprintw(ctx->history, "you: ", ctx->line); + wattroff(ctx->history, COLOR_PAIR(1)); + + wprintw(ctx->history, "%s\n", ctx->line); if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) { + wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Failed to send message.\n"); + wattroff(ctx->history, COLOR_PAIR(3)); } ctx->line[0] = '\0'; ctx->pos = 0; } + else if(key == 0x107) { + if(ctx->pos != 0) { + ctx->line[--ctx->pos] = '\0'; + } + } + } static void chat_onDraw(ToxWindow* self) { @@ -105,7 +127,6 @@ static void chat_onInit(ToxWindow* self) { getmaxyx(self->window, y, x); ctx->history = subwin(self->window, y - 4, x, 0, 0); - wprintw(ctx->history, "Here goes chat\n"); scrollok(ctx->history, 1); ctx->linewin = subwin(self->window, 2, x, y - 3, 0); diff --git a/friendlist.c b/friendlist.c index 629adaf..f9a413f 100644 --- a/friendlist.c +++ b/friendlist.c @@ -22,7 +22,7 @@ typedef struct { uint8_t name[MAX_NAME_LENGTH]; uint8_t status[MAX_USERSTATUS_LENGTH]; int num; - + int chatwin; } friend_t; static friend_t friends[MAX_FRIENDS_NUM]; @@ -37,7 +37,7 @@ void fix_name(uint8_t* name) { uint8_t* q = name; while(*p != 0) { - if(isalnum(*p)) { + if(isprint(*p)) { *q++ = *p; } @@ -47,6 +47,16 @@ void fix_name(uint8_t* name) { *q = 0; } +void friendlist_onMessage(ToxWindow* self, int num, uint8_t* str, uint16_t len) { + + if(num >= num_friends) + return; + + if(friends[num].chatwin == -1) { + friends[num].chatwin = add_window(new_chat(num)); + } +} + void friendlist_onNickChange(ToxWindow* self, int num, uint8_t* str, uint16_t len) { if(len >= MAX_NAME_LENGTH || num >= num_friends) @@ -55,8 +65,6 @@ void friendlist_onNickChange(ToxWindow* self, int num, uint8_t* str, uint16_t le memcpy((char*) &friends[num].name, (char*) str, len); friends[num].name[len] = 0; fix_name(friends[num].name); - - return; } void friendlist_onStatusChange(ToxWindow* self, int num, uint8_t* str, uint16_t len) { @@ -67,8 +75,6 @@ void friendlist_onStatusChange(ToxWindow* self, int num, uint8_t* str, uint16_t memcpy((char*) &friends[num].status, (char*) str, len); friends[num].status[len] = 0; fix_name(friends[num].status); - - return; } int friendlist_onFriendAdded(int num) { @@ -80,6 +86,7 @@ int friendlist_onFriendAdded(int num) { getname(num, friends[num_friends].name); strcpy((char*) friends[num_friends].name, "unknown"); strcpy((char*) friends[num_friends].status, "unknown"); + friends[num_friends].chatwin = -1; num_friends++; return 0; @@ -96,7 +103,12 @@ static void friendlist_onKey(ToxWindow* self, int key) { num_selected = (num_selected+1) % num_friends; } else if(key == '\n') { - focus_window(add_window(new_chat(num_selected))); + + if(friends[num_selected].chatwin != -1) + return; + + friends[num_selected].chatwin = add_window(new_chat(num_selected)); + focus_window(friends[num_selected].chatwin); } } @@ -110,12 +122,8 @@ static void friendlist_onDraw(ToxWindow* self) { } else { wattron(self->window, COLOR_PAIR(2) | A_BOLD); - wprintw(self->window, "Friend list:\n"); - wattroff(self->window, A_BOLD); - - wprintw(self->window, " ENTER: start a chat\n"); - wprintw(self->window, " UP/DOWN: navigate list\n"); - wattroff(self->window, COLOR_PAIR(2)); + wprintw(self->window, "Open chat with.. (up/down keys, enter)\n"); + wattroff(self->window, COLOR_PAIR(2) | A_BOLD); } wprintw(self->window, "\n"); @@ -123,7 +131,7 @@ static void friendlist_onDraw(ToxWindow* self) { for(i=0; iwindow, COLOR_PAIR(3)); - wprintw(self->window, " [%d] ", friends[i].num); + wprintw(self->window, " [#%d] ", friends[i].num); if(i == num_selected) wattroff(self->window, COLOR_PAIR(3)); attron(A_BOLD); @@ -149,6 +157,7 @@ ToxWindow new_friendlist() { ret.onKey = &friendlist_onKey; ret.onDraw = &friendlist_onDraw; ret.onInit = &friendlist_onInit; + ret.onMessage = &friendlist_onMessage; ret.onNickChange = &friendlist_onNickChange; ret.onStatusChange = &friendlist_onStatusChange; strcpy(ret.title, "[friends]"); diff --git a/main.c b/main.c index 1c095c5..fffc3f8 100644 --- a/main.c +++ b/main.c @@ -32,7 +32,14 @@ void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) { size_t i; int n = add_req(public_key); - wprintw(prompt->window, "\nFriend request.\nUse \"accept %d\" to accept it.\n", n); + wprintw(prompt->window, "\nFriend request from:\n"); + + for(i=0; i<32; i++) { + wprintw(prompt->window, "%02x", public_key[i] & 0xff); + } + wprintw(prompt->window, "\n"); + + wprintw(prompt->window, "Use \"accept %d\" to accept it.\n", n); for(i=0; iwindow); + a->blink = false; a->onDraw(a); draw_bar(); diff --git a/prompt.c b/prompt.c index 52e9bde..cd9ef21 100644 --- a/prompt.c +++ b/prompt.c @@ -42,7 +42,7 @@ static int prompt_buf_pos=0; static void execute(ToxWindow* self, char* cmd) { - if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit")) { + if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) { endwin(); exit(0); } @@ -282,12 +282,11 @@ static void prompt_onDraw(ToxWindow* self) { static void print_usage(ToxWindow* self) { wattron(self->window, COLOR_PAIR(2) | A_BOLD); - wprintw(self->window, "Usage:\n"); + wprintw(self->window, "Commands:\n"); wattroff(self->window, A_BOLD); wprintw(self->window, " connect : Connect to DHT server\n"); wprintw(self->window, " add : Add friend\n"); - wprintw(self->window, " msg : Send message\n"); wprintw(self->window, " status : Set your status\n"); wprintw(self->window, " nick : Set your nickname\n"); wprintw(self->window, " accept : Accept friend request\n"); @@ -296,7 +295,7 @@ static void print_usage(ToxWindow* self) { wattron(self->window, A_BOLD); - wprintw(self->window, "Use the TAB key to navigate through the tabs.\n"); + wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n"); wattroff(self->window, A_BOLD); wattroff(self->window, COLOR_PAIR(2)); diff --git a/windows.h b/windows.h index 480fd65..dde1430 100644 --- a/windows.h +++ b/windows.h @@ -1,3 +1,9 @@ +/* + * Toxic -- Tox Curses Client + */ + +#include + typedef struct ToxWindow_ ToxWindow; struct ToxWindow_ { @@ -11,6 +17,7 @@ struct ToxWindow_ { char title[256]; void* x; + bool blink; WINDOW* window; }; From 498ead286678d7460e70d77d3f1b749f00fc4c80 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 31 Jul 2013 15:22:43 -0400 Subject: [PATCH 008/172] Backspace key should now work on more terminals in toxic. --- chat.c | 2 +- prompt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chat.c b/chat.c index da9ad02..dceb1d7 100644 --- a/chat.c +++ b/chat.c @@ -95,7 +95,7 @@ static void chat_onKey(ToxWindow* self, int key) { ctx->line[0] = '\0'; ctx->pos = 0; } - else if(key == 0x107) { + else if(key == 0x107 || key == 0x8 || key == 0x7f) { if(ctx->pos != 0) { ctx->line[--ctx->pos] = '\0'; } diff --git a/prompt.c b/prompt.c index 62470a2..f1b6e68 100644 --- a/prompt.c +++ b/prompt.c @@ -256,7 +256,7 @@ static void prompt_onKey(ToxWindow* self, int key) { } // BACKSPACE key: Remove one character from line. - else if(key == 0x107) { + else if(key == 0x107 || key == 0x8 || key == 0x7f) { if(prompt_buf_pos != 0) { prompt_buf[--prompt_buf_pos] = 0; From 1b431e19da23fbf46f9da24d059ab57b2266787b Mon Sep 17 00:00:00 2001 From: NemDiggers Date: Wed, 31 Jul 2013 19:02:06 -0400 Subject: [PATCH 009/172] Remove period from status set It can make for awkward displays if you put a period in your status. --- prompt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prompt.c b/prompt.c index f1b6e68..b09b3d8 100644 --- a/prompt.c +++ b/prompt.c @@ -148,7 +148,7 @@ static void execute(ToxWindow* self, char* cmd) { msg++; m_set_userstatus((uint8_t*) msg, strlen(msg)+1); - wprintw(self->window, "Status set to: %s.\n", msg); + wprintw(self->window, "Status set to: %s\n", msg); } else if(!strncmp(cmd, "nick ", strlen("nick "))) { char* nick; From 2f302b36e03227298bcf90f09df42c93e652c7d8 Mon Sep 17 00:00:00 2001 From: NemDiggers Date: Wed, 31 Jul 2013 20:23:15 -0400 Subject: [PATCH 010/172] Add help command to Toxic --- prompt.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/prompt.c b/prompt.c index b09b3d8..e18bdff 100644 --- a/prompt.c +++ b/prompt.c @@ -137,6 +137,26 @@ static void execute(ToxWindow* self, char* cmd) { wprintw(self->window, "Friend added as %d.\n", num); on_friendadded(num); } + else if(!strcmp(cmd, "help")) { + wattron(self->window, COLOR_PAIR(2) | A_BOLD); + wprintw(self->window, "Commands:\n"); + wattroff(self->window, A_BOLD); + + wprintw(self->window, " connect : Connect to DHT server\n"); + wprintw(self->window, " add : Add friend\n"); + wprintw(self->window, " status : Set your status\n"); + wprintw(self->window, " nick : Set your nickname\n"); + wprintw(self->window, " accept : Accept friend request\n"); + wprintw(self->window, " myid : Print your ID\n"); + wprintw(self->window, " quit/exit : Exit program\n"); + + + wattron(self->window, A_BOLD); + wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n"); + wattroff(self->window, A_BOLD); + + wattroff(self->window, COLOR_PAIR(2)); + } else if(!strncmp(cmd, "status ", strlen("status "))) { char* msg; @@ -292,6 +312,7 @@ static void print_usage(ToxWindow* self) { wprintw(self->window, " accept : Accept friend request\n"); wprintw(self->window, " myid : Print your ID\n"); wprintw(self->window, " quit/exit : Exit program\n"); + wprintw(self->window, " help : Print this message again\n"); wattron(self->window, A_BOLD); From 2e0fa701ccec9f33034f1679c5cd6a61143e9775 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 31 Jul 2013 21:44:57 -0400 Subject: [PATCH 011/172] fixed friend add bugs --- prompt.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/prompt.c b/prompt.c index e18bdff..6970441 100644 --- a/prompt.c +++ b/prompt.c @@ -133,10 +133,26 @@ static void execute(ToxWindow* self, char* cmd) { } num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); - - wprintw(self->window, "Friend added as %d.\n", num); - on_friendadded(num); + switch (num) { + case -1: + wprintw(self->window, "Message is too long.\n"); + break; + case -2: + wprintw(self->window, "That appears to be your own ID.\n"); + break; + case -3: + wprintw(self->window, "Friend request already sent.\n"); + break; + case -4: + wprintw(self->window, "Invalid ID.\n"); + break; + default: + wprintw(self->window, "Friend added as %d.\n", num); + on_friendadded(num); + break; + } } + else if(!strcmp(cmd, "help")) { wattron(self->window, COLOR_PAIR(2) | A_BOLD); wprintw(self->window, "Commands:\n"); From f5ec15f11cc4d211911599d691aed8ece803af1a Mon Sep 17 00:00:00 2001 From: Spittie Date: Thu, 1 Aug 2013 06:32:54 +0200 Subject: [PATCH 012/172] Add nicknames to the chat list Change from [chat ] to [ ()] --- chat.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/chat.c b/chat.c index dceb1d7..854d381 100644 --- a/chat.c +++ b/chat.c @@ -60,6 +60,8 @@ static void chat_onNickChange(ToxWindow* self, int num, uint8_t* nick, uint16_t nick[len-1] = '\0'; fix_name(nick); + snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num); + wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Your partner changed nick to '%s'\n", nick); wattroff(ctx->history, COLOR_PAIR(3)); @@ -144,7 +146,11 @@ ToxWindow new_chat(int friendnum) { ret.onNickChange = &chat_onNickChange; ret.onStatusChange = &chat_onStatusChange; - snprintf(ret.title, sizeof(ret.title), "[chat %d]", friendnum); + uint8_t nick[MAX_NAME_LENGTH] = {0}; + getname(friendnum, (uint8_t*) &nick); + fix_name(nick); + + snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum); ChatContext* x = calloc(1, sizeof(ChatContext)); x->friendnum = friendnum; From 484575afdb02cf8b09488d373aefc2cb265dd80e Mon Sep 17 00:00:00 2001 From: clpr Date: Thu, 1 Aug 2013 12:03:01 +0100 Subject: [PATCH 013/172] Use print_usage for help command --- prompt.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/prompt.c b/prompt.c index e18bdff..3c4a27d 100644 --- a/prompt.c +++ b/prompt.c @@ -16,6 +16,7 @@ uint8_t pending_requests[256][CLIENT_ID_SIZE]; // XXX uint8_t num_requests=0; // XXX extern void on_friendadded(int friendnumber); +static void print_usage(ToxWindow* self); // XXX: int add_req(uint8_t* public_key) { @@ -138,24 +139,7 @@ static void execute(ToxWindow* self, char* cmd) { on_friendadded(num); } else if(!strcmp(cmd, "help")) { - wattron(self->window, COLOR_PAIR(2) | A_BOLD); - wprintw(self->window, "Commands:\n"); - wattroff(self->window, A_BOLD); - - wprintw(self->window, " connect : Connect to DHT server\n"); - wprintw(self->window, " add : Add friend\n"); - wprintw(self->window, " status : Set your status\n"); - wprintw(self->window, " nick : Set your nickname\n"); - wprintw(self->window, " accept : Accept friend request\n"); - wprintw(self->window, " myid : Print your ID\n"); - wprintw(self->window, " quit/exit : Exit program\n"); - - - wattron(self->window, A_BOLD); - wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n"); - wattroff(self->window, A_BOLD); - - wattroff(self->window, COLOR_PAIR(2)); + print_usage(self); } else if(!strncmp(cmd, "status ", strlen("status "))) { char* msg; From f96602d45c1ef5d1cfcd534b8265b9eb5015fa08 Mon Sep 17 00:00:00 2001 From: clpr Date: Thu, 1 Aug 2013 18:48:50 +0100 Subject: [PATCH 014/172] Add back-tab support for toxic. --- main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main.c b/main.c index fffc3f8..cdc6dc1 100644 --- a/main.c +++ b/main.c @@ -305,6 +305,9 @@ int main(int argc, char* argv[]) { if(ch == '\t') { w_active = (w_active + 1) % w_num; } + else if(ch == KEY_BTAB) { + w_active = (w_active + w_num - 1) % w_num; + } else if(ch != ERR) { a->onKey(a, ch); } From 3923114da4ef281c6e4e2115a7bc1dd938cad223 Mon Sep 17 00:00:00 2001 From: plutooo Date: Thu, 1 Aug 2013 11:52:13 -0700 Subject: [PATCH 015/172] core: getaddrinfo() lookup error handling --- prompt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prompt.c b/prompt.c index 3c4a27d..a3cf2d9 100644 --- a/prompt.c +++ b/prompt.c @@ -83,8 +83,8 @@ static void execute(ToxWindow* self, char* cmd) { dht.port = htons(atoi(port)); - int resolved_address = resolve_addr(ip); - if (resolved_address == -1) { + uint32_t resolved_address = resolve_addr(ip); + if (resolved_address == 0) { return; } From a77b4a962d14a1275f6c8014deda5d58e9ac51a5 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 1 Aug 2013 15:27:08 -0400 Subject: [PATCH 016/172] added error code for no message on friend add & updated nTox.c/nTox_win32.c --- prompt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/prompt.c b/prompt.c index 6970441..21c1f52 100644 --- a/prompt.c +++ b/prompt.c @@ -138,13 +138,15 @@ static void execute(ToxWindow* self, char* cmd) { wprintw(self->window, "Message is too long.\n"); break; case -2: + wprintw(self->window, "Please add a message to your request.\n"); + case -3: wprintw(self->window, "That appears to be your own ID.\n"); break; - case -3: + case -4: wprintw(self->window, "Friend request already sent.\n"); break; - case -4: - wprintw(self->window, "Invalid ID.\n"); + case -5: + wprintw(self->window, "[i] Undefined error when adding friend.\n"); break; default: wprintw(self->window, "Friend added as %d.\n", num); From 396d39f3a64991996103efc3dc7cdb143579a067 Mon Sep 17 00:00:00 2001 From: rlt3 Date: Thu, 1 Aug 2013 15:58:19 -0400 Subject: [PATCH 017/172] Trying to make Lossless UDP more readable with style changes --- toxic | Bin 0 -> 106344 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 toxic diff --git a/toxic b/toxic new file mode 100755 index 0000000000000000000000000000000000000000..1f90dcc6d544af478af52cbecb743cb6ce333d17 GIT binary patch literal 106344 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 literal 0 HcmV?d00001 From 594964d1058e87589df67bd2313c609fa0fb5fc5 Mon Sep 17 00:00:00 2001 From: rlt3 Date: Thu, 1 Aug 2013 16:11:36 -0400 Subject: [PATCH 018/172] Trimming some things down and re styling comments --- toxic | Bin 106344 -> 106344 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/toxic b/toxic index 1f90dcc6d544af478af52cbecb743cb6ce333d17..d71c394bfc8defa2f05a661134f51b11c199c887 100755 GIT binary patch delta 12798 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 KGKxrx`~L$v*d2@j delta 12797 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 Ml$2)_kj8fZ2Rf%Fz5oCK From 22cfcc75855b7df0b7445a0d0c725623ab6543fb Mon Sep 17 00:00:00 2001 From: rlt3 Date: Thu, 1 Aug 2013 17:03:06 -0400 Subject: [PATCH 019/172] removing unnecessary binary files --- toxic | Bin 106344 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 toxic diff --git a/toxic b/toxic deleted file mode 100755 index d71c394bfc8defa2f05a661134f51b11c199c887..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106344 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

?!*w`d z2BQn1f{}jU62;>UcU__Q!-muSia+VO<3JhxA8L5;TE)j2uDVX~NrndupKUmDy}Gv; z9!e`-YPcQ;2FRc1kQl$n&lR&>NPKTs%=0+J>BkihdhSms{;gr&T26kLXb8O)%ma0M!0=xr#`#uPr}!Vl=tOF8F%{kaX}H!f zhH`PQGaSZ%Li#$a%1K{o_zc4zHN4O;Wh_ZwZ}=z=G>hSMINsq`B>jEc+n3>uzic(dU;!+$Wm(C}Xk*BgG# z!zU=eF&I)AewX2WJ&Y+U!>ji2`-&GBUT%1i;qwjum*J%0D?N<8GV;6DaLVvH4?nPn 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 From c4f31e4646c7ffde767b062fa677b12531adbc33 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 2 Aug 2013 03:36:31 -0400 Subject: [PATCH 020/172] fixed cursor --- main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/main.c b/main.c index cdc6dc1..b014a79 100644 --- a/main.c +++ b/main.c @@ -280,6 +280,14 @@ void prepare_window(WINDOW* w) { wresize(w, LINES-2, COLS); } +/* Draws cursor relative to input */ +void position_cursor(WINDOW* w) +{ + int x, y; + getyx(w, y, x); + move(y, x); +} + int main(int argc, char* argv[]) { int ch; ToxWindow* a; @@ -299,6 +307,7 @@ int main(int argc, char* argv[]) { a->blink = false; a->onDraw(a); draw_bar(); + position_cursor(a->window); // Handle input. ch = getch(); From 8eaf96e7bbba81e43c9aa8ac3629815a666845c1 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 2 Aug 2013 04:58:15 -0400 Subject: [PATCH 021/172] remove cursor from friend and chat windows --- main.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/main.c b/main.c index b014a79..6ceab01 100644 --- a/main.c +++ b/main.c @@ -280,12 +280,24 @@ void prepare_window(WINDOW* w) { wresize(w, LINES-2, COLS); } -/* Draws cursor relative to input */ -void position_cursor(WINDOW* w) +/* + * Draws cursor relative to input on prompt window. + * Removes cursor on friends window and chat windows. + * + * TODO: Make it work for chat windows + */ +void position_cursor(WINDOW* w, char* title, ToxWindow* a) { - int x, y; - getyx(w, y, x); - move(y, x); + curs_set(1); + if (strcmp(title, "[prompt]") == 0) { // main/prompt window + int x, y; + getyx(w, y, x); + move(y, x); + } + else if (strcmp(title, "[friends]") == 0) // friends window + curs_set(0); + else // any other window (i.e chat) + curs_set(0); } int main(int argc, char* argv[]) { @@ -307,7 +319,7 @@ int main(int argc, char* argv[]) { a->blink = false; a->onDraw(a); draw_bar(); - position_cursor(a->window); + position_cursor(a->window, a->title, a); // Handle input. ch = getch(); From 64157963ec9bcb7a2aa71fbc109227bb15fb0cbf Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 2 Aug 2013 05:08:04 -0400 Subject: [PATCH 022/172] rm unused arg --- main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index 6ceab01..c596b70 100644 --- a/main.c +++ b/main.c @@ -286,7 +286,7 @@ void prepare_window(WINDOW* w) { * * TODO: Make it work for chat windows */ -void position_cursor(WINDOW* w, char* title, ToxWindow* a) +void position_cursor(WINDOW* w, char* title) { curs_set(1); if (strcmp(title, "[prompt]") == 0) { // main/prompt window @@ -319,7 +319,7 @@ int main(int argc, char* argv[]) { a->blink = false; a->onDraw(a); draw_bar(); - position_cursor(a->window, a->title, a); + position_cursor(a->window, a->title); // Handle input. ch = getch(); From 5aea1c8c151fec7deb98575906d0c45df97ace37 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 2 Aug 2013 03:36:31 -0400 Subject: [PATCH 023/172] fixed cursor --- main.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/main.c b/main.c index cdc6dc1..c596b70 100644 --- a/main.c +++ b/main.c @@ -280,6 +280,26 @@ void prepare_window(WINDOW* w) { wresize(w, LINES-2, COLS); } +/* + * Draws cursor relative to input on prompt window. + * Removes cursor on friends window and chat windows. + * + * TODO: Make it work for chat windows + */ +void position_cursor(WINDOW* w, char* title) +{ + curs_set(1); + if (strcmp(title, "[prompt]") == 0) { // main/prompt window + int x, y; + getyx(w, y, x); + move(y, x); + } + else if (strcmp(title, "[friends]") == 0) // friends window + curs_set(0); + else // any other window (i.e chat) + curs_set(0); +} + int main(int argc, char* argv[]) { int ch; ToxWindow* a; @@ -299,6 +319,7 @@ int main(int argc, char* argv[]) { a->blink = false; a->onDraw(a); draw_bar(); + position_cursor(a->window, a->title); // Handle input. ch = getch(); From cad5f6137255b4219850935ba6e1ffdafea295a8 Mon Sep 17 00:00:00 2001 From: rlt3 Date: Fri, 2 Aug 2013 13:42:30 -0400 Subject: [PATCH 024/172] changing OSX instructions in INSTALL.md to reflect how everything works --- data | Bin 0 -> 1992 bytes main.c | 18 ++++++++---------- toxic | Bin 0 -> 106344 bytes 3 files changed, 8 insertions(+), 10 deletions(-) create mode 100644 data create mode 100755 toxic diff --git a/data b/data new file mode 100644 index 0000000000000000000000000000000000000000..b6e1f6cccbc55c8e12b2b0162e44f25fe942048e GIT binary patch literal 1992 zcmds7_Md$1 tQj_%xceUHwS`Y2)Nl#;$x1oWZVHAvpz-S1JhQMeDjE2By2nfJ literal 0 HcmV?d00001 diff --git a/main.c b/main.c index cdc6dc1..9614d7f 100644 --- a/main.c +++ b/main.c @@ -282,7 +282,7 @@ void prepare_window(WINDOW* w) { int main(int argc, char* argv[]) { int ch; - ToxWindow* a; + ToxWindow* current_window; init_term(); init_tox(); @@ -294,22 +294,20 @@ int main(int argc, char* argv[]) { do_tox(); // Draw. - a = &windows[w_active]; - prepare_window(a->window); - a->blink = false; - a->onDraw(a); + current_window = &windows[w_active]; + prepare_window(current_window->window); + current_window->blink = false; + current_window->onDraw(current_window); draw_bar(); // Handle input. ch = getch(); if(ch == '\t') { w_active = (w_active + 1) % w_num; - } - else if(ch == KEY_BTAB) { + } else if(ch == KEY_BTAB) { w_active = (w_active + w_num - 1) % w_num; - } - else if(ch != ERR) { - a->onKey(a, ch); + } else if(ch != ERR) { + current_window->onKey(current_window, ch); } } diff --git a/toxic b/toxic new file mode 100755 index 0000000000000000000000000000000000000000..6bd0dd78e8dedaf822ee7d42d654f51208f4fe82 GIT binary patch literal 106344 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 literal 0 HcmV?d00001 From 47cc00762efdc1c37a07b363d4e29d1ebeee2597 Mon Sep 17 00:00:00 2001 From: rlt3 Date: Fri, 2 Aug 2013 13:43:54 -0400 Subject: [PATCH 025/172] removing useless files --- data | Bin 1992 -> 0 bytes toxic | Bin 106344 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 data delete mode 100755 toxic diff --git a/data b/data deleted file mode 100644 index b6e1f6cccbc55c8e12b2b0162e44f25fe942048e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1992 zcmds7_Md$1 tQj_%xceUHwS`Y2)Nl#;$x1oWZVHAvpz-S1JhQMeDjE2By2nfJ diff --git a/toxic b/toxic deleted file mode 100755 index 6bd0dd78e8dedaf822ee7d42d654f51208f4fe82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106344 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 From 3a0e85fc5f0f1431556adba90bcb059d89a5b663 Mon Sep 17 00:00:00 2001 From: rlt3 Date: Fri, 2 Aug 2013 14:01:34 -0400 Subject: [PATCH 026/172] reverting unneeded changes --- main.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/main.c b/main.c index 9614d7f..26325d9 100644 --- a/main.c +++ b/main.c @@ -282,7 +282,7 @@ void prepare_window(WINDOW* w) { int main(int argc, char* argv[]) { int ch; - ToxWindow* current_window; + ToxWindow* a; init_term(); init_tox(); @@ -294,20 +294,22 @@ int main(int argc, char* argv[]) { do_tox(); // Draw. - current_window = &windows[w_active]; - prepare_window(current_window->window); - current_window->blink = false; - current_window->onDraw(current_window); + a = &windows[w_active]; + prepare_window(a->window); + a->blink = false; + a->onDraw(a); draw_bar(); // Handle input. ch = getch(); if(ch == '\t') { w_active = (w_active + 1) % w_num; - } else if(ch == KEY_BTAB) { + } + else if(ch == KEY_BTAB) { w_active = (w_active + w_num - 1) % w_num; - } else if(ch != ERR) { - current_window->onKey(current_window, ch); + } + else if(ch != ERR) { + a->onKey(a, ch); } } From 84775df88811b8c376c75125409e89f76a671472 Mon Sep 17 00:00:00 2001 From: rlt3 Date: Fri, 2 Aug 2013 14:05:23 -0400 Subject: [PATCH 027/172] INSTALL.md should reflect how you build on OSX now. --- main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index 26325d9..cdc6dc1 100644 --- a/main.c +++ b/main.c @@ -304,10 +304,10 @@ int main(int argc, char* argv[]) { ch = getch(); if(ch == '\t') { w_active = (w_active + 1) % w_num; - } + } else if(ch == KEY_BTAB) { w_active = (w_active + w_num - 1) % w_num; - } + } else if(ch != ERR) { a->onKey(a, ch); } From 873736df5c9e29ff286fce86d4ad1193e94c9bc4 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Fri, 2 Aug 2013 16:44:32 -0700 Subject: [PATCH 028/172] Adds timestamp to toxic, fixes issue #217 --- chat.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/chat.c b/chat.c index 854d381..10837aa 100644 --- a/chat.c +++ b/chat.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "../../core/Messenger.h" #include "../../core/network.h" @@ -26,11 +27,15 @@ typedef struct { extern void fix_name(uint8_t* name); - static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) { ChatContext* ctx = (ChatContext*) self->x; uint8_t nick[MAX_NAME_LENGTH] = {0}; + time_t now; + time(&now); + struct tm * timeinfo; + timeinfo = localtime(&now); + if(ctx->friendnum != num) return; @@ -42,10 +47,21 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) fix_name(msg); fix_name(nick); + int inthour = timeinfo->tm_hour; + int intmin = timeinfo->tm_min; + char min[2]; + char hour[2]; + sprintf(hour,"%d",inthour); + sprintf(min,"%d",intmin); + + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history,"%s",hour); + wprintw(ctx->history,":%s ",min); + wattron(ctx->history, COLOR_PAIR(4)); + wprintw(ctx->history, "%s: ", now); wattron(ctx->history, COLOR_PAIR(4)); wprintw(ctx->history, "%s: ", nick); wattroff(ctx->history, COLOR_PAIR(4)); - wprintw(ctx->history, "%s\n", msg); self->blink = true; @@ -74,6 +90,11 @@ static void chat_onStatusChange(ToxWindow* self, int num, uint8_t* status, uint1 static void chat_onKey(ToxWindow* self, int key) { ChatContext* ctx = (ChatContext*) self->x; + time_t now; + time(&now); + struct tm * timeinfo; + timeinfo = localtime(&now); + if(isprint(key)) { if(ctx->pos != sizeof(ctx->line)-1) { @@ -82,6 +103,17 @@ static void chat_onKey(ToxWindow* self, int key) { } } else if(key == '\n') { + + int inthour = timeinfo->tm_hour; //Pretty bad, but it gets the job done + int intmin = timeinfo->tm_min; + char min[2]; + char hour[2]; + sprintf(hour,"%d",inthour); + sprintf(min,"%d",intmin); + + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history,"%s",hour); + wprintw(ctx->history,":%s ",min); wattron(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "you: ", ctx->line); wattroff(ctx->history, COLOR_PAIR(1)); From 6f331d6fcb273bd99a0e3fc0090c36e88d19e9ac Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Fri, 2 Aug 2013 17:14:47 -0700 Subject: [PATCH 029/172] Fixed a bug with the minutes only being 1 character long when less than 10 --- chat.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/chat.c b/chat.c index 10837aa..50aa81b 100644 --- a/chat.c +++ b/chat.c @@ -52,7 +52,12 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) char min[2]; char hour[2]; sprintf(hour,"%d",inthour); - sprintf(min,"%d",intmin); + if (intmin < 10) { + sprintf(min,"0%d",intmin); + } else { + sprintf(min,"%d",intmin); + } + wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history,"%s",hour); @@ -109,7 +114,11 @@ static void chat_onKey(ToxWindow* self, int key) { char min[2]; char hour[2]; sprintf(hour,"%d",inthour); - sprintf(min,"%d",intmin); + if (intmin < 10) { + sprintf(min,"0%d",intmin); + } else { + sprintf(min,"%d",intmin); + } wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history,"%s",hour); From 1b53b8ecc47546191f07fe876524471a7740fb44 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Fri, 2 Aug 2013 17:44:30 -0700 Subject: [PATCH 030/172] By popular demand, I made a patch to add seconds to the timestamp --- seconds.patch | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 seconds.patch diff --git a/seconds.patch b/seconds.patch new file mode 100644 index 0000000..d7ce33a --- /dev/null +++ b/seconds.patch @@ -0,0 +1,61 @@ +--- chat.c 2013-08-02 17:41:08.866583333 -0700 ++++ chat2.c 2013-08-02 17:38:13.672991322 -0700 +@@ -49,8 +49,10 @@ + + int inthour = timeinfo->tm_hour; + int intmin = timeinfo->tm_min; ++ int intsec = timeinfo->tm_sec; + char min[2]; + char hour[2]; ++ char sec[2]; + sprintf(hour,"%d",inthour); + if (intmin < 10) { + sprintf(min,"0%d",intmin); +@@ -58,10 +60,17 @@ + sprintf(min,"%d",intmin); + } + ++ if (intsec < 10) { ++ sprintf(sec,"0%d",intsec); ++ } else { ++ sprintf(sec,"%d",intsec); ++ } ++ + + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history,"%s",hour); +- wprintw(ctx->history,":%s ",min); ++ wprintw(ctx->history,":%s",min); ++ wprintw(ctx->history,":%s",sec); + wattron(ctx->history, COLOR_PAIR(4)); + wprintw(ctx->history, "%s: ", now); + wattron(ctx->history, COLOR_PAIR(4)); +@@ -111,8 +120,10 @@ + + int inthour = timeinfo->tm_hour; //Pretty bad, but it gets the job done + int intmin = timeinfo->tm_min; ++ int intsec = timeinfo ->tm_sec; + char min[2]; + char hour[2]; ++ char sec[2]; + sprintf(hour,"%d",inthour); + if (intmin < 10) { + sprintf(min,"0%d",intmin); +@@ -120,9 +131,16 @@ + sprintf(min,"%d",intmin); + } + ++ if (intsec < 10) { ++ sprintf(sec,"0%d",intsec); ++ } else { ++ sprintf(sec,"%d",intsec); ++ } ++ + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history,"%s",hour); +- wprintw(ctx->history,":%s ",min); ++ wprintw(ctx->history,":%s",min); ++ wprintw(ctx->history,":%s ",sec); + wattron(ctx->history, COLOR_PAIR(1)); + wprintw(ctx->history, "you: ", ctx->line); + wattroff(ctx->history, COLOR_PAIR(1)); From a938076f99a301a1604eceb4c0a58dec3902d903 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Fri, 2 Aug 2013 17:50:35 -0700 Subject: [PATCH 031/172] Moved PATCH.md to the toxic folder --- PATCH.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 PATCH.md diff --git a/PATCH.md b/PATCH.md new file mode 100644 index 0000000..4af250f --- /dev/null +++ b/PATCH.md @@ -0,0 +1,2 @@ +Seconds.patch adds support for seconds to the timestamp in toxic. +To use seconds.patch run patch < seconds.patch while in the directory testing/toxic From 53f7d9af0de35f9c713d5919131e1ac7dfa19d8d Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 2 Aug 2013 21:36:01 -0400 Subject: [PATCH 032/172] cursor done better, fixed for chat windows --- chat.c | 3 ++- friendlist.c | 1 + main.c | 23 +---------------------- prompt.c | 1 + 4 files changed, 5 insertions(+), 23 deletions(-) diff --git a/chat.c b/chat.c index 854d381..1bfd94f 100644 --- a/chat.c +++ b/chat.c @@ -106,6 +106,7 @@ static void chat_onKey(ToxWindow* self, int key) { } static void chat_onDraw(ToxWindow* self) { + curs_set(1); int x, y; ChatContext* ctx = (ChatContext*) self->x; @@ -117,7 +118,7 @@ static void chat_onDraw(ToxWindow* self) { wclear(ctx->linewin); mvwhline(ctx->linewin, 0, 0, '_', COLS); - mvwprintw(ctx->linewin, 1, 0, "%s\n", ctx->line); + mvwprintw(self->window, y-1, 0, "%s\n", ctx->line); wrefresh(self->window); } diff --git a/friendlist.c b/friendlist.c index f9a413f..b4b619a 100644 --- a/friendlist.c +++ b/friendlist.c @@ -113,6 +113,7 @@ static void friendlist_onKey(ToxWindow* self, int key) { } static void friendlist_onDraw(ToxWindow* self) { + curs_set(0); size_t i; wclear(self->window); diff --git a/main.c b/main.c index c596b70..bcfc487 100644 --- a/main.c +++ b/main.c @@ -280,26 +280,6 @@ void prepare_window(WINDOW* w) { wresize(w, LINES-2, COLS); } -/* - * Draws cursor relative to input on prompt window. - * Removes cursor on friends window and chat windows. - * - * TODO: Make it work for chat windows - */ -void position_cursor(WINDOW* w, char* title) -{ - curs_set(1); - if (strcmp(title, "[prompt]") == 0) { // main/prompt window - int x, y; - getyx(w, y, x); - move(y, x); - } - else if (strcmp(title, "[friends]") == 0) // friends window - curs_set(0); - else // any other window (i.e chat) - curs_set(0); -} - int main(int argc, char* argv[]) { int ch; ToxWindow* a; @@ -317,9 +297,8 @@ int main(int argc, char* argv[]) { a = &windows[w_active]; prepare_window(a->window); a->blink = false; - a->onDraw(a); draw_bar(); - position_cursor(a->window, a->title); + a->onDraw(a); // Handle input. ch = getch(); diff --git a/prompt.c b/prompt.c index b0f8381..484f590 100644 --- a/prompt.c +++ b/prompt.c @@ -287,6 +287,7 @@ static void prompt_onKey(ToxWindow* self, int key) { } static void prompt_onDraw(ToxWindow* self) { + curs_set(1); int x, y; getyx(self->window, y, x); From 19ed6a4beaeba0f394560b1feec2008657d711dd Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Fri, 2 Aug 2013 19:58:00 -0700 Subject: [PATCH 033/172] Removed the seconds patch, it breaks things --- PATCH.md | 2 -- seconds.patch | 61 --------------------------------------------------- 2 files changed, 63 deletions(-) delete mode 100644 PATCH.md delete mode 100644 seconds.patch diff --git a/PATCH.md b/PATCH.md deleted file mode 100644 index 4af250f..0000000 --- a/PATCH.md +++ /dev/null @@ -1,2 +0,0 @@ -Seconds.patch adds support for seconds to the timestamp in toxic. -To use seconds.patch run patch < seconds.patch while in the directory testing/toxic diff --git a/seconds.patch b/seconds.patch deleted file mode 100644 index d7ce33a..0000000 --- a/seconds.patch +++ /dev/null @@ -1,61 +0,0 @@ ---- chat.c 2013-08-02 17:41:08.866583333 -0700 -+++ chat2.c 2013-08-02 17:38:13.672991322 -0700 -@@ -49,8 +49,10 @@ - - int inthour = timeinfo->tm_hour; - int intmin = timeinfo->tm_min; -+ int intsec = timeinfo->tm_sec; - char min[2]; - char hour[2]; -+ char sec[2]; - sprintf(hour,"%d",inthour); - if (intmin < 10) { - sprintf(min,"0%d",intmin); -@@ -58,10 +60,17 @@ - sprintf(min,"%d",intmin); - } - -+ if (intsec < 10) { -+ sprintf(sec,"0%d",intsec); -+ } else { -+ sprintf(sec,"%d",intsec); -+ } -+ - - wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history,"%s",hour); -- wprintw(ctx->history,":%s ",min); -+ wprintw(ctx->history,":%s",min); -+ wprintw(ctx->history,":%s",sec); - wattron(ctx->history, COLOR_PAIR(4)); - wprintw(ctx->history, "%s: ", now); - wattron(ctx->history, COLOR_PAIR(4)); -@@ -111,8 +120,10 @@ - - int inthour = timeinfo->tm_hour; //Pretty bad, but it gets the job done - int intmin = timeinfo->tm_min; -+ int intsec = timeinfo ->tm_sec; - char min[2]; - char hour[2]; -+ char sec[2]; - sprintf(hour,"%d",inthour); - if (intmin < 10) { - sprintf(min,"0%d",intmin); -@@ -120,9 +131,16 @@ - sprintf(min,"%d",intmin); - } - -+ if (intsec < 10) { -+ sprintf(sec,"0%d",intsec); -+ } else { -+ sprintf(sec,"%d",intsec); -+ } -+ - wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history,"%s",hour); -- wprintw(ctx->history,":%s ",min); -+ wprintw(ctx->history,":%s",min); -+ wprintw(ctx->history,":%s ",sec); - wattron(ctx->history, COLOR_PAIR(1)); - wprintw(ctx->history, "you: ", ctx->line); - wattroff(ctx->history, COLOR_PAIR(1)); From bf4b71e61794a5ea2c492afcc0175db11d23c76d Mon Sep 17 00:00:00 2001 From: g Date: Sat, 3 Aug 2013 15:59:46 +0800 Subject: [PATCH 034/172] Added break Statement --- prompt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/prompt.c b/prompt.c index b0f8381..b248b63 100644 --- a/prompt.c +++ b/prompt.c @@ -140,6 +140,7 @@ static void execute(ToxWindow* self, char* cmd) { break; case -2: wprintw(self->window, "Please add a message to your request.\n"); + break; case -3: wprintw(self->window, "That appears to be your own ID.\n"); break; From 84aa9a9e3b7d6426f85689097d076999c05c8589 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sat, 3 Aug 2013 01:52:13 -0700 Subject: [PATCH 035/172] Merged a change from a pull request, added a break Merged from https://github.com/greato/ProjectTox-Core --- prompt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/prompt.c b/prompt.c index b0f8381..8536b94 100644 --- a/prompt.c +++ b/prompt.c @@ -141,6 +141,7 @@ static void execute(ToxWindow* self, char* cmd) { case -2: wprintw(self->window, "Please add a message to your request.\n"); case -3: + break; wprintw(self->window, "That appears to be your own ID.\n"); break; case -4: From 3e5b40c0db6a4f9ea54d1be27a03a4cb721e2736 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sat, 3 Aug 2013 01:55:07 -0700 Subject: [PATCH 036/172] Added a break from a pull request Merged a change from https://github.com/greato/ProjectTox-Core --- prompt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/prompt.c b/prompt.c index 484f590..e71f5f0 100644 --- a/prompt.c +++ b/prompt.c @@ -141,6 +141,7 @@ static void execute(ToxWindow* self, char* cmd) { case -2: wprintw(self->window, "Please add a message to your request.\n"); case -3: + break; wprintw(self->window, "That appears to be your own ID.\n"); break; case -4: From 77b7694c418c5770dfad4ed518ac19066ba980f5 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sat, 3 Aug 2013 03:59:27 -0700 Subject: [PATCH 037/172] Fixed a segfault when recieving text --- chat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/chat.c b/chat.c index 0e14a29..b835cf2 100644 --- a/chat.c +++ b/chat.c @@ -63,8 +63,6 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) wprintw(ctx->history,"%s",hour); wprintw(ctx->history,":%s ",min); wattron(ctx->history, COLOR_PAIR(4)); - wprintw(ctx->history, "%s: ", now); - wattron(ctx->history, COLOR_PAIR(4)); wprintw(ctx->history, "%s: ", nick); wattroff(ctx->history, COLOR_PAIR(4)); wprintw(ctx->history, "%s\n", msg); @@ -109,17 +107,19 @@ static void chat_onKey(ToxWindow* self, int key) { } else if(key == '\n') { + printf("Get times to int"); int inthour = timeinfo->tm_hour; //Pretty bad, but it gets the job done int intmin = timeinfo->tm_min; char min[2]; char hour[2]; + printf("Turn to varible"); sprintf(hour,"%d",inthour); if (intmin < 10) { sprintf(min,"0%d",intmin); } else { sprintf(min,"%d",intmin); } - + printf("Display"); wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history,"%s",hour); wprintw(ctx->history,":%s ",min); From c571696c46f45dfc3a60a2f10c67b370143b6484 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sat, 3 Aug 2013 04:10:47 -0700 Subject: [PATCH 038/172] Removed some useless code --- chat.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/chat.c b/chat.c index b835cf2..19f5c97 100644 --- a/chat.c +++ b/chat.c @@ -107,19 +107,16 @@ static void chat_onKey(ToxWindow* self, int key) { } else if(key == '\n') { - printf("Get times to int"); int inthour = timeinfo->tm_hour; //Pretty bad, but it gets the job done int intmin = timeinfo->tm_min; char min[2]; char hour[2]; - printf("Turn to varible"); sprintf(hour,"%d",inthour); if (intmin < 10) { sprintf(min,"0%d",intmin); } else { sprintf(min,"%d",intmin); } - printf("Display"); wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history,"%s",hour); wprintw(ctx->history,":%s ",min); From bbffe1b8a38fefa2fe9cde09156b057d9dc6b63a Mon Sep 17 00:00:00 2001 From: Michael Kress Date: Sat, 3 Aug 2013 16:00:48 +0200 Subject: [PATCH 039/172] fixed printing time stamp in toxic --- chat.c | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/chat.c b/chat.c index 19f5c97..ddf5923 100644 --- a/chat.c +++ b/chat.c @@ -47,21 +47,8 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) fix_name(msg); fix_name(nick); - int inthour = timeinfo->tm_hour; - int intmin = timeinfo->tm_min; - char min[2]; - char hour[2]; - sprintf(hour,"%d",inthour); - if (intmin < 10) { - sprintf(min,"0%d",intmin); - } else { - sprintf(min,"%d",intmin); - } - - wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history,"%s",hour); - wprintw(ctx->history,":%s ",min); + wprintw(ctx->history, "%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min); wattron(ctx->history, COLOR_PAIR(4)); wprintw(ctx->history, "%s: ", nick); wattroff(ctx->history, COLOR_PAIR(4)); @@ -106,24 +93,11 @@ static void chat_onKey(ToxWindow* self, int key) { } } else if(key == '\n') { - - int inthour = timeinfo->tm_hour; //Pretty bad, but it gets the job done - int intmin = timeinfo->tm_min; - char min[2]; - char hour[2]; - sprintf(hour,"%d",inthour); - if (intmin < 10) { - sprintf(min,"0%d",intmin); - } else { - sprintf(min,"%d",intmin); - } wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history,"%s",hour); - wprintw(ctx->history,":%s ",min); + wprintw(ctx->history, "%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min); wattron(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "you: ", ctx->line); wattroff(ctx->history, COLOR_PAIR(1)); - wprintw(ctx->history, "%s\n", ctx->line); if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) { @@ -140,7 +114,7 @@ static void chat_onKey(ToxWindow* self, int key) { ctx->line[--ctx->pos] = '\0'; } } - + } static void chat_onDraw(ToxWindow* self) { @@ -188,7 +162,7 @@ ToxWindow new_chat(int friendnum) { uint8_t nick[MAX_NAME_LENGTH] = {0}; getname(friendnum, (uint8_t*) &nick); fix_name(nick); - + snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum); ChatContext* x = calloc(1, sizeof(ChatContext)); From f3ee6207770f700cd9161a9bdad16a2366388af1 Mon Sep 17 00:00:00 2001 From: Michael Kress Date: Sat, 3 Aug 2013 16:26:23 +0200 Subject: [PATCH 040/172] added seconds to time stamp in toxic --- chat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chat.c b/chat.c index ddf5923..7cae1c0 100644 --- a/chat.c +++ b/chat.c @@ -48,7 +48,7 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) fix_name(nick); wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history, "%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min); + wprintw(ctx->history, "%02d:%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattron(ctx->history, COLOR_PAIR(4)); wprintw(ctx->history, "%s: ", nick); wattroff(ctx->history, COLOR_PAIR(4)); @@ -94,7 +94,7 @@ static void chat_onKey(ToxWindow* self, int key) { } else if(key == '\n') { wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history, "%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min); + wprintw(ctx->history, "%02d:%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattron(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "you: ", ctx->line); wattroff(ctx->history, COLOR_PAIR(1)); From 5e905ca12aeed24cbc602df3dbbfcdac2ca32e4d Mon Sep 17 00:00:00 2001 From: NemDiggers Date: Sat, 3 Aug 2013 11:53:51 -0400 Subject: [PATCH 041/172] People aren't that excited to send messages --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index bcfc487..391b0b3 100644 --- a/main.c +++ b/main.c @@ -50,7 +50,7 @@ void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) { void on_message(int friendnumber, uint8_t* string, uint16_t length) { size_t i; - wprintw(prompt->window, "\n(message) %d: %s!\n", friendnumber, string); + wprintw(prompt->window, "\n(message) %d: %s\n", friendnumber, string); for(i=0; i Date: Sat, 3 Aug 2013 11:51:40 -0700 Subject: [PATCH 042/172] Removed an early break --- prompt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/prompt.c b/prompt.c index e80bdab..1db6088 100644 --- a/prompt.c +++ b/prompt.c @@ -142,7 +142,6 @@ static void execute(ToxWindow* self, char* cmd) { wprintw(self->window, "Please add a message to your request.\n"); break; case -3: - break; wprintw(self->window, "That appears to be your own ID.\n"); break; case -4: From 25093fa76e46a688c445f519879512e1b39540f9 Mon Sep 17 00:00:00 2001 From: charmlesscoin Date: Sat, 3 Aug 2013 15:12:02 -0400 Subject: [PATCH 043/172] added the -f flag for toxic --- main.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index 391b0b3..001d338 100644 --- a/main.c +++ b/main.c @@ -170,12 +170,12 @@ static void do_tox() { doMessenger(); } -static void load_data() { +static void load_data(char *path) { FILE* fd; size_t len; uint8_t* buf; - if((fd = fopen("data", "r")) != NULL) { + if((fd = fopen(path, "r")) != NULL) { fseek(fd, 0, SEEK_END); len = ftell(fd); fseek(fd, 0, SEEK_SET); @@ -213,7 +213,7 @@ static void load_data() { Messenger_save(buf); - fd = fopen("data", "w"); + fd = fopen(path, "w"); if(fd == NULL) { fprintf(stderr, "fopen() failed.\n"); @@ -282,11 +282,25 @@ void prepare_window(WINDOW* w) { int main(int argc, char* argv[]) { int ch; + int i = 0; + char *filename = "data"; ToxWindow* a; + for(i = 0; i < argc; i++) { + if(argv[i][0] == '-') { + if(argv[i][1] == 'f') { + if(argv[i + 1] != NULL) + filename = argv[i + 1]; + else { + fputs("[!] you passed '-f' without giving an argument!\n", stderr); + } + } + } + } + init_term(); init_tox(); - load_data(); + load_data(filename); init_windows(); while(true) { From 68476fba64ab6a8a5d6e12a83a9b0cfaf9e05b4b Mon Sep 17 00:00:00 2001 From: charmlesscoin Date: Sat, 3 Aug 2013 16:12:02 -0400 Subject: [PATCH 044/172] added a proper error message for messing up the -f flag --- main.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 001d338..3b45a89 100644 --- a/main.c +++ b/main.c @@ -283,6 +283,7 @@ void prepare_window(WINDOW* w) { int main(int argc, char* argv[]) { int ch; int i = 0; + int f_flag = 0; char *filename = "data"; ToxWindow* a; @@ -292,7 +293,7 @@ int main(int argc, char* argv[]) { if(argv[i + 1] != NULL) filename = argv[i + 1]; else { - fputs("[!] you passed '-f' without giving an argument!\n", stderr); + f_flag = -1; } } } @@ -303,6 +304,14 @@ int main(int argc, char* argv[]) { load_data(filename); init_windows(); + if(f_flag == -1) { + attron(COLOR_PAIR(3) | A_BOLD); + wprintw(prompt->window, "You passed '-f' without giving an argument!\n" + "defaulting to 'data' for a keyfile...\n"); + attroff(COLOR_PAIR(3) | A_BOLD); + } + + while(true) { // Update tox. do_tox(); From 508c805983afd1a08ff3e303eead5d7fd137f3e0 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sat, 3 Aug 2013 17:13:44 -0400 Subject: [PATCH 045/172] added command to clear prompt screen --- prompt.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/prompt.c b/prompt.c index 1db6088..a47238a 100644 --- a/prompt.c +++ b/prompt.c @@ -251,20 +251,21 @@ static void execute(ToxWindow* self, char* cmd) { wprintw(self->window, "Message successfully sent.\n"); } } + + else if (!strncmp(cmd, "clear", strlen("clear"))) { + wclear(self->window); + } else { wprintw(self->window, "Invalid syntax.\n"); } } static void prompt_onKey(ToxWindow* self, int key) { - // PRINTABLE characters: Add to line. if(isprint(key)) { - if(prompt_buf_pos == (sizeof(prompt_buf) - 1)) { return; } - prompt_buf[prompt_buf_pos++] = key; prompt_buf[prompt_buf_pos] = 0; } @@ -273,14 +274,12 @@ static void prompt_onKey(ToxWindow* self, int key) { else if(key == '\n') { wprintw(self->window, "\n"); execute(self, prompt_buf); - prompt_buf_pos = 0; prompt_buf[0] = 0; } // BACKSPACE key: Remove one character from line. else if(key == 0x107 || key == 0x8 || key == 0x7f) { - if(prompt_buf_pos != 0) { prompt_buf[--prompt_buf_pos] = 0; } @@ -315,6 +314,7 @@ static void print_usage(ToxWindow* self) { wprintw(self->window, " nick : Set your nickname\n"); wprintw(self->window, " accept : Accept friend request\n"); wprintw(self->window, " myid : Print your ID\n"); + wprintw(self->window, " clear : Clear the screen\n"); wprintw(self->window, " quit/exit : Exit program\n"); wprintw(self->window, " help : Print this message again\n"); From 99410a510064d26d35344e1e8f600c1986f46b53 Mon Sep 17 00:00:00 2001 From: charmlesscoin Date: Sat, 3 Aug 2013 17:29:18 -0400 Subject: [PATCH 046/172] fix for issue #306 --- chat.c | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/chat.c b/chat.c index 7cae1c0..a90bb2a 100644 --- a/chat.c +++ b/chat.c @@ -77,6 +77,18 @@ static void chat_onStatusChange(ToxWindow* self, int num, uint8_t* status, uint1 } +/* check that the string has one non-space character */ +int string_is_empty(char *string) +{ + int rc = 0; + char *copy = strdup(string); + + rc = ((strtok(copy, " ") == NULL) ? 1:0); + free(copy); + + return rc; +} + static void chat_onKey(ToxWindow* self, int key) { ChatContext* ctx = (ChatContext*) self->x; @@ -92,23 +104,28 @@ static void chat_onKey(ToxWindow* self, int key) { ctx->line[ctx->pos] = '\0'; } } + else if(key == '\n') { - wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history, "%02d:%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); - wattron(ctx->history, COLOR_PAIR(1)); - wprintw(ctx->history, "you: ", ctx->line); - wattroff(ctx->history, COLOR_PAIR(1)); - wprintw(ctx->history, "%s\n", ctx->line); + if(!string_is_empty(ctx->line)) { + /* make sure the string has at least non-space character */ + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "%02d:%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattron(ctx->history, COLOR_PAIR(1)); + wprintw(ctx->history, "you: ", ctx->line); + wattroff(ctx->history, COLOR_PAIR(1)); + wprintw(ctx->history, "%s\n", ctx->line); - if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) { - wattron(ctx->history, COLOR_PAIR(3)); - wprintw(ctx->history, " * Failed to send message.\n"); - wattroff(ctx->history, COLOR_PAIR(3)); + if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) { + wattron(ctx->history, COLOR_PAIR(3)); + wprintw(ctx->history, " * Failed to send message.\n"); + wattroff(ctx->history, COLOR_PAIR(3)); + } + + ctx->line[0] = '\0'; + ctx->pos = 0; } - - ctx->line[0] = '\0'; - ctx->pos = 0; } + else if(key == 0x107 || key == 0x8 || key == 0x7f) { if(ctx->pos != 0) { ctx->line[--ctx->pos] = '\0'; From 6ea6af557bfd2392938eafaf824737e24980b1e7 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 4 Aug 2013 04:42:17 -0400 Subject: [PATCH 047/172] added command functionality to chat windows and a few minor improvements --- chat.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++--------- prompt.c | 9 +++--- 2 files changed, 77 insertions(+), 17 deletions(-) diff --git a/chat.c b/chat.c index a90bb2a..72fa5d4 100644 --- a/chat.c +++ b/chat.c @@ -26,6 +26,8 @@ typedef struct { } ChatContext; extern void fix_name(uint8_t* name); +void print_help(ChatContext* self); +void execute(ToxWindow* self, ChatContext* ctx, char* cmd); static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) { ChatContext* ctx = (ChatContext*) self->x; @@ -92,24 +94,19 @@ int string_is_empty(char *string) static void chat_onKey(ToxWindow* self, int key) { ChatContext* ctx = (ChatContext*) self->x; - time_t now; - time(&now); - struct tm * timeinfo; - timeinfo = localtime(&now); - + /* PRINTABLE characters: Add to line */ if(isprint(key)) { - if(ctx->pos != sizeof(ctx->line)-1) { ctx->line[ctx->pos++] = key; ctx->line[ctx->pos] = '\0'; } } + /* RETURN key: Execute command or print line */ else if(key == '\n') { - if(!string_is_empty(ctx->line)) { - /* make sure the string has at least non-space character */ - wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history, "%02d:%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + if (ctx->line[0] == '/') + execute(self, ctx, ctx->line); + else { wattron(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "you: ", ctx->line); wattroff(ctx->history, COLOR_PAIR(1)); @@ -120,18 +117,65 @@ static void chat_onKey(ToxWindow* self, int key) { wprintw(ctx->history, " * Failed to send message.\n"); wattroff(ctx->history, COLOR_PAIR(3)); } - - ctx->line[0] = '\0'; - ctx->pos = 0; } + ctx->line[0] = '\0'; + ctx->pos = 0; } + /* BACKSPACE key: Remove one character from line */ else if(key == 0x107 || key == 0x8 || key == 0x7f) { if(ctx->pos != 0) { ctx->line[--ctx->pos] = '\0'; } } +} +void execute(ToxWindow* self, ChatContext* ctx, char* cmd) +{ + if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { + wclear(self->window); + wclear(ctx->history); + } + else if (!strcmp(cmd, "/help") || !strcmp(cmd, "/h")) + print_help(ctx); + else if (!strcmp(cmd, "/quit") || !strcmp(cmd, "/exit") || !strcmp(cmd, "/q")) { + endwin(); + exit(0); + } + else if (!strncmp(cmd, "/status ", strlen("/status "))) { + char* msg; + msg = strchr(cmd, ' '); + if(msg == NULL) { + wprintw(ctx->history, "Invalid syntax.\n"); + return; + } + msg++; + m_set_userstatus((uint8_t*) msg, strlen(msg)+1); + wprintw(ctx->history, "Status set to: %s\n", msg); + } + else if (!strncmp(cmd, "/nick ", strlen("/nick "))) { + char* nick; + nick = strchr(cmd, ' '); + if(nick == NULL) { + wprintw(ctx->history, "Invalid syntax.\n"); + return; + } + nick++; + setname((uint8_t*) nick, strlen(nick)+1); + wprintw(ctx->history, "Nickname set to: %s\n", nick); + } + else if(!strcmp(cmd, "/myid")) { + char id[32*2 + 1] = {0}; + int i; + for (i = 0; i < 32; i++) { + char xx[3]; + snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); + strcat(id, xx); + } + wprintw(ctx->history, "Your ID: %s\n", id); + } + else + wprintw(ctx->history, "Invalid command.\n"); } static void chat_onDraw(ToxWindow* self) { @@ -164,6 +208,21 @@ static void chat_onInit(ToxWindow* self) { ctx->linewin = subwin(self->window, 2, x, y - 3, 0); } +void print_help(ChatContext* self) { + wattron(self->history, COLOR_PAIR(2) | A_BOLD); + wprintw(self->history, "\nCommands:\n"); + wattroff(self->history, A_BOLD); + + wprintw(self->history, " /status : Set your status\n"); + wprintw(self->history, " /nick : Set your nickname\n"); + wprintw(self->history, " /myid : Print your ID\n"); + wprintw(self->history, " /clear : Clear the screen\n"); + wprintw(self->history, " /quit or /exit : Exit program\n"); + wprintw(self->history, " /help : Print this message again\n\n"); + + wattroff(self->history, COLOR_PAIR(2)); +} + ToxWindow new_chat(int friendnum) { ToxWindow ret; diff --git a/prompt.c b/prompt.c index a47238a..365aee4 100644 --- a/prompt.c +++ b/prompt.c @@ -148,7 +148,7 @@ static void execute(ToxWindow* self, char* cmd) { wprintw(self->window, "Friend request already sent.\n"); break; case -5: - wprintw(self->window, "[i] Undefined error when adding friend.\n"); + wprintw(self->window, "Undefined error when adding friend.\n"); break; default: wprintw(self->window, "Friend added as %d.\n", num); @@ -178,12 +178,13 @@ static void execute(ToxWindow* self, char* cmd) { nick = strchr(cmd, ' '); if(nick == NULL) { + wprintw(self->window, "Invalid syntax.\n"); return; } nick++; setname((uint8_t*) nick, strlen(nick)+1); - wprintw(self->window, "Nickname set to: %s.\n", nick); + wprintw(self->window, "Nickname set to: %s\n", nick); } else if(!strcmp(cmd, "myid")) { char id[32*2 + 1] = {0}; @@ -195,7 +196,7 @@ static void execute(ToxWindow* self, char* cmd) { strcat(id, xx); } - wprintw(self->window, "%s\n", id); + wprintw(self->window, "Your ID: %s\n", id); } else if(!strncmp(cmd, "accept ", strlen("accept "))) { char* id; @@ -256,7 +257,7 @@ static void execute(ToxWindow* self, char* cmd) { wclear(self->window); } else { - wprintw(self->window, "Invalid syntax.\n"); + wprintw(self->window, "Invalid command.\n"); } } From 18dcb06920cba20ef204e9e689e376e50320807c Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 4 Aug 2013 05:00:16 -0400 Subject: [PATCH 048/172] didn't mean to delete that --- chat.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/chat.c b/chat.c index 72fa5d4..846bcf2 100644 --- a/chat.c +++ b/chat.c @@ -94,6 +94,11 @@ int string_is_empty(char *string) static void chat_onKey(ToxWindow* self, int key) { ChatContext* ctx = (ChatContext*) self->x; + time_t now; + time(&now); + struct tm * timeinfo; + timeinfo = localtime(&now); + /* PRINTABLE characters: Add to line */ if(isprint(key)) { if(ctx->pos != sizeof(ctx->line)-1) { @@ -107,11 +112,15 @@ static void chat_onKey(ToxWindow* self, int key) { if (ctx->line[0] == '/') execute(self, ctx, ctx->line); else { - wattron(ctx->history, COLOR_PAIR(1)); - wprintw(ctx->history, "you: ", ctx->line); - wattroff(ctx->history, COLOR_PAIR(1)); - wprintw(ctx->history, "%s\n", ctx->line); - + if(!string_is_empty(ctx->line)) { + /* make sure the string has at least non-space character */ + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "%02d:%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattron(ctx->history, COLOR_PAIR(1)); + wprintw(ctx->history, "you: ", ctx->line); + wattroff(ctx->history, COLOR_PAIR(1)); + wprintw(ctx->history, "%s\n", ctx->line); + } if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) { wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Failed to send message.\n"); From 337d87a3ef02be3cc3bf6525f22022f113c43fbc Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 4 Aug 2013 05:32:53 -0400 Subject: [PATCH 049/172] already a pull request with this addition --- prompt.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/prompt.c b/prompt.c index 365aee4..3fa9d77 100644 --- a/prompt.c +++ b/prompt.c @@ -253,9 +253,6 @@ static void execute(ToxWindow* self, char* cmd) { } } - else if (!strncmp(cmd, "clear", strlen("clear"))) { - wclear(self->window); - } else { wprintw(self->window, "Invalid command.\n"); } @@ -315,7 +312,6 @@ static void print_usage(ToxWindow* self) { wprintw(self->window, " nick : Set your nickname\n"); wprintw(self->window, " accept : Accept friend request\n"); wprintw(self->window, " myid : Print your ID\n"); - wprintw(self->window, " clear : Clear the screen\n"); wprintw(self->window, " quit/exit : Exit program\n"); wprintw(self->window, " help : Print this message again\n"); From 3c43b276172967c2e6079aea904e7b6991cdeae6 Mon Sep 17 00:00:00 2001 From: plutooo Date: Sun, 4 Aug 2013 03:27:36 -0700 Subject: [PATCH 050/172] toxic: Fixed doMessenger() interval.. Toxic is much faster and responsive now. --- main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index 3b45a89..e0e2370 100644 --- a/main.c +++ b/main.c @@ -91,7 +91,7 @@ static void init_term() { cbreak(); keypad(stdscr, 1); noecho(); - timeout(2000); + timeout(100); if(has_colors()) { start_color(); @@ -255,15 +255,15 @@ static void draw_bar() { attron(A_BOLD); } - odd = (odd+1) % 2; + odd = (odd+1) % 10; - if(windows[i].blink && odd) { + if(windows[i].blink && (odd < 5)) { attron(COLOR_PAIR(3)); } printw(" %s", windows[i].title); - if(windows[i].blink && odd) { + if(windows[i].blink && (odd < 5)) { attron(COLOR_PAIR(3)); } From 6f9dea8510db2192ffbf4bbfa4bcd5c8c2d1cae5 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sun, 4 Aug 2013 03:52:24 -0700 Subject: [PATCH 051/172] Manally merged #314 and #317 --- chat.c | 4 +++- prompt.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/chat.c b/chat.c index 846bcf2..936eb86 100644 --- a/chat.c +++ b/chat.c @@ -51,6 +51,7 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "%02d:%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); wattron(ctx->history, COLOR_PAIR(4)); wprintw(ctx->history, "%s: ", nick); wattroff(ctx->history, COLOR_PAIR(4)); @@ -116,6 +117,7 @@ static void chat_onKey(ToxWindow* self, int key) { /* make sure the string has at least non-space character */ wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "%02d:%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); wattron(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "you: ", ctx->line); wattroff(ctx->history, COLOR_PAIR(1)); @@ -254,6 +256,6 @@ ToxWindow new_chat(int friendnum) { x->friendnum = friendnum; ret.x = (void*) x; - + free(x); return ret; } diff --git a/prompt.c b/prompt.c index 3fa9d77..463b935 100644 --- a/prompt.c +++ b/prompt.c @@ -89,7 +89,9 @@ static void execute(ToxWindow* self, char* cmd) { } dht.ip.i = resolved_address; - DHT_bootstrap(dht, hex_string_to_bin(key)); + unsigned char *binary_string = hex_string_to_bin(key); + DHT_bootstrap(dht, binary_string); + free(binary_string); } else if(!strncmp(cmd, "add ", strlen("add "))) { uint8_t id_bin[32]; From 4ef0b686026c6d9c85ff06d84ebc80d6ff99b7fe Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sun, 4 Aug 2013 13:16:08 -0700 Subject: [PATCH 052/172] Fixed a calloc getting freed before being used --- chat.c | 1 - 1 file changed, 1 deletion(-) diff --git a/chat.c b/chat.c index 936eb86..ff7a166 100644 --- a/chat.c +++ b/chat.c @@ -256,6 +256,5 @@ ToxWindow new_chat(int friendnum) { x->friendnum = friendnum; ret.x = (void*) x; - free(x); return ret; } From 805eb0195aea952bd28b0d4d7f6eb90cdb3509e5 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sun, 4 Aug 2013 14:36:09 -0700 Subject: [PATCH 053/172] Fixed 2 Null pointer derefrences in both nTox and toxic --- main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index e0e2370..45760b1 100644 --- a/main.c +++ b/main.c @@ -288,7 +288,9 @@ int main(int argc, char* argv[]) { ToxWindow* a; for(i = 0; i < argc; i++) { - if(argv[i][0] == '-') { + if (argv[i] == NULL){ + break; + } else if(argv[i][0] == '-') { if(argv[i][1] == 'f') { if(argv[i + 1] != NULL) filename = argv[i + 1]; From 765a722c906dcd0a841e7b527bb1cdb363186cf0 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 5 Aug 2013 01:57:29 -0400 Subject: [PATCH 054/172] added ability to close and reopen chat windows & other minor changes --- chat.c | 15 +++-- friendlist.c | 40 ++++++++----- main.c | 157 ++++++++++++++++++++++++++++++++------------------- prompt.c | 5 +- windows.h | 8 +++ 5 files changed, 150 insertions(+), 75 deletions(-) diff --git a/chat.c b/chat.c index 936eb86..c11a7f1 100644 --- a/chat.c +++ b/chat.c @@ -25,6 +25,8 @@ typedef struct { } ChatContext; +extern void del_window(ToxWindow *w, int f_num); +extern int focus_window(int num); extern void fix_name(uint8_t* name); void print_help(ChatContext* self); void execute(ToxWindow* self, ChatContext* ctx, char* cmd); @@ -50,7 +52,7 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) fix_name(nick); wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history, "%02d:%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattroff(ctx->history, COLOR_PAIR(2)); wattron(ctx->history, COLOR_PAIR(4)); wprintw(ctx->history, "%s: ", nick); @@ -116,7 +118,7 @@ static void chat_onKey(ToxWindow* self, int key) { if(!string_is_empty(ctx->line)) { /* make sure the string has at least non-space character */ wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history, "%02d:%02d:%02d ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattroff(ctx->history, COLOR_PAIR(2)); wattron(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "you: ", ctx->line); @@ -185,6 +187,12 @@ void execute(ToxWindow* self, ChatContext* ctx, char* cmd) } wprintw(ctx->history, "Your ID: %s\n", id); } + else if (strcmp(ctx->line, "/close") == 0) { + focus_window(0); // Go to prompt screen + int f_num = ctx->friendnum; + delwin(ctx->linewin); + del_window(self, f_num); + } else wprintw(ctx->history, "Invalid command.\n"); } @@ -256,6 +264,5 @@ ToxWindow new_chat(int friendnum) { x->friendnum = friendnum; ret.x = (void*) x; - free(x); return ret; -} +} \ No newline at end of file diff --git a/friendlist.c b/friendlist.c index b4b619a..2d060ae 100644 --- a/friendlist.c +++ b/friendlist.c @@ -12,12 +12,11 @@ #include "windows.h" +extern char WINDOW_STATUS[TOXWINDOWS_MAX_NUM]; extern int add_window(ToxWindow w); extern int focus_window(int num); extern ToxWindow new_chat(int friendnum); -#define MAX_FRIENDS_NUM 100 - typedef struct { uint8_t name[MAX_NAME_LENGTH]; uint8_t status[MAX_USERSTATUS_LENGTH]; @@ -86,14 +85,11 @@ int friendlist_onFriendAdded(int num) { getname(num, friends[num_friends].name); strcpy((char*) friends[num_friends].name, "unknown"); strcpy((char*) friends[num_friends].status, "unknown"); - friends[num_friends].chatwin = -1; - - num_friends++; + friends[num_friends++].chatwin = -1; return 0; } static void friendlist_onKey(ToxWindow* self, int key) { - if(key == KEY_UP) { if(num_selected != 0) num_selected--; @@ -103,12 +99,26 @@ static void friendlist_onKey(ToxWindow* self, int key) { num_selected = (num_selected+1) % num_friends; } else if(key == '\n') { - - if(friends[num_selected].chatwin != -1) - return; - - friends[num_selected].chatwin = add_window(new_chat(num_selected)); - focus_window(friends[num_selected].chatwin); + /* Jump to chat window if already open */ + if (friends[num_selected].chatwin != -1) { + int i; + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { + if (WINDOW_STATUS[i] == num_selected) { + focus_window(i); + break; + } + } + }else { + friends[num_selected].chatwin = add_window(new_chat(num_selected)); + focus_window(friends[num_selected].chatwin); + int i; + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { // Find open slot + if (WINDOW_STATUS[i] == -1) { + WINDOW_STATUS[i] = num_selected; + break; + } + } + } } } @@ -145,6 +155,10 @@ static void friendlist_onDraw(ToxWindow* self) { wrefresh(self->window); } +void disable_chatwin(int f_num) { + friends[f_num].chatwin = -1; +} + static void friendlist_onInit(ToxWindow* self) { } @@ -164,4 +178,4 @@ ToxWindow new_friendlist() { strcpy(ret.title, "[friends]"); return ret; -} +} \ No newline at end of file diff --git a/main.c b/main.c index e0e2370..e55cb85 100644 --- a/main.c +++ b/main.c @@ -17,13 +17,12 @@ extern ToxWindow new_prompt(); extern ToxWindow new_friendlist(); extern int friendlist_onFriendAdded(int num); - +extern void disable_chatwin(int f_num); extern int add_req(uint8_t* public_key); // XXX -#define TOXWINDOWS_MAX_NUM 32 - -static ToxWindow windows[TOXWINDOWS_MAX_NUM]; -static int w_num; +char WINDOW_STATUS[MAX_WINDOW_SLOTS]; // Holds status of chat windows +static ToxWindow windows[MAX_WINDOW_SLOTS]; +int w_num; static int w_active; static ToxWindow* prompt; @@ -115,6 +114,16 @@ static void init_tox() { m_callback_userstatus(on_statuschange); } +void init_window_status() { + int i; + for (i = 0; i < N_DEFAULT_WINS; i++) + WINDOW_STATUS[i] = i; + + int j; + for (j = N_DEFAULT_WINS; j < MAX_WINDOW_SLOTS; j++) + WINDOW_STATUS[j] = -1; +} + int add_window(ToxWindow w) { if(w_num == TOXWINDOWS_MAX_NUM) return -1; @@ -133,6 +142,21 @@ int add_window(ToxWindow w) { return w_num - 1; } +/* Deletes window w and cleans up */ +void del_window(ToxWindow *w, int f_num) { + delwin(w->window); + int i; + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { + if (WINDOW_STATUS[i] == f_num) { + WINDOW_STATUS[i] = -1; + disable_chatwin(f_num); + break; + } + } + clear(); + refresh(); +} + int focus_window(int num) { if(num >= w_num || num < 0) return -1; @@ -143,7 +167,6 @@ int focus_window(int num) { static void init_windows() { w_num = 0; - w_active = 0; if(add_window(new_prompt()) == -1 || add_window(new_friendlist()) == -1) { fprintf(stderr, "add_window() failed.\n"); @@ -151,7 +174,6 @@ static void init_windows() { endwin(); exit(1); } - prompt = &windows[0]; } @@ -238,7 +260,6 @@ static void load_data(char *path) { static void draw_bar() { static int odd = 0; - size_t i; attron(COLOR_PAIR(4)); mvhline(LINES - 2, 0, '_', COLS); @@ -250,28 +271,26 @@ static void draw_bar() { printw(" TOXIC 1.0 |"); attroff(COLOR_PAIR(4) | A_BOLD); - for(i=0; i max) { // infinite loop check + endwin(); + clear(); + exit(2); + } + } + }else { + int i = w_active - 1; + if (i < 0) i = max; + while (true) { + if (WINDOW_STATUS[i] != -1) { + w_active = i; + return; + } + if (--i < 0) i = max; + if (f_inf++ > max) { + endwin(); + clear(); + exit(2); + } + } + } +} + int main(int argc, char* argv[]) { int ch; - int i = 0; - int f_flag = 0; - char *filename = "data"; ToxWindow* a; - for(i = 0; i < argc; i++) { - if(argv[i][0] == '-') { - if(argv[i][1] == 'f') { - if(argv[i + 1] != NULL) - filename = argv[i + 1]; - else { - f_flag = -1; - } - } - } - } - init_term(); init_tox(); - load_data(filename); + init_window_status(); init_windows(); + char *filename = "data"; + load_data(filename); - if(f_flag == -1) { - attron(COLOR_PAIR(3) | A_BOLD); - wprintw(prompt->window, "You passed '-f' without giving an argument!\n" + int i; + for(i = 0; i < argc; i++) { + if(argv[i][0] == '-' && argv[i][1] == 'f') { + if(argv[i + 1] != NULL) + filename = argv[i + 1]; + else { + attron(COLOR_PAIR(3) | A_BOLD); + wprintw(prompt->window, "You passed '-f' without giving an argument!\n" "defaulting to 'data' for a keyfile...\n"); - attroff(COLOR_PAIR(3) | A_BOLD); + attroff(COLOR_PAIR(3) | A_BOLD); + } + } } - - while(true) { // Update tox. do_tox(); @@ -325,18 +372,14 @@ int main(int argc, char* argv[]) { // Handle input. ch = getch(); - if(ch == '\t') { - w_active = (w_active + 1) % w_num; - } - else if(ch == KEY_BTAB) { - w_active = (w_active + w_num - 1) % w_num; + if(ch == '\t' || ch == KEY_BTAB) + set_active_window(ch); + else if(ch != ERR) { + a->onKey(a, ch); } else if(ch != ERR) { a->onKey(a, ch); } - } - return 0; -} - +} \ No newline at end of file diff --git a/prompt.c b/prompt.c index 463b935..d40fb2a 100644 --- a/prompt.c +++ b/prompt.c @@ -254,7 +254,9 @@ static void execute(ToxWindow* self, char* cmd) { wprintw(self->window, "Message successfully sent.\n"); } } - + else if (!strncmp(cmd, "clear", strlen("clear"))) { + wclear(self->window); + } else { wprintw(self->window, "Invalid command.\n"); } @@ -314,6 +316,7 @@ static void print_usage(ToxWindow* self) { wprintw(self->window, " nick : Set your nickname\n"); wprintw(self->window, " accept : Accept friend request\n"); wprintw(self->window, " myid : Print your ID\n"); + wprintw(self->window, " clear : Clear the screen\n"); wprintw(self->window, " quit/exit : Exit program\n"); wprintw(self->window, " help : Print this message again\n"); diff --git a/windows.h b/windows.h index dde1430..cb45614 100644 --- a/windows.h +++ b/windows.h @@ -3,6 +3,14 @@ */ #include +#define TOXWINDOWS_MAX_NUM 32 +#define MAX_FRIENDS_NUM 100 + +/* number of permanent default windows */ +#define N_DEFAULT_WINS 2 + +/* maximum window slots for WINDOW_STATUS array */ +#define MAX_WINDOW_SLOTS N_DEFAULT_WINS+MAX_FRIENDS_NUM typedef struct ToxWindow_ ToxWindow; From 8ab8f6b834b19bb5d839527cdd8397628bdb809b Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 5 Aug 2013 02:32:50 -0400 Subject: [PATCH 055/172] test --- chat.c | 4 +++- main.c | 39 ++++++++++++++++++++++++--------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/chat.c b/chat.c index c11a7f1..eb297f7 100644 --- a/chat.c +++ b/chat.c @@ -236,6 +236,7 @@ void print_help(ChatContext* self) { wprintw(self->history, " /nick : Set your nickname\n"); wprintw(self->history, " /myid : Print your ID\n"); wprintw(self->history, " /clear : Clear the screen\n"); + wprintw(self->history, " /close : Closes the current chat window\n"); wprintw(self->history, " /quit or /exit : Exit program\n"); wprintw(self->history, " /help : Print this message again\n\n"); @@ -264,5 +265,6 @@ ToxWindow new_chat(int friendnum) { x->friendnum = friendnum; ret.x = (void*) x; + free(x); return ret; -} \ No newline at end of file +} diff --git a/main.c b/main.c index e55cb85..42657e8 100644 --- a/main.c +++ b/main.c @@ -337,28 +337,37 @@ void set_active_window(int ch) { int main(int argc, char* argv[]) { int ch; + int i = 0; + int f_flag = 0; + char *filename = "data"; ToxWindow* a; + for(i = 0; i < argc; i++) { + if (argv[i] == NULL){ + break; + } else if(argv[i][0] == '-') { + if(argv[i][1] == 'f') { + if(argv[i + 1] != NULL) + filename = argv[i + 1]; + else { + f_flag = -1; + } + } + } + } + init_term(); init_tox(); - init_window_status(); - init_windows(); - char *filename = "data"; load_data(filename); + init_windows(); - int i; - for(i = 0; i < argc; i++) { - if(argv[i][0] == '-' && argv[i][1] == 'f') { - if(argv[i + 1] != NULL) - filename = argv[i + 1]; - else { - attron(COLOR_PAIR(3) | A_BOLD); - wprintw(prompt->window, "You passed '-f' without giving an argument!\n" + if(f_flag == -1) { + attron(COLOR_PAIR(3) | A_BOLD); + wprintw(prompt->window, "You passed '-f' without giving an argument!\n" "defaulting to 'data' for a keyfile...\n"); - attroff(COLOR_PAIR(3) | A_BOLD); - } - } + attroff(COLOR_PAIR(3) | A_BOLD); } + while(true) { // Update tox. do_tox(); @@ -382,4 +391,4 @@ int main(int argc, char* argv[]) { } } return 0; -} \ No newline at end of file +} From f824373e6ab102c5ab3c9c0264074afefdf32d6d Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 5 Aug 2013 02:48:59 -0400 Subject: [PATCH 056/172] init array --- main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/main.c b/main.c index 42657e8..c8cf73e 100644 --- a/main.c +++ b/main.c @@ -360,6 +360,7 @@ int main(int argc, char* argv[]) { init_tox(); load_data(filename); init_windows(); + init_window_status(); if(f_flag == -1) { attron(COLOR_PAIR(3) | A_BOLD); From 14fe0b01f6d4f4c4d97e24026438006dcb9287de Mon Sep 17 00:00:00 2001 From: joshuaj Date: Mon, 5 Aug 2013 10:14:44 -0700 Subject: [PATCH 057/172] Fixed toxic friends list flicker --- friendlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/friendlist.c b/friendlist.c index b4b619a..05651b0 100644 --- a/friendlist.c +++ b/friendlist.c @@ -116,7 +116,7 @@ static void friendlist_onDraw(ToxWindow* self) { curs_set(0); size_t i; - wclear(self->window); + werase(self->window); if(num_friends == 0) { wprintw(self->window, "Empty. Add some friends! :-)\n"); From 34a8d6ecb9bf9b6f8512d34c9d3309459ce05520 Mon Sep 17 00:00:00 2001 From: Nominate Date: Mon, 5 Aug 2013 18:33:16 +0100 Subject: [PATCH 058/172] Added a 'clear' function to the prompt --- prompt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/prompt.c b/prompt.c index 463b935..c28980c 100644 --- a/prompt.c +++ b/prompt.c @@ -158,7 +158,9 @@ static void execute(ToxWindow* self, char* cmd) { break; } } - + else if(!strcmp(cmd, "clear")) { + wclear(self->window); + } else if(!strcmp(cmd, "help")) { print_usage(self); } @@ -316,7 +318,7 @@ static void print_usage(ToxWindow* self) { wprintw(self->window, " myid : Print your ID\n"); wprintw(self->window, " quit/exit : Exit program\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, "TIP: Use the TAB key to navigate through the tabs.\n\n"); From aaf3ce9761555be4a43818851e2c47afa8585668 Mon Sep 17 00:00:00 2001 From: Nominate Date: Mon, 5 Aug 2013 18:52:28 +0100 Subject: [PATCH 059/172] Grammar/aesthetic amendment --- prompt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prompt.c b/prompt.c index c28980c..e5dc508 100644 --- a/prompt.c +++ b/prompt.c @@ -318,7 +318,7 @@ static void print_usage(ToxWindow* self) { wprintw(self->window, " myid : Print your ID\n"); wprintw(self->window, " quit/exit : Exit program\n"); wprintw(self->window, " help : Print this message again\n"); - wprintw(self->window, " clear: : Clear this window\n"); + wprintw(self->window, " clear : Clear this window\n"); wattron(self->window, A_BOLD); wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n"); From 51598d626a21948e2a4ad80779b2edbbeaa028b7 Mon Sep 17 00:00:00 2001 From: Sebastian Stal Date: Mon, 5 Aug 2013 12:30:40 -0700 Subject: [PATCH 060/172] Make test clients compatible with userstatus kinds No features were added, just fixed callbacks. --- chat.c | 2 +- main.c | 6 +++--- prompt.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/chat.c b/chat.c index ff7a166..f28a6a3 100644 --- a/chat.c +++ b/chat.c @@ -161,7 +161,7 @@ void execute(ToxWindow* self, ChatContext* ctx, char* cmd) return; } msg++; - m_set_userstatus((uint8_t*) msg, strlen(msg)+1); + m_set_userstatus(USERSTATUS_KIND_RETAIN, (uint8_t*) msg, strlen(msg)+1); wprintw(ctx->history, "Status set to: %s\n", msg); } else if (!strncmp(cmd, "/nick ", strlen("/nick "))) { diff --git a/main.c b/main.c index 45760b1..b322f95 100644 --- a/main.c +++ b/main.c @@ -69,7 +69,7 @@ void on_nickchange(int friendnumber, uint8_t* string, uint16_t length) { } } -void on_statuschange(int friendnumber, uint8_t* string, uint16_t length) { +void on_statuschange(int friendnumber, USERSTATUS_KIND kind, uint8_t* string, uint16_t length) { size_t i; wprintw(prompt->window, "\n(statuschange) %d: %s!\n", friendnumber, string); @@ -201,7 +201,7 @@ static void load_data(char *path) { Messenger_load(buf, len); } - else { + else { len = Messenger_size(); buf = malloc(len); @@ -289,7 +289,7 @@ int main(int argc, char* argv[]) { for(i = 0; i < argc; i++) { if (argv[i] == NULL){ - break; + break; } else if(argv[i][0] == '-') { if(argv[i][1] == 'f') { if(argv[i + 1] != NULL) diff --git a/prompt.c b/prompt.c index 463b935..1ba1569 100644 --- a/prompt.c +++ b/prompt.c @@ -91,7 +91,7 @@ static void execute(ToxWindow* self, char* cmd) { dht.ip.i = resolved_address; unsigned char *binary_string = hex_string_to_bin(key); DHT_bootstrap(dht, binary_string); - free(binary_string); + free(binary_string); } else if(!strncmp(cmd, "add ", strlen("add "))) { uint8_t id_bin[32]; @@ -137,7 +137,7 @@ static void execute(ToxWindow* self, char* cmd) { num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); switch (num) { - case -1: + case -1: wprintw(self->window, "Message is too long.\n"); break; case -2: @@ -151,7 +151,7 @@ static void execute(ToxWindow* self, char* cmd) { break; case -5: wprintw(self->window, "Undefined error when adding friend.\n"); - break; + break; default: wprintw(self->window, "Friend added as %d.\n", num); on_friendadded(num); @@ -172,7 +172,7 @@ static void execute(ToxWindow* self, char* cmd) { } msg++; - m_set_userstatus((uint8_t*) msg, strlen(msg)+1); + m_set_userstatus(USERSTATUS_KIND_RETAIN, (uint8_t*) msg, strlen(msg)+1); wprintw(self->window, "Status set to: %s\n", msg); } else if(!strncmp(cmd, "nick ", strlen("nick "))) { From 6494a4070b9a34f7614aafa1b19f8c871fcf33e9 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 5 Aug 2013 16:04:06 -0400 Subject: [PATCH 061/172] chat window deleting and re-adding - it just werks --- chat.c | 6 +++--- friendlist.c | 27 +++++++++++++++++++-------- main.c | 41 +++++++++++++++++------------------------ prompt.c | 9 ++++----- 4 files changed, 43 insertions(+), 40 deletions(-) diff --git a/chat.c b/chat.c index 2c1f107..5d0e14a 100644 --- a/chat.c +++ b/chat.c @@ -25,8 +25,8 @@ typedef struct { } ChatContext; +extern int w_active; extern void del_window(ToxWindow *w, int f_num); -extern int focus_window(int num); extern void fix_name(uint8_t* name); void print_help(ChatContext* self); void execute(ToxWindow* self, ChatContext* ctx, char* cmd); @@ -188,7 +188,7 @@ void execute(ToxWindow* self, ChatContext* ctx, char* cmd) wprintw(ctx->history, "Your ID: %s\n", id); } else if (strcmp(ctx->line, "/close") == 0) { - focus_window(0); // Go to prompt screen + w_active = 0; // Go to prompt screen int f_num = ctx->friendnum; delwin(ctx->linewin); del_window(self, f_num); @@ -236,7 +236,7 @@ void print_help(ChatContext* self) { wprintw(self->history, " /nick : Set your nickname\n"); wprintw(self->history, " /myid : Print your ID\n"); wprintw(self->history, " /clear : Clear the screen\n"); - wprintw(self->history, " /close : Closes the current chat window\n"); + wprintw(self->history, " /close : Close the current chat window\n"); wprintw(self->history, " /quit or /exit : Exit program\n"); wprintw(self->history, " /help : Print this message again\n\n"); diff --git a/friendlist.c b/friendlist.c index 2d060ae..647f563 100644 --- a/friendlist.c +++ b/friendlist.c @@ -13,9 +13,9 @@ #include "windows.h" extern char WINDOW_STATUS[TOXWINDOWS_MAX_NUM]; -extern int add_window(ToxWindow w); -extern int focus_window(int num); +extern int add_window(ToxWindow w, int n); extern ToxWindow new_chat(int friendnum); +extern int w_active; typedef struct { uint8_t name[MAX_NAME_LENGTH]; @@ -52,7 +52,17 @@ void friendlist_onMessage(ToxWindow* self, int num, uint8_t* str, uint16_t len) return; if(friends[num].chatwin == -1) { - friends[num].chatwin = add_window(new_chat(num)); + friends[num].chatwin = num; + int i; + /* Find first open slot to hold chat window */ + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { + if (WINDOW_STATUS[i] == -1) { + WINDOW_STATUS[i] = num; + add_window(new_chat(num_selected), i); + w_active = i; + break; + } + } } } @@ -104,17 +114,18 @@ static void friendlist_onKey(ToxWindow* self, int key) { int i; for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { if (WINDOW_STATUS[i] == num_selected) { - focus_window(i); + w_active = i; break; } } }else { - friends[num_selected].chatwin = add_window(new_chat(num_selected)); - focus_window(friends[num_selected].chatwin); int i; - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { // Find open slot + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { if (WINDOW_STATUS[i] == -1) { WINDOW_STATUS[i] = num_selected; + friends[num_selected].chatwin = num_selected; + add_window(new_chat(num_selected), i); + w_active = i; break; } } @@ -178,4 +189,4 @@ ToxWindow new_friendlist() { strcpy(ret.title, "[friends]"); return ret; -} \ No newline at end of file +} diff --git a/main.c b/main.c index c8cf73e..892f812 100644 --- a/main.c +++ b/main.c @@ -23,7 +23,7 @@ extern int add_req(uint8_t* public_key); // XXX char WINDOW_STATUS[MAX_WINDOW_SLOTS]; // Holds status of chat windows static ToxWindow windows[MAX_WINDOW_SLOTS]; int w_num; -static int w_active; +int w_active; static ToxWindow* prompt; // CALLBACKS START @@ -40,7 +40,7 @@ void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) { wprintw(prompt->window, "Use \"accept %d\" to accept it.\n", n); - for(i=0; iwindow, "\n(message) %d: %s\n", friendnumber, string); - for(i=0; iwindow, "\n(nickchange) %d: %s!\n", friendnumber, string); - for(i=0; iwindow, "\n(statuschange) %d: %s!\n", friendnumber, string); - for(i=0; i= TOXWINDOWS_MAX_NUM) return -1; if(LINES < 2) return -1; w.window = newwin(LINES - 2, COLS, 0, 0); - if(w.window == NULL) return -1; - windows[w_num++] = w; + windows[n] = w; w.onInit(&w); - - return w_num - 1; + w_num++; + return n; } /* Deletes window w and cleans up */ @@ -157,24 +157,17 @@ void del_window(ToxWindow *w, int f_num) { refresh(); } -int focus_window(int num) { - if(num >= w_num || num < 0) - return -1; - - w_active = num; - return 0; -} - static void init_windows() { w_num = 0; - - if(add_window(new_prompt()) == -1 || add_window(new_friendlist()) == -1) { + int n_prompt = 0; + int n_friendslist = 1; + if(add_window(new_prompt(), n_prompt) == -1 + || add_window(new_friendlist(), n_friendslist) == -1) { fprintf(stderr, "add_window() failed.\n"); - endwin(); exit(1); } - prompt = &windows[0]; + prompt = &windows[n_prompt]; } static void do_tox() { diff --git a/prompt.c b/prompt.c index d40fb2a..f973afd 100644 --- a/prompt.c +++ b/prompt.c @@ -158,7 +158,9 @@ static void execute(ToxWindow* self, char* cmd) { break; } } - + else if (!strcmp(cmd, "clear")) { + wclear(self->window); + } else if(!strcmp(cmd, "help")) { print_usage(self); } @@ -254,9 +256,6 @@ static void execute(ToxWindow* self, char* cmd) { wprintw(self->window, "Message successfully sent.\n"); } } - else if (!strncmp(cmd, "clear", strlen("clear"))) { - wclear(self->window); - } else { wprintw(self->window, "Invalid command.\n"); } @@ -316,7 +315,7 @@ static void print_usage(ToxWindow* self) { wprintw(self->window, " nick : Set your nickname\n"); wprintw(self->window, " accept : Accept friend request\n"); wprintw(self->window, " myid : Print your ID\n"); - wprintw(self->window, " clear : Clear the screen\n"); + wprintw(self->window, " clear : Clear this window\n"); wprintw(self->window, " quit/exit : Exit program\n"); wprintw(self->window, " help : Print this message again\n"); From 3d0b16c68189aa70e47cfdd4bb9f962abd757d5d Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 5 Aug 2013 16:34:55 -0400 Subject: [PATCH 062/172] list commands on chat window popup --- chat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chat.c b/chat.c index 5d0e14a..175c6b0 100644 --- a/chat.c +++ b/chat.c @@ -225,11 +225,12 @@ static void chat_onInit(ToxWindow* self) { scrollok(ctx->history, 1); ctx->linewin = subwin(self->window, 2, x, y - 3, 0); + print_help(ctx); } void print_help(ChatContext* self) { wattron(self->history, COLOR_PAIR(2) | A_BOLD); - wprintw(self->history, "\nCommands:\n"); + wprintw(self->history, "Commands:\n"); wattroff(self->history, A_BOLD); wprintw(self->history, " /status : Set your status\n"); From 9b7dafc16fe7e46282b247f7c837b57d94f685e4 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 5 Aug 2013 18:07:08 -0400 Subject: [PATCH 063/172] bug fix and added wrapping on friends list --- friendlist.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/friendlist.c b/friendlist.c index 647f563..a1f9851 100644 --- a/friendlist.c +++ b/friendlist.c @@ -58,11 +58,11 @@ void friendlist_onMessage(ToxWindow* self, int num, uint8_t* str, uint16_t len) for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { if (WINDOW_STATUS[i] == -1) { WINDOW_STATUS[i] = num; - add_window(new_chat(num_selected), i); + add_window(new_chat(num), i); w_active = i; break; - } } + } } } @@ -101,8 +101,9 @@ int friendlist_onFriendAdded(int num) { static void friendlist_onKey(ToxWindow* self, int key) { if(key == KEY_UP) { - if(num_selected != 0) - num_selected--; + num_selected--; + if (num_selected < 0) + num_selected = num_friends-1; } else if(key == KEY_DOWN) { if(num_friends != 0) From 251a65ed0a898eaa29a27a65ac0480f8a5b11268 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 5 Aug 2013 18:38:55 -0400 Subject: [PATCH 064/172] spacing didn't match outgoing msgs --- chat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chat.c b/chat.c index 175c6b0..15d124b 100644 --- a/chat.c +++ b/chat.c @@ -52,7 +52,7 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) fix_name(nick); wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattroff(ctx->history, COLOR_PAIR(2)); wattron(ctx->history, COLOR_PAIR(4)); wprintw(ctx->history, "%s: ", nick); From e9ca1321b0878859de699271fa93fe172a6d93e1 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Mon, 5 Aug 2013 15:39:32 -0700 Subject: [PATCH 065/172] Throws in a bell when a message is recieved, to warn to user --- chat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chat.c b/chat.c index ff7a166..ee68dc9 100644 --- a/chat.c +++ b/chat.c @@ -32,7 +32,7 @@ void execute(ToxWindow* self, ChatContext* ctx, char* cmd); static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) { ChatContext* ctx = (ChatContext*) self->x; uint8_t nick[MAX_NAME_LENGTH] = {0}; - + time_t now; time(&now); struct tm * timeinfo; @@ -58,6 +58,7 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) wprintw(ctx->history, "%s\n", msg); self->blink = true; + beep(); } static void chat_onNickChange(ToxWindow* self, int num, uint8_t* nick, uint16_t len) { From 7c6467168ecb4768831c9eebf5c82d50c625c953 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Mon, 5 Aug 2013 17:08:05 -0700 Subject: [PATCH 066/172] Removed a useless ! from toxics status --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index 45760b1..b8b4a66 100644 --- a/main.c +++ b/main.c @@ -72,7 +72,7 @@ void on_nickchange(int friendnumber, uint8_t* string, uint16_t length) { void on_statuschange(int friendnumber, uint8_t* string, uint16_t length) { size_t i; - wprintw(prompt->window, "\n(statuschange) %d: %s!\n", friendnumber, string); + wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); for(i=0; i Date: Mon, 5 Aug 2013 17:47:49 -0700 Subject: [PATCH 067/172] Added flash, apparently in weird cases it works when beep fails --- chat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/chat.c b/chat.c index 4ea459d..da1f9f4 100644 --- a/chat.c +++ b/chat.c @@ -59,6 +59,7 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) self->blink = true; beep(); + flash(); } static void chat_onNickChange(ToxWindow* self, int num, uint8_t* nick, uint16_t len) { From 1701ed7023b36f98e77a57e59eb65c08f09a5001 Mon Sep 17 00:00:00 2001 From: Nominate Date: Tue, 6 Aug 2013 08:10:05 +0100 Subject: [PATCH 068/172] Stops line-spamming and clears before printing help This addresses one issue in #340 perfectly and slightly improves the other. --- prompt.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/prompt.c b/prompt.c index 16750c5..c832db3 100644 --- a/prompt.c +++ b/prompt.c @@ -159,10 +159,11 @@ static void execute(ToxWindow* self, char* cmd) { } } else if(!strcmp(cmd, "clear")) { - wclear(self->window); + wclear(self->window); } else if(!strcmp(cmd, "help")) { - print_usage(self); + wclear(self->window); + print_usage(self); } else if(!strncmp(cmd, "status ", strlen("status "))) { char* msg; @@ -265,8 +266,8 @@ static void execute(ToxWindow* self, char* cmd) { static void prompt_onKey(ToxWindow* self, int key) { // PRINTABLE characters: Add to line. if(isprint(key)) { - if(prompt_buf_pos == (sizeof(prompt_buf) - 1)) { - return; + if(prompt_buf_pos == (COLS - 3)) { + return; } prompt_buf[prompt_buf_pos++] = key; prompt_buf[prompt_buf_pos] = 0; From dfff1e3cc46eab91c67d9190324beda1786f5601 Mon Sep 17 00:00:00 2001 From: Nominate Date: Tue, 6 Aug 2013 11:16:17 +0100 Subject: [PATCH 069/172] Corrected wrap-around This should allow wrap-around and allow proper execution. --- prompt.c | 80 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/prompt.c b/prompt.c index c832db3..742b35f 100644 --- a/prompt.c +++ b/prompt.c @@ -1,6 +1,6 @@ /* - * Toxic -- Tox Curses Client - */ +* Toxic -- Tox Curses Client +*/ #include #include @@ -41,7 +41,17 @@ unsigned char * hex_string_to_bin(char hex_string[]) static char prompt_buf[256] = {0}; static int prompt_buf_pos=0; -static void execute(ToxWindow* self, char* cmd) { +static void execute(ToxWindow* self, char* u_cmd) { + int i; + int newlines = 0; + char cmd[256] = {0}; + for(i = 0; i < strlen(prompt_buf); i++) + { + if (u_cmd[i] == '\n') + ++newlines; + else + cmd[i - newlines] = u_cmd[i]; + } if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) { endwin(); @@ -158,7 +168,7 @@ static void execute(ToxWindow* self, char* cmd) { break; } } - else if(!strcmp(cmd, "clear")) { + else if(!strcmp(cmd, "clear")) { wclear(self->window); } else if(!strcmp(cmd, "help")) { @@ -197,7 +207,7 @@ static void execute(ToxWindow* self, char* cmd) { for(i=0; i<32; i++) { char xx[3]; - snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); + snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); strcat(id, xx); } @@ -266,8 +276,16 @@ static void execute(ToxWindow* self, char* cmd) { static void prompt_onKey(ToxWindow* self, int key) { // PRINTABLE characters: Add to line. if(isprint(key)) { - if(prompt_buf_pos == (COLS - 3)) { - return; + if (prompt_buf_pos == 255){ + wprintw(self->window, "\nToo Long.\n"); + prompt_buf_pos = 0; + prompt_buf[0] = 0; + } + else if(!(prompt_buf_pos == 0) && (prompt_buf_pos < COLS) && (prompt_buf_pos % (COLS - 3) == 0)) { + prompt_buf[prompt_buf_pos++] = '\n'; + } + else if(!(prompt_buf_pos == 0) && (prompt_buf_pos > COLS) && ((prompt_buf_pos - (COLS - 3)) % (COLS) == 0)) { + prompt_buf[prompt_buf_pos++] = '\n'; } prompt_buf[prompt_buf_pos++] = key; prompt_buf[prompt_buf_pos] = 0; @@ -290,20 +308,22 @@ static void prompt_onKey(ToxWindow* self, int key) { } static void prompt_onDraw(ToxWindow* self) { - curs_set(1); - int x, y; - - getyx(self->window, y, x); - (void) x; - - wattron(self->window, COLOR_PAIR(1)); - mvwprintw(self->window, y, 0, "# "); - wattroff(self->window, COLOR_PAIR(1)); - - mvwprintw(self->window, y, 2, "%s", prompt_buf); - wclrtoeol(self->window); - - wrefresh(self->window); + curs_set(1); + int x, y; + getyx(self->window, y, x); + (void) x; + int i; + for (i = 0; i < (strlen(prompt_buf)); i++) + { + if ((prompt_buf[i] == '\n') && (y != 0)) + --y; + } + wattron(self->window, COLOR_PAIR(1)); + mvwprintw(self->window, y, 0, "# "); + wattroff(self->window, COLOR_PAIR(1)); + mvwprintw(self->window, y, 2, "%s", prompt_buf); + wclrtoeol(self->window); + wrefresh(self->window); } static void print_usage(ToxWindow* self) { @@ -311,15 +331,15 @@ static void print_usage(ToxWindow* self) { wprintw(self->window, "Commands:\n"); wattroff(self->window, A_BOLD); - wprintw(self->window, " connect : Connect to DHT server\n"); - wprintw(self->window, " add : Add friend\n"); - wprintw(self->window, " status : Set your status\n"); - wprintw(self->window, " nick : Set your nickname\n"); - wprintw(self->window, " accept : Accept friend request\n"); - wprintw(self->window, " myid : Print your ID\n"); - wprintw(self->window, " quit/exit : Exit program\n"); - wprintw(self->window, " help : Print this message again\n"); - wprintw(self->window, " clear : Clear this window\n"); + wprintw(self->window, " connect : Connect to DHT server\n"); + wprintw(self->window, " add : Add friend\n"); + wprintw(self->window, " status : Set your status\n"); + wprintw(self->window, " nick : Set your nickname\n"); + wprintw(self->window, " accept : Accept friend request\n"); + wprintw(self->window, " myid : Print your ID\n"); + wprintw(self->window, " quit/exit : Exit program\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, "TIP: Use the TAB key to navigate through the tabs.\n\n"); From 79a731991faf1e0a8ecc5a20c7e624fdeb0c419d Mon Sep 17 00:00:00 2001 From: Nominate Date: Tue, 6 Aug 2013 11:20:11 +0100 Subject: [PATCH 070/172] Update prompt.c --- prompt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prompt.c b/prompt.c index 742b35f..3006b8a 100644 --- a/prompt.c +++ b/prompt.c @@ -44,12 +44,12 @@ static int prompt_buf_pos=0; static void execute(ToxWindow* self, char* u_cmd) { int i; int newlines = 0; - char cmd[256] = {0}; + char cmd[256] = {0}; for(i = 0; i < strlen(prompt_buf); i++) { if (u_cmd[i] == '\n') - ++newlines; - else + ++newlines; + else cmd[i - newlines] = u_cmd[i]; } @@ -276,7 +276,7 @@ static void execute(ToxWindow* self, char* u_cmd) { static void prompt_onKey(ToxWindow* self, int key) { // PRINTABLE characters: Add to line. if(isprint(key)) { - if (prompt_buf_pos == 255){ + if (prompt_buf_pos == (sizeof(prompt_buf) - 1)){ wprintw(self->window, "\nToo Long.\n"); prompt_buf_pos = 0; prompt_buf[0] = 0; From c9546b38d40b962e21e67173590a753646e2e28c Mon Sep 17 00:00:00 2001 From: Nominate Date: Tue, 6 Aug 2013 11:50:10 +0100 Subject: [PATCH 071/172] Fixed formatting --- prompt.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/prompt.c b/prompt.c index 3006b8a..a53c163 100644 --- a/prompt.c +++ b/prompt.c @@ -43,8 +43,8 @@ static int prompt_buf_pos=0; static void execute(ToxWindow* self, char* u_cmd) { int i; - int newlines = 0; - char cmd[256] = {0}; + int newlines = 0; + char cmd[256] = {0}; for(i = 0; i < strlen(prompt_buf); i++) { if (u_cmd[i] == '\n') @@ -331,15 +331,15 @@ static void print_usage(ToxWindow* self) { wprintw(self->window, "Commands:\n"); wattroff(self->window, A_BOLD); - wprintw(self->window, " connect : Connect to DHT server\n"); - wprintw(self->window, " add : Add friend\n"); - wprintw(self->window, " status : Set your status\n"); - wprintw(self->window, " nick : Set your nickname\n"); - wprintw(self->window, " accept : Accept friend request\n"); - wprintw(self->window, " myid : Print your ID\n"); - wprintw(self->window, " quit/exit : Exit program\n"); - wprintw(self->window, " help : Print this message again\n"); - wprintw(self->window, " clear : Clear this window\n"); + wprintw(self->window, " connect : Connect to DHT server\n"); + wprintw(self->window, " add : Add friend\n"); + wprintw(self->window, " status : Set your status\n"); + wprintw(self->window, " nick : Set your nickname\n"); + wprintw(self->window, " accept : Accept friend request\n"); + wprintw(self->window, " myid : Print your ID\n"); + wprintw(self->window, " quit/exit : Exit program\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, "TIP: Use the TAB key to navigate through the tabs.\n\n"); From 5fd1a658bcb786a29a877ab1258e90c9d8916e98 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 6 Aug 2013 18:27:51 -0400 Subject: [PATCH 072/172] code format/clean up --- chat.c | 110 ++++++++++---------- friendlist.c | 104 +++++++++---------- main.c | 217 +++++++++++++++++++------------------- prompt.c | 288 +++++++++++++++++++++++---------------------------- 4 files changed, 337 insertions(+), 382 deletions(-) diff --git a/chat.c b/chat.c index 7262e72..20c0162 100644 --- a/chat.c +++ b/chat.c @@ -16,38 +16,34 @@ typedef struct { int friendnum; - char line[256]; size_t pos; - WINDOW* history; WINDOW* linewin; - } ChatContext; -extern int w_active; -extern void del_window(ToxWindow *w, int f_num); -extern void fix_name(uint8_t* name); -void print_help(ChatContext* self); -void execute(ToxWindow* self, ChatContext* ctx, char* cmd); +extern int active_window; -static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) { - ChatContext* ctx = (ChatContext*) self->x; +extern void del_window(ToxWindow *w, int f_num); +extern void fix_name(uint8_t *name); +void print_help(ChatContext *self); +void execute(ToxWindow *self, ChatContext *ctx, char *cmd); + +static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len) +{ + ChatContext *ctx = (ChatContext*) self->x; uint8_t nick[MAX_NAME_LENGTH] = {0}; - time_t now; time(&now); struct tm * timeinfo; timeinfo = localtime(&now); - if(ctx->friendnum != num) + if (ctx->friendnum != num) return; getname(num, (uint8_t*) &nick); - msg[len-1] = '\0'; nick[MAX_NAME_LENGTH-1] = '\0'; - fix_name(msg); fix_name(nick); @@ -64,15 +60,14 @@ static void chat_onMessage(ToxWindow* self, int num, uint8_t* msg, uint16_t len) flash(); } -static void chat_onNickChange(ToxWindow* self, int num, uint8_t* nick, uint16_t len) { - ChatContext* ctx = (ChatContext*) self->x; - - if(ctx->friendnum != num) +static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len) +{ + ChatContext *ctx = (ChatContext*) self->x; + if (ctx->friendnum != num) return; nick[len-1] = '\0'; fix_name(nick); - snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num); wattron(ctx->history, COLOR_PAIR(3)); @@ -80,7 +75,8 @@ static void chat_onNickChange(ToxWindow* self, int num, uint8_t* nick, uint16_t wattroff(ctx->history, COLOR_PAIR(3)); } -static void chat_onStatusChange(ToxWindow* self, int num, uint8_t* status, uint16_t len) { +static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint16_t len) +{ } @@ -89,35 +85,33 @@ int string_is_empty(char *string) { int rc = 0; char *copy = strdup(string); - rc = ((strtok(copy, " ") == NULL) ? 1:0); free(copy); - return rc; } -static void chat_onKey(ToxWindow* self, int key) { - ChatContext* ctx = (ChatContext*) self->x; - +static void chat_onKey(ToxWindow *self, int key) +{ + ChatContext *ctx = (ChatContext*) self->x; time_t now; time(&now); struct tm * timeinfo; timeinfo = localtime(&now); - /* PRINTABLE characters: Add to line */ - if(isprint(key)) { - if(ctx->pos != sizeof(ctx->line)-1) { + /* Add printable characters to line */ + if (isprint(key)) { + if (ctx->pos != sizeof(ctx->line)-1) { ctx->line[ctx->pos++] = key; ctx->line[ctx->pos] = '\0'; } } /* RETURN key: Execute command or print line */ - else if(key == '\n') { + else if (key == '\n') { if (ctx->line[0] == '/') execute(self, ctx, ctx->line); else { - if(!string_is_empty(ctx->line)) { + if (!string_is_empty(ctx->line)) { /* make sure the string has at least non-space character */ wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); @@ -127,7 +121,7 @@ static void chat_onKey(ToxWindow* self, int key) { wattroff(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "%s\n", ctx->line); } - if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) { + if (m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) { wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Failed to send message.\n"); wattroff(ctx->history, COLOR_PAIR(3)); @@ -138,29 +132,32 @@ static void chat_onKey(ToxWindow* self, int key) { } /* BACKSPACE key: Remove one character from line */ - else if(key == 0x107 || key == 0x8 || key == 0x7f) { - if(ctx->pos != 0) { + else if (key == 0x107 || key == 0x8 || key == 0x7f) { + if (ctx->pos != 0) { ctx->line[--ctx->pos] = '\0'; } } } -void execute(ToxWindow* self, ChatContext* ctx, char* cmd) +void execute(ToxWindow *self, ChatContext *ctx, char *cmd) { if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { wclear(self->window); wclear(ctx->history); } + else if (!strcmp(cmd, "/help") || !strcmp(cmd, "/h")) print_help(ctx); + else if (!strcmp(cmd, "/quit") || !strcmp(cmd, "/exit") || !strcmp(cmd, "/q")) { endwin(); exit(0); } + else if (!strncmp(cmd, "/status ", strlen("/status "))) { - char* msg; + char *msg; msg = strchr(cmd, ' '); - if(msg == NULL) { + if (msg == NULL) { wprintw(ctx->history, "Invalid syntax.\n"); return; } @@ -168,10 +165,11 @@ void execute(ToxWindow* self, ChatContext* ctx, char* cmd) m_set_userstatus(USERSTATUS_KIND_RETAIN, (uint8_t*) msg, strlen(msg)+1); wprintw(ctx->history, "Status set to: %s\n", msg); } + else if (!strncmp(cmd, "/nick ", strlen("/nick "))) { - char* nick; + char *nick; nick = strchr(cmd, ' '); - if(nick == NULL) { + if (nick == NULL) { wprintw(ctx->history, "Invalid syntax.\n"); return; } @@ -179,7 +177,8 @@ void execute(ToxWindow* self, ChatContext* ctx, char* cmd) setname((uint8_t*) nick, strlen(nick)+1); wprintw(ctx->history, "Nickname set to: %s\n", nick); } - else if(!strcmp(cmd, "/myid")) { + + else if (!strcmp(cmd, "/myid")) { char id[32*2 + 1] = {0}; int i; for (i = 0; i < 32; i++) { @@ -189,48 +188,46 @@ void execute(ToxWindow* self, ChatContext* ctx, char* cmd) } wprintw(ctx->history, "Your ID: %s\n", id); } + else if (strcmp(ctx->line, "/close") == 0) { - w_active = 0; // Go to prompt screen + active_window = 0; // Go to prompt screen int f_num = ctx->friendnum; delwin(ctx->linewin); del_window(self, f_num); } + else wprintw(ctx->history, "Invalid command.\n"); } -static void chat_onDraw(ToxWindow* self) { +static void chat_onDraw(ToxWindow *self) +{ curs_set(1); int x, y; - ChatContext* ctx = (ChatContext*) self->x; - + ChatContext *ctx = (ChatContext*) self->x; getmaxyx(self->window, y, x); - (void) x; - if(y < 3) - return; + if (y < 3) return; wclear(ctx->linewin); mvwhline(ctx->linewin, 0, 0, '_', COLS); mvwprintw(self->window, y-1, 0, "%s\n", ctx->line); - wrefresh(self->window); } -static void chat_onInit(ToxWindow* self) { +static void chat_onInit(ToxWindow *self) +{ int x, y; - ChatContext* ctx = (ChatContext*) self->x; - + ChatContext *ctx = (ChatContext*) self->x; getmaxyx(self->window, y, x); - ctx->history = subwin(self->window, y - 4, x, 0, 0); scrollok(ctx->history, 1); - ctx->linewin = subwin(self->window, 2, x, y - 3, 0); print_help(ctx); } -void print_help(ChatContext* self) { +void print_help(ChatContext *self) +{ wattron(self->history, COLOR_PAIR(2) | A_BOLD); wprintw(self->history, "Commands:\n"); wattroff(self->history, A_BOLD); @@ -246,9 +243,9 @@ void print_help(ChatContext* self) { wattroff(self->history, COLOR_PAIR(2)); } -ToxWindow new_chat(int friendnum) { +ToxWindow new_chat(int friendnum) +{ ToxWindow ret; - memset(&ret, 0, sizeof(ret)); ret.onKey = &chat_onKey; @@ -264,9 +261,8 @@ ToxWindow new_chat(int friendnum) { snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum); - ChatContext* x = calloc(1, sizeof(ChatContext)); + ChatContext *x = calloc(1, sizeof(ChatContext)); x->friendnum = friendnum; - ret.x = (void*) x; return ret; } diff --git a/friendlist.c b/friendlist.c index 94e8fb4..f03914e 100644 --- a/friendlist.c +++ b/friendlist.c @@ -15,60 +15,56 @@ extern char WINDOW_STATUS[TOXWINDOWS_MAX_NUM]; extern int add_window(ToxWindow w, int n); extern ToxWindow new_chat(int friendnum); -extern int w_active; + +extern int active_window; typedef struct { uint8_t name[MAX_NAME_LENGTH]; uint8_t status[MAX_USERSTATUS_LENGTH]; - int num; - int chatwin; + int num; + int chatwin; } friend_t; static friend_t friends[MAX_FRIENDS_NUM]; static int num_friends = 0; static int num_selected = 0; - -void fix_name(uint8_t* name) { - - // Remove all non alphanumeric characters. - uint8_t* p = name; - uint8_t* q = name; - +void fix_name(uint8_t *name) +{ + /* Remove all non alphanumeric characters */ + uint8_t *p = name; + uint8_t *q = name; while(*p != 0) { - if(isprint(*p)) { + if (isprint(*p)) *q++ = *p; - } - p++; } - *q = 0; } -void friendlist_onMessage(ToxWindow* self, int num, uint8_t* str, uint16_t len) { - - if(num >= num_friends) +void friendlist_onMessage(ToxWindow *self, int num, uint8_t *str, uint16_t len) +{ + if (num >= num_friends) return; - if(friends[num].chatwin == -1) { + if (friends[num].chatwin == -1) { friends[num].chatwin = num; int i; /* Find first open slot to hold chat window */ - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { if (WINDOW_STATUS[i] == -1) { WINDOW_STATUS[i] = num; add_window(new_chat(num), i); - w_active = i; + active_window = i; break; } } } } -void friendlist_onNickChange(ToxWindow* self, int num, uint8_t* str, uint16_t len) { - - if(len >= MAX_NAME_LENGTH || num >= num_friends) +void friendlist_onNickChange(ToxWindow *self, int num, uint8_t *str, uint16_t len) +{ + if (len >= MAX_NAME_LENGTH || num >= num_friends) return; memcpy((char*) &friends[num].name, (char*) str, len); @@ -76,9 +72,9 @@ void friendlist_onNickChange(ToxWindow* self, int num, uint8_t* str, uint16_t le fix_name(friends[num].name); } -void friendlist_onStatusChange(ToxWindow* self, int num, uint8_t* str, uint16_t len) { - - if(len >= MAX_USERSTATUS_LENGTH || num >= num_friends) +void friendlist_onStatusChange(ToxWindow *self, int num, uint8_t *str, uint16_t len) +{ + if (len >= MAX_USERSTATUS_LENGTH || num >= num_friends) return; memcpy((char*) &friends[num].status, (char*) str, len); @@ -86,9 +82,9 @@ void friendlist_onStatusChange(ToxWindow* self, int num, uint8_t* str, uint16_t fix_name(friends[num].status); } -int friendlist_onFriendAdded(int num) { - - if(num_friends == MAX_FRIENDS_NUM) +int friendlist_onFriendAdded(int num) +{ + if (num_friends == MAX_FRIENDS_NUM) return -1; friends[num_friends].num = num; @@ -99,34 +95,34 @@ int friendlist_onFriendAdded(int num) { return 0; } -static void friendlist_onKey(ToxWindow* self, int key) { - if(key == KEY_UP) { - num_selected--; - if (num_selected < 0) +static void friendlist_onKey(ToxWindow *self, int key) +{ + if (key == KEY_UP) { + if (--num_selected < 0) num_selected = num_friends-1; } - else if(key == KEY_DOWN) { - if(num_friends != 0) + else if (key == KEY_DOWN) { + if (num_friends != 0) num_selected = (num_selected+1) % num_friends; } - else if(key == '\n') { + else if (key == '\n') { /* Jump to chat window if already open */ if (friends[num_selected].chatwin != -1) { int i; - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { if (WINDOW_STATUS[i] == num_selected) { - w_active = i; + active_window = i; break; } } }else { int i; - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { if (WINDOW_STATUS[i] == -1) { WINDOW_STATUS[i] = num_selected; friends[num_selected].chatwin = num_selected; add_window(new_chat(num_selected), i); - w_active = i; + active_window = i; break; } } @@ -134,13 +130,11 @@ static void friendlist_onKey(ToxWindow* self, int key) { } } -static void friendlist_onDraw(ToxWindow* self) { +static void friendlist_onDraw(ToxWindow *self) +{ curs_set(0); - size_t i; - werase(self->window); - - if(num_friends == 0) { + if (num_friends == 0) { wprintw(self->window, "Empty. Add some friends! :-)\n"); } else { @@ -150,12 +144,11 @@ static void friendlist_onDraw(ToxWindow* self) { } wprintw(self->window, "\n"); - - for(i=0; iwindow, COLOR_PAIR(3)); + int i; + for (i = 0; i < num_friends; ++i) { + if (i == num_selected) wattron(self->window, COLOR_PAIR(3)); wprintw(self->window, " [#%d] ", friends[i].num); - if(i == num_selected) wattroff(self->window, COLOR_PAIR(3)); + if (i == num_selected) wattroff(self->window, COLOR_PAIR(3)); attron(A_BOLD); wprintw(self->window, "%s ", friends[i].name); @@ -163,22 +156,21 @@ static void friendlist_onDraw(ToxWindow* self) { wprintw(self->window, "(%s)\n", friends[i].status); } - wrefresh(self->window); } -void disable_chatwin(int f_num) { +void disable_chatwin(int f_num) +{ friends[f_num].chatwin = -1; } -static void friendlist_onInit(ToxWindow* self) { +static void friendlist_onInit(ToxWindow *self) +{ } - ToxWindow new_friendlist() { ToxWindow ret; - memset(&ret, 0, sizeof(ret)); ret.onKey = &friendlist_onKey; @@ -187,7 +179,7 @@ ToxWindow new_friendlist() { ret.onMessage = &friendlist_onMessage; ret.onNickChange = &friendlist_onNickChange; ret.onStatusChange = &friendlist_onStatusChange; - strcpy(ret.title, "[friends]"); + strcpy(ret.title, "[friends]"); return ret; } diff --git a/main.c b/main.c index 19a0b95..1ba8b6c 100644 --- a/main.c +++ b/main.c @@ -18,106 +18,108 @@ extern ToxWindow new_friendlist(); extern int friendlist_onFriendAdded(int num); extern void disable_chatwin(int f_num); -extern int add_req(uint8_t* public_key); // XXX +extern int add_req(uint8_t *public_key); // XXX + +/* Holds status of chat windows */ +char WINDOW_STATUS[MAX_WINDOW_SLOTS]; -char WINDOW_STATUS[MAX_WINDOW_SLOTS]; // Holds status of chat windows static ToxWindow windows[MAX_WINDOW_SLOTS]; -int w_num; -int w_active; static ToxWindow* prompt; -// CALLBACKS START -void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) { - size_t i; - int n = add_req(public_key); +int w_num; +int active_window; +/* CALLBACKS START */ +void on_request(uint8_t *public_key, uint8_t *data, uint16_t length) +{ + int n = add_req(public_key); wprintw(prompt->window, "\nFriend request from:\n"); - for(i=0; i<32; i++) { + int i; + for (i = 0; i < 32; ++i) { wprintw(prompt->window, "%02x", public_key[i] & 0xff); } + wprintw(prompt->window, "\n"); - wprintw(prompt->window, "Use \"accept %d\" to accept it.\n", n); - - for(i=0; iwindow, "\n(message) %d: %s\n", friendnumber, string); - - for(i=0; iwindow, "\n(nickchange) %d: %s!\n", friendnumber, string); - - for(i=0; iwindow, "\n(statuschange) %d: %s\n", friendnumber, string); - - for(i=0; i= TOXWINDOWS_MAX_NUM) +int add_window(ToxWindow w, int n) +{ + if (w_num >= TOXWINDOWS_MAX_NUM) return -1; - if(LINES < 2) + if (LINES < 2) return -1; w.window = newwin(LINES - 2, COLS, 0, 0); - if(w.window == NULL) + if (w.window == NULL) return -1; windows[n] = w; @@ -143,10 +146,11 @@ int add_window(ToxWindow w, int n) { } /* Deletes window w and cleans up */ -void del_window(ToxWindow *w, int f_num) { +void del_window(ToxWindow *w, int f_num) +{ delwin(w->window); int i; - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { if (WINDOW_STATUS[i] == f_num) { WINDOW_STATUS[i] = -1; disable_chatwin(f_num); @@ -157,11 +161,12 @@ void del_window(ToxWindow *w, int f_num) { refresh(); } -static void init_windows() { +static void init_windows() +{ w_num = 0; int n_prompt = 0; int n_friendslist = 1; - if(add_window(new_prompt(), n_prompt) == -1 + if (add_window(new_prompt(), n_prompt) == -1 || add_window(new_friendlist(), n_friendslist) == -1) { fprintf(stderr, "add_window() failed.\n"); endwin(); @@ -170,88 +175,79 @@ static void init_windows() { prompt = &windows[n_prompt]; } -static void do_tox() { +static void do_tox() +{ static bool dht_on = false; - - if(!dht_on && DHT_isconnected()) { + if (!dht_on && DHT_isconnected()) { dht_on = true; wprintw(prompt->window, "\nDHT connected!\n"); } - else if(dht_on && !DHT_isconnected()) { + else if (dht_on && !DHT_isconnected()) { dht_on = false; wprintw(prompt->window, "\nDHT disconnected!\n"); } - doMessenger(); } -static void load_data(char *path) { - FILE* fd; +static void load_data(char *path) +{ + FILE *fd; size_t len; - uint8_t* buf; + uint8_t *buf; - if((fd = fopen(path, "r")) != NULL) { + if ((fd = fopen(path, "r")) != NULL) { fseek(fd, 0, SEEK_END); len = ftell(fd); fseek(fd, 0, SEEK_SET); buf = malloc(len); - - if(buf == NULL) { + if (buf == NULL) { fprintf(stderr, "malloc() failed.\n"); - fclose(fd); endwin(); exit(1); } - - if(fread(buf, len, 1, fd) != 1){ + if (fread(buf, len, 1, fd) != 1){ fprintf(stderr, "fread() failed.\n"); - free(buf); fclose(fd); endwin(); exit(1); } - Messenger_load(buf, len); } else { len = Messenger_size(); buf = malloc(len); - - if(buf == NULL) { + if (buf == NULL) { fprintf(stderr, "malloc() failed.\n"); endwin(); exit(1); } - Messenger_save(buf); fd = fopen(path, "w"); - if(fd == NULL) { + if (fd == NULL) { fprintf(stderr, "fopen() failed.\n"); - free(buf); endwin(); exit(1); } - if(fwrite(buf, len, 1, fd) != 1){ + if (fwrite(buf, len, 1, fd) != 1){ fprintf(stderr, "fwrite() failed.\n"); - free(buf); fclose(fd); endwin(); exit(1); } } - free(buf); fclose(fd); } -static void draw_bar() { +static void draw_bar() +{ static int odd = 0; attron(COLOR_PAIR(4)); @@ -265,21 +261,21 @@ static void draw_bar() { attroff(COLOR_PAIR(4) | A_BOLD); int i; - for (i = 0; i < (MAX_WINDOW_SLOTS-1); i++) { + for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) { if (WINDOW_STATUS[i] != -1) { - if (i == w_active) + if (i == active_window) attron(A_BOLD); odd = (odd+1) % 10; - if(windows[i].blink && (odd < 5)) { + if (windows[i].blink && (odd < 5)) { attron(COLOR_PAIR(3)); } printw(" %s", windows[i].title); - if(windows[i].blink && (odd < 5)) { + if (windows[i].blink && (odd < 5)) { attron(COLOR_PAIR(3)); } - if(i == w_active) { + if (i == active_window) { attroff(A_BOLD); } } @@ -287,35 +283,37 @@ static void draw_bar() { refresh(); } -void prepare_window(WINDOW* w) { +void prepare_window(WINDOW *w) +{ mvwin(w, 0, 0); wresize(w, LINES-2, COLS); } /* Shows next window when tab or back-tab is pressed */ -void set_active_window(int ch) { +void set_active_window(int ch) +{ int f_inf = 0; int max = MAX_WINDOW_SLOTS-1; if (ch == '\t') { - int i = (w_active + 1) % max; + int i = (active_window + 1) % max; while (true) { if (WINDOW_STATUS[i] != -1) { - w_active = i; + active_window = i; return; } i = (i + 1) % max; - if (f_inf++ > max) { // infinite loop check + if (f_inf++ > max) { // infinite loop check endwin(); clear(); exit(2); } } }else { - int i = w_active - 1; + int i = active_window - 1; if (i < 0) i = max; while (true) { if (WINDOW_STATUS[i] != -1) { - w_active = i; + active_window = i; return; } if (--i < 0) i = max; @@ -328,26 +326,26 @@ void set_active_window(int ch) { } } -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) +{ int ch; - int i = 0; int f_flag = 0; char *filename = "data"; ToxWindow* a; - for(i = 0; i < argc; i++) { - if (argv[i] == NULL){ - break; - } else if(argv[i][0] == '-') { - if(argv[i][1] == 'f') { - if(argv[i + 1] != NULL) - filename = argv[i + 1]; - else { - f_flag = -1; - } - } - } + int i = 0; + for (i = 0; i < argc; ++i) { + if (argv[i] == NULL) + break; + else if (argv[i][0] == '-') { + if (argv[i][1] == 'f') { + if (argv[i + 1] != NULL) + filename = argv[i + 1]; + else + f_flag = -1; + } } + } init_term(); init_tox(); @@ -355,7 +353,7 @@ int main(int argc, char* argv[]) { init_windows(); init_window_status(); - if(f_flag == -1) { + if (f_flag == -1) { attron(COLOR_PAIR(3) | A_BOLD); wprintw(prompt->window, "You passed '-f' without giving an argument!\n" "defaulting to 'data' for a keyfile...\n"); @@ -363,24 +361,21 @@ int main(int argc, char* argv[]) { } while(true) { - // Update tox. + /* Update tox */ do_tox(); - // Draw. - a = &windows[w_active]; + /* Draw */ + a = &windows[active_window]; prepare_window(a->window); a->blink = false; draw_bar(); a->onDraw(a); - // Handle input. + /* Handle input */ ch = getch(); - if(ch == '\t' || ch == KEY_BTAB) + if (ch == '\t' || ch == KEY_BTAB) set_active_window(ch); - else if(ch != ERR) { - a->onKey(a, ch); - } - else if(ch != ERR) { + else if (ch != ERR) { a->onKey(a, ch); } } diff --git a/prompt.c b/prompt.c index 20f6b48..89c87d8 100644 --- a/prompt.c +++ b/prompt.c @@ -16,83 +16,78 @@ uint8_t pending_requests[256][CLIENT_ID_SIZE]; // XXX uint8_t num_requests=0; // XXX extern void on_friendadded(int friendnumber); -static void print_usage(ToxWindow* self); +static void print_usage(ToxWindow *self); +static char prompt_buf[256] = {0}; +static int prompt_buf_pos = 0; // XXX: -int add_req(uint8_t* public_key) { +int add_req(uint8_t *public_key) +{ memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE); ++num_requests; - return num_requests-1; } // XXX: FIX -unsigned char * hex_string_to_bin(char hex_string[]) +unsigned char *hex_string_to_bin(char hex_string[]) { - size_t len = strlen(hex_string); - unsigned char *val = malloc(len); - char *pos = hex_string; - int i; - for(i = 0; i < len; ++i, pos+=2) - sscanf(pos,"%2hhx",&val[i]); - return val; + size_t len = strlen(hex_string); + unsigned char *val = malloc(len); + char *pos = hex_string; + int i; + for (i = 0; i < len; ++i, pos+=2) + sscanf(pos,"%2hhx",&val[i]); + return val; } -static char prompt_buf[256] = {0}; -static int prompt_buf_pos=0; - -static void execute(ToxWindow* self, char* u_cmd) { - int i; - int newlines = 0; - char cmd[256] = {0}; - for(i = 0; i < strlen(prompt_buf); i++) - { +static void execute(ToxWindow *self, char *u_cmd) +{ + int newlines = 0; + char cmd[256] = {0}; + int i; + for (i = 0; i < strlen(prompt_buf); ++i) { if (u_cmd[i] == '\n') - ++newlines; - else - cmd[i - newlines] = u_cmd[i]; - } + ++newlines; + else + cmd[i - newlines] = u_cmd[i]; + } - if(!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) { + if (!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) { endwin(); exit(0); } - else if(!strncmp(cmd, "connect ", strlen("connect "))) { - char* ip; - char* port; - char* key; - IP_Port dht; - ip = strchr(cmd, ' '); - if(ip == NULL) { + else if (!strncmp(cmd, "connect ", strlen("connect "))) { + IP_Port dht; + char *ip = strchr(cmd, ' '); + if (ip == NULL) { wprintw(self->window, "Invalid syntax.\n"); return; } ip++; - port = strchr(ip, ' '); - if(port == NULL) { + char *port = strchr(ip, ' '); + if (port == NULL) { wprintw(self->window, "Invalid syntax.\n"); return; } port[0] = 0; port++; - key = strchr(port, ' '); - if(key == NULL) { + char *key = strchr(port, ' '); + if (key == NULL) { wprintw(self->window, "Invalid syntax.\n"); return; } key[0] = 0; key++; - if(atoi(port) == 0) { + if (atoi(port) == 0) { wprintw(self->window, "Invalid syntax.\n"); return; } dht.port = htons(atoi(port)); - uint32_t resolved_address = resolve_addr(ip); if (resolved_address == 0) { return; @@ -103,49 +98,39 @@ static void execute(ToxWindow* self, char* u_cmd) { DHT_bootstrap(dht, binary_string); free(binary_string); } - else if(!strncmp(cmd, "add ", strlen("add "))) { + + else if (!strncmp(cmd, "add ", strlen("add "))) { uint8_t id_bin[32]; - size_t i; char xx[3]; uint32_t x; - - char* id; - char* msg; - int num; - - id = strchr(cmd, ' '); - if(id == NULL) { + char *id = strchr(cmd, ' '); + if (id == NULL) { wprintw(self->window, "Invalid syntax.\n"); return; } id++; - - msg = strchr(id, ' '); - if(msg != NULL) { + char *msg = strchr(id, ' '); + if (msg != NULL) { msg[0] = 0; msg++; } else msg = ""; - - if(strlen(id) != 2*32) { + if (strlen(id) != 2*32) { wprintw(self->window, "Invalid ID length.\n"); return; } - - for(i=0; i<32; i++) { + int i; + for (i = 0; i < 32; ++i) { xx[0] = id[2*i]; xx[1] = id[2*i+1]; xx[2] = '\0'; - - if(sscanf(xx, "%02x", &x) != 1) { + if (sscanf(xx, "%02x", &x) != 1) { wprintw(self->window, "Invalid ID.\n"); return; } - id_bin[i] = x; } - - num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); + int num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); switch (num) { case -1: wprintw(self->window, "Message is too long.\n"); @@ -168,178 +153,167 @@ static void execute(ToxWindow* self, char* u_cmd) { break; } } - else if(!strcmp(cmd, "clear")) { - wclear(self->window); - } - else if(!strcmp(cmd, "help")) { - wclear(self->window); - print_usage(self); - } - else if(!strncmp(cmd, "status ", strlen("status "))) { - char* msg; - msg = strchr(cmd, ' '); - if(msg == NULL) { + else if (!strcmp(cmd, "clear")) { + wclear(self->window); + } + + else if (!strcmp(cmd, "help")) { + wclear(self->window); + print_usage(self); + } + + else if (!strncmp(cmd, "status ", strlen("status "))) { + char *msg = strchr(cmd, ' '); + if (msg == NULL) { wprintw(self->window, "Invalid syntax.\n"); return; } msg++; - m_set_userstatus(USERSTATUS_KIND_RETAIN, (uint8_t*) msg, strlen(msg)+1); wprintw(self->window, "Status set to: %s\n", msg); } - else if(!strncmp(cmd, "nick ", strlen("nick "))) { - char* nick; - nick = strchr(cmd, ' '); - if(nick == NULL) { + else if (!strncmp(cmd, "nick ", strlen("nick "))) { + char *nick = strchr(cmd, ' '); + if (nick == NULL) { wprintw(self->window, "Invalid syntax.\n"); return; } nick++; - setname((uint8_t*) nick, strlen(nick)+1); wprintw(self->window, "Nickname set to: %s\n", nick); } - else if(!strcmp(cmd, "myid")) { + + else if (!strcmp(cmd, "myid")) { char id[32*2 + 1] = {0}; size_t i; - - for(i=0; i<32; i++) { + for (i = 0; i < 32; ++i) { char xx[3]; snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); strcat(id, xx); } - wprintw(self->window, "Your ID: %s\n", id); } - else if(!strncmp(cmd, "accept ", strlen("accept "))) { - char* id; - int num; - id = strchr(cmd, ' '); - if(id == NULL) { + else if (!strncmp(cmd, "accept ", strlen("accept "))) { + char *id = strchr(cmd, ' '); + if (id == NULL) { wprintw(self->window, "Invalid syntax.\n"); return; } id++; - num = atoi(id); - if(num >= num_requests) { + int num = atoi(id); + if (num >= num_requests) { wprintw(self->window, "Invalid syntax.\n"); return; } num = m_addfriend_norequest(pending_requests[num]); - - if(num == -1) { + if (num == -1) wprintw(self->window, "Failed to add friend.\n"); - } else { wprintw(self->window, "Friend accepted as: %d.\n", num); on_friendadded(num); } } - else if(!strncmp(cmd, "msg ", strlen("msg "))) { - char* id; - char* msg; - id = strchr(cmd, ' '); - - if(id == NULL) { + else if (!strncmp(cmd, "msg ", strlen("msg "))) { + char *id = strchr(cmd, ' '); + if (id == NULL) { wprintw(self->window, "Invalid syntax.\n"); return; } - id++; - - msg = strchr(id, ' '); - if(msg == NULL) { + char *msg = strchr(++id, ' '); + if (msg == NULL) { wprintw(self->window, "Invalid syntax.\n"); return; } msg[0] = 0; msg++; - - if(m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) < 0) { + if (m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) < 0) wprintw(self->window, "Error occurred while sending message.\n"); - } - else { + else wprintw(self->window, "Message successfully sent.\n"); - } } - else { + else wprintw(self->window, "Invalid command.\n"); - } } -static void prompt_onKey(ToxWindow* self, int key) { - // PRINTABLE characters: Add to line. - if(isprint(key)) { - if (prompt_buf_pos == (sizeof(prompt_buf) - 1)){ - wprintw(self->window, "\nToo Long.\n"); - prompt_buf_pos = 0; - prompt_buf[0] = 0; - } - else if(!(prompt_buf_pos == 0) && (prompt_buf_pos < COLS) && (prompt_buf_pos % (COLS - 3) == 0)) { - prompt_buf[prompt_buf_pos++] = '\n'; +static void prompt_onKey(ToxWindow *self, int key) +{ + /* Add printable characters to line */ + if (isprint(key)) { + if (prompt_buf_pos == (sizeof(prompt_buf) - 1)) { + wprintw(self->window, "\nToo Long.\n"); + prompt_buf_pos = 0; + prompt_buf[0] = 0; } - else if(!(prompt_buf_pos == 0) && (prompt_buf_pos > COLS) && ((prompt_buf_pos - (COLS - 3)) % (COLS) == 0)) { - prompt_buf[prompt_buf_pos++] = '\n'; + else if (!(prompt_buf_pos == 0) && (prompt_buf_pos < COLS) + && (prompt_buf_pos % (COLS - 3) == 0)) { + prompt_buf[prompt_buf_pos++] = '\n'; + } + else if (!(prompt_buf_pos == 0) && (prompt_buf_pos > COLS) + && ((prompt_buf_pos - (COLS - 3)) % (COLS) == 0)) { + prompt_buf[prompt_buf_pos++] = '\n'; } prompt_buf[prompt_buf_pos++] = key; prompt_buf[prompt_buf_pos] = 0; } - // RETURN key: execute command. - else if(key == '\n') { + /* RETURN key: execute command */ + else if (key == '\n') { wprintw(self->window, "\n"); execute(self, prompt_buf); prompt_buf_pos = 0; prompt_buf[0] = 0; } - // BACKSPACE key: Remove one character from line. - else if(key == 0x107 || key == 0x8 || key == 0x7f) { - if(prompt_buf_pos != 0) { + /* BACKSPACE key: Remove one character from line */ + else if (key == 0x107 || key == 0x8 || key == 0x7f) { + if (prompt_buf_pos != 0) { prompt_buf[--prompt_buf_pos] = 0; } } } -static void prompt_onDraw(ToxWindow* self) { - curs_set(1); - int x, y; - getyx(self->window, y, x); - (void) x; - int i; - for (i = 0; i < (strlen(prompt_buf)); i++) - { - if ((prompt_buf[i] == '\n') && (y != 0)) - --y; - } - wattron(self->window, COLOR_PAIR(1)); - mvwprintw(self->window, y, 0, "# "); - wattroff(self->window, COLOR_PAIR(1)); - mvwprintw(self->window, y, 2, "%s", prompt_buf); - wclrtoeol(self->window); - wrefresh(self->window); +static void prompt_onDraw(ToxWindow *self) +{ + curs_set(1); + int x, y; + getyx(self->window, y, x); + (void) x; + int i; + for (i = 0; i < (strlen(prompt_buf)); ++i) { + if ((prompt_buf[i] == '\n') && (y != 0)) + --y; + } + + wattron(self->window, COLOR_PAIR(1)); + mvwprintw(self->window, y, 0, "# "); + wattroff(self->window, COLOR_PAIR(1)); + mvwprintw(self->window, y, 2, "%s", prompt_buf); + wclrtoeol(self->window); + wrefresh(self->window); } -static void print_usage(ToxWindow* self) { +static void print_usage(ToxWindow *self) +{ wattron(self->window, COLOR_PAIR(2) | A_BOLD); wprintw(self->window, "Commands:\n"); wattroff(self->window, A_BOLD); - - wprintw(self->window, " connect : Connect to DHT server\n"); - wprintw(self->window, " add : Add friend\n"); - wprintw(self->window, " status : Set your status\n"); - wprintw(self->window, " nick : Set your nickname\n"); - wprintw(self->window, " accept : Accept friend request\n"); - wprintw(self->window, " myid : Print your ID\n"); - wprintw(self->window, " quit/exit : Exit program\n"); - wprintw(self->window, " help : Print this message again\n"); - wprintw(self->window, " clear : Clear this window\n"); + wprintw(self->window, " connect : Connect to DHT server\n"); + wprintw(self->window, " add : Add friend\n"); + wprintw(self->window, " status : Set your status\n"); + wprintw(self->window, " nick : Set your nickname\n"); + wprintw(self->window, " accept : Accept friend request\n"); + wprintw(self->window, " myid : Print your ID\n"); + wprintw(self->window, " quit/exit : Exit program\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, "TIP: Use the TAB key to navigate through the tabs.\n\n"); wattroff(self->window, A_BOLD); @@ -347,22 +321,20 @@ static void print_usage(ToxWindow* self) { wattroff(self->window, COLOR_PAIR(2)); } -static void prompt_onInit(ToxWindow* self) { +static void prompt_onInit(ToxWindow *self) +{ scrollok(self->window, 1); - print_usage(self); wclrtoeol(self->window); } -ToxWindow new_prompt() { +ToxWindow new_prompt() +{ ToxWindow ret; - memset(&ret, 0, sizeof(ret)); - ret.onKey = &prompt_onKey; ret.onDraw = &prompt_onDraw; ret.onInit = &prompt_onInit; strcpy(ret.title, "[prompt]"); - return ret; } From 78a37829c5fc193343e3e5d7d657bd79f6af8f8e Mon Sep 17 00:00:00 2001 From: ptrasd Date: Wed, 7 Aug 2013 02:10:46 -0400 Subject: [PATCH 073/172] testing/toxic/prompt.c: changed execute() to skip whitespace at start of command --- prompt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/prompt.c b/prompt.c index 89c87d8..a96c07b 100644 --- a/prompt.c +++ b/prompt.c @@ -52,6 +52,11 @@ static void execute(ToxWindow *self, char *u_cmd) cmd[i - newlines] = u_cmd[i]; } + int leading_spc = 0; + for (i = 0; i < 256 && isspace(cmd[i]); ++i) + leading_spc++; + memmove(cmd, cmd + leading_spc, 256 - leading_spc); + if (!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) { endwin(); exit(0); From 132576c28c4bb2f3528e85b2f6bcb5063891da30 Mon Sep 17 00:00:00 2001 From: ptrasd Date: Wed, 7 Aug 2013 02:25:20 -0400 Subject: [PATCH 074/172] testing/toxic/prompt.c: changed execute() to ignore whitespace at end of commands --- prompt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/prompt.c b/prompt.c index a96c07b..b0e21c6 100644 --- a/prompt.c +++ b/prompt.c @@ -57,6 +57,12 @@ static void execute(ToxWindow *self, char *u_cmd) leading_spc++; memmove(cmd, cmd + leading_spc, 256 - leading_spc); + int cmd_end = strlen(cmd); + while (cmd_end > 0 && cmd_end--) + if (!isspace(cmd[cmd_end])) + break; + cmd[cmd_end + 1] = '\0'; + if (!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) { endwin(); exit(0); From c6cbaf8d2eb6faecd556bc7407a6e1e54f995696 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 7 Aug 2013 02:34:55 -0400 Subject: [PATCH 075/172] Fixed two bugs --- main.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/main.c b/main.c index 1ba8b6c..4443065 100644 --- a/main.c +++ b/main.c @@ -249,6 +249,7 @@ static void load_data(char *path) static void draw_bar() { static int odd = 0; + int blinkrate = 30; attron(COLOR_PAIR(4)); mvhline(LINES - 2, 0, '_', COLS); @@ -266,14 +267,13 @@ static void draw_bar() if (i == active_window) attron(A_BOLD); - odd = (odd+1) % 10; - if (windows[i].blink && (odd < 5)) { + odd = (odd+1) % blinkrate; + if (windows[i].blink && (odd < (blinkrate/2))) { attron(COLOR_PAIR(3)); } - printw(" %s", windows[i].title); if (windows[i].blink && (odd < 5)) { - attron(COLOR_PAIR(3)); + attroff(COLOR_PAIR(3)); } if (i == active_window) { attroff(A_BOLD); @@ -375,9 +375,8 @@ int main(int argc, char *argv[]) ch = getch(); if (ch == '\t' || ch == KEY_BTAB) set_active_window(ch); - else if (ch != ERR) { + else if (ch != ERR) a->onKey(a, ch); - } } return 0; } From 4cc4d3b755c63f7a9efa584e82e7c4a06ebbbbbb Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 7 Aug 2013 02:52:56 -0400 Subject: [PATCH 076/172] forgot this --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index 4443065..8de7624 100644 --- a/main.c +++ b/main.c @@ -272,7 +272,7 @@ static void draw_bar() attron(COLOR_PAIR(3)); } printw(" %s", windows[i].title); - if (windows[i].blink && (odd < 5)) { + if (windows[i].blink && (odd < (blinkrate/2))) { attroff(COLOR_PAIR(3)); } if (i == active_window) { From 5614e73a17c0750e5de9c711e8ef0364a7fff33e Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Wed, 7 Aug 2013 00:24:37 -0700 Subject: [PATCH 077/172] Manually merged my earlier commits with upstream --- main.c | 3 ++- prompt.c | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 1ba8b6c..2bf1676 100644 --- a/main.c +++ b/main.c @@ -22,6 +22,7 @@ extern int add_req(uint8_t *public_key); // XXX /* Holds status of chat windows */ char WINDOW_STATUS[MAX_WINDOW_SLOTS]; +#define TOXICVER "0.1.0" //Will be moved to a -D flag later static ToxWindow windows[MAX_WINDOW_SLOTS]; static ToxWindow* prompt; @@ -257,7 +258,7 @@ static void draw_bar() move(LINES - 1, 0); attron(COLOR_PAIR(4) | A_BOLD); - printw(" TOXIC 1.0 |"); + printw(" TOXIC " TOXICVER " |"); attroff(COLOR_PAIR(4) | A_BOLD); int i; diff --git a/prompt.c b/prompt.c index 89c87d8..c4d7d2f 100644 --- a/prompt.c +++ b/prompt.c @@ -52,6 +52,13 @@ static void execute(ToxWindow *self, char *u_cmd) cmd[i - newlines] = u_cmd[i]; } + if (cmd[0] == '/') { + int i; + for (i = i1; i < strlen(cmd); i++) { //This doesn't work when it doesn't end with a space and another word + cmd[i - 1] = cmd[i]; //Still working on why + } + } + if (!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) { endwin(); exit(0); From 65694a06c4af6b3419567014c8d5acd4e98a1ef5 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Wed, 7 Aug 2013 00:26:21 -0700 Subject: [PATCH 078/172] Fixed flash killing beep --- chat.c | 1 - 1 file changed, 1 deletion(-) diff --git a/chat.c b/chat.c index 20c0162..344071f 100644 --- a/chat.c +++ b/chat.c @@ -57,7 +57,6 @@ static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len) self->blink = true; beep(); - flash(); } static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len) From 41238577e4d75abbc62a71d5a4ba7ac3efbcaeae Mon Sep 17 00:00:00 2001 From: jin-eld Date: Wed, 7 Aug 2013 10:14:10 +0300 Subject: [PATCH 079/172] Allow to set a specific userstatus type in toxic Use: status , where type is one of online away busy offline The message parameter is optional. To set only the status message, as it was before, use: statusmsg --- prompt.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/prompt.c b/prompt.c index 89c87d8..6b11007 100644 --- a/prompt.c +++ b/prompt.c @@ -164,6 +164,54 @@ static void execute(ToxWindow *self, char *u_cmd) } else if (!strncmp(cmd, "status ", strlen("status "))) { + char *status = strchr(cmd, ' '); + char *msg; + char *status_text; + if (status == NULL) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + status++; + USERSTATUS_KIND status_kind; + if (!strncmp(status, "online", strlen("online"))) { + status_kind = USERSTATUS_KIND_ONLINE; + status_text = "ONLINE"; + } + + else if (!strncmp(status, "away", strlen("away"))) { + status_kind = USERSTATUS_KIND_AWAY; + status_text = "AWAY"; + } + + else if (!strncmp(status, "busy", strlen("busy"))) { + status_kind = USERSTATUS_KIND_BUSY; + status_text = "BUSY"; + } + + else if (!strncmp(status, "offline", strlen("offline"))) { + status_kind = USERSTATUS_KIND_OFFLINE; + status_text = "OFFLINE"; + } + + else + { + wprintw(self->window, "Invalid status.\n"); + return; + } + + msg = strchr(status, ' '); + if (msg == NULL) { + m_set_userstatus_kind(status_kind); + wprintw(self->window, "Status set to: %s\n", status_text); + } + else { + msg++; + m_set_userstatus(status_kind, (uint8_t*) msg, strlen(msg)+1); + wprintw(self->window, "Status set to: %s, %s\n", status_text, msg); + } + } + + else if (!strncmp(cmd, "statusmsg ", strlen("statumsg "))) { char *msg = strchr(cmd, ' '); if (msg == NULL) { wprintw(self->window, "Invalid syntax.\n"); @@ -306,7 +354,8 @@ static void print_usage(ToxWindow *self) wprintw(self->window, " connect : Connect to DHT server\n"); wprintw(self->window, " add : Add friend\n"); - wprintw(self->window, " status : Set your status\n"); + wprintw(self->window, " status : Set your status\n"); + wprintw(self->window, " statusmsg : Set your status\n"); wprintw(self->window, " nick : Set your nickname\n"); wprintw(self->window, " accept : Accept friend request\n"); wprintw(self->window, " myid : Print your ID\n"); From 9e5c88859a1f60ac73198a34c4460e340ad3e6cb Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Wed, 7 Aug 2013 09:35:37 -0700 Subject: [PATCH 080/172] Fixed it not compiling --- prompt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prompt.c b/prompt.c index c4d7d2f..24b728f 100644 --- a/prompt.c +++ b/prompt.c @@ -54,7 +54,7 @@ static void execute(ToxWindow *self, char *u_cmd) if (cmd[0] == '/') { int i; - for (i = i1; i < strlen(cmd); i++) { //This doesn't work when it doesn't end with a space and another word + for (i = i; i < strlen(cmd); i++) { //This doesn't work when it doesn't end with a space and another word cmd[i - 1] = cmd[i]; //Still working on why } } From 660bfc134048444d2311ff296a548b6d3ab7a6c2 Mon Sep 17 00:00:00 2001 From: Sebastian Stal Date: Wed, 7 Aug 2013 09:57:23 -0700 Subject: [PATCH 081/172] Check for correct error value in toxic. --- chat.c | 2 +- prompt.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/chat.c b/chat.c index 7262e72..bad4cbf 100644 --- a/chat.c +++ b/chat.c @@ -127,7 +127,7 @@ static void chat_onKey(ToxWindow* self, int key) { wattroff(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "%s\n", ctx->line); } - if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) { + if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) == 0) { wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Failed to send message.\n"); wattroff(ctx->history, COLOR_PAIR(3)); diff --git a/prompt.c b/prompt.c index 20f6b48..670a93a 100644 --- a/prompt.c +++ b/prompt.c @@ -45,7 +45,7 @@ static void execute(ToxWindow* self, char* u_cmd) { int i; int newlines = 0; char cmd[256] = {0}; - for(i = 0; i < strlen(prompt_buf); i++) + for(i = 0; i < strlen(prompt_buf); i++) { if (u_cmd[i] == '\n') ++newlines; @@ -260,7 +260,7 @@ static void execute(ToxWindow* self, char* u_cmd) { msg[0] = 0; msg++; - if(m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) < 0) { + if(m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) == 0) { wprintw(self->window, "Error occurred while sending message.\n"); } else { @@ -338,7 +338,7 @@ static void print_usage(ToxWindow* self) { wprintw(self->window, " myid : Print your ID\n"); wprintw(self->window, " quit/exit : Exit program\n"); wprintw(self->window, " help : Print this message again\n"); - wprintw(self->window, " clear : Clear this window\n"); + wprintw(self->window, " clear : Clear this window\n"); wattron(self->window, A_BOLD); wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n"); From 5411f625670365b71f38358262c6bc4eeb0a6385 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Wed, 7 Aug 2013 10:36:32 -0700 Subject: [PATCH 082/172] Moved main.c to maaster --- main.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/main.c b/main.c index 2bf1676..27e3d85 100644 --- a/main.c +++ b/main.c @@ -22,7 +22,7 @@ extern int add_req(uint8_t *public_key); // XXX /* Holds status of chat windows */ char WINDOW_STATUS[MAX_WINDOW_SLOTS]; -#define TOXICVER "0.1.0" //Will be moved to a -D flag later +#define TOXICVER "0.1.0" //Will be moved to a -D flag later static ToxWindow windows[MAX_WINDOW_SLOTS]; static ToxWindow* prompt; @@ -250,6 +250,7 @@ static void load_data(char *path) static void draw_bar() { static int odd = 0; + int blinkrate = 30; attron(COLOR_PAIR(4)); mvhline(LINES - 2, 0, '_', COLS); @@ -258,7 +259,7 @@ static void draw_bar() move(LINES - 1, 0); attron(COLOR_PAIR(4) | A_BOLD); - printw(" TOXIC " TOXICVER " |"); + printw(" TOXIC " TOXICVER " |"); attroff(COLOR_PAIR(4) | A_BOLD); int i; @@ -267,14 +268,13 @@ static void draw_bar() if (i == active_window) attron(A_BOLD); - odd = (odd+1) % 10; - if (windows[i].blink && (odd < 5)) { + odd = (odd+1) % blinkrate; + if (windows[i].blink && (odd < (blinkrate/2))) { attron(COLOR_PAIR(3)); } - printw(" %s", windows[i].title); - if (windows[i].blink && (odd < 5)) { - attron(COLOR_PAIR(3)); + if (windows[i].blink && (odd < (blinkrate/2))) { + attroff(COLOR_PAIR(3)); } if (i == active_window) { attroff(A_BOLD); @@ -376,9 +376,8 @@ int main(int argc, char *argv[]) ch = getch(); if (ch == '\t' || ch == KEY_BTAB) set_active_window(ch); - else if (ch != ERR) { + else if (ch != ERR) a->onKey(a, ch); - } } return 0; } From 84847d8e29723eda622d5f4b1edc9c9a7cfb5296 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Wed, 7 Aug 2013 10:57:17 -0700 Subject: [PATCH 083/172] Manually merged prompt.c to upstream --- prompt.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/prompt.c b/prompt.c index 24b728f..b6827ce 100644 --- a/prompt.c +++ b/prompt.c @@ -52,9 +52,21 @@ static void execute(ToxWindow *self, char *u_cmd) cmd[i - newlines] = u_cmd[i]; } + int leading_spc = 0; + for (i = 0; i < 256 && isspace(cmd[i]); ++i) + leading_spc++; + memmove(cmd, cmd + leading_spc, 256 - leading_spc); + + int cmd_end = strlen(cmd); + while (cmd_end > 0 && cmd_end--) + if (!isspace(cmd[cmd_end])) + break; + cmd[cmd_end + 1] = '\0'; + if (cmd[0] == '/') { + wprintw(self->window,"Warning: Run your command without the /, this may not work\n"); int i; - for (i = i; i < strlen(cmd); i++) { //This doesn't work when it doesn't end with a space and another word + for (i = 1; i < strlen(cmd); i++) { //This doesn't work when it doesn't end with a space and another word cmd[i - 1] = cmd[i]; //Still working on why } } @@ -171,6 +183,54 @@ static void execute(ToxWindow *self, char *u_cmd) } else if (!strncmp(cmd, "status ", strlen("status "))) { + char *status = strchr(cmd, ' '); + char *msg; + char *status_text; + if (status == NULL) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + status++; + USERSTATUS_KIND status_kind; + if (!strncmp(status, "online", strlen("online"))) { + status_kind = USERSTATUS_KIND_ONLINE; + status_text = "ONLINE"; + } + + else if (!strncmp(status, "away", strlen("away"))) { + status_kind = USERSTATUS_KIND_AWAY; + status_text = "AWAY"; + } + + else if (!strncmp(status, "busy", strlen("busy"))) { + status_kind = USERSTATUS_KIND_BUSY; + status_text = "BUSY"; + } + + else if (!strncmp(status, "offline", strlen("offline"))) { + status_kind = USERSTATUS_KIND_OFFLINE; + status_text = "OFFLINE"; + } + + else + { + wprintw(self->window, "Invalid status.\n"); + return; + } + + msg = strchr(status, ' '); + if (msg == NULL) { + m_set_userstatus_kind(status_kind); + wprintw(self->window, "Status set to: %s\n", status_text); + } + else { + msg++; + m_set_userstatus(status_kind, (uint8_t*) msg, strlen(msg)+1); + wprintw(self->window, "Status set to: %s, %s\n", status_text, msg); + } + } + + else if (!strncmp(cmd, "statusmsg ", strlen("statumsg "))) { char *msg = strchr(cmd, ' '); if (msg == NULL) { wprintw(self->window, "Invalid syntax.\n"); @@ -313,7 +373,8 @@ static void print_usage(ToxWindow *self) wprintw(self->window, " connect : Connect to DHT server\n"); wprintw(self->window, " add : Add friend\n"); - wprintw(self->window, " status : Set your status\n"); + wprintw(self->window, " status : Set your status\n"); + wprintw(self->window, " statusmsg : Set your status\n"); wprintw(self->window, " nick : Set your nickname\n"); wprintw(self->window, " accept : Accept friend request\n"); wprintw(self->window, " myid : Print your ID\n"); From 174604a448e0467c4ab51d86ce01bd3529227959 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Wed, 7 Aug 2013 18:12:59 -0400 Subject: [PATCH 084/172] Modified clients to properly work with the changes --- chat.c | 2 +- friendlist.c | 4 ++-- main.c | 4 ++-- prompt.c | 20 ++++++++------------ 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/chat.c b/chat.c index 20c0162..2563fa9 100644 --- a/chat.c +++ b/chat.c @@ -162,7 +162,7 @@ void execute(ToxWindow *self, ChatContext *ctx, char *cmd) return; } msg++; - m_set_userstatus(USERSTATUS_KIND_RETAIN, (uint8_t*) msg, strlen(msg)+1); + m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); wprintw(ctx->history, "Status set to: %s\n", msg); } diff --git a/friendlist.c b/friendlist.c index f03914e..159217b 100644 --- a/friendlist.c +++ b/friendlist.c @@ -20,7 +20,7 @@ extern int active_window; typedef struct { uint8_t name[MAX_NAME_LENGTH]; - uint8_t status[MAX_USERSTATUS_LENGTH]; + uint8_t status[MAX_STATUSMESSAGE_LENGTH]; int num; int chatwin; } friend_t; @@ -74,7 +74,7 @@ void friendlist_onNickChange(ToxWindow *self, int num, uint8_t *str, uint16_t le void friendlist_onStatusChange(ToxWindow *self, int num, uint8_t *str, uint16_t len) { - if (len >= MAX_USERSTATUS_LENGTH || num >= num_friends) + if (len >= MAX_STATUSMESSAGE_LENGTH || num >= num_friends) return; memcpy((char*) &friends[num].status, (char*) str, len); diff --git a/main.c b/main.c index 8de7624..5933300 100644 --- a/main.c +++ b/main.c @@ -68,7 +68,7 @@ void on_nickchange(int friendnumber, uint8_t *string, uint16_t length) } } -void on_statuschange(int friendnumber, USERSTATUS_KIND kind, uint8_t *string, uint16_t length) +void on_statuschange(int friendnumber, uint8_t *string, uint16_t length) { wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); int i; @@ -112,7 +112,7 @@ static void init_tox() m_callback_friendrequest(on_request); m_callback_friendmessage(on_message); m_callback_namechange(on_nickchange); - m_callback_userstatus(on_statuschange); + m_callback_statusmessage(on_statuschange); } void init_window_status() diff --git a/prompt.c b/prompt.c index d79d061..01261cc 100644 --- a/prompt.c +++ b/prompt.c @@ -183,27 +183,22 @@ static void execute(ToxWindow *self, char *u_cmd) return; } status++; - USERSTATUS_KIND status_kind; + USERSTATUS status_kind; if (!strncmp(status, "online", strlen("online"))) { - status_kind = USERSTATUS_KIND_ONLINE; + status_kind = USERSTATUS_NONE; status_text = "ONLINE"; } else if (!strncmp(status, "away", strlen("away"))) { - status_kind = USERSTATUS_KIND_AWAY; + status_kind = USERSTATUS_AWAY; status_text = "AWAY"; } else if (!strncmp(status, "busy", strlen("busy"))) { - status_kind = USERSTATUS_KIND_BUSY; + status_kind = USERSTATUS_BUSY; status_text = "BUSY"; } - else if (!strncmp(status, "offline", strlen("offline"))) { - status_kind = USERSTATUS_KIND_OFFLINE; - status_text = "OFFLINE"; - } - else { wprintw(self->window, "Invalid status.\n"); @@ -212,12 +207,13 @@ static void execute(ToxWindow *self, char *u_cmd) msg = strchr(status, ' '); if (msg == NULL) { - m_set_userstatus_kind(status_kind); + m_set_userstatus(status_kind); wprintw(self->window, "Status set to: %s\n", status_text); } else { msg++; - m_set_userstatus(status_kind, (uint8_t*) msg, strlen(msg)+1); + m_set_userstatus(status_kind); + m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); wprintw(self->window, "Status set to: %s, %s\n", status_text, msg); } } @@ -229,7 +225,7 @@ static void execute(ToxWindow *self, char *u_cmd) return; } msg++; - m_set_userstatus(USERSTATUS_KIND_RETAIN, (uint8_t*) msg, strlen(msg)+1); + m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); wprintw(self->window, "Status set to: %s\n", msg); } From 94dab852758a9d5a85e8c3d9e0a89f2aa26fa1b7 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Wed, 7 Aug 2013 18:52:11 -0700 Subject: [PATCH 085/172] Adds full -D support to toxics versioning, includes the commit number --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f30d8e9..38f02dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 2.6.0) project(toxic C) +execute_process(COMMAND git rev-list HEAD --count OUTPUT_VARIABLE COMMIT) +SET(GCC_COVERAGE_COMPILE_FLAGS '-DTOXICVER="0.1.1_r${COMMIT}"') +add_definitions(${GCC_COVERAGE_COMPILE_FLAGS}) set(exe_name toxic) add_executable(${exe_name} From c7463f0de2e3cb78ae9240075d7066f9ce7595f6 Mon Sep 17 00:00:00 2001 From: Simon Levermann Date: Thu, 8 Aug 2013 10:15:07 +0200 Subject: [PATCH 086/172] Attempt to get and create a proper directory for config storage. --- configdir.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++ configdir.h | 27 ++++++++++++++++ main.c | 20 +++++++++++- 3 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 configdir.c create mode 100644 configdir.h diff --git a/configdir.c b/configdir.c new file mode 100644 index 0000000..c9f7de8 --- /dev/null +++ b/configdir.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox 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. + * + * Tox 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 Tox. If not, see . + * + */ + +#include +#include +#include + +#ifdef _win32 +#include +#endif + +#ifdef __APPLE__ +#include +#include +#include +#endif + +char *get_user_config_dir(void) +{ + char *user_config_dir; + + #ifdef _win32 + + char appdata[MAX_PATH]; + HRESULT result = SHGetFolderPath( + NULL, + CSIDL_APPDATA, // TODO: Maybe use CSIDL_LOCAL_APPDATA instead? Not sure. + NULL, + SHGFP_TYPE_CURRENT, + appdata + ) + if (!result) return NULL; + + user_config_dir = malloc(strlen(appdata) + strlen(CONFIGDIR) + 1); + if (user_config_dir) { + strcpy(user_config_dir, appdata); + strcat(user_config_dir, CONFIGDIR); + } + return user_config_dir; + + #elif defined __APPLE__ + + struct passwd *pass = getpwuid(getuid()); + if (!pass) return NULL; + char *home = pass->pw_dir; + user_config_dir = malloc(strlen(home) + strlen("/Library/Application Support") + strlen(CONFIGDIR) + 1); + + if(user_config_dir) { + strcpy(user_config_dir, home); + strcat(user_config_dir, "/Library/Application Support"); + strcat(user_config_dir, CONFIGDIR); + } + return user_config_dir; + + #else + + if (getenv("XDG_CONFIG_HOME")) { + user_config_dir = malloc(strlen(getenv("XDG_CONFIG_HOME")) + strlen(CONFIGDIR) + 1); + if (user_config_dir) { + strcpy(user_config_dir, getenv("XDG_CONFIG_HOME")); + strcat(user_config_dir, CONFIGDIR); + } + } else { + user_config_dir = malloc(strlen(getenv("HOME")) + strlen("/.config") + strlen(CONFIGDIR) + 1); + if (user_config_dir) { + strcpy(user_config_dir, getenv("HOME")); + strcat(user_config_dir, "/.config"); + strcat(user_config_dir, CONFIGDIR); + } + } + return user_config_dir; + + #endif +} \ No newline at end of file diff --git a/configdir.h b/configdir.h new file mode 100644 index 0000000..441ffda --- /dev/null +++ b/configdir.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox 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. + * + * Tox 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 Tox. If not, see . + * + */ + +#ifdef _win32 +#define CONFIGDIR "\\toxic\\" +#else +#define CONFIGDIR "/toxic/" +#endif + +char *get_user_config_dir(void); \ No newline at end of file diff --git a/main.c b/main.c index b2310c8..ec439c8 100644 --- a/main.c +++ b/main.c @@ -11,6 +11,7 @@ #include "../../core/Messenger.h" #include "../../core/network.h" +#include "configdir.h" #include "windows.h" extern ToxWindow new_prompt(); @@ -331,7 +332,24 @@ int main(int argc, char *argv[]) { int ch; int f_flag = 0; - char *filename = "data"; + char *configdir = get_user_config_dir(); + char *default_file = "data"; + int mkdir_err + #ifdef _win32 + mkdir_err = _mkdir(configdir); + #else + mkdir_err = mkdir(configdir, 0700); + #endif + + char *filename; + if(mkdir_err == -1) { + filename = default_file; + } else { + filename = malloc(strlen(configdir) + strlen(default_file) + 1); + strcpy(filename, configdir); + strcat(filename, default_file); + } + ToxWindow* a; int i = 0; From 297ee1ecaaea0731d5954624aed4b4663f8934f6 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 8 Aug 2013 04:51:58 -0400 Subject: [PATCH 087/172] fix magic numbers --- chat.c | 6 +++--- main.c | 2 +- prompt.c | 24 ++++++++++++------------ windows.h | 4 +++- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/chat.c b/chat.c index 28c5de6..56dfb05 100644 --- a/chat.c +++ b/chat.c @@ -16,7 +16,7 @@ typedef struct { int friendnum; - char line[256]; + char line[MAX_STR_SIZE]; size_t pos; WINDOW* history; WINDOW* linewin; @@ -178,9 +178,9 @@ void execute(ToxWindow *self, ChatContext *ctx, char *cmd) } else if (!strcmp(cmd, "/myid")) { - char id[32*2 + 1] = {0}; + char id[KEY_SIZE_BYTES*2+1] = {0}; int i; - for (i = 0; i < 32; i++) { + for (i = 0; i < KEY_SIZE_BYTES; i++) { char xx[3]; snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); strcat(id, xx); diff --git a/main.c b/main.c index b2310c8..d151955 100644 --- a/main.c +++ b/main.c @@ -37,7 +37,7 @@ void on_request(uint8_t *public_key, uint8_t *data, uint16_t length) wprintw(prompt->window, "\nFriend request from:\n"); int i; - for (i = 0; i < 32; ++i) { + for (i = 0; i < KEY_SIZE_BYTES; ++i) { wprintw(prompt->window, "%02x", public_key[i] & 0xff); } diff --git a/prompt.c b/prompt.c index 661d881..08874a9 100644 --- a/prompt.c +++ b/prompt.c @@ -12,12 +12,12 @@ #include "windows.h" -uint8_t pending_requests[256][CLIENT_ID_SIZE]; // XXX +uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX uint8_t num_requests=0; // XXX extern void on_friendadded(int friendnumber); static void print_usage(ToxWindow *self); -static char prompt_buf[256] = {0}; +static char prompt_buf[MAX_STR_SIZE] = {0}; static int prompt_buf_pos = 0; // XXX: @@ -43,7 +43,7 @@ unsigned char *hex_string_to_bin(char hex_string[]) static void execute(ToxWindow *self, char *u_cmd) { int newlines = 0; - char cmd[256] = {0}; + char cmd[MAX_STR_SIZE] = {0}; int i; for (i = 0; i < strlen(prompt_buf); ++i) { if (u_cmd[i] == '\n') @@ -53,9 +53,9 @@ static void execute(ToxWindow *self, char *u_cmd) } int leading_spc = 0; - for (i = 0; i < 256 && isspace(cmd[i]); ++i) + for (i = 0; i < MAX_STR_SIZE && isspace(cmd[i]); ++i) leading_spc++; - memmove(cmd, cmd + leading_spc, 256 - leading_spc); + memmove(cmd, cmd + leading_spc, MAX_STR_SIZE - leading_spc); int cmd_end = strlen(cmd); while (cmd_end > 0 && cmd_end--) @@ -109,7 +109,7 @@ static void execute(ToxWindow *self, char *u_cmd) } dht.port = htons(atoi(port)); - uint32_t resolved_address = resolve_addr(ip); + uintKEY_SIZE_BYTES_t resolved_address = resolve_addr(ip); if (resolved_address == 0) { return; } @@ -121,9 +121,9 @@ static void execute(ToxWindow *self, char *u_cmd) } else if (!strncmp(cmd, "add ", strlen("add "))) { - uint8_t id_bin[32]; + uint8_t id_bin[KEY_SIZE_BYTES]; char xx[3]; - uint32_t x; + uintKEY_SIZE_BYTES_t x; char *id = strchr(cmd, ' '); if (id == NULL) { wprintw(self->window, "Invalid syntax.\n"); @@ -136,12 +136,12 @@ static void execute(ToxWindow *self, char *u_cmd) msg++; } else msg = ""; - if (strlen(id) != 2*32) { + if (strlen(id) != 2*KEY_SIZE_BYTES) { wprintw(self->window, "Invalid ID length.\n"); return; } int i; - for (i = 0; i < 32; ++i) { + for (i = 0; i < KEY_SIZE_BYTES; ++i) { xx[0] = id[2*i]; xx[1] = id[2*i+1]; xx[2] = '\0'; @@ -251,9 +251,9 @@ static void execute(ToxWindow *self, char *u_cmd) } else if (!strcmp(cmd, "myid")) { - char id[32*2 + 1] = {0}; + char id[KEY_SIZE_BYTES*2 + 1] = {0}; size_t i; - for (i = 0; i < 32; ++i) { + for (i = 0; i < KEY_SIZE_BYTES; ++i) { char xx[3]; snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); strcat(id, xx); diff --git a/windows.h b/windows.h index cb45614..287e534 100644 --- a/windows.h +++ b/windows.h @@ -5,7 +5,9 @@ #include #define TOXWINDOWS_MAX_NUM 32 #define MAX_FRIENDS_NUM 100 - +#define MAX_STR_SIZE 256 +#define KEY_SIZE_BYTES 32 + /* number of permanent default windows */ #define N_DEFAULT_WINS 2 From 757073a461d6a5a749a4c0194234152d592d627b Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 8 Aug 2013 04:55:22 -0400 Subject: [PATCH 088/172] oops --- prompt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prompt.c b/prompt.c index 08874a9..b50792f 100644 --- a/prompt.c +++ b/prompt.c @@ -109,7 +109,7 @@ static void execute(ToxWindow *self, char *u_cmd) } dht.port = htons(atoi(port)); - uintKEY_SIZE_BYTES_t resolved_address = resolve_addr(ip); + uint32_t resolved_address = resolve_addr(ip); if (resolved_address == 0) { return; } @@ -123,7 +123,7 @@ static void execute(ToxWindow *self, char *u_cmd) else if (!strncmp(cmd, "add ", strlen("add "))) { uint8_t id_bin[KEY_SIZE_BYTES]; char xx[3]; - uintKEY_SIZE_BYTES_t x; + uint32_t x; char *id = strchr(cmd, ' '); if (id == NULL) { wprintw(self->window, "Invalid syntax.\n"); From 4cf43ae0974e5fcc18447d936f5e02dd97977e05 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Thu, 8 Aug 2013 03:04:36 -0700 Subject: [PATCH 089/172] Merged upstream main.c changes --- main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index 27e3d85..777ed80 100644 --- a/main.c +++ b/main.c @@ -22,7 +22,7 @@ extern int add_req(uint8_t *public_key); // XXX /* Holds status of chat windows */ char WINDOW_STATUS[MAX_WINDOW_SLOTS]; -#define TOXICVER "0.1.0" //Will be moved to a -D flag later +//#define TOXICVER "0.1.0" //Will be moved to a -D flag later static ToxWindow windows[MAX_WINDOW_SLOTS]; static ToxWindow* prompt; @@ -69,7 +69,7 @@ void on_nickchange(int friendnumber, uint8_t *string, uint16_t length) } } -void on_statuschange(int friendnumber, USERSTATUS_KIND kind, uint8_t *string, uint16_t length) +void on_statuschange(int friendnumber, uint8_t *string, uint16_t length) { wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); int i; @@ -113,7 +113,7 @@ static void init_tox() m_callback_friendrequest(on_request); m_callback_friendmessage(on_message); m_callback_namechange(on_nickchange); - m_callback_userstatus(on_statuschange); + m_callback_statusmessage(on_statuschange); } void init_window_status() From 6a37d6e9f1e7bf40a3309a20b209d0629bb58db5 Mon Sep 17 00:00:00 2001 From: Nominate Date: Thu, 8 Aug 2013 11:09:46 +0100 Subject: [PATCH 090/172] Removed superfluous statusmsg Users can just respecify their status with a message. This will also encourage users to think about which status is actually appropriate instead of just leaving the status alone. --- prompt.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/prompt.c b/prompt.c index 661d881..b3d6d22 100644 --- a/prompt.c +++ b/prompt.c @@ -228,17 +228,6 @@ static void execute(ToxWindow *self, char *u_cmd) } } - else if (!strncmp(cmd, "statusmsg ", strlen("statumsg "))) { - char *msg = strchr(cmd, ' '); - if (msg == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - msg++; - m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); - wprintw(self->window, "Status set to: %s\n", msg); - } - else if (!strncmp(cmd, "nick ", strlen("nick "))) { char *nick = strchr(cmd, ' '); if (nick == NULL) { @@ -372,7 +361,6 @@ static void print_usage(ToxWindow *self) wprintw(self->window, " connect : Connect to DHT server\n"); wprintw(self->window, " add : Add friend\n"); wprintw(self->window, " status : Set your status\n"); - wprintw(self->window, " statusmsg : Set your status\n"); wprintw(self->window, " nick : Set your nickname\n"); wprintw(self->window, " accept : Accept friend request\n"); wprintw(self->window, " myid : Print your ID\n"); From d6468d7d0cc9b4c3cb424e3986cc9275e7d007ff Mon Sep 17 00:00:00 2001 From: Nominate Date: Thu, 8 Aug 2013 11:22:48 +0100 Subject: [PATCH 091/172] Updated chat.c to bring /status inline with prompt.c status command --- chat.c | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/chat.c b/chat.c index 28c5de6..669fd14 100644 --- a/chat.c +++ b/chat.c @@ -154,15 +154,47 @@ void execute(ToxWindow *self, ChatContext *ctx, char *cmd) } else if (!strncmp(cmd, "/status ", strlen("/status "))) { + char *status = strchr(cmd, ' '); char *msg; - msg = strchr(cmd, ' '); - if (msg == NULL) { + char *status_text; + if (status == NULL) { wprintw(ctx->history, "Invalid syntax.\n"); return; } - msg++; - m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); - wprintw(ctx->history, "Status set to: %s\n", msg); + status++; + USERSTATUS status_kind; + if (!strncmp(status, "online", strlen("online"))) { + status_kind = USERSTATUS_NONE; + status_text = "ONLINE"; + } + + else if (!strncmp(status, "away", strlen("away"))) { + status_kind = USERSTATUS_AWAY; + status_text = "AWAY"; + } + + else if (!strncmp(status, "busy", strlen("busy"))) { + status_kind = USERSTATUS_BUSY; + status_text = "BUSY"; + } + + else + { + wprintw(ctx->history, "Invalid status.\n"); + return; + } + + msg = strchr(status, ' '); + if (msg == NULL) { + m_set_userstatus(status_kind); + wprintw(ctx->history, "Status set to: %s\n", status_text); + } + else { + msg++; + m_set_userstatus(status_kind); + m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); + wprintw(ctx->history, "Status set to: %s, %s\n", status_text, msg); + } } else if (!strncmp(cmd, "/nick ", strlen("/nick "))) { @@ -231,7 +263,7 @@ void print_help(ChatContext *self) wprintw(self->history, "Commands:\n"); wattroff(self->history, A_BOLD); - wprintw(self->history, " /status : Set your status\n"); + wprintw(self->history, " /status : Set your status\n"); wprintw(self->history, " /nick : Set your nickname\n"); wprintw(self->history, " /myid : Print your ID\n"); wprintw(self->history, " /clear : Clear the screen\n"); From c3c144ddd00a6f40fc635816025ae41e72c09d32 Mon Sep 17 00:00:00 2001 From: Simon Levermann Date: Thu, 8 Aug 2013 16:00:12 +0200 Subject: [PATCH 092/172] Implement proper config directories. --- CMakeLists.txt | 3 +- configdir.c | 151 +++++++++++++++++++++++++++++++++---------------- configdir.h | 8 ++- main.c | 38 ++++++++----- 4 files changed, 135 insertions(+), 65 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f30d8e9..bfcf04b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,8 @@ add_executable(${exe_name} main.c prompt.c friendlist.c - chat.c) + chat.c + configdir.c) target_link_libraries(${exe_name} curses) diff --git a/configdir.c b/configdir.c index c9f7de8..7d11d02 100644 --- a/configdir.c +++ b/configdir.c @@ -21,71 +21,126 @@ #include #include #include +#include +#include +#include -#ifdef _win32 +#ifdef WIN32 #include +#include #endif #ifdef __APPLE__ -#include #include #include #endif +#include "configdir.h" + +/* + * Retrieves a correct configuration directory, depending on the OS used, with a trailing slash + */ char *get_user_config_dir(void) { - char *user_config_dir; + char *user_config_dir; - #ifdef _win32 + #ifdef WIN32 - char appdata[MAX_PATH]; - HRESULT result = SHGetFolderPath( - NULL, - CSIDL_APPDATA, // TODO: Maybe use CSIDL_LOCAL_APPDATA instead? Not sure. - NULL, - SHGFP_TYPE_CURRENT, - appdata - ) - if (!result) return NULL; + char appdata[MAX_PATH]; + HRESULT result = SHGetFolderPath( + NULL, + CSIDL_APPDATA, + NULL, + SHGFP_TYPE_CURRENT, + appdata + ) + if (!result) return NULL; - user_config_dir = malloc(strlen(appdata) + strlen(CONFIGDIR) + 1); - if (user_config_dir) { - strcpy(user_config_dir, appdata); - strcat(user_config_dir, CONFIGDIR); - } - return user_config_dir; + user_config_dir = malloc(strlen(appdata) + 1); + if (user_config_dir) { + strcpy(user_config_dir, appdata); + } + return user_config_dir; - #elif defined __APPLE__ + #elif defined __APPLE__ - struct passwd *pass = getpwuid(getuid()); - if (!pass) return NULL; - char *home = pass->pw_dir; - user_config_dir = malloc(strlen(home) + strlen("/Library/Application Support") + strlen(CONFIGDIR) + 1); - - if(user_config_dir) { - strcpy(user_config_dir, home); - strcat(user_config_dir, "/Library/Application Support"); - strcat(user_config_dir, CONFIGDIR); - } - return user_config_dir; + struct passwd *pass = getpwuid(getuid()); + if (!pass) return NULL; + char *home = pass->pw_dir; + user_config_dir = malloc(strlen(home) + strlen("/Library/Application Support") + 1); + + if(user_config_dir) { + strcpy(user_config_dir, home); + strcat(user_config_dir, "/Library/Application Support"); + } + return user_config_dir; - #else + #else - if (getenv("XDG_CONFIG_HOME")) { - user_config_dir = malloc(strlen(getenv("XDG_CONFIG_HOME")) + strlen(CONFIGDIR) + 1); - if (user_config_dir) { - strcpy(user_config_dir, getenv("XDG_CONFIG_HOME")); - strcat(user_config_dir, CONFIGDIR); - } - } else { - user_config_dir = malloc(strlen(getenv("HOME")) + strlen("/.config") + strlen(CONFIGDIR) + 1); - if (user_config_dir) { - strcpy(user_config_dir, getenv("HOME")); - strcat(user_config_dir, "/.config"); - strcat(user_config_dir, CONFIGDIR); - } - } - return user_config_dir; + if (getenv("XDG_CONFIG_HOME")) { + user_config_dir = malloc(strlen(getenv("XDG_CONFIG_HOME")) + 1); + if (user_config_dir) { + strcpy(user_config_dir, getenv("XDG_CONFIG_HOME")); + } + } else { + user_config_dir = malloc(strlen(getenv("HOME")) + strlen("/.config") + 1); + if (user_config_dir) { + strcpy(user_config_dir, getenv("HOME")); + strcat(user_config_dir, "/.config"); + } + } + return user_config_dir; - #endif + #endif +} + +/* + * Creates the config directory. + */ +int create_user_config_dir(char *path) +{ + + int mkdir_err; + + #ifdef WIN32 + + char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1); + strcpy(fullpath, path); + strcat(fullpath, CONFIGDIR); + + mkdir_err = _mkdir(fullpath); + + if (mkdir_err) { + if(errno != EEXIST) return -1; + struct _stat buf; + if(_wstat64(fullpath, &buf)) return -1; + if(!S_ISDIR(buf.st_mode)) return -1; + } + + #else + + mkdir_err = mkdir(path, 0700); + struct stat buf; + + if(mkdir_err) { + if(errno != EEXIST) return -1; + if(stat(path, &buf)) return -1; + if(!S_ISDIR(buf.st_mode)) return -1; + } + + char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1); + strcpy(fullpath, path); + strcat(fullpath, CONFIGDIR); + + mkdir_err = mkdir(fullpath, 0700); + + if(mkdir_err) { + if(errno != EEXIST) return -1; + if(stat(fullpath, &buf)) return -1; + if(!S_ISDIR(buf.st_mode)) return -1; + } + + #endif + + return 0; } \ No newline at end of file diff --git a/configdir.h b/configdir.h index 441ffda..d9837d7 100644 --- a/configdir.h +++ b/configdir.h @@ -23,5 +23,11 @@ #else #define CONFIGDIR "/toxic/" #endif + +#ifndef S_ISDIR +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif -char *get_user_config_dir(void); \ No newline at end of file +char *get_user_config_dir(void); + +int create_user_config_dir(char *path); \ No newline at end of file diff --git a/main.c b/main.c index ec439c8..cb0d9e1 100644 --- a/main.c +++ b/main.c @@ -3,11 +3,19 @@ */ #include +#include #include #include #include #include +#ifdef _win32 +#include +#else +#include +#include +#endif + #include "../../core/Messenger.h" #include "../../core/network.h" @@ -332,26 +340,19 @@ int main(int argc, char *argv[]) { int ch; int f_flag = 0; - char *configdir = get_user_config_dir(); - char *default_file = "data"; - int mkdir_err - #ifdef _win32 - mkdir_err = _mkdir(configdir); - #else - mkdir_err = mkdir(configdir, 0700); - #endif - + char *user_config_dir = get_user_config_dir(); char *filename; - if(mkdir_err == -1) { - filename = default_file; + int config_err = create_user_config_dir(user_config_dir); + if(config_err) { + filename = "data"; } else { - filename = malloc(strlen(configdir) + strlen(default_file) + 1); - strcpy(filename, configdir); - strcat(filename, default_file); + filename = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); + strcpy(filename, user_config_dir); + strcat(filename, CONFIGDIR); + strcat(filename, "data"); } ToxWindow* a; - int i = 0; for (i = 0; i < argc; ++i) { if (argv[i] == NULL) @@ -378,6 +379,13 @@ int main(int argc, char *argv[]) "defaulting to 'data' for a keyfile...\n"); attroff(COLOR_PAIR(3) | A_BOLD); } + + if(config_err) { + attron(COLOR_PAIR(3) | A_BOLD); + wprintw(prompt->window, "Unable to determine configuration directory!\n" + "defaulting to 'data' for a keyfile...\n"); + attroff(COLOR_PAIR(3) | A_BOLD); + } while(true) { /* Update tox */ From a9ec08b9989747791e42eca1b618a89732ebe7c4 Mon Sep 17 00:00:00 2001 From: Simon Levermann Date: Thu, 8 Aug 2013 16:36:16 +0200 Subject: [PATCH 093/172] Cleanup and Error fixes Add several frees that were missing to prevent memory leaks Replace strcpy with strdup where appropriate Replace _stat with __stat64 for building on Windows --- configdir.c | 36 +++++++++++++----------------------- configdir.h | 2 +- main.c | 1 + 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/configdir.c b/configdir.c index 7d11d02..d91d080 100644 --- a/configdir.c +++ b/configdir.c @@ -56,10 +56,8 @@ char *get_user_config_dir(void) ) if (!result) return NULL; - user_config_dir = malloc(strlen(appdata) + 1); - if (user_config_dir) { - strcpy(user_config_dir, appdata); - } + user_config_dir = strdup(appdata); + return user_config_dir; #elif defined __APPLE__ @@ -78,10 +76,7 @@ char *get_user_config_dir(void) #else if (getenv("XDG_CONFIG_HOME")) { - user_config_dir = malloc(strlen(getenv("XDG_CONFIG_HOME")) + 1); - if (user_config_dir) { - strcpy(user_config_dir, getenv("XDG_CONFIG_HOME")); - } + user_config_dir = strdup(getenv("XDG_CONFIG_HOME")); } else { user_config_dir = malloc(strlen(getenv("HOME")) + strlen("/.config") + 1); if (user_config_dir) { @@ -109,12 +104,10 @@ int create_user_config_dir(char *path) strcat(fullpath, CONFIGDIR); mkdir_err = _mkdir(fullpath); - - if (mkdir_err) { - if(errno != EEXIST) return -1; - struct _stat buf; - if(_wstat64(fullpath, &buf)) return -1; - if(!S_ISDIR(buf.st_mode)) return -1; + struct __stat64 buf; + if (mkdir_err && (errno != EEXIST || _wstat64(fullpath, &buf) || !S_ISDIR(buf.st_mode))) { + free(fullpath); + return -1; } #else @@ -122,10 +115,8 @@ int create_user_config_dir(char *path) mkdir_err = mkdir(path, 0700); struct stat buf; - if(mkdir_err) { - if(errno != EEXIST) return -1; - if(stat(path, &buf)) return -1; - if(!S_ISDIR(buf.st_mode)) return -1; + if(mkdir_err && (errno != EEXIST || stat(path, &buf) || !S_ISDIR(buf.st_mode))) { + return -1; } char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1); @@ -134,13 +125,12 @@ int create_user_config_dir(char *path) mkdir_err = mkdir(fullpath, 0700); - if(mkdir_err) { - if(errno != EEXIST) return -1; - if(stat(fullpath, &buf)) return -1; - if(!S_ISDIR(buf.st_mode)) return -1; + if(mkdir_err && (errno != EEXIST || stat(fullpath, &buf) || !S_ISDIR(buf.st_mode))) { + free(fullpath); + return -1; } #endif return 0; -} \ No newline at end of file +} diff --git a/configdir.h b/configdir.h index d9837d7..fad949c 100644 --- a/configdir.h +++ b/configdir.h @@ -30,4 +30,4 @@ char *get_user_config_dir(void); -int create_user_config_dir(char *path); \ No newline at end of file +int create_user_config_dir(char *path); diff --git a/main.c b/main.c index cb0d9e1..13577cc 100644 --- a/main.c +++ b/main.c @@ -370,6 +370,7 @@ int main(int argc, char *argv[]) init_term(); init_tox(); load_data(filename); + free(filename); init_windows(); init_window_status(); From 0eff37e3d7cbfd5e8a55b5c0fbcebe6923283de3 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 8 Aug 2013 10:59:22 -0400 Subject: [PATCH 094/172] Moved a define and fixed another. --- main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index d457957..7fa9e96 100644 --- a/main.c +++ b/main.c @@ -22,7 +22,10 @@ extern int add_req(uint8_t *public_key); // XXX /* Holds status of chat windows */ char WINDOW_STATUS[MAX_WINDOW_SLOTS]; -//#define TOXICVER "0.1.0" //Will be moved to a -D flag later + +#ifndef TOXICVER +#define TOXICVER "NOVER" //Use the -D flag to set this +#endif static ToxWindow windows[MAX_WINDOW_SLOTS]; static ToxWindow* prompt; From 30377630ee804a07049eb53b9df0396047d2ddd8 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 8 Aug 2013 15:01:33 -0400 Subject: [PATCH 095/172] added /me actions to toxic --- chat.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++----- friendlist.c | 1 + main.c | 26 ++++++++++++++------- windows.h | 1 + 4 files changed, 79 insertions(+), 15 deletions(-) diff --git a/chat.c b/chat.c index 8376577..73cb145 100644 --- a/chat.c +++ b/chat.c @@ -27,7 +27,7 @@ extern int active_window; extern void del_window(ToxWindow *w, int f_num); extern void fix_name(uint8_t *name); void print_help(ChatContext *self); -void execute(ToxWindow *self, ChatContext *ctx, char *cmd); +void execute(ToxWindow *self, ChatContext *ctx, char *cmd, struct tm *timeinfo); static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len) { @@ -35,7 +35,7 @@ static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len) uint8_t nick[MAX_NAME_LENGTH] = {0}; time_t now; time(&now); - struct tm * timeinfo; + struct tm *timeinfo; timeinfo = localtime(&now); if (ctx->friendnum != num) @@ -59,6 +59,32 @@ static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len) beep(); } +static void chat_onAction(ToxWindow *self, int num, uint8_t *action, uint16_t len) +{ + ChatContext *ctx = (ChatContext*) self->x; + time_t now; + time(&now); + struct tm *timeinfo; + timeinfo = localtime(&now); + + if (ctx->friendnum != num) + return; + + action[len-1] = '\0'; + fix_name(action); + + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); + + wattron(ctx->history, COLOR_PAIR(4)); + wprintw(ctx->history, "%s\n", action); + wattroff(ctx->history, COLOR_PAIR(4)); + + self->blink = true; + beep(); +} + static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len) { ChatContext *ctx = (ChatContext*) self->x; @@ -108,7 +134,7 @@ static void chat_onKey(ToxWindow *self, int key) /* RETURN key: Execute command or print line */ else if (key == '\n') { if (ctx->line[0] == '/') - execute(self, ctx, ctx->line); + execute(self, ctx, ctx->line, timeinfo); else { if (!string_is_empty(ctx->line)) { /* make sure the string has at least non-space character */ @@ -138,7 +164,7 @@ static void chat_onKey(ToxWindow *self, int key) } } -void execute(ToxWindow *self, ChatContext *ctx, char *cmd) +void execute(ToxWindow *self, ChatContext *ctx, char *cmd, struct tm *timeinfo) { if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { wclear(self->window); @@ -153,6 +179,33 @@ void execute(ToxWindow *self, ChatContext *ctx, char *cmd) exit(0); } + else if (!strncmp(cmd, "/me ", strlen("/me "))) { + char *action = strchr(cmd, ' '); + if (action == NULL) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + action++; + + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); + + uint8_t selfname[MAX_NAME_LENGTH]; + int len = getself_name(selfname); + char msg[MAX_STR_SIZE-len-4]; + snprintf(msg, sizeof(msg), "* %s %s\n", (uint8_t*) selfname, action); + + wattron(ctx->history, COLOR_PAIR(1)); + wprintw(ctx->history, msg); + wattroff(ctx->history, COLOR_PAIR(1)); + if (m_sendaction(ctx->friendnum, (uint8_t*) msg, strlen(msg)+1) < 0) { + wattron(ctx->history, COLOR_PAIR(3)); + wprintw(ctx->history, " * Failed to send action\n"); + wattroff(ctx->history, COLOR_PAIR(3)); + } + } + else if (!strncmp(cmd, "/status ", strlen("/status "))) { char *status = strchr(cmd, ' '); char *msg; @@ -178,8 +231,7 @@ void execute(ToxWindow *self, ChatContext *ctx, char *cmd) status_text = "BUSY"; } - else - { + else { wprintw(ctx->history, "Invalid status.\n"); return; } @@ -265,6 +317,7 @@ void print_help(ChatContext *self) wprintw(self->history, " /status : Set your status\n"); wprintw(self->history, " /nick : Set your nickname\n"); + wprintw(self->history, " /me : Do an action\n"); wprintw(self->history, " /myid : Print your ID\n"); wprintw(self->history, " /clear : Clear the screen\n"); wprintw(self->history, " /close : Close the current chat window\n"); @@ -285,6 +338,7 @@ ToxWindow new_chat(int friendnum) ret.onMessage = &chat_onMessage; ret.onNickChange = &chat_onNickChange; ret.onStatusChange = &chat_onStatusChange; + ret.onAction = &chat_onAction; uint8_t nick[MAX_NAME_LENGTH] = {0}; getname(friendnum, (uint8_t*) &nick); diff --git a/friendlist.c b/friendlist.c index 159217b..f2aa1cf 100644 --- a/friendlist.c +++ b/friendlist.c @@ -177,6 +177,7 @@ ToxWindow new_friendlist() { ret.onDraw = &friendlist_onDraw; ret.onInit = &friendlist_onInit; ret.onMessage = &friendlist_onMessage; + ret.onAction = &friendlist_onMessage; // Action has identical behaviour to message ret.onNickChange = &friendlist_onNickChange; ret.onStatusChange = &friendlist_onStatusChange; diff --git a/main.c b/main.c index 7fa9e96..d5999eb 100644 --- a/main.c +++ b/main.c @@ -44,8 +44,9 @@ void on_request(uint8_t *public_key, uint8_t *data, uint16_t length) wprintw(prompt->window, "%02x", public_key[i] & 0xff); } - wprintw(prompt->window, "\n"); - wprintw(prompt->window, "Use \"accept %d\" to accept it.\n", n); + wprintw(prompt->window, "\nWith the message: %s\n", data); + wprintw(prompt->window, "\nUse \"accept %d\" to accept it.\n", n); + for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { if (windows[i].onFriendRequest != NULL) windows[i].onFriendRequest(&windows[i], public_key, data, length); @@ -54,7 +55,6 @@ void on_request(uint8_t *public_key, uint8_t *data, uint16_t length) void on_message(int friendnumber, uint8_t *string, uint16_t length) { - wprintw(prompt->window, "\n(message) %d: %s\n", friendnumber, string); int i; for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { if (windows[i].onMessage != NULL) @@ -62,6 +62,15 @@ void on_message(int friendnumber, uint8_t *string, uint16_t length) } } +void on_action(int friendnumber, uint8_t *string, uint16_t length) +{ + int i; + for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + if (windows[i].onAction != NULL) + windows[i].onAction(&windows[i], friendnumber, string, length); + } +} + void on_nickchange(int friendnumber, uint8_t *string, uint16_t length) { wprintw(prompt->window, "\n(nickchange) %d: %s!\n", friendnumber, string); @@ -117,6 +126,7 @@ static void init_tox() m_callback_friendmessage(on_message); m_callback_namechange(on_nickchange); m_callback_statusmessage(on_statuschange); + m_callback_action(on_action); } void init_window_status() @@ -272,13 +282,13 @@ static void draw_bar() attron(A_BOLD); odd = (odd+1) % blinkrate; - if (windows[i].blink && (odd < (blinkrate/2))) { + if (windows[i].blink && (odd < (blinkrate/2))) attron(COLOR_PAIR(3)); - } + printw(" %s", windows[i].title); - if (windows[i].blink && (odd < (blinkrate/2))) { + if (windows[i].blink && (odd < (blinkrate/2))) attroff(COLOR_PAIR(3)); - } + if (i == active_window) { attroff(A_BOLD); } @@ -308,7 +318,6 @@ void set_active_window(int ch) i = (i + 1) % max; if (f_inf++ > max) { // infinite loop check endwin(); - clear(); exit(2); } } @@ -323,7 +332,6 @@ void set_active_window(int ch) if (--i < 0) i = max; if (f_inf++ > max) { endwin(); - clear(); exit(2); } } diff --git a/windows.h b/windows.h index 287e534..c6925ce 100644 --- a/windows.h +++ b/windows.h @@ -24,6 +24,7 @@ struct ToxWindow_ { void(*onMessage)(ToxWindow*, int, uint8_t*, uint16_t); void(*onNickChange)(ToxWindow*, int, uint8_t*, uint16_t); void(*onStatusChange)(ToxWindow*, int, uint8_t*, uint16_t); + void(*onAction)(ToxWindow*, int, uint8_t*, uint16_t); char title[256]; void* x; From 7de004aea1154c2e811eab359ea4d78ac9965273 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 8 Aug 2013 18:50:29 -0400 Subject: [PATCH 096/172] added -n argument to toxic to disable loading keys from file (for testing) --- main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 2922456..3c5c4be 100644 --- a/main.c +++ b/main.c @@ -354,6 +354,7 @@ int main(int argc, char *argv[]) char *user_config_dir = get_user_config_dir(); char *filename; int config_err = create_user_config_dir(user_config_dir); + uint8_t loadfromfile = 1; if(config_err) { filename = "data"; } else { @@ -374,13 +375,16 @@ int main(int argc, char *argv[]) filename = argv[i + 1]; else f_flag = -1; + } else if (argv[i][1] == 'n') { + loadfromfile = 0; } } } init_term(); init_tox(); - load_data(filename); + if(loadfromfile) + load_data(filename); free(filename); init_windows(); init_window_status(); From e40344186e14bb7baacf9e9ad99c5a76f88f479e Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 9 Aug 2013 00:25:45 -0400 Subject: [PATCH 097/172] fixed chat window text wrapping --- chat.c | 51 +++++++++++++++++++++++++++++++++------------------ main.c | 4 ++-- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/chat.c b/chat.c index 73cb145..33f51f2 100644 --- a/chat.c +++ b/chat.c @@ -14,6 +14,8 @@ #include "windows.h" +#define CURS_Y_OFFSET 3 + typedef struct { int friendnum; char line[MAX_STR_SIZE]; @@ -123,16 +125,35 @@ static void chat_onKey(ToxWindow *self, int key) struct tm * timeinfo; timeinfo = localtime(&now); - /* Add printable characters to line */ + int x, y, y2, x2; + getyx(self->window, y, x); + getmaxyx(self->window, y2, x2); + + /* Add printable chars to buffer and print on input space */ if (isprint(key)) { if (ctx->pos != sizeof(ctx->line)-1) { + mvwaddch(self->window, y, x, key); ctx->line[ctx->pos++] = key; ctx->line[ctx->pos] = '\0'; } } + /* BACKSPACE key: Remove one character from line */ + else if (key == 0x107 || key == 0x8 || key == 0x7f) { + if (ctx->pos > 0) { + ctx->line[--ctx->pos] = '\0'; + if (x == 0) + mvwdelch(self->window, y-1, x2-1); + else + mvwdelch(self->window, y, x-1); + } + } + /* RETURN key: Execute command or print line */ - else if (key == '\n') { + if (key == '\n') { + wclear(ctx->linewin); + wmove(self->window, y2-CURS_Y_OFFSET, 0); + wclrtobot(self->window); if (ctx->line[0] == '/') execute(self, ctx, ctx->line, timeinfo); else { @@ -155,13 +176,6 @@ static void chat_onKey(ToxWindow *self, int key) ctx->line[0] = '\0'; ctx->pos = 0; } - - /* BACKSPACE key: Remove one character from line */ - else if (key == 0x107 || key == 0x8 || key == 0x7f) { - if (ctx->pos != 0) { - ctx->line[--ctx->pos] = '\0'; - } - } } void execute(ToxWindow *self, ChatContext *ctx, char *cmd, struct tm *timeinfo) @@ -169,6 +183,10 @@ void execute(ToxWindow *self, ChatContext *ctx, char *cmd, struct tm *timeinfo) if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { wclear(self->window); wclear(ctx->history); + int x, y; + getmaxyx(self->window, y, x); + (void) x; + wmove(self->window, y-CURS_Y_OFFSET, 0); } else if (!strcmp(cmd, "/help") || !strcmp(cmd, "/h")) @@ -287,14 +305,10 @@ static void chat_onDraw(ToxWindow *self) { curs_set(1); int x, y; - ChatContext *ctx = (ChatContext*) self->x; getmaxyx(self->window, y, x); - (void) x; - if (y < 3) return; - - wclear(ctx->linewin); - mvwhline(ctx->linewin, 0, 0, '_', COLS); - mvwprintw(self->window, y-1, 0, "%s\n", ctx->line); + (void) y; + ChatContext *ctx = (ChatContext*) self->x; + mvwhline(ctx->linewin, 0, 0, '_', x); wrefresh(self->window); } @@ -303,10 +317,11 @@ static void chat_onInit(ToxWindow *self) int x, y; ChatContext *ctx = (ChatContext*) self->x; getmaxyx(self->window, y, x); - ctx->history = subwin(self->window, y - 4, x, 0, 0); + ctx->history = subwin(self->window, y-4, x, 0, 0); scrollok(ctx->history, 1); - ctx->linewin = subwin(self->window, 2, x, y - 3, 0); + ctx->linewin = subwin(self->window, 2, x, y-4, 0); print_help(ctx); + wmove(self->window, y-CURS_Y_OFFSET, 0); } void print_help(ChatContext *self) diff --git a/main.c b/main.c index 2922456..ce2e246 100644 --- a/main.c +++ b/main.c @@ -82,7 +82,7 @@ void on_action(int friendnumber, uint8_t *string, uint16_t length) void on_nickchange(int friendnumber, uint8_t *string, uint16_t length) { - wprintw(prompt->window, "\n(nickchange) %d: %s!\n", friendnumber, string); + wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string); int i; for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { if (windows[i].onNickChange != NULL) @@ -281,7 +281,7 @@ static void draw_bar() move(LINES - 1, 0); attron(COLOR_PAIR(4) | A_BOLD); - printw(" TOXIC " TOXICVER " |"); + printw(" TOXIC " TOXICVER "|"); attroff(COLOR_PAIR(4) | A_BOLD); int i; From 0314d11bf03231abc840ba70b8c6cd040e929451 Mon Sep 17 00:00:00 2001 From: Luke Champine Date: Fri, 9 Aug 2013 10:31:29 -0400 Subject: [PATCH 098/172] make toxic handle input in a more sane manner --- prompt.c | 514 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 267 insertions(+), 247 deletions(-) diff --git a/prompt.c b/prompt.c index eaa8d7b..e4eb259 100644 --- a/prompt.c +++ b/prompt.c @@ -16,10 +16,44 @@ uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX uint8_t num_requests=0; // XXX extern void on_friendadded(int friendnumber); -static void print_usage(ToxWindow *self); static char prompt_buf[MAX_STR_SIZE] = {0}; static int prompt_buf_pos = 0; +/* commands */ +void cmd_accept(ToxWindow *, char **); +void cmd_add(ToxWindow *, char **); +void cmd_clear(ToxWindow *, char **); +void cmd_connect(ToxWindow *, char **); +void cmd_help(ToxWindow *, char **); +void cmd_msg(ToxWindow *, char **); +void cmd_myid(ToxWindow *, char **); +void cmd_nick(ToxWindow *, char **); +void cmd_quit(ToxWindow *, char **); +void cmd_status(ToxWindow *, char **); +void cmd_statusmsg(ToxWindow *, char **); + +#define NUM_COMMANDS 13 + +static struct { + char *name; + int numargs; + void (*func)(ToxWindow *, char **); +} commands[] = { + { "accept", 1, cmd_accept }, + { "add", 2, cmd_add }, + { "clear", 0, cmd_clear }, + { "connect", 3, cmd_connect }, + { "exit", 0, cmd_quit }, + { "help", 0, cmd_help }, + { "msg", 2, cmd_msg }, + { "myid", 0, cmd_myid }, + { "nick", 1, cmd_nick }, + { "q", 0, cmd_quit }, + { "quit", 0, cmd_quit }, + { "status", 2, cmd_status }, + { "statusmsg", 1, cmd_statusmsg }, +}; + // XXX: int add_req(uint8_t *public_key) { @@ -40,6 +74,209 @@ unsigned char *hex_string_to_bin(char hex_string[]) return val; } +void cmd_accept(ToxWindow *self, char **args) +{ + int num = atoi(args[1]); + if (num >= num_requests) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + + num = m_addfriend_norequest(pending_requests[num]); + if (num == -1) + wprintw(self->window, "Failed to add friend.\n"); + else { + wprintw(self->window, "Friend accepted as: %d.\n", num); + on_friendadded(num); + } +} + +void cmd_add(ToxWindow *self, char **args) +{ + uint8_t id_bin[KEY_SIZE_BYTES]; + char xx[3]; + uint32_t x; + char *id = args[1]; + char *msg = args[2]; + + if (!id) { + wprintw(self->window, "Invalid command: add expected at least one argument.\n"); + return; + } + if (!msg) + msg = ""; + + if (strlen(id) != 2*KEY_SIZE_BYTES) { + wprintw(self->window, "Invalid ID length.\n"); + return; + } + int i; + for (i = 0; i < KEY_SIZE_BYTES; ++i) { + xx[0] = id[2*i]; + xx[1] = id[2*i+1]; + xx[2] = '\0'; + if (sscanf(xx, "%02x", &x) != 1) { + wprintw(self->window, "Invalid ID.\n"); + return; + } + id_bin[i] = x; + } + int num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); + switch (num) { + case FAERR_TOOLONG: + wprintw(self->window, "Message is too long.\n"); + break; + case FAERR_NOMESSAGE: + wprintw(self->window, "Please add a message to your request.\n"); + break; + case FAERR_OWNKEY: + wprintw(self->window, "That appears to be your own ID.\n"); + break; + case FAERR_ALREADYSENT: + wprintw(self->window, "Friend request already sent.\n"); + break; + case FAERR_UNKNOWN: + wprintw(self->window, "Undefined error when adding friend.\n"); + break; + default: + wprintw(self->window, "Friend added as %d.\n", num); + on_friendadded(num); + break; + } +} + +void cmd_clear(ToxWindow *self, char **args) +{ + wclear(self->window); +} + +void cmd_connect(ToxWindow *self, char **args) +{ + IP_Port dht; + char *ip = args[1]; + char *port = args[2]; + char *key = args[3]; + + if (atoi(port) == 0) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + + dht.port = htons(atoi(port)); + uint32_t resolved_address = resolve_addr(ip); + if (resolved_address == 0) { + return; + } + + dht.ip.i = resolved_address; + unsigned char *binary_string = hex_string_to_bin(key); + DHT_bootstrap(dht, binary_string); + free(binary_string); +} + +void cmd_quit(ToxWindow *self, char **args) +{ + endwin(); + exit(0); +} + +void cmd_help(ToxWindow *self, char **args) +{ + wclear(self->window); + wattron(self->window, COLOR_PAIR(2) | A_BOLD); + wprintw(self->window, "Commands:\n"); + wattroff(self->window, A_BOLD); + + wprintw(self->window, " connect : Connect to DHT server\n"); + wprintw(self->window, " add : Add friend\n"); + wprintw(self->window, " status : Set your status\n"); + wprintw(self->window, " statusmsg : Set your status\n"); + wprintw(self->window, " nick : Set your nickname\n"); + wprintw(self->window, " accept : Accept friend request\n"); + wprintw(self->window, " myid : Print your ID\n"); + wprintw(self->window, " quit/exit : Exit program\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, "TIP: Use the TAB key to navigate through the tabs.\n\n"); + wattroff(self->window, A_BOLD); + + wattroff(self->window, COLOR_PAIR(2)); +} + +void cmd_msg(ToxWindow *self, char **args) +{ + char *id = args[1]; + char *msg = args[2]; + if (m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) == 0) + wprintw(self->window, "Error occurred while sending message.\n"); + else + wprintw(self->window, "Message successfully sent.\n"); +} + +void cmd_myid(ToxWindow *self, char **args) +{ + char id[KEY_SIZE_BYTES*2 + 1] = {0}; + size_t i; + for (i = 0; i < KEY_SIZE_BYTES; ++i) { + char xx[3]; + snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); + strcat(id, xx); + } + wprintw(self->window, "Your ID: %s\n", id); +} + +void cmd_nick(ToxWindow *self, char **args) +{ + char *nick = args[1]; + setname((uint8_t*) nick, strlen(nick)+1); + wprintw(self->window, "Nickname set to: %s\n", nick); +} + +void cmd_status(ToxWindow *self, char **args) +{ + char *status = args[1]; + char *status_text; + + USERSTATUS status_kind; + if (!strncmp(status, "online", strlen("online"))) { + status_kind = USERSTATUS_NONE; + status_text = "ONLINE"; + } + else if (!strncmp(status, "away", strlen("away"))) { + status_kind = USERSTATUS_AWAY; + status_text = "AWAY"; + } + else if (!strncmp(status, "busy", strlen("busy"))) { + status_kind = USERSTATUS_BUSY; + status_text = "BUSY"; + } + else + { + wprintw(self->window, "Invalid status.\n"); + return; + } + + char *msg = args[2]; + if (msg == NULL) { + m_set_userstatus(status_kind); + wprintw(self->window, "Status set to: %s\n", status_text); + } + else { + m_set_userstatus(status_kind); + m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); + wprintw(self->window, "Status set to: %s, %s\n", status_text, msg); + } +} + +void cmd_statusmsg(ToxWindow *self, char **args) +{ + char *msg = args[1]; + m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); + wprintw(self->window, "Status set to: %s\n", msg); +} + static void execute(ToxWindow *self, char *u_cmd) { int newlines = 0; @@ -62,237 +299,43 @@ static void execute(ToxWindow *self, char *u_cmd) if (!isspace(cmd[cmd_end])) break; cmd[cmd_end + 1] = '\0'; - -/* What is this supposed to do? - if (cmd[0] == '/') { - wprintw(self->window,"Warning: Run your command without the /, this may not work\n"); - int i; - for (i = 1; i < strlen(cmd); i++) { //This doesn't work when it doesn't end with a space and another word - cmd[i - 1] = cmd[i]; //Still working on why - } - } -*/ - if (!strcmp(cmd, "quit") || !strcmp(cmd, "exit") || !strcmp(cmd, "q")) { - endwin(); - exit(0); - } + char *args[4]; + args[0] = strtok(cmd, " "); - else if (!strncmp(cmd, "connect ", strlen("connect "))) { - IP_Port dht; - char *ip = strchr(cmd, ' '); - if (ip == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - ip++; + /* no input */ + if (!args[0]) + return; - char *port = strchr(ip, ' '); - if (port == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - port[0] = 0; - port++; - - char *key = strchr(port, ' '); - if (key == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - key[0] = 0; - key++; - - if (atoi(port) == 0) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - - dht.port = htons(atoi(port)); - uint32_t resolved_address = resolve_addr(ip); - if (resolved_address == 0) { - return; - } - - dht.ip.i = resolved_address; - unsigned char *binary_string = hex_string_to_bin(key); - DHT_bootstrap(dht, binary_string); - free(binary_string); - } - - else if (!strncmp(cmd, "add ", strlen("add "))) { - uint8_t id_bin[KEY_SIZE_BYTES]; - char xx[3]; - uint32_t x; - char *id = strchr(cmd, ' '); - if (id == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - id++; - char *msg = strchr(id, ' '); - if (msg != NULL) { - msg[0] = 0; - msg++; - } - else msg = ""; - if (strlen(id) != 2*KEY_SIZE_BYTES) { - wprintw(self->window, "Invalid ID length.\n"); - return; - } - int i; - for (i = 0; i < KEY_SIZE_BYTES; ++i) { - xx[0] = id[2*i]; - xx[1] = id[2*i+1]; - xx[2] = '\0'; - if (sscanf(xx, "%02x", &x) != 1) { - wprintw(self->window, "Invalid ID.\n"); + /* match input to command list */ + for (i = 0; i < NUM_COMMANDS; i++) { + if (!strcmp(args[0], commands[i].name)) { + /* read in arguments */ + int j; + for (j = 1; j <= commands[i].numargs; j++) { + args[j] = strtok(NULL, " "); + /* check for missing arguments */ + /* add is special because it can take either 1 or 2 arguments */ + if (strcmp(args[0], "add") != 0 && args[j] == NULL) { + wprintw(self->window, "Invalid command: %s expected %d arguments, got %d.\n", + commands[i].name, commands[i].numargs, j - 1); + return; + } + } + /* check for excess arguments */ + /* add is special because the add message may contain spaces */ + if (strcmp(args[0], "add") != 0 && strtok(NULL, " ") != NULL) { + wprintw(self->window, "Invalid command: too many arguments to %s.\n", commands[i].name); return; } - id_bin[i] = x; - } - int num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); - switch (num) { - case -1: - wprintw(self->window, "Message is too long.\n"); - break; - case -2: - wprintw(self->window, "Please add a message to your request.\n"); - break; - case -3: - wprintw(self->window, "That appears to be your own ID.\n"); - break; - case -4: - wprintw(self->window, "Friend request already sent.\n"); - break; - case -5: - wprintw(self->window, "Undefined error when adding friend.\n"); - break; - default: - wprintw(self->window, "Friend added as %d.\n", num); - on_friendadded(num); - break; - } - } - - else if (!strcmp(cmd, "clear")) { - wclear(self->window); - } - - else if (!strcmp(cmd, "help")) { - wclear(self->window); - print_usage(self); - } - - else if (!strncmp(cmd, "status ", strlen("status "))) { - char *status = strchr(cmd, ' '); - char *msg; - char *status_text; - if (status == NULL) { - wprintw(self->window, "Invalid syntax.\n"); + /* pass arguments to command function */ + (commands[i].func)(self, args); return; } - status++; - USERSTATUS status_kind; - if (!strncmp(status, "online", strlen("online"))) { - status_kind = USERSTATUS_NONE; - status_text = "ONLINE"; - } - - else if (!strncmp(status, "away", strlen("away"))) { - status_kind = USERSTATUS_AWAY; - status_text = "AWAY"; - } - - else if (!strncmp(status, "busy", strlen("busy"))) { - status_kind = USERSTATUS_BUSY; - status_text = "BUSY"; - } - - else - { - wprintw(self->window, "Invalid status.\n"); - return; - } - - msg = strchr(status, ' '); - if (msg == NULL) { - m_set_userstatus(status_kind); - wprintw(self->window, "Status set to: %s\n", status_text); - } - else { - msg++; - m_set_userstatus(status_kind); - m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); - wprintw(self->window, "Status set to: %s, %s\n", status_text, msg); - } } - else if (!strncmp(cmd, "nick ", strlen("nick "))) { - char *nick = strchr(cmd, ' '); - if (nick == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - nick++; - setname((uint8_t*) nick, strlen(nick)+1); - wprintw(self->window, "Nickname set to: %s\n", nick); - } - - else if (!strcmp(cmd, "myid")) { - char id[KEY_SIZE_BYTES*2 + 1] = {0}; - size_t i; - for (i = 0; i < KEY_SIZE_BYTES; ++i) { - char xx[3]; - snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); - strcat(id, xx); - } - wprintw(self->window, "Your ID: %s\n", id); - } - - else if (!strncmp(cmd, "accept ", strlen("accept "))) { - char *id = strchr(cmd, ' '); - if (id == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - id++; - - int num = atoi(id); - if (num >= num_requests) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - - num = m_addfriend_norequest(pending_requests[num]); - if (num == -1) - wprintw(self->window, "Failed to add friend.\n"); - else { - wprintw(self->window, "Friend accepted as: %d.\n", num); - on_friendadded(num); - } - } - - else if (!strncmp(cmd, "msg ", strlen("msg "))) { - char *id = strchr(cmd, ' '); - if (id == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - char *msg = strchr(++id, ' '); - if (msg == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - msg[0] = 0; - msg++; - if (m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) == 0) - wprintw(self->window, "Error occurred while sending message.\n"); - else - wprintw(self->window, "Message successfully sent.\n"); - } - else - wprintw(self->window, "Invalid command.\n"); + /* no match */ + wprintw(self->window, "Invalid command.\n"); } static void prompt_onKey(ToxWindow *self, int key) @@ -352,33 +395,10 @@ static void prompt_onDraw(ToxWindow *self) wrefresh(self->window); } -static void print_usage(ToxWindow *self) -{ - wattron(self->window, COLOR_PAIR(2) | A_BOLD); - wprintw(self->window, "Commands:\n"); - wattroff(self->window, A_BOLD); - - wprintw(self->window, " connect : Connect to DHT server\n"); - wprintw(self->window, " add : Add friend\n"); - wprintw(self->window, " status : Set your status\n"); - wprintw(self->window, " nick : Set your nickname\n"); - wprintw(self->window, " accept : Accept friend request\n"); - wprintw(self->window, " myid : Print your ID\n"); - wprintw(self->window, " quit/exit : Exit program\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, "TIP: Use the TAB key to navigate through the tabs.\n\n"); - wattroff(self->window, A_BOLD); - - wattroff(self->window, COLOR_PAIR(2)); -} - static void prompt_onInit(ToxWindow *self) { scrollok(self->window, 1); - print_usage(self); + cmd_help(self, NULL); wclrtoeol(self->window); } From 7d0a56e6a6c9a59283fc0288b75344c34a59ca49 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sat, 10 Aug 2013 15:46:29 -0400 Subject: [PATCH 099/172] auto-connect to DHT on startup --- chat.c | 2 +- main.c | 99 ++++++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 76 insertions(+), 25 deletions(-) diff --git a/chat.c b/chat.c index 33f51f2..e189723 100644 --- a/chat.c +++ b/chat.c @@ -150,7 +150,7 @@ static void chat_onKey(ToxWindow *self, int key) } /* RETURN key: Execute command or print line */ - if (key == '\n') { + else if (key == '\n') { wclear(ctx->linewin); wmove(self->window, y2-CURS_Y_OFFSET, 0); wclrtobot(self->window); diff --git a/main.c b/main.c index bb5faf8..8805d12 100644 --- a/main.c +++ b/main.c @@ -28,6 +28,8 @@ extern ToxWindow new_friendlist(); extern int friendlist_onFriendAdded(int num); extern void disable_chatwin(int f_num); extern int add_req(uint8_t *public_key); // XXX +extern void cmd_connect(ToxWindow *self, char **args); +extern unsigned char *hex_string_to_bin(char hex_string[]); /* Holds status of chat windows */ char WINDOW_STATUS[MAX_WINDOW_SLOTS]; @@ -138,6 +140,51 @@ static void init_tox() m_callback_action(on_action); } +#define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */ +#define MAXSERVERS 50 + +/* Connects to a random DHT server listed in the DHTservers file */ +int init_connection(void) +{ + if (DHT_isconnected()) + return 0; + + FILE *fp = fopen("../../../other/DHTservers", "r"); + if (fp == NULL) + return 1; + + char servers[MAXSERVERS][MAXLINE]; + char line[MAXLINE]; + int linecnt = 0; + while (fgets(line, sizeof(line), fp) && linecnt < MAXSERVERS) { + int len = strlen(line); + if (len > 74 && len < MAXLINE) + strcpy(servers[linecnt++], line); + } + if (linecnt < 1) { + fclose(fp); + return 2; + } + fclose(fp); + + int servnum = rand() % linecnt; + char *server = servers[servnum]; + char *ip = strtok(server, " "); + char *port = strtok(NULL, " "); + char *key = strtok(NULL, " "); + + IP_Port dht; + dht.port = htons(atoi(port)); + uint32_t resolved_address = resolve_addr(ip); + if (resolved_address == 0) + return 3; + dht.ip.i = resolved_address; + unsigned char *binary_string = hex_string_to_bin(key); + DHT_bootstrap(dht, binary_string); + free(binary_string); + return 0; +} + void init_window_status() { /* Default window values decrement from -2 */ @@ -203,11 +250,11 @@ static void do_tox() static bool dht_on = false; if (!dht_on && DHT_isconnected()) { dht_on = true; - wprintw(prompt->window, "\nDHT connected!\n"); + wprintw(prompt->window, "\nDHT connected.\n"); } else if (dht_on && !DHT_isconnected()) { dht_on = false; - wprintw(prompt->window, "\nDHT disconnected!\n"); + wprintw(prompt->window, "\nDHT disconnected.\n"); } doMessenger(); } @@ -350,21 +397,22 @@ void set_active_window(int ch) int main(int argc, char *argv[]) { int ch; - int f_flag = 0; - char *user_config_dir = get_user_config_dir(); - char *filename; - int config_err = create_user_config_dir(user_config_dir); - uint8_t loadfromfile = 1; - if(config_err) { - filename = "data"; - } else { - filename = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); - strcpy(filename, user_config_dir); - strcat(filename, CONFIGDIR); - strcat(filename, "data"); - } - ToxWindow* a; + char *user_config_dir = get_user_config_dir(); + char *DATA_FILE; + int config_err = create_user_config_dir(user_config_dir); + if(config_err) { + DATA_FILE = "data"; + } else { + DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); + strcpy(DATA_FILE, user_config_dir); + strcat(DATA_FILE, CONFIGDIR); + strcat(DATA_FILE, "data"); + } + + /* This is broken */ + int f_loadfromfile = 1; + int f_flag = 0; int i = 0; for (i = 0; i < argc; ++i) { if (argv[i] == NULL) @@ -372,37 +420,40 @@ int main(int argc, char *argv[]) else if (argv[i][0] == '-') { if (argv[i][1] == 'f') { if (argv[i + 1] != NULL) - filename = argv[i + 1]; + DATA_FILE = argv[i + 1]; else f_flag = -1; } else if (argv[i][1] == 'n') { - loadfromfile = 0; + f_loadfromfile = 0; } } } + if(f_loadfromfile) + load_data(DATA_FILE); + free(DATA_FILE); init_term(); init_tox(); - if(loadfromfile) - load_data(filename); - free(filename); init_windows(); init_window_status(); + int connected = init_connection(); + if (connected != 0) + wprintw(prompt->window, "Auto-connect failed (error code %d)\n", connected); + if (f_flag == -1) { attron(COLOR_PAIR(3) | A_BOLD); - wprintw(prompt->window, "You passed '-f' without giving an argument!\n" + wprintw(prompt->window, "You passed '-f' without giving an argument.\n" "defaulting to 'data' for a keyfile...\n"); attroff(COLOR_PAIR(3) | A_BOLD); } if(config_err) { attron(COLOR_PAIR(3) | A_BOLD); - wprintw(prompt->window, "Unable to determine configuration directory!\n" + wprintw(prompt->window, "Unable to determine configuration directory.\n" "defaulting to 'data' for a keyfile...\n"); attroff(COLOR_PAIR(3) | A_BOLD); } - while(true) { /* Update tox */ do_tox(); From d99e8c9926be3f333c1f94d2954ab5e084d51837 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sat, 10 Aug 2013 15:50:49 -0400 Subject: [PATCH 100/172] don't need that --- main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/main.c b/main.c index 8805d12..865c911 100644 --- a/main.c +++ b/main.c @@ -28,7 +28,6 @@ extern ToxWindow new_friendlist(); extern int friendlist_onFriendAdded(int num); extern void disable_chatwin(int f_num); extern int add_req(uint8_t *public_key); // XXX -extern void cmd_connect(ToxWindow *self, char **args); extern unsigned char *hex_string_to_bin(char hex_string[]); /* Holds status of chat windows */ From 35f7ba210d7f61638c0a9b2856d5f15ff31db2fd Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sat, 10 Aug 2013 16:28:40 -0400 Subject: [PATCH 101/172] fix memory leak --- configdir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configdir.c b/configdir.c index d91d080..6cbb06b 100644 --- a/configdir.c +++ b/configdir.c @@ -129,8 +129,8 @@ int create_user_config_dir(char *path) free(fullpath); return -1; } - + #endif - + free(fullpath); return 0; } From 31a9a344d2a811532ea808c03c037032fc038fa2 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sat, 10 Aug 2013 18:00:54 -0400 Subject: [PATCH 102/172] was making the ID change on every startup --- main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index 865c911..3db963b 100644 --- a/main.c +++ b/main.c @@ -427,14 +427,15 @@ int main(int argc, char *argv[]) } } } - if(f_loadfromfile) - load_data(DATA_FILE); - free(DATA_FILE); init_term(); init_tox(); init_windows(); init_window_status(); + + if(f_loadfromfile) + load_data(DATA_FILE); + free(DATA_FILE); int connected = init_connection(); if (connected != 0) From 309de728299565242b3a4c30a21ca7dff277b186 Mon Sep 17 00:00:00 2001 From: lukechampine Date: Sat, 10 Aug 2013 20:10:03 -0400 Subject: [PATCH 103/172] make argument handling (esp. of strings) more robust --- prompt.c | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/prompt.c b/prompt.c index e4eb259..ab44e96 100644 --- a/prompt.c +++ b/prompt.c @@ -40,7 +40,7 @@ static struct { void (*func)(ToxWindow *, char **); } commands[] = { { "accept", 1, cmd_accept }, - { "add", 2, cmd_add }, + { "add", 1, cmd_add }, { "clear", 0, cmd_clear }, { "connect", 3, cmd_connect }, { "exit", 0, cmd_quit }, @@ -300,36 +300,54 @@ static void execute(ToxWindow *self, char *u_cmd) break; cmd[cmd_end + 1] = '\0'; - char *args[4]; - args[0] = strtok(cmd, " "); + /* insert \0 at argument boundaries */ + int numargs = 0; + for (i = 0; i < MAX_STR_SIZE; i++) { + if (cmd[i] == '\"') + while (cmd[++i] != '\"'); /* skip over strings */ + if (cmd[i] == ' ') { + cmd[i] = '\0'; + numargs++; + } + } + + /* excessive arguments */ + if (numargs > 3) { + wprintw(self->window, "Invalid command: too many arguments.\n"); + return; + } + + /* read arguments into array */ + char *cmdargs[5]; + int pos = 0; + for (i = 0; i < 5; i++) { + cmdargs[i] = cmd + pos; + pos += strlen(cmdargs[i]) + 1; + } /* no input */ - if (!args[0]) + if (strlen(cmdargs[0]) == 0) return; /* match input to command list */ for (i = 0; i < NUM_COMMANDS; i++) { - if (!strcmp(args[0], commands[i].name)) { - /* read in arguments */ + if (!strcmp(cmdargs[0], commands[i].name)) { + /* check for missing arguments */ int j; - for (j = 1; j <= commands[i].numargs; j++) { - args[j] = strtok(NULL, " "); - /* check for missing arguments */ - /* add is special because it can take either 1 or 2 arguments */ - if (strcmp(args[0], "add") != 0 && args[j] == NULL) { + for (j = 0; j <= commands[i].numargs; j++) { + if (strlen(cmdargs[j]) == 0) { wprintw(self->window, "Invalid command: %s expected %d arguments, got %d.\n", commands[i].name, commands[i].numargs, j - 1); return; } } - /* check for excess arguments */ - /* add is special because the add message may contain spaces */ - if (strcmp(args[0], "add") != 0 && strtok(NULL, " ") != NULL) { + /* check for excess arguments */ + if (strcmp(cmdargs[0], "add") && strlen(cmdargs[j]) != 0) { wprintw(self->window, "Invalid command: too many arguments to %s.\n", commands[i].name); return; } /* pass arguments to command function */ - (commands[i].func)(self, args); + (commands[i].func)(self, cmdargs); return; } } From 663f4eb4ff773d99c289fd24970da80c35773b0d Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 11 Aug 2013 00:55:09 -0400 Subject: [PATCH 104/172] potential seg fault --- main.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/main.c b/main.c index 3db963b..d7d375a 100644 --- a/main.c +++ b/main.c @@ -140,6 +140,7 @@ static void init_tox() } #define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */ +#define MINLINE 70 #define MAXSERVERS 50 /* Connects to a random DHT server listed in the DHTservers file */ @@ -149,7 +150,7 @@ int init_connection(void) return 0; FILE *fp = fopen("../../../other/DHTservers", "r"); - if (fp == NULL) + if (!fp) return 1; char servers[MAXSERVERS][MAXLINE]; @@ -157,7 +158,7 @@ int init_connection(void) int linecnt = 0; while (fgets(line, sizeof(line), fp) && linecnt < MAXSERVERS) { int len = strlen(line); - if (len > 74 && len < MAXLINE) + if (len > MINLINE && len < MAXLINE) strcpy(servers[linecnt++], line); } if (linecnt < 1) { @@ -166,17 +167,18 @@ int init_connection(void) } fclose(fp); - int servnum = rand() % linecnt; - char *server = servers[servnum]; + char *server = servers[rand() % linecnt]; char *ip = strtok(server, " "); char *port = strtok(NULL, " "); char *key = strtok(NULL, " "); + if (!ip || !port || !key) + return 3; IP_Port dht; dht.port = htons(atoi(port)); uint32_t resolved_address = resolve_addr(ip); if (resolved_address == 0) - return 3; + return 4; dht.ip.i = resolved_address; unsigned char *binary_string = hex_string_to_bin(key); DHT_bootstrap(dht, binary_string); @@ -432,7 +434,7 @@ int main(int argc, char *argv[]) init_tox(); init_windows(); init_window_status(); - + if(f_loadfromfile) load_data(DATA_FILE); free(DATA_FILE); From 652f7aec269d935aefd80992d1fb3d1c2f0d5777 Mon Sep 17 00:00:00 2001 From: Simon Levermann Date: Sun, 11 Aug 2013 17:51:10 +0200 Subject: [PATCH 105/172] Fix a possible memory leak --- main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/main.c b/main.c index d7d375a..752453f 100644 --- a/main.c +++ b/main.c @@ -410,6 +410,7 @@ int main(int argc, char *argv[]) strcat(DATA_FILE, CONFIGDIR); strcat(DATA_FILE, "data"); } + free(user_config_dir); /* This is broken */ int f_loadfromfile = 1; From a8d2ab1af0abae9bbec47a8de74b4d120c108e80 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 12 Aug 2013 03:10:47 -0400 Subject: [PATCH 106/172] make connection more robust --- main.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/main.c b/main.c index 752453f..9bf0b9f 100644 --- a/main.c +++ b/main.c @@ -157,8 +157,7 @@ int init_connection(void) char line[MAXLINE]; int linecnt = 0; while (fgets(line, sizeof(line), fp) && linecnt < MAXSERVERS) { - int len = strlen(line); - if (len > MINLINE && len < MAXLINE) + if (strlen(line) > MINLINE) strcpy(servers[linecnt++], line); } if (linecnt < 1) { @@ -248,14 +247,21 @@ static void init_windows() static void do_tox() { + static int conn_try = 1; static bool dht_on = false; - if (!dht_on && DHT_isconnected()) { + if (!dht_on && !DHT_isconnected()) { + init_connection(); + if (!(conn_try++ % 100)) + wprintw(prompt->window, "\nAttempting to connect...\n"); + } + else if (!dht_on && DHT_isconnected()) { dht_on = true; wprintw(prompt->window, "\nDHT connected.\n"); } else if (dht_on && !DHT_isconnected()) { dht_on = false; - wprintw(prompt->window, "\nDHT disconnected.\n"); + wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n"); + init_connection(); } doMessenger(); } @@ -440,10 +446,6 @@ int main(int argc, char *argv[]) load_data(DATA_FILE); free(DATA_FILE); - int connected = init_connection(); - if (connected != 0) - wprintw(prompt->window, "Auto-connect failed (error code %d)\n", connected); - if (f_flag == -1) { attron(COLOR_PAIR(3) | A_BOLD); wprintw(prompt->window, "You passed '-f' without giving an argument.\n" From 8687a54a879b11df2e54be4677a5e835d3991896 Mon Sep 17 00:00:00 2001 From: Chris Hall Date: Sun, 11 Aug 2013 15:24:11 +1200 Subject: [PATCH 107/172] Messenger refactor - redid work from pull request 79 Moves static state out of Messenger.c and into a Messenger struct Purely stylistic, no functional changes were made. This commit also changed all the callers of Messenger as they now have to pass an instance of the Messenger struct to messenger functions. Also removed some uses of the 'static' keyword at the beginning of function definitions when the function was already declared static, as these caused gcc to whine. --- chat.c | 36 ++++++++++++------------ friendlist.c | 16 +++++------ main.c | 47 ++++++++++++++++--------------- prompt.c | 78 ++++++++++++++++++++++++++-------------------------- windows.h | 10 +++---- 5 files changed, 95 insertions(+), 92 deletions(-) diff --git a/chat.c b/chat.c index e189723..112b20b 100644 --- a/chat.c +++ b/chat.c @@ -29,9 +29,9 @@ extern int active_window; extern void del_window(ToxWindow *w, int f_num); extern void fix_name(uint8_t *name); void print_help(ChatContext *self); -void execute(ToxWindow *self, ChatContext *ctx, char *cmd, struct tm *timeinfo); +void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd, struct tm *timeinfo); -static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len) +static void chat_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *msg, uint16_t len) { ChatContext *ctx = (ChatContext*) self->x; uint8_t nick[MAX_NAME_LENGTH] = {0}; @@ -43,7 +43,7 @@ static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len) if (ctx->friendnum != num) return; - getname(num, (uint8_t*) &nick); + getname(m, num, (uint8_t*) &nick); msg[len-1] = '\0'; nick[MAX_NAME_LENGTH-1] = '\0'; fix_name(msg); @@ -61,7 +61,7 @@ static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len) beep(); } -static void chat_onAction(ToxWindow *self, int num, uint8_t *action, uint16_t len) +static void chat_onAction(ToxWindow *self, Messenger *m, int num, uint8_t *action, uint16_t len) { ChatContext *ctx = (ChatContext*) self->x; time_t now; @@ -117,7 +117,7 @@ int string_is_empty(char *string) return rc; } -static void chat_onKey(ToxWindow *self, int key) +static void chat_onKey(ToxWindow *self, Messenger *m, int key) { ChatContext *ctx = (ChatContext*) self->x; time_t now; @@ -155,7 +155,7 @@ static void chat_onKey(ToxWindow *self, int key) wmove(self->window, y2-CURS_Y_OFFSET, 0); wclrtobot(self->window); if (ctx->line[0] == '/') - execute(self, ctx, ctx->line, timeinfo); + execute(self, ctx, m, ctx->line, timeinfo); else { if (!string_is_empty(ctx->line)) { /* make sure the string has at least non-space character */ @@ -167,7 +167,7 @@ static void chat_onKey(ToxWindow *self, int key) wattroff(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "%s\n", ctx->line); } - if (m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) == 0) { + if (m_sendmessage(m, ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) == 0) { wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Failed to send message.\n"); wattroff(ctx->history, COLOR_PAIR(3)); @@ -178,7 +178,7 @@ static void chat_onKey(ToxWindow *self, int key) } } -void execute(ToxWindow *self, ChatContext *ctx, char *cmd, struct tm *timeinfo) +void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd, struct tm *timeinfo) { if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { wclear(self->window); @@ -210,14 +210,14 @@ void execute(ToxWindow *self, ChatContext *ctx, char *cmd, struct tm *timeinfo) wattroff(ctx->history, COLOR_PAIR(2)); uint8_t selfname[MAX_NAME_LENGTH]; - int len = getself_name(selfname); + int len = getself_name(m, selfname); char msg[MAX_STR_SIZE-len-4]; snprintf(msg, sizeof(msg), "* %s %s\n", (uint8_t*) selfname, action); wattron(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, msg); wattroff(ctx->history, COLOR_PAIR(1)); - if (m_sendaction(ctx->friendnum, (uint8_t*) msg, strlen(msg)+1) < 0) { + if (m_sendaction(m, ctx->friendnum, (uint8_t*) msg, strlen(msg)+1) < 0) { wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Failed to send action\n"); wattroff(ctx->history, COLOR_PAIR(3)); @@ -256,13 +256,13 @@ void execute(ToxWindow *self, ChatContext *ctx, char *cmd, struct tm *timeinfo) msg = strchr(status, ' '); if (msg == NULL) { - m_set_userstatus(status_kind); + m_set_userstatus(m, status_kind); wprintw(ctx->history, "Status set to: %s\n", status_text); } else { msg++; - m_set_userstatus(status_kind); - m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); + m_set_userstatus(m, status_kind); + m_set_statusmessage(m, ( uint8_t*) msg, strlen(msg)+1); wprintw(ctx->history, "Status set to: %s, %s\n", status_text, msg); } } @@ -275,7 +275,7 @@ void execute(ToxWindow *self, ChatContext *ctx, char *cmd, struct tm *timeinfo) return; } nick++; - setname((uint8_t*) nick, strlen(nick)+1); + setname(m, (uint8_t*) nick, strlen(nick)+1); wprintw(ctx->history, "Nickname set to: %s\n", nick); } @@ -312,7 +312,7 @@ static void chat_onDraw(ToxWindow *self) wrefresh(self->window); } -static void chat_onInit(ToxWindow *self) +static void chat_onInit(ToxWindow *self, Messenger *m) { int x, y; ChatContext *ctx = (ChatContext*) self->x; @@ -329,7 +329,7 @@ void print_help(ChatContext *self) wattron(self->history, COLOR_PAIR(2) | A_BOLD); wprintw(self->history, "Commands:\n"); wattroff(self->history, A_BOLD); - + wprintw(self->history, " /status : Set your status\n"); wprintw(self->history, " /nick : Set your nickname\n"); wprintw(self->history, " /me : Do an action\n"); @@ -342,7 +342,7 @@ void print_help(ChatContext *self) wattroff(self->history, COLOR_PAIR(2)); } -ToxWindow new_chat(int friendnum) +ToxWindow new_chat(Messenger *m, int friendnum) { ToxWindow ret; memset(&ret, 0, sizeof(ret)); @@ -356,7 +356,7 @@ ToxWindow new_chat(int friendnum) ret.onAction = &chat_onAction; uint8_t nick[MAX_NAME_LENGTH] = {0}; - getname(friendnum, (uint8_t*) &nick); + getname(m, friendnum, (uint8_t*) &nick); fix_name(nick); snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum); diff --git a/friendlist.c b/friendlist.c index f2aa1cf..56061cf 100644 --- a/friendlist.c +++ b/friendlist.c @@ -14,7 +14,7 @@ extern char WINDOW_STATUS[TOXWINDOWS_MAX_NUM]; extern int add_window(ToxWindow w, int n); -extern ToxWindow new_chat(int friendnum); +extern ToxWindow new_chat(Messenger *m, int friendnum); extern int active_window; @@ -42,7 +42,7 @@ void fix_name(uint8_t *name) *q = 0; } -void friendlist_onMessage(ToxWindow *self, int num, uint8_t *str, uint16_t len) +void friendlist_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *str, uint16_t len) { if (num >= num_friends) return; @@ -54,7 +54,7 @@ void friendlist_onMessage(ToxWindow *self, int num, uint8_t *str, uint16_t len) for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { if (WINDOW_STATUS[i] == -1) { WINDOW_STATUS[i] = num; - add_window(new_chat(num), i); + add_window(new_chat(m, num), i); active_window = i; break; } @@ -82,20 +82,20 @@ void friendlist_onStatusChange(ToxWindow *self, int num, uint8_t *str, uint16_t fix_name(friends[num].status); } -int friendlist_onFriendAdded(int num) +int friendlist_onFriendAdded(Messenger *m, int num) { if (num_friends == MAX_FRIENDS_NUM) return -1; friends[num_friends].num = num; - getname(num, friends[num_friends].name); + getname(m, num, friends[num_friends].name); strcpy((char*) friends[num_friends].name, "unknown"); strcpy((char*) friends[num_friends].status, "unknown"); friends[num_friends++].chatwin = -1; return 0; } -static void friendlist_onKey(ToxWindow *self, int key) +static void friendlist_onKey(ToxWindow *self, Messenger *m, int key) { if (key == KEY_UP) { if (--num_selected < 0) @@ -121,7 +121,7 @@ static void friendlist_onKey(ToxWindow *self, int key) if (WINDOW_STATUS[i] == -1) { WINDOW_STATUS[i] = num_selected; friends[num_selected].chatwin = num_selected; - add_window(new_chat(num_selected), i); + add_window(new_chat(m, num_selected), i); active_window = i; break; } @@ -164,7 +164,7 @@ void disable_chatwin(int f_num) friends[f_num].chatwin = -1; } -static void friendlist_onInit(ToxWindow *self) +static void friendlist_onInit(ToxWindow *self, Messenger *m) { } diff --git a/main.c b/main.c index 752453f..c14dee1 100644 --- a/main.c +++ b/main.c @@ -25,7 +25,7 @@ extern ToxWindow new_prompt(); extern ToxWindow new_friendlist(); -extern int friendlist_onFriendAdded(int num); +extern int friendlist_onFriendAdded(Messenger *m, int num); extern void disable_chatwin(int f_num); extern int add_req(uint8_t *public_key); // XXX extern unsigned char *hex_string_to_bin(char hex_string[]); @@ -40,6 +40,8 @@ char WINDOW_STATUS[MAX_WINDOW_SLOTS]; static ToxWindow windows[MAX_WINDOW_SLOTS]; static ToxWindow* prompt; +static Messenger *m; + int w_num; int active_window; @@ -63,25 +65,25 @@ void on_request(uint8_t *public_key, uint8_t *data, uint16_t length) } } -void on_message(int friendnumber, uint8_t *string, uint16_t length) +void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length) { int i; for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { if (windows[i].onMessage != NULL) - windows[i].onMessage(&windows[i], friendnumber, string, length); + windows[i].onMessage(&windows[i], m, friendnumber, string, length); } } -void on_action(int friendnumber, uint8_t *string, uint16_t length) +void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length) { int i; for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { if (windows[i].onAction != NULL) - windows[i].onAction(&windows[i], friendnumber, string, length); + windows[i].onAction(&windows[i], m, friendnumber, string, length); } } -void on_nickchange(int friendnumber, uint8_t *string, uint16_t length) +void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length) { wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string); int i; @@ -91,7 +93,7 @@ void on_nickchange(int friendnumber, uint8_t *string, uint16_t length) } } -void on_statuschange(int friendnumber, uint8_t *string, uint16_t length) +void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length) { wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); int i; @@ -103,7 +105,7 @@ void on_statuschange(int friendnumber, uint8_t *string, uint16_t length) void on_friendadded(int friendnumber) { - friendlist_onFriendAdded(friendnumber); + friendlist_onFriendAdded(m, friendnumber); } /* CALLBACKS END */ @@ -129,14 +131,14 @@ static void init_term() static void init_tox() { /* Init core */ - initMessenger(); + m = initMessenger(); /* Callbacks */ - m_callback_friendrequest(on_request); - m_callback_friendmessage(on_message); - m_callback_namechange(on_nickchange); - m_callback_statusmessage(on_statuschange); - m_callback_action(on_action); + m_callback_friendrequest(m, on_request); + m_callback_friendmessage(m, on_message); + m_callback_namechange(m, on_nickchange); + m_callback_statusmessage(m, on_statuschange); + m_callback_action(m, on_action); } #define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */ @@ -211,7 +213,7 @@ int add_window(ToxWindow w, int n) return -1; windows[n] = w; - w.onInit(&w); + w.onInit(&w, m); w_num++; return n; } @@ -237,7 +239,7 @@ static void init_windows() w_num = 0; int n_prompt = 0; int n_friendslist = 1; - if (add_window(new_prompt(), n_prompt) == -1 + if (add_window(new_prompt(), n_prompt) == -1 || add_window(new_friendlist(), n_friendslist) == -1) { fprintf(stderr, "add_window() failed.\n"); endwin(); @@ -257,7 +259,7 @@ static void do_tox() dht_on = false; wprintw(prompt->window, "\nDHT disconnected.\n"); } - doMessenger(); + doMessenger(m); } static void load_data(char *path) @@ -285,17 +287,17 @@ static void load_data(char *path) endwin(); exit(1); } - Messenger_load(buf, len); + Messenger_load(m, buf, len); } else { - len = Messenger_size(); + len = Messenger_size(m); buf = malloc(len); if (buf == NULL) { fprintf(stderr, "malloc() failed.\n"); endwin(); exit(1); } - Messenger_save(buf); + Messenger_save(m, buf); fd = fopen(path, "w"); if (fd == NULL) { @@ -329,7 +331,7 @@ static void draw_bar() move(LINES - 1, 0); attron(COLOR_PAIR(4) | A_BOLD); - printw(" TOXIC " TOXICVER "|"); + printw(" TOXIC " TOXICVER "|"); attroff(COLOR_PAIR(4) | A_BOLD); int i; @@ -473,7 +475,8 @@ int main(int argc, char *argv[]) if (ch == '\t' || ch == KEY_BTAB) set_active_window(ch); else if (ch != ERR) - a->onKey(a, ch); + a->onKey(a, m, ch); } + cleanupMessenger(m); return 0; } diff --git a/prompt.c b/prompt.c index ab44e96..67f80fe 100644 --- a/prompt.c +++ b/prompt.c @@ -20,24 +20,24 @@ static char prompt_buf[MAX_STR_SIZE] = {0}; static int prompt_buf_pos = 0; /* commands */ -void cmd_accept(ToxWindow *, char **); -void cmd_add(ToxWindow *, char **); -void cmd_clear(ToxWindow *, char **); -void cmd_connect(ToxWindow *, char **); -void cmd_help(ToxWindow *, char **); -void cmd_msg(ToxWindow *, char **); -void cmd_myid(ToxWindow *, char **); -void cmd_nick(ToxWindow *, char **); -void cmd_quit(ToxWindow *, char **); -void cmd_status(ToxWindow *, char **); -void cmd_statusmsg(ToxWindow *, char **); +void cmd_accept(ToxWindow *, Messenger *m, char **); +void cmd_add(ToxWindow *, Messenger *m, char **); +void cmd_clear(ToxWindow *, Messenger *m, char **); +void cmd_connect(ToxWindow *, Messenger *m, char **); +void cmd_help(ToxWindow *, Messenger *m, char **); +void cmd_msg(ToxWindow *, Messenger *m, char **); +void cmd_myid(ToxWindow *, Messenger *m, char **); +void cmd_nick(ToxWindow *, Messenger *m, char **); +void cmd_quit(ToxWindow *, Messenger *m, char **); +void cmd_status(ToxWindow *, Messenger *m, char **); +void cmd_statusmsg(ToxWindow *, Messenger *m, char **); #define NUM_COMMANDS 13 static struct { char *name; int numargs; - void (*func)(ToxWindow *, char **); + void (*func)(ToxWindow *, Messenger *m, char **); } commands[] = { { "accept", 1, cmd_accept }, { "add", 1, cmd_add }, @@ -74,7 +74,7 @@ unsigned char *hex_string_to_bin(char hex_string[]) return val; } -void cmd_accept(ToxWindow *self, char **args) +void cmd_accept(ToxWindow *self, Messenger *m, char **args) { int num = atoi(args[1]); if (num >= num_requests) { @@ -82,7 +82,7 @@ void cmd_accept(ToxWindow *self, char **args) return; } - num = m_addfriend_norequest(pending_requests[num]); + num = m_addfriend_norequest(m, pending_requests[num]); if (num == -1) wprintw(self->window, "Failed to add friend.\n"); else { @@ -91,7 +91,7 @@ void cmd_accept(ToxWindow *self, char **args) } } -void cmd_add(ToxWindow *self, char **args) +void cmd_add(ToxWindow *self, Messenger *m, char **args) { uint8_t id_bin[KEY_SIZE_BYTES]; char xx[3]; @@ -121,7 +121,7 @@ void cmd_add(ToxWindow *self, char **args) } id_bin[i] = x; } - int num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); + int num = m_addfriend(m, id_bin, (uint8_t*) msg, strlen(msg)+1); switch (num) { case FAERR_TOOLONG: wprintw(self->window, "Message is too long.\n"); @@ -145,12 +145,12 @@ void cmd_add(ToxWindow *self, char **args) } } -void cmd_clear(ToxWindow *self, char **args) +void cmd_clear(ToxWindow *self, Messenger *m, char **args) { wclear(self->window); } -void cmd_connect(ToxWindow *self, char **args) +void cmd_connect(ToxWindow *self, Messenger *m, char **args) { IP_Port dht; char *ip = args[1]; @@ -174,13 +174,13 @@ void cmd_connect(ToxWindow *self, char **args) free(binary_string); } -void cmd_quit(ToxWindow *self, char **args) +void cmd_quit(ToxWindow *self, Messenger *m, char **args) { endwin(); exit(0); } -void cmd_help(ToxWindow *self, char **args) +void cmd_help(ToxWindow *self, Messenger *m, char **args) { wclear(self->window); wattron(self->window, COLOR_PAIR(2) | A_BOLD); @@ -197,7 +197,7 @@ void cmd_help(ToxWindow *self, char **args) wprintw(self->window, " quit/exit : Exit program\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, "TIP: Use the TAB key to navigate through the tabs.\n\n"); wattroff(self->window, A_BOLD); @@ -205,17 +205,17 @@ void cmd_help(ToxWindow *self, char **args) wattroff(self->window, COLOR_PAIR(2)); } -void cmd_msg(ToxWindow *self, char **args) +void cmd_msg(ToxWindow *self, Messenger *m, char **args) { char *id = args[1]; char *msg = args[2]; - if (m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) == 0) + if (m_sendmessage(m, atoi(id), (uint8_t*) msg, strlen(msg)+1) == 0) wprintw(self->window, "Error occurred while sending message.\n"); else wprintw(self->window, "Message successfully sent.\n"); } -void cmd_myid(ToxWindow *self, char **args) +void cmd_myid(ToxWindow *self, Messenger *m, char **args) { char id[KEY_SIZE_BYTES*2 + 1] = {0}; size_t i; @@ -227,14 +227,14 @@ void cmd_myid(ToxWindow *self, char **args) wprintw(self->window, "Your ID: %s\n", id); } -void cmd_nick(ToxWindow *self, char **args) +void cmd_nick(ToxWindow *self, Messenger *m, char **args) { char *nick = args[1]; - setname((uint8_t*) nick, strlen(nick)+1); + setname(m, (uint8_t*) nick, strlen(nick)+1); wprintw(self->window, "Nickname set to: %s\n", nick); } -void cmd_status(ToxWindow *self, char **args) +void cmd_status(ToxWindow *self, Messenger *m, char **args) { char *status = args[1]; char *status_text; @@ -260,24 +260,24 @@ void cmd_status(ToxWindow *self, char **args) char *msg = args[2]; if (msg == NULL) { - m_set_userstatus(status_kind); + m_set_userstatus(m, status_kind); wprintw(self->window, "Status set to: %s\n", status_text); } else { - m_set_userstatus(status_kind); - m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); + m_set_userstatus(m, status_kind); + m_set_statusmessage(m, (uint8_t*) msg, strlen(msg)+1); wprintw(self->window, "Status set to: %s, %s\n", status_text, msg); } } -void cmd_statusmsg(ToxWindow *self, char **args) +void cmd_statusmsg(ToxWindow *self, Messenger *m, char **args) { char *msg = args[1]; - m_set_statusmessage((uint8_t*) msg, strlen(msg)+1); + m_set_statusmessage(m, (uint8_t*) msg, strlen(msg)+1); wprintw(self->window, "Status set to: %s\n", msg); } -static void execute(ToxWindow *self, char *u_cmd) +static void execute(ToxWindow *self, Messenger *m, char *u_cmd) { int newlines = 0; char cmd[MAX_STR_SIZE] = {0}; @@ -341,13 +341,13 @@ static void execute(ToxWindow *self, char *u_cmd) return; } } - /* check for excess arguments */ + /* check for excess arguments */ if (strcmp(cmdargs[0], "add") && strlen(cmdargs[j]) != 0) { wprintw(self->window, "Invalid command: too many arguments to %s.\n", commands[i].name); return; } /* pass arguments to command function */ - (commands[i].func)(self, cmdargs); + (commands[i].func)(self, m, cmdargs); return; } } @@ -356,7 +356,7 @@ static void execute(ToxWindow *self, char *u_cmd) wprintw(self->window, "Invalid command.\n"); } -static void prompt_onKey(ToxWindow *self, int key) +static void prompt_onKey(ToxWindow *self, Messenger *m, int key) { /* Add printable characters to line */ if (isprint(key)) { @@ -380,7 +380,7 @@ static void prompt_onKey(ToxWindow *self, int key) /* RETURN key: execute command */ else if (key == '\n') { wprintw(self->window, "\n"); - execute(self, prompt_buf); + execute(self, m, prompt_buf); prompt_buf_pos = 0; prompt_buf[0] = 0; } @@ -413,10 +413,10 @@ static void prompt_onDraw(ToxWindow *self) wrefresh(self->window); } -static void prompt_onInit(ToxWindow *self) +static void prompt_onInit(ToxWindow *self, Messenger *m) { scrollok(self->window, 1); - cmd_help(self, NULL); + cmd_help(self, m, NULL); wclrtoeol(self->window); } diff --git a/windows.h b/windows.h index c6925ce..648243d 100644 --- a/windows.h +++ b/windows.h @@ -9,7 +9,7 @@ #define KEY_SIZE_BYTES 32 /* number of permanent default windows */ -#define N_DEFAULT_WINS 2 +#define N_DEFAULT_WINS 2 /* maximum window slots for WINDOW_STATUS array */ #define MAX_WINDOW_SLOTS N_DEFAULT_WINS+MAX_FRIENDS_NUM @@ -17,14 +17,14 @@ typedef struct ToxWindow_ ToxWindow; struct ToxWindow_ { - void(*onKey)(ToxWindow*, int); + void(*onKey)(ToxWindow*, Messenger*, int); void(*onDraw)(ToxWindow*); - void(*onInit)(ToxWindow*); + void(*onInit)(ToxWindow*, Messenger*); void(*onFriendRequest)(ToxWindow*, uint8_t*, uint8_t*, uint16_t); - void(*onMessage)(ToxWindow*, int, uint8_t*, uint16_t); + void(*onMessage)(ToxWindow*, Messenger*, int, uint8_t*, uint16_t); void(*onNickChange)(ToxWindow*, int, uint8_t*, uint16_t); void(*onStatusChange)(ToxWindow*, int, uint8_t*, uint16_t); - void(*onAction)(ToxWindow*, int, uint8_t*, uint16_t); + void(*onAction)(ToxWindow*, Messenger*, int, uint8_t*, uint16_t); char title[256]; void* x; From 8162cfde0d81f5f545b48e27a33f40639564c997 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 12 Aug 2013 05:59:08 -0400 Subject: [PATCH 108/172] a little overkill --- main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index 9bf0b9f..3550ac6 100644 --- a/main.c +++ b/main.c @@ -247,12 +247,11 @@ static void init_windows() static void do_tox() { - static int conn_try = 1; + static int conn_try = 0; static bool dht_on = false; - if (!dht_on && !DHT_isconnected()) { + if (!dht_on && !DHT_isconnected() && !(conn_try++ % 100)) { init_connection(); - if (!(conn_try++ % 100)) - wprintw(prompt->window, "\nAttempting to connect...\n"); + wprintw(prompt->window, "\nEstablishing connection...\n"); } else if (!dht_on && DHT_isconnected()) { dht_on = true; From 3946277a074e74a018af6e32a8571db6abb7d5bd Mon Sep 17 00:00:00 2001 From: alek900 Date: Mon, 12 Aug 2013 14:23:46 +0200 Subject: [PATCH 109/172] Added support for userdata in callbacks --- main.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/main.c b/main.c index c14dee1..ad89b23 100644 --- a/main.c +++ b/main.c @@ -46,7 +46,7 @@ int w_num; int active_window; /* CALLBACKS START */ -void on_request(uint8_t *public_key, uint8_t *data, uint16_t length) +void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void* userdata) { int n = add_req(public_key); wprintw(prompt->window, "\nFriend request from:\n"); @@ -65,7 +65,7 @@ void on_request(uint8_t *public_key, uint8_t *data, uint16_t length) } } -void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length) +void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) { int i; for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { @@ -74,7 +74,7 @@ void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length } } -void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length) +void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) { int i; for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { @@ -83,7 +83,7 @@ void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length) } } -void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length) +void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) { wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string); int i; @@ -93,7 +93,7 @@ void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t len } } -void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length) +void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) { wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); int i; @@ -134,11 +134,11 @@ static void init_tox() m = initMessenger(); /* Callbacks */ - m_callback_friendrequest(m, on_request); - m_callback_friendmessage(m, on_message); - m_callback_namechange(m, on_nickchange); - m_callback_statusmessage(m, on_statuschange); - m_callback_action(m, on_action); + m_callback_friendrequest(m, on_request, NULL); + m_callback_friendmessage(m, on_message, NULL); + m_callback_namechange(m, on_nickchange, NULL); + m_callback_statusmessage(m, on_statuschange, NULL); + m_callback_action(m, on_action, NULL); } #define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */ From 24083b30829333f7588ae4ce04f9d974f2229ebc Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 12 Aug 2013 19:50:50 -0400 Subject: [PATCH 110/172] minor improvements and bug fixes --- chat.c | 38 +++++++++++++++++++++++++++----------- main.c | 2 ++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/chat.c b/chat.c index 112b20b..da67567 100644 --- a/chat.c +++ b/chat.c @@ -79,9 +79,9 @@ static void chat_onAction(ToxWindow *self, Messenger *m, int num, uint8_t *actio wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattroff(ctx->history, COLOR_PAIR(2)); - wattron(ctx->history, COLOR_PAIR(4)); + wattron(ctx->history, COLOR_PAIR(5)); wprintw(ctx->history, "%s\n", action); - wattroff(ctx->history, COLOR_PAIR(4)); + wattroff(ctx->history, COLOR_PAIR(5)); self->blink = true; beep(); @@ -104,7 +104,18 @@ static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint16_t len) { + ChatContext *ctx = (ChatContext*) self->x; + if (ctx->friendnum != num) + return; + + status[len-1] = '\0'; + fix_name(status); + snprintf(self->title, sizeof(self->title), "[%s (%d)]", status, num); + wattron(ctx->history, COLOR_PAIR(3)); + wprintw(ctx->history, " * Your partner changed status to '%s'\n", status); + wattroff(ctx->history, COLOR_PAIR(3)); + } /* check that the string has one non-space character */ @@ -157,20 +168,24 @@ static void chat_onKey(ToxWindow *self, Messenger *m, int key) if (ctx->line[0] == '/') execute(self, ctx, m, ctx->line, timeinfo); else { + /* make sure the string has at least non-space character */ if (!string_is_empty(ctx->line)) { - /* make sure the string has at least non-space character */ + uint8_t selfname[MAX_NAME_LENGTH]; + getself_name(m, selfname); + fix_name(selfname); + wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattroff(ctx->history, COLOR_PAIR(2)); wattron(ctx->history, COLOR_PAIR(1)); - wprintw(ctx->history, "you: ", ctx->line); + wprintw(ctx->history, "%s: ", selfname); wattroff(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "%s\n", ctx->line); - } - if (m_sendmessage(m, ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) == 0) { - wattron(ctx->history, COLOR_PAIR(3)); - wprintw(ctx->history, " * Failed to send message.\n"); - wattroff(ctx->history, COLOR_PAIR(3)); + if (m_sendmessage(m, ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) == 0) { + wattron(ctx->history, COLOR_PAIR(3)); + wprintw(ctx->history, " * Failed to send message.\n"); + wattroff(ctx->history, COLOR_PAIR(3)); + } } } ctx->line[0] = '\0'; @@ -214,9 +229,9 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd, struct char msg[MAX_STR_SIZE-len-4]; snprintf(msg, sizeof(msg), "* %s %s\n", (uint8_t*) selfname, action); - wattron(ctx->history, COLOR_PAIR(1)); + wattron(ctx->history, COLOR_PAIR(5)); wprintw(ctx->history, msg); - wattroff(ctx->history, COLOR_PAIR(1)); + wattroff(ctx->history, COLOR_PAIR(5)); if (m_sendaction(m, ctx->friendnum, (uint8_t*) msg, strlen(msg)+1) < 0) { wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Failed to send action\n"); @@ -274,6 +289,7 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd, struct wprintw(ctx->history, "Invalid syntax.\n"); return; } + nick++; setname(m, (uint8_t*) nick, strlen(nick)+1); wprintw(ctx->history, "Nickname set to: %s\n", nick); diff --git a/main.c b/main.c index 397f939..c5c881f 100644 --- a/main.c +++ b/main.c @@ -124,6 +124,7 @@ static void init_term() init_pair(2, COLOR_CYAN, COLOR_BLACK); init_pair(3, COLOR_RED, COLOR_BLACK); init_pair(4, COLOR_BLUE, COLOR_BLACK); + init_pair(5, COLOR_YELLOW, COLOR_BLACK); } refresh(); } @@ -139,6 +140,7 @@ static void init_tox() m_callback_namechange(m, on_nickchange, NULL); m_callback_statusmessage(m, on_statuschange, NULL); m_callback_action(m, on_action, NULL); + setname(m, (uint8_t*) "n00b", strlen("n00b")+1); } #define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */ From ab11469d37bb3a29e63a11ac293b97c57fdec3cc Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 12 Aug 2013 20:28:43 -0400 Subject: [PATCH 111/172] put a bunch of repeated code into a function and added timestamps to status/nick changes --- chat.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/chat.c b/chat.c index da67567..a312d21 100644 --- a/chat.c +++ b/chat.c @@ -29,16 +29,21 @@ extern int active_window; extern void del_window(ToxWindow *w, int f_num); extern void fix_name(uint8_t *name); void print_help(ChatContext *self); -void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd, struct tm *timeinfo); +void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd); + +struct tm *get_time(void) { + struct tm *timeinfo; + time_t now; + time(&now); + timeinfo = localtime(&now); + return timeinfo; +} static void chat_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *msg, uint16_t len) { ChatContext *ctx = (ChatContext*) self->x; uint8_t nick[MAX_NAME_LENGTH] = {0}; - time_t now; - time(&now); - struct tm *timeinfo; - timeinfo = localtime(&now); + struct tm *timeinfo = get_time(); if (ctx->friendnum != num) return; @@ -64,10 +69,7 @@ static void chat_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *msg, static void chat_onAction(ToxWindow *self, Messenger *m, int num, uint8_t *action, uint16_t len) { ChatContext *ctx = (ChatContext*) self->x; - time_t now; - time(&now); - struct tm *timeinfo; - timeinfo = localtime(&now); + struct tm *timeinfo = get_time(); if (ctx->friendnum != num) return; @@ -90,30 +92,40 @@ static void chat_onAction(ToxWindow *self, Messenger *m, int num, uint8_t *actio static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len) { ChatContext *ctx = (ChatContext*) self->x; + struct tm *timeinfo = get_time(); if (ctx->friendnum != num) return; + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); + nick[len-1] = '\0'; fix_name(nick); snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num); wattron(ctx->history, COLOR_PAIR(3)); - wprintw(ctx->history, " * Your partner changed nick to '%s'\n", nick); + wprintw(ctx->history, "* Your partner changed nick to '%s'\n", nick); wattroff(ctx->history, COLOR_PAIR(3)); } static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint16_t len) { ChatContext *ctx = (ChatContext*) self->x; + struct tm *timeinfo = get_time(); if (ctx->friendnum != num) return; - + + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); + status[len-1] = '\0'; fix_name(status); snprintf(self->title, sizeof(self->title), "[%s (%d)]", status, num); wattron(ctx->history, COLOR_PAIR(3)); - wprintw(ctx->history, " * Your partner changed status to '%s'\n", status); + wprintw(ctx->history, "* Your partner changed status to '%s'\n", status); wattroff(ctx->history, COLOR_PAIR(3)); } @@ -131,10 +143,7 @@ int string_is_empty(char *string) static void chat_onKey(ToxWindow *self, Messenger *m, int key) { ChatContext *ctx = (ChatContext*) self->x; - time_t now; - time(&now); - struct tm * timeinfo; - timeinfo = localtime(&now); + struct tm *timeinfo = get_time(); int x, y, y2, x2; getyx(self->window, y, x); @@ -166,7 +175,7 @@ static void chat_onKey(ToxWindow *self, Messenger *m, int key) wmove(self->window, y2-CURS_Y_OFFSET, 0); wclrtobot(self->window); if (ctx->line[0] == '/') - execute(self, ctx, m, ctx->line, timeinfo); + execute(self, ctx, m, ctx->line); else { /* make sure the string has at least non-space character */ if (!string_is_empty(ctx->line)) { @@ -193,7 +202,7 @@ static void chat_onKey(ToxWindow *self, Messenger *m, int key) } } -void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd, struct tm *timeinfo) +void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) { if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { wclear(self->window); @@ -213,6 +222,7 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd, struct } else if (!strncmp(cmd, "/me ", strlen("/me "))) { + struct tm *timeinfo = get_time(); char *action = strchr(cmd, ' '); if (action == NULL) { wprintw(self->window, "Invalid syntax.\n"); From 0c6204ce827fcc75ad8f14cb200e3e3122b5a725 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 12 Aug 2013 22:04:07 -0400 Subject: [PATCH 112/172] auto-connect errors verbose --- main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index c5c881f..63c4db2 100644 --- a/main.c +++ b/main.c @@ -252,10 +252,15 @@ static void init_windows() static void do_tox() { static int conn_try = 0; + static int conn_err = 0; static bool dht_on = false; if (!dht_on && !DHT_isconnected() && !(conn_try++ % 100)) { - init_connection(); - wprintw(prompt->window, "\nEstablishing connection...\n"); + if (!conn_err) { + conn_err = init_connection(); + wprintw(prompt->window, "\nEstablishing connection...\n"); + if (conn_err) + wprintw(prompt->window, "\nAuto-connect failed with error code %d\n", conn_err); + } } else if (!dht_on && DHT_isconnected()) { dht_on = true; @@ -264,7 +269,6 @@ static void do_tox() else if (dht_on && !DHT_isconnected()) { dht_on = false; wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n"); - init_connection(); } doMessenger(m); } From 095b1b5db2e2c55c4985e5d9793ffa04cd699f38 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 12 Aug 2013 22:34:08 -0400 Subject: [PATCH 113/172] unresolved addresses fail silently --- chat.c | 3 ++- main.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/chat.c b/chat.c index a312d21..a0a4b57 100644 --- a/chat.c +++ b/chat.c @@ -31,7 +31,8 @@ extern void fix_name(uint8_t *name); void print_help(ChatContext *self); void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd); -struct tm *get_time(void) { +struct tm *get_time(void) +{ struct tm *timeinfo; time_t now; time(&now); diff --git a/main.c b/main.c index 63c4db2..8ef4401 100644 --- a/main.c +++ b/main.c @@ -181,7 +181,7 @@ int init_connection(void) dht.port = htons(atoi(port)); uint32_t resolved_address = resolve_addr(ip); if (resolved_address == 0) - return 4; + return 0; dht.ip.i = resolved_address; unsigned char *binary_string = hex_string_to_bin(key); DHT_bootstrap(dht, binary_string); From b5a4cac6e184976bf404e5897882e779150b745b Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Sun, 11 Aug 2013 12:52:56 +0200 Subject: [PATCH 114/172] toxic: Fix get_user_config_dir(). --- configdir.c | 114 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 48 deletions(-) diff --git a/configdir.c b/configdir.c index 6cbb06b..18e211c 100644 --- a/configdir.c +++ b/configdir.c @@ -28,65 +28,83 @@ #ifdef WIN32 #include #include -#endif - -#ifdef __APPLE__ +#else /* WIN32 */ #include #include -#endif +#endif /* WIN32 */ #include "configdir.h" -/* - * Retrieves a correct configuration directory, depending on the OS used, with a trailing slash +/** + * @brief Get the users config directory. + * + * This is without a trailing slash. + * + * @return The users config dir or NULL on error. */ char *get_user_config_dir(void) { - char *user_config_dir; + char *user_config_dir; +#ifdef WIN32 + char appdata[MAX_PATH]; + BOOL ok; - #ifdef WIN32 - - char appdata[MAX_PATH]; - HRESULT result = SHGetFolderPath( - NULL, - CSIDL_APPDATA, - NULL, - SHGFP_TYPE_CURRENT, - appdata - ) - if (!result) return NULL; - - user_config_dir = strdup(appdata); - - return user_config_dir; - - #elif defined __APPLE__ - - struct passwd *pass = getpwuid(getuid()); - if (!pass) return NULL; - char *home = pass->pw_dir; - user_config_dir = malloc(strlen(home) + strlen("/Library/Application Support") + 1); - - if(user_config_dir) { - strcpy(user_config_dir, home); - strcat(user_config_dir, "/Library/Application Support"); - } - return user_config_dir; - - #else - - if (getenv("XDG_CONFIG_HOME")) { - user_config_dir = strdup(getenv("XDG_CONFIG_HOME")); - } else { - user_config_dir = malloc(strlen(getenv("HOME")) + strlen("/.config") + 1); - if (user_config_dir) { - strcpy(user_config_dir, getenv("HOME")); - strcat(user_config_dir, "/.config"); + ok = SHGetSpecialFolderPathA(NULL, appdata, CSIDL_PROFILE, TRUE); + if (!ok) { + return NULL; } - } - return user_config_dir; - #endif + user_config_dir = strdup(appdata); + + return user_config_dir; + +#else /* WIN32 */ + +#ifndef NSS_BUFLEN_PASSWD +#define NSS_BUFLEN_PASSWD 4096 +#endif /* NSS_BUFLEN_PASSWD */ + + struct passwd pwd; + struct passwd *pwdbuf; + const char *home; + char buf[NSS_BUFLEN_PASSWD]; + size_t len; + int rc; + + rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf); + if (rc == 0) { + home = pwd.pw_dir; + } else { + home = getenv("HOME"); + if (home == NULL) { + return NULL; + } + /* env variables can be tainted */ + snprintf(buf, sizeof(buf), "%s", home); + home = buf; + } + +# if defined(__APPLE__) + len = strlen(home) + strlen("/Library/Application Support") + 1; + user_config_dir = malloc(len); + if (user_config_dir == NULL) { + return NULL; + } + + snprintf(user_config_dir, len, "%s/Library/Application Support", home); +# else /* __APPLE__ */ + len = strlen(home) + strlen("/.config") + 1; + user_config_dir = malloc(len); + if (user_config_dir == NULL) { + return NULL; + } + + snprintf(user_config_dir, len, "%s/.config", home); +# endif /* __APPLE__ */ + + return user_config_dir; +#undef NSS_BUFLEN_PASSWD +#endif /* WIN32 */ } /* From 98ecf06b4cce0bb7fc3664ee8de3c01859c52f7a Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Sun, 11 Aug 2013 15:24:47 +0200 Subject: [PATCH 115/172] core: Fix a possible buffer overflow using getself_name(). If the passed buffer is smaller than MAX_NAME_LENGTH then, you will probably overflow it. --- chat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chat.c b/chat.c index 112b20b..59b1349 100644 --- a/chat.c +++ b/chat.c @@ -210,7 +210,7 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd, struct wattroff(ctx->history, COLOR_PAIR(2)); uint8_t selfname[MAX_NAME_LENGTH]; - int len = getself_name(m, selfname); + int len = getself_name(m, selfname, sizeof(selfname)); char msg[MAX_STR_SIZE-len-4]; snprintf(msg, sizeof(msg), "* %s %s\n", (uint8_t*) selfname, action); From fcf556cd1b37fe0c9ce3778529cf96bfc6755fe8 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 13 Aug 2013 07:39:04 -0400 Subject: [PATCH 116/172] Fixed merge problem and set better default names. --- chat.c | 2 +- main.c | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/chat.c b/chat.c index 32c05de..35be3bd 100644 --- a/chat.c +++ b/chat.c @@ -181,7 +181,7 @@ static void chat_onKey(ToxWindow *self, Messenger *m, int key) /* make sure the string has at least non-space character */ if (!string_is_empty(ctx->line)) { uint8_t selfname[MAX_NAME_LENGTH]; - getself_name(m, selfname); + getself_name(m, selfname, sizeof(selfname)); fix_name(selfname); wattron(ctx->history, COLOR_PAIR(2)); diff --git a/main.c b/main.c index 8ef4401..40ff5d0 100644 --- a/main.c +++ b/main.c @@ -140,7 +140,13 @@ static void init_tox() m_callback_namechange(m, on_nickchange, NULL); m_callback_statusmessage(m, on_statuschange, NULL); m_callback_action(m, on_action, NULL); - setname(m, (uint8_t*) "n00b", strlen("n00b")+1); +#ifdef __linux__ + setname(m, (uint8_t*) "Cool guy", sizeof("Cool guy")); +#elif WIN32 + setname(m, (uint8_t*) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); +#else + setname(m, (uint8_t*) "Hipster", sizeof("Hipster")); +#endif } #define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */ From 2857e6af8f8d5af82eb1b8cb3ae9142a34f58aae Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 13 Aug 2013 09:32:31 -0400 Subject: [PATCH 117/172] Fixed spam problem. (I broke the API so this will not build) The friend address is what the byte string that you give away for people to add you will be called. 1. Every friend address now contains a number set by the friend. This is to prevent someone from randomly spamming people in the DHT with friend requests and makes it so you need the person to actually give you the address in some way to send the friend request. This number is expected to be encrypted with the friend request. All requests that do not contain this number will be rejected. This means the spammer can no longer use the DHT to collect lists of valid addresses to spam. It also enables users to quickly change the number in case a spammer gets hold of the address and starts spamming it. 2. A 2 byte checksum will be added (not implemented yet) to prevent people from accidentally adding random strings as friends. (NOTE that this has nothing to do with the spam problem I just decided to add a placeholder for it now.) --- chat.c | 8 +++++--- prompt.c | 14 ++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/chat.c b/chat.c index 35be3bd..1b5e743 100644 --- a/chat.c +++ b/chat.c @@ -307,11 +307,13 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) } else if (!strcmp(cmd, "/myid")) { - char id[KEY_SIZE_BYTES*2+1] = {0}; + char id[FRIEND_ADDRESS_SIZE*2+1] = {0}; int i; - for (i = 0; i < KEY_SIZE_BYTES; i++) { + uint8_t address[FRIEND_ADDRESS_SIZE]; + getaddress(m, address); + for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) { char xx[3]; - snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); + snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); strcat(id, xx); } wprintw(ctx->history, "Your ID: %s\n", id); diff --git a/prompt.c b/prompt.c index 67f80fe..e1a7d75 100644 --- a/prompt.c +++ b/prompt.c @@ -93,7 +93,7 @@ void cmd_accept(ToxWindow *self, Messenger *m, char **args) void cmd_add(ToxWindow *self, Messenger *m, char **args) { - uint8_t id_bin[KEY_SIZE_BYTES]; + uint8_t id_bin[FRIEND_ADDRESS_SIZE]; char xx[3]; uint32_t x; char *id = args[1]; @@ -106,12 +106,12 @@ void cmd_add(ToxWindow *self, Messenger *m, char **args) if (!msg) msg = ""; - if (strlen(id) != 2*KEY_SIZE_BYTES) { + if (strlen(id) != 2*FRIEND_ADDRESS_SIZE) { wprintw(self->window, "Invalid ID length.\n"); return; } int i; - for (i = 0; i < KEY_SIZE_BYTES; ++i) { + for (i = 0; i < FRIEND_ADDRESS_SIZE; ++i) { xx[0] = id[2*i]; xx[1] = id[2*i+1]; xx[2] = '\0'; @@ -217,11 +217,13 @@ void cmd_msg(ToxWindow *self, Messenger *m, char **args) void cmd_myid(ToxWindow *self, Messenger *m, char **args) { - char id[KEY_SIZE_BYTES*2 + 1] = {0}; + char id[FRIEND_ADDRESS_SIZE*2 + 1] = {0}; size_t i; - for (i = 0; i < KEY_SIZE_BYTES; ++i) { + uint8_t address[FRIEND_ADDRESS_SIZE]; + getaddress(m, address); + for (i = 0; i < FRIEND_ADDRESS_SIZE; ++i) { char xx[3]; - snprintf(xx, sizeof(xx), "%02x", self_public_key[i] & 0xff); + snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); strcat(id, xx); } wprintw(self->window, "Your ID: %s\n", id); From 115893064168ff5d12bad12b4aaa3a4f82f2a9a8 Mon Sep 17 00:00:00 2001 From: Michael Rose Date: Tue, 13 Aug 2013 22:07:46 +0200 Subject: [PATCH 118/172] store messenger when friends are added --- main.c | 113 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 45 deletions(-) diff --git a/main.c b/main.c index 40ff5d0..27a34e0 100644 --- a/main.c +++ b/main.c @@ -30,6 +30,8 @@ extern void disable_chatwin(int f_num); extern int add_req(uint8_t *public_key); // XXX extern unsigned char *hex_string_to_bin(char hex_string[]); +static int store_data(char*); + /* Holds status of chat windows */ char WINDOW_STATUS[MAX_WINDOW_SLOTS]; @@ -41,6 +43,7 @@ static ToxWindow windows[MAX_WINDOW_SLOTS]; static ToxWindow* prompt; static Messenger *m; +static char *DATA_FILE; int w_num; int active_window; @@ -105,7 +108,11 @@ void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t l void on_friendadded(int friendnumber) { - friendlist_onFriendAdded(m, friendnumber); + friendlist_onFriendAdded(m, friendnumber); + int st; + if ((st = store_data(DATA_FILE)) != 0) { + wprintw(prompt->window, "\nCould not store messenger, error code: %d\n", st); + } } /* CALLBACKS END */ @@ -279,61 +286,76 @@ static void do_tox() doMessenger(m); } -static void load_data(char *path) +/* + * Store Messenger data to path + * Return 0 Messenger stored successfully + * Return 1 malloc failed + * Return 2 fopen failed + * Return 3 fwrite failed + */ +static int store_data(char *path) { - FILE *fd; - size_t len; - uint8_t *buf; + FILE *fd; + size_t len; + uint8_t *buf; - if ((fd = fopen(path, "r")) != NULL) { - fseek(fd, 0, SEEK_END); - len = ftell(fd); - fseek(fd, 0, SEEK_SET); - - buf = malloc(len); - if (buf == NULL) { - fprintf(stderr, "malloc() failed.\n"); - fclose(fd); - endwin(); - exit(1); - } - if (fread(buf, len, 1, fd) != 1){ - fprintf(stderr, "fread() failed.\n"); - free(buf); - fclose(fd); - endwin(); - exit(1); - } - Messenger_load(m, buf, len); - } - else { len = Messenger_size(m); buf = malloc(len); if (buf == NULL) { - fprintf(stderr, "malloc() failed.\n"); - endwin(); - exit(1); + return 1; } Messenger_save(m, buf); fd = fopen(path, "w"); if (fd == NULL) { - fprintf(stderr, "fopen() failed.\n"); - free(buf); - endwin(); - exit(1); + return 2; } - if (fwrite(buf, len, 1, fd) != 1){ - fprintf(stderr, "fwrite() failed.\n"); - free(buf); - fclose(fd); - endwin(); - exit(1); + if (fwrite(buf, len, 1, fd) != 1) { + return 3; + } + + free(buf); + fclose(fd); + + return 0; +} + +static void load_data(char *path) { + FILE *fd; + size_t len; + uint8_t *buf; + + if ((fd = fopen(path, "r")) != NULL) { + fseek(fd, 0, SEEK_END); + len = ftell(fd); + fseek(fd, 0, SEEK_SET); + + buf = malloc(len); + if (buf == NULL) { + fprintf(stderr, "malloc() failed.\n"); + fclose(fd); + endwin(); + exit(1); + } + if (fread(buf, len, 1, fd) != 1) { + fprintf(stderr, "fread() failed.\n"); + free(buf); + fclose(fd); + endwin(); + exit(1); + } + Messenger_load(m, buf, len); + free(buf); + fclose(fd); + } else { + int st; + if ((st = store_data(path)) != 0) { + fprintf(stderr, "storing messenger failed with error code: %d", st); + endwin(); + exit(1); + } } - } - free(buf); - fclose(fd); } static void draw_bar() @@ -419,7 +441,6 @@ int main(int argc, char *argv[]) int ch; ToxWindow* a; char *user_config_dir = get_user_config_dir(); - char *DATA_FILE; int config_err = create_user_config_dir(user_config_dir); if(config_err) { DATA_FILE = "data"; @@ -457,7 +478,6 @@ int main(int argc, char *argv[]) if(f_loadfromfile) load_data(DATA_FILE); - free(DATA_FILE); if (f_flag == -1) { attron(COLOR_PAIR(3) | A_BOLD); @@ -490,6 +510,9 @@ int main(int argc, char *argv[]) else if (ch != ERR) a->onKey(a, m, ch); } + cleanupMessenger(m); + free(DATA_FILE); + return 0; } From 076ea43c0776eb572b7b803c749b9262186c7529 Mon Sep 17 00:00:00 2001 From: Michael Rose Date: Wed, 14 Aug 2013 09:31:19 +0200 Subject: [PATCH 119/172] fix memory leak --- main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main.c b/main.c index 27a34e0..fd3c732 100644 --- a/main.c +++ b/main.c @@ -308,10 +308,13 @@ static int store_data(char *path) fd = fopen(path, "w"); if (fd == NULL) { + free(buf); return 2; } if (fwrite(buf, len, 1, fd) != 1) { + free(buf); + fclose(fd); return 3; } From ce9d0660548fb33328b5e460a9c3a68a6e2f5a6a Mon Sep 17 00:00:00 2001 From: Aaron Lipinski Date: Wed, 14 Aug 2013 21:16:02 +1200 Subject: [PATCH 120/172] Have toxic handle new no-spam values from friend request --- prompt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/prompt.c b/prompt.c index e1a7d75..b1d6693 100644 --- a/prompt.c +++ b/prompt.c @@ -138,6 +138,12 @@ void cmd_add(ToxWindow *self, Messenger *m, char **args) case FAERR_UNKNOWN: wprintw(self->window, "Undefined error when adding friend.\n"); break; + case FAERR_BADCHECKSUM: + wprintw(self->window, "Bad checksum in address.\n"); + break; + case FAERR_SETNEWNOSPAM: + wprintw(self->window, "Nospam was different.\n"); + break; default: wprintw(self->window, "Friend added as %d.\n", num); on_friendadded(num); From 6df39d572b6ea941bb1873f0f9108a419aab795e Mon Sep 17 00:00:00 2001 From: Michael Rose Date: Wed, 14 Aug 2013 11:37:58 +0200 Subject: [PATCH 121/172] populate friends in toxic on startup --- main.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index fd3c732..40b70ba 100644 --- a/main.c +++ b/main.c @@ -286,6 +286,15 @@ static void do_tox() doMessenger(m); } +static void populate_friends() +{ + wprintw(prompt->window, "Populating friends...\n"); + for (int i = 0; i < m->numfriends; i++) { + wprintw(prompt->window, "Added friend %d\n", i); + friendlist_onFriendAdded(m, i); + } +} + /* * Store Messenger data to path * Return 0 Messenger stored successfully @@ -321,6 +330,8 @@ static int store_data(char *path) free(buf); fclose(fd); + wprintw(prompt->window, "Messenger stored\n"); + return 0; } @@ -348,7 +359,9 @@ static void load_data(char *path) { endwin(); exit(1); } - Messenger_load(m, buf, len); + if (Messenger_load(m, buf, len) != 0) { + fprintf(stderr, "Problem while loading messenger"); + } free(buf); fclose(fd); } else { @@ -479,8 +492,10 @@ int main(int argc, char *argv[]) init_windows(); init_window_status(); - if(f_loadfromfile) - load_data(DATA_FILE); + if(f_loadfromfile) { + load_data(DATA_FILE); + populate_friends(); + } if (f_flag == -1) { attron(COLOR_PAIR(3) | A_BOLD); From 5225b7d55ccd49ebe31278c210fd07296cbfd8dd Mon Sep 17 00:00:00 2001 From: Michael Rose Date: Wed, 14 Aug 2013 11:59:11 +0200 Subject: [PATCH 122/172] C99 fix --- main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 40b70ba..e9d285c 100644 --- a/main.c +++ b/main.c @@ -289,7 +289,8 @@ static void do_tox() static void populate_friends() { wprintw(prompt->window, "Populating friends...\n"); - for (int i = 0; i < m->numfriends; i++) { + uint32_t i; + for (i = 0; i < m->numfriends; i++) { wprintw(prompt->window, "Added friend %d\n", i); friendlist_onFriendAdded(m, i); } From 4a6edcbf1e44804819883377e744f8e93dc8ac17 Mon Sep 17 00:00:00 2001 From: Astonex Date: Wed, 14 Aug 2013 11:23:38 +0100 Subject: [PATCH 123/172] Update prompt.c Make id uppercase. --- prompt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/prompt.c b/prompt.c index e1a7d75..c0169c6 100644 --- a/prompt.c +++ b/prompt.c @@ -121,6 +121,11 @@ void cmd_add(ToxWindow *self, Messenger *m, char **args) } id_bin[i] = x; } + + for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) { + id[i] = toupper(id[i]); + } + int num = m_addfriend(m, id_bin, (uint8_t*) msg, strlen(msg)+1); switch (num) { case FAERR_TOOLONG: From 5d07842d96c384685b34d8abf31e2e4c8193fce6 Mon Sep 17 00:00:00 2001 From: Aaron Lipinski Date: Tue, 13 Aug 2013 09:34:46 +1200 Subject: [PATCH 124/172] prefer param over static Conflicts: testing/toxic/main.c --- friendlist.c | 6 +++--- main.c | 29 ++++++++++++++--------------- prompt.c | 6 +++--- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/friendlist.c b/friendlist.c index 56061cf..1a77440 100644 --- a/friendlist.c +++ b/friendlist.c @@ -13,7 +13,7 @@ #include "windows.h" extern char WINDOW_STATUS[TOXWINDOWS_MAX_NUM]; -extern int add_window(ToxWindow w, int n); +extern int add_window(Messenger *m, ToxWindow w, int n); extern ToxWindow new_chat(Messenger *m, int friendnum); extern int active_window; @@ -54,7 +54,7 @@ void friendlist_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *str, for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { if (WINDOW_STATUS[i] == -1) { WINDOW_STATUS[i] = num; - add_window(new_chat(m, num), i); + add_window(m, new_chat(m, num), i); active_window = i; break; } @@ -121,7 +121,7 @@ static void friendlist_onKey(ToxWindow *self, Messenger *m, int key) if (WINDOW_STATUS[i] == -1) { WINDOW_STATUS[i] = num_selected; friends[num_selected].chatwin = num_selected; - add_window(new_chat(m, num_selected), i); + add_window(m, new_chat(m, num_selected), i); active_window = i; break; } diff --git a/main.c b/main.c index 40ff5d0..8ab2d39 100644 --- a/main.c +++ b/main.c @@ -40,8 +40,6 @@ char WINDOW_STATUS[MAX_WINDOW_SLOTS]; static ToxWindow windows[MAX_WINDOW_SLOTS]; static ToxWindow* prompt; -static Messenger *m; - int w_num; int active_window; @@ -103,7 +101,7 @@ void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t l } } -void on_friendadded(int friendnumber) +void on_friendadded(Messenger *m, int friendnumber) { friendlist_onFriendAdded(m, friendnumber); } @@ -129,10 +127,10 @@ static void init_term() refresh(); } -static void init_tox() +static Messenger * init_tox() { /* Init core */ - m = initMessenger(); + Messenger *m = initMessenger(); /* Callbacks */ m_callback_friendrequest(m, on_request, NULL); @@ -147,6 +145,7 @@ static void init_tox() #else setname(m, (uint8_t*) "Hipster", sizeof("Hipster")); #endif + return m; } #define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */ @@ -207,7 +206,7 @@ void init_window_status() WINDOW_STATUS[j] = -1; } -int add_window(ToxWindow w, int n) +int add_window(Messenger *m, ToxWindow w, int n) { if (w_num >= TOXWINDOWS_MAX_NUM) return -1; @@ -241,13 +240,13 @@ void del_window(ToxWindow *w, int f_num) refresh(); } -static void init_windows() +static void init_windows(Messenger *m) { w_num = 0; int n_prompt = 0; int n_friendslist = 1; - if (add_window(new_prompt(), n_prompt) == -1 - || add_window(new_friendlist(), n_friendslist) == -1) { + if (add_window(m, new_prompt(), n_prompt) == -1 + || add_window(m, new_friendlist(), n_friendslist) == -1) { fprintf(stderr, "add_window() failed.\n"); endwin(); exit(1); @@ -255,7 +254,7 @@ static void init_windows() prompt = &windows[n_prompt]; } -static void do_tox() +static void do_tox(Messenger *m) { static int conn_try = 0; static int conn_err = 0; @@ -279,7 +278,7 @@ static void do_tox() doMessenger(m); } -static void load_data(char *path) +static void load_data(Messenger *m, char *path) { FILE *fd; size_t len; @@ -451,12 +450,12 @@ int main(int argc, char *argv[]) } init_term(); - init_tox(); - init_windows(); + Messenger *m = init_tox(); + init_windows(m); init_window_status(); if(f_loadfromfile) - load_data(DATA_FILE); + load_data(m, DATA_FILE); free(DATA_FILE); if (f_flag == -1) { @@ -474,7 +473,7 @@ int main(int argc, char *argv[]) } while(true) { /* Update tox */ - do_tox(); + do_tox(m); /* Draw */ a = &windows[active_window]; diff --git a/prompt.c b/prompt.c index b1d6693..c01ed71 100644 --- a/prompt.c +++ b/prompt.c @@ -15,7 +15,7 @@ uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX uint8_t num_requests=0; // XXX -extern void on_friendadded(int friendnumber); +extern void on_friendadded(Messenger *m, int friendnumber); static char prompt_buf[MAX_STR_SIZE] = {0}; static int prompt_buf_pos = 0; @@ -87,7 +87,7 @@ void cmd_accept(ToxWindow *self, Messenger *m, char **args) wprintw(self->window, "Failed to add friend.\n"); else { wprintw(self->window, "Friend accepted as: %d.\n", num); - on_friendadded(num); + on_friendadded(m, num); } } @@ -146,7 +146,7 @@ void cmd_add(ToxWindow *self, Messenger *m, char **args) break; default: wprintw(self->window, "Friend added as %d.\n", num); - on_friendadded(num); + on_friendadded(m, num); break; } } From 063523a042f7c67d5ee8a2345dc0ab1cd2115b21 Mon Sep 17 00:00:00 2001 From: Aaron Lipinski Date: Sun, 11 Aug 2013 12:58:15 +1200 Subject: [PATCH 125/172] add header guard and includes to windows.h --- windows.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/windows.h b/windows.h index 648243d..4eb55a9 100644 --- a/windows.h +++ b/windows.h @@ -1,8 +1,13 @@ /* * Toxic -- Tox Curses Client */ +#ifndef _windows_h +#define _windows_h +#include +#include #include +#include "../../core/Messenger.h" #define TOXWINDOWS_MAX_NUM 32 #define MAX_FRIENDS_NUM 100 #define MAX_STR_SIZE 256 @@ -32,3 +37,6 @@ struct ToxWindow_ { WINDOW* window; }; + +#endif + From 2c81fd5e4b91b0db42f7a21784a06f572a12aa27 Mon Sep 17 00:00:00 2001 From: Aaron Lipinski Date: Tue, 13 Aug 2013 10:50:43 +1200 Subject: [PATCH 126/172] remove externs in favor of includes --- chat.c | 10 +++---- chat.h | 7 +++++ friendlist.c | 25 ++++++++-------- friendlist.h | 14 +++++++++ main.c | 84 +++++++++++++++++++++++++--------------------------- prompt.c | 6 ++-- prompt.h | 14 +++++++++ 7 files changed, 98 insertions(+), 62 deletions(-) create mode 100644 chat.h create mode 100644 friendlist.h create mode 100644 prompt.h diff --git a/chat.c b/chat.c index 1b5e743..6811569 100644 --- a/chat.c +++ b/chat.c @@ -13,6 +13,8 @@ #include "../../core/network.h" #include "windows.h" +#include "friendlist.h" +#include "chat.h" #define CURS_Y_OFFSET 3 @@ -24,10 +26,8 @@ typedef struct { WINDOW* linewin; } ChatContext; -extern int active_window; +static delWindowFn *del_window; -extern void del_window(ToxWindow *w, int f_num); -extern void fix_name(uint8_t *name); void print_help(ChatContext *self); void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd); @@ -320,7 +320,6 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) } else if (strcmp(ctx->line, "/close") == 0) { - active_window = 0; // Go to prompt screen int f_num = ctx->friendnum; delwin(ctx->linewin); del_window(self, f_num); @@ -371,8 +370,9 @@ void print_help(ChatContext *self) wattroff(self->history, COLOR_PAIR(2)); } -ToxWindow new_chat(Messenger *m, int friendnum) +ToxWindow new_chat(Messenger *m, int friendnum, delWindowFn *f) { + del_window = f; ToxWindow ret; memset(&ret, 0, sizeof(ret)); diff --git a/chat.h b/chat.h new file mode 100644 index 0000000..dcd5b3b --- /dev/null +++ b/chat.h @@ -0,0 +1,7 @@ +#ifndef CHAT_H_6489PZ13 +#define CHAT_H_6489PZ13 + +typedef void (delWindowFn)(ToxWindow *w, int f_num); +ToxWindow new_chat(Messenger *m, int friendnum, delWindowFn f); + +#endif /* end of include guard: CHAT_H_6489PZ13 */ diff --git a/friendlist.c b/friendlist.c index 1a77440..5b79fde 100644 --- a/friendlist.c +++ b/friendlist.c @@ -10,13 +10,12 @@ #include "../../core/Messenger.h" #include "../../core/network.h" -#include "windows.h" +#include "friendlist.h" -extern char WINDOW_STATUS[TOXWINDOWS_MAX_NUM]; -extern int add_window(Messenger *m, ToxWindow w, int n); -extern ToxWindow new_chat(Messenger *m, int friendnum); - -extern int active_window; +static delWindowFn *del_window; +static setActiveWindowFn *set_active_window; +static addWindowFn *add_window; +static char * WINDOW_STATUS; typedef struct { uint8_t name[MAX_NAME_LENGTH]; @@ -54,8 +53,7 @@ void friendlist_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *str, for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { if (WINDOW_STATUS[i] == -1) { WINDOW_STATUS[i] = num; - add_window(m, new_chat(m, num), i); - active_window = i; + add_window(m, new_chat(m, num, del_window), i); break; } } @@ -111,7 +109,7 @@ static void friendlist_onKey(ToxWindow *self, Messenger *m, int key) int i; for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { if (WINDOW_STATUS[i] == num_selected) { - active_window = i; + set_active_window(i); break; } } @@ -121,8 +119,7 @@ static void friendlist_onKey(ToxWindow *self, Messenger *m, int key) if (WINDOW_STATUS[i] == -1) { WINDOW_STATUS[i] = num_selected; friends[num_selected].chatwin = num_selected; - add_window(m, new_chat(m, num_selected), i); - active_window = i; + add_window(m, new_chat(m, num_selected, del_window), i); break; } } @@ -169,7 +166,11 @@ static void friendlist_onInit(ToxWindow *self, Messenger *m) } -ToxWindow new_friendlist() { +ToxWindow new_friendlist(delWindowFn dw, setActiveWindowFn saw, addWindowFn aw, char * ws) { + del_window = dw; + set_active_window = saw; + add_window = aw; + WINDOW_STATUS = ws; ToxWindow ret; memset(&ret, 0, sizeof(ret)); diff --git a/friendlist.h b/friendlist.h new file mode 100644 index 0000000..e8b93ae --- /dev/null +++ b/friendlist.h @@ -0,0 +1,14 @@ +#ifndef FRIENDLIST_H_53I41IM +#define FRIENDLIST_H_53I41IM + + +#include "windows.h" +#include "chat.h" +typedef void (setActiveWindowFn)(int ch); +typedef int (addWindowFn)(Messenger *m, ToxWindow w, int n); +ToxWindow new_friendlist(delWindowFn dw, setActiveWindowFn saw, addWindowFn aw, char * ws); +int friendlist_onFriendAdded(Messenger *m, int num); +void disable_chatwin(int f_num); +void fix_name(uint8_t *name); + +#endif /* end of include guard: FRIENDLIST_H_53I41IM */ diff --git a/main.c b/main.c index 8ab2d39..a109311 100644 --- a/main.c +++ b/main.c @@ -21,14 +21,9 @@ #include "configdir.h" #include "windows.h" +#include "prompt.h" +#include "friendlist.h" -extern ToxWindow new_prompt(); -extern ToxWindow new_friendlist(); - -extern int friendlist_onFriendAdded(Messenger *m, int num); -extern void disable_chatwin(int f_num); -extern int add_req(uint8_t *public_key); // XXX -extern unsigned char *hex_string_to_bin(char hex_string[]); /* Holds status of chat windows */ char WINDOW_STATUS[MAX_WINDOW_SLOTS]; @@ -221,12 +216,14 @@ int add_window(Messenger *m, ToxWindow w, int n) windows[n] = w; w.onInit(&w, m); w_num++; + active_window = n; return n; } /* Deletes window w and cleans up */ void del_window(ToxWindow *w, int f_num) { + active_window = 0; // Go to prompt screen delwin(w->window); int i; for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { @@ -240,13 +237,48 @@ void del_window(ToxWindow *w, int f_num) refresh(); } +/* Shows next window when tab or back-tab is pressed */ +void set_active_window(int ch) +{ + int f_inf = 0; + int max = MAX_WINDOW_SLOTS-1; + if (ch == '\t') { + int i = (active_window + 1) % max; + while (true) { + if (WINDOW_STATUS[i] != -1) { + active_window = i; + return; + } + i = (i + 1) % max; + if (f_inf++ > max) { // infinite loop check + endwin(); + exit(2); + } + } + }else { + int i = active_window - 1; + if (i < 0) i = max; + while (true) { + if (WINDOW_STATUS[i] != -1) { + active_window = i; + return; + } + if (--i < 0) i = max; + if (f_inf++ > max) { + endwin(); + exit(2); + } + } + } +} + static void init_windows(Messenger *m) { w_num = 0; int n_prompt = 0; int n_friendslist = 1; - if (add_window(m, new_prompt(), n_prompt) == -1 - || add_window(m, new_friendlist(), n_friendslist) == -1) { + if (add_window(m, new_prompt(on_friendadded), n_prompt) == -1 + || add_window(m, new_friendlist(del_window, set_active_window, add_window, WINDOW_STATUS), n_friendslist) == -1) { fprintf(stderr, "add_window() failed.\n"); endwin(); exit(1); @@ -378,40 +410,6 @@ void prepare_window(WINDOW *w) wresize(w, LINES-2, COLS); } -/* Shows next window when tab or back-tab is pressed */ -void set_active_window(int ch) -{ - int f_inf = 0; - int max = MAX_WINDOW_SLOTS-1; - if (ch == '\t') { - int i = (active_window + 1) % max; - while (true) { - if (WINDOW_STATUS[i] != -1) { - active_window = i; - return; - } - i = (i + 1) % max; - if (f_inf++ > max) { // infinite loop check - endwin(); - exit(2); - } - } - }else { - int i = active_window - 1; - if (i < 0) i = max; - while (true) { - if (WINDOW_STATUS[i] != -1) { - active_window = i; - return; - } - if (--i < 0) i = max; - if (f_inf++ > max) { - endwin(); - exit(2); - } - } - } -} int main(int argc, char *argv[]) { diff --git a/prompt.c b/prompt.c index c01ed71..bc4b854 100644 --- a/prompt.c +++ b/prompt.c @@ -11,11 +11,12 @@ #include "../../core/network.h" #include "windows.h" +#include "prompt.h" uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX uint8_t num_requests=0; // XXX -extern void on_friendadded(Messenger *m, int friendnumber); +static friendAddedFn *on_friendadded; static char prompt_buf[MAX_STR_SIZE] = {0}; static int prompt_buf_pos = 0; @@ -428,8 +429,9 @@ static void prompt_onInit(ToxWindow *self, Messenger *m) wclrtoeol(self->window); } -ToxWindow new_prompt() +ToxWindow new_prompt(friendAddedFn *f) { + on_friendadded = f; ToxWindow ret; memset(&ret, 0, sizeof(ret)); ret.onKey = &prompt_onKey; diff --git a/prompt.h b/prompt.h new file mode 100644 index 0000000..6c5320a --- /dev/null +++ b/prompt.h @@ -0,0 +1,14 @@ +#ifndef PROMPT_H_UZYGWFFL +#define PROMPT_H_UZYGWFFL + +#include "windows.h" + +typedef void (friendAddedFn)(Messenger *m, int friendnumber); + +ToxWindow new_prompt(friendAddedFn *f); +int add_req(uint8_t *public_key); +unsigned char *hex_string_to_bin(char hex_string[]); + +#endif /* end of include guard: PROMPT_H_UZYGWFFL */ + + From 722d27212852a780a7e97462eb2a02d143998b8d Mon Sep 17 00:00:00 2001 From: Aaron Lipinski Date: Tue, 13 Aug 2013 12:21:03 +1200 Subject: [PATCH 127/172] move windows functions to its own file --- CMakeLists.txt | 1 + main.c | 236 +------------------------------------------------ windows.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++ windows.h | 8 ++ 4 files changed, 248 insertions(+), 232 deletions(-) create mode 100644 windows.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 13b8692..dd811b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ set(exe_name toxic) add_executable(${exe_name} main.c + windows.c prompt.c friendlist.c chat.c diff --git a/main.c b/main.c index a109311..d7b251d 100644 --- a/main.c +++ b/main.c @@ -24,84 +24,10 @@ #include "prompt.h" #include "friendlist.h" - -/* Holds status of chat windows */ -char WINDOW_STATUS[MAX_WINDOW_SLOTS]; - #ifndef TOXICVER #define TOXICVER "NOVER" //Use the -D flag to set this #endif -static ToxWindow windows[MAX_WINDOW_SLOTS]; -static ToxWindow* prompt; - -int w_num; -int active_window; - -/* CALLBACKS START */ -void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void* userdata) -{ - int n = add_req(public_key); - wprintw(prompt->window, "\nFriend request from:\n"); - - int i; - for (i = 0; i < KEY_SIZE_BYTES; ++i) { - wprintw(prompt->window, "%02x", public_key[i] & 0xff); - } - - wprintw(prompt->window, "\nWith the message: %s\n", data); - wprintw(prompt->window, "\nUse \"accept %d\" to accept it.\n", n); - - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { - if (windows[i].onFriendRequest != NULL) - windows[i].onFriendRequest(&windows[i], public_key, data, length); - } -} - -void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) -{ - int i; - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { - if (windows[i].onMessage != NULL) - windows[i].onMessage(&windows[i], m, friendnumber, string, length); - } -} - -void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) -{ - int i; - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { - if (windows[i].onAction != NULL) - windows[i].onAction(&windows[i], m, friendnumber, string, length); - } -} - -void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) -{ - wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string); - int i; - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { - if (windows[i].onNickChange != NULL) - windows[i].onNickChange(&windows[i], friendnumber, string, length); - } -} - -void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) -{ - wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); - int i; - for (i=0; i= TOXWINDOWS_MAX_NUM) - return -1; - - if (LINES < 2) - return -1; - - w.window = newwin(LINES - 2, COLS, 0, 0); - if (w.window == NULL) - return -1; - - windows[n] = w; - w.onInit(&w, m); - w_num++; - active_window = n; - return n; -} - -/* Deletes window w and cleans up */ -void del_window(ToxWindow *w, int f_num) -{ - active_window = 0; // Go to prompt screen - delwin(w->window); - int i; - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { - if (WINDOW_STATUS[i] == f_num) { - WINDOW_STATUS[i] = -1; - disable_chatwin(f_num); - break; - } - } - clear(); - refresh(); -} - -/* Shows next window when tab or back-tab is pressed */ -void set_active_window(int ch) -{ - int f_inf = 0; - int max = MAX_WINDOW_SLOTS-1; - if (ch == '\t') { - int i = (active_window + 1) % max; - while (true) { - if (WINDOW_STATUS[i] != -1) { - active_window = i; - return; - } - i = (i + 1) % max; - if (f_inf++ > max) { // infinite loop check - endwin(); - exit(2); - } - } - }else { - int i = active_window - 1; - if (i < 0) i = max; - while (true) { - if (WINDOW_STATUS[i] != -1) { - active_window = i; - return; - } - if (--i < 0) i = max; - if (f_inf++ > max) { - endwin(); - exit(2); - } - } - } -} - -static void init_windows(Messenger *m) -{ - w_num = 0; - int n_prompt = 0; - int n_friendslist = 1; - if (add_window(m, new_prompt(on_friendadded), n_prompt) == -1 - || add_window(m, new_friendlist(del_window, set_active_window, add_window, WINDOW_STATUS), n_friendslist) == -1) { - fprintf(stderr, "add_window() failed.\n"); - endwin(); - exit(1); - } - prompt = &windows[n_prompt]; -} - -static void do_tox(Messenger *m) +static void do_tox(Messenger *m, ToxWindow * prompt) { static int conn_try = 0; static int conn_err = 0; @@ -367,54 +196,8 @@ static void load_data(Messenger *m, char *path) fclose(fd); } -static void draw_bar() -{ - static int odd = 0; - int blinkrate = 30; - - attron(COLOR_PAIR(4)); - mvhline(LINES - 2, 0, '_', COLS); - attroff(COLOR_PAIR(4)); - - move(LINES - 1, 0); - - attron(COLOR_PAIR(4) | A_BOLD); - printw(" TOXIC " TOXICVER "|"); - attroff(COLOR_PAIR(4) | A_BOLD); - - int i; - for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) { - if (WINDOW_STATUS[i] != -1) { - if (i == active_window) - attron(A_BOLD); - - odd = (odd+1) % blinkrate; - if (windows[i].blink && (odd < (blinkrate/2))) - attron(COLOR_PAIR(3)); - - printw(" %s", windows[i].title); - if (windows[i].blink && (odd < (blinkrate/2))) - attroff(COLOR_PAIR(3)); - - if (i == active_window) { - attroff(A_BOLD); - } - } - } - refresh(); -} - -void prepare_window(WINDOW *w) -{ - mvwin(w, 0, 0); - wresize(w, LINES-2, COLS); -} - - int main(int argc, char *argv[]) { - int ch; - ToxWindow* a; char *user_config_dir = get_user_config_dir(); char *DATA_FILE; int config_err = create_user_config_dir(user_config_dir); @@ -449,7 +232,7 @@ int main(int argc, char *argv[]) init_term(); Messenger *m = init_tox(); - init_windows(m); + ToxWindow * prompt = init_windows(m); init_window_status(); if(f_loadfromfile) @@ -471,21 +254,10 @@ int main(int argc, char *argv[]) } while(true) { /* Update tox */ - do_tox(m); + do_tox(m, prompt); /* Draw */ - a = &windows[active_window]; - prepare_window(a->window); - a->blink = false; - draw_bar(); - a->onDraw(a); - - /* Handle input */ - ch = getch(); - if (ch == '\t' || ch == KEY_BTAB) - set_active_window(ch); - else if (ch != ERR) - a->onKey(a, m, ch); + draw_active_window(m); } cleanupMessenger(m); return 0; diff --git a/windows.c b/windows.c new file mode 100644 index 0000000..c395243 --- /dev/null +++ b/windows.c @@ -0,0 +1,235 @@ +#include "friendlist.h" +#include "prompt.h" +#include "windows.h" + +/* Holds status of chat windows */ +char WINDOW_STATUS[MAX_WINDOW_SLOTS]; + +static int w_num; +static ToxWindow windows[MAX_WINDOW_SLOTS]; +static Messenger *m; +int active_window; + +static ToxWindow* prompt; + +/* CALLBACKS START */ +void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void* userdata) +{ + int n = add_req(public_key); + wprintw(prompt->window, "\nFriend request from:\n"); + + int i; + for (i = 0; i < KEY_SIZE_BYTES; ++i) { + wprintw(prompt->window, "%02x", public_key[i] & 0xff); + } + + wprintw(prompt->window, "\nWith the message: %s\n", data); + wprintw(prompt->window, "\nUse \"accept %d\" to accept it.\n", n); + + for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + if (windows[i].onFriendRequest != NULL) + windows[i].onFriendRequest(&windows[i], public_key, data, length); + } +} + +void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) +{ + int i; + for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + if (windows[i].onMessage != NULL) + windows[i].onMessage(&windows[i], m, friendnumber, string, length); + } +} + +void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) +{ + int i; + for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + if (windows[i].onAction != NULL) + windows[i].onAction(&windows[i], m, friendnumber, string, length); + } +} + +void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) +{ + wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string); + int i; + for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + if (windows[i].onNickChange != NULL) + windows[i].onNickChange(&windows[i], friendnumber, string, length); + } +} + +void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) +{ + wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); + int i; + for (i=0; i= TOXWINDOWS_MAX_NUM) + return -1; + + if (LINES < 2) + return -1; + + w.window = newwin(LINES - 2, COLS, 0, 0); + if (w.window == NULL) + return -1; + + windows[n] = w; + w.onInit(&w, m); + w_num++; + active_window = n; + return n; +} + +/* Deletes window w and cleans up */ +void del_window(ToxWindow *w, int f_num) +{ + active_window = 0; // Go to prompt screen + delwin(w->window); + int i; + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { + if (WINDOW_STATUS[i] == f_num) { + WINDOW_STATUS[i] = -1; + disable_chatwin(f_num); + break; + } + } + clear(); + refresh(); +} + +/* Shows next window when tab or back-tab is pressed */ +void set_active_window(int ch) +{ + int f_inf = 0; + int max = MAX_WINDOW_SLOTS-1; + if (ch == '\t') { + int i = (active_window + 1) % max; + while (true) { + if (WINDOW_STATUS[i] != -1) { + active_window = i; + return; + } + i = (i + 1) % max; + if (f_inf++ > max) { // infinite loop check + endwin(); + exit(2); + } + } + }else { + int i = active_window - 1; + if (i < 0) i = max; + while (true) { + if (WINDOW_STATUS[i] != -1) { + active_window = i; + return; + } + if (--i < 0) i = max; + if (f_inf++ > max) { + endwin(); + exit(2); + } + } + } +} + +void init_window_status() +{ + /* Default window values decrement from -2 */ + int i; + for (i = 0; i < N_DEFAULT_WINS; ++i) + WINDOW_STATUS[i] = -(i+2); + + int j; + for (j = N_DEFAULT_WINS; j < MAX_WINDOW_SLOTS; j++) + WINDOW_STATUS[j] = -1; +} + +ToxWindow * init_windows() +{ + w_num = 0; + int n_prompt = 0; + int n_friendslist = 1; + if (add_window(m, new_prompt(on_friendadded), n_prompt) == -1 + || add_window(m, new_friendlist(del_window, set_active_window, add_window, WINDOW_STATUS), n_friendslist) == -1) { + fprintf(stderr, "add_window() failed.\n"); + endwin(); + exit(1); + } + prompt = &windows[n_prompt]; + return prompt; +} + +static void draw_bar() +{ + static int odd = 0; + int blinkrate = 30; + + attron(COLOR_PAIR(4)); + mvhline(LINES - 2, 0, '_', COLS); + attroff(COLOR_PAIR(4)); + + move(LINES - 1, 0); + + attron(COLOR_PAIR(4) | A_BOLD); + printw(" TOXIC " TOXICVER "|"); + attroff(COLOR_PAIR(4) | A_BOLD); + + int i; + for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) { + if (WINDOW_STATUS[i] != -1) { + if (i == active_window) + attron(A_BOLD); + + odd = (odd+1) % blinkrate; + if (windows[i].blink && (odd < (blinkrate/2))) + attron(COLOR_PAIR(3)); + + printw(" %s", windows[i].title); + if (windows[i].blink && (odd < (blinkrate/2))) + attroff(COLOR_PAIR(3)); + + if (i == active_window) { + attroff(A_BOLD); + } + } + } + refresh(); +} + +void prepare_window(WINDOW *w) +{ + mvwin(w, 0, 0); + wresize(w, LINES-2, COLS); +} + +void draw_active_window(Messenger * m) +{ + + ToxWindow *a = &windows[active_window]; + prepare_window(a->window); + a->blink = false; + draw_bar(); + a->onDraw(a); + + /* Handle input */ + int ch = getch(); + if (ch == '\t' || ch == KEY_BTAB) + set_active_window(ch); + else if (ch != ERR) + a->onKey(a, m, ch); +} diff --git a/windows.h b/windows.h index 4eb55a9..613fa3b 100644 --- a/windows.h +++ b/windows.h @@ -38,5 +38,13 @@ struct ToxWindow_ { WINDOW* window; }; +void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void* userdata); +void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); +void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); +void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); +void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); +void init_window_status(); +ToxWindow * init_windows(); +void draw_active_window(Messenger * m); #endif From 4a3292a32b7db96e6c073beb2b87a131ac190c14 Mon Sep 17 00:00:00 2001 From: Aaron Lipinski Date: Tue, 13 Aug 2013 12:32:09 +1200 Subject: [PATCH 128/172] remove temporary callbacks from refactoring --- chat.c | 5 +---- chat.h | 3 +-- friendlist.c | 13 ++++--------- friendlist.h | 6 ++---- windows.c | 2 +- windows.h | 3 +++ 6 files changed, 12 insertions(+), 20 deletions(-) diff --git a/chat.c b/chat.c index 6811569..e4da948 100644 --- a/chat.c +++ b/chat.c @@ -26,8 +26,6 @@ typedef struct { WINDOW* linewin; } ChatContext; -static delWindowFn *del_window; - void print_help(ChatContext *self); void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd); @@ -370,9 +368,8 @@ void print_help(ChatContext *self) wattroff(self->history, COLOR_PAIR(2)); } -ToxWindow new_chat(Messenger *m, int friendnum, delWindowFn *f) +ToxWindow new_chat(Messenger *m, int friendnum) { - del_window = f; ToxWindow ret; memset(&ret, 0, sizeof(ret)); diff --git a/chat.h b/chat.h index dcd5b3b..7599d46 100644 --- a/chat.h +++ b/chat.h @@ -1,7 +1,6 @@ #ifndef CHAT_H_6489PZ13 #define CHAT_H_6489PZ13 -typedef void (delWindowFn)(ToxWindow *w, int f_num); -ToxWindow new_chat(Messenger *m, int friendnum, delWindowFn f); +ToxWindow new_chat(Messenger *m, int friendnum); #endif /* end of include guard: CHAT_H_6489PZ13 */ diff --git a/friendlist.c b/friendlist.c index 5b79fde..e7504fb 100644 --- a/friendlist.c +++ b/friendlist.c @@ -10,11 +10,9 @@ #include "../../core/Messenger.h" #include "../../core/network.h" +#include "windows.h" #include "friendlist.h" -static delWindowFn *del_window; -static setActiveWindowFn *set_active_window; -static addWindowFn *add_window; static char * WINDOW_STATUS; typedef struct { @@ -53,7 +51,7 @@ void friendlist_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *str, for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { if (WINDOW_STATUS[i] == -1) { WINDOW_STATUS[i] = num; - add_window(m, new_chat(m, num, del_window), i); + add_window(m, new_chat(m, num), i); break; } } @@ -119,7 +117,7 @@ static void friendlist_onKey(ToxWindow *self, Messenger *m, int key) if (WINDOW_STATUS[i] == -1) { WINDOW_STATUS[i] = num_selected; friends[num_selected].chatwin = num_selected; - add_window(m, new_chat(m, num_selected, del_window), i); + add_window(m, new_chat(m, num_selected), i); break; } } @@ -166,10 +164,7 @@ static void friendlist_onInit(ToxWindow *self, Messenger *m) } -ToxWindow new_friendlist(delWindowFn dw, setActiveWindowFn saw, addWindowFn aw, char * ws) { - del_window = dw; - set_active_window = saw; - add_window = aw; +ToxWindow new_friendlist(char * ws) { WINDOW_STATUS = ws; ToxWindow ret; memset(&ret, 0, sizeof(ret)); diff --git a/friendlist.h b/friendlist.h index e8b93ae..c3d8dac 100644 --- a/friendlist.h +++ b/friendlist.h @@ -1,12 +1,10 @@ #ifndef FRIENDLIST_H_53I41IM #define FRIENDLIST_H_53I41IM - #include "windows.h" #include "chat.h" -typedef void (setActiveWindowFn)(int ch); -typedef int (addWindowFn)(Messenger *m, ToxWindow w, int n); -ToxWindow new_friendlist(delWindowFn dw, setActiveWindowFn saw, addWindowFn aw, char * ws); + +ToxWindow new_friendlist(char * ws); int friendlist_onFriendAdded(Messenger *m, int num); void disable_chatwin(int f_num); void fix_name(uint8_t *name); diff --git a/windows.c b/windows.c index c395243..d19392a 100644 --- a/windows.c +++ b/windows.c @@ -165,7 +165,7 @@ ToxWindow * init_windows() int n_prompt = 0; int n_friendslist = 1; if (add_window(m, new_prompt(on_friendadded), n_prompt) == -1 - || add_window(m, new_friendlist(del_window, set_active_window, add_window, WINDOW_STATUS), n_friendslist) == -1) { + || add_window(m, new_friendlist(WINDOW_STATUS), n_friendslist) == -1) { fprintf(stderr, "add_window() failed.\n"); endwin(); exit(1); diff --git a/windows.h b/windows.h index 613fa3b..37f3e9d 100644 --- a/windows.h +++ b/windows.h @@ -46,5 +46,8 @@ void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t l void init_window_status(); ToxWindow * init_windows(); void draw_active_window(Messenger * m); +int add_window(Messenger *m, ToxWindow w, int n); +void del_window(ToxWindow *w, int f_num); +void set_active_window(int ch); #endif From 56210d46f992516fc28e0b62d9a96433b153f830 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 14 Aug 2013 08:56:29 -0400 Subject: [PATCH 129/172] Fixed small compile error on my end. --- main.c | 3 --- windows.h | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index d7b251d..063c148 100644 --- a/main.c +++ b/main.c @@ -24,9 +24,6 @@ #include "prompt.h" #include "friendlist.h" -#ifndef TOXICVER -#define TOXICVER "NOVER" //Use the -D flag to set this -#endif static void init_term() { diff --git a/windows.h b/windows.h index 37f3e9d..7d81e81 100644 --- a/windows.h +++ b/windows.h @@ -19,6 +19,10 @@ /* maximum window slots for WINDOW_STATUS array */ #define MAX_WINDOW_SLOTS N_DEFAULT_WINS+MAX_FRIENDS_NUM +#ifndef TOXICVER +#define TOXICVER "NOVER" //Use the -D flag to set this +#endif + typedef struct ToxWindow_ ToxWindow; struct ToxWindow_ { From 9cabdaa6a0cb9e1cc4ed43cf6df88b2f9577fa3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Arg=C3=BCelles?= Date: Wed, 14 Aug 2013 10:40:26 -0500 Subject: [PATCH 130/172] Fix segfault when using -f in toxic Call strdup() to the data file argument string to avoid segmentation fault when it is later freed. --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index 063c148..ec33c72 100644 --- a/main.c +++ b/main.c @@ -218,7 +218,7 @@ int main(int argc, char *argv[]) else if (argv[i][0] == '-') { if (argv[i][1] == 'f') { if (argv[i + 1] != NULL) - DATA_FILE = argv[i + 1]; + DATA_FILE = strdup(argv[i + 1]); else f_flag = -1; } else if (argv[i][1] == 'n') { From cab4d4388900af61f4dbe8e110bdf3efe724c974 Mon Sep 17 00:00:00 2001 From: naxuroqa Date: Wed, 14 Aug 2013 19:21:36 +0200 Subject: [PATCH 131/172] Fix for another segfault/leak case when using -f arg --- main.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/main.c b/main.c index ec33c72..53639eb 100644 --- a/main.c +++ b/main.c @@ -196,17 +196,8 @@ static void load_data(Messenger *m, char *path) int main(int argc, char *argv[]) { char *user_config_dir = get_user_config_dir(); - char *DATA_FILE; - int config_err = create_user_config_dir(user_config_dir); - if(config_err) { - DATA_FILE = "data"; - } else { - DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); - strcpy(DATA_FILE, user_config_dir); - strcat(DATA_FILE, CONFIGDIR); - strcat(DATA_FILE, "data"); - } - free(user_config_dir); + char *DATA_FILE = NULL; + int config_err = 0; /* This is broken */ int f_loadfromfile = 1; @@ -227,6 +218,19 @@ int main(int argc, char *argv[]) } } + if (DATA_FILE == NULL ) { + config_err = create_user_config_dir(user_config_dir); + if (config_err) { + DATA_FILE = strdup("data"); + } else { + DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); + strcpy(DATA_FILE, user_config_dir); + strcat(DATA_FILE, CONFIGDIR); + strcat(DATA_FILE, "data"); + } + } + free(user_config_dir); + init_term(); Messenger *m = init_tox(); ToxWindow * prompt = init_windows(m); From 202d162d2e8f7f972bdea6e4adce57cc4302a052 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 14 Aug 2013 16:02:21 -0400 Subject: [PATCH 132/172] small bug fixes --- chat.c | 2 +- main.c | 5 ++--- prompt.c | 2 +- windows.c | 5 +++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/chat.c b/chat.c index e4da948..d5edf95 100644 --- a/chat.c +++ b/chat.c @@ -314,7 +314,7 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); strcat(id, xx); } - wprintw(ctx->history, "Your ID: %s\n", id); + wprintw(ctx->history, "%s\n", id); } else if (strcmp(ctx->line, "/close") == 0) { diff --git a/main.c b/main.c index 53639eb..d1a4be5 100644 --- a/main.c +++ b/main.c @@ -45,7 +45,7 @@ static void init_term() refresh(); } -static Messenger * init_tox() +static Messenger *init_tox() { /* Init core */ Messenger *m = initMessenger(); @@ -199,7 +199,6 @@ int main(int argc, char *argv[]) char *DATA_FILE = NULL; int config_err = 0; - /* This is broken */ int f_loadfromfile = 1; int f_flag = 0; int i = 0; @@ -233,7 +232,7 @@ int main(int argc, char *argv[]) init_term(); Messenger *m = init_tox(); - ToxWindow * prompt = init_windows(m); + ToxWindow *prompt = init_windows(m); init_window_status(); if(f_loadfromfile) diff --git a/prompt.c b/prompt.c index fb8a509..b84773a 100644 --- a/prompt.c +++ b/prompt.c @@ -238,7 +238,7 @@ void cmd_myid(ToxWindow *self, Messenger *m, char **args) snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); strcat(id, xx); } - wprintw(self->window, "Your ID: %s\n", id); + wprintw(self->window, "%s\n", id); } void cmd_nick(ToxWindow *self, Messenger *m, char **args) diff --git a/windows.c b/windows.c index d19392a..aab46e9 100644 --- a/windows.c +++ b/windows.c @@ -159,7 +159,7 @@ void init_window_status() WINDOW_STATUS[j] = -1; } -ToxWindow * init_windows() +ToxWindow *init_windows() { w_num = 0; int n_prompt = 0; @@ -170,6 +170,7 @@ ToxWindow * init_windows() endwin(); exit(1); } + active_window = n_prompt; prompt = &windows[n_prompt]; return prompt; } @@ -217,7 +218,7 @@ void prepare_window(WINDOW *w) wresize(w, LINES-2, COLS); } -void draw_active_window(Messenger * m) +void draw_active_window(Messenger *m) { ToxWindow *a = &windows[active_window]; From 0ac97aa79401493f3bc5209dfa057b3e652a3cf2 Mon Sep 17 00:00:00 2001 From: Aaron Lipinski Date: Sun, 11 Aug 2013 12:59:16 +1200 Subject: [PATCH 133/172] refresh windows after resize --- main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/main.c b/main.c index d1a4be5..aa025a1 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef _win32 #include @@ -25,9 +26,17 @@ #include "friendlist.h" +void on_window_resize(int sig) +{ + endwin(); + refresh(); + clear(); +} + static void init_term() { /* Setup terminal */ + signal(SIGWINCH, on_window_resize); initscr(); cbreak(); keypad(stdscr, 1); From 1af9d84aad95a83f11bc104ac2da68be4e65c186 Mon Sep 17 00:00:00 2001 From: Aaron Lipinski Date: Sun, 11 Aug 2013 14:48:02 +1200 Subject: [PATCH 134/172] add dhtstatus file --- CMakeLists.txt | 1 + dhtstatus.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ dhtstatus.h | 8 +++++ 3 files changed, 98 insertions(+) create mode 100644 dhtstatus.c create mode 100644 dhtstatus.h diff --git a/CMakeLists.txt b/CMakeLists.txt index dd811b9..9ee7020 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ add_executable(${exe_name} windows.c prompt.c friendlist.c + dhtstatus.c chat.c configdir.c) diff --git a/dhtstatus.c b/dhtstatus.c new file mode 100644 index 0000000..6626890 --- /dev/null +++ b/dhtstatus.c @@ -0,0 +1,89 @@ +#include "dhtstatus.h" +#include "string.h" +#include "../../core/network.h" +#include "../../core/DHT.h" + +typedef uint8_t ipbuf[3*4+3+1]; +static int num_selected = 0; + +static void printip(ipbuf buf, IP ip) +{ + sprintf((char*)buf, "%u.%u.%u.%u", ip.c[0], ip.c[1], ip.c[2], ip.c[3]); +} + +static void dhtstatus_onKey(ToxWindow *self, Messenger *m, int key) +{ + switch(key) { + case KEY_UP: + case 'k': + if (--num_selected < 0) + num_selected = CLIENT_ID_SIZE-1; + break; + + case KEY_DOWN: + case 'j': + num_selected = (num_selected+1) % CLIENT_ID_SIZE; + break; + + case '\n': + break; + + default: + break; + } +} + +static void dhtstatus_onDraw(ToxWindow *self) +{ + Client_data * close_clientlist = DHT_get_close_list(); + curs_set(0); + werase(self->window); + + uint64_t now = unix_time(); + uint32_t i, j; + ipbuf ipbuf; + wprintw(self->window,"\n%llu ______________________ CLOSE LIST ________________________ ___ IP ADDR ___ _PRT_ LST PNG ____ SELF ____ _PRT_ LST\n\n", now); + for(i = 0; i < CLIENT_ID_SIZE; i++) { + Client_data * client = close_clientlist + i; + if (i == num_selected) wattron(self->window, COLOR_PAIR(3)); + wprintw(self->window,"[%02i] ", i); + uint16_t port = ntohs(client->ip_port.port); + if(port) { + for(j = 0; j < 32; j++) + wprintw(self->window, "%02hhx", client->client_id[j]); + + printip(ipbuf, client->ip_port.ip); + wprintw(self->window, " %15s %5u ", ipbuf, port); + wprintw(self->window, " %3llu ", now - client->timestamp); + wprintw(self->window, " %3llu ", now - client->last_pinged); + + port = ntohs(client->ret_ip_port.port); + if(port) { + printip(ipbuf, client->ret_ip_port.ip); + wprintw(self->window, " %15s %5u %3llu", ipbuf, port, now - close_clientlist[i].ret_timestamp); + } + } + wprintw(self->window, "\n"); + if (i == num_selected) wattroff(self->window, COLOR_PAIR(3)); + } + + wrefresh(self->window); +} + +static void dhtstatus_onInit(ToxWindow *self, Messenger *m) +{ + +} + +ToxWindow new_dhtstatus() +{ + ToxWindow ret; + memset(&ret, 0, sizeof(ret)); + + ret.onKey = &dhtstatus_onKey; + ret.onDraw = &dhtstatus_onDraw; + ret.onInit = &dhtstatus_onInit; + + strcpy(ret.title, "[dht status]"); + return ret; +} diff --git a/dhtstatus.h b/dhtstatus.h new file mode 100644 index 0000000..2b30e5a --- /dev/null +++ b/dhtstatus.h @@ -0,0 +1,8 @@ +#ifndef _dhtstatus_h +#define _dhtstatus_h + +#include "windows.h" + +ToxWindow new_dhtstatus(); + +#endif From 662b1f2bac9d5e8debbd5d158bc8f13b1b397f66 Mon Sep 17 00:00:00 2001 From: Aaron Lipinski Date: Sun, 11 Aug 2013 14:49:41 +1200 Subject: [PATCH 135/172] add dhtstatus window --- windows.c | 5 ++++- windows.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/windows.c b/windows.c index aab46e9..6de5074 100644 --- a/windows.c +++ b/windows.c @@ -1,5 +1,6 @@ #include "friendlist.h" #include "prompt.h" +#include "dhtstatus.h" #include "windows.h" /* Holds status of chat windows */ @@ -164,8 +165,10 @@ ToxWindow *init_windows() w_num = 0; int n_prompt = 0; int n_friendslist = 1; + int n_dhtstatus = 2; if (add_window(m, new_prompt(on_friendadded), n_prompt) == -1 - || add_window(m, new_friendlist(WINDOW_STATUS), n_friendslist) == -1) { + || add_window(m, new_friendlist(WINDOW_STATUS), n_friendslist) == -1 + || add_window(m, new_dhtstatus(), n_dhtstatus) == -1) { fprintf(stderr, "add_window() failed.\n"); endwin(); exit(1); diff --git a/windows.h b/windows.h index 7d81e81..893ccf6 100644 --- a/windows.h +++ b/windows.h @@ -14,7 +14,7 @@ #define KEY_SIZE_BYTES 32 /* number of permanent default windows */ -#define N_DEFAULT_WINS 2 +#define N_DEFAULT_WINS 3 /* maximum window slots for WINDOW_STATUS array */ #define MAX_WINDOW_SLOTS N_DEFAULT_WINS+MAX_FRIENDS_NUM From 399dd33b97ee92dee70aace7de1779bbc6fda13e Mon Sep 17 00:00:00 2001 From: Michael Rose Date: Thu, 15 Aug 2013 12:11:48 +0200 Subject: [PATCH 136/172] Merge fix --- main.c | 114 +++++++++++++++++++++++++++++++++--------------------- prompt.c | 8 ++-- windows.c | 6 +++ windows.h | 1 + 4 files changed, 81 insertions(+), 48 deletions(-) diff --git a/main.c b/main.c index aa025a1..4d52469 100644 --- a/main.c +++ b/main.c @@ -25,6 +25,8 @@ #include "prompt.h" #include "friendlist.h" +/* Export for use in Callbacks */ +char *DATA_FILE = NULL; void on_window_resize(int sig) { @@ -145,67 +147,90 @@ static void do_tox(Messenger *m, ToxWindow * prompt) doMessenger(m); } -static void load_data(Messenger *m, char *path) +/* + * Store Messenger to given location + * Return 0 stored successfully + * Return 1 malloc failed + * Return 2 opening path failed + * Return 3 fwrite failed + */ +int store_data(Messenger *m, char *path) { - FILE *fd; - size_t len; - uint8_t *buf; + FILE *fd; + size_t len; + uint8_t *buf; - if ((fd = fopen(path, "r")) != NULL) { - fseek(fd, 0, SEEK_END); - len = ftell(fd); - fseek(fd, 0, SEEK_SET); - - buf = malloc(len); - if (buf == NULL) { - fprintf(stderr, "malloc() failed.\n"); - fclose(fd); - endwin(); - exit(1); - } - if (fread(buf, len, 1, fd) != 1){ - fprintf(stderr, "fread() failed.\n"); - free(buf); - fclose(fd); - endwin(); - exit(1); - } - Messenger_load(m, buf, len); - } - else { len = Messenger_size(m); buf = malloc(len); if (buf == NULL) { - fprintf(stderr, "malloc() failed.\n"); - endwin(); - exit(1); + return 1; } Messenger_save(m, buf); fd = fopen(path, "w"); if (fd == NULL) { - fprintf(stderr, "fopen() failed.\n"); - free(buf); - endwin(); - exit(1); + free(buf); + return 2; } - if (fwrite(buf, len, 1, fd) != 1){ - fprintf(stderr, "fwrite() failed.\n"); - free(buf); - fclose(fd); - endwin(); - exit(1); + if (fwrite(buf, len, 1, fd) != 1) { + free(buf); + fclose(fd); + return 3; + } + + free(buf); + fclose(fd); + return 0; +} + +static void load_data(Messenger *m, char *path) +{ + FILE *fd; + size_t len; + uint8_t *buf; + + if ((fd = fopen(path, "r")) != NULL) { + fseek(fd, 0, SEEK_END); + len = ftell(fd); + fseek(fd, 0, SEEK_SET); + + buf = malloc(len); + if (buf == NULL) { + fprintf(stderr, "malloc() failed.\n"); + fclose(fd); + endwin(); + exit(1); + } + if (fread(buf, len, 1, fd) != 1) { + fprintf(stderr, "fread() failed.\n"); + free(buf); + fclose(fd); + endwin(); + exit(1); + } + Messenger_load(m, buf, len); + + uint32_t i; + for (i = 0; i < m->numfriends; i++) { + on_friendadded(m, i); + } + + free(buf); + fclose(fd); + } else { + int st; + if ((st = store_data(m, path)) != 0) { + fprintf(stderr, "Store messenger failed with return code: %d\n", st); + endwin(); + exit(1); + } } - } - free(buf); - fclose(fd); } int main(int argc, char *argv[]) { char *user_config_dir = get_user_config_dir(); - char *DATA_FILE = NULL; int config_err = 0; int f_loadfromfile = 1; @@ -246,7 +271,6 @@ int main(int argc, char *argv[]) if(f_loadfromfile) load_data(m, DATA_FILE); - free(DATA_FILE); if (f_flag == -1) { attron(COLOR_PAIR(3) | A_BOLD); @@ -268,6 +292,8 @@ int main(int argc, char *argv[]) /* Draw */ draw_active_window(m); } + cleanupMessenger(m); + free(DATA_FILE); return 0; } diff --git a/prompt.c b/prompt.c index b84773a..1d0e014 100644 --- a/prompt.c +++ b/prompt.c @@ -16,7 +16,7 @@ uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX uint8_t num_requests=0; // XXX -static friendAddedFn *on_friendadded; +static friendAddedFn *on_friendadded_cb; static char prompt_buf[MAX_STR_SIZE] = {0}; static int prompt_buf_pos = 0; @@ -88,7 +88,7 @@ void cmd_accept(ToxWindow *self, Messenger *m, char **args) wprintw(self->window, "Failed to add friend.\n"); else { wprintw(self->window, "Friend accepted as: %d.\n", num); - on_friendadded(m, num); + on_friendadded_cb(m, num); } } @@ -152,7 +152,7 @@ void cmd_add(ToxWindow *self, Messenger *m, char **args) break; default: wprintw(self->window, "Friend added as %d.\n", num); - on_friendadded(m, num); + on_friendadded_cb(m, num); break; } } @@ -436,7 +436,7 @@ static void prompt_onInit(ToxWindow *self, Messenger *m) ToxWindow new_prompt(friendAddedFn *f) { - on_friendadded = f; + on_friendadded_cb = f; ToxWindow ret; memset(&ret, 0, sizeof(ret)); ret.onKey = &prompt_onKey; diff --git a/windows.c b/windows.c index 6de5074..15caddf 100644 --- a/windows.c +++ b/windows.c @@ -3,6 +3,9 @@ #include "dhtstatus.h" #include "windows.h" +extern char *DATA_FILE; +extern int store_data(Messenger *m, char *path); + /* Holds status of chat windows */ char WINDOW_STATUS[MAX_WINDOW_SLOTS]; @@ -74,6 +77,9 @@ void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t l void on_friendadded(Messenger *m, int friendnumber) { friendlist_onFriendAdded(m, friendnumber); + if (store_data(m, DATA_FILE) != 0) { + wprintw(prompt->window, "\nCould not store Messenger data\n"); + } } /* CALLBACKS END */ diff --git a/windows.h b/windows.h index 893ccf6..9f4d74a 100644 --- a/windows.h +++ b/windows.h @@ -47,6 +47,7 @@ void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); +void on_friendadded(Messenger *m, int friendnumber); void init_window_status(); ToxWindow * init_windows(); void draw_active_window(Messenger * m); From a59f4867ee6a85a6c6b664348a2689c2565f8df4 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 15 Aug 2013 14:24:32 -0400 Subject: [PATCH 137/172] Small improvement to DHT. Useless file removed. Small fix to toxic. --- dhtstatus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dhtstatus.c b/dhtstatus.c index 6626890..e026a17 100644 --- a/dhtstatus.c +++ b/dhtstatus.c @@ -43,13 +43,13 @@ static void dhtstatus_onDraw(ToxWindow *self) uint32_t i, j; ipbuf ipbuf; wprintw(self->window,"\n%llu ______________________ CLOSE LIST ________________________ ___ IP ADDR ___ _PRT_ LST PNG ____ SELF ____ _PRT_ LST\n\n", now); - for(i = 0; i < CLIENT_ID_SIZE; i++) { + for(i = 0; i < 32; i++) { /*Number of nodes in closelist*/ Client_data * client = close_clientlist + i; if (i == num_selected) wattron(self->window, COLOR_PAIR(3)); wprintw(self->window,"[%02i] ", i); uint16_t port = ntohs(client->ip_port.port); if(port) { - for(j = 0; j < 32; j++) + for(j = 0; j < CLIENT_ID_SIZE; j++) wprintw(self->window, "%02hhx", client->client_id[j]); printip(ipbuf, client->ip_port.ip); From 9f9ca0a9718185cca8df9a93e0d716d1b0138276 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 15 Aug 2013 20:56:22 -0400 Subject: [PATCH 138/172] Fixed loading and a small problem with the length of crypto requests. --- main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 4d52469..38c20df 100644 --- a/main.c +++ b/main.c @@ -147,6 +147,8 @@ static void do_tox(Messenger *m, ToxWindow * prompt) doMessenger(m); } +int f_loadfromfile; + /* * Store Messenger to given location * Return 0 stored successfully @@ -156,6 +158,8 @@ static void do_tox(Messenger *m, ToxWindow * prompt) */ int store_data(Messenger *m, char *path) { + if (f_loadfromfile == 0) /*If file loading/saving is disabled*/ + return 0; FILE *fd; size_t len; uint8_t *buf; @@ -186,6 +190,8 @@ int store_data(Messenger *m, char *path) static void load_data(Messenger *m, char *path) { + if (f_loadfromfile == 0) /*If file loading/saving is disabled*/ + return; FILE *fd; size_t len; uint8_t *buf; @@ -233,7 +239,7 @@ int main(int argc, char *argv[]) char *user_config_dir = get_user_config_dir(); int config_err = 0; - int f_loadfromfile = 1; + f_loadfromfile = 1; int f_flag = 0; int i = 0; for (i = 0; i < argc; ++i) { From 9dce121a76c5a70bb79a0c08d4e7f3df5c1519bb Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 16 Aug 2013 13:11:09 -0400 Subject: [PATCH 139/172] Passed everything through astyle. --- chat.c | 631 +++++++++++++++++++++++++------------------------ configdir.c | 77 +++--- configdir.h | 2 +- dhtstatus.c | 134 ++++++----- friendlist.c | 227 +++++++++--------- friendlist.h | 2 +- main.c | 299 +++++++++++++----------- prompt.c | 647 +++++++++++++++++++++++++++------------------------ windows.c | 336 ++++++++++++++------------ windows.h | 38 +-- 10 files changed, 1256 insertions(+), 1137 deletions(-) diff --git a/chat.c b/chat.c index d5edf95..ef932cd 100644 --- a/chat.c +++ b/chat.c @@ -19,376 +19,391 @@ #define CURS_Y_OFFSET 3 typedef struct { - int friendnum; - char line[MAX_STR_SIZE]; - size_t pos; - WINDOW* history; - WINDOW* linewin; + int friendnum; + char line[MAX_STR_SIZE]; + size_t pos; + WINDOW *history; + WINDOW *linewin; } ChatContext; void print_help(ChatContext *self); void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd); -struct tm *get_time(void) +struct tm *get_time(void) { - struct tm *timeinfo; - time_t now; - time(&now); - timeinfo = localtime(&now); - return timeinfo; + struct tm *timeinfo; + time_t now; + time(&now); + timeinfo = localtime(&now); + return timeinfo; } static void chat_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *msg, uint16_t len) { - ChatContext *ctx = (ChatContext*) self->x; - uint8_t nick[MAX_NAME_LENGTH] = {0}; - struct tm *timeinfo = get_time(); + ChatContext *ctx = (ChatContext *) self->x; + uint8_t nick[MAX_NAME_LENGTH] = {0}; + struct tm *timeinfo = get_time(); - if (ctx->friendnum != num) - return; + if (ctx->friendnum != num) + return; - getname(m, num, (uint8_t*) &nick); - msg[len-1] = '\0'; - nick[MAX_NAME_LENGTH-1] = '\0'; - fix_name(msg); - fix_name(nick); + getname(m, num, (uint8_t *) &nick); + msg[len - 1] = '\0'; + nick[MAX_NAME_LENGTH - 1] = '\0'; + fix_name(msg); + fix_name(nick); - wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); - wattroff(ctx->history, COLOR_PAIR(2)); - wattron(ctx->history, COLOR_PAIR(4)); - wprintw(ctx->history, "%s: ", nick); - wattroff(ctx->history, COLOR_PAIR(4)); - wprintw(ctx->history, "%s\n", msg); + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); + wattron(ctx->history, COLOR_PAIR(4)); + wprintw(ctx->history, "%s: ", nick); + wattroff(ctx->history, COLOR_PAIR(4)); + wprintw(ctx->history, "%s\n", msg); - self->blink = true; - beep(); + self->blink = true; + beep(); } static void chat_onAction(ToxWindow *self, Messenger *m, int num, uint8_t *action, uint16_t len) { - ChatContext *ctx = (ChatContext*) self->x; - struct tm *timeinfo = get_time(); - - if (ctx->friendnum != num) - return; - - action[len-1] = '\0'; - fix_name(action); - - wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); - wattroff(ctx->history, COLOR_PAIR(2)); - - wattron(ctx->history, COLOR_PAIR(5)); - wprintw(ctx->history, "%s\n", action); - wattroff(ctx->history, COLOR_PAIR(5)); - - self->blink = true; - beep(); -} - -static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len) -{ - ChatContext *ctx = (ChatContext*) self->x; - struct tm *timeinfo = get_time(); - if (ctx->friendnum != num) - return; - - wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); - wattroff(ctx->history, COLOR_PAIR(2)); - - nick[len-1] = '\0'; - fix_name(nick); - snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num); - - wattron(ctx->history, COLOR_PAIR(3)); - wprintw(ctx->history, "* Your partner changed nick to '%s'\n", nick); - wattroff(ctx->history, COLOR_PAIR(3)); -} - -static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint16_t len) -{ - ChatContext *ctx = (ChatContext*) self->x; - struct tm *timeinfo = get_time(); - if (ctx->friendnum != num) - return; - - wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); - wattroff(ctx->history, COLOR_PAIR(2)); - - status[len-1] = '\0'; - fix_name(status); - snprintf(self->title, sizeof(self->title), "[%s (%d)]", status, num); - - wattron(ctx->history, COLOR_PAIR(3)); - wprintw(ctx->history, "* Your partner changed status to '%s'\n", status); - wattroff(ctx->history, COLOR_PAIR(3)); - -} - -/* check that the string has one non-space character */ -int string_is_empty(char *string) -{ - int rc = 0; - char *copy = strdup(string); - rc = ((strtok(copy, " ") == NULL) ? 1:0); - free(copy); - return rc; -} - -static void chat_onKey(ToxWindow *self, Messenger *m, int key) -{ - ChatContext *ctx = (ChatContext*) self->x; - struct tm *timeinfo = get_time(); - - int x, y, y2, x2; - getyx(self->window, y, x); - getmaxyx(self->window, y2, x2); - - /* Add printable chars to buffer and print on input space */ - if (isprint(key)) { - if (ctx->pos != sizeof(ctx->line)-1) { - mvwaddch(self->window, y, x, key); - ctx->line[ctx->pos++] = key; - ctx->line[ctx->pos] = '\0'; - } - } - - /* BACKSPACE key: Remove one character from line */ - else if (key == 0x107 || key == 0x8 || key == 0x7f) { - if (ctx->pos > 0) { - ctx->line[--ctx->pos] = '\0'; - if (x == 0) - mvwdelch(self->window, y-1, x2-1); - else - mvwdelch(self->window, y, x-1); - } - } - - /* RETURN key: Execute command or print line */ - else if (key == '\n') { - wclear(ctx->linewin); - wmove(self->window, y2-CURS_Y_OFFSET, 0); - wclrtobot(self->window); - if (ctx->line[0] == '/') - execute(self, ctx, m, ctx->line); - else { - /* make sure the string has at least non-space character */ - if (!string_is_empty(ctx->line)) { - uint8_t selfname[MAX_NAME_LENGTH]; - getself_name(m, selfname, sizeof(selfname)); - fix_name(selfname); - - wattron(ctx->history, COLOR_PAIR(2)); - wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); - wattroff(ctx->history, COLOR_PAIR(2)); - wattron(ctx->history, COLOR_PAIR(1)); - wprintw(ctx->history, "%s: ", selfname); - wattroff(ctx->history, COLOR_PAIR(1)); - wprintw(ctx->history, "%s\n", ctx->line); - if (m_sendmessage(m, ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) == 0) { - wattron(ctx->history, COLOR_PAIR(3)); - wprintw(ctx->history, " * Failed to send message.\n"); - wattroff(ctx->history, COLOR_PAIR(3)); - } - } - } - ctx->line[0] = '\0'; - ctx->pos = 0; - } -} - -void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) -{ - if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { - wclear(self->window); - wclear(ctx->history); - int x, y; - getmaxyx(self->window, y, x); - (void) x; - wmove(self->window, y-CURS_Y_OFFSET, 0); - } - - else if (!strcmp(cmd, "/help") || !strcmp(cmd, "/h")) - print_help(ctx); - - else if (!strcmp(cmd, "/quit") || !strcmp(cmd, "/exit") || !strcmp(cmd, "/q")) { - endwin(); - exit(0); - } - - else if (!strncmp(cmd, "/me ", strlen("/me "))) { + ChatContext *ctx = (ChatContext *) self->x; struct tm *timeinfo = get_time(); - char *action = strchr(cmd, ' '); - if (action == NULL) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } - action++; + + if (ctx->friendnum != num) + return; + + action[len - 1] = '\0'; + fix_name(action); wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattroff(ctx->history, COLOR_PAIR(2)); - uint8_t selfname[MAX_NAME_LENGTH]; - int len = getself_name(m, selfname, sizeof(selfname)); - char msg[MAX_STR_SIZE-len-4]; - snprintf(msg, sizeof(msg), "* %s %s\n", (uint8_t*) selfname, action); - wattron(ctx->history, COLOR_PAIR(5)); - wprintw(ctx->history, msg); + wprintw(ctx->history, "%s\n", action); wattroff(ctx->history, COLOR_PAIR(5)); - if (m_sendaction(m, ctx->friendnum, (uint8_t*) msg, strlen(msg)+1) < 0) { - wattron(ctx->history, COLOR_PAIR(3)); - wprintw(ctx->history, " * Failed to send action\n"); - wattroff(ctx->history, COLOR_PAIR(3)); - } - } - else if (!strncmp(cmd, "/status ", strlen("/status "))) { - char *status = strchr(cmd, ' '); - char *msg; - char *status_text; - if (status == NULL) { - wprintw(ctx->history, "Invalid syntax.\n"); - return; - } - status++; - USERSTATUS status_kind; - if (!strncmp(status, "online", strlen("online"))) { - status_kind = USERSTATUS_NONE; - status_text = "ONLINE"; + self->blink = true; + beep(); +} + +static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len) +{ + ChatContext *ctx = (ChatContext *) self->x; + struct tm *timeinfo = get_time(); + + if (ctx->friendnum != num) + return; + + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); + + nick[len - 1] = '\0'; + fix_name(nick); + snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num); + + wattron(ctx->history, COLOR_PAIR(3)); + wprintw(ctx->history, "* Your partner changed nick to '%s'\n", nick); + wattroff(ctx->history, COLOR_PAIR(3)); +} + +static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint16_t len) +{ + ChatContext *ctx = (ChatContext *) self->x; + struct tm *timeinfo = get_time(); + + if (ctx->friendnum != num) + return; + + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); + + status[len - 1] = '\0'; + fix_name(status); + snprintf(self->title, sizeof(self->title), "[%s (%d)]", status, num); + + wattron(ctx->history, COLOR_PAIR(3)); + wprintw(ctx->history, "* Your partner changed status to '%s'\n", status); + wattroff(ctx->history, COLOR_PAIR(3)); + +} + +/* check that the string has one non-space character */ +int string_is_empty(char *string) +{ + int rc = 0; + char *copy = strdup(string); + rc = ((strtok(copy, " ") == NULL) ? 1 : 0); + free(copy); + return rc; +} + +static void chat_onKey(ToxWindow *self, Messenger *m, int key) +{ + ChatContext *ctx = (ChatContext *) self->x; + struct tm *timeinfo = get_time(); + + int x, y, y2, x2; + getyx(self->window, y, x); + getmaxyx(self->window, y2, x2); + + /* Add printable chars to buffer and print on input space */ + if (isprint(key)) { + if (ctx->pos != sizeof(ctx->line) - 1) { + mvwaddch(self->window, y, x, key); + ctx->line[ctx->pos++] = key; + ctx->line[ctx->pos] = '\0'; + } } - else if (!strncmp(status, "away", strlen("away"))) { - status_kind = USERSTATUS_AWAY; - status_text = "AWAY"; + /* BACKSPACE key: Remove one character from line */ + else if (key == 0x107 || key == 0x8 || key == 0x7f) { + if (ctx->pos > 0) { + ctx->line[--ctx->pos] = '\0'; + + if (x == 0) + mvwdelch(self->window, y - 1, x2 - 1); + else + mvwdelch(self->window, y, x - 1); + } } - else if (!strncmp(status, "busy", strlen("busy"))) { - status_kind = USERSTATUS_BUSY; - status_text = "BUSY"; + /* RETURN key: Execute command or print line */ + else if (key == '\n') { + wclear(ctx->linewin); + wmove(self->window, y2 - CURS_Y_OFFSET, 0); + wclrtobot(self->window); + + if (ctx->line[0] == '/') + execute(self, ctx, m, ctx->line); + else { + /* make sure the string has at least non-space character */ + if (!string_is_empty(ctx->line)) { + uint8_t selfname[MAX_NAME_LENGTH]; + getself_name(m, selfname, sizeof(selfname)); + fix_name(selfname); + + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); + wattron(ctx->history, COLOR_PAIR(1)); + wprintw(ctx->history, "%s: ", selfname); + wattroff(ctx->history, COLOR_PAIR(1)); + wprintw(ctx->history, "%s\n", ctx->line); + + if (m_sendmessage(m, ctx->friendnum, (uint8_t *) ctx->line, strlen(ctx->line) + 1) == 0) { + wattron(ctx->history, COLOR_PAIR(3)); + wprintw(ctx->history, " * Failed to send message.\n"); + wattroff(ctx->history, COLOR_PAIR(3)); + } + } + } + + ctx->line[0] = '\0'; + ctx->pos = 0; + } +} + +void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) +{ + if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { + wclear(self->window); + wclear(ctx->history); + int x, y; + getmaxyx(self->window, y, x); + (void) x; + wmove(self->window, y - CURS_Y_OFFSET, 0); } - else { - wprintw(ctx->history, "Invalid status.\n"); - return; + else if (!strcmp(cmd, "/help") || !strcmp(cmd, "/h")) + print_help(ctx); + + else if (!strcmp(cmd, "/quit") || !strcmp(cmd, "/exit") || !strcmp(cmd, "/q")) { + endwin(); + exit(0); } - msg = strchr(status, ' '); - if (msg == NULL) { - m_set_userstatus(m, status_kind); - wprintw(ctx->history, "Status set to: %s\n", status_text); - } - else { - msg++; - m_set_userstatus(m, status_kind); - m_set_statusmessage(m, ( uint8_t*) msg, strlen(msg)+1); - wprintw(ctx->history, "Status set to: %s, %s\n", status_text, msg); - } - } + else if (!strncmp(cmd, "/me ", strlen("/me "))) { + struct tm *timeinfo = get_time(); + char *action = strchr(cmd, ' '); - else if (!strncmp(cmd, "/nick ", strlen("/nick "))) { - char *nick; - nick = strchr(cmd, ' '); - if (nick == NULL) { - wprintw(ctx->history, "Invalid syntax.\n"); - return; + if (action == NULL) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + + action++; + + wattron(ctx->history, COLOR_PAIR(2)); + wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); + wattroff(ctx->history, COLOR_PAIR(2)); + + uint8_t selfname[MAX_NAME_LENGTH]; + int len = getself_name(m, selfname, sizeof(selfname)); + char msg[MAX_STR_SIZE - len - 4]; + snprintf(msg, sizeof(msg), "* %s %s\n", (uint8_t *) selfname, action); + + wattron(ctx->history, COLOR_PAIR(5)); + wprintw(ctx->history, msg); + wattroff(ctx->history, COLOR_PAIR(5)); + + if (m_sendaction(m, ctx->friendnum, (uint8_t *) msg, strlen(msg) + 1) < 0) { + wattron(ctx->history, COLOR_PAIR(3)); + wprintw(ctx->history, " * Failed to send action\n"); + wattroff(ctx->history, COLOR_PAIR(3)); + } } - nick++; - setname(m, (uint8_t*) nick, strlen(nick)+1); - wprintw(ctx->history, "Nickname set to: %s\n", nick); - } + else if (!strncmp(cmd, "/status ", strlen("/status "))) { + char *status = strchr(cmd, ' '); + char *msg; + char *status_text; - else if (!strcmp(cmd, "/myid")) { - char id[FRIEND_ADDRESS_SIZE*2+1] = {0}; - int i; - uint8_t address[FRIEND_ADDRESS_SIZE]; - getaddress(m, address); - for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) { - char xx[3]; - snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); - strcat(id, xx); + if (status == NULL) { + wprintw(ctx->history, "Invalid syntax.\n"); + return; + } + + status++; + USERSTATUS status_kind; + + if (!strncmp(status, "online", strlen("online"))) { + status_kind = USERSTATUS_NONE; + status_text = "ONLINE"; + } + + else if (!strncmp(status, "away", strlen("away"))) { + status_kind = USERSTATUS_AWAY; + status_text = "AWAY"; + } + + else if (!strncmp(status, "busy", strlen("busy"))) { + status_kind = USERSTATUS_BUSY; + status_text = "BUSY"; + } + + else { + wprintw(ctx->history, "Invalid status.\n"); + return; + } + + msg = strchr(status, ' '); + + if (msg == NULL) { + m_set_userstatus(m, status_kind); + wprintw(ctx->history, "Status set to: %s\n", status_text); + } else { + msg++; + m_set_userstatus(m, status_kind); + m_set_statusmessage(m, ( uint8_t *) msg, strlen(msg) + 1); + wprintw(ctx->history, "Status set to: %s, %s\n", status_text, msg); + } } - wprintw(ctx->history, "%s\n", id); - } - else if (strcmp(ctx->line, "/close") == 0) { - int f_num = ctx->friendnum; - delwin(ctx->linewin); - del_window(self, f_num); - } + else if (!strncmp(cmd, "/nick ", strlen("/nick "))) { + char *nick; + nick = strchr(cmd, ' '); - else - wprintw(ctx->history, "Invalid command.\n"); + if (nick == NULL) { + wprintw(ctx->history, "Invalid syntax.\n"); + return; + } + + nick++; + setname(m, (uint8_t *) nick, strlen(nick) + 1); + wprintw(ctx->history, "Nickname set to: %s\n", nick); + } + + else if (!strcmp(cmd, "/myid")) { + char id[FRIEND_ADDRESS_SIZE * 2 + 1] = {0}; + int i; + uint8_t address[FRIEND_ADDRESS_SIZE]; + getaddress(m, address); + + for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) { + char xx[3]; + snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); + strcat(id, xx); + } + + wprintw(ctx->history, "%s\n", id); + } + + else if (strcmp(ctx->line, "/close") == 0) { + int f_num = ctx->friendnum; + delwin(ctx->linewin); + del_window(self, f_num); + } + + else + wprintw(ctx->history, "Invalid command.\n"); } static void chat_onDraw(ToxWindow *self) { - curs_set(1); - int x, y; - getmaxyx(self->window, y, x); - (void) y; - ChatContext *ctx = (ChatContext*) self->x; - mvwhline(ctx->linewin, 0, 0, '_', x); - wrefresh(self->window); + curs_set(1); + int x, y; + getmaxyx(self->window, y, x); + (void) y; + ChatContext *ctx = (ChatContext *) self->x; + mvwhline(ctx->linewin, 0, 0, '_', x); + wrefresh(self->window); } static void chat_onInit(ToxWindow *self, Messenger *m) { - int x, y; - ChatContext *ctx = (ChatContext*) self->x; - getmaxyx(self->window, y, x); - ctx->history = subwin(self->window, y-4, x, 0, 0); - scrollok(ctx->history, 1); - ctx->linewin = subwin(self->window, 2, x, y-4, 0); - print_help(ctx); - wmove(self->window, y-CURS_Y_OFFSET, 0); + int x, y; + ChatContext *ctx = (ChatContext *) self->x; + getmaxyx(self->window, y, x); + ctx->history = subwin(self->window, y - 4, x, 0, 0); + scrollok(ctx->history, 1); + ctx->linewin = subwin(self->window, 2, x, y - 4, 0); + print_help(ctx); + wmove(self->window, y - CURS_Y_OFFSET, 0); } void print_help(ChatContext *self) { - wattron(self->history, COLOR_PAIR(2) | A_BOLD); - wprintw(self->history, "Commands:\n"); - wattroff(self->history, A_BOLD); + wattron(self->history, COLOR_PAIR(2) | A_BOLD); + wprintw(self->history, "Commands:\n"); + wattroff(self->history, A_BOLD); - wprintw(self->history, " /status : Set your status\n"); - wprintw(self->history, " /nick : Set your nickname\n"); - wprintw(self->history, " /me : Do an action\n"); - wprintw(self->history, " /myid : Print your ID\n"); - wprintw(self->history, " /clear : Clear the screen\n"); - wprintw(self->history, " /close : Close the current chat window\n"); - wprintw(self->history, " /quit or /exit : Exit program\n"); - wprintw(self->history, " /help : Print this message again\n\n"); + wprintw(self->history, " /status : Set your status\n"); + wprintw(self->history, " /nick : Set your nickname\n"); + wprintw(self->history, " /me : Do an action\n"); + wprintw(self->history, " /myid : Print your ID\n"); + wprintw(self->history, " /clear : Clear the screen\n"); + wprintw(self->history, " /close : Close the current chat window\n"); + wprintw(self->history, " /quit or /exit : Exit program\n"); + wprintw(self->history, " /help : Print this message again\n\n"); - wattroff(self->history, COLOR_PAIR(2)); + wattroff(self->history, COLOR_PAIR(2)); } ToxWindow new_chat(Messenger *m, int friendnum) { - ToxWindow ret; - memset(&ret, 0, sizeof(ret)); + ToxWindow ret; + memset(&ret, 0, sizeof(ret)); - ret.onKey = &chat_onKey; - ret.onDraw = &chat_onDraw; - ret.onInit = &chat_onInit; - ret.onMessage = &chat_onMessage; - ret.onNickChange = &chat_onNickChange; - ret.onStatusChange = &chat_onStatusChange; - ret.onAction = &chat_onAction; + ret.onKey = &chat_onKey; + ret.onDraw = &chat_onDraw; + ret.onInit = &chat_onInit; + ret.onMessage = &chat_onMessage; + ret.onNickChange = &chat_onNickChange; + ret.onStatusChange = &chat_onStatusChange; + ret.onAction = &chat_onAction; - uint8_t nick[MAX_NAME_LENGTH] = {0}; - getname(m, friendnum, (uint8_t*) &nick); - fix_name(nick); + uint8_t nick[MAX_NAME_LENGTH] = {0}; + getname(m, friendnum, (uint8_t *) &nick); + fix_name(nick); - snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum); + snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum); - ChatContext *x = calloc(1, sizeof(ChatContext)); - x->friendnum = friendnum; - ret.x = (void*) x; - return ret; + ChatContext *x = calloc(1, sizeof(ChatContext)); + x->friendnum = friendnum; + ret.x = (void *) x; + return ret; } diff --git a/configdir.c b/configdir.c index 18e211c..1a62e8e 100644 --- a/configdir.c +++ b/configdir.c @@ -50,6 +50,7 @@ char *get_user_config_dir(void) BOOL ok; ok = SHGetSpecialFolderPathA(NULL, appdata, CSIDL_PROFILE, TRUE); + if (!ok) { return NULL; } @@ -72,13 +73,16 @@ char *get_user_config_dir(void) int rc; rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf); + if (rc == 0) { home = pwd.pw_dir; } else { home = getenv("HOME"); + if (home == NULL) { return NULL; } + /* env variables can be tainted */ snprintf(buf, sizeof(buf), "%s", home); home = buf; @@ -87,6 +91,7 @@ char *get_user_config_dir(void) # if defined(__APPLE__) len = strlen(home) + strlen("/Library/Application Support") + 1; user_config_dir = malloc(len); + if (user_config_dir == NULL) { return NULL; } @@ -95,6 +100,7 @@ char *get_user_config_dir(void) # else /* __APPLE__ */ len = strlen(home) + strlen("/.config") + 1; user_config_dir = malloc(len); + if (user_config_dir == NULL) { return NULL; } @@ -111,44 +117,45 @@ char *get_user_config_dir(void) * Creates the config directory. */ int create_user_config_dir(char *path) -{ +{ - int mkdir_err; + int mkdir_err; - #ifdef WIN32 +#ifdef WIN32 - char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1); - strcpy(fullpath, path); - strcat(fullpath, CONFIGDIR); + char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1); + strcpy(fullpath, path); + strcat(fullpath, CONFIGDIR); - mkdir_err = _mkdir(fullpath); - struct __stat64 buf; - if (mkdir_err && (errno != EEXIST || _wstat64(fullpath, &buf) || !S_ISDIR(buf.st_mode))) { + mkdir_err = _mkdir(fullpath); + struct __stat64 buf; + + if (mkdir_err && (errno != EEXIST || _wstat64(fullpath, &buf) || !S_ISDIR(buf.st_mode))) { + free(fullpath); + return -1; + } + +#else + + mkdir_err = mkdir(path, 0700); + struct stat buf; + + if (mkdir_err && (errno != EEXIST || stat(path, &buf) || !S_ISDIR(buf.st_mode))) { + return -1; + } + + char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1); + strcpy(fullpath, path); + strcat(fullpath, CONFIGDIR); + + mkdir_err = mkdir(fullpath, 0700); + + if (mkdir_err && (errno != EEXIST || stat(fullpath, &buf) || !S_ISDIR(buf.st_mode))) { + free(fullpath); + return -1; + } + +#endif free(fullpath); - return -1; - } - - #else - - mkdir_err = mkdir(path, 0700); - struct stat buf; - - if(mkdir_err && (errno != EEXIST || stat(path, &buf) || !S_ISDIR(buf.st_mode))) { - return -1; - } - - char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1); - strcpy(fullpath, path); - strcat(fullpath, CONFIGDIR); - - mkdir_err = mkdir(fullpath, 0700); - - if(mkdir_err && (errno != EEXIST || stat(fullpath, &buf) || !S_ISDIR(buf.st_mode))) { - free(fullpath); - return -1; - } - - #endif - free(fullpath); - return 0; + return 0; } diff --git a/configdir.h b/configdir.h index fad949c..17d9510 100644 --- a/configdir.h +++ b/configdir.h @@ -23,7 +23,7 @@ #else #define CONFIGDIR "/toxic/" #endif - + #ifndef S_ISDIR #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #endif diff --git a/dhtstatus.c b/dhtstatus.c index e026a17..a11dc61 100644 --- a/dhtstatus.c +++ b/dhtstatus.c @@ -3,87 +3,97 @@ #include "../../core/network.h" #include "../../core/DHT.h" -typedef uint8_t ipbuf[3*4+3+1]; +typedef uint8_t ipbuf[3 * 4 + 3 + 1]; static int num_selected = 0; -static void printip(ipbuf buf, IP ip) +static void printip(ipbuf buf, IP ip) { - sprintf((char*)buf, "%u.%u.%u.%u", ip.c[0], ip.c[1], ip.c[2], ip.c[3]); + sprintf((char *)buf, "%u.%u.%u.%u", ip.c[0], ip.c[1], ip.c[2], ip.c[3]); } static void dhtstatus_onKey(ToxWindow *self, Messenger *m, int key) { - switch(key) { - case KEY_UP: - case 'k': - if (--num_selected < 0) - num_selected = CLIENT_ID_SIZE-1; - break; - - case KEY_DOWN: - case 'j': - num_selected = (num_selected+1) % CLIENT_ID_SIZE; - break; - - case '\n': - break; - - default: - break; - } + switch (key) { + case KEY_UP: + case 'k': + if (--num_selected < 0) + num_selected = CLIENT_ID_SIZE - 1; + + break; + + case KEY_DOWN: + case 'j': + num_selected = (num_selected + 1) % CLIENT_ID_SIZE; + break; + + case '\n': + break; + + default: + break; + } } static void dhtstatus_onDraw(ToxWindow *self) { - Client_data * close_clientlist = DHT_get_close_list(); - curs_set(0); - werase(self->window); - - uint64_t now = unix_time(); - uint32_t i, j; - ipbuf ipbuf; - wprintw(self->window,"\n%llu ______________________ CLOSE LIST ________________________ ___ IP ADDR ___ _PRT_ LST PNG ____ SELF ____ _PRT_ LST\n\n", now); - for(i = 0; i < 32; i++) { /*Number of nodes in closelist*/ - Client_data * client = close_clientlist + i; - if (i == num_selected) wattron(self->window, COLOR_PAIR(3)); - wprintw(self->window,"[%02i] ", i); - uint16_t port = ntohs(client->ip_port.port); - if(port) { - for(j = 0; j < CLIENT_ID_SIZE; j++) - wprintw(self->window, "%02hhx", client->client_id[j]); - - printip(ipbuf, client->ip_port.ip); - wprintw(self->window, " %15s %5u ", ipbuf, port); - wprintw(self->window, " %3llu ", now - client->timestamp); - wprintw(self->window, " %3llu ", now - client->last_pinged); - - port = ntohs(client->ret_ip_port.port); - if(port) { - printip(ipbuf, client->ret_ip_port.ip); - wprintw(self->window, " %15s %5u %3llu", ipbuf, port, now - close_clientlist[i].ret_timestamp); - } + Client_data *close_clientlist = DHT_get_close_list(); + curs_set(0); + werase(self->window); + + uint64_t now = unix_time(); + uint32_t i, j; + ipbuf ipbuf; + wprintw(self->window, + "\n%llu ______________________ CLOSE LIST ________________________ ___ IP ADDR ___ _PRT_ LST PNG ____ SELF ____ _PRT_ LST\n\n", + now); + + for (i = 0; i < 32; i++) { /*Number of nodes in closelist*/ + Client_data *client = close_clientlist + i; + + if (i == num_selected) wattron(self->window, COLOR_PAIR(3)); + + wprintw(self->window, "[%02i] ", i); + uint16_t port = ntohs(client->ip_port.port); + + if (port) { + for (j = 0; j < CLIENT_ID_SIZE; j++) + wprintw(self->window, "%02hhx", client->client_id[j]); + + printip(ipbuf, client->ip_port.ip); + wprintw(self->window, " %15s %5u ", ipbuf, port); + wprintw(self->window, " %3llu ", now - client->timestamp); + wprintw(self->window, " %3llu ", now - client->last_pinged); + + port = ntohs(client->ret_ip_port.port); + + if (port) { + printip(ipbuf, client->ret_ip_port.ip); + wprintw(self->window, " %15s %5u %3llu", ipbuf, port, now - close_clientlist[i].ret_timestamp); + } + } + + wprintw(self->window, "\n"); + + if (i == num_selected) wattroff(self->window, COLOR_PAIR(3)); } - wprintw(self->window, "\n"); - if (i == num_selected) wattroff(self->window, COLOR_PAIR(3)); - } - - wrefresh(self->window); + + wrefresh(self->window); } static void dhtstatus_onInit(ToxWindow *self, Messenger *m) { } - -ToxWindow new_dhtstatus() + +ToxWindow new_dhtstatus() { - ToxWindow ret; - memset(&ret, 0, sizeof(ret)); + ToxWindow ret; + memset(&ret, 0, sizeof(ret)); - ret.onKey = &dhtstatus_onKey; - ret.onDraw = &dhtstatus_onDraw; - ret.onInit = &dhtstatus_onInit; + ret.onKey = &dhtstatus_onKey; + ret.onDraw = &dhtstatus_onDraw; + ret.onInit = &dhtstatus_onInit; - strcpy(ret.title, "[dht status]"); - return ret; + strcpy(ret.title, "[dht status]"); + return ret; } diff --git a/friendlist.c b/friendlist.c index e7504fb..c85fd3a 100644 --- a/friendlist.c +++ b/friendlist.c @@ -13,13 +13,13 @@ #include "windows.h" #include "friendlist.h" -static char * WINDOW_STATUS; +static char *WINDOW_STATUS; typedef struct { - uint8_t name[MAX_NAME_LENGTH]; - uint8_t status[MAX_STATUSMESSAGE_LENGTH]; - int num; - int chatwin; + uint8_t name[MAX_NAME_LENGTH]; + uint8_t status[MAX_STATUSMESSAGE_LENGTH]; + int num; + int chatwin; } friend_t; static friend_t friends[MAX_FRIENDS_NUM]; @@ -28,135 +28,143 @@ static int num_selected = 0; void fix_name(uint8_t *name) { - /* Remove all non alphanumeric characters */ - uint8_t *p = name; - uint8_t *q = name; - while(*p != 0) { - if (isprint(*p)) - *q++ = *p; - p++; - } - *q = 0; + /* Remove all non alphanumeric characters */ + uint8_t *p = name; + uint8_t *q = name; + + while (*p != 0) { + if (isprint(*p)) + *q++ = *p; + + p++; + } + + *q = 0; } void friendlist_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *str, uint16_t len) { - if (num >= num_friends) - return; + if (num >= num_friends) + return; - if (friends[num].chatwin == -1) { - friends[num].chatwin = num; - int i; - /* Find first open slot to hold chat window */ - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { - if (WINDOW_STATUS[i] == -1) { - WINDOW_STATUS[i] = num; - add_window(m, new_chat(m, num), i); - break; - } + if (friends[num].chatwin == -1) { + friends[num].chatwin = num; + int i; + + /* Find first open slot to hold chat window */ + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { + if (WINDOW_STATUS[i] == -1) { + WINDOW_STATUS[i] = num; + add_window(m, new_chat(m, num), i); + break; + } + } } - } } void friendlist_onNickChange(ToxWindow *self, int num, uint8_t *str, uint16_t len) { - if (len >= MAX_NAME_LENGTH || num >= num_friends) - return; + if (len >= MAX_NAME_LENGTH || num >= num_friends) + return; - memcpy((char*) &friends[num].name, (char*) str, len); - friends[num].name[len] = 0; - fix_name(friends[num].name); + memcpy((char *) &friends[num].name, (char *) str, len); + friends[num].name[len] = 0; + fix_name(friends[num].name); } void friendlist_onStatusChange(ToxWindow *self, int num, uint8_t *str, uint16_t len) { - if (len >= MAX_STATUSMESSAGE_LENGTH || num >= num_friends) - return; + if (len >= MAX_STATUSMESSAGE_LENGTH || num >= num_friends) + return; - memcpy((char*) &friends[num].status, (char*) str, len); - friends[num].status[len] = 0; - fix_name(friends[num].status); + memcpy((char *) &friends[num].status, (char *) str, len); + friends[num].status[len] = 0; + fix_name(friends[num].status); } int friendlist_onFriendAdded(Messenger *m, int num) { - if (num_friends == MAX_FRIENDS_NUM) - return -1; + if (num_friends == MAX_FRIENDS_NUM) + return -1; - friends[num_friends].num = num; - getname(m, num, friends[num_friends].name); - strcpy((char*) friends[num_friends].name, "unknown"); - strcpy((char*) friends[num_friends].status, "unknown"); - friends[num_friends++].chatwin = -1; - return 0; + friends[num_friends].num = num; + getname(m, num, friends[num_friends].name); + strcpy((char *) friends[num_friends].name, "unknown"); + strcpy((char *) friends[num_friends].status, "unknown"); + friends[num_friends++].chatwin = -1; + return 0; } static void friendlist_onKey(ToxWindow *self, Messenger *m, int key) { - if (key == KEY_UP) { - if (--num_selected < 0) - num_selected = num_friends-1; - } - else if (key == KEY_DOWN) { - if (num_friends != 0) - num_selected = (num_selected+1) % num_friends; - } - else if (key == '\n') { - /* Jump to chat window if already open */ - if (friends[num_selected].chatwin != -1) { - int i; - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { - if (WINDOW_STATUS[i] == num_selected) { - set_active_window(i); - break; + if (key == KEY_UP) { + if (--num_selected < 0) + num_selected = num_friends - 1; + } else if (key == KEY_DOWN) { + if (num_friends != 0) + num_selected = (num_selected + 1) % num_friends; + } else if (key == '\n') { + /* Jump to chat window if already open */ + if (friends[num_selected].chatwin != -1) { + int i; + + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { + if (WINDOW_STATUS[i] == num_selected) { + set_active_window(i); + break; + } + } + } else { + int i; + + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { + if (WINDOW_STATUS[i] == -1) { + WINDOW_STATUS[i] = num_selected; + friends[num_selected].chatwin = num_selected; + add_window(m, new_chat(m, num_selected), i); + break; + } + } } - } - }else { - int i; - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { - if (WINDOW_STATUS[i] == -1) { - WINDOW_STATUS[i] = num_selected; - friends[num_selected].chatwin = num_selected; - add_window(m, new_chat(m, num_selected), i); - break; - } - } } - } } static void friendlist_onDraw(ToxWindow *self) { - curs_set(0); - werase(self->window); - if (num_friends == 0) { - wprintw(self->window, "Empty. Add some friends! :-)\n"); - } - else { - wattron(self->window, COLOR_PAIR(2) | A_BOLD); - wprintw(self->window, "Open chat with.. (up/down keys, enter)\n"); - wattroff(self->window, COLOR_PAIR(2) | A_BOLD); - } + curs_set(0); + werase(self->window); - wprintw(self->window, "\n"); - int i; - for (i = 0; i < num_friends; ++i) { - if (i == num_selected) wattron(self->window, COLOR_PAIR(3)); - wprintw(self->window, " [#%d] ", friends[i].num); - if (i == num_selected) wattroff(self->window, COLOR_PAIR(3)); + if (num_friends == 0) { + wprintw(self->window, "Empty. Add some friends! :-)\n"); + } else { + wattron(self->window, COLOR_PAIR(2) | A_BOLD); + wprintw(self->window, "Open chat with.. (up/down keys, enter)\n"); + wattroff(self->window, COLOR_PAIR(2) | A_BOLD); + } - attron(A_BOLD); - wprintw(self->window, "%s ", friends[i].name); - attroff(A_BOLD); + wprintw(self->window, "\n"); + int i; - wprintw(self->window, "(%s)\n", friends[i].status); - } - wrefresh(self->window); + for (i = 0; i < num_friends; ++i) { + if (i == num_selected) wattron(self->window, COLOR_PAIR(3)); + + wprintw(self->window, " [#%d] ", friends[i].num); + + if (i == num_selected) wattroff(self->window, COLOR_PAIR(3)); + + attron(A_BOLD); + wprintw(self->window, "%s ", friends[i].name); + attroff(A_BOLD); + + wprintw(self->window, "(%s)\n", friends[i].status); + } + + wrefresh(self->window); } void disable_chatwin(int f_num) { - friends[f_num].chatwin = -1; + friends[f_num].chatwin = -1; } static void friendlist_onInit(ToxWindow *self, Messenger *m) @@ -164,19 +172,20 @@ static void friendlist_onInit(ToxWindow *self, Messenger *m) } -ToxWindow new_friendlist(char * ws) { - WINDOW_STATUS = ws; - ToxWindow ret; - memset(&ret, 0, sizeof(ret)); +ToxWindow new_friendlist(char *ws) +{ + WINDOW_STATUS = ws; + ToxWindow ret; + memset(&ret, 0, sizeof(ret)); - ret.onKey = &friendlist_onKey; - ret.onDraw = &friendlist_onDraw; - ret.onInit = &friendlist_onInit; - ret.onMessage = &friendlist_onMessage; - ret.onAction = &friendlist_onMessage; // Action has identical behaviour to message - ret.onNickChange = &friendlist_onNickChange; - ret.onStatusChange = &friendlist_onStatusChange; + ret.onKey = &friendlist_onKey; + ret.onDraw = &friendlist_onDraw; + ret.onInit = &friendlist_onInit; + ret.onMessage = &friendlist_onMessage; + ret.onAction = &friendlist_onMessage; // Action has identical behaviour to message + ret.onNickChange = &friendlist_onNickChange; + ret.onStatusChange = &friendlist_onStatusChange; - strcpy(ret.title, "[friends]"); - return ret; + strcpy(ret.title, "[friends]"); + return ret; } diff --git a/friendlist.h b/friendlist.h index c3d8dac..f0c27f5 100644 --- a/friendlist.h +++ b/friendlist.h @@ -4,7 +4,7 @@ #include "windows.h" #include "chat.h" -ToxWindow new_friendlist(char * ws); +ToxWindow new_friendlist(char *ws); int friendlist_onFriendAdded(Messenger *m, int num); void disable_chatwin(int f_num); void fix_name(uint8_t *name); diff --git a/main.c b/main.c index 38c20df..816873b 100644 --- a/main.c +++ b/main.c @@ -28,7 +28,7 @@ /* Export for use in Callbacks */ char *DATA_FILE = NULL; -void on_window_resize(int sig) +void on_window_resize(int sig) { endwin(); refresh(); @@ -37,44 +37,45 @@ void on_window_resize(int sig) static void init_term() { - /* Setup terminal */ - signal(SIGWINCH, on_window_resize); - initscr(); - cbreak(); - keypad(stdscr, 1); - noecho(); - timeout(100); + /* Setup terminal */ + signal(SIGWINCH, on_window_resize); + initscr(); + cbreak(); + keypad(stdscr, 1); + noecho(); + timeout(100); - if (has_colors()) { - start_color(); - init_pair(1, COLOR_GREEN, COLOR_BLACK); - init_pair(2, COLOR_CYAN, COLOR_BLACK); - init_pair(3, COLOR_RED, COLOR_BLACK); - init_pair(4, COLOR_BLUE, COLOR_BLACK); - init_pair(5, COLOR_YELLOW, COLOR_BLACK); - } - refresh(); + if (has_colors()) { + start_color(); + init_pair(1, COLOR_GREEN, COLOR_BLACK); + init_pair(2, COLOR_CYAN, COLOR_BLACK); + init_pair(3, COLOR_RED, COLOR_BLACK); + init_pair(4, COLOR_BLUE, COLOR_BLACK); + init_pair(5, COLOR_YELLOW, COLOR_BLACK); + } + + refresh(); } static Messenger *init_tox() { - /* Init core */ - Messenger *m = initMessenger(); + /* Init core */ + Messenger *m = initMessenger(); - /* Callbacks */ - m_callback_friendrequest(m, on_request, NULL); - m_callback_friendmessage(m, on_message, NULL); - m_callback_namechange(m, on_nickchange, NULL); - m_callback_statusmessage(m, on_statuschange, NULL); - m_callback_action(m, on_action, NULL); + /* Callbacks */ + m_callback_friendrequest(m, on_request, NULL); + m_callback_friendmessage(m, on_message, NULL); + m_callback_namechange(m, on_nickchange, NULL); + m_callback_statusmessage(m, on_statuschange, NULL); + m_callback_action(m, on_action, NULL); #ifdef __linux__ - setname(m, (uint8_t*) "Cool guy", sizeof("Cool guy")); + setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy")); #elif WIN32 - setname(m, (uint8_t*) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); + setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); #else - setname(m, (uint8_t*) "Hipster", sizeof("Hipster")); + setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); #endif - return m; + return m; } #define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */ @@ -84,67 +85,75 @@ static Messenger *init_tox() /* Connects to a random DHT server listed in the DHTservers file */ int init_connection(void) { - if (DHT_isconnected()) - return 0; + if (DHT_isconnected()) + return 0; - FILE *fp = fopen("../../../other/DHTservers", "r"); - if (!fp) - return 1; + FILE *fp = fopen("../../../other/DHTservers", "r"); + + if (!fp) + return 1; + + char servers[MAXSERVERS][MAXLINE]; + char line[MAXLINE]; + int linecnt = 0; + + while (fgets(line, sizeof(line), fp) && linecnt < MAXSERVERS) { + if (strlen(line) > MINLINE) + strcpy(servers[linecnt++], line); + } + + if (linecnt < 1) { + fclose(fp); + return 2; + } - char servers[MAXSERVERS][MAXLINE]; - char line[MAXLINE]; - int linecnt = 0; - while (fgets(line, sizeof(line), fp) && linecnt < MAXSERVERS) { - if (strlen(line) > MINLINE) - strcpy(servers[linecnt++], line); - } - if (linecnt < 1) { fclose(fp); - return 2; - } - fclose(fp); - char *server = servers[rand() % linecnt]; - char *ip = strtok(server, " "); - char *port = strtok(NULL, " "); - char *key = strtok(NULL, " "); - if (!ip || !port || !key) - return 3; + char *server = servers[rand() % linecnt]; + char *ip = strtok(server, " "); + char *port = strtok(NULL, " "); + char *key = strtok(NULL, " "); - IP_Port dht; - dht.port = htons(atoi(port)); - uint32_t resolved_address = resolve_addr(ip); - if (resolved_address == 0) + if (!ip || !port || !key) + return 3; + + IP_Port dht; + dht.port = htons(atoi(port)); + uint32_t resolved_address = resolve_addr(ip); + + if (resolved_address == 0) + return 0; + + dht.ip.i = resolved_address; + unsigned char *binary_string = hex_string_to_bin(key); + DHT_bootstrap(dht, binary_string); + free(binary_string); return 0; - dht.ip.i = resolved_address; - unsigned char *binary_string = hex_string_to_bin(key); - DHT_bootstrap(dht, binary_string); - free(binary_string); - return 0; } -static void do_tox(Messenger *m, ToxWindow * prompt) +static void do_tox(Messenger *m, ToxWindow *prompt) { - static int conn_try = 0; - static int conn_err = 0; - static bool dht_on = false; - if (!dht_on && !DHT_isconnected() && !(conn_try++ % 100)) { - if (!conn_err) { - conn_err = init_connection(); - wprintw(prompt->window, "\nEstablishing connection...\n"); - if (conn_err) - wprintw(prompt->window, "\nAuto-connect failed with error code %d\n", conn_err); + static int conn_try = 0; + static int conn_err = 0; + static bool dht_on = false; + + if (!dht_on && !DHT_isconnected() && !(conn_try++ % 100)) { + if (!conn_err) { + conn_err = init_connection(); + wprintw(prompt->window, "\nEstablishing connection...\n"); + + if (conn_err) + wprintw(prompt->window, "\nAuto-connect failed with error code %d\n", conn_err); + } + } else if (!dht_on && DHT_isconnected()) { + dht_on = true; + wprintw(prompt->window, "\nDHT connected.\n"); + } else if (dht_on && !DHT_isconnected()) { + dht_on = false; + wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n"); } - } - else if (!dht_on && DHT_isconnected()) { - dht_on = true; - wprintw(prompt->window, "\nDHT connected.\n"); - } - else if (dht_on && !DHT_isconnected()) { - dht_on = false; - wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n"); - } - doMessenger(m); + + doMessenger(m); } int f_loadfromfile; @@ -160,18 +169,22 @@ int store_data(Messenger *m, char *path) { if (f_loadfromfile == 0) /*If file loading/saving is disabled*/ return 0; + FILE *fd; size_t len; uint8_t *buf; len = Messenger_size(m); buf = malloc(len); + if (buf == NULL) { return 1; } + Messenger_save(m, buf); fd = fopen(path, "w"); + if (fd == NULL) { free(buf); return 2; @@ -192,6 +205,7 @@ static void load_data(Messenger *m, char *path) { if (f_loadfromfile == 0) /*If file loading/saving is disabled*/ return; + FILE *fd; size_t len; uint8_t *buf; @@ -202,12 +216,14 @@ static void load_data(Messenger *m, char *path) fseek(fd, 0, SEEK_SET); buf = malloc(len); + if (buf == NULL) { fprintf(stderr, "malloc() failed.\n"); fclose(fd); endwin(); exit(1); } + if (fread(buf, len, 1, fd) != 1) { fprintf(stderr, "fread() failed.\n"); free(buf); @@ -215,9 +231,11 @@ static void load_data(Messenger *m, char *path) endwin(); exit(1); } + Messenger_load(m, buf, len); uint32_t i; + for (i = 0; i < m->numfriends; i++) { on_friendadded(m, i); } @@ -226,6 +244,7 @@ static void load_data(Messenger *m, char *path) fclose(fd); } else { int st; + if ((st = store_data(m, path)) != 0) { fprintf(stderr, "Store messenger failed with return code: %d\n", st); endwin(); @@ -236,70 +255,74 @@ static void load_data(Messenger *m, char *path) int main(int argc, char *argv[]) { - char *user_config_dir = get_user_config_dir(); - int config_err = 0; + char *user_config_dir = get_user_config_dir(); + int config_err = 0; - f_loadfromfile = 1; - int f_flag = 0; - int i = 0; - for (i = 0; i < argc; ++i) { - if (argv[i] == NULL) - break; - else if (argv[i][0] == '-') { - if (argv[i][1] == 'f') { - if (argv[i + 1] != NULL) - DATA_FILE = strdup(argv[i + 1]); - else - f_flag = -1; - } else if (argv[i][1] == 'n') { - f_loadfromfile = 0; - } + f_loadfromfile = 1; + int f_flag = 0; + int i = 0; + + for (i = 0; i < argc; ++i) { + if (argv[i] == NULL) + break; + else if (argv[i][0] == '-') { + if (argv[i][1] == 'f') { + if (argv[i + 1] != NULL) + DATA_FILE = strdup(argv[i + 1]); + else + f_flag = -1; + } else if (argv[i][1] == 'n') { + f_loadfromfile = 0; + } + } + } + + if (DATA_FILE == NULL ) { + config_err = create_user_config_dir(user_config_dir); + + if (config_err) { + DATA_FILE = strdup("data"); + } else { + DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); + strcpy(DATA_FILE, user_config_dir); + strcat(DATA_FILE, CONFIGDIR); + strcat(DATA_FILE, "data"); + } + } + + free(user_config_dir); + + init_term(); + Messenger *m = init_tox(); + ToxWindow *prompt = init_windows(m); + init_window_status(); + + if (f_loadfromfile) + load_data(m, DATA_FILE); + + if (f_flag == -1) { + attron(COLOR_PAIR(3) | A_BOLD); + wprintw(prompt->window, "You passed '-f' without giving an argument.\n" + "defaulting to 'data' for a keyfile...\n"); + attroff(COLOR_PAIR(3) | A_BOLD); } - } - if (DATA_FILE == NULL ) { - config_err = create_user_config_dir(user_config_dir); if (config_err) { - DATA_FILE = strdup("data"); - } else { - DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); - strcpy(DATA_FILE, user_config_dir); - strcat(DATA_FILE, CONFIGDIR); - strcat(DATA_FILE, "data"); + attron(COLOR_PAIR(3) | A_BOLD); + wprintw(prompt->window, "Unable to determine configuration directory.\n" + "defaulting to 'data' for a keyfile...\n"); + attroff(COLOR_PAIR(3) | A_BOLD); } - } - free(user_config_dir); - init_term(); - Messenger *m = init_tox(); - ToxWindow *prompt = init_windows(m); - init_window_status(); + while (true) { + /* Update tox */ + do_tox(m, prompt); - if(f_loadfromfile) - load_data(m, DATA_FILE); + /* Draw */ + draw_active_window(m); + } - if (f_flag == -1) { - attron(COLOR_PAIR(3) | A_BOLD); - wprintw(prompt->window, "You passed '-f' without giving an argument.\n" - "defaulting to 'data' for a keyfile...\n"); - attroff(COLOR_PAIR(3) | A_BOLD); - } - - if(config_err) { - attron(COLOR_PAIR(3) | A_BOLD); - wprintw(prompt->window, "Unable to determine configuration directory.\n" - "defaulting to 'data' for a keyfile...\n"); - attroff(COLOR_PAIR(3) | A_BOLD); - } - while(true) { - /* Update tox */ - do_tox(m, prompt); - - /* Draw */ - draw_active_window(m); - } - - cleanupMessenger(m); - free(DATA_FILE); - return 0; + cleanupMessenger(m); + free(DATA_FILE); + return 0; } diff --git a/prompt.c b/prompt.c index 1d0e014..f6d3e21 100644 --- a/prompt.c +++ b/prompt.c @@ -14,7 +14,7 @@ #include "prompt.h" uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX -uint8_t num_requests=0; // XXX +uint8_t num_requests = 0; // XXX static friendAddedFn *on_friendadded_cb; static char prompt_buf[MAX_STR_SIZE] = {0}; @@ -36,412 +36,441 @@ void cmd_statusmsg(ToxWindow *, Messenger *m, char **); #define NUM_COMMANDS 13 static struct { - char *name; - int numargs; - void (*func)(ToxWindow *, Messenger *m, char **); + char *name; + int numargs; + void (*func)(ToxWindow *, Messenger *m, char **); } commands[] = { - { "accept", 1, cmd_accept }, - { "add", 1, cmd_add }, - { "clear", 0, cmd_clear }, - { "connect", 3, cmd_connect }, - { "exit", 0, cmd_quit }, - { "help", 0, cmd_help }, - { "msg", 2, cmd_msg }, - { "myid", 0, cmd_myid }, - { "nick", 1, cmd_nick }, - { "q", 0, cmd_quit }, - { "quit", 0, cmd_quit }, - { "status", 2, cmd_status }, - { "statusmsg", 1, cmd_statusmsg }, + { "accept", 1, cmd_accept }, + { "add", 1, cmd_add }, + { "clear", 0, cmd_clear }, + { "connect", 3, cmd_connect }, + { "exit", 0, cmd_quit }, + { "help", 0, cmd_help }, + { "msg", 2, cmd_msg }, + { "myid", 0, cmd_myid }, + { "nick", 1, cmd_nick }, + { "q", 0, cmd_quit }, + { "quit", 0, cmd_quit }, + { "status", 2, cmd_status }, + { "statusmsg", 1, cmd_statusmsg }, }; // XXX: int add_req(uint8_t *public_key) { - memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE); - ++num_requests; - return num_requests-1; + memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE); + ++num_requests; + return num_requests - 1; } // XXX: FIX unsigned char *hex_string_to_bin(char hex_string[]) { - size_t len = strlen(hex_string); - unsigned char *val = malloc(len); - char *pos = hex_string; - int i; - for (i = 0; i < len; ++i, pos+=2) - sscanf(pos,"%2hhx",&val[i]); - return val; + size_t len = strlen(hex_string); + unsigned char *val = malloc(len); + char *pos = hex_string; + int i; + + for (i = 0; i < len; ++i, pos += 2) + sscanf(pos, "%2hhx", &val[i]); + + return val; } void cmd_accept(ToxWindow *self, Messenger *m, char **args) { - int num = atoi(args[1]); - if (num >= num_requests) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } + int num = atoi(args[1]); - num = m_addfriend_norequest(m, pending_requests[num]); - if (num == -1) - wprintw(self->window, "Failed to add friend.\n"); - else { - wprintw(self->window, "Friend accepted as: %d.\n", num); - on_friendadded_cb(m, num); - } + if (num >= num_requests) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } + + num = m_addfriend_norequest(m, pending_requests[num]); + + if (num == -1) + wprintw(self->window, "Failed to add friend.\n"); + else { + wprintw(self->window, "Friend accepted as: %d.\n", num); + on_friendadded_cb(m, num); + } } void cmd_add(ToxWindow *self, Messenger *m, char **args) { - uint8_t id_bin[FRIEND_ADDRESS_SIZE]; - char xx[3]; - uint32_t x; - char *id = args[1]; - char *msg = args[2]; + uint8_t id_bin[FRIEND_ADDRESS_SIZE]; + char xx[3]; + uint32_t x; + char *id = args[1]; + char *msg = args[2]; - if (!id) { - wprintw(self->window, "Invalid command: add expected at least one argument.\n"); - return; - } - if (!msg) - msg = ""; - - if (strlen(id) != 2*FRIEND_ADDRESS_SIZE) { - wprintw(self->window, "Invalid ID length.\n"); - return; - } - int i; - for (i = 0; i < 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(self->window, "Invalid ID.\n"); - return; + if (!id) { + wprintw(self->window, "Invalid command: add expected at least one argument.\n"); + return; + } + + if (!msg) + msg = ""; + + if (strlen(id) != 2 * FRIEND_ADDRESS_SIZE) { + wprintw(self->window, "Invalid ID length.\n"); + return; + } + + int i; + + for (i = 0; i < 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(self->window, "Invalid ID.\n"); + return; + } + + id_bin[i] = x; + } + + for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) { + id[i] = toupper(id[i]); + } + + int num = m_addfriend(m, id_bin, (uint8_t *) msg, strlen(msg) + 1); + + switch (num) { + case FAERR_TOOLONG: + wprintw(self->window, "Message is too long.\n"); + break; + + case FAERR_NOMESSAGE: + wprintw(self->window, "Please add a message to your request.\n"); + break; + + case FAERR_OWNKEY: + wprintw(self->window, "That appears to be your own ID.\n"); + break; + + case FAERR_ALREADYSENT: + wprintw(self->window, "Friend request already sent.\n"); + break; + + case FAERR_UNKNOWN: + wprintw(self->window, "Undefined error when adding friend.\n"); + break; + + case FAERR_BADCHECKSUM: + wprintw(self->window, "Bad checksum in address.\n"); + break; + + case FAERR_SETNEWNOSPAM: + wprintw(self->window, "Nospam was different.\n"); + break; + + default: + wprintw(self->window, "Friend added as %d.\n", num); + on_friendadded_cb(m, num); + break; } - id_bin[i] = x; - } - - for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) { - id[i] = toupper(id[i]); - } - - int num = m_addfriend(m, id_bin, (uint8_t*) msg, strlen(msg)+1); - switch (num) { - case FAERR_TOOLONG: - wprintw(self->window, "Message is too long.\n"); - break; - case FAERR_NOMESSAGE: - wprintw(self->window, "Please add a message to your request.\n"); - break; - case FAERR_OWNKEY: - wprintw(self->window, "That appears to be your own ID.\n"); - break; - case FAERR_ALREADYSENT: - wprintw(self->window, "Friend request already sent.\n"); - break; - case FAERR_UNKNOWN: - wprintw(self->window, "Undefined error when adding friend.\n"); - break; - case FAERR_BADCHECKSUM: - wprintw(self->window, "Bad checksum in address.\n"); - break; - case FAERR_SETNEWNOSPAM: - wprintw(self->window, "Nospam was different.\n"); - break; - default: - wprintw(self->window, "Friend added as %d.\n", num); - on_friendadded_cb(m, num); - break; - } } void cmd_clear(ToxWindow *self, Messenger *m, char **args) { - wclear(self->window); + wclear(self->window); } void cmd_connect(ToxWindow *self, Messenger *m, char **args) { - IP_Port dht; - char *ip = args[1]; - char *port = args[2]; - char *key = args[3]; + IP_Port dht; + char *ip = args[1]; + char *port = args[2]; + char *key = args[3]; - if (atoi(port) == 0) { - wprintw(self->window, "Invalid syntax.\n"); - return; - } + if (atoi(port) == 0) { + wprintw(self->window, "Invalid syntax.\n"); + return; + } - dht.port = htons(atoi(port)); - uint32_t resolved_address = resolve_addr(ip); - if (resolved_address == 0) { - return; - } + dht.port = htons(atoi(port)); + uint32_t resolved_address = resolve_addr(ip); - dht.ip.i = resolved_address; - unsigned char *binary_string = hex_string_to_bin(key); - DHT_bootstrap(dht, binary_string); - free(binary_string); + if (resolved_address == 0) { + return; + } + + dht.ip.i = resolved_address; + unsigned char *binary_string = hex_string_to_bin(key); + DHT_bootstrap(dht, binary_string); + free(binary_string); } void cmd_quit(ToxWindow *self, Messenger *m, char **args) { - endwin(); - exit(0); + endwin(); + exit(0); } void cmd_help(ToxWindow *self, Messenger *m, char **args) { - wclear(self->window); - wattron(self->window, COLOR_PAIR(2) | A_BOLD); - wprintw(self->window, "Commands:\n"); - wattroff(self->window, A_BOLD); + wclear(self->window); + wattron(self->window, COLOR_PAIR(2) | A_BOLD); + wprintw(self->window, "Commands:\n"); + wattroff(self->window, A_BOLD); - wprintw(self->window, " connect : Connect to DHT server\n"); - wprintw(self->window, " add : Add friend\n"); - wprintw(self->window, " status : Set your status\n"); - wprintw(self->window, " statusmsg : Set your status\n"); - wprintw(self->window, " nick : Set your nickname\n"); - wprintw(self->window, " accept : Accept friend request\n"); - wprintw(self->window, " myid : Print your ID\n"); - wprintw(self->window, " quit/exit : Exit program\n"); - wprintw(self->window, " help : Print this message again\n"); - wprintw(self->window, " clear : Clear this window\n"); + wprintw(self->window, " connect : Connect to DHT server\n"); + wprintw(self->window, " add : Add friend\n"); + wprintw(self->window, " status : Set your status\n"); + wprintw(self->window, " statusmsg : Set your status\n"); + wprintw(self->window, " nick : Set your nickname\n"); + wprintw(self->window, " accept : Accept friend request\n"); + wprintw(self->window, " myid : Print your ID\n"); + wprintw(self->window, " quit/exit : Exit program\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, "TIP: Use the TAB key to navigate through the tabs.\n\n"); - wattroff(self->window, A_BOLD); + wattron(self->window, A_BOLD); + wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n"); + wattroff(self->window, A_BOLD); - wattroff(self->window, COLOR_PAIR(2)); + wattroff(self->window, COLOR_PAIR(2)); } void cmd_msg(ToxWindow *self, Messenger *m, char **args) { - char *id = args[1]; - char *msg = args[2]; - if (m_sendmessage(m, atoi(id), (uint8_t*) msg, strlen(msg)+1) == 0) - wprintw(self->window, "Error occurred while sending message.\n"); - else - wprintw(self->window, "Message successfully sent.\n"); + char *id = args[1]; + char *msg = args[2]; + + if (m_sendmessage(m, atoi(id), (uint8_t *) msg, strlen(msg) + 1) == 0) + wprintw(self->window, "Error occurred while sending message.\n"); + else + wprintw(self->window, "Message successfully sent.\n"); } void cmd_myid(ToxWindow *self, Messenger *m, char **args) { - char id[FRIEND_ADDRESS_SIZE*2 + 1] = {0}; - size_t i; - uint8_t address[FRIEND_ADDRESS_SIZE]; - getaddress(m, address); - for (i = 0; i < FRIEND_ADDRESS_SIZE; ++i) { - char xx[3]; - snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); - strcat(id, xx); - } - wprintw(self->window, "%s\n", id); + char id[FRIEND_ADDRESS_SIZE * 2 + 1] = {0}; + size_t i; + uint8_t address[FRIEND_ADDRESS_SIZE]; + getaddress(m, address); + + for (i = 0; i < FRIEND_ADDRESS_SIZE; ++i) { + char xx[3]; + snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); + strcat(id, xx); + } + + wprintw(self->window, "%s\n", id); } void cmd_nick(ToxWindow *self, Messenger *m, char **args) { - char *nick = args[1]; - setname(m, (uint8_t*) nick, strlen(nick)+1); - wprintw(self->window, "Nickname set to: %s\n", nick); + char *nick = args[1]; + setname(m, (uint8_t *) nick, strlen(nick) + 1); + wprintw(self->window, "Nickname set to: %s\n", nick); } void cmd_status(ToxWindow *self, Messenger *m, char **args) { - char *status = args[1]; - char *status_text; + char *status = args[1]; + char *status_text; - USERSTATUS status_kind; - if (!strncmp(status, "online", strlen("online"))) { - status_kind = USERSTATUS_NONE; - status_text = "ONLINE"; - } - else if (!strncmp(status, "away", strlen("away"))) { - status_kind = USERSTATUS_AWAY; - status_text = "AWAY"; - } - else if (!strncmp(status, "busy", strlen("busy"))) { - status_kind = USERSTATUS_BUSY; - status_text = "BUSY"; - } - else - { - wprintw(self->window, "Invalid status.\n"); - return; - } + USERSTATUS status_kind; - char *msg = args[2]; - if (msg == NULL) { - m_set_userstatus(m, status_kind); - wprintw(self->window, "Status set to: %s\n", status_text); - } - else { - m_set_userstatus(m, status_kind); - m_set_statusmessage(m, (uint8_t*) msg, strlen(msg)+1); - wprintw(self->window, "Status set to: %s, %s\n", status_text, msg); - } + if (!strncmp(status, "online", strlen("online"))) { + status_kind = USERSTATUS_NONE; + status_text = "ONLINE"; + } else if (!strncmp(status, "away", strlen("away"))) { + status_kind = USERSTATUS_AWAY; + status_text = "AWAY"; + } else if (!strncmp(status, "busy", strlen("busy"))) { + status_kind = USERSTATUS_BUSY; + status_text = "BUSY"; + } else { + wprintw(self->window, "Invalid status.\n"); + return; + } + + char *msg = args[2]; + + if (msg == NULL) { + m_set_userstatus(m, status_kind); + wprintw(self->window, "Status set to: %s\n", status_text); + } else { + m_set_userstatus(m, status_kind); + m_set_statusmessage(m, (uint8_t *) msg, strlen(msg) + 1); + wprintw(self->window, "Status set to: %s, %s\n", status_text, msg); + } } void cmd_statusmsg(ToxWindow *self, Messenger *m, char **args) { char *msg = args[1]; - m_set_statusmessage(m, (uint8_t*) msg, strlen(msg)+1); + m_set_statusmessage(m, (uint8_t *) msg, strlen(msg) + 1); wprintw(self->window, "Status set to: %s\n", msg); } static void execute(ToxWindow *self, Messenger *m, char *u_cmd) { - int newlines = 0; - char cmd[MAX_STR_SIZE] = {0}; - int i; - for (i = 0; i < strlen(prompt_buf); ++i) { - if (u_cmd[i] == '\n') - ++newlines; - else - cmd[i - newlines] = u_cmd[i]; - } + int newlines = 0; + char cmd[MAX_STR_SIZE] = {0}; + int 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] == '\"') - while (cmd[++i] != '\"'); /* skip over strings */ - if (cmd[i] == ' ') { - cmd[i] = '\0'; - numargs++; + for (i = 0; i < strlen(prompt_buf); ++i) { + if (u_cmd[i] == '\n') + ++newlines; + else + cmd[i - newlines] = u_cmd[i]; } - } - /* excessive arguments */ - if (numargs > 3) { - wprintw(self->window, "Invalid command: too many arguments.\n"); - return; - } + int leading_spc = 0; - /* read arguments into array */ - char *cmdargs[5]; - int pos = 0; - for (i = 0; i < 5; i++) { - cmdargs[i] = cmd + pos; - pos += strlen(cmdargs[i]) + 1; - } + for (i = 0; i < MAX_STR_SIZE && isspace(cmd[i]); ++i) + leading_spc++; - /* no input */ - if (strlen(cmdargs[0]) == 0) - return; + memmove(cmd, cmd + leading_spc, MAX_STR_SIZE - leading_spc); - /* match input to command list */ - for (i = 0; i < NUM_COMMANDS; i++) { - if (!strcmp(cmdargs[0], commands[i].name)) { - /* check for missing arguments */ - int j; - for (j = 0; j <= commands[i].numargs; j++) { - if (strlen(cmdargs[j]) == 0) { - wprintw(self->window, "Invalid command: %s expected %d arguments, got %d.\n", - commands[i].name, commands[i].numargs, j - 1); - return; + 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] == '\"') + while (cmd[++i] != '\"'); /* skip over strings */ + + if (cmd[i] == ' ') { + cmd[i] = '\0'; + numargs++; } - } - /* check for excess arguments */ - if (strcmp(cmdargs[0], "add") && strlen(cmdargs[j]) != 0) { - wprintw(self->window, "Invalid command: too many arguments to %s.\n", commands[i].name); - return; - } - /* pass arguments to command function */ - (commands[i].func)(self, m, cmdargs); - return; } - } - /* no match */ - wprintw(self->window, "Invalid command.\n"); + /* excessive arguments */ + if (numargs > 3) { + wprintw(self->window, "Invalid command: too many arguments.\n"); + return; + } + + /* read arguments into array */ + char *cmdargs[5]; + int pos = 0; + + for (i = 0; i < 5; i++) { + cmdargs[i] = cmd + pos; + pos += strlen(cmdargs[i]) + 1; + } + + /* no input */ + if (strlen(cmdargs[0]) == 0) + return; + + /* match input to command list */ + for (i = 0; i < NUM_COMMANDS; i++) { + if (!strcmp(cmdargs[0], commands[i].name)) { + /* check for missing arguments */ + int j; + + for (j = 0; j <= commands[i].numargs; j++) { + if (strlen(cmdargs[j]) == 0) { + wprintw(self->window, "Invalid command: %s expected %d arguments, got %d.\n", + commands[i].name, commands[i].numargs, j - 1); + return; + } + } + + /* check for excess arguments */ + if (strcmp(cmdargs[0], "add") && strlen(cmdargs[j]) != 0) { + wprintw(self->window, "Invalid command: too many arguments to %s.\n", commands[i].name); + return; + } + + /* pass arguments to command function */ + (commands[i].func)(self, m, cmdargs); + return; + } + } + + /* no match */ + wprintw(self->window, "Invalid command.\n"); } static void prompt_onKey(ToxWindow *self, Messenger *m, int key) { - /* Add printable characters to line */ - if (isprint(key)) { - if (prompt_buf_pos == (sizeof(prompt_buf) - 1)) { - wprintw(self->window, "\nToo Long.\n"); - prompt_buf_pos = 0; - prompt_buf[0] = 0; - } - else if (!(prompt_buf_pos == 0) && (prompt_buf_pos < COLS) - && (prompt_buf_pos % (COLS - 3) == 0)) { - prompt_buf[prompt_buf_pos++] = '\n'; - } - else if (!(prompt_buf_pos == 0) && (prompt_buf_pos > COLS) - && ((prompt_buf_pos - (COLS - 3)) % (COLS) == 0)) { - prompt_buf[prompt_buf_pos++] = '\n'; - } - prompt_buf[prompt_buf_pos++] = key; - prompt_buf[prompt_buf_pos] = 0; - } + /* Add printable characters to line */ + if (isprint(key)) { + if (prompt_buf_pos == (sizeof(prompt_buf) - 1)) { + wprintw(self->window, "\nToo Long.\n"); + prompt_buf_pos = 0; + prompt_buf[0] = 0; + } else if (!(prompt_buf_pos == 0) && (prompt_buf_pos < COLS) + && (prompt_buf_pos % (COLS - 3) == 0)) { + prompt_buf[prompt_buf_pos++] = '\n'; + } else if (!(prompt_buf_pos == 0) && (prompt_buf_pos > COLS) + && ((prompt_buf_pos - (COLS - 3)) % (COLS) == 0)) { + prompt_buf[prompt_buf_pos++] = '\n'; + } - /* RETURN key: execute command */ - else if (key == '\n') { - wprintw(self->window, "\n"); - execute(self, m, prompt_buf); - prompt_buf_pos = 0; - prompt_buf[0] = 0; - } - - /* BACKSPACE key: Remove one character from line */ - else if (key == 0x107 || key == 0x8 || key == 0x7f) { - if (prompt_buf_pos != 0) { - prompt_buf[--prompt_buf_pos] = 0; + prompt_buf[prompt_buf_pos++] = key; + prompt_buf[prompt_buf_pos] = 0; + } + + /* RETURN key: execute command */ + else if (key == '\n') { + wprintw(self->window, "\n"); + execute(self, m, prompt_buf); + prompt_buf_pos = 0; + prompt_buf[0] = 0; + } + + /* BACKSPACE key: Remove one character from line */ + else if (key == 0x107 || key == 0x8 || key == 0x7f) { + if (prompt_buf_pos != 0) { + prompt_buf[--prompt_buf_pos] = 0; + } } - } } static void prompt_onDraw(ToxWindow *self) { - curs_set(1); - int x, y; - getyx(self->window, y, x); - (void) x; - int i; - for (i = 0; i < (strlen(prompt_buf)); ++i) { - if ((prompt_buf[i] == '\n') && (y != 0)) - --y; - } + curs_set(1); + int x, y; + getyx(self->window, y, x); + (void) x; + int i; - wattron(self->window, COLOR_PAIR(1)); - mvwprintw(self->window, y, 0, "# "); - wattroff(self->window, COLOR_PAIR(1)); - mvwprintw(self->window, y, 2, "%s", prompt_buf); - wclrtoeol(self->window); - wrefresh(self->window); + for (i = 0; i < (strlen(prompt_buf)); ++i) { + if ((prompt_buf[i] == '\n') && (y != 0)) + --y; + } + + wattron(self->window, COLOR_PAIR(1)); + mvwprintw(self->window, y, 0, "# "); + wattroff(self->window, COLOR_PAIR(1)); + mvwprintw(self->window, y, 2, "%s", prompt_buf); + wclrtoeol(self->window); + wrefresh(self->window); } static void prompt_onInit(ToxWindow *self, Messenger *m) { - scrollok(self->window, 1); - cmd_help(self, m, NULL); - wclrtoeol(self->window); + scrollok(self->window, 1); + cmd_help(self, m, NULL); + wclrtoeol(self->window); } ToxWindow new_prompt(friendAddedFn *f) { - on_friendadded_cb = f; - ToxWindow ret; - memset(&ret, 0, sizeof(ret)); - ret.onKey = &prompt_onKey; - ret.onDraw = &prompt_onDraw; - ret.onInit = &prompt_onInit; - strcpy(ret.title, "[prompt]"); - return ret; + on_friendadded_cb = f; + ToxWindow ret; + memset(&ret, 0, sizeof(ret)); + ret.onKey = &prompt_onKey; + ret.onDraw = &prompt_onDraw; + ret.onInit = &prompt_onInit; + strcpy(ret.title, "[prompt]"); + return ret; } diff --git a/windows.c b/windows.c index 15caddf..183c0f9 100644 --- a/windows.c +++ b/windows.c @@ -14,232 +14,258 @@ static ToxWindow windows[MAX_WINDOW_SLOTS]; static Messenger *m; int active_window; -static ToxWindow* prompt; +static ToxWindow *prompt; /* CALLBACKS START */ -void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void* userdata) +void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata) { - int n = add_req(public_key); - wprintw(prompt->window, "\nFriend request from:\n"); + int n = add_req(public_key); + wprintw(prompt->window, "\nFriend request from:\n"); - int i; - for (i = 0; i < KEY_SIZE_BYTES; ++i) { - wprintw(prompt->window, "%02x", public_key[i] & 0xff); - } + int i; - wprintw(prompt->window, "\nWith the message: %s\n", data); - wprintw(prompt->window, "\nUse \"accept %d\" to accept it.\n", n); + for (i = 0; i < KEY_SIZE_BYTES; ++i) { + wprintw(prompt->window, "%02x", public_key[i] & 0xff); + } - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { - if (windows[i].onFriendRequest != NULL) - windows[i].onFriendRequest(&windows[i], public_key, data, length); - } + wprintw(prompt->window, "\nWith the message: %s\n", data); + wprintw(prompt->window, "\nUse \"accept %d\" to accept it.\n", n); + + for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + if (windows[i].onFriendRequest != NULL) + windows[i].onFriendRequest(&windows[i], public_key, data, length); + } } -void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) +void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata) { - int i; - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { - if (windows[i].onMessage != NULL) - windows[i].onMessage(&windows[i], m, friendnumber, string, length); - } + int i; + + for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + if (windows[i].onMessage != NULL) + windows[i].onMessage(&windows[i], m, friendnumber, string, length); + } } -void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) +void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata) { - int i; - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { - if (windows[i].onAction != NULL) - windows[i].onAction(&windows[i], m, friendnumber, string, length); - } + int i; + + for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + if (windows[i].onAction != NULL) + windows[i].onAction(&windows[i], m, friendnumber, string, length); + } } -void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) +void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata) { - wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string); - int i; - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { - if (windows[i].onNickChange != NULL) - windows[i].onNickChange(&windows[i], friendnumber, string, length); - } + wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string); + int i; + + for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + if (windows[i].onNickChange != NULL) + windows[i].onNickChange(&windows[i], friendnumber, string, length); + } } -void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) +void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata) { - wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); - int i; - for (i=0; iwindow, "\n(statuschange) %d: %s\n", friendnumber, string); + int i; + + for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + if (windows[i].onStatusChange != NULL) + windows[i].onStatusChange(&windows[i], friendnumber, string, length); + } } void on_friendadded(Messenger *m, int friendnumber) { - friendlist_onFriendAdded(m, friendnumber); - if (store_data(m, DATA_FILE) != 0) { - wprintw(prompt->window, "\nCould not store Messenger data\n"); - } + friendlist_onFriendAdded(m, friendnumber); + + if (store_data(m, DATA_FILE) != 0) { + wprintw(prompt->window, "\nCould not store Messenger data\n"); + } } /* CALLBACKS END */ int add_window(Messenger *m, ToxWindow w, int n) { - if (w_num >= TOXWINDOWS_MAX_NUM) - return -1; + if (w_num >= TOXWINDOWS_MAX_NUM) + return -1; - if (LINES < 2) - return -1; + if (LINES < 2) + return -1; - w.window = newwin(LINES - 2, COLS, 0, 0); - if (w.window == NULL) - return -1; + w.window = newwin(LINES - 2, COLS, 0, 0); - windows[n] = w; - w.onInit(&w, m); - w_num++; - active_window = n; - return n; + if (w.window == NULL) + return -1; + + windows[n] = w; + w.onInit(&w, m); + w_num++; + active_window = n; + return n; } /* Deletes window w and cleans up */ void del_window(ToxWindow *w, int f_num) { - active_window = 0; // Go to prompt screen - delwin(w->window); - int i; - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { - if (WINDOW_STATUS[i] == f_num) { - WINDOW_STATUS[i] = -1; - disable_chatwin(f_num); - break; + active_window = 0; // Go to prompt screen + delwin(w->window); + int i; + + for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { + if (WINDOW_STATUS[i] == f_num) { + WINDOW_STATUS[i] = -1; + disable_chatwin(f_num); + break; + } } - } - clear(); - refresh(); + + clear(); + refresh(); } /* Shows next window when tab or back-tab is pressed */ void set_active_window(int ch) { - int f_inf = 0; - int max = MAX_WINDOW_SLOTS-1; - if (ch == '\t') { - int i = (active_window + 1) % max; - while (true) { - if (WINDOW_STATUS[i] != -1) { - active_window = i; - return; - } - i = (i + 1) % max; - if (f_inf++ > max) { // infinite loop check - endwin(); - exit(2); - } + int f_inf = 0; + int max = MAX_WINDOW_SLOTS - 1; + + if (ch == '\t') { + int i = (active_window + 1) % max; + + while (true) { + if (WINDOW_STATUS[i] != -1) { + active_window = i; + return; + } + + i = (i + 1) % max; + + if (f_inf++ > max) { // infinite loop check + endwin(); + exit(2); + } + } + } else { + int i = active_window - 1; + + if (i < 0) i = max; + + while (true) { + if (WINDOW_STATUS[i] != -1) { + active_window = i; + return; + } + + if (--i < 0) i = max; + + if (f_inf++ > max) { + endwin(); + exit(2); + } + } } - }else { - int i = active_window - 1; - if (i < 0) i = max; - while (true) { - if (WINDOW_STATUS[i] != -1) { - active_window = i; - return; - } - if (--i < 0) i = max; - if (f_inf++ > max) { - endwin(); - exit(2); - } - } - } } void init_window_status() { - /* Default window values decrement from -2 */ - int i; - for (i = 0; i < N_DEFAULT_WINS; ++i) - WINDOW_STATUS[i] = -(i+2); + /* Default window values decrement from -2 */ + int i; - int j; - for (j = N_DEFAULT_WINS; j < MAX_WINDOW_SLOTS; j++) - WINDOW_STATUS[j] = -1; + for (i = 0; i < N_DEFAULT_WINS; ++i) + WINDOW_STATUS[i] = -(i + 2); + + int j; + + for (j = N_DEFAULT_WINS; j < MAX_WINDOW_SLOTS; j++) + WINDOW_STATUS[j] = -1; } ToxWindow *init_windows() { - w_num = 0; - int n_prompt = 0; - int n_friendslist = 1; - int n_dhtstatus = 2; - if (add_window(m, new_prompt(on_friendadded), n_prompt) == -1 - || add_window(m, new_friendlist(WINDOW_STATUS), n_friendslist) == -1 - || add_window(m, new_dhtstatus(), n_dhtstatus) == -1) { - fprintf(stderr, "add_window() failed.\n"); - endwin(); - exit(1); - } - active_window = n_prompt; - prompt = &windows[n_prompt]; - return prompt; + w_num = 0; + int n_prompt = 0; + int n_friendslist = 1; + int n_dhtstatus = 2; + + if (add_window(m, new_prompt(on_friendadded), n_prompt) == -1 + || add_window(m, new_friendlist(WINDOW_STATUS), n_friendslist) == -1 + || add_window(m, new_dhtstatus(), n_dhtstatus) == -1) { + fprintf(stderr, "add_window() failed.\n"); + endwin(); + exit(1); + } + + active_window = n_prompt; + prompt = &windows[n_prompt]; + return prompt; } static void draw_bar() { - static int odd = 0; - int blinkrate = 30; + static int odd = 0; + int blinkrate = 30; - attron(COLOR_PAIR(4)); - mvhline(LINES - 2, 0, '_', COLS); - attroff(COLOR_PAIR(4)); + attron(COLOR_PAIR(4)); + mvhline(LINES - 2, 0, '_', COLS); + attroff(COLOR_PAIR(4)); - move(LINES - 1, 0); + move(LINES - 1, 0); - attron(COLOR_PAIR(4) | A_BOLD); - printw(" TOXIC " TOXICVER "|"); - attroff(COLOR_PAIR(4) | A_BOLD); + attron(COLOR_PAIR(4) | A_BOLD); + printw(" TOXIC " TOXICVER "|"); + attroff(COLOR_PAIR(4) | A_BOLD); - int i; - for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) { - if (WINDOW_STATUS[i] != -1) { - if (i == active_window) - attron(A_BOLD); + int i; - odd = (odd+1) % blinkrate; - if (windows[i].blink && (odd < (blinkrate/2))) - attron(COLOR_PAIR(3)); + for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) { + if (WINDOW_STATUS[i] != -1) { + if (i == active_window) + attron(A_BOLD); - printw(" %s", windows[i].title); - if (windows[i].blink && (odd < (blinkrate/2))) - attroff(COLOR_PAIR(3)); + odd = (odd + 1) % blinkrate; - if (i == active_window) { - attroff(A_BOLD); - } + if (windows[i].blink && (odd < (blinkrate / 2))) + attron(COLOR_PAIR(3)); + + printw(" %s", windows[i].title); + + if (windows[i].blink && (odd < (blinkrate / 2))) + attroff(COLOR_PAIR(3)); + + if (i == active_window) { + attroff(A_BOLD); + } + } } - } - refresh(); + + refresh(); } void prepare_window(WINDOW *w) { - mvwin(w, 0, 0); - wresize(w, LINES-2, COLS); + mvwin(w, 0, 0); + wresize(w, LINES - 2, COLS); } void draw_active_window(Messenger *m) { - ToxWindow *a = &windows[active_window]; - prepare_window(a->window); - a->blink = false; - draw_bar(); - a->onDraw(a); + ToxWindow *a = &windows[active_window]; + prepare_window(a->window); + a->blink = false; + draw_bar(); + a->onDraw(a); - /* Handle input */ - int ch = getch(); - if (ch == '\t' || ch == KEY_BTAB) - set_active_window(ch); - else if (ch != ERR) - a->onKey(a, m, ch); + /* Handle input */ + int ch = getch(); + + if (ch == '\t' || ch == KEY_BTAB) + set_active_window(ch); + else if (ch != ERR) + a->onKey(a, m, ch); } diff --git a/windows.h b/windows.h index 9f4d74a..553a620 100644 --- a/windows.h +++ b/windows.h @@ -26,31 +26,31 @@ typedef struct ToxWindow_ ToxWindow; struct ToxWindow_ { - void(*onKey)(ToxWindow*, Messenger*, int); - void(*onDraw)(ToxWindow*); - void(*onInit)(ToxWindow*, Messenger*); - void(*onFriendRequest)(ToxWindow*, uint8_t*, uint8_t*, uint16_t); - void(*onMessage)(ToxWindow*, Messenger*, int, uint8_t*, uint16_t); - void(*onNickChange)(ToxWindow*, int, uint8_t*, uint16_t); - void(*onStatusChange)(ToxWindow*, int, uint8_t*, uint16_t); - void(*onAction)(ToxWindow*, Messenger*, int, uint8_t*, uint16_t); - char title[256]; + void(*onKey)(ToxWindow *, Messenger *, int); + void(*onDraw)(ToxWindow *); + void(*onInit)(ToxWindow *, Messenger *); + void(*onFriendRequest)(ToxWindow *, uint8_t *, uint8_t *, uint16_t); + void(*onMessage)(ToxWindow *, Messenger *, int, uint8_t *, uint16_t); + void(*onNickChange)(ToxWindow *, int, uint8_t *, uint16_t); + void(*onStatusChange)(ToxWindow *, int, uint8_t *, uint16_t); + void(*onAction)(ToxWindow *, Messenger *, int, uint8_t *, uint16_t); + char title[256]; - void* x; - bool blink; + void *x; + bool blink; - WINDOW* window; + WINDOW *window; }; -void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void* userdata); -void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); -void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); -void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); -void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); +void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata); +void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata); +void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata); +void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata); +void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata); void on_friendadded(Messenger *m, int friendnumber); void init_window_status(); -ToxWindow * init_windows(); -void draw_active_window(Messenger * m); +ToxWindow *init_windows(); +void draw_active_window(Messenger *m); int add_window(Messenger *m, ToxWindow w, int n); void del_window(ToxWindow *w, int f_num); void set_active_window(int ch); From 5d8ccde3d9c9d22f529dbb5747373bc5a9e51765 Mon Sep 17 00:00:00 2001 From: Michael Rose Date: Sat, 17 Aug 2013 11:59:28 +0200 Subject: [PATCH 140/172] Messenger stores / loads nickname new toxic command to show nickname (mynick) --- prompt.c | 19 ++++++++++++++++++- windows.c | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/prompt.c b/prompt.c index f6d3e21..a37fdaa 100644 --- a/prompt.c +++ b/prompt.c @@ -13,6 +13,9 @@ #include "windows.h" #include "prompt.h" +extern char *DATA_FILE; +extern int store_data(Messenger *m, char *path); + uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX uint8_t num_requests = 0; // XXX @@ -29,11 +32,12 @@ void cmd_help(ToxWindow *, Messenger *m, char **); void cmd_msg(ToxWindow *, Messenger *m, char **); void cmd_myid(ToxWindow *, Messenger *m, char **); void cmd_nick(ToxWindow *, Messenger *m, char **); +void cmd_mynick(ToxWindow *, Messenger *m, char **); void cmd_quit(ToxWindow *, Messenger *m, char **); void cmd_status(ToxWindow *, Messenger *m, char **); void cmd_statusmsg(ToxWindow *, Messenger *m, char **); -#define NUM_COMMANDS 13 +#define NUM_COMMANDS 14 static struct { char *name; @@ -49,6 +53,7 @@ static struct { { "msg", 2, cmd_msg }, { "myid", 0, cmd_myid }, { "nick", 1, cmd_nick }, + { "mynick", 0, cmd_mynick }, { "q", 0, cmd_quit }, { "quit", 0, cmd_quit }, { "status", 2, cmd_status }, @@ -222,6 +227,7 @@ void cmd_help(ToxWindow *self, Messenger *m, char **args) wprintw(self->window, " status : Set your status\n"); wprintw(self->window, " statusmsg : Set your status\n"); wprintw(self->window, " nick : Set your nickname\n"); + wprintw(self->window, " mynick : Print your current nickname\n"); wprintw(self->window, " accept : Accept friend request\n"); wprintw(self->window, " myid : Print your ID\n"); wprintw(self->window, " quit/exit : Exit program\n"); @@ -267,6 +273,17 @@ void cmd_nick(ToxWindow *self, Messenger *m, char **args) char *nick = args[1]; setname(m, (uint8_t *) nick, strlen(nick) + 1); wprintw(self->window, "Nickname set to: %s\n", nick); + if (store_data(m, DATA_FILE)) { + wprintw(self->window, "\nCould not store Messenger data\n"); + } +} + +void cmd_mynick(ToxWindow *self, Messenger *m, char **args) +{ + uint8_t *nick = malloc(m->name_length); + getself_name(m, nick, m->name_length); + wprintw(self->window, "Current nickname: %s\n", nick); + free(nick); } void cmd_status(ToxWindow *self, Messenger *m, char **args) diff --git a/windows.c b/windows.c index 183c0f9..11396e2 100644 --- a/windows.c +++ b/windows.c @@ -83,7 +83,7 @@ void on_friendadded(Messenger *m, int friendnumber) { friendlist_onFriendAdded(m, friendnumber); - if (store_data(m, DATA_FILE) != 0) { + if (store_data(m, DATA_FILE)) { wprintw(prompt->window, "\nCould not store Messenger data\n"); } } From 374b7b9c6b6063ae0390ec18211cf8cfe75dd88d Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sat, 17 Aug 2013 19:26:31 -0700 Subject: [PATCH 141/172] Standarized DHTservers --- main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 816873b..6267751 100644 --- a/main.c +++ b/main.c @@ -88,7 +88,11 @@ int init_connection(void) if (DHT_isconnected()) return 0; - FILE *fp = fopen("../../../other/DHTservers", "r"); + #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) + FILE *fp = fopen("DHTservers", "r"); + #else + FILE *fp = fopen("~/.tox/DHTservers", "r"); + #endif if (!fp) return 1; From 1a8dce7905174de0925f093bacc807363420fa79 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sat, 17 Aug 2013 19:43:10 -0700 Subject: [PATCH 142/172] Added more colors --- main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/main.c b/main.c index 6267751..1bb6cb5 100644 --- a/main.c +++ b/main.c @@ -52,6 +52,10 @@ static void init_term() init_pair(3, COLOR_RED, COLOR_BLACK); init_pair(4, COLOR_BLUE, COLOR_BLACK); init_pair(5, COLOR_YELLOW, COLOR_BLACK); + init_pair(6, COLOR_MAGENTA, COLOR_BLACK); + init_pair(7, COLOR_BLACK, COLOR_BLACK); + init_pair(8, COLOR_BLACK, COLOR_WHITE); + } refresh(); From 6196c1f4ebb07bb588f81af6d5d0eb908e51ce42 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sat, 17 Aug 2013 20:57:35 -0700 Subject: [PATCH 143/172] Might improve windows detection --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index 1bb6cb5..2da87bc 100644 --- a/main.c +++ b/main.c @@ -74,7 +74,7 @@ static Messenger *init_tox() m_callback_action(m, on_action, NULL); #ifdef __linux__ setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy")); -#elif WIN32 +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); #else setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); From 61b72daf6a7206b56ae3131e0b2862159f794a66 Mon Sep 17 00:00:00 2001 From: Aaron Lipinski Date: Sat, 17 Aug 2013 20:00:19 +1200 Subject: [PATCH 144/172] remove WINDOW_STATUS, simplify adding and selecting chat windows --- chat.c | 3 +- friendlist.c | 36 ++---------- friendlist.h | 2 +- main.c | 1 - windows.c | 155 ++++++++++++++++++++------------------------------- windows.h | 5 +- 6 files changed, 69 insertions(+), 133 deletions(-) diff --git a/chat.c b/chat.c index ef932cd..67c2ed0 100644 --- a/chat.c +++ b/chat.c @@ -335,7 +335,8 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) else if (strcmp(ctx->line, "/close") == 0) { int f_num = ctx->friendnum; delwin(ctx->linewin); - del_window(self, f_num); + del_window(self); + disable_chatwin(f_num); } else diff --git a/friendlist.c b/friendlist.c index c85fd3a..0a58bc5 100644 --- a/friendlist.c +++ b/friendlist.c @@ -13,7 +13,6 @@ #include "windows.h" #include "friendlist.h" -static char *WINDOW_STATUS; typedef struct { uint8_t name[MAX_NAME_LENGTH]; @@ -48,17 +47,7 @@ void friendlist_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *str, return; if (friends[num].chatwin == -1) { - friends[num].chatwin = num; - int i; - - /* Find first open slot to hold chat window */ - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { - if (WINDOW_STATUS[i] == -1) { - WINDOW_STATUS[i] = num; - add_window(m, new_chat(m, num), i); - break; - } - } + friends[num].chatwin = add_window(m, new_chat(m, num)); } } @@ -106,25 +95,9 @@ static void friendlist_onKey(ToxWindow *self, Messenger *m, int key) } else if (key == '\n') { /* Jump to chat window if already open */ if (friends[num_selected].chatwin != -1) { - int i; - - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { - if (WINDOW_STATUS[i] == num_selected) { - set_active_window(i); - break; - } - } + set_active_window(friends[num_selected].chatwin); } else { - int i; - - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { - if (WINDOW_STATUS[i] == -1) { - WINDOW_STATUS[i] = num_selected; - friends[num_selected].chatwin = num_selected; - add_window(m, new_chat(m, num_selected), i); - break; - } - } + friends[num_selected].chatwin = add_window(m, new_chat(m, num_selected)); } } } @@ -172,9 +145,8 @@ static void friendlist_onInit(ToxWindow *self, Messenger *m) } -ToxWindow new_friendlist(char *ws) +ToxWindow new_friendlist() { - WINDOW_STATUS = ws; ToxWindow ret; memset(&ret, 0, sizeof(ret)); diff --git a/friendlist.h b/friendlist.h index f0c27f5..91b917f 100644 --- a/friendlist.h +++ b/friendlist.h @@ -4,7 +4,7 @@ #include "windows.h" #include "chat.h" -ToxWindow new_friendlist(char *ws); +ToxWindow new_friendlist(); int friendlist_onFriendAdded(Messenger *m, int num); void disable_chatwin(int f_num); void fix_name(uint8_t *name); diff --git a/main.c b/main.c index 816873b..4562f39 100644 --- a/main.c +++ b/main.c @@ -295,7 +295,6 @@ int main(int argc, char *argv[]) init_term(); Messenger *m = init_tox(); ToxWindow *prompt = init_windows(m); - init_window_status(); if (f_loadfromfile) load_data(m, DATA_FILE); diff --git a/windows.c b/windows.c index 11396e2..a8efa06 100644 --- a/windows.c +++ b/windows.c @@ -6,15 +6,10 @@ extern char *DATA_FILE; extern int store_data(Messenger *m, char *path); -/* Holds status of chat windows */ -char WINDOW_STATUS[MAX_WINDOW_SLOTS]; - -static int w_num; static ToxWindow windows[MAX_WINDOW_SLOTS]; -static Messenger *m; -int active_window; - +static ToxWindow *active_window; static ToxWindow *prompt; +static Messenger *m; /* CALLBACKS START */ void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata) @@ -89,119 +84,89 @@ void on_friendadded(Messenger *m, int friendnumber) } /* CALLBACKS END */ -int add_window(Messenger *m, ToxWindow w, int n) +int add_window(Messenger *m, ToxWindow w) { - if (w_num >= TOXWINDOWS_MAX_NUM) - return -1; - if (LINES < 2) return -1; + + int i; + for(i = 0; i < MAX_WINDOW_SLOTS; i++) { + if (windows[i].window) + continue; + + w.window = newwin(LINES - 2, COLS, 0, 0); + if (w.window == NULL) + return -1; - w.window = newwin(LINES - 2, COLS, 0, 0); - - if (w.window == NULL) - return -1; - - windows[n] = w; - w.onInit(&w, m); - w_num++; - active_window = n; - return n; + windows[i] = w; + w.onInit(&w, m); + + active_window = windows+i; + return i; + } + + return -1; } /* Deletes window w and cleans up */ -void del_window(ToxWindow *w, int f_num) +void del_window(ToxWindow *w) { - active_window = 0; // Go to prompt screen + active_window = windows; // Go to prompt screen delwin(w->window); - int i; - - for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { - if (WINDOW_STATUS[i] == f_num) { - WINDOW_STATUS[i] = -1; - disable_chatwin(f_num); - break; - } - } - + if (w->x) + free(w->x); + w->window = NULL; + memset(w, 0, sizeof(ToxWindow)); clear(); refresh(); } /* Shows next window when tab or back-tab is pressed */ -void set_active_window(int ch) +void set_next_window(int ch) { - int f_inf = 0; - int max = MAX_WINDOW_SLOTS - 1; - - if (ch == '\t') { - int i = (active_window + 1) % max; - - while (true) { - if (WINDOW_STATUS[i] != -1) { - active_window = i; - return; - } - - i = (i + 1) % max; - - if (f_inf++ > max) { // infinite loop check - endwin(); - exit(2); - } - } - } else { - int i = active_window - 1; - - if (i < 0) i = max; - - while (true) { - if (WINDOW_STATUS[i] != -1) { - active_window = i; - return; - } - - if (--i < 0) i = max; - - if (f_inf++ > max) { - endwin(); - exit(2); - } + ToxWindow *end = windows+MAX_WINDOW_SLOTS-1; + ToxWindow *inf = active_window; + while(true) { + if (ch == '\t') { + if (++active_window > end) + active_window = windows; + } else + if (--active_window < windows) + active_window = end; + + if (active_window->window) + return; + + if (active_window == inf) { // infinite loop check + endwin(); + exit(2); } } } -void init_window_status() +void set_active_window(int index) { - /* Default window values decrement from -2 */ - int i; - - for (i = 0; i < N_DEFAULT_WINS; ++i) - WINDOW_STATUS[i] = -(i + 2); - - int j; - - for (j = N_DEFAULT_WINS; j < MAX_WINDOW_SLOTS; j++) - WINDOW_STATUS[j] = -1; + if (index < 0 || index >= MAX_WINDOW_SLOTS) + return; + + active_window = windows+index; } ToxWindow *init_windows() { - w_num = 0; - int n_prompt = 0; - int n_friendslist = 1; - int n_dhtstatus = 2; - - if (add_window(m, new_prompt(on_friendadded), n_prompt) == -1 - || add_window(m, new_friendlist(WINDOW_STATUS), n_friendslist) == -1 - || add_window(m, new_dhtstatus(), n_dhtstatus) == -1) { + int n_prompt = add_window(m, new_prompt(on_friendadded)); + + if (n_prompt == -1 + || add_window(m, new_friendlist()) == -1 + || add_window(m, new_dhtstatus()) == -1) { fprintf(stderr, "add_window() failed.\n"); endwin(); exit(1); } - active_window = n_prompt; prompt = &windows[n_prompt]; + active_window = prompt; + return prompt; } @@ -223,8 +188,8 @@ static void draw_bar() int i; for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) { - if (WINDOW_STATUS[i] != -1) { - if (i == active_window) + if (windows[i].window) { + if (windows+i == active_window) attron(A_BOLD); odd = (odd + 1) % blinkrate; @@ -237,7 +202,7 @@ static void draw_bar() if (windows[i].blink && (odd < (blinkrate / 2))) attroff(COLOR_PAIR(3)); - if (i == active_window) { + if (windows+i == active_window) { attroff(A_BOLD); } } @@ -255,7 +220,7 @@ void prepare_window(WINDOW *w) void draw_active_window(Messenger *m) { - ToxWindow *a = &windows[active_window]; + ToxWindow *a = active_window; prepare_window(a->window); a->blink = false; draw_bar(); @@ -265,7 +230,7 @@ void draw_active_window(Messenger *m) int ch = getch(); if (ch == '\t' || ch == KEY_BTAB) - set_active_window(ch); + set_next_window(ch); else if (ch != ERR) a->onKey(a, m, ch); } diff --git a/windows.h b/windows.h index 553a620..7b78469 100644 --- a/windows.h +++ b/windows.h @@ -48,11 +48,10 @@ void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata); void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata); void on_friendadded(Messenger *m, int friendnumber); -void init_window_status(); ToxWindow *init_windows(); void draw_active_window(Messenger *m); -int add_window(Messenger *m, ToxWindow w, int n); -void del_window(ToxWindow *w, int f_num); +int add_window(Messenger *m, ToxWindow w); +void del_window(ToxWindow *w); void set_active_window(int ch); #endif From 9ca6c99cdcff88cf40758f79a0e61aafa6c9bf03 Mon Sep 17 00:00:00 2001 From: Aaron Lipinski Date: Sun, 18 Aug 2013 01:40:30 +1200 Subject: [PATCH 145/172] reduce number of windows, use consistent naming --- windows.c | 20 ++++++++++---------- windows.h | 5 +---- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/windows.c b/windows.c index a8efa06..80d6428 100644 --- a/windows.c +++ b/windows.c @@ -6,7 +6,7 @@ extern char *DATA_FILE; extern int store_data(Messenger *m, char *path); -static ToxWindow windows[MAX_WINDOW_SLOTS]; +static ToxWindow windows[MAX_WINDOWS_NUM]; static ToxWindow *active_window; static ToxWindow *prompt; static Messenger *m; @@ -26,7 +26,7 @@ void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void *userd wprintw(prompt->window, "\nWith the message: %s\n", data); wprintw(prompt->window, "\nUse \"accept %d\" to accept it.\n", n); - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onFriendRequest != NULL) windows[i].onFriendRequest(&windows[i], public_key, data, length); } @@ -36,7 +36,7 @@ void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length { int i; - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onMessage != NULL) windows[i].onMessage(&windows[i], m, friendnumber, string, length); } @@ -46,7 +46,7 @@ void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, { int i; - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onAction != NULL) windows[i].onAction(&windows[i], m, friendnumber, string, length); } @@ -57,7 +57,7 @@ void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t len wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string); int i; - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onNickChange != NULL) windows[i].onNickChange(&windows[i], friendnumber, string, length); } @@ -68,7 +68,7 @@ void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t l wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); int i; - for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { if (windows[i].onStatusChange != NULL) windows[i].onStatusChange(&windows[i], friendnumber, string, length); } @@ -90,7 +90,7 @@ int add_window(Messenger *m, ToxWindow w) return -1; int i; - for(i = 0; i < MAX_WINDOW_SLOTS; i++) { + for(i = 0; i < MAX_WINDOWS_NUM; i++) { if (windows[i].window) continue; @@ -124,7 +124,7 @@ void del_window(ToxWindow *w) /* Shows next window when tab or back-tab is pressed */ void set_next_window(int ch) { - ToxWindow *end = windows+MAX_WINDOW_SLOTS-1; + ToxWindow *end = windows+MAX_WINDOWS_NUM-1; ToxWindow *inf = active_window; while(true) { if (ch == '\t') { @@ -146,7 +146,7 @@ void set_next_window(int ch) void set_active_window(int index) { - if (index < 0 || index >= MAX_WINDOW_SLOTS) + if (index < 0 || index >= MAX_WINDOWS_NUM) return; active_window = windows+index; @@ -187,7 +187,7 @@ static void draw_bar() int i; - for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) { + for (i = 0; i < (MAX_WINDOWS_NUM); ++i) { if (windows[i].window) { if (windows+i == active_window) attron(A_BOLD); diff --git a/windows.h b/windows.h index 7b78469..be5557e 100644 --- a/windows.h +++ b/windows.h @@ -8,7 +8,7 @@ #include #include #include "../../core/Messenger.h" -#define TOXWINDOWS_MAX_NUM 32 +#define MAX_WINDOWS_NUM 32 #define MAX_FRIENDS_NUM 100 #define MAX_STR_SIZE 256 #define KEY_SIZE_BYTES 32 @@ -16,9 +16,6 @@ /* number of permanent default windows */ #define N_DEFAULT_WINS 3 -/* maximum window slots for WINDOW_STATUS array */ -#define MAX_WINDOW_SLOTS N_DEFAULT_WINS+MAX_FRIENDS_NUM - #ifndef TOXICVER #define TOXICVER "NOVER" //Use the -D flag to set this #endif From 901d8eb8b91d357b39f6bb0e4a8a366d9eb25509 Mon Sep 17 00:00:00 2001 From: Aaron Lipinski Date: Sun, 18 Aug 2013 02:05:32 +1200 Subject: [PATCH 146/172] remove callback introduced temporarily during refactoring --- prompt.c | 8 +++----- prompt.h | 4 +--- windows.c | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/prompt.c b/prompt.c index a37fdaa..0c1cf4b 100644 --- a/prompt.c +++ b/prompt.c @@ -19,7 +19,6 @@ extern int store_data(Messenger *m, char *path); uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX uint8_t num_requests = 0; // XXX -static friendAddedFn *on_friendadded_cb; static char prompt_buf[MAX_STR_SIZE] = {0}; static int prompt_buf_pos = 0; @@ -97,7 +96,7 @@ void cmd_accept(ToxWindow *self, Messenger *m, char **args) wprintw(self->window, "Failed to add friend.\n"); else { wprintw(self->window, "Friend accepted as: %d.\n", num); - on_friendadded_cb(m, num); + on_friendadded(m, num); } } @@ -174,7 +173,7 @@ void cmd_add(ToxWindow *self, Messenger *m, char **args) default: wprintw(self->window, "Friend added as %d.\n", num); - on_friendadded_cb(m, num); + on_friendadded(m, num); break; } } @@ -480,9 +479,8 @@ static void prompt_onInit(ToxWindow *self, Messenger *m) wclrtoeol(self->window); } -ToxWindow new_prompt(friendAddedFn *f) +ToxWindow new_prompt() { - on_friendadded_cb = f; ToxWindow ret; memset(&ret, 0, sizeof(ret)); ret.onKey = &prompt_onKey; diff --git a/prompt.h b/prompt.h index 6c5320a..8e12a42 100644 --- a/prompt.h +++ b/prompt.h @@ -3,9 +3,7 @@ #include "windows.h" -typedef void (friendAddedFn)(Messenger *m, int friendnumber); - -ToxWindow new_prompt(friendAddedFn *f); +ToxWindow new_prompt(); int add_req(uint8_t *public_key); unsigned char *hex_string_to_bin(char hex_string[]); diff --git a/windows.c b/windows.c index 80d6428..a2c649d 100644 --- a/windows.c +++ b/windows.c @@ -154,7 +154,7 @@ void set_active_window(int index) ToxWindow *init_windows() { - int n_prompt = add_window(m, new_prompt(on_friendadded)); + int n_prompt = add_window(m, new_prompt()); if (n_prompt == -1 || add_window(m, new_friendlist()) == -1 From ccfff8b3051afbd9c1f43e6e1b1d1ba67def2d0f Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sun, 18 Aug 2013 01:48:36 -0700 Subject: [PATCH 147/172] Ran it through astyle --- main.c | 10 +++++----- prompt.c | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/main.c b/main.c index 2da87bc..c89f2f8 100644 --- a/main.c +++ b/main.c @@ -92,11 +92,11 @@ int init_connection(void) if (DHT_isconnected()) return 0; - #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) - FILE *fp = fopen("DHTservers", "r"); - #else - FILE *fp = fopen("~/.tox/DHTservers", "r"); - #endif +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) + FILE *fp = fopen("DHTservers", "r"); +#else + FILE *fp = fopen("~/.tox/DHTservers", "r"); +#endif if (!fp) return 1; diff --git a/prompt.c b/prompt.c index a37fdaa..e6c8851 100644 --- a/prompt.c +++ b/prompt.c @@ -273,6 +273,7 @@ void cmd_nick(ToxWindow *self, Messenger *m, char **args) char *nick = args[1]; setname(m, (uint8_t *) nick, strlen(nick) + 1); wprintw(self->window, "Nickname set to: %s\n", nick); + if (store_data(m, DATA_FILE)) { wprintw(self->window, "\nCould not store Messenger data\n"); } From e5dd681b285229b420e1bc167b821da89c2701b9 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sun, 18 Aug 2013 03:12:55 -0700 Subject: [PATCH 148/172] Added windows support to the standarized location --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index c89f2f8..f9cb1b1 100644 --- a/main.c +++ b/main.c @@ -93,7 +93,7 @@ int init_connection(void) return 0; #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) - FILE *fp = fopen("DHTservers", "r"); + FILE *fp = fopen("%appdata%/.tox/DHTservers", "r"); #else FILE *fp = fopen("~/.tox/DHTservers", "r"); #endif From 145571610903a9d4d6fb1a47db20e605dec68128 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sun, 18 Aug 2013 03:25:18 -0700 Subject: [PATCH 149/172] Added mac support with data, standarized data --- main.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index f9cb1b1..52e810d 100644 --- a/main.c +++ b/main.c @@ -289,12 +289,28 @@ int main(int argc, char *argv[]) config_err = create_user_config_dir(user_config_dir); if (config_err) { - DATA_FILE = strdup("data"); + #if WIN32 + DATA_FILE = strdup("%appdata/.tox/data"); + #else + #if MAC_OSX + DATA_FILE = strdup("~Library/Application Support/data"); + #else + DATA_FILE = strdup("~/.tox/data"); + #endif + #endif } else { DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); strcpy(DATA_FILE, user_config_dir); strcat(DATA_FILE, CONFIGDIR); - strcat(DATA_FILE, "data"); + #if WIN32 + DATA_FILE = strdup("%appdata/.tox/data"); + #else + #if MAC_OSX + DATA_FILE = strdup("~Library/Application Support/data"); + #else + DATA_FILE = strdup("~/.tox/data"); + #endif + #endif } } From 8f244f2b6d98fbafba5904f9b6a1993585d1223c Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sun, 18 Aug 2013 03:41:30 -0700 Subject: [PATCH 150/172] Added mac support to the standardized data file, cleaned up a bit --- main.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/main.c b/main.c index 52e810d..2ce2dbf 100644 --- a/main.c +++ b/main.c @@ -74,10 +74,10 @@ static Messenger *init_tox() m_callback_action(m, on_action, NULL); #ifdef __linux__ setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy")); -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) +#elif win32 setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); #else - setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); + setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); //This implies users of other Unixes are hipsters #endif return m; } @@ -92,8 +92,10 @@ int init_connection(void) if (DHT_isconnected()) return 0; -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) +#if win32 FILE *fp = fopen("%appdata%/.tox/DHTservers", "r"); +#elif MAC_OSX + FILE *fp = fopen("~/Library/Application Support/.tox/DHTservers", "r"); #else FILE *fp = fopen("~/.tox/DHTservers", "r"); #endif @@ -291,26 +293,22 @@ int main(int argc, char *argv[]) if (config_err) { #if WIN32 DATA_FILE = strdup("%appdata/.tox/data"); - #else - #if MAC_OSX + #elif MAC_OSX DATA_FILE = strdup("~Library/Application Support/data"); #else DATA_FILE = strdup("~/.tox/data"); #endif - #endif } else { DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); strcpy(DATA_FILE, user_config_dir); strcat(DATA_FILE, CONFIGDIR); #if WIN32 DATA_FILE = strdup("%appdata/.tox/data"); - #else - #if MAC_OSX + #elif MAC_OSX DATA_FILE = strdup("~Library/Application Support/data"); #else DATA_FILE = strdup("~/.tox/data"); #endif - #endif } } From 4fe94ca403c182dce3dc598eaf0e700df773f771 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sun, 18 Aug 2013 03:44:52 -0700 Subject: [PATCH 151/172] No longer assumes Minix/BSD/AIX users actually use Macs when assigning a default name --- main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 2ce2dbf..73a903d 100644 --- a/main.c +++ b/main.c @@ -76,8 +76,10 @@ static Messenger *init_tox() setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy")); #elif win32 setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); +#elif MAC_OSX + setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); //This used to users of other Unixes are hipsters #else - setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); //This implies users of other Unixes are hipsters + setname(m, (uint8_t *) "Registered Minix user #4", sizeof("Registered Minix user #4")); #endif return m; } From 3c77156d6dc20799361609b7a6242a40140c38a1 Mon Sep 17 00:00:00 2001 From: Sean Qureshi Date: Sun, 18 Aug 2013 05:34:50 -0700 Subject: [PATCH 152/172] Fixed toxic not running --- main.c | 65 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/main.c b/main.c index 73a903d..04f6c4f 100644 --- a/main.c +++ b/main.c @@ -27,6 +27,7 @@ /* Export for use in Callbacks */ char *DATA_FILE = NULL; +char dir[31]; void on_window_resize(int sig) { @@ -35,6 +36,17 @@ void on_window_resize(int sig) clear(); } +void setdir() +{ + #ifdef WIN32 + strcpy(dir, "%appdata%/.tox/"); + #elif defined(MAC_OSX) + strcpy(dir, "~/Library/Application Support/.tox/"); + #elif defined(linux) + strcpy(dir, "~/.tox/"); + #endif +} + static void init_term() { /* Setup terminal */ @@ -72,15 +84,15 @@ static Messenger *init_tox() m_callback_namechange(m, on_nickchange, NULL); m_callback_statusmessage(m, on_statuschange, NULL); m_callback_action(m, on_action, NULL); -#ifdef __linux__ - setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy")); -#elif win32 - setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); -#elif MAC_OSX - setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); //This used to users of other Unixes are hipsters -#else - setname(m, (uint8_t *) "Registered Minix user #4", sizeof("Registered Minix user #4")); -#endif + #ifdef __linux__ + setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy")); + #elif defined(WIN32) + setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); + #elif defined(MAC_OSX) + setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); //This used to users of other Unixes are hipsters + #else + setname(m, (uint8_t *) "Registered Minix user #4", sizeof("Registered Minix user #4")); + #endif return m; } @@ -94,13 +106,13 @@ int init_connection(void) if (DHT_isconnected()) return 0; -#if win32 - FILE *fp = fopen("%appdata%/.tox/DHTservers", "r"); -#elif MAC_OSX - FILE *fp = fopen("~/Library/Application Support/.tox/DHTservers", "r"); -#else - FILE *fp = fopen("~/.tox/DHTservers", "r"); -#endif + #if WIN32 + FILE *fp = fopen("%appdata%/.tox/DHTservers", "r"); + #elif MAC_OSX + FILE *fp = fopen("~/Library/Application Support/.tox/DHTservers", "r"); + #else + FILE *fp = fopen("~/.tox/DHTservers", "r"); + #endif if (!fp) return 1; @@ -267,6 +279,7 @@ static void load_data(Messenger *m, char *path) int main(int argc, char *argv[]) { + setdir(); char *user_config_dir = get_user_config_dir(); int config_err = 0; @@ -293,24 +306,16 @@ int main(int argc, char *argv[]) config_err = create_user_config_dir(user_config_dir); if (config_err) { - #if WIN32 - DATA_FILE = strdup("%appdata/.tox/data"); - #elif MAC_OSX - DATA_FILE = strdup("~Library/Application Support/data"); - #else - DATA_FILE = strdup("~/.tox/data"); - #endif + strcat(DATA_FILE, dir); + DATA_FILE = strdup("data"); + + } else { DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); strcpy(DATA_FILE, user_config_dir); strcat(DATA_FILE, CONFIGDIR); - #if WIN32 - DATA_FILE = strdup("%appdata/.tox/data"); - #elif MAC_OSX - DATA_FILE = strdup("~Library/Application Support/data"); - #else - DATA_FILE = strdup("~/.tox/data"); - #endif + strcat(DATA_FILE, dir); + DATA_FILE = strdup("data"); } } From bb0251a0272c3d79c0e599bbf7de82ac0fc20e0a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 18 Aug 2013 11:59:34 -0400 Subject: [PATCH 153/172] Fixed stack problem. --- main.c | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/main.c b/main.c index 05fabe4..72d8633 100644 --- a/main.c +++ b/main.c @@ -27,7 +27,7 @@ /* Export for use in Callbacks */ char *DATA_FILE = NULL; -char dir[31]; +char dir[256]; void on_window_resize(int sig) { @@ -38,13 +38,13 @@ void on_window_resize(int sig) void setdir() { - #ifdef WIN32 - strcpy(dir, "%appdata%/.tox/"); - #elif defined(MAC_OSX) - strcpy(dir, "~/Library/Application Support/.tox/"); - #elif defined(linux) - strcpy(dir, "~/.tox/"); - #endif +#ifdef WIN32 + strcpy(dir, "%appdata%/.tox/"); +#elif defined(MAC_OSX) + strcpy(dir, "~/Library/Application Support/.tox/"); +#elif defined(linux) + strcpy(dir, "~/.tox/"); +#endif } static void init_term() @@ -84,15 +84,15 @@ static Messenger *init_tox() m_callback_namechange(m, on_nickchange, NULL); m_callback_statusmessage(m, on_statuschange, NULL); m_callback_action(m, on_action, NULL); - #ifdef __linux__ - setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy")); - #elif defined(WIN32) - setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); - #elif defined(MAC_OSX) - setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); //This used to users of other Unixes are hipsters - #else - setname(m, (uint8_t *) "Registered Minix user #4", sizeof("Registered Minix user #4")); - #endif +#ifdef __linux__ + setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy")); +#elif defined(WIN32) + setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); +#elif defined(MAC_OSX) + setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); //This used to users of other Unixes are hipsters +#else + setname(m, (uint8_t *) "Registered Minix user #4", sizeof("Registered Minix user #4")); +#endif return m; } @@ -106,13 +106,13 @@ int init_connection(void) if (DHT_isconnected()) return 0; - #if WIN32 - FILE *fp = fopen("%appdata%/.tox/DHTservers", "r"); - #elif MAC_OSX - FILE *fp = fopen("~/Library/Application Support/.tox/DHTservers", "r"); - #else - FILE *fp = fopen("~/.tox/DHTservers", "r"); - #endif +#if WIN32 + FILE *fp = fopen("%appdata%/.tox/DHTservers", "r"); +#elif MAC_OSX + FILE *fp = fopen("~/Library/Application Support/.tox/DHTservers", "r"); +#else + FILE *fp = fopen("~/.tox/DHTservers", "r"); +#endif if (!fp) return 1; @@ -309,7 +309,7 @@ int main(int argc, char *argv[]) strcat(DATA_FILE, dir); DATA_FILE = strdup("data"); - + } else { DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); strcpy(DATA_FILE, user_config_dir); From 76473ea8b48072acdaaa2b6ebaed18a53c30e35e Mon Sep 17 00:00:00 2001 From: Michael Rose Date: Sun, 18 Aug 2013 21:12:54 +0200 Subject: [PATCH 154/172] fix OS check in toxic --- main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index 72d8633..f2a3560 100644 --- a/main.c +++ b/main.c @@ -40,7 +40,7 @@ void setdir() { #ifdef WIN32 strcpy(dir, "%appdata%/.tox/"); -#elif defined(MAC_OSX) +#elif __APPLE__ strcpy(dir, "~/Library/Application Support/.tox/"); #elif defined(linux) strcpy(dir, "~/.tox/"); @@ -88,7 +88,7 @@ static Messenger *init_tox() setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy")); #elif defined(WIN32) setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); -#elif defined(MAC_OSX) +#elif __APPLE__ setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); //This used to users of other Unixes are hipsters #else setname(m, (uint8_t *) "Registered Minix user #4", sizeof("Registered Minix user #4")); @@ -108,7 +108,7 @@ int init_connection(void) #if WIN32 FILE *fp = fopen("%appdata%/.tox/DHTservers", "r"); -#elif MAC_OSX +#elif __APPLE__ FILE *fp = fopen("~/Library/Application Support/.tox/DHTservers", "r"); #else FILE *fp = fopen("~/.tox/DHTservers", "r"); From 9367508824c4ec49550a7deb783477fab41bae9b Mon Sep 17 00:00:00 2001 From: loadletter Date: Sun, 18 Aug 2013 23:16:39 +0200 Subject: [PATCH 155/172] Use configdir.c instead of hardcoded paths for the list of DHT servers. --- configdir.h | 4 ++-- main.c | 35 ++++++++++++----------------------- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/configdir.h b/configdir.h index 17d9510..e886e53 100644 --- a/configdir.h +++ b/configdir.h @@ -19,9 +19,9 @@ */ #ifdef _win32 -#define CONFIGDIR "\\toxic\\" +#define CONFIGDIR "\\tox\\" #else -#define CONFIGDIR "/toxic/" +#define CONFIGDIR "/tox/" #endif #ifndef S_ISDIR diff --git a/main.c b/main.c index 72d8633..3ed2fa5 100644 --- a/main.c +++ b/main.c @@ -27,7 +27,7 @@ /* Export for use in Callbacks */ char *DATA_FILE = NULL; -char dir[256]; +char *SRVLIST_FILE = NULL; void on_window_resize(int sig) { @@ -36,17 +36,6 @@ void on_window_resize(int sig) clear(); } -void setdir() -{ -#ifdef WIN32 - strcpy(dir, "%appdata%/.tox/"); -#elif defined(MAC_OSX) - strcpy(dir, "~/Library/Application Support/.tox/"); -#elif defined(linux) - strcpy(dir, "~/.tox/"); -#endif -} - static void init_term() { /* Setup terminal */ @@ -103,16 +92,12 @@ static Messenger *init_tox() /* Connects to a random DHT server listed in the DHTservers file */ int init_connection(void) { + FILE *fp = NULL; + if (DHT_isconnected()) return 0; -#if WIN32 - FILE *fp = fopen("%appdata%/.tox/DHTservers", "r"); -#elif MAC_OSX - FILE *fp = fopen("~/Library/Application Support/.tox/DHTservers", "r"); -#else - FILE *fp = fopen("~/.tox/DHTservers", "r"); -#endif + fp = fopen(SRVLIST_FILE, "r"); if (!fp) return 1; @@ -279,7 +264,6 @@ static void load_data(Messenger *m, char *path) int main(int argc, char *argv[]) { - setdir(); char *user_config_dir = get_user_config_dir(); int config_err = 0; @@ -306,16 +290,20 @@ int main(int argc, char *argv[]) config_err = create_user_config_dir(user_config_dir); if (config_err) { - strcat(DATA_FILE, dir); DATA_FILE = strdup("data"); + SRVLIST_FILE = strdup("../../other/DHTservers"); } else { DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); strcpy(DATA_FILE, user_config_dir); strcat(DATA_FILE, CONFIGDIR); - strcat(DATA_FILE, dir); - DATA_FILE = strdup("data"); + strcat(DATA_FILE, "data"); + + SRVLIST_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("DHTservers") + 1); + strcpy(SRVLIST_FILE, user_config_dir); + strcat(SRVLIST_FILE, CONFIGDIR); + strcat(SRVLIST_FILE, "DHTservers"); } } @@ -352,5 +340,6 @@ int main(int argc, char *argv[]) cleanupMessenger(m); free(DATA_FILE); + free(SRVLIST_FILE); return 0; } From 1e0310cfed97977b5ee4fb63b90c7d636806fdee Mon Sep 17 00:00:00 2001 From: Frederik Holden Date: Mon, 19 Aug 2013 01:21:36 +0200 Subject: [PATCH 156/172] Made configdir check XDG_CONFIG_HOME for config dir --- configdir.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/configdir.c b/configdir.c index 1a62e8e..a43dd1d 100644 --- a/configdir.c +++ b/configdir.c @@ -98,14 +98,18 @@ char *get_user_config_dir(void) snprintf(user_config_dir, len, "%s/Library/Application Support", home); # else /* __APPLE__ */ - len = strlen(home) + strlen("/.config") + 1; - user_config_dir = malloc(len); - if (user_config_dir == NULL) { - return NULL; + if (!(user_config_dir = getenv("XDG_CONFIG_HOME"))) { + len = strlen(home) + strlen("/.config") + 1; + user_config_dir = malloc(len); + + if (user_config_dir == NULL) { + return NULL; + } + + snprintf(user_config_dir, len, "%s/.config", home); } - snprintf(user_config_dir, len, "%s/.config", home); # endif /* __APPLE__ */ return user_config_dir; From 4a8146b9433ec511c72c935ed299a61823acdf56 Mon Sep 17 00:00:00 2001 From: Michael Rose Date: Mon, 19 Aug 2013 09:23:40 +0200 Subject: [PATCH 157/172] fix define checks --- main.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/main.c b/main.c index f2a3560..e416525 100644 --- a/main.c +++ b/main.c @@ -40,7 +40,7 @@ void setdir() { #ifdef WIN32 strcpy(dir, "%appdata%/.tox/"); -#elif __APPLE__ +#elif defined(__APPLE__) strcpy(dir, "~/Library/Application Support/.tox/"); #elif defined(linux) strcpy(dir, "~/.tox/"); @@ -88,7 +88,7 @@ static Messenger *init_tox() setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy")); #elif defined(WIN32) setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); -#elif __APPLE__ +#elif defined(__APPLE__) setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); //This used to users of other Unixes are hipsters #else setname(m, (uint8_t *) "Registered Minix user #4", sizeof("Registered Minix user #4")); @@ -108,7 +108,7 @@ int init_connection(void) #if WIN32 FILE *fp = fopen("%appdata%/.tox/DHTservers", "r"); -#elif __APPLE__ +#elif defined(__APPLE__) FILE *fp = fopen("~/Library/Application Support/.tox/DHTservers", "r"); #else FILE *fp = fopen("~/.tox/DHTservers", "r"); @@ -314,8 +314,7 @@ int main(int argc, char *argv[]) DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); strcpy(DATA_FILE, user_config_dir); strcat(DATA_FILE, CONFIGDIR); - strcat(DATA_FILE, dir); - DATA_FILE = strdup("data"); + strcat(DATA_FILE, "data"); } } From 26d691f021a77c17ba6c9ac40a4449b7b97e6638 Mon Sep 17 00:00:00 2001 From: Michael Rose Date: Mon, 19 Aug 2013 10:19:57 +0200 Subject: [PATCH 158/172] fix potential memory issue --- main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/main.c b/main.c index e416525..c4c84ea 100644 --- a/main.c +++ b/main.c @@ -306,10 +306,7 @@ int main(int argc, char *argv[]) config_err = create_user_config_dir(user_config_dir); if (config_err) { - strcat(DATA_FILE, dir); DATA_FILE = strdup("data"); - - } else { DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); strcpy(DATA_FILE, user_config_dir); From 10d97b2942395e195c6ea83abeab98fca5543c1a Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 19 Aug 2013 16:55:04 -0400 Subject: [PATCH 159/172] fix tab bar bugs --- chat.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/chat.c b/chat.c index 67c2ed0..57404a5 100644 --- a/chat.c +++ b/chat.c @@ -123,8 +123,7 @@ static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint1 status[len - 1] = '\0'; fix_name(status); - snprintf(self->title, sizeof(self->title), "[%s (%d)]", status, num); - + wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, "* Your partner changed status to '%s'\n", status); wattroff(ctx->history, COLOR_PAIR(3)); From f017a76c4a7da66a1dcf365b571a2b8d95cfc5d8 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 19 Aug 2013 16:59:24 -0400 Subject: [PATCH 160/172] fix tab bar bugs --- windows.c | 1 + 1 file changed, 1 insertion(+) diff --git a/windows.c b/windows.c index a2c649d..c0ff302 100644 --- a/windows.c +++ b/windows.c @@ -197,6 +197,7 @@ static void draw_bar() if (windows[i].blink && (odd < (blinkrate / 2))) attron(COLOR_PAIR(3)); + clrtoeol(); printw(" %s", windows[i].title); if (windows[i].blink && (odd < (blinkrate / 2))) From 512abe64f44add7f20cef33442578012869efe72 Mon Sep 17 00:00:00 2001 From: Michael Rose Date: Tue, 20 Aug 2013 13:40:15 +0200 Subject: [PATCH 161/172] fixed space handling in commands (issue #495) --- prompt.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/prompt.c b/prompt.c index 473633d..81f00bc 100644 --- a/prompt.c +++ b/prompt.c @@ -363,6 +363,11 @@ static void execute(ToxWindow *self, Messenger *m, char *u_cmd) if (cmd[i] == ' ') { cmd[i] = '\0'; + + int j = i; + while (++j < MAX_STR_SIZE && isspace(cmd[j])); + i = j - 1; + numargs++; } } @@ -380,6 +385,9 @@ static void execute(ToxWindow *self, Messenger *m, char *u_cmd) for (i = 0; i < 5; i++) { cmdargs[i] = cmd + pos; pos += strlen(cmdargs[i]) + 1; + + while (isspace(cmd[pos]) && pos < MAX_STR_SIZE) + ++pos; } /* no input */ From da369f150772e188e2e41f3838911a59c1a26b24 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 20 Aug 2013 12:08:55 -0400 Subject: [PATCH 162/172] More refactoring done. --- dhtstatus.c | 2 +- main.c | 14 +++++++------- prompt.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dhtstatus.c b/dhtstatus.c index a11dc61..c7a57c7 100644 --- a/dhtstatus.c +++ b/dhtstatus.c @@ -36,7 +36,7 @@ static void dhtstatus_onKey(ToxWindow *self, Messenger *m, int key) static void dhtstatus_onDraw(ToxWindow *self) { - Client_data *close_clientlist = DHT_get_close_list(); + Client_data *close_clientlist = DHT_get_close_list(temp_DHT); curs_set(0); werase(self->window); diff --git a/main.c b/main.c index 9abe8de..6f6c9db 100644 --- a/main.c +++ b/main.c @@ -90,11 +90,11 @@ static Messenger *init_tox() #define MAXSERVERS 50 /* Connects to a random DHT server listed in the DHTservers file */ -int init_connection(void) +int init_connection(Messenger *m) { FILE *fp = NULL; - if (DHT_isconnected()) + if (DHT_isconnected(m->dht)) return 0; fp = fopen(SRVLIST_FILE, "r"); @@ -135,7 +135,7 @@ int init_connection(void) dht.ip.i = resolved_address; unsigned char *binary_string = hex_string_to_bin(key); - DHT_bootstrap(dht, binary_string); + DHT_bootstrap(m->dht, dht, binary_string); free(binary_string); return 0; } @@ -146,18 +146,18 @@ static void do_tox(Messenger *m, ToxWindow *prompt) static int conn_err = 0; static bool dht_on = false; - if (!dht_on && !DHT_isconnected() && !(conn_try++ % 100)) { + if (!dht_on && !DHT_isconnected(m->dht) && !(conn_try++ % 100)) { if (!conn_err) { - conn_err = init_connection(); + conn_err = init_connection(m); wprintw(prompt->window, "\nEstablishing connection...\n"); if (conn_err) wprintw(prompt->window, "\nAuto-connect failed with error code %d\n", conn_err); } - } else if (!dht_on && DHT_isconnected()) { + } else if (!dht_on && DHT_isconnected(m->dht)) { dht_on = true; wprintw(prompt->window, "\nDHT connected.\n"); - } else if (dht_on && !DHT_isconnected()) { + } else if (dht_on && !DHT_isconnected(m->dht)) { dht_on = false; wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n"); } diff --git a/prompt.c b/prompt.c index 81f00bc..204cd7e 100644 --- a/prompt.c +++ b/prompt.c @@ -204,7 +204,7 @@ void cmd_connect(ToxWindow *self, Messenger *m, char **args) dht.ip.i = resolved_address; unsigned char *binary_string = hex_string_to_bin(key); - DHT_bootstrap(dht, binary_string); + DHT_bootstrap(m->dht, dht, binary_string); free(binary_string); } From 05fd02767fd583108731a06cc15fcd033ef0186b Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 20 Aug 2013 14:47:32 -0400 Subject: [PATCH 163/172] Refactor of core done. --- chat.c | 2 +- dhtstatus.c | 4 ++-- friendlist.c | 2 +- prompt.c | 2 +- windows.c | 2 +- windows.h | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/chat.c b/chat.c index 57404a5..d3e68ec 100644 --- a/chat.c +++ b/chat.c @@ -342,7 +342,7 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) wprintw(ctx->history, "Invalid command.\n"); } -static void chat_onDraw(ToxWindow *self) +static void chat_onDraw(ToxWindow *self, Messenger *m) { curs_set(1); int x, y; diff --git a/dhtstatus.c b/dhtstatus.c index c7a57c7..6c9f2a8 100644 --- a/dhtstatus.c +++ b/dhtstatus.c @@ -34,9 +34,9 @@ static void dhtstatus_onKey(ToxWindow *self, Messenger *m, int key) } } -static void dhtstatus_onDraw(ToxWindow *self) +static void dhtstatus_onDraw(ToxWindow *self, Messenger *m) { - Client_data *close_clientlist = DHT_get_close_list(temp_DHT); + Client_data *close_clientlist = DHT_get_close_list(m->dht); curs_set(0); werase(self->window); diff --git a/friendlist.c b/friendlist.c index 0a58bc5..2e46f12 100644 --- a/friendlist.c +++ b/friendlist.c @@ -102,7 +102,7 @@ static void friendlist_onKey(ToxWindow *self, Messenger *m, int key) } } -static void friendlist_onDraw(ToxWindow *self) +static void friendlist_onDraw(ToxWindow *self, Messenger *m) { curs_set(0); werase(self->window); diff --git a/prompt.c b/prompt.c index 204cd7e..12f8a20 100644 --- a/prompt.c +++ b/prompt.c @@ -460,7 +460,7 @@ static void prompt_onKey(ToxWindow *self, Messenger *m, int key) } } -static void prompt_onDraw(ToxWindow *self) +static void prompt_onDraw(ToxWindow *self, Messenger *m) { curs_set(1); int x, y; diff --git a/windows.c b/windows.c index c0ff302..de92432 100644 --- a/windows.c +++ b/windows.c @@ -225,7 +225,7 @@ void draw_active_window(Messenger *m) prepare_window(a->window); a->blink = false; draw_bar(); - a->onDraw(a); + a->onDraw(a, m); /* Handle input */ int ch = getch(); diff --git a/windows.h b/windows.h index be5557e..86917db 100644 --- a/windows.h +++ b/windows.h @@ -24,7 +24,7 @@ typedef struct ToxWindow_ ToxWindow; struct ToxWindow_ { void(*onKey)(ToxWindow *, Messenger *, int); - void(*onDraw)(ToxWindow *); + void(*onDraw)(ToxWindow *, Messenger *); void(*onInit)(ToxWindow *, Messenger *); void(*onFriendRequest)(ToxWindow *, uint8_t *, uint8_t *, uint16_t); void(*onMessage)(ToxWindow *, Messenger *, int, uint8_t *, uint16_t); From 43d0d7a1c0638e307660abce7740515039f21686 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 20 Aug 2013 19:37:05 -0400 Subject: [PATCH 164/172] astyle --options=tools/astylerc -r ./*.{c,h} --- chat.c | 2 +- main.c | 4 ++-- prompt.c | 2 ++ windows.c | 46 +++++++++++++++++++++++++--------------------- 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/chat.c b/chat.c index d3e68ec..c797984 100644 --- a/chat.c +++ b/chat.c @@ -123,7 +123,7 @@ static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint1 status[len - 1] = '\0'; fix_name(status); - + wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, "* Your partner changed status to '%s'\n", status); wattroff(ctx->history, COLOR_PAIR(3)); diff --git a/main.c b/main.c index 6f6c9db..e5525e9 100644 --- a/main.c +++ b/main.c @@ -93,7 +93,7 @@ static Messenger *init_tox() int init_connection(Messenger *m) { FILE *fp = NULL; - + if (DHT_isconnected(m->dht)) return 0; @@ -297,7 +297,7 @@ int main(int argc, char *argv[]) strcpy(DATA_FILE, user_config_dir); strcat(DATA_FILE, CONFIGDIR); strcat(DATA_FILE, "data"); - + SRVLIST_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("DHTservers") + 1); strcpy(SRVLIST_FILE, user_config_dir); strcat(SRVLIST_FILE, CONFIGDIR); diff --git a/prompt.c b/prompt.c index 12f8a20..e194a90 100644 --- a/prompt.c +++ b/prompt.c @@ -365,7 +365,9 @@ static void execute(ToxWindow *self, Messenger *m, char *u_cmd) cmd[i] = '\0'; int j = i; + while (++j < MAX_STR_SIZE && isspace(cmd[j])); + i = j - 1; numargs++; diff --git a/windows.c b/windows.c index de92432..8fdf4e1 100644 --- a/windows.c +++ b/windows.c @@ -88,23 +88,25 @@ int add_window(Messenger *m, ToxWindow w) { if (LINES < 2) return -1; - + int i; - for(i = 0; i < MAX_WINDOWS_NUM; i++) { - if (windows[i].window) + + for (i = 0; i < MAX_WINDOWS_NUM; i++) { + if (windows[i].window) continue; - + w.window = newwin(LINES - 2, COLS, 0, 0); + if (w.window == NULL) return -1; windows[i] = w; w.onInit(&w, m); - - active_window = windows+i; + + active_window = windows + i; return i; } - + return -1; } @@ -113,8 +115,10 @@ void del_window(ToxWindow *w) { active_window = windows; // Go to prompt screen delwin(w->window); + if (w->x) free(w->x); + w->window = NULL; memset(w, 0, sizeof(ToxWindow)); clear(); @@ -124,19 +128,19 @@ void del_window(ToxWindow *w) /* Shows next window when tab or back-tab is pressed */ void set_next_window(int ch) { - ToxWindow *end = windows+MAX_WINDOWS_NUM-1; + ToxWindow *end = windows + MAX_WINDOWS_NUM - 1; ToxWindow *inf = active_window; - while(true) { + + while (true) { if (ch == '\t') { if (++active_window > end) active_window = windows; - } else - if (--active_window < windows) - active_window = end; - + } else if (--active_window < windows) + active_window = end; + if (active_window->window) return; - + if (active_window == inf) { // infinite loop check endwin(); exit(2); @@ -148,14 +152,14 @@ void set_active_window(int index) { if (index < 0 || index >= MAX_WINDOWS_NUM) return; - - active_window = windows+index; + + active_window = windows + index; } ToxWindow *init_windows() { int n_prompt = add_window(m, new_prompt()); - + if (n_prompt == -1 || add_window(m, new_friendlist()) == -1 || add_window(m, new_dhtstatus()) == -1) { @@ -166,7 +170,7 @@ ToxWindow *init_windows() prompt = &windows[n_prompt]; active_window = prompt; - + return prompt; } @@ -189,7 +193,7 @@ static void draw_bar() for (i = 0; i < (MAX_WINDOWS_NUM); ++i) { if (windows[i].window) { - if (windows+i == active_window) + if (windows + i == active_window) attron(A_BOLD); odd = (odd + 1) % blinkrate; @@ -197,13 +201,13 @@ static void draw_bar() if (windows[i].blink && (odd < (blinkrate / 2))) attron(COLOR_PAIR(3)); - clrtoeol(); + clrtoeol(); printw(" %s", windows[i].title); if (windows[i].blink && (odd < (blinkrate / 2))) attroff(COLOR_PAIR(3)); - if (windows+i == active_window) { + if (windows + i == active_window) { attroff(A_BOLD); } } From c31cdf53eb8f2ca9d754642fbb43a41fd74a98a4 Mon Sep 17 00:00:00 2001 From: Sanket Parmar Date: Wed, 21 Aug 2013 23:24:11 +0530 Subject: [PATCH 165/172] Fixed segfault and added support for single quotes in toxic --- prompt.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/prompt.c b/prompt.c index e194a90..6c762c8 100644 --- a/prompt.c +++ b/prompt.c @@ -358,8 +358,16 @@ static void execute(ToxWindow *self, Messenger *m, char *u_cmd) int numargs = 0; for (i = 0; i < MAX_STR_SIZE; i++) { - if (cmd[i] == '\"') - while (cmd[++i] != '\"'); /* skip over strings */ + char quote_chr; + if (cmd[i] == '\"' || cmd[i] == '\'') { + quote_chr = cmd[i]; + while (cmd[++i] != quote_chr && i < MAX_STR_SIZE); /* skip over strings */ + /* Check if got qoute character */ + if (cmd[i] != quote_chr) { + wprintw(self->window, "Missing terminating %c character\n", quote_chr); + return; + } + } if (cmd[i] == ' ') { cmd[i] = '\0'; From 46b69e6db162249961e8371b483289da706f22b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Arg=C3=BCelles?= Date: Wed, 21 Aug 2013 13:56:07 -0500 Subject: [PATCH 166/172] Add cmake module for ncursesw Default Curses module fails to detect the wide char version of curses when both are installed. Current module should do better. --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ee7020..53316af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,9 @@ add_executable(${exe_name} chat.c configdir.c) +include_directories(${CURSES_INCLUDE_DIR}) + target_link_libraries(${exe_name} - curses) + ${CURSES_LIBRARIES}) linkCoreLibraries(${exe_name}) From 422a89d32db82dcd0c2ec220dcc9833b27a7cb10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Arg=C3=BCelles?= Date: Wed, 21 Aug 2013 16:19:35 -0500 Subject: [PATCH 167/172] Add wide char support in toxic (issue #440) Set current locale, use of get_wch instead of getch for reading, use wctomb and friends to convert back from wchar_t, link with cursesw. Unicode support is only added to chat windows. --- chat.c | 67 ++++++++++++++++++++++++++++++++++++++++------------ dhtstatus.c | 2 +- friendlist.c | 3 +-- main.c | 3 +++ prompt.c | 3 +-- windows.c | 6 +++-- windows.h | 5 +++- 7 files changed, 66 insertions(+), 23 deletions(-) diff --git a/chat.c b/chat.c index c797984..3e34285 100644 --- a/chat.c +++ b/chat.c @@ -2,12 +2,12 @@ * Toxic -- Tox Curses Client */ -#include #include #include #include #include #include +#include #include "../../core/Messenger.h" #include "../../core/network.h" @@ -20,7 +20,7 @@ typedef struct { int friendnum; - char line[MAX_STR_SIZE]; + wchar_t line[MAX_STR_SIZE]; size_t pos; WINDOW *history; WINDOW *linewin; @@ -50,7 +50,6 @@ static void chat_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *msg, getname(m, num, (uint8_t *) &nick); msg[len - 1] = '\0'; nick[MAX_NAME_LENGTH - 1] = '\0'; - fix_name(msg); fix_name(nick); wattron(ctx->history, COLOR_PAIR(2)); @@ -140,7 +139,43 @@ int string_is_empty(char *string) return rc; } -static void chat_onKey(ToxWindow *self, Messenger *m, int key) +/* convert wide characters to null terminated string */ +static char *wcs_to_char(wchar_t *string) +{ + size_t len = 0; + char *ret = NULL; + + len = wcstombs(NULL, string, 0); + if (len != (size_t) -1) { + len++; + ret = malloc(len); + wcstombs(ret, string, len); + } else { + ret = malloc(2); + ret[0] = ' '; + ret[1] = '\0'; + } + return ret; +} + +/* convert a wide char to null terminated string */ +static char *wc_to_char(wchar_t ch) +{ + int len = 0; + static char ret[MB_LEN_MAX + 1]; + + len = wctomb(ret, ch); + if (len == -1) { + ret[0] = ' '; + ret[1] = '\0'; + } else { + ret[len] = '\0'; + } + + return ret; +} + +static void chat_onKey(ToxWindow *self, Messenger *m, wint_t key) { ChatContext *ctx = (ChatContext *) self->x; struct tm *timeinfo = get_time(); @@ -150,18 +185,18 @@ static void chat_onKey(ToxWindow *self, Messenger *m, int key) getmaxyx(self->window, y2, x2); /* Add printable chars to buffer and print on input space */ - if (isprint(key)) { + if (iswprint(key)) { if (ctx->pos != sizeof(ctx->line) - 1) { - mvwaddch(self->window, y, x, key); + mvwaddstr(self->window, y, x, wc_to_char(key)); ctx->line[ctx->pos++] = key; - ctx->line[ctx->pos] = '\0'; + ctx->line[ctx->pos] = L'\0'; } } /* BACKSPACE key: Remove one character from line */ else if (key == 0x107 || key == 0x8 || key == 0x7f) { if (ctx->pos > 0) { - ctx->line[--ctx->pos] = '\0'; + ctx->line[--ctx->pos] = L'\0'; if (x == 0) mvwdelch(self->window, y - 1, x2 - 1); @@ -172,15 +207,16 @@ static void chat_onKey(ToxWindow *self, Messenger *m, int key) /* RETURN key: Execute command or print line */ else if (key == '\n') { + char *line = wcs_to_char(ctx->line); wclear(ctx->linewin); wmove(self->window, y2 - CURS_Y_OFFSET, 0); wclrtobot(self->window); - if (ctx->line[0] == '/') - execute(self, ctx, m, ctx->line); + if (line[0] == '/') + execute(self, ctx, m, line); else { /* make sure the string has at least non-space character */ - if (!string_is_empty(ctx->line)) { + if (!string_is_empty(line)) { uint8_t selfname[MAX_NAME_LENGTH]; getself_name(m, selfname, sizeof(selfname)); fix_name(selfname); @@ -191,9 +227,9 @@ static void chat_onKey(ToxWindow *self, Messenger *m, int key) wattron(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "%s: ", selfname); wattroff(ctx->history, COLOR_PAIR(1)); - wprintw(ctx->history, "%s\n", ctx->line); + wprintw(ctx->history, "%s\n", line); - if (m_sendmessage(m, ctx->friendnum, (uint8_t *) ctx->line, strlen(ctx->line) + 1) == 0) { + if (m_sendmessage(m, ctx->friendnum, (uint8_t *) line, strlen(line) + 1) == 0) { wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Failed to send message.\n"); wattroff(ctx->history, COLOR_PAIR(3)); @@ -201,8 +237,9 @@ static void chat_onKey(ToxWindow *self, Messenger *m, int key) } } - ctx->line[0] = '\0'; + ctx->line[0] = L'\0'; ctx->pos = 0; + free(line); } } @@ -331,7 +368,7 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) wprintw(ctx->history, "%s\n", id); } - else if (strcmp(ctx->line, "/close") == 0) { + else if (strcmp(cmd, "/close") == 0) { int f_num = ctx->friendnum; delwin(ctx->linewin); del_window(self); diff --git a/dhtstatus.c b/dhtstatus.c index 6c9f2a8..3330077 100644 --- a/dhtstatus.c +++ b/dhtstatus.c @@ -11,7 +11,7 @@ static void printip(ipbuf buf, IP ip) sprintf((char *)buf, "%u.%u.%u.%u", ip.c[0], ip.c[1], ip.c[2], ip.c[3]); } -static void dhtstatus_onKey(ToxWindow *self, Messenger *m, int key) +static void dhtstatus_onKey(ToxWindow *self, Messenger *m, wint_t key) { switch (key) { case KEY_UP: diff --git a/friendlist.c b/friendlist.c index 2e46f12..72b1da9 100644 --- a/friendlist.c +++ b/friendlist.c @@ -2,7 +2,6 @@ * Toxic -- Tox Curses Client */ -#include #include #include #include @@ -84,7 +83,7 @@ int friendlist_onFriendAdded(Messenger *m, int num) return 0; } -static void friendlist_onKey(ToxWindow *self, Messenger *m, int key) +static void friendlist_onKey(ToxWindow *self, Messenger *m, wint_t key) { if (key == KEY_UP) { if (--num_selected < 0) diff --git a/main.c b/main.c index e5525e9..12b529f 100644 --- a/main.c +++ b/main.c @@ -2,6 +2,7 @@ * Toxic -- Tox Curses Client */ +#define _XOPEN_SOURCE_EXTENDED #include #include #include @@ -9,6 +10,7 @@ #include #include #include +#include #ifdef _win32 #include @@ -40,6 +42,7 @@ static void init_term() { /* Setup terminal */ signal(SIGWINCH, on_window_resize); + setlocale(LC_ALL, ""); initscr(); cbreak(); keypad(stdscr, 1); diff --git a/prompt.c b/prompt.c index e194a90..d210023 100644 --- a/prompt.c +++ b/prompt.c @@ -5,7 +5,6 @@ #include #include #include -#include #include "../../core/Messenger.h" #include "../../core/network.h" @@ -426,7 +425,7 @@ static void execute(ToxWindow *self, Messenger *m, char *u_cmd) wprintw(self->window, "Invalid command.\n"); } -static void prompt_onKey(ToxWindow *self, Messenger *m, int key) +static void prompt_onKey(ToxWindow *self, Messenger *m, wint_t key) { /* Add printable characters to line */ if (isprint(key)) { diff --git a/windows.c b/windows.c index 8fdf4e1..f50bdc2 100644 --- a/windows.c +++ b/windows.c @@ -226,16 +226,18 @@ void draw_active_window(Messenger *m) { ToxWindow *a = active_window; + wint_t ch = 0; + prepare_window(a->window); a->blink = false; draw_bar(); a->onDraw(a, m); /* Handle input */ - int ch = getch(); + get_wch(&ch); if (ch == '\t' || ch == KEY_BTAB) - set_next_window(ch); + set_next_window((int) ch); else if (ch != ERR) a->onKey(a, m, ch); } diff --git a/windows.h b/windows.h index 86917db..227040b 100644 --- a/windows.h +++ b/windows.h @@ -4,9 +4,12 @@ #ifndef _windows_h #define _windows_h +#define _XOPEN_SOURCE_EXTENDED #include #include #include +#include +#include #include "../../core/Messenger.h" #define MAX_WINDOWS_NUM 32 #define MAX_FRIENDS_NUM 100 @@ -23,7 +26,7 @@ typedef struct ToxWindow_ ToxWindow; struct ToxWindow_ { - void(*onKey)(ToxWindow *, Messenger *, int); + void(*onKey)(ToxWindow *, Messenger *, wint_t); void(*onDraw)(ToxWindow *, Messenger *); void(*onInit)(ToxWindow *, Messenger *); void(*onFriendRequest)(ToxWindow *, uint8_t *, uint8_t *, uint16_t); From 11404240ce24ab751c551b507e4f6086336f19fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Arg=C3=BCelles?= Date: Wed, 21 Aug 2013 16:24:33 -0500 Subject: [PATCH 168/172] Remove fix_name() function With unicode support this function is not longer valid. --- chat.c | 7 +------ friendlist.c | 17 ----------------- friendlist.h | 1 - 3 files changed, 1 insertion(+), 24 deletions(-) diff --git a/chat.c b/chat.c index 3e34285..c7a0f98 100644 --- a/chat.c +++ b/chat.c @@ -50,7 +50,6 @@ static void chat_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *msg, getname(m, num, (uint8_t *) &nick); msg[len - 1] = '\0'; nick[MAX_NAME_LENGTH - 1] = '\0'; - fix_name(nick); wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); @@ -73,7 +72,6 @@ static void chat_onAction(ToxWindow *self, Messenger *m, int num, uint8_t *actio return; action[len - 1] = '\0'; - fix_name(action); wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); @@ -100,7 +98,6 @@ static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t wattroff(ctx->history, COLOR_PAIR(2)); nick[len - 1] = '\0'; - fix_name(nick); snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num); wattron(ctx->history, COLOR_PAIR(3)); @@ -121,7 +118,7 @@ static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint1 wattroff(ctx->history, COLOR_PAIR(2)); status[len - 1] = '\0'; - fix_name(status); + snprintf(self->title, sizeof(self->title), "[%s (%d)]", status, num); wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, "* Your partner changed status to '%s'\n", status); @@ -219,7 +216,6 @@ static void chat_onKey(ToxWindow *self, Messenger *m, wint_t key) if (!string_is_empty(line)) { uint8_t selfname[MAX_NAME_LENGTH]; getself_name(m, selfname, sizeof(selfname)); - fix_name(selfname); wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); @@ -435,7 +431,6 @@ ToxWindow new_chat(Messenger *m, int friendnum) uint8_t nick[MAX_NAME_LENGTH] = {0}; getname(m, friendnum, (uint8_t *) &nick); - fix_name(nick); snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum); diff --git a/friendlist.c b/friendlist.c index 72b1da9..8fa3b47 100644 --- a/friendlist.c +++ b/friendlist.c @@ -24,21 +24,6 @@ static friend_t friends[MAX_FRIENDS_NUM]; static int num_friends = 0; static int num_selected = 0; -void fix_name(uint8_t *name) -{ - /* Remove all non alphanumeric characters */ - uint8_t *p = name; - uint8_t *q = name; - - while (*p != 0) { - if (isprint(*p)) - *q++ = *p; - - p++; - } - - *q = 0; -} void friendlist_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *str, uint16_t len) { @@ -57,7 +42,6 @@ void friendlist_onNickChange(ToxWindow *self, int num, uint8_t *str, uint16_t le memcpy((char *) &friends[num].name, (char *) str, len); friends[num].name[len] = 0; - fix_name(friends[num].name); } void friendlist_onStatusChange(ToxWindow *self, int num, uint8_t *str, uint16_t len) @@ -67,7 +51,6 @@ void friendlist_onStatusChange(ToxWindow *self, int num, uint8_t *str, uint16_t memcpy((char *) &friends[num].status, (char *) str, len); friends[num].status[len] = 0; - fix_name(friends[num].status); } int friendlist_onFriendAdded(Messenger *m, int num) diff --git a/friendlist.h b/friendlist.h index 91b917f..6f045d4 100644 --- a/friendlist.h +++ b/friendlist.h @@ -7,6 +7,5 @@ ToxWindow new_friendlist(); int friendlist_onFriendAdded(Messenger *m, int num); void disable_chatwin(int f_num); -void fix_name(uint8_t *name); #endif /* end of include guard: FRIENDLIST_H_53I41IM */ From 43372f09a6c8ebef1f0856a1f05a6666b0cae847 Mon Sep 17 00:00:00 2001 From: Sergey 'Jin' Bostandzhyan Date: Thu, 22 Aug 2013 23:57:20 +0300 Subject: [PATCH 169/172] Move sources to an own subdirectory --- CMakeLists.txt => src/CMakeLists.txt | 0 chat.c => src/chat.c | 0 chat.h => src/chat.h | 0 configdir.c => src/configdir.c | 0 configdir.h => src/configdir.h | 0 dhtstatus.c => src/dhtstatus.c | 0 dhtstatus.h => src/dhtstatus.h | 0 friendlist.c => src/friendlist.c | 0 friendlist.h => src/friendlist.h | 0 main.c => src/main.c | 0 prompt.c => src/prompt.c | 0 prompt.h => src/prompt.h | 0 windows.c => src/windows.c | 0 windows.h => src/windows.h | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename CMakeLists.txt => src/CMakeLists.txt (100%) rename chat.c => src/chat.c (100%) rename chat.h => src/chat.h (100%) rename configdir.c => src/configdir.c (100%) rename configdir.h => src/configdir.h (100%) rename dhtstatus.c => src/dhtstatus.c (100%) rename dhtstatus.h => src/dhtstatus.h (100%) rename friendlist.c => src/friendlist.c (100%) rename friendlist.h => src/friendlist.h (100%) rename main.c => src/main.c (100%) rename prompt.c => src/prompt.c (100%) rename prompt.h => src/prompt.h (100%) rename windows.c => src/windows.c (100%) rename windows.h => src/windows.h (100%) diff --git a/CMakeLists.txt b/src/CMakeLists.txt similarity index 100% rename from CMakeLists.txt rename to src/CMakeLists.txt diff --git a/chat.c b/src/chat.c similarity index 100% rename from chat.c rename to src/chat.c diff --git a/chat.h b/src/chat.h similarity index 100% rename from chat.h rename to src/chat.h diff --git a/configdir.c b/src/configdir.c similarity index 100% rename from configdir.c rename to src/configdir.c diff --git a/configdir.h b/src/configdir.h similarity index 100% rename from configdir.h rename to src/configdir.h diff --git a/dhtstatus.c b/src/dhtstatus.c similarity index 100% rename from dhtstatus.c rename to src/dhtstatus.c diff --git a/dhtstatus.h b/src/dhtstatus.h similarity index 100% rename from dhtstatus.h rename to src/dhtstatus.h diff --git a/friendlist.c b/src/friendlist.c similarity index 100% rename from friendlist.c rename to src/friendlist.c diff --git a/friendlist.h b/src/friendlist.h similarity index 100% rename from friendlist.h rename to src/friendlist.h diff --git a/main.c b/src/main.c similarity index 100% rename from main.c rename to src/main.c diff --git a/prompt.c b/src/prompt.c similarity index 100% rename from prompt.c rename to src/prompt.c diff --git a/prompt.h b/src/prompt.h similarity index 100% rename from prompt.h rename to src/prompt.h diff --git a/windows.c b/src/windows.c similarity index 100% rename from windows.c rename to src/windows.c diff --git a/windows.h b/src/windows.h similarity index 100% rename from windows.h rename to src/windows.h From 95312642f4a6189e387c3e6f3bf080a135e40bd0 Mon Sep 17 00:00:00 2001 From: Sergey 'Jin' Bostandzhyan Date: Fri, 23 Aug 2013 01:09:23 +0300 Subject: [PATCH 170/172] Renamed windows.h header to avoid conflict on Win32 winsock2.h includes windows.h as well, if for some reason our windows.h is chosen first then we will run into errors. --- src/{windows.h => toxic_windows.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{windows.h => toxic_windows.h} (100%) diff --git a/src/windows.h b/src/toxic_windows.h similarity index 100% rename from src/windows.h rename to src/toxic_windows.h From c157837f9747289eb319b3890eb1c491044b1dc0 Mon Sep 17 00:00:00 2001 From: Sergey 'Jin' Bostandzhyan Date: Fri, 23 Aug 2013 01:18:53 +0300 Subject: [PATCH 171/172] Added autotools based build scripts Limitations: currently the tox core library does not ship proper public headers, so we'll have to tell the configure script where the headers are (i.e. directory in the ProjectTox-Core source tree. Since these headers are not really public, they include sodium.h, so right now the toxic configure script will check for sodium.h as well. We also need to look for the libsodium library for linking vs Tox core. --- .gitignore | 27 ++ AUTHORS | 0 COPYING | 674 ++++++++++++++++++++++++++++++++++++++++++++ ChangeLog | 0 INSTALL | 365 ++++++++++++++++++++++++ Makefile.am | 4 + NEWS | 0 README | 0 build/Makefile.am | 30 ++ configure.ac | 294 +++++++++++++++++++ m4/pkg.m4 | 199 +++++++++++++ src/chat.c | 6 +- src/dhtstatus.c | 4 +- src/dhtstatus.h | 2 +- src/friendlist.c | 5 +- src/friendlist.h | 2 +- src/main.c | 6 +- src/prompt.c | 5 +- src/prompt.h | 2 +- src/toxic_windows.h | 2 +- src/windows.c | 2 +- 21 files changed, 1610 insertions(+), 19 deletions(-) create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100644 build/Makefile.am create mode 100644 configure.ac create mode 100644 m4/pkg.m4 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..69a7bdb --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +.DS_Store +*~ +*.swp +*.o +*.lo +*.a +*.exe +*.out +*.app +*.swp +*.la +m4/* +!m4/pkg.m4 +configure +configure_aux +Makefile.in +aclocal.m4 +config.h* +config.log +config.status +stamp-h1 +autom4te.cache +.deps +.libs +*.orig +build/toxic +Makefile diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e69de29 diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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. + + This program 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 this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..7d1c323 --- /dev/null +++ b/INSTALL @@ -0,0 +1,365 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007, 2008, 2009 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..e67ff9d --- /dev/null +++ b/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = build + +ACLOCAL_AMFLAGS = -I m4 + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/build/Makefile.am b/build/Makefile.am new file mode 100644 index 0000000..a4c19ed --- /dev/null +++ b/build/Makefile.am @@ -0,0 +1,30 @@ +bin_PROGRAMS = toxic + + +toxic_SOURCES = $(top_srcdir)/src/main.c \ + $(top_srcdir)/src/chat.h \ + $(top_srcdir)/src/chat.c \ + $(top_srcdir)/src/configdir.h \ + $(top_srcdir)/src/configdir.c \ + $(top_srcdir)/src/prompt.h \ + $(top_srcdir)/src/prompt.c \ + $(top_srcdir)/src/friendlist.h \ + $(top_srcdir)/src/friendlist.c \ + $(top_srcdir)/src/toxic_windows.h \ + $(top_srcdir)/src/windows.c \ + $(top_srcdir)/src/dhtstatus.h \ + $(top_srcdir)/src/dhtstatus.c + +toxic_CFLAGS = $(NCURSES_CFLAGS) \ + $(LIBSODIUM_CFLAGS) \ + $(LIBTOXCORE_CFLAGS) + +toxic_CPPFLAGS = '-DTOXICVER="$(TOXIC_VERSION)"' + +toxic_LDADD = $(LIBTOXCORE_LDFLAGS) \ + $(LIBSODIUM_LDFLAGS) \ + $(NCURSES_LIBS) \ + $(LIBTOXCORE_LIBS) \ + $(LIBSODIUM_LIBS) \ + $(WINSOCK2_LIBS) + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..e60f00b --- /dev/null +++ b/configure.ac @@ -0,0 +1,294 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.65]) +AC_INIT([toxic], [0.1.1], [http://tox.im/]) +AC_CONFIG_AUX_DIR(configure_aux) +AC_CONFIG_SRCDIR([src/main.c]) +AC_CONFIG_HEADERS([config.h]) +AM_INIT_AUTOMAKE([1.10 -Wall]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) +AC_CONFIG_MACRO_DIR([m4]) + +if test "x${prefix}" = "xNONE"; then + prefix="${ac_default_prefix}" +fi + +DEPSEARCH= +LIBTOXCORE_SEARCH_HEADERS= +LIBTOXCORE_SEARCH_LIBS= +LIBSODIUM_SEARCH_HEADERS= +LIBSODIUM_SEARCH_LIBS= + +AC_ARG_WITH(dependency-search, + AC_HELP_STRING([--with-dependency-search=DIR], + [search for dependencies in DIR, i.e. look for libraries in + DIR/lib and for headers in DIR/include]), + [ + DEPSEARCH="$withval" + ] +) + +if test -n "$DEPSEARCH"; then + CFLAGS="$CFLAGS -I$DEPSEARCH/include" + CPPFLAGS="$CPPFLAGS -I$DEPSEARCH/include" + LDFLAGS="$LDFLAGS -L$DEPSEARCH/lib" + export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$DEPSEARCH/lib/pkgconfig +fi + +AC_ARG_WITH(libtoxcore-headers, + AC_HELP_STRING([--with-libtoxcore-headers=DIR], + [search for libtoxcore header files in DIR]), + [ + LIBTOXCORE_SEARCH_HEADERS="$withval" + AC_MSG_NOTICE([Will search for libtoxcore header files in $withval]) + ] +) + +AC_ARG_WITH(libtoxcore-libs, + AC_HELP_STRING([--with-libtoxcore-libs=DIR], + [search for libtoxcore libraries in DIR]), + [ + LIBTOXCORE_SEARCH_LIBS="$withval" + AC_MSG_NOTICE([Will search for libtoxcore libraries in $withval]) + ] +) + +AC_ARG_WITH(libsodium-headers, + AC_HELP_STRING([--with-libsodium-headers=DIR], + [search for libsodium header files in DIR]), + [ + LIBSODIUM_SEARCH_HEADERS="$withval" + AC_MSG_NOTICE([Will search for libsodium header files in $withval]) + ] +) + +AC_ARG_WITH(libsodium-libs, + AC_HELP_STRING([--with-libsodium-libs=DIR], + [search for libsodium libraries in DIR]), + [ + LIBSODIUM_SEARCH_LIBS="$withval" + AC_MSG_NOTICE([Will search for libsodium libraries in $withval]) + ] +) + +WIN32=no +AC_CANONICAL_HOST +case $host_os in + *mingw*) + WIN32="yes" + ;; +esac + + +# Checks for programs. +AC_PROG_CC +AM_PROG_CC_C_O + +AC_CHECK_HEADERS( + [limits.h locale.h stdint.h stdlib.h string.h unistd.h wchar.h wctype.h], + [], + [ AC_MSG_ERROR([required header is missing on your system]) ]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_STDBOOL +AC_TYPE_SIZE_T +AC_TYPE_UINT16_T +AC_TYPE_UINT32_T +AC_TYPE_UINT64_T +AC_TYPE_UINT8_T + +# Checks for library functions. +AC_FUNC_MALLOC +AC_CHECK_FUNCS( + [iswprint memmove memset mkdir setlocale strchr strdup], + [], + [ AC_MSG_ERROR([required library function is missing on your system])]) + +# pkg-config based tests +PKG_PROG_PKG_CONFIG + +if test -n "$PKG_CONFIG"; then + if test "$WIN32" != "xyes"; then + PKG_CHECK_MODULES([NCURSES], [ncursesw], [], + [ + AC_MSG_ERROR([required library ncursesw was not found on your system: $NCURSES_PKG_ERRORS]) + ]) + fi +else + AC_MSG_WARN([pkg-config was not found on your sytem]) +fi + + +if (test -z "$PKG_CONFIG") || (test "x$WIN32" = "xyes"); then + AC_CHECK_HEADER([curses.h], + [], + [ + AC_MSG_ERROR([headers for the ncurses library were not found on your system]) + ] + ) + + if test "x$WIN32" = "xyes"; then + AC_CHECK_LIB([pdcurses], [clear], + [], + [ + AC_MSG_ERROR([required library pdcurses was not found on your system]) + ] + ) + + AC_CHECK_LIB(ws2_32, main, + [ + WINSOCK2_LIBS="-lws2_32" + AC_SUBST(WINSOCK2_LIBS) + ], + [ + AC_MSG_ERROR([required library winsock2 was not found on the system, please check your MinGW installation]) + ] + ) + else + AC_CHECK_LIB([ncursesw], [get_wch], + [], + [ + unset ac_cv_lib_ncursesw_get_wch + AC_CHECK_LIB([ncursesw], [get_wch], + [], + [ + AC_MSG_ERROR([required library ncurses was not found on your system]) + ], + [ + -ltinfo + ] + ) + ] + ) + fi +fi + +# sodium is included by Tox headers so we kind of need to know where it is +LIBSODIUM_CFLAGS= +CFLAGS_SAVE="$CFLAGS" +CPPFLAGS_SAVE="$CPPFLAGS" +if test -n "$LIBSODIUM_SEARCH_HEADERS"; then + CFLAGS="$CFLAGS -I$LIBSODIUM_SEARCH_HEADERS" + CPPFLAGS="$CFLAGS -I$LIBSODIUM_SEARCH_HEADERS" + AC_CHECK_HEADER(sodium.h, + [ + LIBSODIUM_CFLAGS="-I$LIBSODIUM_SEARCH_HEADERS" + ], + [ + AC_MSG_ERROR([header files for required library libsodium was not found in requested location $LIBSODIUM_SEARCH_HEADERS]) + ] + ) +else + AC_CHECK_HEADER(sodium.h, + [], + [ + AC_MSG_ERROR([header files for required library libsodium was not found on your system, please check http://download.libsodium.org/libsodium/releases/]) + ] + ) +fi +CFLAGS="$CFLAGS_SAVE" +CPPFLAGS="$CPPFLAGS_SAVE" +AC_SUBST(LIBSODIUM_CFLAGS) + + +LIBSODIUM_LIBS= +LIBSODIUM_LDFLAGS= +LDFLAGS_SAVE="$LDFLAGS" +if test -n "$LIBSODIUM_SEARCH_LIBS"; then + LDFLAGS="$LDFLAGS -L$LIBSODIUM_SEARCH_LIBS" + AC_CHECK_LIB(sodium, randombytes_random, + [ + LIBSODIUM_LDFLAGS="-L$LIBSODIUM_SEARCH_LIBS" + LIBSODIUM_LIBS="-lsodium" + ], + [ + AC_MSG_ERROR([required library libsodium was not found in requested location $LIBSODIUM_SEARCH_LIBS]) + ] + ) +else + AC_CHECK_LIB(sodium, randombytes_random, + [], + [ + AC_MSG_ERROR([required library libsodium was not found on your system, please check http://download.libsodium.org/libsodium/releases/]) + ] + ) +fi + +LDFLAGS="$LDFLAGS_SAVE" +AC_SUBST(LIBSODIUM_LIBS) +AC_SUBST(LIBSODIUM_LDFLAGS) + + + +LIBTOXCORE_CFLAGS= +CFLAGS_SAVE="$CFLAGS" +CPPFLAGS_SAVE="$CPPFLAGS" + +if test -n "$LIBTOXCORE_SEARCH_HEADERS"; then + CFLAGS="$CFLAGS -I$LIBTOXCORE_SEARCH_HEADERS $LIBSODIUM_CFLAGS" + CPPFLAGS="$CPPFLAGS -I$LIBTOXCORE_SEARCH_HEADERS $LIBSODIUM_CFLAGS" + AC_CHECK_HEADER([Messenger.h], + [ + LIBTOXCORE_CFLAGS="-I$LIBTOXCORE_SEARCH_HEADERS" + ], + [ + AC_MSG_ERROR([headers for the toxcore library were not found on your system]) + ] + ) +else + CFLAGS="$CFLAGS $LIBSODIUM_CFLAGS" + CPPFLAGS="$CPPFLAGS $LIBSODIUM_CFLAGS" + AC_CHECK_HEADER([Messenger.h], + [], + [ + AC_MSG_ERROR([headers for the toxcore library were not found on your system]) + ] + ) +fi +CFLAGS="$CFLAGS_SAVE" +CPPFLAGS="$CPPFLAGS_SAVE" +AC_SUBST(LIBTOXCORE_CFLAGS) + +LIBTOXCORE_LIBS= +LIBTOXCORE_LDFLAGS= +LDFLAGS_SAVE="$LDFLAGS" +if test -n "$LIBTOXCORE_SEARCH_LIBS"; then + LDFLAGS="$LDFLAGS $LIBSODIUM_LDFLAGS -L$LIBTOXCORE_SEARCH_LIBS $LIBSODIUM_LIBS" + AC_CHECK_LIB([toxcore], [initMessenger], + [ + LIBTOXCORE_LDFLAGS="-L$LIBTOXCORE_SEARCH_LIBS" + LIBTOXCORE_LIBS="-ltoxcore" + ], + [ + AC_MSG_ERROR([required library toxcore was not found on your system]) + ] + ) +else + LDFLAGS="$LDFLAGS $LIBSODIUM_LDFLAGS $LIBSODIUM_LIBS" + AC_CHECK_LIB([toxcore], [initMessenger], + [], + [ + AC_MSG_ERROR([required library toxcore was not found on your system]) + ] + ) +fi +LDFLAGS="$LDFLAGS_SAVE" +AC_SUBST(LIBTOXCORE_LIBS) +AC_SUBST(LIBTOXCORE_LDFLAGS) + + + +TOXIC_VERSION="$PACKAGE_VERSION" +AC_PATH_PROG([GIT], [git], [no]) +if test "x$GIT" != "xno"; then + if test -d ${srcdir}/.git; then + TOXIC_VERSION="${TOXIC_VERSION}_r`${GIT} rev-list HEAD --count`" + fi +fi +AC_SUBST(TOXIC_VERSION) + + +AC_CONFIG_FILES([Makefile + build/Makefile]) +AC_OUTPUT diff --git a/m4/pkg.m4 b/m4/pkg.m4 new file mode 100644 index 0000000..f26f84c --- /dev/null +++ b/m4/pkg.m4 @@ -0,0 +1,199 @@ +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 1 (pkg-config-0.24) +# +# Copyright © 2004 Scott James Remnant . +# +# This program 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 2 of the License, or +# (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])# PKG_PROG_PKG_CONFIG + +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +# only at the first occurence in configure.ac, so if the first place +# it's called might be skipped (such as if it is within an "if", you +# have to call PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])# _PKG_CONFIG + +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])# _PKG_SHORT_ERRORS_SUPPORTED + + +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])# PKG_CHECK_MODULES + + +# PKG_INSTALLDIR(DIRECTORY) +# ------------------------- +# Substitutes the variable pkgconfigdir as the location where a module +# should install pkg-config .pc files. By default the directory is +# $libdir/pkgconfig, but the default can be changed by passing +# DIRECTORY. The user can override through the --with-pkgconfigdir +# parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +]) dnl PKG_INSTALLDIR + + +# PKG_NOARCH_INSTALLDIR(DIRECTORY) +# ------------------------- +# Substitutes the variable noarch_pkgconfigdir as the location where a +# module should install arch-independent pkg-config .pc files. By +# default the directory is $datadir/pkgconfig, but the default can be +# changed by passing DIRECTORY. The user can override through the +# --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +]) dnl PKG_NOARCH_INSTALLDIR diff --git a/src/chat.c b/src/chat.c index c7a0f98..41dab99 100644 --- a/src/chat.c +++ b/src/chat.c @@ -9,10 +9,10 @@ #include #include -#include "../../core/Messenger.h" -#include "../../core/network.h" +#include "Messenger.h" +#include "network.h" -#include "windows.h" +#include "toxic_windows.h" #include "friendlist.h" #include "chat.h" diff --git a/src/dhtstatus.c b/src/dhtstatus.c index 3330077..84d58f6 100644 --- a/src/dhtstatus.c +++ b/src/dhtstatus.c @@ -1,7 +1,7 @@ #include "dhtstatus.h" #include "string.h" -#include "../../core/network.h" -#include "../../core/DHT.h" +#include "network.h" +#include "DHT.h" typedef uint8_t ipbuf[3 * 4 + 3 + 1]; static int num_selected = 0; diff --git a/src/dhtstatus.h b/src/dhtstatus.h index 2b30e5a..3c4a55c 100644 --- a/src/dhtstatus.h +++ b/src/dhtstatus.h @@ -1,7 +1,7 @@ #ifndef _dhtstatus_h #define _dhtstatus_h -#include "windows.h" +#include "toxic_windows.h" ToxWindow new_dhtstatus(); diff --git a/src/friendlist.c b/src/friendlist.c index 8fa3b47..5f1bedf 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -6,10 +6,9 @@ #include #include -#include "../../core/Messenger.h" -#include "../../core/network.h" +#include "Messenger.h" +#include "network.h" -#include "windows.h" #include "friendlist.h" diff --git a/src/friendlist.h b/src/friendlist.h index 6f045d4..3a5d393 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -1,7 +1,7 @@ #ifndef FRIENDLIST_H_53I41IM #define FRIENDLIST_H_53I41IM -#include "windows.h" +#include "toxic_windows.h" #include "chat.h" ToxWindow new_friendlist(); diff --git a/src/main.c b/src/main.c index 12b529f..543b7d0 100644 --- a/src/main.c +++ b/src/main.c @@ -19,11 +19,11 @@ #include #endif -#include "../../core/Messenger.h" -#include "../../core/network.h" +#include "Messenger.h" +#include "network.h" #include "configdir.h" -#include "windows.h" +#include "toxic_windows.h" #include "prompt.h" #include "friendlist.h" diff --git a/src/prompt.c b/src/prompt.c index b00dba2..fc21fcb 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -6,10 +6,9 @@ #include #include -#include "../../core/Messenger.h" -#include "../../core/network.h" +#include "Messenger.h" +#include "network.h" -#include "windows.h" #include "prompt.h" extern char *DATA_FILE; diff --git a/src/prompt.h b/src/prompt.h index 8e12a42..b42f6fe 100644 --- a/src/prompt.h +++ b/src/prompt.h @@ -1,7 +1,7 @@ #ifndef PROMPT_H_UZYGWFFL #define PROMPT_H_UZYGWFFL -#include "windows.h" +#include "toxic_windows.h" ToxWindow new_prompt(); int add_req(uint8_t *public_key); diff --git a/src/toxic_windows.h b/src/toxic_windows.h index 227040b..243d5c6 100644 --- a/src/toxic_windows.h +++ b/src/toxic_windows.h @@ -10,7 +10,7 @@ #include #include #include -#include "../../core/Messenger.h" +#include "Messenger.h" #define MAX_WINDOWS_NUM 32 #define MAX_FRIENDS_NUM 100 #define MAX_STR_SIZE 256 diff --git a/src/windows.c b/src/windows.c index f50bdc2..aff86b7 100644 --- a/src/windows.c +++ b/src/windows.c @@ -1,7 +1,7 @@ #include "friendlist.h" #include "prompt.h" #include "dhtstatus.h" -#include "windows.h" +#include "toxic_windows.h" extern char *DATA_FILE; extern int store_data(Messenger *m, char *path); From 30666d2debbbb38c481c5383ad55579711965ecb Mon Sep 17 00:00:00 2001 From: Sergey 'Jin' Bostandzhyan Date: Fri, 23 Aug 2013 01:37:19 +0300 Subject: [PATCH 172/172] Install and use DHTservers file DHTservers will go to $prefix/share/toxic/DHTservers --- Makefile.am | 2 +- configure.ac | 5 +++++ misc/DHTservers | 9 +++++++++ misc/Makefile.am | 1 + src/main.c | 6 +++++- 5 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 misc/DHTservers create mode 100644 misc/Makefile.am diff --git a/Makefile.am b/Makefile.am index e67ff9d..630a1b0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = build +SUBDIRS = build misc ACLOCAL_AMFLAGS = -I m4 diff --git a/configure.ac b/configure.ac index e60f00b..df59b53 100644 --- a/configure.ac +++ b/configure.ac @@ -288,7 +288,12 @@ if test "x$GIT" != "xno"; then fi AC_SUBST(TOXIC_VERSION) +eval PACKAGE_DATADIR="${datadir}/${PACKAGE}" +eval PACKAGE_DATADIR="${PACKAGE_DATADIR}" +AC_DEFINE_UNQUOTED(PACKAGE_DATADIR, "$PACKAGE_DATADIR", [toxic data directory]) + AC_CONFIG_FILES([Makefile + misc/Makefile build/Makefile]) AC_OUTPUT diff --git a/misc/DHTservers b/misc/DHTservers new file mode 100644 index 0000000..bf2d272 --- /dev/null +++ b/misc/DHTservers @@ -0,0 +1,9 @@ +192.81.133.111 33445 8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858 +66.175.223.88 33445 AC4112C975240CAD260BB2FCD134266521FAAF0A5D159C5FD3201196191E4F5D +192.184.81.118 33445 5CD7EB176C19A2FD840406CD56177BB8E75587BB366F7BB3004B19E3EDC04143 +192.210.149.121 33445 F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67 +81.224.34.47 443 48F0D94C0D54EB1995A2ECEDE7DB6BDD5E05D81704B2F3D1BB9FE43AC97B7269 +198.46.136.167 33445 728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854 +95.47.140.214 33445 F4BF7C5A9D0EF4CB684090C38DE937FAE1612021F21FEA4DCBFAC6AAFEF58E68 +54.215.145.71 33445 6EDDEE2188EF579303C0766B4796DCBA89C93058B6032FEA51593DCD42FB746C +66.74.30.125 33445 7155386A691E7BD3C4C0589D70ACDA191D488634772885CCED5DD7B3F7E6310D diff --git a/misc/Makefile.am b/misc/Makefile.am new file mode 100644 index 0000000..c25600a --- /dev/null +++ b/misc/Makefile.am @@ -0,0 +1 @@ +dist_pkgdata_DATA = DHTservers diff --git a/src/main.c b/src/main.c index 543b7d0..6c31041 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,10 @@ * Toxic -- Tox Curses Client */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define _XOPEN_SOURCE_EXTENDED #include #include @@ -294,7 +298,7 @@ int main(int argc, char *argv[]) if (config_err) { DATA_FILE = strdup("data"); - SRVLIST_FILE = strdup("../../other/DHTservers"); + SRVLIST_FILE = strdup(PACKAGE_DATADIR "/DHTservers"); } else { DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); strcpy(DATA_FILE, user_config_dir);