summaryrefslogtreecommitdiff
path: root/apps/recorder/keyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/recorder/keyboard.c')
-rw-r--r--apps/recorder/keyboard.c680
1 files changed, 341 insertions, 339 deletions
diff --git a/apps/recorder/keyboard.c b/apps/recorder/keyboard.c
index 856a1482e3..76e7df0509 100644
--- a/apps/recorder/keyboard.c
+++ b/apps/recorder/keyboard.c
@@ -147,7 +147,6 @@ static const unsigned char morse_codes[] = {
147 0x06,0x0f,0x16,0x1d,0x0a,0x08,0x03,0x09,0x11,0x0b,0x19,0x1b,0x1c, 147 0x06,0x0f,0x16,0x1d,0x0a,0x08,0x03,0x09,0x11,0x0b,0x19,0x1b,0x1c,
148 0x2f,0x27,0x23,0x21,0x20,0x30,0x38,0x3c,0x3e,0x3f, 148 0x2f,0x27,0x23,0x21,0x20,0x30,0x38,0x3c,0x3e,0x3f,
149 0x73,0x55,0x4c,0x61,0x5a,0x80 }; 149 0x73,0x55,0x4c,0x61,0x5a,0x80 };
150
151#endif 150#endif
152 151
153/* Loads a custom keyboard into memory 152/* Loads a custom keyboard into memory
@@ -158,14 +157,6 @@ int load_kbd(unsigned char* filename)
158 int i = 0; 157 int i = 0;
159 unsigned char buf[4]; 158 unsigned char buf[4];
160 159
161 FOR_NB_SCREENS(l)
162 {
163 /* initialize parameters */
164 struct keyboard_parameters *pm = &kbd_param[l];
165 pm->x = pm->y = pm->page = 0;
166 pm->default_lines = 0;
167 }
168
169 if (filename == NULL) 160 if (filename == NULL)
170 { 161 {
171 kbd_loaded = false; 162 kbd_loaded = false;
@@ -212,7 +203,13 @@ int load_kbd(unsigned char* filename)
212 kbd_loaded = true; 203 kbd_loaded = true;
213 204
214 FOR_NB_SCREENS(l) 205 FOR_NB_SCREENS(l)
215 kbd_param[l].nchars = i; 206 {
207 struct keyboard_parameters *pm = &kbd_param[l];
208 pm->nchars = i;
209 /* initialize parameters */
210 pm->x = pm->y = pm->page = 0;
211 pm->default_lines = 0;
212 }
216 213
217 return 0; 214 return 0;
218} 215}
@@ -285,6 +282,13 @@ static unsigned short get_kbd_ch(const struct keyboard_parameters *pm)
285 return (k < pm->nchars)? pm->kbd_buf[k]: ' '; 282 return (k < pm->nchars)? pm->kbd_buf[k]: ' ';
286} 283}
287 284
285static void kbd_calc_params(struct keyboard_parameters *pm,
286 struct screen *sc, struct edit_state *state);
287static void kbd_draw_picker(struct keyboard_parameters *pm,
288 struct screen *sc, struct edit_state *state);
289static void kbd_draw_edit_line(struct keyboard_parameters *pm,
290 struct screen *sc, struct edit_state *state);
291
288int kbd_input(char* text, int buflen) 292int kbd_input(char* text, int buflen)
289{ 293{
290 bool done = false; 294 bool done = false;
@@ -303,7 +307,6 @@ int kbd_input(char* text, int buflen)
303 viewportmanager_theme_enable(l, false, NULL); 307 viewportmanager_theme_enable(l, false, NULL);
304 } 308 }
305 309
306 char outline[8];
307#ifdef HAVE_BUTTONBAR 310#ifdef HAVE_BUTTONBAR
308 struct gui_buttonbar buttonbar; 311 struct gui_buttonbar buttonbar;
309 bool buttonbar_config = global_settings.buttonbar; 312 bool buttonbar_config = global_settings.buttonbar;
@@ -316,6 +319,8 @@ int kbd_input(char* text, int buflen)
316 /* initialize state */ 319 /* initialize state */
317 state.text = text; 320 state.text = text;
318 state.buflen = buflen; 321 state.buflen = buflen;
322 /* Initial edit position is after last character */
323 state.editpos = utf8length(state.text);
319 state.cur_blink = true; 324 state.cur_blink = true;
320#ifdef HAVE_MORSE_INPUT 325#ifdef HAVE_MORSE_INPUT
321 state.morse_mode = global_settings.morse_input; 326 state.morse_mode = global_settings.morse_input;
@@ -332,9 +337,6 @@ int kbd_input(char* text, int buflen)
332 const unsigned char *p; 337 const unsigned char *p;
333 int i = 0; 338 int i = 0;
334 339
335 /* initialize parameters */
336 pm->x = pm->y = pm->page = 0;
337
338#if LCD_WIDTH >= 160 && LCD_HEIGHT >= 96 340#if LCD_WIDTH >= 160 && LCD_HEIGHT >= 96
339 struct screen *sc = &screens[l]; 341 struct screen *sc = &screens[l];
340 342
@@ -376,6 +378,8 @@ int kbd_input(char* text, int buflen)
376 p = utf8decode(p, &pm->kbd_buf[i++]); 378 p = utf8decode(p, &pm->kbd_buf[i++]);
377 379
378 pm->nchars = i; 380 pm->nchars = i;
381 /* initialize parameters */
382 pm->x = pm->y = pm->page = 0;
379 } 383 }
380 kbd_loaded = true; 384 kbd_loaded = true;
381 } 385 }
@@ -384,153 +388,9 @@ int kbd_input(char* text, int buflen)
384 { 388 {
385 struct keyboard_parameters *pm = &param[l]; 389 struct keyboard_parameters *pm = &param[l];
386 struct screen *sc = &screens[l]; 390 struct screen *sc = &screens[l];
387 struct font* font; 391 kbd_calc_params(pm, sc, &state);
388 const unsigned char *p;
389 int icon_w, sc_w;
390 int i, w;
391
392 pm->curfont = pm->default_lines ? FONT_SYSFIXED : FONT_UI;
393 font = font_get(pm->curfont);
394 pm->font_h = font->height;
395
396 /* check if FONT_UI fits the screen */
397 if (2*pm->font_h + 3 + BUTTONBAR_HEIGHT > sc->getheight())
398 {
399 pm->curfont = FONT_SYSFIXED;
400 font = font_get(FONT_SYSFIXED);
401 pm->font_h = font->height;
402 }
403
404 /* find max width of keyboard glyphs.
405 * since we're going to be adding spaces,
406 * max width is at least their width */
407 pm->font_w = font_get_width(font, ' ');
408 for (i = 0; i < pm->nchars; i++)
409 {
410 if (pm->kbd_buf[i] != '\n')
411 {
412 w = font_get_width(font, pm->kbd_buf[i]);
413 if (pm->font_w < w)
414 pm->font_w = w;
415 }
416 }
417
418 /* Find max width for text string */
419 pm->text_w = pm->font_w;
420 p = state.text;
421 while (*p)
422 {
423 p = utf8decode(p, &ch);
424 w = font_get_width(font, ch);
425 if (pm->text_w < w)
426 pm->text_w = w;
427 }
428
429 /* calculate how many characters to put in a row. */
430 icon_w = get_icon_width(l);
431 sc_w = sc->getwidth();
432 pm->max_chars = sc_w / pm->font_w;
433 pm->max_chars_text = (sc_w - icon_w * 2 - 2) / pm->text_w;
434 if (pm->max_chars_text < 3 && icon_w > pm->text_w)
435 pm->max_chars_text = sc_w / pm->text_w - 2;
436 } 392 }
437 393
438 FOR_NB_SCREENS(l)
439 {
440 struct keyboard_parameters *pm = &param[l];
441 int i = 0;
442
443 /* Pad lines with spaces */
444 while (i < pm->nchars)
445 {
446 if (pm->kbd_buf[i] == '\n')
447 {
448 int k = pm->max_chars - i % ( pm->max_chars ) - 1;
449 int j;
450
451 if (k == pm->max_chars - 1)
452 {
453 pm->nchars--;
454
455 for (j = i; j < pm->nchars; j++)
456 {
457 pm->kbd_buf[j] = pm->kbd_buf[j + 1];
458 }
459 }
460 else
461 {
462 if (pm->nchars + k - 1 >= KBD_BUF_SIZE)
463 { /* We don't want to overflow the buffer */
464 k = KBD_BUF_SIZE - pm->nchars;
465 }
466
467 for (j = pm->nchars + k - 1; j > i + k; j--)
468 {
469 pm->kbd_buf[j] = pm->kbd_buf[j-k];
470 }
471
472 pm->nchars += k;
473 k++;
474
475 while (k--)
476 {
477 pm->kbd_buf[i++] = ' ';
478 }
479 }
480 }
481 else
482 {
483 i++;
484 }
485 }
486 }
487
488 /* calculate pm->pages and pm->lines */
489 FOR_NB_SCREENS(l)
490 {
491 struct keyboard_parameters *pm = &param[l];
492 struct screen *sc = &screens[l];
493 int sc_h, total_lines;
494
495 sc_h = sc->getheight();
496 pm->lines = (sc_h - BUTTONBAR_HEIGHT) / pm->font_h - 1;
497
498 if (pm->default_lines && pm->lines > pm->default_lines)
499 pm->lines = pm->default_lines;
500
501 pm->keyboard_margin = sc_h - BUTTONBAR_HEIGHT
502 - (pm->lines+1)*pm->font_h;
503
504 if (pm->keyboard_margin < 3 && pm->lines > 1)
505 {
506 pm->lines--;
507 pm->keyboard_margin += pm->font_h;
508 }
509
510 if (pm->keyboard_margin > DEFAULT_MARGIN)
511 pm->keyboard_margin = DEFAULT_MARGIN;
512
513 total_lines = (pm->nchars + pm->max_chars - 1) / pm->max_chars;
514 pm->pages = (total_lines + pm->lines - 1) / pm->lines;
515 pm->lines = (total_lines + pm->pages - 1) / pm->pages;
516
517 pm->main_y = pm->font_h*pm->lines + pm->keyboard_margin;
518 pm->keyboard_margin -= pm->keyboard_margin/2;
519
520#ifdef HAVE_MORSE_INPUT
521 pm->old_main_y = sc_h - pm->font_h - BUTTONBAR_HEIGHT;
522 if (state.morse_mode)
523 {
524 int y = pm->main_y;
525 pm->main_y = pm->old_main_y;
526 pm->old_main_y = y;
527 }
528#endif
529 }
530
531 /* Initial edit position is after last character */
532 state.editpos = utf8length(state.text);
533
534 if (global_settings.talk_menu) /* voice UI? */ 394 if (global_settings.talk_menu) /* voice UI? */
535 talk_spell(state.text, true); /* spell initial text */ 395 talk_spell(state.text, true); /* spell initial text */
536 396
@@ -551,189 +411,14 @@ int kbd_input(char* text, int buflen)
551 state.len_utf8 = utf8length(state.text); 411 state.len_utf8 = utf8length(state.text);
552 412
553 FOR_NB_SCREENS(l) 413 FOR_NB_SCREENS(l)
554 screens[l].clear_display();
555
556 FOR_NB_SCREENS(l)
557 {
558#ifdef HAVE_MORSE_INPUT
559 if (state.morse_mode)
560 {
561 /* declare scoped pointers inside screen loops - hide the
562 declarations from previous block level */
563 const int w = 6, h = 8; /* sysfixed font width, height */
564 struct keyboard_parameters *pm = &param[l];
565 struct screen *sc = &screens[l];
566 int i, x, y;
567 int sc_w = sc->getwidth(), sc_h = pm->main_y - pm->keyboard_margin - 1;
568
569 /* Draw morse code screen with sysfont */
570 sc->setfont(FONT_SYSFIXED);
571 x = 0;
572 y = 0;
573 outline[1] = '\0';
574
575 /* Draw morse code table with code descriptions. */
576 for (i = 0; morse_alphabets[i] != '\0'; i++)
577 {
578 int morse_code, j;
579
580 outline[0] = morse_alphabets[i];
581 sc->putsxy(x, y, outline);
582
583 morse_code = morse_codes[i];
584 for (j = 0; morse_code > 0x01; morse_code >>= 1)
585 j++;
586
587 x += w + 3 + j*4;
588 morse_code = morse_codes[i];
589 for (; morse_code > 0x01; morse_code >>= 1)
590 {
591 x -= 4;
592 if (morse_code & 0x01)
593 sc->fillrect(x, y + 2, 3, 4);
594 else
595 sc->fillrect(x, y + 3, 1, 2);
596 }
597
598 x += w*5 - 3;
599 if (x + w*6 >= sc_w)
600 {
601 x = 0;
602 y += h;
603 if (y + h >= sc_h)
604 break;
605 }
606 }
607 }
608 else
609#endif /* HAVE_MORSE_INPUT */
610 {
611 /* draw page */
612 struct keyboard_parameters *pm = &param[l];
613 struct screen *sc = &screens[l];
614 int i, j, k;
615
616 sc->setfont(pm->curfont);
617
618 k = pm->page*pm->max_chars*pm->lines;
619
620 for (i = j = 0; k < pm->nchars; k++)
621 {
622 int w;
623 unsigned char *utf8;
624 utf8 = utf8encode(pm->kbd_buf[k], outline);
625 *utf8 = 0;
626
627 sc->getstringsize(outline, &w, NULL);
628 sc->putsxy(i*pm->font_w + (pm->font_w-w) / 2,
629 j*pm->font_h, outline);
630
631 if (++i >= pm->max_chars)
632 {
633 i = 0;
634 if (++j >= pm->lines)
635 break;
636 }
637 }
638
639#ifdef KBD_MODES
640 if (!pm->line_edit)
641#endif
642 {
643 /* highlight the key that has focus */
644 sc->set_drawmode(DRMODE_COMPLEMENT);
645 sc->fillrect(pm->font_w*pm->x, pm->font_h*pm->y,
646 pm->font_w, pm->font_h);
647 sc->set_drawmode(DRMODE_SOLID);
648 }
649 }
650 }
651
652 FOR_NB_SCREENS(l)
653 { 414 {
415 /* declare scoped pointers inside screen loops - hide the
416 declarations from previous block level */
654 struct keyboard_parameters *pm = &param[l]; 417 struct keyboard_parameters *pm = &param[l];
655 struct screen *sc = &screens[l]; 418 struct screen *sc = &screens[l];
656 unsigned char *utf8; 419 sc->clear_display();
657 int i = 0, j = 0, icon_w; 420 kbd_draw_picker(pm, sc, &state);
658 int text_w = pm->text_w; 421 kbd_draw_edit_line(pm, sc, &state);
659 int sc_w = sc->getwidth();
660 int y = pm->main_y - pm->keyboard_margin, w;
661 int text_margin = (sc_w - text_w * pm->max_chars_text) / 2;
662
663 /* Clear text area one pixel above separator line so any overdraw
664 doesn't collide */
665 screen_clear_area(sc, 0, y - 1, sc_w, pm->font_h + 4);
666
667 sc->hline(0, sc_w - 1, y);
668
669 /* write out the text */
670 sc->setfont(pm->curfont);
671
672 pm->curpos = MIN(state.editpos, pm->max_chars_text
673 - MIN(state.len_utf8 - state.editpos, 2));
674 pm->leftpos = state.editpos - pm->curpos;
675 utf8 = state.text + utf8seek(state.text, pm->leftpos);
676
677 while (*utf8 && i < pm->max_chars_text)
678 {
679 j = utf8seek(utf8, 1);
680 strlcpy(outline, utf8, j+1);
681 sc->getstringsize(outline, &w, NULL);
682 sc->putsxy(text_margin + i*text_w + (text_w-w)/2,
683 pm->main_y, outline);
684 utf8 += j;
685 i++;
686 }
687
688 icon_w = get_icon_width(l);
689 if (pm->leftpos > 0)
690 {
691 /* Draw nicer bitmap arrow if room, else settle for "<". */
692 if (text_margin >= icon_w)
693 {
694 screen_put_icon_with_offset(sc, 0, 0,
695 (text_margin - icon_w) / 2,
696 pm->main_y, Icon_Reverse_Cursor);
697 }
698 else
699 {
700 sc->getstringsize("<", &w, NULL);
701 sc->putsxy(text_margin - w, pm->main_y, "<");
702 }
703 }
704
705 if (state.len_utf8 - pm->leftpos > pm->max_chars_text)
706 {
707 /* Draw nicer bitmap arrow if room, else settle for ">". */
708 if (text_margin >= icon_w)
709 {
710 screen_put_icon_with_offset(sc, 0, 0,
711 sc_w - (text_margin + icon_w) / 2,
712 pm->main_y, Icon_Cursor);
713 }
714 else
715 {
716 sc->putsxy(sc_w - text_margin, pm->main_y, ">");
717 }
718 }
719
720 /* cursor */
721 i = text_margin + pm->curpos * text_w;
722
723 if (state.cur_blink)
724 sc->vline(i, pm->main_y, pm->main_y + pm->font_h - 1);
725
726 if (state.hangul) /* draw underbar */
727 sc->hline(i - text_w, i, pm->main_y + pm->font_h - 1);
728
729#ifdef KBD_MODES
730 if (pm->line_edit)
731 {
732 sc->set_drawmode(DRMODE_COMPLEMENT);
733 sc->fillrect(0, y + 2, sc_w, pm->font_h + 2);
734 sc->set_drawmode(DRMODE_SOLID);
735 }
736#endif
737 } 422 }
738 423
739 state.cur_blink = !state.cur_blink; 424 state.cur_blink = !state.cur_blink;
@@ -1145,3 +830,320 @@ int kbd_input(char* text, int buflen)
1145 } 830 }
1146 return ret; 831 return ret;
1147} 832}
833
834static void kbd_calc_params(struct keyboard_parameters *pm,
835 struct screen *sc, struct edit_state *state)
836{
837 struct font* font;
838 const unsigned char *p;
839 unsigned short ch;
840 int icon_w, sc_w, sc_h, w;
841 int i, total_lines;
842
843 pm->curfont = pm->default_lines ? FONT_SYSFIXED : FONT_UI;
844 font = font_get(pm->curfont);
845 pm->font_h = font->height;
846
847 /* check if FONT_UI fits the screen */
848 if (2*pm->font_h + 3 + BUTTONBAR_HEIGHT > sc->getheight())
849 {
850 pm->curfont = FONT_SYSFIXED;
851 font = font_get(FONT_SYSFIXED);
852 pm->font_h = font->height;
853 }
854
855 /* find max width of keyboard glyphs.
856 * since we're going to be adding spaces,
857 * max width is at least their width */
858 pm->font_w = font_get_width(font, ' ');
859 for (i = 0; i < pm->nchars; i++)
860 {
861 if (pm->kbd_buf[i] != '\n')
862 {
863 w = font_get_width(font, pm->kbd_buf[i]);
864 if (pm->font_w < w)
865 pm->font_w = w;
866 }
867 }
868
869 /* Find max width for text string */
870 pm->text_w = pm->font_w;
871 p = state->text;
872 while (*p)
873 {
874 p = utf8decode(p, &ch);
875 w = font_get_width(font, ch);
876 if (pm->text_w < w)
877 pm->text_w = w;
878 }
879
880 /* calculate how many characters to put in a row. */
881 icon_w = get_icon_width(sc->screen_type);
882 sc_w = sc->getwidth();
883 pm->max_chars = sc_w / pm->font_w;
884 pm->max_chars_text = (sc_w - icon_w * 2 - 2) / pm->text_w;
885 if (pm->max_chars_text < 3 && icon_w > pm->text_w)
886 pm->max_chars_text = sc_w / pm->text_w - 2;
887
888
889 i = 0;
890 /* Pad lines with spaces */
891 while (i < pm->nchars)
892 {
893 if (pm->kbd_buf[i] == '\n')
894 {
895 int k = pm->max_chars - i % ( pm->max_chars ) - 1;
896 int j;
897
898 if (k == pm->max_chars - 1)
899 {
900 pm->nchars--;
901
902 for (j = i; j < pm->nchars; j++)
903 {
904 pm->kbd_buf[j] = pm->kbd_buf[j + 1];
905 }
906 }
907 else
908 {
909 if (pm->nchars + k - 1 >= KBD_BUF_SIZE)
910 { /* We don't want to overflow the buffer */
911 k = KBD_BUF_SIZE - pm->nchars;
912 }
913
914 for (j = pm->nchars + k - 1; j > i + k; j--)
915 {
916 pm->kbd_buf[j] = pm->kbd_buf[j-k];
917 }
918
919 pm->nchars += k;
920 k++;
921
922 while (k--)
923 {
924 pm->kbd_buf[i++] = ' ';
925 }
926 }
927 }
928 else
929 {
930 i++;
931 }
932 }
933
934 /* calculate pm->pages and pm->lines */
935 sc_h = sc->getheight();
936 pm->lines = (sc_h - BUTTONBAR_HEIGHT) / pm->font_h - 1;
937
938 if (pm->default_lines && pm->lines > pm->default_lines)
939 pm->lines = pm->default_lines;
940
941 pm->keyboard_margin = sc_h - BUTTONBAR_HEIGHT
942 - (pm->lines+1)*pm->font_h;
943
944 if (pm->keyboard_margin < 3 && pm->lines > 1)
945 {
946 pm->lines--;
947 pm->keyboard_margin += pm->font_h;
948 }
949
950 if (pm->keyboard_margin > DEFAULT_MARGIN)
951 pm->keyboard_margin = DEFAULT_MARGIN;
952
953 total_lines = (pm->nchars + pm->max_chars - 1) / pm->max_chars;
954 pm->pages = (total_lines + pm->lines - 1) / pm->lines;
955 pm->lines = (total_lines + pm->pages - 1) / pm->pages;
956
957 pm->main_y = pm->font_h*pm->lines + pm->keyboard_margin;
958 pm->keyboard_margin -= pm->keyboard_margin/2;
959
960#ifdef HAVE_MORSE_INPUT
961 pm->old_main_y = sc_h - pm->font_h - BUTTONBAR_HEIGHT;
962 if (state->morse_mode)
963 {
964 int y = pm->main_y;
965 pm->main_y = pm->old_main_y;
966 pm->old_main_y = y;
967 }
968#endif
969}
970
971static void kbd_draw_picker(struct keyboard_parameters *pm,
972 struct screen *sc, struct edit_state *state)
973{
974 char outline[8];
975#ifdef HAVE_MORSE_INPUT
976 if (state->morse_mode)
977 {
978 const int w = 6, h = 8; /* sysfixed font width, height */
979 int i, j, x, y;
980 int sc_w = sc->getwidth(), sc_h = pm->main_y - pm->keyboard_margin - 1;
981
982 /* Draw morse code screen with sysfont */
983 sc->setfont(FONT_SYSFIXED);
984 x = 0;
985 y = 0;
986 outline[1] = '\0';
987
988 /* Draw morse code table with code descriptions. */
989 for (i = 0; morse_alphabets[i] != '\0'; i++)
990 {
991 int morse_code;
992
993 outline[0] = morse_alphabets[i];
994 sc->putsxy(x, y, outline);
995
996 morse_code = morse_codes[i];
997 for (j = 0; morse_code > 0x01; morse_code >>= 1)
998 j++;
999
1000 x += w + 3 + j*4;
1001 morse_code = morse_codes[i];
1002 for (; morse_code > 0x01; morse_code >>= 1)
1003 {
1004 x -= 4;
1005 if (morse_code & 0x01)
1006 sc->fillrect(x, y + 2, 3, 4);
1007 else
1008 sc->fillrect(x, y + 3, 1, 2);
1009 }
1010
1011 x += w*5 - 3;
1012 if (x + w*6 >= sc_w)
1013 {
1014 x = 0;
1015 y += h;
1016 if (y + h >= sc_h)
1017 break;
1018 }
1019 }
1020 }
1021 else
1022#else
1023 (void) state;
1024#endif /* HAVE_MORSE_INPUT */
1025 {
1026 /* draw page */
1027 int i, j, k;
1028
1029 sc->setfont(pm->curfont);
1030
1031 k = pm->page*pm->max_chars*pm->lines;
1032
1033 for (i = j = 0; k < pm->nchars; k++)
1034 {
1035 int w;
1036 unsigned char *utf8;
1037 utf8 = utf8encode(pm->kbd_buf[k], outline);
1038 *utf8 = 0;
1039
1040 sc->getstringsize(outline, &w, NULL);
1041 sc->putsxy(i*pm->font_w + (pm->font_w-w) / 2,
1042 j*pm->font_h, outline);
1043
1044 if (++i >= pm->max_chars)
1045 {
1046 i = 0;
1047 if (++j >= pm->lines)
1048 break;
1049 }
1050 }
1051
1052#ifdef KBD_MODES
1053 if (!pm->line_edit)
1054#endif
1055 {
1056 /* highlight the key that has focus */
1057 sc->set_drawmode(DRMODE_COMPLEMENT);
1058 sc->fillrect(pm->font_w*pm->x, pm->font_h*pm->y,
1059 pm->font_w, pm->font_h);
1060 sc->set_drawmode(DRMODE_SOLID);
1061 }
1062 }
1063}
1064
1065static void kbd_draw_edit_line(struct keyboard_parameters *pm,
1066 struct screen *sc, struct edit_state *state)
1067{
1068 char outline[8];
1069 unsigned char *utf8;
1070 int i = 0, j = 0, icon_w, w;
1071 int sc_w = sc->getwidth();
1072 int y = pm->main_y - pm->keyboard_margin;
1073 int text_margin = (sc_w - pm->text_w * pm->max_chars_text) / 2;
1074
1075 /* Clear text area one pixel above separator line so any overdraw
1076 doesn't collide */
1077 screen_clear_area(sc, 0, y - 1, sc_w, pm->font_h + 6);
1078
1079 sc->hline(0, sc_w - 1, y);
1080
1081 /* write out the text */
1082 sc->setfont(pm->curfont);
1083
1084 pm->leftpos = MAX(0, MIN(state->len_utf8, state->editpos + 2)
1085 - pm->max_chars_text);
1086 pm->curpos = state->editpos - pm->leftpos;
1087 utf8 = state->text + utf8seek(state->text, pm->leftpos);
1088
1089 while (*utf8 && i < pm->max_chars_text)
1090 {
1091 j = utf8seek(utf8, 1);
1092 strlcpy(outline, utf8, j+1);
1093 sc->getstringsize(outline, &w, NULL);
1094 sc->putsxy(text_margin + i*pm->text_w + (pm->text_w-w)/2,
1095 pm->main_y, outline);
1096 utf8 += j;
1097 i++;
1098 }
1099
1100 icon_w = get_icon_width(sc->screen_type);
1101 if (pm->leftpos > 0)
1102 {
1103 /* Draw nicer bitmap arrow if room, else settle for "<". */
1104 if (text_margin >= icon_w)
1105 {
1106 screen_put_icon_with_offset(sc, 0, 0,
1107 (text_margin - icon_w) / 2,
1108 pm->main_y, Icon_Reverse_Cursor);
1109 }
1110 else
1111 {
1112 sc->getstringsize("<", &w, NULL);
1113 sc->putsxy(text_margin - w, pm->main_y, "<");
1114 }
1115 }
1116
1117 if (state->len_utf8 - pm->leftpos > pm->max_chars_text)
1118 {
1119 /* Draw nicer bitmap arrow if room, else settle for ">". */
1120 if (text_margin >= icon_w)
1121 {
1122 screen_put_icon_with_offset(sc, 0, 0,
1123 sc_w - (text_margin + icon_w) / 2,
1124 pm->main_y, Icon_Cursor);
1125 }
1126 else
1127 {
1128 sc->putsxy(sc_w - text_margin, pm->main_y, ">");
1129 }
1130 }
1131
1132 /* cursor */
1133 i = text_margin + pm->curpos * pm->text_w;
1134
1135 if (state->cur_blink)
1136 sc->vline(i, pm->main_y, pm->main_y + pm->font_h - 1);
1137
1138 if (state->hangul) /* draw underbar */
1139 sc->hline(i - pm->text_w, i, pm->main_y + pm->font_h - 1);
1140
1141#ifdef KBD_MODES
1142 if (pm->line_edit)
1143 {
1144 sc->set_drawmode(DRMODE_COMPLEMENT);
1145 sc->fillrect(0, y + 2, sc_w, pm->font_h + 2);
1146 sc->set_drawmode(DRMODE_SOLID);
1147 }
1148#endif
1149}