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 }