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; };