diff options
-rw-r--r-- | core/Messenger.c | 28 | ||||
-rw-r--r-- | core/Messenger.h | 10 | ||||
-rw-r--r-- | testing/toxic/chat.c | 66 | ||||
-rw-r--r-- | testing/toxic/friendlist.c | 1 | ||||
-rw-r--r-- | testing/toxic/main.c | 26 | ||||
-rw-r--r-- | testing/toxic/windows.h | 1 |
6 files changed, 117 insertions, 15 deletions
diff --git a/core/Messenger.c b/core/Messenger.c index 90dfe48d..af4fd797 100644 --- a/core/Messenger.c +++ b/core/Messenger.c | |||
@@ -247,6 +247,21 @@ uint32_t m_sendmessage_withid(int friendnumber, uint32_t theid, uint8_t *message | |||
247 | return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 1 + sizeof(theid)); | 247 | return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 1 + sizeof(theid)); |
248 | } | 248 | } |
249 | 249 | ||
250 | /* send an action to an online friend | ||
251 | return 1 if packet was successfully put into the send queue | ||
252 | return 0 if it was not */ | ||
253 | int m_sendaction(int friendnumber, uint8_t *action, uint32_t length) | ||
254 | { | ||
255 | if (friendnumber < 0 || friendnumber >= numfriends) | ||
256 | return 0; | ||
257 | if (length >= MAX_DATA_SIZE || friendlist[friendnumber].status != FRIEND_ONLINE) | ||
258 | return 0; | ||
259 | uint8_t temp[MAX_DATA_SIZE]; | ||
260 | temp[0] = PACKET_ID_ACTION; | ||
261 | memcpy(temp + 1, action, length); | ||
262 | return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 1); | ||
263 | } | ||
264 | |||
250 | /* send a name packet to friendnumber | 265 | /* send a name packet to friendnumber |
251 | length is the length with the NULL terminator*/ | 266 | length is the length with the NULL terminator*/ |
252 | static int m_sendname(int friendnumber, uint8_t * name, uint16_t length) | 267 | static int m_sendname(int friendnumber, uint8_t * name, uint16_t length) |
@@ -447,6 +462,14 @@ void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)) | |||
447 | friend_message_isset = 1; | 462 | friend_message_isset = 1; |
448 | } | 463 | } |
449 | 464 | ||
465 | static void (*friend_action)(int, uint8_t *, uint16_t); | ||
466 | static uint8_t friend_action_isset = 0; | ||
467 | void m_callback_action(void (*function)(int, uint8_t *, uint16_t)) | ||
468 | { | ||
469 | friend_action = function; | ||
470 | friend_action_isset = 1; | ||
471 | } | ||
472 | |||
450 | static void (*friend_namechange)(int, uint8_t *, uint16_t); | 473 | static void (*friend_namechange)(int, uint8_t *, uint16_t); |
451 | static uint8_t friend_namechange_isset = 0; | 474 | static uint8_t friend_namechange_isset = 0; |
452 | void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)) | 475 | void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)) |
@@ -606,6 +629,11 @@ static void doFriends(void) | |||
606 | (*friend_message)(i, temp + 5, len - 5); | 629 | (*friend_message)(i, temp + 5, len - 5); |
607 | break; | 630 | break; |
608 | } | 631 | } |
632 | case PACKET_ID_ACTION: { | ||
633 | if (friend_action_isset) | ||
634 | (*friend_action)(i, temp + 1, len - 1); | ||
635 | break; | ||
636 | } | ||
609 | case PACKET_ID_RECEIPT: { | 637 | case PACKET_ID_RECEIPT: { |
610 | uint32_t msgid; | 638 | uint32_t msgid; |
611 | if (len < 1 + sizeof(msgid)) | 639 | if (len < 1 + sizeof(msgid)) |
diff --git a/core/Messenger.h b/core/Messenger.h index 3044122b..55c86682 100644 --- a/core/Messenger.h +++ b/core/Messenger.h | |||
@@ -43,6 +43,7 @@ extern "C" { | |||
43 | #define PACKET_ID_USERSTATUS 50 | 43 | #define PACKET_ID_USERSTATUS 50 |
44 | #define PACKET_ID_RECEIPT 65 | 44 | #define PACKET_ID_RECEIPT 65 |
45 | #define PACKET_ID_MESSAGE 64 | 45 | #define PACKET_ID_MESSAGE 64 |
46 | #define PACKET_ID_ACTION 63 | ||
46 | 47 | ||
47 | /* status definitions */ | 48 | /* status definitions */ |
48 | #define FRIEND_ONLINE 4 | 49 | #define FRIEND_ONLINE 4 |
@@ -122,6 +123,11 @@ int m_friendstatus(int friendnumber); | |||
122 | uint32_t m_sendmessage(int friendnumber, uint8_t *message, uint32_t length); | 123 | uint32_t m_sendmessage(int friendnumber, uint8_t *message, uint32_t length); |
123 | uint32_t m_sendmessage_withid(int friendnumber, uint32_t theid, uint8_t *message, uint32_t length); | 124 | uint32_t m_sendmessage_withid(int friendnumber, uint32_t theid, uint8_t *message, uint32_t length); |
124 | 125 | ||
126 | /* send an action to an online friend | ||
127 | returns 1 if packet was successfully put into the send queue | ||
128 | return 0 if it was not */ | ||
129 | int m_sendaction(int friendnumber, uint8_t *action, uint32_t length); | ||
130 | |||
125 | /* Set our nickname | 131 | /* Set our nickname |
126 | name must be a string of maximum MAX_NAME_LENGTH length. | 132 | name must be a string of maximum MAX_NAME_LENGTH length. |
127 | length must be at least 1 byte | 133 | length must be at least 1 byte |
@@ -178,6 +184,10 @@ void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); | |||
178 | function format is: function(int friendnumber, uint8_t * message, uint32_t length) */ | 184 | function format is: function(int friendnumber, uint8_t * message, uint32_t length) */ |
179 | void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)); | 185 | void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)); |
180 | 186 | ||
187 | /* set the function that will be executed when an action from a friend is received. | ||
188 | function format is: function(int friendnumber, uint8_t * action, uint32_t length) */ | ||
189 | void m_callback_action(void (*function)(int, uint8_t *, uint16_t)); | ||
190 | |||
181 | /* set the callback for name changes | 191 | /* set the callback for name changes |
182 | function(int friendnumber, uint8_t *newname, uint16_t length) | 192 | function(int friendnumber, uint8_t *newname, uint16_t length) |
183 | you are not responsible for freeing newname */ | 193 | you are not responsible for freeing newname */ |
diff --git a/testing/toxic/chat.c b/testing/toxic/chat.c index 83765777..73cb1458 100644 --- a/testing/toxic/chat.c +++ b/testing/toxic/chat.c | |||
@@ -27,7 +27,7 @@ extern int active_window; | |||
27 | extern void del_window(ToxWindow *w, int f_num); | 27 | extern void del_window(ToxWindow *w, int f_num); |
28 | extern void fix_name(uint8_t *name); | 28 | extern void fix_name(uint8_t *name); |
29 | void print_help(ChatContext *self); | 29 | void print_help(ChatContext *self); |
30 | void execute(ToxWindow *self, ChatContext *ctx, char *cmd); | 30 | void execute(ToxWindow *self, ChatContext *ctx, char *cmd, struct tm *timeinfo); |
31 | 31 | ||
32 | static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len) | 32 | static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len) |
33 | { | 33 | { |
@@ -35,7 +35,7 @@ static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len) | |||
35 | uint8_t nick[MAX_NAME_LENGTH] = {0}; | 35 | uint8_t nick[MAX_NAME_LENGTH] = {0}; |
36 | time_t now; | 36 | time_t now; |
37 | time(&now); | 37 | time(&now); |
38 | struct tm * timeinfo; | 38 | struct tm *timeinfo; |
39 | timeinfo = localtime(&now); | 39 | timeinfo = localtime(&now); |
40 | 40 | ||
41 | if (ctx->friendnum != num) | 41 | if (ctx->friendnum != num) |
@@ -59,6 +59,32 @@ static void chat_onMessage(ToxWindow *self, int num, uint8_t *msg, uint16_t len) | |||
59 | beep(); | 59 | beep(); |
60 | } | 60 | } |
61 | 61 | ||
62 | static void chat_onAction(ToxWindow *self, int num, uint8_t *action, uint16_t len) | ||
63 | { | ||
64 | ChatContext *ctx = (ChatContext*) self->x; | ||
65 | time_t now; | ||
66 | time(&now); | ||
67 | struct tm *timeinfo; | ||
68 | timeinfo = localtime(&now); | ||
69 | |||
70 | if (ctx->friendnum != num) | ||
71 | return; | ||
72 | |||
73 | action[len-1] = '\0'; | ||
74 | fix_name(action); | ||
75 | |||
76 | wattron(ctx->history, COLOR_PAIR(2)); | ||
77 | wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); | ||
78 | wattroff(ctx->history, COLOR_PAIR(2)); | ||
79 | |||
80 | wattron(ctx->history, COLOR_PAIR(4)); | ||
81 | wprintw(ctx->history, "%s\n", action); | ||
82 | wattroff(ctx->history, COLOR_PAIR(4)); | ||
83 | |||
84 | self->blink = true; | ||
85 | beep(); | ||
86 | } | ||
87 | |||
62 | static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len) | 88 | static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len) |
63 | { | 89 | { |
64 | ChatContext *ctx = (ChatContext*) self->x; | 90 | ChatContext *ctx = (ChatContext*) self->x; |
@@ -108,7 +134,7 @@ static void chat_onKey(ToxWindow *self, int key) | |||
108 | /* RETURN key: Execute command or print line */ | 134 | /* RETURN key: Execute command or print line */ |
109 | else if (key == '\n') { | 135 | else if (key == '\n') { |
110 | if (ctx->line[0] == '/') | 136 | if (ctx->line[0] == '/') |
111 | execute(self, ctx, ctx->line); | 137 | execute(self, ctx, ctx->line, timeinfo); |
112 | else { | 138 | else { |
113 | if (!string_is_empty(ctx->line)) { | 139 | if (!string_is_empty(ctx->line)) { |
114 | /* make sure the string has at least non-space character */ | 140 | /* make sure the string has at least non-space character */ |
@@ -138,7 +164,7 @@ static void chat_onKey(ToxWindow *self, int key) | |||
138 | } | 164 | } |
139 | } | 165 | } |
140 | 166 | ||
141 | void execute(ToxWindow *self, ChatContext *ctx, char *cmd) | 167 | void execute(ToxWindow *self, ChatContext *ctx, char *cmd, struct tm *timeinfo) |
142 | { | 168 | { |
143 | if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { | 169 | if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { |
144 | wclear(self->window); | 170 | wclear(self->window); |
@@ -153,6 +179,33 @@ void execute(ToxWindow *self, ChatContext *ctx, char *cmd) | |||
153 | exit(0); | 179 | exit(0); |
154 | } | 180 | } |
155 | 181 | ||
182 | else if (!strncmp(cmd, "/me ", strlen("/me "))) { | ||
183 | char *action = strchr(cmd, ' '); | ||
184 | if (action == NULL) { | ||
185 | wprintw(self->window, "Invalid syntax.\n"); | ||
186 | return; | ||
187 | } | ||
188 | action++; | ||
189 | |||
190 | wattron(ctx->history, COLOR_PAIR(2)); | ||
191 | wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); | ||
192 | wattroff(ctx->history, COLOR_PAIR(2)); | ||
193 | |||
194 | uint8_t selfname[MAX_NAME_LENGTH]; | ||
195 | int len = getself_name(selfname); | ||
196 | char msg[MAX_STR_SIZE-len-4]; | ||
197 | snprintf(msg, sizeof(msg), "* %s %s\n", (uint8_t*) selfname, action); | ||
198 | |||
199 | wattron(ctx->history, COLOR_PAIR(1)); | ||
200 | wprintw(ctx->history, msg); | ||
201 | wattroff(ctx->history, COLOR_PAIR(1)); | ||
202 | if (m_sendaction(ctx->friendnum, (uint8_t*) msg, strlen(msg)+1) < 0) { | ||
203 | wattron(ctx->history, COLOR_PAIR(3)); | ||
204 | wprintw(ctx->history, " * Failed to send action\n"); | ||
205 | wattroff(ctx->history, COLOR_PAIR(3)); | ||
206 | } | ||
207 | } | ||
208 | |||
156 | else if (!strncmp(cmd, "/status ", strlen("/status "))) { | 209 | else if (!strncmp(cmd, "/status ", strlen("/status "))) { |
157 | char *status = strchr(cmd, ' '); | 210 | char *status = strchr(cmd, ' '); |
158 | char *msg; | 211 | char *msg; |
@@ -178,8 +231,7 @@ void execute(ToxWindow *self, ChatContext *ctx, char *cmd) | |||
178 | status_text = "BUSY"; | 231 | status_text = "BUSY"; |
179 | } | 232 | } |
180 | 233 | ||
181 | else | 234 | else { |
182 | { | ||
183 | wprintw(ctx->history, "Invalid status.\n"); | 235 | wprintw(ctx->history, "Invalid status.\n"); |
184 | return; | 236 | return; |
185 | } | 237 | } |
@@ -265,6 +317,7 @@ void print_help(ChatContext *self) | |||
265 | 317 | ||
266 | wprintw(self->history, " /status <type> <message> : Set your status\n"); | 318 | wprintw(self->history, " /status <type> <message> : Set your status\n"); |
267 | wprintw(self->history, " /nick <nickname> : Set your nickname\n"); | 319 | wprintw(self->history, " /nick <nickname> : Set your nickname\n"); |
320 | wprintw(self->history, " /me <action> : Do an action\n"); | ||
268 | wprintw(self->history, " /myid : Print your ID\n"); | 321 | wprintw(self->history, " /myid : Print your ID\n"); |
269 | wprintw(self->history, " /clear : Clear the screen\n"); | 322 | wprintw(self->history, " /clear : Clear the screen\n"); |
270 | wprintw(self->history, " /close : Close the current chat window\n"); | 323 | wprintw(self->history, " /close : Close the current chat window\n"); |
@@ -285,6 +338,7 @@ ToxWindow new_chat(int friendnum) | |||
285 | ret.onMessage = &chat_onMessage; | 338 | ret.onMessage = &chat_onMessage; |
286 | ret.onNickChange = &chat_onNickChange; | 339 | ret.onNickChange = &chat_onNickChange; |
287 | ret.onStatusChange = &chat_onStatusChange; | 340 | ret.onStatusChange = &chat_onStatusChange; |
341 | ret.onAction = &chat_onAction; | ||
288 | 342 | ||
289 | uint8_t nick[MAX_NAME_LENGTH] = {0}; | 343 | uint8_t nick[MAX_NAME_LENGTH] = {0}; |
290 | getname(friendnum, (uint8_t*) &nick); | 344 | getname(friendnum, (uint8_t*) &nick); |
diff --git a/testing/toxic/friendlist.c b/testing/toxic/friendlist.c index 159217b1..f2aa1cf4 100644 --- a/testing/toxic/friendlist.c +++ b/testing/toxic/friendlist.c | |||
@@ -177,6 +177,7 @@ ToxWindow new_friendlist() { | |||
177 | ret.onDraw = &friendlist_onDraw; | 177 | ret.onDraw = &friendlist_onDraw; |
178 | ret.onInit = &friendlist_onInit; | 178 | ret.onInit = &friendlist_onInit; |
179 | ret.onMessage = &friendlist_onMessage; | 179 | ret.onMessage = &friendlist_onMessage; |
180 | ret.onAction = &friendlist_onMessage; // Action has identical behaviour to message | ||
180 | ret.onNickChange = &friendlist_onNickChange; | 181 | ret.onNickChange = &friendlist_onNickChange; |
181 | ret.onStatusChange = &friendlist_onStatusChange; | 182 | ret.onStatusChange = &friendlist_onStatusChange; |
182 | 183 | ||
diff --git a/testing/toxic/main.c b/testing/toxic/main.c index 162cce68..2922456e 100644 --- a/testing/toxic/main.c +++ b/testing/toxic/main.c | |||
@@ -53,8 +53,9 @@ void on_request(uint8_t *public_key, uint8_t *data, uint16_t length) | |||
53 | wprintw(prompt->window, "%02x", public_key[i] & 0xff); | 53 | wprintw(prompt->window, "%02x", public_key[i] & 0xff); |
54 | } | 54 | } |
55 | 55 | ||
56 | wprintw(prompt->window, "\n"); | 56 | wprintw(prompt->window, "\nWith the message: %s\n", data); |
57 | wprintw(prompt->window, "Use \"accept %d\" to accept it.\n", n); | 57 | wprintw(prompt->window, "\nUse \"accept %d\" to accept it.\n", n); |
58 | |||
58 | for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { | 59 | for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { |
59 | if (windows[i].onFriendRequest != NULL) | 60 | if (windows[i].onFriendRequest != NULL) |
60 | windows[i].onFriendRequest(&windows[i], public_key, data, length); | 61 | windows[i].onFriendRequest(&windows[i], public_key, data, length); |
@@ -63,7 +64,6 @@ void on_request(uint8_t *public_key, uint8_t *data, uint16_t length) | |||
63 | 64 | ||
64 | void on_message(int friendnumber, uint8_t *string, uint16_t length) | 65 | void on_message(int friendnumber, uint8_t *string, uint16_t length) |
65 | { | 66 | { |
66 | wprintw(prompt->window, "\n(message) %d: %s\n", friendnumber, string); | ||
67 | int i; | 67 | int i; |
68 | for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { | 68 | for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { |
69 | if (windows[i].onMessage != NULL) | 69 | if (windows[i].onMessage != NULL) |
@@ -71,6 +71,15 @@ void on_message(int friendnumber, uint8_t *string, uint16_t length) | |||
71 | } | 71 | } |
72 | } | 72 | } |
73 | 73 | ||
74 | void on_action(int friendnumber, uint8_t *string, uint16_t length) | ||
75 | { | ||
76 | int i; | ||
77 | for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { | ||
78 | if (windows[i].onAction != NULL) | ||
79 | windows[i].onAction(&windows[i], friendnumber, string, length); | ||
80 | } | ||
81 | } | ||
82 | |||
74 | void on_nickchange(int friendnumber, uint8_t *string, uint16_t length) | 83 | void on_nickchange(int friendnumber, uint8_t *string, uint16_t length) |
75 | { | 84 | { |
76 | wprintw(prompt->window, "\n(nickchange) %d: %s!\n", friendnumber, string); | 85 | wprintw(prompt->window, "\n(nickchange) %d: %s!\n", friendnumber, string); |
@@ -126,6 +135,7 @@ static void init_tox() | |||
126 | m_callback_friendmessage(on_message); | 135 | m_callback_friendmessage(on_message); |
127 | m_callback_namechange(on_nickchange); | 136 | m_callback_namechange(on_nickchange); |
128 | m_callback_statusmessage(on_statuschange); | 137 | m_callback_statusmessage(on_statuschange); |
138 | m_callback_action(on_action); | ||
129 | } | 139 | } |
130 | 140 | ||
131 | void init_window_status() | 141 | void init_window_status() |
@@ -281,13 +291,13 @@ static void draw_bar() | |||
281 | attron(A_BOLD); | 291 | attron(A_BOLD); |
282 | 292 | ||
283 | odd = (odd+1) % blinkrate; | 293 | odd = (odd+1) % blinkrate; |
284 | if (windows[i].blink && (odd < (blinkrate/2))) { | 294 | if (windows[i].blink && (odd < (blinkrate/2))) |
285 | attron(COLOR_PAIR(3)); | 295 | attron(COLOR_PAIR(3)); |
286 | } | 296 | |
287 | printw(" %s", windows[i].title); | 297 | printw(" %s", windows[i].title); |
288 | if (windows[i].blink && (odd < (blinkrate/2))) { | 298 | if (windows[i].blink && (odd < (blinkrate/2))) |
289 | attroff(COLOR_PAIR(3)); | 299 | attroff(COLOR_PAIR(3)); |
290 | } | 300 | |
291 | if (i == active_window) { | 301 | if (i == active_window) { |
292 | attroff(A_BOLD); | 302 | attroff(A_BOLD); |
293 | } | 303 | } |
@@ -317,7 +327,6 @@ void set_active_window(int ch) | |||
317 | i = (i + 1) % max; | 327 | i = (i + 1) % max; |
318 | if (f_inf++ > max) { // infinite loop check | 328 | if (f_inf++ > max) { // infinite loop check |
319 | endwin(); | 329 | endwin(); |
320 | clear(); | ||
321 | exit(2); | 330 | exit(2); |
322 | } | 331 | } |
323 | } | 332 | } |
@@ -332,7 +341,6 @@ void set_active_window(int ch) | |||
332 | if (--i < 0) i = max; | 341 | if (--i < 0) i = max; |
333 | if (f_inf++ > max) { | 342 | if (f_inf++ > max) { |
334 | endwin(); | 343 | endwin(); |
335 | clear(); | ||
336 | exit(2); | 344 | exit(2); |
337 | } | 345 | } |
338 | } | 346 | } |
diff --git a/testing/toxic/windows.h b/testing/toxic/windows.h index 287e534a..c6925ce1 100644 --- a/testing/toxic/windows.h +++ b/testing/toxic/windows.h | |||
@@ -24,6 +24,7 @@ struct ToxWindow_ { | |||
24 | void(*onMessage)(ToxWindow*, int, uint8_t*, uint16_t); | 24 | void(*onMessage)(ToxWindow*, int, uint8_t*, uint16_t); |
25 | void(*onNickChange)(ToxWindow*, int, uint8_t*, uint16_t); | 25 | void(*onNickChange)(ToxWindow*, int, uint8_t*, uint16_t); |
26 | void(*onStatusChange)(ToxWindow*, int, uint8_t*, uint16_t); | 26 | void(*onStatusChange)(ToxWindow*, int, uint8_t*, uint16_t); |
27 | void(*onAction)(ToxWindow*, int, uint8_t*, uint16_t); | ||
27 | char title[256]; | 28 | char title[256]; |
28 | 29 | ||
29 | void* x; | 30 | void* x; |