Mercurial > hg > nnchat
comparison ui.c @ 513:ef5a2aa8382b
Refactor input handling.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 05 Jun 2012 22:16:42 +0300 |
parents | f71c59cbc5a7 |
children | 436e86afa70a |
comparison
equal
deleted
inserted
replaced
512:93c8ba1ef55f | 513:ef5a2aa8382b |
---|---|
4 * (C) Copyright 2008-2012 Tecnic Software productions (TNSP) | 4 * (C) Copyright 2008-2012 Tecnic Software productions (TNSP) |
5 */ | 5 */ |
6 #include "util.h" | 6 #include "util.h" |
7 #include "ui.h" | 7 #include "ui.h" |
8 | 8 |
9 #define STATUS_YPOS 0 | |
10 | 9 |
11 nn_window_t *chatWindows[SET_MAX_WINDOWS], | 10 nn_window_t *chatWindows[SET_MAX_WINDOWS], |
12 *currWin = NULL; | 11 *currWin = NULL; |
13 | 12 |
14 BOOL cursesInit = FALSE; | 13 BOOL cursesInit = FALSE; |
290 | 289 |
291 return 0; | 290 return 0; |
292 } | 291 } |
293 | 292 |
294 | 293 |
295 char *nnwin_prompt_requester(const char *info, BOOL allowEmpty) | |
296 { | |
297 char buf[512], *ptr; | |
298 | |
299 echo(); | |
300 wattrset(stdscr, A_NORMAL); | |
301 wbkgdset(stdscr, COLOR_PAIR(0)); | |
302 waddstr(stdscr, info); | |
303 wgetnstr(stdscr, buf, sizeof(buf) - 1); | |
304 noecho(); | |
305 | |
306 str_trim_right(buf); | |
307 ptr = str_trim_left(buf); | |
308 | |
309 if (allowEmpty || ptr[0]) | |
310 return th_strdup(ptr); | |
311 else | |
312 return NULL; | |
313 } | |
314 | |
315 | |
316 static void nnwin_print_str(WINDOW *win, const char *fmt, BOOL clip) | 294 static void nnwin_print_str(WINDOW *win, const char *fmt, BOOL clip) |
317 { | 295 { |
318 const char *s = fmt; | 296 const char *s = fmt; |
319 int col = 0; | 297 int col = 0; |
320 while (*s) | 298 while (*s) |
343 } | 321 } |
344 } | 322 } |
345 } | 323 } |
346 | 324 |
347 | 325 |
348 void nnwin_update(BOOL force, nn_editbuf_t *ebuf, char *username, int usercolor) | 326 void nnwin_update(BOOL force, BOOL mask, nn_editbuf_t *ebuf, char *username, int usercolor) |
349 { | 327 { |
350 int sx, sy; | 328 int sx, sy; |
351 | 329 |
352 // Save cursor position | 330 // Save cursor position |
353 getyx(stdscr, sy, sx); | 331 getyx(stdscr, sy, sx); |
452 // Update editbuf if needed | 430 // Update editbuf if needed |
453 if (ebuf != NULL && (force || ebuf->dirty)) | 431 if (ebuf != NULL && (force || ebuf->dirty)) |
454 { | 432 { |
455 int yoffs = ebuf->pos / scrWidth, | 433 int yoffs = ebuf->pos / scrWidth, |
456 xoffs = ebuf->pos % scrWidth; | 434 xoffs = ebuf->pos % scrWidth; |
457 char *tmp; | |
458 | |
459 ebuf->dirty = FALSE; | |
460 ebuf->data[ebuf->len] = 0; | |
461 tmp = nn_username_decode(th_strdup(ebuf->data)); | |
462 | 435 |
463 wmove(stdscr, scrHeight - 3, 0); | 436 wmove(stdscr, scrHeight - 3, 0); |
464 wattrset(stdscr, A_NORMAL); | 437 wattrset(stdscr, A_NORMAL); |
465 wbkgdset(stdscr, COLOR_PAIR(0)); | 438 wbkgdset(stdscr, COLOR_PAIR(0)); |
466 waddnstr(stdscr, tmp, ebuf->len); | 439 |
440 ebuf->dirty = FALSE; | |
441 if (mask) | |
442 { | |
443 size_t i; | |
444 for (i = 0; i < ebuf->len; i++) | |
445 waddch(stdscr, '*'); | |
446 } | |
447 else | |
448 { | |
449 char *tmp; | |
450 ebuf->data[ebuf->len] = 0; | |
451 tmp = nn_username_decode(th_strdup(ebuf->data)); | |
452 waddnstr(stdscr, tmp, ebuf->len); | |
453 th_free(tmp); | |
454 } | |
467 wmove(stdscr, scrHeight - 3 + yoffs, xoffs); | 455 wmove(stdscr, scrHeight - 3 + yoffs, xoffs); |
468 | 456 |
469 th_free(tmp); | |
470 } | 457 } |
471 | 458 |
472 wrefresh(stdscr); | 459 wrefresh(stdscr); |
473 } | 460 } |
461 | |
462 | |
463 void nnwin_input_process(nn_editbuf_t *editBuf, nn_editstate_t *editState, | |
464 BOOL (*callback)(int, nn_editbuf_t *, nn_editstate_t *)) | |
465 { | |
466 int c, cnt = 0; | |
467 | |
468 // Handle several buffered keypresses at once | |
469 do | |
470 { | |
471 c = wgetch(stdscr); | |
472 | |
473 /* Handle various problematic cases where terminal | |
474 * keycodes do not get properly translated by curses | |
475 */ | |
476 if (c == 10 || c == 13) | |
477 c = KEY_ENTER; | |
478 else | |
479 if (c == 0x1b) | |
480 { | |
481 // ^[O | |
482 c = wgetch(stdscr); | |
483 if (c == 'O') | |
484 { | |
485 c = wgetch(stdscr); | |
486 switch (c) | |
487 { | |
488 case 'd': | |
489 c = 0x204; | |
490 break; | |
491 case 'c': | |
492 c = 0x206; | |
493 break; | |
494 default: | |
495 editState->debugMsg("Unhandled ESC-O key sequence 0x%02x\n", c); | |
496 break; | |
497 } | |
498 } | |
499 // ^[[ | |
500 else if (c == '[') | |
501 { | |
502 c = wgetch(stdscr); | |
503 switch (c) | |
504 { | |
505 case 0x31: | |
506 c = wgetch(stdscr); | |
507 if (c >= 0x31 && c <= 0x39) | |
508 c = KEY_F(c - 0x30); | |
509 else | |
510 c = ERR; | |
511 break; | |
512 | |
513 case 0x32: | |
514 c = KEY_IC; | |
515 break; | |
516 case 0x33: | |
517 c = KEY_DC; | |
518 break; | |
519 | |
520 case 0x35: | |
521 c = KEY_PPAGE; | |
522 break; | |
523 case 0x36: | |
524 c = KEY_NPAGE; | |
525 break; | |
526 | |
527 case 0x37: | |
528 c = KEY_HOME; | |
529 break; | |
530 case 0x38: | |
531 c = KEY_END; | |
532 break; | |
533 | |
534 default: | |
535 editState->debugMsg("Unhandled ESC-[*~ key sequence 0x%02x\n", c); | |
536 c = ERR; | |
537 break; | |
538 } | |
539 // Get the trailing ~ | |
540 if (c != ERR) | |
541 wgetch(stdscr); | |
542 } | |
543 else | |
544 if (c >= 0x31 && c <= 0x39) | |
545 { | |
546 c = c - 0x30 + 0x5000; | |
547 } | |
548 else | |
549 { | |
550 editState->debugMsg("Unhandled ESC key sequence 0x%02x\n", c); | |
551 } | |
552 } | |
553 #if defined(__WIN32) && defined(PDCURSES) | |
554 else | |
555 if (c >= 0x198 && c <= 0x1a0) | |
556 { | |
557 c = c - 0x198 + 0x5000; | |
558 } | |
559 #endif | |
560 | |
561 switch (c) | |
562 { | |
563 #ifdef KEY_RESIZE | |
564 case KEY_RESIZE: | |
565 resize_term(0, 0); | |
566 erase(); | |
567 timeout(SET_DELAY); | |
568 nnwin_reset(); | |
569 editState->update = TRUE; | |
570 break; | |
571 #endif | |
572 | |
573 case 0x204: // ctrl+left arrow = Skip words left | |
574 case 0x20b: | |
575 while (editBuf->pos > 0 && isspace((int) editBuf->data[editBuf->pos - 1])) | |
576 editBuf->pos--; | |
577 while (editBuf->pos > 0 && !isspace((int) editBuf->data[editBuf->pos - 1])) | |
578 editBuf->pos--; | |
579 editBuf->dirty = TRUE; | |
580 break; | |
581 | |
582 case 0x206: // ctrl+right arrow = Skip words right | |
583 case 0x210: | |
584 while (editBuf->pos < editBuf->len && isspace((int) editBuf->data[editBuf->pos])) | |
585 editBuf->pos++; | |
586 while (editBuf->pos < editBuf->len && !isspace((int) editBuf->data[editBuf->pos])) | |
587 editBuf->pos++; | |
588 editBuf->dirty = TRUE; | |
589 break; | |
590 | |
591 case KEY_HOME: | |
592 nn_editbuf_setpos(editBuf, 0); | |
593 break; | |
594 case KEY_END: | |
595 nn_editbuf_setpos(editBuf, editBuf->len); | |
596 break; | |
597 case KEY_LEFT: | |
598 nn_editbuf_setpos(editBuf, editBuf->pos - 1); | |
599 break; | |
600 case KEY_RIGHT: | |
601 nn_editbuf_setpos(editBuf, editBuf->pos + 1); | |
602 break; | |
603 | |
604 case KEY_BACKSPACE: | |
605 case 0x08: | |
606 case 0x7f: | |
607 nn_editbuf_delete(editBuf, editBuf->pos - 1); | |
608 nn_editbuf_setpos(editBuf, editBuf->pos - 1); | |
609 break; | |
610 | |
611 case KEY_DC: // Delete character | |
612 nn_editbuf_delete(editBuf, editBuf->pos); | |
613 break; | |
614 | |
615 case KEY_IC: // Ins = Toggle insert / overwrite mode | |
616 editState->insertMode = !editState->insertMode; | |
617 break; | |
618 | |
619 case KEY_F(2): // F2 = Clear editbuffer | |
620 nn_editbuf_clear(editBuf); | |
621 break; | |
622 | |
623 case 0x0c: // Ctrl + L | |
624 editState->update = TRUE; | |
625 break; | |
626 | |
627 case ERR: | |
628 // Ignore | |
629 break; | |
630 | |
631 default: | |
632 if (!callback(c, editBuf, editState)) | |
633 { | |
634 if (isprint(c) || c == 0xe4 || c == 0xf6 || c == 0xc4 || c == 0xd6) | |
635 { | |
636 if (editState->insertMode) | |
637 nn_editbuf_insert(editBuf, editBuf->pos, c); | |
638 else | |
639 nn_editbuf_write(editBuf, editBuf->pos, c); | |
640 nn_editbuf_setpos(editBuf, editBuf->pos + 1); | |
641 } | |
642 else | |
643 editState->debugMsg("Unhandled key: 0x%02x\n", c); | |
644 } | |
645 break; | |
646 } | |
647 } | |
648 while (c != ERR && ++cnt < 10); | |
649 } | |
650 | |
651 | |
652 | |
653 char *nnwin_prompt_requester(BOOL allowEmpty, nn_editstate_t *editState, | |
654 BOOL (*callback)(int, nn_editbuf_t *, nn_editstate_t *), | |
655 void (*update)(nn_editbuf_t *, nn_editstate_t *)) | |
656 { | |
657 nn_editbuf_t *editBuf = nn_editbuf_new(NN_TMPBUF_SIZE); | |
658 char *res; | |
659 | |
660 editState->done = FALSE; | |
661 while (!editState->isError && !editState->exitProg && !editState->done) | |
662 { | |
663 nnwin_input_process(editBuf, editState, callback); | |
664 update(editBuf, editState); | |
665 } | |
666 | |
667 if (allowEmpty || editBuf->len > 0) | |
668 res = nn_editbuf_get_string(editBuf, 0, editBuf->len); | |
669 else | |
670 res = NULL; | |
671 | |
672 nn_editbuf_free(editBuf); | |
673 | |
674 return res; | |
675 } |