summaryrefslogtreecommitdiff
path: root/testing/toxic
diff options
context:
space:
mode:
Diffstat (limited to 'testing/toxic')
-rw-r--r--testing/toxic/chat.c603
-rw-r--r--testing/toxic/configdir.c65
-rw-r--r--testing/toxic/configdir.h2
-rw-r--r--testing/toxic/dhtstatus.c134
-rw-r--r--testing/toxic/friendlist.c241
-rw-r--r--testing/toxic/friendlist.h2
-rw-r--r--testing/toxic/main.c317
-rw-r--r--testing/toxic/prompt.c675
-rw-r--r--testing/toxic/windows.c340
-rw-r--r--testing/toxic/windows.h42
10 files changed, 1270 insertions, 1151 deletions
diff --git a/testing/toxic/chat.c b/testing/toxic/chat.c
index d5edf956..ef932cd2 100644
--- a/testing/toxic/chat.c
+++ b/testing/toxic/chat.c
@@ -19,376 +19,391 @@
19#define CURS_Y_OFFSET 3 19#define CURS_Y_OFFSET 3
20 20
21typedef struct { 21typedef struct {
22 int friendnum; 22 int friendnum;
23 char line[MAX_STR_SIZE]; 23 char line[MAX_STR_SIZE];
24 size_t pos; 24 size_t pos;
25 WINDOW* history; 25 WINDOW *history;
26 WINDOW* linewin; 26 WINDOW *linewin;
27} ChatContext; 27} ChatContext;
28 28
29void print_help(ChatContext *self); 29void print_help(ChatContext *self);
30void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd); 30void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd);
31 31
32struct tm *get_time(void) 32struct tm *get_time(void)
33{ 33{
34 struct tm *timeinfo; 34 struct tm *timeinfo;
35 time_t now; 35 time_t now;
36 time(&now); 36 time(&now);
37 timeinfo = localtime(&now); 37 timeinfo = localtime(&now);
38 return timeinfo; 38 return timeinfo;
39} 39}
40 40
41static void chat_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *msg, uint16_t len) 41static void chat_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *msg, uint16_t len)
42{ 42{
43 ChatContext *ctx = (ChatContext*) self->x; 43 ChatContext *ctx = (ChatContext *) self->x;
44 uint8_t nick[MAX_NAME_LENGTH] = {0}; 44 uint8_t nick[MAX_NAME_LENGTH] = {0};
45 struct tm *timeinfo = get_time(); 45 struct tm *timeinfo = get_time();
46 46
47 if (ctx->friendnum != num) 47 if (ctx->friendnum != num)
48 return; 48 return;
49 49
50 getname(m, num, (uint8_t*) &nick); 50 getname(m, num, (uint8_t *) &nick);
51 msg[len-1] = '\0'; 51 msg[len - 1] = '\0';
52 nick[MAX_NAME_LENGTH-1] = '\0'; 52 nick[MAX_NAME_LENGTH - 1] = '\0';
53 fix_name(msg); 53 fix_name(msg);
54 fix_name(nick); 54 fix_name(nick);
55 55
56 wattron(ctx->history, COLOR_PAIR(2)); 56 wattron(ctx->history, COLOR_PAIR(2));
57 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); 57 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
58 wattroff(ctx->history, COLOR_PAIR(2)); 58 wattroff(ctx->history, COLOR_PAIR(2));
59 wattron(ctx->history, COLOR_PAIR(4)); 59 wattron(ctx->history, COLOR_PAIR(4));
60 wprintw(ctx->history, "%s: ", nick); 60 wprintw(ctx->history, "%s: ", nick);
61 wattroff(ctx->history, COLOR_PAIR(4)); 61 wattroff(ctx->history, COLOR_PAIR(4));
62 wprintw(ctx->history, "%s\n", msg); 62 wprintw(ctx->history, "%s\n", msg);
63 63
64 self->blink = true; 64 self->blink = true;
65 beep(); 65 beep();
66} 66}
67 67
68static void chat_onAction(ToxWindow *self, Messenger *m, int num, uint8_t *action, uint16_t len) 68static void chat_onAction(ToxWindow *self, Messenger *m, int num, uint8_t *action, uint16_t len)
69{ 69{
70 ChatContext *ctx = (ChatContext*) self->x; 70 ChatContext *ctx = (ChatContext *) self->x;
71 struct tm *timeinfo = get_time(); 71 struct tm *timeinfo = get_time();
72 72
73 if (ctx->friendnum != num) 73 if (ctx->friendnum != num)
74 return; 74 return;
75 75
76 action[len-1] = '\0'; 76 action[len - 1] = '\0';
77 fix_name(action); 77 fix_name(action);
78 78
79 wattron(ctx->history, COLOR_PAIR(2)); 79 wattron(ctx->history, COLOR_PAIR(2));
80 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); 80 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
81 wattroff(ctx->history, COLOR_PAIR(2)); 81 wattroff(ctx->history, COLOR_PAIR(2));
82 82
83 wattron(ctx->history, COLOR_PAIR(5)); 83 wattron(ctx->history, COLOR_PAIR(5));
84 wprintw(ctx->history, "%s\n", action); 84 wprintw(ctx->history, "%s\n", action);
85 wattroff(ctx->history, COLOR_PAIR(5)); 85 wattroff(ctx->history, COLOR_PAIR(5));
86 86
87 self->blink = true; 87 self->blink = true;
88 beep(); 88 beep();
89} 89}
90 90
91static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len) 91static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len)
92{ 92{
93 ChatContext *ctx = (ChatContext*) self->x; 93 ChatContext *ctx = (ChatContext *) self->x;
94 struct tm *timeinfo = get_time(); 94 struct tm *timeinfo = get_time();
95 if (ctx->friendnum != num) 95
96 return; 96 if (ctx->friendnum != num)
97 97 return;
98 wattron(ctx->history, COLOR_PAIR(2)); 98
99 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); 99 wattron(ctx->history, COLOR_PAIR(2));
100 wattroff(ctx->history, COLOR_PAIR(2)); 100 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
101 101 wattroff(ctx->history, COLOR_PAIR(2));
102 nick[len-1] = '\0'; 102
103 fix_name(nick); 103 nick[len - 1] = '\0';
104 snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num); 104 fix_name(nick);
105 105 snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num);
106 wattron(ctx->history, COLOR_PAIR(3)); 106
107 wprintw(ctx->history, "* Your partner changed nick to '%s'\n", nick); 107 wattron(ctx->history, COLOR_PAIR(3));
108 wattroff(ctx->history, COLOR_PAIR(3)); 108 wprintw(ctx->history, "* Your partner changed nick to '%s'\n", nick);
109 wattroff(ctx->history, COLOR_PAIR(3));
109} 110}
110 111
111static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint16_t len) 112static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint16_t len)
112{ 113{
113 ChatContext *ctx = (ChatContext*) self->x; 114 ChatContext *ctx = (ChatContext *) self->x;
114 struct tm *timeinfo = get_time(); 115 struct tm *timeinfo = get_time();
115 if (ctx->friendnum != num) 116
116 return; 117 if (ctx->friendnum != num)
117 118 return;
118 wattron(ctx->history, COLOR_PAIR(2)); 119
119 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); 120 wattron(ctx->history, COLOR_PAIR(2));
120 wattroff(ctx->history, COLOR_PAIR(2)); 121 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
121 122 wattroff(ctx->history, COLOR_PAIR(2));
122 status[len-1] = '\0'; 123
123 fix_name(status); 124 status[len - 1] = '\0';
124 snprintf(self->title, sizeof(self->title), "[%s (%d)]", status, num); 125 fix_name(status);
125 126 snprintf(self->title, sizeof(self->title), "[%s (%d)]", status, num);
126 wattron(ctx->history, COLOR_PAIR(3)); 127
127 wprintw(ctx->history, "* Your partner changed status to '%s'\n", status); 128 wattron(ctx->history, COLOR_PAIR(3));
128 wattroff(ctx->history, COLOR_PAIR(3)); 129 wprintw(ctx->history, "* Your partner changed status to '%s'\n", status);
129 130 wattroff(ctx->history, COLOR_PAIR(3));
131
130} 132}
131 133
132/* check that the string has one non-space character */ 134/* check that the string has one non-space character */
133int string_is_empty(char *string) 135int string_is_empty(char *string)
134{ 136{
135 int rc = 0; 137 int rc = 0;
136 char *copy = strdup(string); 138 char *copy = strdup(string);
137 rc = ((strtok(copy, " ") == NULL) ? 1:0); 139 rc = ((strtok(copy, " ") == NULL) ? 1 : 0);
138 free(copy); 140 free(copy);
139 return rc; 141 return rc;
140} 142}
141 143
142static void chat_onKey(ToxWindow *self, Messenger *m, int key) 144static void chat_onKey(ToxWindow *self, Messenger *m, int key)
143{ 145{
144 ChatContext *ctx = (ChatContext*) self->x; 146 ChatContext *ctx = (ChatContext *) self->x;
145 struct tm *timeinfo = get_time(); 147 struct tm *timeinfo = get_time();
146 148
147 int x, y, y2, x2; 149 int x, y, y2, x2;
148 getyx(self->window, y, x); 150 getyx(self->window, y, x);
149 getmaxyx(self->window, y2, x2); 151 getmaxyx(self->window, y2, x2);
150 152
151 /* Add printable chars to buffer and print on input space */ 153 /* Add printable chars to buffer and print on input space */
152 if (isprint(key)) { 154 if (isprint(key)) {
153 if (ctx->pos != sizeof(ctx->line)-1) { 155 if (ctx->pos != sizeof(ctx->line) - 1) {
154 mvwaddch(self->window, y, x, key); 156 mvwaddch(self->window, y, x, key);
155 ctx->line[ctx->pos++] = key; 157 ctx->line[ctx->pos++] = key;
156 ctx->line[ctx->pos] = '\0'; 158 ctx->line[ctx->pos] = '\0';
159 }
157 } 160 }
158 } 161
159 162 /* BACKSPACE key: Remove one character from line */
160 /* BACKSPACE key: Remove one character from line */ 163 else if (key == 0x107 || key == 0x8 || key == 0x7f) {
161 else if (key == 0x107 || key == 0x8 || key == 0x7f) { 164 if (ctx->pos > 0) {
162 if (ctx->pos > 0) { 165 ctx->line[--ctx->pos] = '\0';
163 ctx->line[--ctx->pos] = '\0'; 166
164 if (x == 0) 167 if (x == 0)
165 mvwdelch(self->window, y-1, x2-1); 168 mvwdelch(self->window, y - 1, x2 - 1);
166 else 169 else
167 mvwdelch(self->window, y, x-1); 170 mvwdelch(self->window, y, x - 1);
171 }
168 } 172 }
169 }
170
171 /* RETURN key: Execute command or print line */
172 else if (key == '\n') {
173 wclear(ctx->linewin);
174 wmove(self->window, y2-CURS_Y_OFFSET, 0);
175 wclrtobot(self->window);
176 if (ctx->line[0] == '/')
177 execute(self, ctx, m, ctx->line);
178 else {
179 /* make sure the string has at least non-space character */
180 if (!string_is_empty(ctx->line)) {
181 uint8_t selfname[MAX_NAME_LENGTH];
182 getself_name(m, selfname, sizeof(selfname));
183 fix_name(selfname);
184 173
185 wattron(ctx->history, COLOR_PAIR(2)); 174 /* RETURN key: Execute command or print line */
186 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); 175 else if (key == '\n') {
187 wattroff(ctx->history, COLOR_PAIR(2)); 176 wclear(ctx->linewin);
188 wattron(ctx->history, COLOR_PAIR(1)); 177 wmove(self->window, y2 - CURS_Y_OFFSET, 0);
189 wprintw(ctx->history, "%s: ", selfname); 178 wclrtobot(self->window);
190 wattroff(ctx->history, COLOR_PAIR(1)); 179
191 wprintw(ctx->history, "%s\n", ctx->line); 180 if (ctx->line[0] == '/')
192 if (m_sendmessage(m, ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) == 0) { 181 execute(self, ctx, m, ctx->line);
193 wattron(ctx->history, COLOR_PAIR(3)); 182 else {
194 wprintw(ctx->history, " * Failed to send message.\n"); 183 /* make sure the string has at least non-space character */
195 wattroff(ctx->history, COLOR_PAIR(3)); 184 if (!string_is_empty(ctx->line)) {
185 uint8_t selfname[MAX_NAME_LENGTH];
186 getself_name(m, selfname, sizeof(selfname));
187 fix_name(selfname);
188
189 wattron(ctx->history, COLOR_PAIR(2));
190 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
191 wattroff(ctx->history, COLOR_PAIR(2));
192 wattron(ctx->history, COLOR_PAIR(1));
193 wprintw(ctx->history, "%s: ", selfname);
194 wattroff(ctx->history, COLOR_PAIR(1));
195 wprintw(ctx->history, "%s\n", ctx->line);
196
197 if (m_sendmessage(m, ctx->friendnum, (uint8_t *) ctx->line, strlen(ctx->line) + 1) == 0) {
198 wattron(ctx->history, COLOR_PAIR(3));
199 wprintw(ctx->history, " * Failed to send message.\n");
200 wattroff(ctx->history, COLOR_PAIR(3));
201 }
202 }
196 } 203 }
197 } 204
205 ctx->line[0] = '\0';
206 ctx->pos = 0;
198 } 207 }
199 ctx->line[0] = '\0';
200 ctx->pos = 0;
201 }
202} 208}
203 209
204void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) 210void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd)
205{ 211{
206 if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { 212 if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) {
207 wclear(self->window); 213 wclear(self->window);
208 wclear(ctx->history); 214 wclear(ctx->history);
209 int x, y; 215 int x, y;
210 getmaxyx(self->window, y, x); 216 getmaxyx(self->window, y, x);
211 (void) x; 217 (void) x;
212 wmove(self->window, y-CURS_Y_OFFSET, 0); 218 wmove(self->window, y - CURS_Y_OFFSET, 0);
213 } 219 }
214
215 else if (!strcmp(cmd, "/help") || !strcmp(cmd, "/h"))
216 print_help(ctx);
217 220
218 else if (!strcmp(cmd, "/quit") || !strcmp(cmd, "/exit") || !strcmp(cmd, "/q")) { 221 else if (!strcmp(cmd, "/help") || !strcmp(cmd, "/h"))
219 endwin(); 222 print_help(ctx);
220 exit(0);
221 }
222 223
223 else if (!strncmp(cmd, "/me ", strlen("/me "))) { 224 else if (!strcmp(cmd, "/quit") || !strcmp(cmd, "/exit") || !strcmp(cmd, "/q")) {
224 struct tm *timeinfo = get_time(); 225 endwin();
225 char *action = strchr(cmd, ' '); 226 exit(0);
226 if (action == NULL) {
227 wprintw(self->window, "Invalid syntax.\n");
228 return;
229 } 227 }
230 action++;
231 228
232 wattron(ctx->history, COLOR_PAIR(2)); 229 else if (!strncmp(cmd, "/me ", strlen("/me "))) {
233 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); 230 struct tm *timeinfo = get_time();
234 wattroff(ctx->history, COLOR_PAIR(2)); 231 char *action = strchr(cmd, ' ');
235 232
236 uint8_t selfname[MAX_NAME_LENGTH]; 233 if (action == NULL) {
237 int len = getself_name(m, selfname, sizeof(selfname)); 234 wprintw(self->window, "Invalid syntax.\n");
238 char msg[MAX_STR_SIZE-len-4]; 235 return;
239 snprintf(msg, sizeof(msg), "* %s %s\n", (uint8_t*) selfname, action); 236 }
240 237
241 wattron(ctx->history, COLOR_PAIR(5)); 238 action++;
242 wprintw(ctx->history, msg);
243 wattroff(ctx->history, COLOR_PAIR(5));
244 if (m_sendaction(m, ctx->friendnum, (uint8_t*) msg, strlen(msg)+1) < 0) {
245 wattron(ctx->history, COLOR_PAIR(3));
246 wprintw(ctx->history, " * Failed to send action\n");
247 wattroff(ctx->history, COLOR_PAIR(3));
248 }
249 }
250
251 else if (!strncmp(cmd, "/status ", strlen("/status "))) {
252 char *status = strchr(cmd, ' ');
253 char *msg;
254 char *status_text;
255 if (status == NULL) {
256 wprintw(ctx->history, "Invalid syntax.\n");
257 return;
258 }
259 status++;
260 USERSTATUS status_kind;
261 if (!strncmp(status, "online", strlen("online"))) {
262 status_kind = USERSTATUS_NONE;
263 status_text = "ONLINE";
264 }
265 239
266 else if (!strncmp(status, "away", strlen("away"))) { 240 wattron(ctx->history, COLOR_PAIR(2));
267 status_kind = USERSTATUS_AWAY; 241 wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
268 status_text = "AWAY"; 242 wattroff(ctx->history, COLOR_PAIR(2));
269 }
270 243
271 else if (!strncmp(status, "busy", strlen("busy"))) { 244 uint8_t selfname[MAX_NAME_LENGTH];
272 status_kind = USERSTATUS_BUSY; 245 int len = getself_name(m, selfname, sizeof(selfname));
273 status_text = "BUSY"; 246 char msg[MAX_STR_SIZE - len - 4];
274 } 247 snprintf(msg, sizeof(msg), "* %s %s\n", (uint8_t *) selfname, action);
275 248
276 else { 249 wattron(ctx->history, COLOR_PAIR(5));
277 wprintw(ctx->history, "Invalid status.\n"); 250 wprintw(ctx->history, msg);
278 return; 251 wattroff(ctx->history, COLOR_PAIR(5));
279 }
280 252
281 msg = strchr(status, ' '); 253 if (m_sendaction(m, ctx->friendnum, (uint8_t *) msg, strlen(msg) + 1) < 0) {
282 if (msg == NULL) { 254 wattron(ctx->history, COLOR_PAIR(3));
283 m_set_userstatus(m, status_kind); 255 wprintw(ctx->history, " * Failed to send action\n");
284 wprintw(ctx->history, "Status set to: %s\n", status_text); 256 wattroff(ctx->history, COLOR_PAIR(3));
257 }
285 } 258 }
286 else { 259
287 msg++; 260 else if (!strncmp(cmd, "/status ", strlen("/status "))) {
288 m_set_userstatus(m, status_kind); 261 char *status = strchr(cmd, ' ');
289 m_set_statusmessage(m, ( uint8_t*) msg, strlen(msg)+1); 262 char *msg;
290 wprintw(ctx->history, "Status set to: %s, %s\n", status_text, msg); 263 char *status_text;
264
265 if (status == NULL) {
266 wprintw(ctx->history, "Invalid syntax.\n");
267 return;
268 }
269
270 status++;
271 USERSTATUS status_kind;
272
273 if (!strncmp(status, "online", strlen("online"))) {
274 status_kind = USERSTATUS_NONE;
275 status_text = "ONLINE";
276 }
277
278 else if (!strncmp(status, "away", strlen("away"))) {
279 status_kind = USERSTATUS_AWAY;
280 status_text = "AWAY";
281 }
282
283 else if (!strncmp(status, "busy", strlen("busy"))) {
284 status_kind = USERSTATUS_BUSY;
285 status_text = "BUSY";
286 }
287
288 else {
289 wprintw(ctx->history, "Invalid status.\n");
290 return;
291 }
292
293 msg = strchr(status, ' ');
294
295 if (msg == NULL) {
296 m_set_userstatus(m, status_kind);
297 wprintw(ctx->history, "Status set to: %s\n", status_text);
298 } else {
299 msg++;
300 m_set_userstatus(m, status_kind);
301 m_set_statusmessage(m, ( uint8_t *) msg, strlen(msg) + 1);
302 wprintw(ctx->history, "Status set to: %s, %s\n", status_text, msg);
303 }
291 } 304 }
292 } 305
293 306 else if (!strncmp(cmd, "/nick ", strlen("/nick "))) {
294 else if (!strncmp(cmd, "/nick ", strlen("/nick "))) { 307 char *nick;
295 char *nick; 308 nick = strchr(cmd, ' ');
296 nick = strchr(cmd, ' '); 309
297 if (nick == NULL) { 310 if (nick == NULL) {
298 wprintw(ctx->history, "Invalid syntax.\n"); 311 wprintw(ctx->history, "Invalid syntax.\n");
299 return; 312 return;
313 }
314
315 nick++;
316 setname(m, (uint8_t *) nick, strlen(nick) + 1);
317 wprintw(ctx->history, "Nickname set to: %s\n", nick);
300 } 318 }
301 319
302 nick++; 320 else if (!strcmp(cmd, "/myid")) {
303 setname(m, (uint8_t*) nick, strlen(nick)+1); 321 char id[FRIEND_ADDRESS_SIZE * 2 + 1] = {0};
304 wprintw(ctx->history, "Nickname set to: %s\n", nick); 322 int i;
305 } 323 uint8_t address[FRIEND_ADDRESS_SIZE];
306 324 getaddress(m, address);
307 else if (!strcmp(cmd, "/myid")) { 325
308 char id[FRIEND_ADDRESS_SIZE*2+1] = {0}; 326 for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) {
309 int i; 327 char xx[3];
310 uint8_t address[FRIEND_ADDRESS_SIZE]; 328 snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff);
311 getaddress(m, address); 329 strcat(id, xx);
312 for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) { 330 }
313 char xx[3]; 331
314 snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); 332 wprintw(ctx->history, "%s\n", id);
315 strcat(id, xx);
316 } 333 }
317 wprintw(ctx->history, "%s\n", id);
318 }
319 334
320 else if (strcmp(ctx->line, "/close") == 0) { 335 else if (strcmp(ctx->line, "/close") == 0) {
321 int f_num = ctx->friendnum; 336 int f_num = ctx->friendnum;
322 delwin(ctx->linewin); 337 delwin(ctx->linewin);
323 del_window(self, f_num); 338 del_window(self, f_num);
324 } 339 }
325 340
326 else 341 else
327 wprintw(ctx->history, "Invalid command.\n"); 342 wprintw(ctx->history, "Invalid command.\n");
328} 343}
329 344
330static void chat_onDraw(ToxWindow *self) 345static void chat_onDraw(ToxWindow *self)
331{ 346{
332 curs_set(1); 347 curs_set(1);
333 int x, y; 348 int x, y;
334 getmaxyx(self->window, y, x); 349 getmaxyx(self->window, y, x);
335 (void) y; 350 (void) y;
336 ChatContext *ctx = (ChatContext*) self->x; 351 ChatContext *ctx = (ChatContext *) self->x;
337 mvwhline(ctx->linewin, 0, 0, '_', x); 352 mvwhline(ctx->linewin, 0, 0, '_', x);
338 wrefresh(self->window); 353 wrefresh(self->window);
339} 354}
340 355
341static void chat_onInit(ToxWindow *self, Messenger *m) 356static void chat_onInit(ToxWindow *self, Messenger *m)
342{ 357{
343 int x, y; 358 int x, y;
344 ChatContext *ctx = (ChatContext*) self->x; 359 ChatContext *ctx = (ChatContext *) self->x;
345 getmaxyx(self->window, y, x); 360 getmaxyx(self->window, y, x);
346 ctx->history = subwin(self->window, y-4, x, 0, 0); 361 ctx->history = subwin(self->window, y - 4, x, 0, 0);
347 scrollok(ctx->history, 1); 362 scrollok(ctx->history, 1);
348 ctx->linewin = subwin(self->window, 2, x, y-4, 0); 363 ctx->linewin = subwin(self->window, 2, x, y - 4, 0);
349 print_help(ctx); 364 print_help(ctx);
350 wmove(self->window, y-CURS_Y_OFFSET, 0); 365 wmove(self->window, y - CURS_Y_OFFSET, 0);
351} 366}
352 367
353void print_help(ChatContext *self) 368void print_help(ChatContext *self)
354{ 369{
355 wattron(self->history, COLOR_PAIR(2) | A_BOLD); 370 wattron(self->history, COLOR_PAIR(2) | A_BOLD);
356 wprintw(self->history, "Commands:\n"); 371 wprintw(self->history, "Commands:\n");
357 wattroff(self->history, A_BOLD); 372 wattroff(self->history, A_BOLD);
358 373
359 wprintw(self->history, " /status <type> <message> : Set your status\n"); 374 wprintw(self->history, " /status <type> <message> : Set your status\n");
360 wprintw(self->history, " /nick <nickname> : Set your nickname\n"); 375 wprintw(self->history, " /nick <nickname> : Set your nickname\n");
361 wprintw(self->history, " /me <action> : Do an action\n"); 376 wprintw(self->history, " /me <action> : Do an action\n");
362 wprintw(self->history, " /myid : Print your ID\n"); 377 wprintw(self->history, " /myid : Print your ID\n");
363 wprintw(self->history, " /clear : Clear the screen\n"); 378 wprintw(self->history, " /clear : Clear the screen\n");
364 wprintw(self->history, " /close : Close the current chat window\n"); 379 wprintw(self->history, " /close : Close the current chat window\n");
365 wprintw(self->history, " /quit or /exit : Exit program\n"); 380 wprintw(self->history, " /quit or /exit : Exit program\n");
366 wprintw(self->history, " /help : Print this message again\n\n"); 381 wprintw(self->history, " /help : Print this message again\n\n");
367 382
368 wattroff(self->history, COLOR_PAIR(2)); 383 wattroff(self->history, COLOR_PAIR(2));
369} 384}
370 385
371ToxWindow new_chat(Messenger *m, int friendnum) 386ToxWindow new_chat(Messenger *m, int friendnum)
372{ 387{
373 ToxWindow ret; 388 ToxWindow ret;
374 memset(&ret, 0, sizeof(ret)); 389 memset(&ret, 0, sizeof(ret));
375 390
376 ret.onKey = &chat_onKey; 391 ret.onKey = &chat_onKey;
377 ret.onDraw = &chat_onDraw; 392 ret.onDraw = &chat_onDraw;
378 ret.onInit = &chat_onInit; 393 ret.onInit = &chat_onInit;
379 ret.onMessage = &chat_onMessage; 394 ret.onMessage = &chat_onMessage;
380 ret.onNickChange = &chat_onNickChange; 395 ret.onNickChange = &chat_onNickChange;
381 ret.onStatusChange = &chat_onStatusChange; 396 ret.onStatusChange = &chat_onStatusChange;
382 ret.onAction = &chat_onAction; 397 ret.onAction = &chat_onAction;
383 398
384 uint8_t nick[MAX_NAME_LENGTH] = {0}; 399 uint8_t nick[MAX_NAME_LENGTH] = {0};
385 getname(m, friendnum, (uint8_t*) &nick); 400 getname(m, friendnum, (uint8_t *) &nick);
386 fix_name(nick); 401 fix_name(nick);
387 402
388 snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum); 403 snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum);
389 404
390 ChatContext *x = calloc(1, sizeof(ChatContext)); 405 ChatContext *x = calloc(1, sizeof(ChatContext));
391 x->friendnum = friendnum; 406 x->friendnum = friendnum;
392 ret.x = (void*) x; 407 ret.x = (void *) x;
393 return ret; 408 return ret;
394} 409}
diff --git a/testing/toxic/configdir.c b/testing/toxic/configdir.c
index 18e211ce..1a62e8ed 100644
--- a/testing/toxic/configdir.c
+++ b/testing/toxic/configdir.c
@@ -50,6 +50,7 @@ char *get_user_config_dir(void)
50 BOOL ok; 50 BOOL ok;
51 51
52 ok = SHGetSpecialFolderPathA(NULL, appdata, CSIDL_PROFILE, TRUE); 52 ok = SHGetSpecialFolderPathA(NULL, appdata, CSIDL_PROFILE, TRUE);
53
53 if (!ok) { 54 if (!ok) {
54 return NULL; 55 return NULL;
55 } 56 }
@@ -72,13 +73,16 @@ char *get_user_config_dir(void)
72 int rc; 73 int rc;
73 74
74 rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf); 75 rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
76
75 if (rc == 0) { 77 if (rc == 0) {
76 home = pwd.pw_dir; 78 home = pwd.pw_dir;
77 } else { 79 } else {
78 home = getenv("HOME"); 80 home = getenv("HOME");
81
79 if (home == NULL) { 82 if (home == NULL) {
80 return NULL; 83 return NULL;
81 } 84 }
85
82 /* env variables can be tainted */ 86 /* env variables can be tainted */
83 snprintf(buf, sizeof(buf), "%s", home); 87 snprintf(buf, sizeof(buf), "%s", home);
84 home = buf; 88 home = buf;
@@ -87,6 +91,7 @@ char *get_user_config_dir(void)
87# if defined(__APPLE__) 91# if defined(__APPLE__)
88 len = strlen(home) + strlen("/Library/Application Support") + 1; 92 len = strlen(home) + strlen("/Library/Application Support") + 1;
89 user_config_dir = malloc(len); 93 user_config_dir = malloc(len);
94
90 if (user_config_dir == NULL) { 95 if (user_config_dir == NULL) {
91 return NULL; 96 return NULL;
92 } 97 }
@@ -95,6 +100,7 @@ char *get_user_config_dir(void)
95# else /* __APPLE__ */ 100# else /* __APPLE__ */
96 len = strlen(home) + strlen("/.config") + 1; 101 len = strlen(home) + strlen("/.config") + 1;
97 user_config_dir = malloc(len); 102 user_config_dir = malloc(len);
103
98 if (user_config_dir == NULL) { 104 if (user_config_dir == NULL) {
99 return NULL; 105 return NULL;
100 } 106 }
@@ -111,44 +117,45 @@ char *get_user_config_dir(void)
111 * Creates the config directory. 117 * Creates the config directory.
112 */ 118 */
113int create_user_config_dir(char *path) 119int create_user_config_dir(char *path)
114{ 120{
115 121
116 int mkdir_err; 122 int mkdir_err;
117 123
118 #ifdef WIN32 124#ifdef WIN32
119 125
120 char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1); 126 char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1);
121 strcpy(fullpath, path); 127 strcpy(fullpath, path);
122 strcat(fullpath, CONFIGDIR); 128 strcat(fullpath, CONFIGDIR);
123 129
124 mkdir_err = _mkdir(fullpath); 130 mkdir_err = _mkdir(fullpath);
125 struct __stat64 buf; 131 struct __stat64 buf;
126 if (mkdir_err && (errno != EEXIST || _wstat64(fullpath, &buf) || !S_ISDIR(buf.st_mode))) {
127 free(fullpath);
128 return -1;
129 }
130 132
131 #else 133 if (mkdir_err && (errno != EEXIST || _wstat64(fullpath, &buf) || !S_ISDIR(buf.st_mode))) {
134 free(fullpath);
135 return -1;
136 }
132 137
133 mkdir_err = mkdir(path, 0700); 138#else
134 struct stat buf;
135 139
136 if(mkdir_err && (errno != EEXIST || stat(path, &buf) || !S_ISDIR(buf.st_mode))) { 140 mkdir_err = mkdir(path, 0700);
137 return -1; 141 struct stat buf;
138 }
139 142
140 char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1); 143 if (mkdir_err && (errno != EEXIST || stat(path, &buf) || !S_ISDIR(buf.st_mode))) {
141 strcpy(fullpath, path); 144 return -1;
142 strcat(fullpath, CONFIGDIR); 145 }
143 146
144 mkdir_err = mkdir(fullpath, 0700); 147 char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1);
148 strcpy(fullpath, path);
149 strcat(fullpath, CONFIGDIR);
150
151 mkdir_err = mkdir(fullpath, 0700);
152
153 if (mkdir_err && (errno != EEXIST || stat(fullpath, &buf) || !S_ISDIR(buf.st_mode))) {
154 free(fullpath);
155 return -1;
156 }
145 157
146 if(mkdir_err && (errno != EEXIST || stat(fullpath, &buf) || !S_ISDIR(buf.st_mode))) { 158#endif
147 free(fullpath); 159 free(fullpath);
148 return -1; 160 return 0;
149 }
150
151 #endif
152 free(fullpath);
153 return 0;
154} 161}
diff --git a/testing/toxic/configdir.h b/testing/toxic/configdir.h
index fad949cf..17d95107 100644
--- a/testing/toxic/configdir.h
+++ b/testing/toxic/configdir.h
@@ -23,7 +23,7 @@
23#else 23#else
24#define CONFIGDIR "/toxic/" 24#define CONFIGDIR "/toxic/"
25#endif 25#endif
26 26
27#ifndef S_ISDIR 27#ifndef S_ISDIR
28#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) 28#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
29#endif 29#endif
diff --git a/testing/toxic/dhtstatus.c b/testing/toxic/dhtstatus.c
index e026a173..a11dc616 100644
--- a/testing/toxic/dhtstatus.c
+++ b/testing/toxic/dhtstatus.c
@@ -3,87 +3,97 @@
3#include "../../core/network.h" 3#include "../../core/network.h"
4#include "../../core/DHT.h" 4#include "../../core/DHT.h"
5 5
6typedef uint8_t ipbuf[3*4+3+1]; 6typedef uint8_t ipbuf[3 * 4 + 3 + 1];
7static int num_selected = 0; 7static int num_selected = 0;
8 8
9static void printip(ipbuf buf, IP ip) 9static void printip(ipbuf buf, IP ip)
10{ 10{
11 sprintf((char*)buf, "%u.%u.%u.%u", ip.c[0], ip.c[1], ip.c[2], ip.c[3]); 11 sprintf((char *)buf, "%u.%u.%u.%u", ip.c[0], ip.c[1], ip.c[2], ip.c[3]);
12} 12}
13 13
14static void dhtstatus_onKey(ToxWindow *self, Messenger *m, int key) 14static void dhtstatus_onKey(ToxWindow *self, Messenger *m, int key)
15{ 15{
16 switch(key) { 16 switch (key) {
17 case KEY_UP: 17 case KEY_UP:
18 case 'k': 18 case 'k':
19 if (--num_selected < 0) 19 if (--num_selected < 0)
20 num_selected = CLIENT_ID_SIZE-1; 20 num_selected = CLIENT_ID_SIZE - 1;
21 break; 21
22 22 break;
23 case KEY_DOWN: 23
24 case 'j': 24 case KEY_DOWN:
25 num_selected = (num_selected+1) % CLIENT_ID_SIZE; 25 case 'j':
26 break; 26 num_selected = (num_selected + 1) % CLIENT_ID_SIZE;
27 27 break;
28 case '\n': 28
29 break; 29 case '\n':
30 30 break;
31 default: 31
32 break; 32 default:
33 } 33 break;
34 }
34} 35}
35 36
36static void dhtstatus_onDraw(ToxWindow *self) 37static void dhtstatus_onDraw(ToxWindow *self)
37{ 38{
38 Client_data * close_clientlist = DHT_get_close_list(); 39 Client_data *close_clientlist = DHT_get_close_list();
39 curs_set(0); 40 curs_set(0);
40 werase(self->window); 41 werase(self->window);
41 42
42 uint64_t now = unix_time(); 43 uint64_t now = unix_time();
43 uint32_t i, j; 44 uint32_t i, j;
44 ipbuf ipbuf; 45 ipbuf ipbuf;
45 wprintw(self->window,"\n%llu ______________________ CLOSE LIST ________________________ ___ IP ADDR ___ _PRT_ LST PNG ____ SELF ____ _PRT_ LST\n\n", now); 46 wprintw(self->window,
46 for(i = 0; i < 32; i++) { /*Number of nodes in closelist*/ 47 "\n%llu ______________________ CLOSE LIST ________________________ ___ IP ADDR ___ _PRT_ LST PNG ____ SELF ____ _PRT_ LST\n\n",
47 Client_data * client = close_clientlist + i; 48 now);
48 if (i == num_selected) wattron(self->window, COLOR_PAIR(3)); 49
49 wprintw(self->window,"[%02i] ", i); 50 for (i = 0; i < 32; i++) { /*Number of nodes in closelist*/
50 uint16_t port = ntohs(client->ip_port.port); 51 Client_data *client = close_clientlist + i;
51 if(port) { 52
52 for(j = 0; j < CLIENT_ID_SIZE; j++) 53 if (i == num_selected) wattron(self->window, COLOR_PAIR(3));
53 wprintw(self->window, "%02hhx", client->client_id[j]); 54
54 55 wprintw(self->window, "[%02i] ", i);
55 printip(ipbuf, client->ip_port.ip); 56 uint16_t port = ntohs(client->ip_port.port);
56 wprintw(self->window, " %15s %5u ", ipbuf, port); 57
57 wprintw(self->window, " %3llu ", now - client->timestamp); 58 if (port) {
58 wprintw(self->window, " %3llu ", now - client->last_pinged); 59 for (j = 0; j < CLIENT_ID_SIZE; j++)
59 60 wprintw(self->window, "%02hhx", client->client_id[j]);
60 port = ntohs(client->ret_ip_port.port); 61
61 if(port) { 62 printip(ipbuf, client->ip_port.ip);
62 printip(ipbuf, client->ret_ip_port.ip); 63 wprintw(self->window, " %15s %5u ", ipbuf, port);
63 wprintw(self->window, " %15s %5u %3llu", ipbuf, port, now - close_clientlist[i].ret_timestamp); 64 wprintw(self->window, " %3llu ", now - client->timestamp);
64 } 65 wprintw(self->window, " %3llu ", now - client->last_pinged);
66
67 port = ntohs(client->ret_ip_port.port);
68
69 if (port) {
70 printip(ipbuf, client->ret_ip_port.ip);
71 wprintw(self->window, " %15s %5u %3llu", ipbuf, port, now - close_clientlist[i].ret_timestamp);
72 }
73 }
74
75 wprintw(self->window, "\n");
76
77 if (i == num_selected) wattroff(self->window, COLOR_PAIR(3));
65 } 78 }
66 wprintw(self->window, "\n"); 79
67 if (i == num_selected) wattroff(self->window, COLOR_PAIR(3)); 80 wrefresh(self->window);
68 }
69
70 wrefresh(self->window);
71} 81}
72 82
73static void dhtstatus_onInit(ToxWindow *self, Messenger *m) 83static void dhtstatus_onInit(ToxWindow *self, Messenger *m)
74{ 84{
75 85
76} 86}
77 87
78ToxWindow new_dhtstatus() 88ToxWindow new_dhtstatus()
79{ 89{
80 ToxWindow ret; 90 ToxWindow ret;
81 memset(&ret, 0, sizeof(ret)); 91 memset(&ret, 0, sizeof(ret));
82 92
83 ret.onKey = &dhtstatus_onKey; 93 ret.onKey = &dhtstatus_onKey;
84 ret.onDraw = &dhtstatus_onDraw; 94 ret.onDraw = &dhtstatus_onDraw;
85 ret.onInit = &dhtstatus_onInit; 95 ret.onInit = &dhtstatus_onInit;
86 96
87 strcpy(ret.title, "[dht status]"); 97 strcpy(ret.title, "[dht status]");
88 return ret; 98 return ret;
89} 99}
diff --git a/testing/toxic/friendlist.c b/testing/toxic/friendlist.c
index e7504fbf..c85fd3ae 100644
--- a/testing/toxic/friendlist.c
+++ b/testing/toxic/friendlist.c
@@ -13,13 +13,13 @@
13#include "windows.h" 13#include "windows.h"
14#include "friendlist.h" 14#include "friendlist.h"
15 15
16static char * WINDOW_STATUS; 16static char *WINDOW_STATUS;
17 17
18typedef struct { 18typedef struct {
19 uint8_t name[MAX_NAME_LENGTH]; 19 uint8_t name[MAX_NAME_LENGTH];
20 uint8_t status[MAX_STATUSMESSAGE_LENGTH]; 20 uint8_t status[MAX_STATUSMESSAGE_LENGTH];
21 int num; 21 int num;
22 int chatwin; 22 int chatwin;
23} friend_t; 23} friend_t;
24 24
25static friend_t friends[MAX_FRIENDS_NUM]; 25static friend_t friends[MAX_FRIENDS_NUM];
@@ -28,135 +28,143 @@ static int num_selected = 0;
28 28
29void fix_name(uint8_t *name) 29void fix_name(uint8_t *name)
30{ 30{
31 /* Remove all non alphanumeric characters */ 31 /* Remove all non alphanumeric characters */
32 uint8_t *p = name; 32 uint8_t *p = name;
33 uint8_t *q = name; 33 uint8_t *q = name;
34 while(*p != 0) { 34
35 if (isprint(*p)) 35 while (*p != 0) {
36 *q++ = *p; 36 if (isprint(*p))
37 p++; 37 *q++ = *p;
38 } 38
39 *q = 0; 39 p++;
40 }
41
42 *q = 0;
40} 43}
41 44
42void friendlist_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *str, uint16_t len) 45void friendlist_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *str, uint16_t len)
43{ 46{
44 if (num >= num_friends) 47 if (num >= num_friends)
45 return; 48 return;
46 49
47 if (friends[num].chatwin == -1) { 50 if (friends[num].chatwin == -1) {
48 friends[num].chatwin = num; 51 friends[num].chatwin = num;
49 int i; 52 int i;
50 /* Find first open slot to hold chat window */ 53
51 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { 54 /* Find first open slot to hold chat window */
52 if (WINDOW_STATUS[i] == -1) { 55 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) {
53 WINDOW_STATUS[i] = num; 56 if (WINDOW_STATUS[i] == -1) {
54 add_window(m, new_chat(m, num), i); 57 WINDOW_STATUS[i] = num;
55 break; 58 add_window(m, new_chat(m, num), i);
56 } 59 break;
60 }
61 }
57 } 62 }
58 }
59} 63}
60 64
61void friendlist_onNickChange(ToxWindow *self, int num, uint8_t *str, uint16_t len) 65void friendlist_onNickChange(ToxWindow *self, int num, uint8_t *str, uint16_t len)
62{ 66{
63 if (len >= MAX_NAME_LENGTH || num >= num_friends) 67 if (len >= MAX_NAME_LENGTH || num >= num_friends)
64 return; 68 return;
65 69
66 memcpy((char*) &friends[num].name, (char*) str, len); 70 memcpy((char *) &friends[num].name, (char *) str, len);
67 friends[num].name[len] = 0; 71 friends[num].name[len] = 0;
68 fix_name(friends[num].name); 72 fix_name(friends[num].name);
69} 73}
70 74
71void friendlist_onStatusChange(ToxWindow *self, int num, uint8_t *str, uint16_t len) 75void friendlist_onStatusChange(ToxWindow *self, int num, uint8_t *str, uint16_t len)
72{ 76{
73 if (len >= MAX_STATUSMESSAGE_LENGTH || num >= num_friends) 77 if (len >= MAX_STATUSMESSAGE_LENGTH || num >= num_friends)
74 return; 78 return;
75 79
76 memcpy((char*) &friends[num].status, (char*) str, len); 80 memcpy((char *) &friends[num].status, (char *) str, len);
77 friends[num].status[len] = 0; 81 friends[num].status[len] = 0;
78 fix_name(friends[num].status); 82 fix_name(friends[num].status);
79} 83}
80 84
81int friendlist_onFriendAdded(Messenger *m, int num) 85int friendlist_onFriendAdded(Messenger *m, int num)
82{ 86{
83 if (num_friends == MAX_FRIENDS_NUM) 87 if (num_friends == MAX_FRIENDS_NUM)
84 return -1; 88 return -1;
85 89
86 friends[num_friends].num = num; 90 friends[num_friends].num = num;
87 getname(m, num, friends[num_friends].name); 91 getname(m, num, friends[num_friends].name);
88 strcpy((char*) friends[num_friends].name, "unknown"); 92 strcpy((char *) friends[num_friends].name, "unknown");
89 strcpy((char*) friends[num_friends].status, "unknown"); 93 strcpy((char *) friends[num_friends].status, "unknown");
90 friends[num_friends++].chatwin = -1; 94 friends[num_friends++].chatwin = -1;
91 return 0; 95 return 0;
92} 96}
93 97
94static void friendlist_onKey(ToxWindow *self, Messenger *m, int key) 98static void friendlist_onKey(ToxWindow *self, Messenger *m, int key)
95{ 99{
96 if (key == KEY_UP) { 100 if (key == KEY_UP) {
97 if (--num_selected < 0) 101 if (--num_selected < 0)
98 num_selected = num_friends-1; 102 num_selected = num_friends - 1;
99 } 103 } else if (key == KEY_DOWN) {
100 else if (key == KEY_DOWN) { 104 if (num_friends != 0)
101 if (num_friends != 0) 105 num_selected = (num_selected + 1) % num_friends;
102 num_selected = (num_selected+1) % num_friends; 106 } else if (key == '\n') {
103 } 107 /* Jump to chat window if already open */
104 else if (key == '\n') { 108 if (friends[num_selected].chatwin != -1) {
105 /* Jump to chat window if already open */ 109 int i;
106 if (friends[num_selected].chatwin != -1) { 110
107 int i; 111 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) {
108 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { 112 if (WINDOW_STATUS[i] == num_selected) {
109 if (WINDOW_STATUS[i] == num_selected) { 113 set_active_window(i);
110 set_active_window(i); 114 break;
111 break; 115 }
112 } 116 }
113 } 117 } else {
114 }else { 118 int i;
115 int i; 119
116 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { 120 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) {
117 if (WINDOW_STATUS[i] == -1) { 121 if (WINDOW_STATUS[i] == -1) {
118 WINDOW_STATUS[i] = num_selected; 122 WINDOW_STATUS[i] = num_selected;
119 friends[num_selected].chatwin = num_selected; 123 friends[num_selected].chatwin = num_selected;
120 add_window(m, new_chat(m, num_selected), i); 124 add_window(m, new_chat(m, num_selected), i);
121 break; 125 break;
126 }
127 }
122 } 128 }
123 }
124 } 129 }
125 }
126} 130}
127 131
128static void friendlist_onDraw(ToxWindow *self) 132static void friendlist_onDraw(ToxWindow *self)
129{ 133{
130 curs_set(0); 134 curs_set(0);
131 werase(self->window); 135 werase(self->window);
132 if (num_friends == 0) { 136
133 wprintw(self->window, "Empty. Add some friends! :-)\n"); 137 if (num_friends == 0) {
134 } 138 wprintw(self->window, "Empty. Add some friends! :-)\n");
135 else { 139 } else {
136 wattron(self->window, COLOR_PAIR(2) | A_BOLD); 140 wattron(self->window, COLOR_PAIR(2) | A_BOLD);
137 wprintw(self->window, "Open chat with.. (up/down keys, enter)\n"); 141 wprintw(self->window, "Open chat with.. (up/down keys, enter)\n");
138 wattroff(self->window, COLOR_PAIR(2) | A_BOLD); 142 wattroff(self->window, COLOR_PAIR(2) | A_BOLD);
139 } 143 }
140 144
141 wprintw(self->window, "\n"); 145 wprintw(self->window, "\n");
142 int i; 146 int i;
143 for (i = 0; i < num_friends; ++i) { 147
144 if (i == num_selected) wattron(self->window, COLOR_PAIR(3)); 148 for (i = 0; i < num_friends; ++i) {
145 wprintw(self->window, " [#%d] ", friends[i].num); 149 if (i == num_selected) wattron(self->window, COLOR_PAIR(3));
146 if (i == num_selected) wattroff(self->window, COLOR_PAIR(3)); 150
147 151 wprintw(self->window, " [#%d] ", friends[i].num);
148 attron(A_BOLD); 152
149 wprintw(self->window, "%s ", friends[i].name); 153 if (i == num_selected) wattroff(self->window, COLOR_PAIR(3));
150 attroff(A_BOLD); 154
151 155 attron(A_BOLD);
152 wprintw(self->window, "(%s)\n", friends[i].status); 156 wprintw(self->window, "%s ", friends[i].name);
153 } 157 attroff(A_BOLD);
154 wrefresh(self->window); 158
159 wprintw(self->window, "(%s)\n", friends[i].status);
160 }
161
162 wrefresh(self->window);
155} 163}
156 164
157void disable_chatwin(int f_num) 165void disable_chatwin(int f_num)
158{ 166{
159 friends[f_num].chatwin = -1; 167 friends[f_num].chatwin = -1;
160} 168}
161 169
162static void friendlist_onInit(ToxWindow *self, Messenger *m) 170static void friendlist_onInit(ToxWindow *self, Messenger *m)
@@ -164,19 +172,20 @@ static void friendlist_onInit(ToxWindow *self, Messenger *m)
164 172
165} 173}
166 174
167ToxWindow new_friendlist(char * ws) { 175ToxWindow new_friendlist(char *ws)
168 WINDOW_STATUS = ws; 176{
169 ToxWindow ret; 177 WINDOW_STATUS = ws;
170 memset(&ret, 0, sizeof(ret)); 178 ToxWindow ret;
171 179 memset(&ret, 0, sizeof(ret));
172 ret.onKey = &friendlist_onKey; 180
173 ret.onDraw = &friendlist_onDraw; 181 ret.onKey = &friendlist_onKey;
174 ret.onInit = &friendlist_onInit; 182 ret.onDraw = &friendlist_onDraw;
175 ret.onMessage = &friendlist_onMessage; 183 ret.onInit = &friendlist_onInit;
176 ret.onAction = &friendlist_onMessage; // Action has identical behaviour to message 184 ret.onMessage = &friendlist_onMessage;
177 ret.onNickChange = &friendlist_onNickChange; 185 ret.onAction = &friendlist_onMessage; // Action has identical behaviour to message
178 ret.onStatusChange = &friendlist_onStatusChange; 186 ret.onNickChange = &friendlist_onNickChange;
179 187 ret.onStatusChange = &friendlist_onStatusChange;
180 strcpy(ret.title, "[friends]"); 188
181 return ret; 189 strcpy(ret.title, "[friends]");
190 return ret;
182} 191}
diff --git a/testing/toxic/friendlist.h b/testing/toxic/friendlist.h
index c3d8dac7..f0c27f53 100644
--- a/testing/toxic/friendlist.h
+++ b/testing/toxic/friendlist.h
@@ -4,7 +4,7 @@
4#include "windows.h" 4#include "windows.h"
5#include "chat.h" 5#include "chat.h"
6 6
7ToxWindow new_friendlist(char * ws); 7ToxWindow new_friendlist(char *ws);
8int friendlist_onFriendAdded(Messenger *m, int num); 8int friendlist_onFriendAdded(Messenger *m, int num);
9void disable_chatwin(int f_num); 9void disable_chatwin(int f_num);
10void fix_name(uint8_t *name); 10void fix_name(uint8_t *name);
diff --git a/testing/toxic/main.c b/testing/toxic/main.c
index 38c20df6..816873b3 100644
--- a/testing/toxic/main.c
+++ b/testing/toxic/main.c
@@ -28,7 +28,7 @@
28/* Export for use in Callbacks */ 28/* Export for use in Callbacks */
29char *DATA_FILE = NULL; 29char *DATA_FILE = NULL;
30 30
31void on_window_resize(int sig) 31void on_window_resize(int sig)
32{ 32{
33 endwin(); 33 endwin();
34 refresh(); 34 refresh();
@@ -37,44 +37,45 @@ void on_window_resize(int sig)
37 37
38static void init_term() 38static void init_term()
39{ 39{
40 /* Setup terminal */ 40 /* Setup terminal */
41 signal(SIGWINCH, on_window_resize); 41 signal(SIGWINCH, on_window_resize);
42 initscr(); 42 initscr();
43 cbreak(); 43 cbreak();
44 keypad(stdscr, 1); 44 keypad(stdscr, 1);
45 noecho(); 45 noecho();
46 timeout(100); 46 timeout(100);
47 47
48 if (has_colors()) { 48 if (has_colors()) {
49 start_color(); 49 start_color();
50 init_pair(1, COLOR_GREEN, COLOR_BLACK); 50 init_pair(1, COLOR_GREEN, COLOR_BLACK);
51 init_pair(2, COLOR_CYAN, COLOR_BLACK); 51 init_pair(2, COLOR_CYAN, COLOR_BLACK);
52 init_pair(3, COLOR_RED, COLOR_BLACK); 52 init_pair(3, COLOR_RED, COLOR_BLACK);
53 init_pair(4, COLOR_BLUE, COLOR_BLACK); 53 init_pair(4, COLOR_BLUE, COLOR_BLACK);
54 init_pair(5, COLOR_YELLOW, COLOR_BLACK); 54 init_pair(5, COLOR_YELLOW, COLOR_BLACK);
55 } 55 }
56 refresh(); 56
57 refresh();
57} 58}
58 59
59static Messenger *init_tox() 60static Messenger *init_tox()
60{ 61{
61 /* Init core */ 62 /* Init core */
62 Messenger *m = initMessenger(); 63 Messenger *m = initMessenger();
63 64
64 /* Callbacks */ 65 /* Callbacks */
65 m_callback_friendrequest(m, on_request, NULL); 66 m_callback_friendrequest(m, on_request, NULL);
66 m_callback_friendmessage(m, on_message, NULL); 67 m_callback_friendmessage(m, on_message, NULL);
67 m_callback_namechange(m, on_nickchange, NULL); 68 m_callback_namechange(m, on_nickchange, NULL);
68 m_callback_statusmessage(m, on_statuschange, NULL); 69 m_callback_statusmessage(m, on_statuschange, NULL);
69 m_callback_action(m, on_action, NULL); 70 m_callback_action(m, on_action, NULL);
70#ifdef __linux__ 71#ifdef __linux__
71 setname(m, (uint8_t*) "Cool guy", sizeof("Cool guy")); 72 setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy"));
72#elif WIN32 73#elif WIN32
73 setname(m, (uint8_t*) "I should install GNU/Linux", sizeof("I should install GNU/Linux")); 74 setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux"));
74#else 75#else
75 setname(m, (uint8_t*) "Hipster", sizeof("Hipster")); 76 setname(m, (uint8_t *) "Hipster", sizeof("Hipster"));
76#endif 77#endif
77 return m; 78 return m;
78} 79}
79 80
80#define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */ 81#define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */
@@ -84,67 +85,75 @@ static Messenger *init_tox()
84/* Connects to a random DHT server listed in the DHTservers file */ 85/* Connects to a random DHT server listed in the DHTservers file */
85int init_connection(void) 86int init_connection(void)
86{ 87{
87 if (DHT_isconnected()) 88 if (DHT_isconnected())
88 return 0; 89 return 0;
90
91 FILE *fp = fopen("../../../other/DHTservers", "r");
92
93 if (!fp)
94 return 1;
95
96 char servers[MAXSERVERS][MAXLINE];
97 char line[MAXLINE];
98 int linecnt = 0;
99
100 while (fgets(line, sizeof(line), fp) && linecnt < MAXSERVERS) {
101 if (strlen(line) > MINLINE)
102 strcpy(servers[linecnt++], line);
103 }
104
105 if (linecnt < 1) {
106 fclose(fp);
107 return 2;
108 }
89 109
90 FILE *fp = fopen("../../../other/DHTservers", "r");
91 if (!fp)
92 return 1;
93
94 char servers[MAXSERVERS][MAXLINE];
95 char line[MAXLINE];
96 int linecnt = 0;
97 while (fgets(line, sizeof(line), fp) && linecnt < MAXSERVERS) {
98 if (strlen(line) > MINLINE)
99 strcpy(servers[linecnt++], line);
100 }
101 if (linecnt < 1) {
102 fclose(fp); 110 fclose(fp);
103 return 2; 111
104 } 112 char *server = servers[rand() % linecnt];
105 fclose(fp); 113 char *ip = strtok(server, " ");
106 114 char *port = strtok(NULL, " ");
107 char *server = servers[rand() % linecnt]; 115 char *key = strtok(NULL, " ");
108 char *ip = strtok(server, " "); 116
109 char *port = strtok(NULL, " "); 117 if (!ip || !port || !key)
110 char *key = strtok(NULL, " "); 118 return 3;
111 if (!ip || !port || !key) 119
112 return 3; 120 IP_Port dht;
113 121 dht.port = htons(atoi(port));
114 IP_Port dht; 122 uint32_t resolved_address = resolve_addr(ip);
115 dht.port = htons(atoi(port)); 123
116 uint32_t resolved_address = resolve_addr(ip); 124 if (resolved_address == 0)
117 if (resolved_address == 0) 125 return 0;
126
127 dht.ip.i = resolved_address;
128 unsigned char *binary_string = hex_string_to_bin(key);
129 DHT_bootstrap(dht, binary_string);
130 free(binary_string);
118 return 0; 131 return 0;
119 dht.ip.i = resolved_address;
120 unsigned char *binary_string = hex_string_to_bin(key);
121 DHT_bootstrap(dht, binary_string);
122 free(binary_string);
123 return 0;
124} 132}
125 133
126static void do_tox(Messenger *m, ToxWindow * prompt) 134static void do_tox(Messenger *m, ToxWindow *prompt)
127{ 135{
128 static int conn_try = 0; 136 static int conn_try = 0;
129 static int conn_err = 0; 137 static int conn_err = 0;
130 static bool dht_on = false; 138 static bool dht_on = false;
131 if (!dht_on && !DHT_isconnected() && !(conn_try++ % 100)) { 139
132 if (!conn_err) { 140 if (!dht_on && !DHT_isconnected() && !(conn_try++ % 100)) {
133 conn_err = init_connection(); 141 if (!conn_err) {
134 wprintw(prompt->window, "\nEstablishing connection...\n"); 142 conn_err = init_connection();
135 if (conn_err) 143 wprintw(prompt->window, "\nEstablishing connection...\n");
136 wprintw(prompt->window, "\nAuto-connect failed with error code %d\n", conn_err); 144
145 if (conn_err)
146 wprintw(prompt->window, "\nAuto-connect failed with error code %d\n", conn_err);
147 }
148 } else if (!dht_on && DHT_isconnected()) {
149 dht_on = true;
150 wprintw(prompt->window, "\nDHT connected.\n");
151 } else if (dht_on && !DHT_isconnected()) {
152 dht_on = false;
153 wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n");
137 } 154 }
138 } 155
139 else if (!dht_on && DHT_isconnected()) { 156 doMessenger(m);
140 dht_on = true;
141 wprintw(prompt->window, "\nDHT connected.\n");
142 }
143 else if (dht_on && !DHT_isconnected()) {
144 dht_on = false;
145 wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n");
146 }
147 doMessenger(m);
148} 157}
149 158
150int f_loadfromfile; 159int f_loadfromfile;
@@ -160,18 +169,22 @@ int store_data(Messenger *m, char *path)
160{ 169{
161 if (f_loadfromfile == 0) /*If file loading/saving is disabled*/ 170 if (f_loadfromfile == 0) /*If file loading/saving is disabled*/
162 return 0; 171 return 0;
172
163 FILE *fd; 173 FILE *fd;
164 size_t len; 174 size_t len;
165 uint8_t *buf; 175 uint8_t *buf;
166 176
167 len = Messenger_size(m); 177 len = Messenger_size(m);
168 buf = malloc(len); 178 buf = malloc(len);
179
169 if (buf == NULL) { 180 if (buf == NULL) {
170 return 1; 181 return 1;
171 } 182 }
183
172 Messenger_save(m, buf); 184 Messenger_save(m, buf);
173 185
174 fd = fopen(path, "w"); 186 fd = fopen(path, "w");
187
175 if (fd == NULL) { 188 if (fd == NULL) {
176 free(buf); 189 free(buf);
177 return 2; 190 return 2;
@@ -192,6 +205,7 @@ static void load_data(Messenger *m, char *path)
192{ 205{
193 if (f_loadfromfile == 0) /*If file loading/saving is disabled*/ 206 if (f_loadfromfile == 0) /*If file loading/saving is disabled*/
194 return; 207 return;
208
195 FILE *fd; 209 FILE *fd;
196 size_t len; 210 size_t len;
197 uint8_t *buf; 211 uint8_t *buf;
@@ -202,12 +216,14 @@ static void load_data(Messenger *m, char *path)
202 fseek(fd, 0, SEEK_SET); 216 fseek(fd, 0, SEEK_SET);
203 217
204 buf = malloc(len); 218 buf = malloc(len);
219
205 if (buf == NULL) { 220 if (buf == NULL) {
206 fprintf(stderr, "malloc() failed.\n"); 221 fprintf(stderr, "malloc() failed.\n");
207 fclose(fd); 222 fclose(fd);
208 endwin(); 223 endwin();
209 exit(1); 224 exit(1);
210 } 225 }
226
211 if (fread(buf, len, 1, fd) != 1) { 227 if (fread(buf, len, 1, fd) != 1) {
212 fprintf(stderr, "fread() failed.\n"); 228 fprintf(stderr, "fread() failed.\n");
213 free(buf); 229 free(buf);
@@ -215,9 +231,11 @@ static void load_data(Messenger *m, char *path)
215 endwin(); 231 endwin();
216 exit(1); 232 exit(1);
217 } 233 }
234
218 Messenger_load(m, buf, len); 235 Messenger_load(m, buf, len);
219 236
220 uint32_t i; 237 uint32_t i;
238
221 for (i = 0; i < m->numfriends; i++) { 239 for (i = 0; i < m->numfriends; i++) {
222 on_friendadded(m, i); 240 on_friendadded(m, i);
223 } 241 }
@@ -226,6 +244,7 @@ static void load_data(Messenger *m, char *path)
226 fclose(fd); 244 fclose(fd);
227 } else { 245 } else {
228 int st; 246 int st;
247
229 if ((st = store_data(m, path)) != 0) { 248 if ((st = store_data(m, path)) != 0) {
230 fprintf(stderr, "Store messenger failed with return code: %d\n", st); 249 fprintf(stderr, "Store messenger failed with return code: %d\n", st);
231 endwin(); 250 endwin();
@@ -236,70 +255,74 @@ static void load_data(Messenger *m, char *path)
236 255
237int main(int argc, char *argv[]) 256int main(int argc, char *argv[])
238{ 257{
239 char *user_config_dir = get_user_config_dir(); 258 char *user_config_dir = get_user_config_dir();
240 int config_err = 0; 259 int config_err = 0;
241 260
242 f_loadfromfile = 1; 261 f_loadfromfile = 1;
243 int f_flag = 0; 262 int f_flag = 0;
244 int i = 0; 263 int i = 0;
245 for (i = 0; i < argc; ++i) { 264
246 if (argv[i] == NULL) 265 for (i = 0; i < argc; ++i) {
247 break; 266 if (argv[i] == NULL)
248 else if (argv[i][0] == '-') { 267 break;
249 if (argv[i][1] == 'f') { 268 else if (argv[i][0] == '-') {
250 if (argv[i + 1] != NULL) 269 if (argv[i][1] == 'f') {
251 DATA_FILE = strdup(argv[i + 1]); 270 if (argv[i + 1] != NULL)
252 else 271 DATA_FILE = strdup(argv[i + 1]);
253 f_flag = -1; 272 else
254 } else if (argv[i][1] == 'n') { 273 f_flag = -1;
255 f_loadfromfile = 0; 274 } else if (argv[i][1] == 'n') {
256 } 275 f_loadfromfile = 0;
276 }
277 }
278 }
279
280 if (DATA_FILE == NULL ) {
281 config_err = create_user_config_dir(user_config_dir);
282
283 if (config_err) {
284 DATA_FILE = strdup("data");
285 } else {
286 DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1);
287 strcpy(DATA_FILE, user_config_dir);
288 strcat(DATA_FILE, CONFIGDIR);
289 strcat(DATA_FILE, "data");
290 }
291 }
292
293 free(user_config_dir);
294
295 init_term();
296 Messenger *m = init_tox();
297 ToxWindow *prompt = init_windows(m);
298 init_window_status();
299
300 if (f_loadfromfile)
301 load_data(m, DATA_FILE);
302
303 if (f_flag == -1) {
304 attron(COLOR_PAIR(3) | A_BOLD);
305 wprintw(prompt->window, "You passed '-f' without giving an argument.\n"
306 "defaulting to 'data' for a keyfile...\n");
307 attroff(COLOR_PAIR(3) | A_BOLD);
257 } 308 }
258 }
259 309
260 if (DATA_FILE == NULL ) {
261 config_err = create_user_config_dir(user_config_dir);
262 if (config_err) { 310 if (config_err) {
263 DATA_FILE = strdup("data"); 311 attron(COLOR_PAIR(3) | A_BOLD);
264 } else { 312 wprintw(prompt->window, "Unable to determine configuration directory.\n"
265 DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); 313 "defaulting to 'data' for a keyfile...\n");
266 strcpy(DATA_FILE, user_config_dir); 314 attroff(COLOR_PAIR(3) | A_BOLD);
267 strcat(DATA_FILE, CONFIGDIR); 315 }
268 strcat(DATA_FILE, "data"); 316
317 while (true) {
318 /* Update tox */
319 do_tox(m, prompt);
320
321 /* Draw */
322 draw_active_window(m);
269 } 323 }
270 } 324
271 free(user_config_dir); 325 cleanupMessenger(m);
272 326 free(DATA_FILE);
273 init_term(); 327 return 0;
274 Messenger *m = init_tox();
275 ToxWindow *prompt = init_windows(m);
276 init_window_status();
277
278 if(f_loadfromfile)
279 load_data(m, DATA_FILE);
280
281 if (f_flag == -1) {
282 attron(COLOR_PAIR(3) | A_BOLD);
283 wprintw(prompt->window, "You passed '-f' without giving an argument.\n"
284 "defaulting to 'data' for a keyfile...\n");
285 attroff(COLOR_PAIR(3) | A_BOLD);
286 }
287
288 if(config_err) {
289 attron(COLOR_PAIR(3) | A_BOLD);
290 wprintw(prompt->window, "Unable to determine configuration directory.\n"
291 "defaulting to 'data' for a keyfile...\n");
292 attroff(COLOR_PAIR(3) | A_BOLD);
293 }
294 while(true) {
295 /* Update tox */
296 do_tox(m, prompt);
297
298 /* Draw */
299 draw_active_window(m);
300 }
301
302 cleanupMessenger(m);
303 free(DATA_FILE);
304 return 0;
305} 328}
diff --git a/testing/toxic/prompt.c b/testing/toxic/prompt.c
index 1d0e0144..f6d3e21f 100644
--- a/testing/toxic/prompt.c
+++ b/testing/toxic/prompt.c
@@ -14,7 +14,7 @@
14#include "prompt.h" 14#include "prompt.h"
15 15
16uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX 16uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX
17uint8_t num_requests=0; // XXX 17uint8_t num_requests = 0; // XXX
18 18
19static friendAddedFn *on_friendadded_cb; 19static friendAddedFn *on_friendadded_cb;
20static char prompt_buf[MAX_STR_SIZE] = {0}; 20static char prompt_buf[MAX_STR_SIZE] = {0};
@@ -36,412 +36,441 @@ void cmd_statusmsg(ToxWindow *, Messenger *m, char **);
36#define NUM_COMMANDS 13 36#define NUM_COMMANDS 13
37 37
38static struct { 38static struct {
39 char *name; 39 char *name;
40 int numargs; 40 int numargs;
41 void (*func)(ToxWindow *, Messenger *m, char **); 41 void (*func)(ToxWindow *, Messenger *m, char **);
42} commands[] = { 42} commands[] = {
43 { "accept", 1, cmd_accept }, 43 { "accept", 1, cmd_accept },
44 { "add", 1, cmd_add }, 44 { "add", 1, cmd_add },
45 { "clear", 0, cmd_clear }, 45 { "clear", 0, cmd_clear },
46 { "connect", 3, cmd_connect }, 46 { "connect", 3, cmd_connect },
47 { "exit", 0, cmd_quit }, 47 { "exit", 0, cmd_quit },
48 { "help", 0, cmd_help }, 48 { "help", 0, cmd_help },
49 { "msg", 2, cmd_msg }, 49 { "msg", 2, cmd_msg },
50 { "myid", 0, cmd_myid }, 50 { "myid", 0, cmd_myid },
51 { "nick", 1, cmd_nick }, 51 { "nick", 1, cmd_nick },
52 { "q", 0, cmd_quit }, 52 { "q", 0, cmd_quit },
53 { "quit", 0, cmd_quit }, 53 { "quit", 0, cmd_quit },
54 { "status", 2, cmd_status }, 54 { "status", 2, cmd_status },
55 { "statusmsg", 1, cmd_statusmsg }, 55 { "statusmsg", 1, cmd_statusmsg },
56}; 56};
57 57
58// XXX: 58// XXX:
59int add_req(uint8_t *public_key) 59int add_req(uint8_t *public_key)
60{ 60{
61 memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE); 61 memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE);
62 ++num_requests; 62 ++num_requests;
63 return num_requests-1; 63 return num_requests - 1;
64} 64}
65 65
66// XXX: FIX 66// XXX: FIX
67unsigned char *hex_string_to_bin(char hex_string[]) 67unsigned char *hex_string_to_bin(char hex_string[])
68{ 68{
69 size_t len = strlen(hex_string); 69 size_t len = strlen(hex_string);
70 unsigned char *val = malloc(len); 70 unsigned char *val = malloc(len);
71 char *pos = hex_string; 71 char *pos = hex_string;
72 int i; 72 int i;
73 for (i = 0; i < len; ++i, pos+=2) 73
74 sscanf(pos,"%2hhx",&val[i]); 74 for (i = 0; i < len; ++i, pos += 2)
75 return val; 75 sscanf(pos, "%2hhx", &val[i]);
76
77 return val;
76} 78}
77 79
78void cmd_accept(ToxWindow *self, Messenger *m, char **args) 80void cmd_accept(ToxWindow *self, Messenger *m, char **args)
79{ 81{
80 int num = atoi(args[1]); 82 int num = atoi(args[1]);
81 if (num >= num_requests) { 83
82 wprintw(self->window, "Invalid syntax.\n"); 84 if (num >= num_requests) {
83 return; 85 wprintw(self->window, "Invalid syntax.\n");
84 } 86 return;
85 87 }
86 num = m_addfriend_norequest(m, pending_requests[num]); 88
87 if (num == -1) 89 num = m_addfriend_norequest(m, pending_requests[num]);
88 wprintw(self->window, "Failed to add friend.\n"); 90
89 else { 91 if (num == -1)
90 wprintw(self->window, "Friend accepted as: %d.\n", num); 92 wprintw(self->window, "Failed to add friend.\n");
91 on_friendadded_cb(m, num); 93 else {
92 } 94 wprintw(self->window, "Friend accepted as: %d.\n", num);
95 on_friendadded_cb(m, num);
96 }
93} 97}
94 98
95void cmd_add(ToxWindow *self, Messenger *m, char **args) 99void cmd_add(ToxWindow *self, Messenger *m, char **args)
96{ 100{
97 uint8_t id_bin[FRIEND_ADDRESS_SIZE]; 101 uint8_t id_bin[FRIEND_ADDRESS_SIZE];
98 char xx[3]; 102 char xx[3];
99 uint32_t x; 103 uint32_t x;
100 char *id = args[1]; 104 char *id = args[1];
101 char *msg = args[2]; 105 char *msg = args[2];
102 106
103 if (!id) { 107 if (!id) {
104 wprintw(self->window, "Invalid command: add expected at least one argument.\n"); 108 wprintw(self->window, "Invalid command: add expected at least one argument.\n");
105 return; 109 return;
106 } 110 }
107 if (!msg) 111
108 msg = ""; 112 if (!msg)
109 113 msg = "";
110 if (strlen(id) != 2*FRIEND_ADDRESS_SIZE) { 114
111 wprintw(self->window, "Invalid ID length.\n"); 115 if (strlen(id) != 2 * FRIEND_ADDRESS_SIZE) {
112 return; 116 wprintw(self->window, "Invalid ID length.\n");
113 } 117 return;
114 int i; 118 }
115 for (i = 0; i < FRIEND_ADDRESS_SIZE; ++i) { 119
116 xx[0] = id[2*i]; 120 int i;
117 xx[1] = id[2*i+1]; 121
118 xx[2] = '\0'; 122 for (i = 0; i < FRIEND_ADDRESS_SIZE; ++i) {
119 if (sscanf(xx, "%02x", &x) != 1) { 123 xx[0] = id[2 * i];
120 wprintw(self->window, "Invalid ID.\n"); 124 xx[1] = id[2 * i + 1];
121 return; 125 xx[2] = '\0';
126
127 if (sscanf(xx, "%02x", &x) != 1) {
128 wprintw(self->window, "Invalid ID.\n");
129 return;
130 }
131
132 id_bin[i] = x;
133 }
134
135 for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) {
136 id[i] = toupper(id[i]);
137 }
138
139 int num = m_addfriend(m, id_bin, (uint8_t *) msg, strlen(msg) + 1);
140
141 switch (num) {
142 case FAERR_TOOLONG:
143 wprintw(self->window, "Message is too long.\n");
144 break;
145
146 case FAERR_NOMESSAGE:
147 wprintw(self->window, "Please add a message to your request.\n");
148 break;
149
150 case FAERR_OWNKEY:
151 wprintw(self->window, "That appears to be your own ID.\n");
152 break;
153
154 case FAERR_ALREADYSENT:
155 wprintw(self->window, "Friend request already sent.\n");
156 break;
157
158 case FAERR_UNKNOWN:
159 wprintw(self->window, "Undefined error when adding friend.\n");
160 break;
161
162 case FAERR_BADCHECKSUM:
163 wprintw(self->window, "Bad checksum in address.\n");
164 break;
165
166 case FAERR_SETNEWNOSPAM:
167 wprintw(self->window, "Nospam was different.\n");
168 break;
169
170 default:
171 wprintw(self->window, "Friend added as %d.\n", num);
172 on_friendadded_cb(m, num);
173 break;
122 } 174 }
123 id_bin[i] = x;
124 }
125
126 for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) {
127 id[i] = toupper(id[i]);
128 }
129
130 int num = m_addfriend(m, id_bin, (uint8_t*) msg, strlen(msg)+1);
131 switch (num) {
132 case FAERR_TOOLONG:
133 wprintw(self->window, "Message is too long.\n");
134 break;
135 case FAERR_NOMESSAGE:
136 wprintw(self->window, "Please add a message to your request.\n");
137 break;
138 case FAERR_OWNKEY:
139 wprintw(self->window, "That appears to be your own ID.\n");
140 break;
141 case FAERR_ALREADYSENT:
142 wprintw(self->window, "Friend request already sent.\n");
143 break;
144 case FAERR_UNKNOWN:
145 wprintw(self->window, "Undefined error when adding friend.\n");
146 break;
147 case FAERR_BADCHECKSUM:
148 wprintw(self->window, "Bad checksum in address.\n");
149 break;
150 case FAERR_SETNEWNOSPAM:
151 wprintw(self->window, "Nospam was different.\n");
152 break;
153 default:
154 wprintw(self->window, "Friend added as %d.\n", num);
155 on_friendadded_cb(m, num);
156 break;
157 }
158} 175}
159 176
160void cmd_clear(ToxWindow *self, Messenger *m, char **args) 177void cmd_clear(ToxWindow *self, Messenger *m, char **args)
161{ 178{
162 wclear(self->window); 179 wclear(self->window);
163} 180}
164 181
165void cmd_connect(ToxWindow *self, Messenger *m, char **args) 182void cmd_connect(ToxWindow *self, Messenger *m, char **args)
166{ 183{
167 IP_Port dht; 184 IP_Port dht;
168 char *ip = args[1]; 185 char *ip = args[1];
169 char *port = args[2]; 186 char *port = args[2];
170 char *key = args[3]; 187 char *key = args[3];
171 188
172 if (atoi(port) == 0) { 189 if (atoi(port) == 0) {
173 wprintw(self->window, "Invalid syntax.\n"); 190 wprintw(self->window, "Invalid syntax.\n");
174 return; 191 return;
175 } 192 }
176 193
177 dht.port = htons(atoi(port)); 194 dht.port = htons(atoi(port));
178 uint32_t resolved_address = resolve_addr(ip); 195 uint32_t resolved_address = resolve_addr(ip);
179 if (resolved_address == 0) { 196
180 return; 197 if (resolved_address == 0) {
181 } 198 return;
182 199 }
183 dht.ip.i = resolved_address; 200
184 unsigned char *binary_string = hex_string_to_bin(key); 201 dht.ip.i = resolved_address;
185 DHT_bootstrap(dht, binary_string); 202 unsigned char *binary_string = hex_string_to_bin(key);
186 free(binary_string); 203 DHT_bootstrap(dht, binary_string);
204 free(binary_string);
187} 205}
188 206
189void cmd_quit(ToxWindow *self, Messenger *m, char **args) 207void cmd_quit(ToxWindow *self, Messenger *m, char **args)
190{ 208{
191 endwin(); 209 endwin();
192 exit(0); 210 exit(0);
193} 211}
194 212
195void cmd_help(ToxWindow *self, Messenger *m, char **args) 213void cmd_help(ToxWindow *self, Messenger *m, char **args)
196{ 214{
197 wclear(self->window); 215 wclear(self->window);
198 wattron(self->window, COLOR_PAIR(2) | A_BOLD); 216 wattron(self->window, COLOR_PAIR(2) | A_BOLD);
199 wprintw(self->window, "Commands:\n"); 217 wprintw(self->window, "Commands:\n");
200 wattroff(self->window, A_BOLD); 218 wattroff(self->window, A_BOLD);
201 219
202 wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n"); 220 wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n");
203 wprintw(self->window, " add <id> <message> : Add friend\n"); 221 wprintw(self->window, " add <id> <message> : Add friend\n");
204 wprintw(self->window, " status <type> <message> : Set your status\n"); 222 wprintw(self->window, " status <type> <message> : Set your status\n");
205 wprintw(self->window, " statusmsg <message> : Set your status\n"); 223 wprintw(self->window, " statusmsg <message> : Set your status\n");
206 wprintw(self->window, " nick <nickname> : Set your nickname\n"); 224 wprintw(self->window, " nick <nickname> : Set your nickname\n");
207 wprintw(self->window, " accept <number> : Accept friend request\n"); 225 wprintw(self->window, " accept <number> : Accept friend request\n");
208 wprintw(self->window, " myid : Print your ID\n"); 226 wprintw(self->window, " myid : Print your ID\n");
209 wprintw(self->window, " quit/exit : Exit program\n"); 227 wprintw(self->window, " quit/exit : Exit program\n");
210 wprintw(self->window, " help : Print this message again\n"); 228 wprintw(self->window, " help : Print this message again\n");
211 wprintw(self->window, " clear : Clear this window\n"); 229 wprintw(self->window, " clear : Clear this window\n");
212 230
213 wattron(self->window, A_BOLD); 231 wattron(self->window, A_BOLD);
214 wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n"); 232 wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n");
215 wattroff(self->window, A_BOLD); 233 wattroff(self->window, A_BOLD);
216 234
217 wattroff(self->window, COLOR_PAIR(2)); 235 wattroff(self->window, COLOR_PAIR(2));
218} 236}
219 237
220void cmd_msg(ToxWindow *self, Messenger *m, char **args) 238void cmd_msg(ToxWindow *self, Messenger *m, char **args)
221{ 239{
222 char *id = args[1]; 240 char *id = args[1];
223 char *msg = args[2]; 241 char *msg = args[2];
224 if (m_sendmessage(m, atoi(id), (uint8_t*) msg, strlen(msg)+1) == 0) 242
225 wprintw(self->window, "Error occurred while sending message.\n"); 243 if (m_sendmessage(m, atoi(id), (uint8_t *) msg, strlen(msg) + 1) == 0)
226 else 244 wprintw(self->window, "Error occurred while sending message.\n");
227 wprintw(self->window, "Message successfully sent.\n"); 245 else
246 wprintw(self->window, "Message successfully sent.\n");
228} 247}
229 248
230void cmd_myid(ToxWindow *self, Messenger *m, char **args) 249void cmd_myid(ToxWindow *self, Messenger *m, char **args)
231{ 250{
232 char id[FRIEND_ADDRESS_SIZE*2 + 1] = {0}; 251 char id[FRIEND_ADDRESS_SIZE * 2 + 1] = {0};
233 size_t i; 252 size_t i;
234 uint8_t address[FRIEND_ADDRESS_SIZE]; 253 uint8_t address[FRIEND_ADDRESS_SIZE];
235 getaddress(m, address); 254 getaddress(m, address);
236 for (i = 0; i < FRIEND_ADDRESS_SIZE; ++i) { 255
237 char xx[3]; 256 for (i = 0; i < FRIEND_ADDRESS_SIZE; ++i) {
238 snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); 257 char xx[3];
239 strcat(id, xx); 258 snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff);
240 } 259 strcat(id, xx);
241 wprintw(self->window, "%s\n", id); 260 }
261
262 wprintw(self->window, "%s\n", id);
242} 263}
243 264
244void cmd_nick(ToxWindow *self, Messenger *m, char **args) 265void cmd_nick(ToxWindow *self, Messenger *m, char **args)
245{ 266{
246 char *nick = args[1]; 267 char *nick = args[1];
247 setname(m, (uint8_t*) nick, strlen(nick)+1); 268 setname(m, (uint8_t *) nick, strlen(nick) + 1);
248 wprintw(self->window, "Nickname set to: %s\n", nick); 269 wprintw(self->window, "Nickname set to: %s\n", nick);
249} 270}
250 271
251void cmd_status(ToxWindow *self, Messenger *m, char **args) 272void cmd_status(ToxWindow *self, Messenger *m, char **args)
252{ 273{
253 char *status = args[1]; 274 char *status = args[1];
254 char *status_text; 275 char *status_text;
255 276
256 USERSTATUS status_kind; 277 USERSTATUS status_kind;
257 if (!strncmp(status, "online", strlen("online"))) { 278
258 status_kind = USERSTATUS_NONE; 279 if (!strncmp(status, "online", strlen("online"))) {
259 status_text = "ONLINE"; 280 status_kind = USERSTATUS_NONE;
260 } 281 status_text = "ONLINE";
261 else if (!strncmp(status, "away", strlen("away"))) { 282 } else if (!strncmp(status, "away", strlen("away"))) {
262 status_kind = USERSTATUS_AWAY; 283 status_kind = USERSTATUS_AWAY;
263 status_text = "AWAY"; 284 status_text = "AWAY";
264 } 285 } else if (!strncmp(status, "busy", strlen("busy"))) {
265 else if (!strncmp(status, "busy", strlen("busy"))) { 286 status_kind = USERSTATUS_BUSY;
266 status_kind = USERSTATUS_BUSY; 287 status_text = "BUSY";
267 status_text = "BUSY"; 288 } else {
268 } 289 wprintw(self->window, "Invalid status.\n");
269 else 290 return;
270 { 291 }
271 wprintw(self->window, "Invalid status.\n"); 292
272 return; 293 char *msg = args[2];
273 } 294
274 295 if (msg == NULL) {
275 char *msg = args[2]; 296 m_set_userstatus(m, status_kind);
276 if (msg == NULL) { 297 wprintw(self->window, "Status set to: %s\n", status_text);
277 m_set_userstatus(m, status_kind); 298 } else {
278 wprintw(self->window, "Status set to: %s\n", status_text); 299 m_set_userstatus(m, status_kind);
279 } 300 m_set_statusmessage(m, (uint8_t *) msg, strlen(msg) + 1);
280 else { 301 wprintw(self->window, "Status set to: %s, %s\n", status_text, msg);
281 m_set_userstatus(m, status_kind); 302 }
282 m_set_statusmessage(m, (uint8_t*) msg, strlen(msg)+1);
283 wprintw(self->window, "Status set to: %s, %s\n", status_text, msg);
284 }
285} 303}
286 304
287void cmd_statusmsg(ToxWindow *self, Messenger *m, char **args) 305void cmd_statusmsg(ToxWindow *self, Messenger *m, char **args)
288{ 306{
289 char *msg = args[1]; 307 char *msg = args[1];
290 m_set_statusmessage(m, (uint8_t*) msg, strlen(msg)+1); 308 m_set_statusmessage(m, (uint8_t *) msg, strlen(msg) + 1);
291 wprintw(self->window, "Status set to: %s\n", msg); 309 wprintw(self->window, "Status set to: %s\n", msg);
292} 310}
293 311
294static void execute(ToxWindow *self, Messenger *m, char *u_cmd) 312static void execute(ToxWindow *self, Messenger *m, char *u_cmd)
295{ 313{
296 int newlines = 0; 314 int newlines = 0;
297 char cmd[MAX_STR_SIZE] = {0}; 315 char cmd[MAX_STR_SIZE] = {0};
298 int i; 316 int i;
299 for (i = 0; i < strlen(prompt_buf); ++i) { 317
300 if (u_cmd[i] == '\n') 318 for (i = 0; i < strlen(prompt_buf); ++i) {
301 ++newlines; 319 if (u_cmd[i] == '\n')
302 else 320 ++newlines;
303 cmd[i - newlines] = u_cmd[i]; 321 else
304 } 322 cmd[i - newlines] = u_cmd[i];
305
306 int leading_spc = 0;
307 for (i = 0; i < MAX_STR_SIZE && isspace(cmd[i]); ++i)
308 leading_spc++;
309 memmove(cmd, cmd + leading_spc, MAX_STR_SIZE - leading_spc);
310
311 int cmd_end = strlen(cmd);
312 while (cmd_end > 0 && cmd_end--)
313 if (!isspace(cmd[cmd_end]))
314 break;
315 cmd[cmd_end + 1] = '\0';
316
317 /* insert \0 at argument boundaries */
318 int numargs = 0;
319 for (i = 0; i < MAX_STR_SIZE; i++) {
320 if (cmd[i] == '\"')
321 while (cmd[++i] != '\"'); /* skip over strings */
322 if (cmd[i] == ' ') {
323 cmd[i] = '\0';
324 numargs++;
325 } 323 }
326 } 324
327 325 int leading_spc = 0;
328 /* excessive arguments */ 326
329 if (numargs > 3) { 327 for (i = 0; i < MAX_STR_SIZE && isspace(cmd[i]); ++i)
330 wprintw(self->window, "Invalid command: too many arguments.\n"); 328 leading_spc++;
331 return; 329
332 } 330 memmove(cmd, cmd + leading_spc, MAX_STR_SIZE - leading_spc);
333 331
334 /* read arguments into array */ 332 int cmd_end = strlen(cmd);
335 char *cmdargs[5]; 333
336 int pos = 0; 334 while (cmd_end > 0 && cmd_end--)
337 for (i = 0; i < 5; i++) { 335 if (!isspace(cmd[cmd_end]))
338 cmdargs[i] = cmd + pos; 336 break;
339 pos += strlen(cmdargs[i]) + 1; 337
340 } 338 cmd[cmd_end + 1] = '\0';
341 339
342 /* no input */ 340 /* insert \0 at argument boundaries */
343 if (strlen(cmdargs[0]) == 0) 341 int numargs = 0;
344 return; 342
345 343 for (i = 0; i < MAX_STR_SIZE; i++) {
346 /* match input to command list */ 344 if (cmd[i] == '\"')
347 for (i = 0; i < NUM_COMMANDS; i++) { 345 while (cmd[++i] != '\"'); /* skip over strings */
348 if (!strcmp(cmdargs[0], commands[i].name)) { 346
349 /* check for missing arguments */ 347 if (cmd[i] == ' ') {
350 int j; 348 cmd[i] = '\0';
351 for (j = 0; j <= commands[i].numargs; j++) { 349 numargs++;
352 if (strlen(cmdargs[j]) == 0) {
353 wprintw(self->window, "Invalid command: %s expected %d arguments, got %d.\n",
354 commands[i].name, commands[i].numargs, j - 1);
355 return;
356 } 350 }
357 } 351 }
358 /* check for excess arguments */ 352
359 if (strcmp(cmdargs[0], "add") && strlen(cmdargs[j]) != 0) { 353 /* excessive arguments */
360 wprintw(self->window, "Invalid command: too many arguments to %s.\n", commands[i].name); 354 if (numargs > 3) {
355 wprintw(self->window, "Invalid command: too many arguments.\n");
361 return; 356 return;
362 }
363 /* pass arguments to command function */
364 (commands[i].func)(self, m, cmdargs);
365 return;
366 } 357 }
367 }
368 358
369 /* no match */ 359 /* read arguments into array */
370 wprintw(self->window, "Invalid command.\n"); 360 char *cmdargs[5];
361 int pos = 0;
362
363 for (i = 0; i < 5; i++) {
364 cmdargs[i] = cmd + pos;
365 pos += strlen(cmdargs[i]) + 1;
366 }
367
368 /* no input */
369 if (strlen(cmdargs[0]) == 0)
370 return;
371
372 /* match input to command list */
373 for (i = 0; i < NUM_COMMANDS; i++) {
374 if (!strcmp(cmdargs[0], commands[i].name)) {
375 /* check for missing arguments */
376 int j;
377
378 for (j = 0; j <= commands[i].numargs; j++) {
379 if (strlen(cmdargs[j]) == 0) {
380 wprintw(self->window, "Invalid command: %s expected %d arguments, got %d.\n",
381 commands[i].name, commands[i].numargs, j - 1);
382 return;
383 }
384 }
385
386 /* check for excess arguments */
387 if (strcmp(cmdargs[0], "add") && strlen(cmdargs[j]) != 0) {
388 wprintw(self->window, "Invalid command: too many arguments to %s.\n", commands[i].name);
389 return;
390 }
391
392 /* pass arguments to command function */
393 (commands[i].func)(self, m, cmdargs);
394 return;
395 }
396 }
397
398 /* no match */
399 wprintw(self->window, "Invalid command.\n");
371} 400}
372 401
373static void prompt_onKey(ToxWindow *self, Messenger *m, int key) 402static void prompt_onKey(ToxWindow *self, Messenger *m, int key)
374{ 403{
375 /* Add printable characters to line */ 404 /* Add printable characters to line */
376 if (isprint(key)) { 405 if (isprint(key)) {
377 if (prompt_buf_pos == (sizeof(prompt_buf) - 1)) { 406 if (prompt_buf_pos == (sizeof(prompt_buf) - 1)) {
378 wprintw(self->window, "\nToo Long.\n"); 407 wprintw(self->window, "\nToo Long.\n");
379 prompt_buf_pos = 0; 408 prompt_buf_pos = 0;
380 prompt_buf[0] = 0; 409 prompt_buf[0] = 0;
381 } 410 } else if (!(prompt_buf_pos == 0) && (prompt_buf_pos < COLS)
382 else if (!(prompt_buf_pos == 0) && (prompt_buf_pos < COLS) 411 && (prompt_buf_pos % (COLS - 3) == 0)) {
383 && (prompt_buf_pos % (COLS - 3) == 0)) { 412 prompt_buf[prompt_buf_pos++] = '\n';
384 prompt_buf[prompt_buf_pos++] = '\n'; 413 } else if (!(prompt_buf_pos == 0) && (prompt_buf_pos > COLS)
414 && ((prompt_buf_pos - (COLS - 3)) % (COLS) == 0)) {
415 prompt_buf[prompt_buf_pos++] = '\n';
416 }
417
418 prompt_buf[prompt_buf_pos++] = key;
419 prompt_buf[prompt_buf_pos] = 0;
385 } 420 }
386 else if (!(prompt_buf_pos == 0) && (prompt_buf_pos > COLS) 421
387 && ((prompt_buf_pos - (COLS - 3)) % (COLS) == 0)) { 422 /* RETURN key: execute command */
388 prompt_buf[prompt_buf_pos++] = '\n'; 423 else if (key == '\n') {
424 wprintw(self->window, "\n");
425 execute(self, m, prompt_buf);
426 prompt_buf_pos = 0;
427 prompt_buf[0] = 0;
389 } 428 }
390 prompt_buf[prompt_buf_pos++] = key; 429
391 prompt_buf[prompt_buf_pos] = 0; 430 /* BACKSPACE key: Remove one character from line */
392 } 431 else if (key == 0x107 || key == 0x8 || key == 0x7f) {
393 432 if (prompt_buf_pos != 0) {
394 /* RETURN key: execute command */ 433 prompt_buf[--prompt_buf_pos] = 0;
395 else if (key == '\n') { 434 }
396 wprintw(self->window, "\n");
397 execute(self, m, prompt_buf);
398 prompt_buf_pos = 0;
399 prompt_buf[0] = 0;
400 }
401
402 /* BACKSPACE key: Remove one character from line */
403 else if (key == 0x107 || key == 0x8 || key == 0x7f) {
404 if (prompt_buf_pos != 0) {
405 prompt_buf[--prompt_buf_pos] = 0;
406 } 435 }
407 }
408} 436}
409 437
410static void prompt_onDraw(ToxWindow *self) 438static void prompt_onDraw(ToxWindow *self)
411{ 439{
412 curs_set(1); 440 curs_set(1);
413 int x, y; 441 int x, y;
414 getyx(self->window, y, x); 442 getyx(self->window, y, x);
415 (void) x; 443 (void) x;
416 int i; 444 int i;
417 for (i = 0; i < (strlen(prompt_buf)); ++i) { 445
418 if ((prompt_buf[i] == '\n') && (y != 0)) 446 for (i = 0; i < (strlen(prompt_buf)); ++i) {
419 --y; 447 if ((prompt_buf[i] == '\n') && (y != 0))
420 } 448 --y;
421 449 }
422 wattron(self->window, COLOR_PAIR(1)); 450
423 mvwprintw(self->window, y, 0, "# "); 451 wattron(self->window, COLOR_PAIR(1));
424 wattroff(self->window, COLOR_PAIR(1)); 452 mvwprintw(self->window, y, 0, "# ");
425 mvwprintw(self->window, y, 2, "%s", prompt_buf); 453 wattroff(self->window, COLOR_PAIR(1));
426 wclrtoeol(self->window); 454 mvwprintw(self->window, y, 2, "%s", prompt_buf);
427 wrefresh(self->window); 455 wclrtoeol(self->window);
456 wrefresh(self->window);
428} 457}
429 458
430static void prompt_onInit(ToxWindow *self, Messenger *m) 459static void prompt_onInit(ToxWindow *self, Messenger *m)
431{ 460{
432 scrollok(self->window, 1); 461 scrollok(self->window, 1);
433 cmd_help(self, m, NULL); 462 cmd_help(self, m, NULL);
434 wclrtoeol(self->window); 463 wclrtoeol(self->window);
435} 464}
436 465
437ToxWindow new_prompt(friendAddedFn *f) 466ToxWindow new_prompt(friendAddedFn *f)
438{ 467{
439 on_friendadded_cb = f; 468 on_friendadded_cb = f;
440 ToxWindow ret; 469 ToxWindow ret;
441 memset(&ret, 0, sizeof(ret)); 470 memset(&ret, 0, sizeof(ret));
442 ret.onKey = &prompt_onKey; 471 ret.onKey = &prompt_onKey;
443 ret.onDraw = &prompt_onDraw; 472 ret.onDraw = &prompt_onDraw;
444 ret.onInit = &prompt_onInit; 473 ret.onInit = &prompt_onInit;
445 strcpy(ret.title, "[prompt]"); 474 strcpy(ret.title, "[prompt]");
446 return ret; 475 return ret;
447} 476}
diff --git a/testing/toxic/windows.c b/testing/toxic/windows.c
index 15caddf7..183c0f9b 100644
--- a/testing/toxic/windows.c
+++ b/testing/toxic/windows.c
@@ -14,232 +14,258 @@ static ToxWindow windows[MAX_WINDOW_SLOTS];
14static Messenger *m; 14static Messenger *m;
15int active_window; 15int active_window;
16 16
17static ToxWindow* prompt; 17static ToxWindow *prompt;
18 18
19/* CALLBACKS START */ 19/* CALLBACKS START */
20void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void* userdata) 20void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata)
21{ 21{
22 int n = add_req(public_key); 22 int n = add_req(public_key);
23 wprintw(prompt->window, "\nFriend request from:\n"); 23 wprintw(prompt->window, "\nFriend request from:\n");
24 24
25 int i; 25 int i;
26 for (i = 0; i < KEY_SIZE_BYTES; ++i) {
27 wprintw(prompt->window, "%02x", public_key[i] & 0xff);
28 }
29 26
30 wprintw(prompt->window, "\nWith the message: %s\n", data); 27 for (i = 0; i < KEY_SIZE_BYTES; ++i) {
31 wprintw(prompt->window, "\nUse \"accept %d\" to accept it.\n", n); 28 wprintw(prompt->window, "%02x", public_key[i] & 0xff);
29 }
30
31 wprintw(prompt->window, "\nWith the message: %s\n", data);
32 wprintw(prompt->window, "\nUse \"accept %d\" to accept it.\n", n);
32 33
33 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { 34 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
34 if (windows[i].onFriendRequest != NULL) 35 if (windows[i].onFriendRequest != NULL)
35 windows[i].onFriendRequest(&windows[i], public_key, data, length); 36 windows[i].onFriendRequest(&windows[i], public_key, data, length);
36 } 37 }
37} 38}
38 39
39void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) 40void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata)
40{ 41{
41 int i; 42 int i;
42 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { 43
43 if (windows[i].onMessage != NULL) 44 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
44 windows[i].onMessage(&windows[i], m, friendnumber, string, length); 45 if (windows[i].onMessage != NULL)
45 } 46 windows[i].onMessage(&windows[i], m, friendnumber, string, length);
47 }
46} 48}
47 49
48void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) 50void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata)
49{ 51{
50 int i; 52 int i;
51 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { 53
52 if (windows[i].onAction != NULL) 54 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
53 windows[i].onAction(&windows[i], m, friendnumber, string, length); 55 if (windows[i].onAction != NULL)
54 } 56 windows[i].onAction(&windows[i], m, friendnumber, string, length);
57 }
55} 58}
56 59
57void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) 60void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata)
58{ 61{
59 wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string); 62 wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string);
60 int i; 63 int i;
61 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { 64
62 if (windows[i].onNickChange != NULL) 65 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
63 windows[i].onNickChange(&windows[i], friendnumber, string, length); 66 if (windows[i].onNickChange != NULL)
64 } 67 windows[i].onNickChange(&windows[i], friendnumber, string, length);
68 }
65} 69}
66 70
67void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata) 71void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata)
68{ 72{
69 wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); 73 wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string);
70 int i; 74 int i;
71 for (i=0; i<MAX_WINDOW_SLOTS; ++i) { 75
72 if (windows[i].onStatusChange != NULL) 76 for (i = 0; i < MAX_WINDOW_SLOTS; ++i) {
73 windows[i].onStatusChange(&windows[i], friendnumber, string, length); 77 if (windows[i].onStatusChange != NULL)
74 } 78 windows[i].onStatusChange(&windows[i], friendnumber, string, length);
79 }
75} 80}
76 81
77void on_friendadded(Messenger *m, int friendnumber) 82void on_friendadded(Messenger *m, int friendnumber)
78{ 83{
79 friendlist_onFriendAdded(m, friendnumber); 84 friendlist_onFriendAdded(m, friendnumber);
80 if (store_data(m, DATA_FILE) != 0) { 85
81 wprintw(prompt->window, "\nCould not store Messenger data\n"); 86 if (store_data(m, DATA_FILE) != 0) {
82 } 87 wprintw(prompt->window, "\nCould not store Messenger data\n");
88 }
83} 89}
84/* CALLBACKS END */ 90/* CALLBACKS END */
85 91
86int add_window(Messenger *m, ToxWindow w, int n) 92int add_window(Messenger *m, ToxWindow w, int n)
87{ 93{
88 if (w_num >= TOXWINDOWS_MAX_NUM) 94 if (w_num >= TOXWINDOWS_MAX_NUM)
89 return -1; 95 return -1;
96
97 if (LINES < 2)
98 return -1;
90 99
91 if (LINES < 2) 100 w.window = newwin(LINES - 2, COLS, 0, 0);
92 return -1;
93 101
94 w.window = newwin(LINES - 2, COLS, 0, 0); 102 if (w.window == NULL)
95 if (w.window == NULL) 103 return -1;
96 return -1;
97 104
98 windows[n] = w; 105 windows[n] = w;
99 w.onInit(&w, m); 106 w.onInit(&w, m);
100 w_num++; 107 w_num++;
101 active_window = n; 108 active_window = n;
102 return n; 109 return n;
103} 110}
104 111
105/* Deletes window w and cleans up */ 112/* Deletes window w and cleans up */
106void del_window(ToxWindow *w, int f_num) 113void del_window(ToxWindow *w, int f_num)
107{ 114{
108 active_window = 0; // Go to prompt screen 115 active_window = 0; // Go to prompt screen
109 delwin(w->window); 116 delwin(w->window);
110 int i; 117 int i;
111 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { 118
112 if (WINDOW_STATUS[i] == f_num) { 119 for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) {
113 WINDOW_STATUS[i] = -1; 120 if (WINDOW_STATUS[i] == f_num) {
114 disable_chatwin(f_num); 121 WINDOW_STATUS[i] = -1;
115 break; 122 disable_chatwin(f_num);
123 break;
124 }
116 } 125 }
117 } 126
118 clear(); 127 clear();
119 refresh(); 128 refresh();
120} 129}
121 130
122/* Shows next window when tab or back-tab is pressed */ 131/* Shows next window when tab or back-tab is pressed */
123void set_active_window(int ch) 132void set_active_window(int ch)
124{ 133{
125 int f_inf = 0; 134 int f_inf = 0;
126 int max = MAX_WINDOW_SLOTS-1; 135 int max = MAX_WINDOW_SLOTS - 1;
127 if (ch == '\t') { 136
128 int i = (active_window + 1) % max; 137 if (ch == '\t') {
129 while (true) { 138 int i = (active_window + 1) % max;
130 if (WINDOW_STATUS[i] != -1) { 139
131 active_window = i; 140 while (true) {
132 return; 141 if (WINDOW_STATUS[i] != -1) {
133 } 142 active_window = i;
134 i = (i + 1) % max; 143 return;
135 if (f_inf++ > max) { // infinite loop check 144 }
136 endwin(); 145
137 exit(2); 146 i = (i + 1) % max;
138 } 147
139 } 148 if (f_inf++ > max) { // infinite loop check
140 }else { 149 endwin();
141 int i = active_window - 1; 150 exit(2);
142 if (i < 0) i = max; 151 }
143 while (true) { 152 }
144 if (WINDOW_STATUS[i] != -1) { 153 } else {
145 active_window = i; 154 int i = active_window - 1;
146 return; 155
147 } 156 if (i < 0) i = max;
148 if (--i < 0) i = max; 157
149 if (f_inf++ > max) { 158 while (true) {
150 endwin(); 159 if (WINDOW_STATUS[i] != -1) {
151 exit(2); 160 active_window = i;
152 } 161 return;
162 }
163
164 if (--i < 0) i = max;
165
166 if (f_inf++ > max) {
167 endwin();
168 exit(2);
169 }
170 }
153 } 171 }
154 }
155} 172}
156 173
157void init_window_status() 174void init_window_status()
158{ 175{
159 /* Default window values decrement from -2 */ 176 /* Default window values decrement from -2 */
160 int i; 177 int i;
161 for (i = 0; i < N_DEFAULT_WINS; ++i) 178
162 WINDOW_STATUS[i] = -(i+2); 179 for (i = 0; i < N_DEFAULT_WINS; ++i)
163 180 WINDOW_STATUS[i] = -(i + 2);
164 int j; 181
165 for (j = N_DEFAULT_WINS; j < MAX_WINDOW_SLOTS; j++) 182 int j;
166 WINDOW_STATUS[j] = -1; 183
184 for (j = N_DEFAULT_WINS; j < MAX_WINDOW_SLOTS; j++)
185 WINDOW_STATUS[j] = -1;
167} 186}
168 187
169ToxWindow *init_windows() 188ToxWindow *init_windows()
170{ 189{
171 w_num = 0; 190 w_num = 0;
172 int n_prompt = 0; 191 int n_prompt = 0;
173 int n_friendslist = 1; 192 int n_friendslist = 1;
174 int n_dhtstatus = 2; 193 int n_dhtstatus = 2;
175 if (add_window(m, new_prompt(on_friendadded), n_prompt) == -1 194
176 || add_window(m, new_friendlist(WINDOW_STATUS), n_friendslist) == -1 195 if (add_window(m, new_prompt(on_friendadded), n_prompt) == -1
177 || add_window(m, new_dhtstatus(), n_dhtstatus) == -1) { 196 || add_window(m, new_friendlist(WINDOW_STATUS), n_friendslist) == -1
178 fprintf(stderr, "add_window() failed.\n"); 197 || add_window(m, new_dhtstatus(), n_dhtstatus) == -1) {
179 endwin(); 198 fprintf(stderr, "add_window() failed.\n");
180 exit(1); 199 endwin();
181 } 200 exit(1);
182 active_window = n_prompt; 201 }
183 prompt = &windows[n_prompt]; 202
184 return prompt; 203 active_window = n_prompt;
204 prompt = &windows[n_prompt];
205 return prompt;
185} 206}
186 207
187static void draw_bar() 208static void draw_bar()
188{ 209{
189 static int odd = 0; 210 static int odd = 0;
190 int blinkrate = 30; 211 int blinkrate = 30;
212
213 attron(COLOR_PAIR(4));
214 mvhline(LINES - 2, 0, '_', COLS);
215 attroff(COLOR_PAIR(4));
216
217 move(LINES - 1, 0);
218
219 attron(COLOR_PAIR(4) | A_BOLD);
220 printw(" TOXIC " TOXICVER "|");
221 attroff(COLOR_PAIR(4) | A_BOLD);
191 222
192 attron(COLOR_PAIR(4)); 223 int i;
193 mvhline(LINES - 2, 0, '_', COLS);
194 attroff(COLOR_PAIR(4));
195 224
196 move(LINES - 1, 0); 225 for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) {
226 if (WINDOW_STATUS[i] != -1) {
227 if (i == active_window)
228 attron(A_BOLD);
197 229
198 attron(COLOR_PAIR(4) | A_BOLD); 230 odd = (odd + 1) % blinkrate;
199 printw(" TOXIC " TOXICVER "|");
200 attroff(COLOR_PAIR(4) | A_BOLD);
201 231
202 int i; 232 if (windows[i].blink && (odd < (blinkrate / 2)))
203 for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) { 233 attron(COLOR_PAIR(3));
204 if (WINDOW_STATUS[i] != -1) {
205 if (i == active_window)
206 attron(A_BOLD);
207 234
208 odd = (odd+1) % blinkrate; 235 printw(" %s", windows[i].title);
209 if (windows[i].blink && (odd < (blinkrate/2)))
210 attron(COLOR_PAIR(3));
211 236
212 printw(" %s", windows[i].title); 237 if (windows[i].blink && (odd < (blinkrate / 2)))
213 if (windows[i].blink && (odd < (blinkrate/2))) 238 attroff(COLOR_PAIR(3));
214 attroff(COLOR_PAIR(3));
215 239
216 if (i == active_window) { 240 if (i == active_window) {
217 attroff(A_BOLD); 241 attroff(A_BOLD);
218 } 242 }
243 }
219 } 244 }
220 } 245
221 refresh(); 246 refresh();
222} 247}
223 248
224void prepare_window(WINDOW *w) 249void prepare_window(WINDOW *w)
225{ 250{
226 mvwin(w, 0, 0); 251 mvwin(w, 0, 0);
227 wresize(w, LINES-2, COLS); 252 wresize(w, LINES - 2, COLS);
228} 253}
229 254
230void draw_active_window(Messenger *m) 255void draw_active_window(Messenger *m)
231{ 256{
232 257
233 ToxWindow *a = &windows[active_window]; 258 ToxWindow *a = &windows[active_window];
234 prepare_window(a->window); 259 prepare_window(a->window);
235 a->blink = false; 260 a->blink = false;
236 draw_bar(); 261 draw_bar();
237 a->onDraw(a); 262 a->onDraw(a);
238 263
239 /* Handle input */ 264 /* Handle input */
240 int ch = getch(); 265 int ch = getch();
241 if (ch == '\t' || ch == KEY_BTAB) 266
242 set_active_window(ch); 267 if (ch == '\t' || ch == KEY_BTAB)
243 else if (ch != ERR) 268 set_active_window(ch);
244 a->onKey(a, m, ch); 269 else if (ch != ERR)
270 a->onKey(a, m, ch);
245} 271}
diff --git a/testing/toxic/windows.h b/testing/toxic/windows.h
index 9f4d74a2..553a6200 100644
--- a/testing/toxic/windows.h
+++ b/testing/toxic/windows.h
@@ -26,31 +26,31 @@
26typedef struct ToxWindow_ ToxWindow; 26typedef struct ToxWindow_ ToxWindow;
27 27
28struct ToxWindow_ { 28struct ToxWindow_ {
29 void(*onKey)(ToxWindow*, Messenger*, int); 29 void(*onKey)(ToxWindow *, Messenger *, int);
30 void(*onDraw)(ToxWindow*); 30 void(*onDraw)(ToxWindow *);
31 void(*onInit)(ToxWindow*, Messenger*); 31 void(*onInit)(ToxWindow *, Messenger *);
32 void(*onFriendRequest)(ToxWindow*, uint8_t*, uint8_t*, uint16_t); 32 void(*onFriendRequest)(ToxWindow *, uint8_t *, uint8_t *, uint16_t);
33 void(*onMessage)(ToxWindow*, Messenger*, int, uint8_t*, uint16_t); 33 void(*onMessage)(ToxWindow *, Messenger *, int, uint8_t *, uint16_t);
34 void(*onNickChange)(ToxWindow*, int, uint8_t*, uint16_t); 34 void(*onNickChange)(ToxWindow *, int, uint8_t *, uint16_t);
35 void(*onStatusChange)(ToxWindow*, int, uint8_t*, uint16_t); 35 void(*onStatusChange)(ToxWindow *, int, uint8_t *, uint16_t);
36 void(*onAction)(ToxWindow*, Messenger*, int, uint8_t*, uint16_t); 36 void(*onAction)(ToxWindow *, Messenger *, int, uint8_t *, uint16_t);
37 char title[256]; 37 char title[256];
38 38
39 void* x; 39 void *x;
40 bool blink; 40 bool blink;
41 41
42 WINDOW* window; 42 WINDOW *window;
43}; 43};
44 44
45void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void* userdata); 45void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata);
46void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); 46void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
47void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); 47void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
48void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); 48void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
49void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void* userdata); 49void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
50void on_friendadded(Messenger *m, int friendnumber); 50void on_friendadded(Messenger *m, int friendnumber);
51void init_window_status(); 51void init_window_status();
52ToxWindow * init_windows(); 52ToxWindow *init_windows();
53void draw_active_window(Messenger * m); 53void draw_active_window(Messenger *m);
54int add_window(Messenger *m, ToxWindow w, int n); 54int add_window(Messenger *m, ToxWindow w, int n);
55void del_window(ToxWindow *w, int f_num); 55void del_window(ToxWindow *w, int f_num);
56void set_active_window(int ch); 56void set_active_window(int ch);