diff options
Diffstat (limited to 'testing/toxic/main.c')
-rw-r--r-- | testing/toxic/main.c | 217 |
1 files changed, 106 insertions, 111 deletions
diff --git a/testing/toxic/main.c b/testing/toxic/main.c index 19a0b959..1ba8b6c9 100644 --- a/testing/toxic/main.c +++ b/testing/toxic/main.c | |||
@@ -18,106 +18,108 @@ extern ToxWindow new_friendlist(); | |||
18 | 18 | ||
19 | extern int friendlist_onFriendAdded(int num); | 19 | extern int friendlist_onFriendAdded(int num); |
20 | extern void disable_chatwin(int f_num); | 20 | extern void disable_chatwin(int f_num); |
21 | extern int add_req(uint8_t* public_key); // XXX | 21 | extern int add_req(uint8_t *public_key); // XXX |
22 | |||
23 | /* Holds status of chat windows */ | ||
24 | char WINDOW_STATUS[MAX_WINDOW_SLOTS]; | ||
22 | 25 | ||
23 | char WINDOW_STATUS[MAX_WINDOW_SLOTS]; // Holds status of chat windows | ||
24 | static ToxWindow windows[MAX_WINDOW_SLOTS]; | 26 | static ToxWindow windows[MAX_WINDOW_SLOTS]; |
25 | int w_num; | ||
26 | int w_active; | ||
27 | static ToxWindow* prompt; | 27 | static ToxWindow* prompt; |
28 | 28 | ||
29 | // CALLBACKS START | 29 | int w_num; |
30 | void on_request(uint8_t* public_key, uint8_t* data, uint16_t length) { | 30 | int active_window; |
31 | size_t i; | ||
32 | int n = add_req(public_key); | ||
33 | 31 | ||
32 | /* CALLBACKS START */ | ||
33 | void on_request(uint8_t *public_key, uint8_t *data, uint16_t length) | ||
34 | { | ||
35 | int n = add_req(public_key); | ||
34 | wprintw(prompt->window, "\nFriend request from:\n"); | 36 | wprintw(prompt->window, "\nFriend request from:\n"); |
35 | 37 | ||
36 | for(i=0; i<32; i++) { | 38 | int i; |
39 | for (i = 0; i < 32; ++i) { | ||
37 | wprintw(prompt->window, "%02x", public_key[i] & 0xff); | 40 | wprintw(prompt->window, "%02x", public_key[i] & 0xff); |
38 | } | 41 | } |
39 | wprintw(prompt->window, "\n"); | ||
40 | 42 | ||
43 | wprintw(prompt->window, "\n"); | ||
41 | wprintw(prompt->window, "Use \"accept %d\" to accept it.\n", n); | 44 | wprintw(prompt->window, "Use \"accept %d\" to accept it.\n", n); |
42 | 45 | for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { | |
43 | for(i=0; i<MAX_WINDOW_SLOTS; i++) { | 46 | if (windows[i].onFriendRequest != NULL) |
44 | if(windows[i].onFriendRequest != NULL) | ||
45 | windows[i].onFriendRequest(&windows[i], public_key, data, length); | 47 | windows[i].onFriendRequest(&windows[i], public_key, data, length); |
46 | } | 48 | } |
47 | } | 49 | } |
48 | 50 | ||
49 | void on_message(int friendnumber, uint8_t* string, uint16_t length) { | 51 | void on_message(int friendnumber, uint8_t *string, uint16_t length) |
50 | size_t i; | 52 | { |
51 | |||
52 | wprintw(prompt->window, "\n(message) %d: %s\n", friendnumber, string); | 53 | wprintw(prompt->window, "\n(message) %d: %s\n", friendnumber, string); |
53 | 54 | int i; | |
54 | for(i=0; i<MAX_WINDOW_SLOTS; i++) { | 55 | for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { |
55 | if(windows[i].onMessage != NULL) | 56 | if (windows[i].onMessage != NULL) |
56 | windows[i].onMessage(&windows[i], friendnumber, string, length); | 57 | windows[i].onMessage(&windows[i], friendnumber, string, length); |
57 | } | 58 | } |
58 | } | 59 | } |
59 | 60 | ||
60 | void on_nickchange(int friendnumber, uint8_t* string, uint16_t length) { | 61 | void on_nickchange(int friendnumber, uint8_t *string, uint16_t length) |
61 | size_t i; | 62 | { |
62 | |||
63 | wprintw(prompt->window, "\n(nickchange) %d: %s!\n", friendnumber, string); | 63 | wprintw(prompt->window, "\n(nickchange) %d: %s!\n", friendnumber, string); |
64 | 64 | int i; | |
65 | for(i=0; i<MAX_WINDOW_SLOTS; i++) { | 65 | for (i = 0; i < MAX_WINDOW_SLOTS; ++i) { |
66 | if(windows[i].onNickChange != NULL) | 66 | if (windows[i].onNickChange != NULL) |
67 | windows[i].onNickChange(&windows[i], friendnumber, string, length); | 67 | windows[i].onNickChange(&windows[i], friendnumber, string, length); |
68 | } | 68 | } |
69 | } | 69 | } |
70 | 70 | ||
71 | void on_statuschange(int friendnumber, USERSTATUS_KIND kind, uint8_t* string, uint16_t length) { | 71 | void on_statuschange(int friendnumber, USERSTATUS_KIND kind, uint8_t *string, uint16_t length) |
72 | size_t i; | 72 | { |
73 | |||
74 | wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); | 73 | wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); |
75 | 74 | int i; | |
76 | for(i=0; i<MAX_WINDOW_SLOTS; i++) { | 75 | for (i=0; i<MAX_WINDOW_SLOTS; ++i) { |
77 | if(windows[i].onStatusChange != NULL) | 76 | if (windows[i].onStatusChange != NULL) |
78 | windows[i].onStatusChange(&windows[i], friendnumber, string, length); | 77 | windows[i].onStatusChange(&windows[i], friendnumber, string, length); |
79 | } | 78 | } |
80 | } | 79 | } |
81 | 80 | ||
82 | void on_friendadded(int friendnumber) { | 81 | void on_friendadded(int friendnumber) |
82 | { | ||
83 | friendlist_onFriendAdded(friendnumber); | 83 | friendlist_onFriendAdded(friendnumber); |
84 | } | 84 | } |
85 | // CALLBACKS END | 85 | /* CALLBACKS END */ |
86 | 86 | ||
87 | static void init_term() { | 87 | static void init_term() |
88 | // Setup terminal. | 88 | { |
89 | /* Setup terminal */ | ||
89 | initscr(); | 90 | initscr(); |
90 | cbreak(); | 91 | cbreak(); |
91 | keypad(stdscr, 1); | 92 | keypad(stdscr, 1); |
92 | noecho(); | 93 | noecho(); |
93 | timeout(100); | 94 | timeout(100); |
94 | 95 | ||
95 | if(has_colors()) { | 96 | if (has_colors()) { |
96 | start_color(); | 97 | start_color(); |
97 | init_pair(1, COLOR_GREEN, COLOR_BLACK); | 98 | init_pair(1, COLOR_GREEN, COLOR_BLACK); |
98 | init_pair(2, COLOR_CYAN, COLOR_BLACK); | 99 | init_pair(2, COLOR_CYAN, COLOR_BLACK); |
99 | init_pair(3, COLOR_RED, COLOR_BLACK); | 100 | init_pair(3, COLOR_RED, COLOR_BLACK); |
100 | init_pair(4, COLOR_BLUE, COLOR_BLACK); | 101 | init_pair(4, COLOR_BLUE, COLOR_BLACK); |
101 | } | 102 | } |
102 | |||
103 | refresh(); | 103 | refresh(); |
104 | } | 104 | } |
105 | 105 | ||
106 | static void init_tox() { | 106 | static void init_tox() |
107 | // Init core. | 107 | { |
108 | /* Init core */ | ||
108 | initMessenger(); | 109 | initMessenger(); |
109 | 110 | ||
110 | // Callbacks. | 111 | /* Callbacks */ |
111 | m_callback_friendrequest(on_request); | 112 | m_callback_friendrequest(on_request); |
112 | m_callback_friendmessage(on_message); | 113 | m_callback_friendmessage(on_message); |
113 | m_callback_namechange(on_nickchange); | 114 | m_callback_namechange(on_nickchange); |
114 | m_callback_userstatus(on_statuschange); | 115 | m_callback_userstatus(on_statuschange); |
115 | } | 116 | } |
116 | 117 | ||
117 | void init_window_status() { | 118 | void init_window_status() |
119 | { | ||
118 | /* Default window values decrement from -2 */ | 120 | /* Default window values decrement from -2 */ |
119 | int i; | 121 | int i; |
120 | for (i = 0; i < N_DEFAULT_WINS; i++) | 122 | for (i = 0; i < N_DEFAULT_WINS; ++i) |
121 | WINDOW_STATUS[i] = -(i+2); | 123 | WINDOW_STATUS[i] = -(i+2); |
122 | 124 | ||
123 | int j; | 125 | int j; |
@@ -125,15 +127,16 @@ void init_window_status() { | |||
125 | WINDOW_STATUS[j] = -1; | 127 | WINDOW_STATUS[j] = -1; |
126 | } | 128 | } |
127 | 129 | ||
128 | int add_window(ToxWindow w, int n) { | 130 | int add_window(ToxWindow w, int n) |
129 | if(w_num >= TOXWINDOWS_MAX_NUM) | 131 | { |
132 | if (w_num >= TOXWINDOWS_MAX_NUM) | ||
130 | return -1; | 133 | return -1; |
131 | 134 | ||
132 | if(LINES < 2) | 135 | if (LINES < 2) |
133 | return -1; | 136 | return -1; |
134 | 137 | ||
135 | w.window = newwin(LINES - 2, COLS, 0, 0); | 138 | w.window = newwin(LINES - 2, COLS, 0, 0); |
136 | if(w.window == NULL) | 139 | if (w.window == NULL) |
137 | return -1; | 140 | return -1; |
138 | 141 | ||
139 | windows[n] = w; | 142 | windows[n] = w; |
@@ -143,10 +146,11 @@ int add_window(ToxWindow w, int n) { | |||
143 | } | 146 | } |
144 | 147 | ||
145 | /* Deletes window w and cleans up */ | 148 | /* Deletes window w and cleans up */ |
146 | void del_window(ToxWindow *w, int f_num) { | 149 | void del_window(ToxWindow *w, int f_num) |
150 | { | ||
147 | delwin(w->window); | 151 | delwin(w->window); |
148 | int i; | 152 | int i; |
149 | for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; i++) { | 153 | for (i = N_DEFAULT_WINS; i < MAX_WINDOW_SLOTS; ++i) { |
150 | if (WINDOW_STATUS[i] == f_num) { | 154 | if (WINDOW_STATUS[i] == f_num) { |
151 | WINDOW_STATUS[i] = -1; | 155 | WINDOW_STATUS[i] = -1; |
152 | disable_chatwin(f_num); | 156 | disable_chatwin(f_num); |
@@ -157,11 +161,12 @@ void del_window(ToxWindow *w, int f_num) { | |||
157 | refresh(); | 161 | refresh(); |
158 | } | 162 | } |
159 | 163 | ||
160 | static void init_windows() { | 164 | static void init_windows() |
165 | { | ||
161 | w_num = 0; | 166 | w_num = 0; |
162 | int n_prompt = 0; | 167 | int n_prompt = 0; |
163 | int n_friendslist = 1; | 168 | int n_friendslist = 1; |
164 | if(add_window(new_prompt(), n_prompt) == -1 | 169 | if (add_window(new_prompt(), n_prompt) == -1 |
165 | || add_window(new_friendlist(), n_friendslist) == -1) { | 170 | || add_window(new_friendlist(), n_friendslist) == -1) { |
166 | fprintf(stderr, "add_window() failed.\n"); | 171 | fprintf(stderr, "add_window() failed.\n"); |
167 | endwin(); | 172 | endwin(); |
@@ -170,88 +175,79 @@ static void init_windows() { | |||
170 | prompt = &windows[n_prompt]; | 175 | prompt = &windows[n_prompt]; |
171 | } | 176 | } |
172 | 177 | ||
173 | static void do_tox() { | 178 | static void do_tox() |
179 | { | ||
174 | static bool dht_on = false; | 180 | static bool dht_on = false; |
175 | 181 | if (!dht_on && DHT_isconnected()) { | |
176 | if(!dht_on && DHT_isconnected()) { | ||
177 | dht_on = true; | 182 | dht_on = true; |
178 | wprintw(prompt->window, "\nDHT connected!\n"); | 183 | wprintw(prompt->window, "\nDHT connected!\n"); |
179 | } | 184 | } |
180 | else if(dht_on && !DHT_isconnected()) { | 185 | else if (dht_on && !DHT_isconnected()) { |
181 | dht_on = false; | 186 | dht_on = false; |
182 | wprintw(prompt->window, "\nDHT disconnected!\n"); | 187 | wprintw(prompt->window, "\nDHT disconnected!\n"); |
183 | } | 188 | } |
184 | |||
185 | doMessenger(); | 189 | doMessenger(); |
186 | } | 190 | } |
187 | 191 | ||
188 | static void load_data(char *path) { | 192 | static void load_data(char *path) |
189 | FILE* fd; | 193 | { |
194 | FILE *fd; | ||
190 | size_t len; | 195 | size_t len; |
191 | uint8_t* buf; | 196 | uint8_t *buf; |
192 | 197 | ||
193 | if((fd = fopen(path, "r")) != NULL) { | 198 | if ((fd = fopen(path, "r")) != NULL) { |
194 | fseek(fd, 0, SEEK_END); | 199 | fseek(fd, 0, SEEK_END); |
195 | len = ftell(fd); | 200 | len = ftell(fd); |
196 | fseek(fd, 0, SEEK_SET); | 201 | fseek(fd, 0, SEEK_SET); |
197 | 202 | ||
198 | buf = malloc(len); | 203 | buf = malloc(len); |
199 | 204 | if (buf == NULL) { | |
200 | if(buf == NULL) { | ||
201 | fprintf(stderr, "malloc() failed.\n"); | 205 | fprintf(stderr, "malloc() failed.\n"); |
202 | |||
203 | fclose(fd); | 206 | fclose(fd); |
204 | endwin(); | 207 | endwin(); |
205 | exit(1); | 208 | exit(1); |
206 | } | 209 | } |
207 | 210 | if (fread(buf, len, 1, fd) != 1){ | |
208 | if(fread(buf, len, 1, fd) != 1){ | ||
209 | fprintf(stderr, "fread() failed.\n"); | 211 | fprintf(stderr, "fread() failed.\n"); |
210 | |||
211 | free(buf); | 212 | free(buf); |
212 | fclose(fd); | 213 | fclose(fd); |
213 | endwin(); | 214 | endwin(); |
214 | exit(1); | 215 | exit(1); |
215 | } | 216 | } |
216 | |||
217 | Messenger_load(buf, len); | 217 | Messenger_load(buf, len); |
218 | } | 218 | } |
219 | else { | 219 | else { |
220 | len = Messenger_size(); | 220 | len = Messenger_size(); |
221 | buf = malloc(len); | 221 | buf = malloc(len); |
222 | 222 | if (buf == NULL) { | |
223 | if(buf == NULL) { | ||
224 | fprintf(stderr, "malloc() failed.\n"); | 223 | fprintf(stderr, "malloc() failed.\n"); |
225 | endwin(); | 224 | endwin(); |
226 | exit(1); | 225 | exit(1); |
227 | } | 226 | } |
228 | |||
229 | Messenger_save(buf); | 227 | Messenger_save(buf); |
230 | 228 | ||
231 | fd = fopen(path, "w"); | 229 | fd = fopen(path, "w"); |
232 | if(fd == NULL) { | 230 | if (fd == NULL) { |
233 | fprintf(stderr, "fopen() failed.\n"); | 231 | fprintf(stderr, "fopen() failed.\n"); |
234 | |||
235 | free(buf); | 232 | free(buf); |
236 | endwin(); | 233 | endwin(); |
237 | exit(1); | 234 | exit(1); |
238 | } | 235 | } |
239 | 236 | ||
240 | if(fwrite(buf, len, 1, fd) != 1){ | 237 | if (fwrite(buf, len, 1, fd) != 1){ |
241 | fprintf(stderr, "fwrite() failed.\n"); | 238 | fprintf(stderr, "fwrite() failed.\n"); |
242 | |||
243 | free(buf); | 239 | free(buf); |
244 | fclose(fd); | 240 | fclose(fd); |
245 | endwin(); | 241 | endwin(); |
246 | exit(1); | 242 | exit(1); |
247 | } | 243 | } |
248 | } | 244 | } |
249 | |||
250 | free(buf); | 245 | free(buf); |
251 | fclose(fd); | 246 | fclose(fd); |
252 | } | 247 | } |
253 | 248 | ||
254 | static void draw_bar() { | 249 | static void draw_bar() |
250 | { | ||
255 | static int odd = 0; | 251 | static int odd = 0; |
256 | 252 | ||
257 | attron(COLOR_PAIR(4)); | 253 | attron(COLOR_PAIR(4)); |
@@ -265,21 +261,21 @@ static void draw_bar() { | |||
265 | attroff(COLOR_PAIR(4) | A_BOLD); | 261 | attroff(COLOR_PAIR(4) | A_BOLD); |
266 | 262 | ||
267 | int i; | 263 | int i; |
268 | for (i = 0; i < (MAX_WINDOW_SLOTS-1); i++) { | 264 | for (i = 0; i < (MAX_WINDOW_SLOTS); ++i) { |
269 | if (WINDOW_STATUS[i] != -1) { | 265 | if (WINDOW_STATUS[i] != -1) { |
270 | if (i == w_active) | 266 | if (i == active_window) |
271 | attron(A_BOLD); | 267 | attron(A_BOLD); |
272 | 268 | ||
273 | odd = (odd+1) % 10; | 269 | odd = (odd+1) % 10; |
274 | if(windows[i].blink && (odd < 5)) { | 270 | if (windows[i].blink && (odd < 5)) { |
275 | attron(COLOR_PAIR(3)); | 271 | attron(COLOR_PAIR(3)); |
276 | } | 272 | } |
277 | 273 | ||
278 | printw(" %s", windows[i].title); | 274 | printw(" %s", windows[i].title); |
279 | if(windows[i].blink && (odd < 5)) { | 275 | if (windows[i].blink && (odd < 5)) { |
280 | attron(COLOR_PAIR(3)); | 276 | attron(COLOR_PAIR(3)); |
281 | } | 277 | } |
282 | if(i == w_active) { | 278 | if (i == active_window) { |
283 | attroff(A_BOLD); | 279 | attroff(A_BOLD); |
284 | } | 280 | } |
285 | } | 281 | } |
@@ -287,35 +283,37 @@ static void draw_bar() { | |||
287 | refresh(); | 283 | refresh(); |
288 | } | 284 | } |
289 | 285 | ||
290 | void prepare_window(WINDOW* w) { | 286 | void prepare_window(WINDOW *w) |
287 | { | ||
291 | mvwin(w, 0, 0); | 288 | mvwin(w, 0, 0); |
292 | wresize(w, LINES-2, COLS); | 289 | wresize(w, LINES-2, COLS); |
293 | } | 290 | } |
294 | 291 | ||
295 | /* Shows next window when tab or back-tab is pressed */ | 292 | /* Shows next window when tab or back-tab is pressed */ |
296 | void set_active_window(int ch) { | 293 | void set_active_window(int ch) |
294 | { | ||
297 | int f_inf = 0; | 295 | int f_inf = 0; |
298 | int max = MAX_WINDOW_SLOTS-1; | 296 | int max = MAX_WINDOW_SLOTS-1; |
299 | if (ch == '\t') { | 297 | if (ch == '\t') { |
300 | int i = (w_active + 1) % max; | 298 | int i = (active_window + 1) % max; |
301 | while (true) { | 299 | while (true) { |
302 | if (WINDOW_STATUS[i] != -1) { | 300 | if (WINDOW_STATUS[i] != -1) { |
303 | w_active = i; | 301 | active_window = i; |
304 | return; | 302 | return; |
305 | } | 303 | } |
306 | i = (i + 1) % max; | 304 | i = (i + 1) % max; |
307 | if (f_inf++ > max) { // infinite loop check | 305 | if (f_inf++ > max) { // infinite loop check |
308 | endwin(); | 306 | endwin(); |
309 | clear(); | 307 | clear(); |
310 | exit(2); | 308 | exit(2); |
311 | } | 309 | } |
312 | } | 310 | } |
313 | }else { | 311 | }else { |
314 | int i = w_active - 1; | 312 | int i = active_window - 1; |
315 | if (i < 0) i = max; | 313 | if (i < 0) i = max; |
316 | while (true) { | 314 | while (true) { |
317 | if (WINDOW_STATUS[i] != -1) { | 315 | if (WINDOW_STATUS[i] != -1) { |
318 | w_active = i; | 316 | active_window = i; |
319 | return; | 317 | return; |
320 | } | 318 | } |
321 | if (--i < 0) i = max; | 319 | if (--i < 0) i = max; |
@@ -328,26 +326,26 @@ void set_active_window(int ch) { | |||
328 | } | 326 | } |
329 | } | 327 | } |
330 | 328 | ||
331 | int main(int argc, char* argv[]) { | 329 | int main(int argc, char *argv[]) |
330 | { | ||
332 | int ch; | 331 | int ch; |
333 | int i = 0; | ||
334 | int f_flag = 0; | 332 | int f_flag = 0; |
335 | char *filename = "data"; | 333 | char *filename = "data"; |
336 | ToxWindow* a; | 334 | ToxWindow* a; |
337 | 335 | ||
338 | for(i = 0; i < argc; i++) { | 336 | int i = 0; |
339 | if (argv[i] == NULL){ | 337 | for (i = 0; i < argc; ++i) { |
340 | break; | 338 | if (argv[i] == NULL) |
341 | } else if(argv[i][0] == '-') { | 339 | break; |
342 | if(argv[i][1] == 'f') { | 340 | else if (argv[i][0] == '-') { |
343 | if(argv[i + 1] != NULL) | 341 | if (argv[i][1] == 'f') { |
344 | filename = argv[i + 1]; | 342 | if (argv[i + 1] != NULL) |
345 | else { | 343 | filename = argv[i + 1]; |
346 | f_flag = -1; | 344 | else |
347 | } | 345 | f_flag = -1; |
348 | } | 346 | } |
349 | } | ||
350 | } | 347 | } |
348 | } | ||
351 | 349 | ||
352 | init_term(); | 350 | init_term(); |
353 | init_tox(); | 351 | init_tox(); |
@@ -355,7 +353,7 @@ int main(int argc, char* argv[]) { | |||
355 | init_windows(); | 353 | init_windows(); |
356 | init_window_status(); | 354 | init_window_status(); |
357 | 355 | ||
358 | if(f_flag == -1) { | 356 | if (f_flag == -1) { |
359 | attron(COLOR_PAIR(3) | A_BOLD); | 357 | attron(COLOR_PAIR(3) | A_BOLD); |
360 | wprintw(prompt->window, "You passed '-f' without giving an argument!\n" | 358 | wprintw(prompt->window, "You passed '-f' without giving an argument!\n" |
361 | "defaulting to 'data' for a keyfile...\n"); | 359 | "defaulting to 'data' for a keyfile...\n"); |
@@ -363,24 +361,21 @@ int main(int argc, char* argv[]) { | |||
363 | } | 361 | } |
364 | 362 | ||
365 | while(true) { | 363 | while(true) { |
366 | // Update tox. | 364 | /* Update tox */ |
367 | do_tox(); | 365 | do_tox(); |
368 | 366 | ||
369 | // Draw. | 367 | /* Draw */ |
370 | a = &windows[w_active]; | 368 | a = &windows[active_window]; |
371 | prepare_window(a->window); | 369 | prepare_window(a->window); |
372 | a->blink = false; | 370 | a->blink = false; |
373 | draw_bar(); | 371 | draw_bar(); |
374 | a->onDraw(a); | 372 | a->onDraw(a); |
375 | 373 | ||
376 | // Handle input. | 374 | /* Handle input */ |
377 | ch = getch(); | 375 | ch = getch(); |
378 | if(ch == '\t' || ch == KEY_BTAB) | 376 | if (ch == '\t' || ch == KEY_BTAB) |
379 | set_active_window(ch); | 377 | set_active_window(ch); |
380 | else if(ch != ERR) { | 378 | else if (ch != ERR) { |
381 | a->onKey(a, ch); | ||
382 | } | ||
383 | else if(ch != ERR) { | ||
384 | a->onKey(a, ch); | 379 | a->onKey(a, ch); |
385 | } | 380 | } |
386 | } | 381 | } |