1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Björn Stenberg
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
30 #include "rbunicode.h"
31 #include "buttonbar.h"
48 #define DEFAULT_MARGIN 6
49 #define KBD_BUF_SIZE 500
51 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
52 (CONFIG_KEYPAD == IRIVER_H300_PAD)
53 #define KBD_CURSOR_KEYS /* certain key combos move the cursor even if not
55 #define KBD_MODES /* I-Rivers can use picker, line edit and cursor keys */
56 #define KBD_MORSE_INPUT /* I-Rivers have a Morse input mode */
58 #elif CONFIG_KEYPAD == ONDIO_PAD /* restricted Ondio keypad */
59 #define KBD_MODES /* Ondio uses 2 modes, picker and line edit */
61 #elif (CONFIG_KEYPAD == IPOD_1G2G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) \
62 || (CONFIG_KEYPAD == IPOD_4G_PAD)
63 #define KBD_MODES /* iPod uses 2 modes, picker and line edit */
64 #define KBD_MORSE_INPUT
66 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
67 #define KBD_MODES /* iFP7xx uses 2 modes, picker and line edit */
69 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) || (CONFIG_KEYPAD == IAUDIO_M3_PAD)
70 #define KBD_MODES /* iAudios use 2 modes, picker and line edit */
72 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
73 #define KBD_MODES /* iriver H10 uses 2 modes, picker and line edit */
74 #define KBD_MORSE_INPUT
76 #elif CONFIG_KEYPAD == GIGABEAT_PAD
77 #define KBD_CURSOR_KEYS
79 #define KBD_MORSE_INPUT
81 #elif CONFIG_KEYPAD == SANSA_E200_PAD \
82 || CONFIG_KEYPAD == SANSA_FUZE_PAD
83 #define KBD_CURSOR_KEYS
86 #elif CONFIG_KEYPAD == SANSA_C200_PAD
87 #define KBD_CURSOR_KEYS
90 #elif CONFIG_KEYPAD == MROBE100_PAD
91 #define KBD_MORSE_INPUT
94 struct keyboard_parameters
96 const unsigned char* default_kbd
;
98 unsigned short kbd_buf
[KBD_BUF_SIZE
];
121 unsigned short hlead
, hvowel
, htail
;
124 static struct keyboard_parameters kbd_param
[NB_SCREENS
];
125 static bool kbd_loaded
= false;
127 #ifdef KBD_MORSE_INPUT
128 /* FIXME: We should put this to a configuration file. */
129 static const char *morse_alphabets
=
130 "abcdefghijklmnopqrstuvwxyz1234567890,.?-@ ";
131 static const unsigned char morse_codes
[] = {
132 0x05,0x18,0x1a,0x0c,0x02,0x12,0x0e,0x10,0x04,0x17,0x0d,0x14,0x07,
133 0x06,0x0f,0x16,0x1d,0x0a,0x08,0x03,0x09,0x11,0x0b,0x19,0x1b,0x1c,
134 0x2f,0x27,0x23,0x21,0x20,0x30,0x38,0x3c,0x3e,0x3f,
135 0x73,0x55,0x4c,0x61,0x5a,0x80 };
137 static bool morse_mode
= false;
140 /* Loads a custom keyboard into memory
141 call with NULL to reset keyboard */
142 int load_kbd(unsigned char* filename
)
146 unsigned char buf
[4];
148 if (filename
== NULL
)
154 fd
= open_utf8(filename
, O_RDONLY
|O_BINARY
);
158 while (read(fd
, buf
, 1) == 1 && i
< KBD_BUF_SIZE
)
160 /* check how many bytes to read for this character */
161 static const unsigned char sizes
[4] = { 0x80, 0xe0, 0xf0, 0xf5 };
164 for (count
= 0; count
< ARRAYLEN(sizes
); count
++)
166 if (buf
[0] < sizes
[count
])
170 if (count
>= ARRAYLEN(sizes
))
171 continue; /* Invalid size. */
173 if (read(fd
, &buf
[1], count
) != (ssize_t
)count
)
181 utf8decode(buf
, &kbd_param
[l
].kbd_buf
[i
]);
183 if (kbd_param
[0].kbd_buf
[i
] != 0xFEFF &&
184 kbd_param
[0].kbd_buf
[i
] != '\r') /*skip BOM & carriage returns */
194 kbd_param
[l
].nchars
= i
;
199 /* helper function to spell a char if voice UI is enabled */
200 static void kbd_spellchar(unsigned short c
)
202 if (global_settings
.talk_menu
) /* voice UI? */
204 unsigned char tmp
[5];
205 /* store char to pass to talk_spell */
206 unsigned char* utf8
= utf8encode(c
, tmp
);
210 talk_id(VOICE_BLANK
, false);
212 talk_spell(tmp
, false);
217 static void say_edit(void)
219 if(global_settings
.talk_menu
)
220 talk_id(VOICE_EDIT
, false);
224 static void kbd_inschar(unsigned char* text
, int buflen
,
225 int* editpos
, unsigned short ch
)
228 unsigned char tmp
[4];
232 k
= utf8length(text
);
233 utf8
= utf8encode(ch
, tmp
);
234 j
= (long)utf8
- (long)tmp
;
236 if (len
+ j
< buflen
)
238 for (i
= len
+j
; k
>= *editpos
; i
--)
241 if ((text
[i
] & MASK
) != COMP
)
252 static void kbd_delchar(unsigned char* text
, int* editpos
)
259 utf8
= text
+ utf8seek(text
, *editpos
);
266 while ((*utf8
& MASK
) == COMP
);
279 /* Lookup k value based on state of param (pm) */
280 static int get_param_k(const struct keyboard_parameters
*pm
)
282 return (pm
->page
*pm
->lines
+ pm
->y
)*pm
->max_chars
+ pm
->x
;
285 int kbd_input(char* text
, int buflen
)
289 /* This seems to keep the sizes for ARM way down */
290 struct keyboard_parameters
* volatile param
= kbd_param
;
292 struct keyboard_parameters
* const param
= kbd_param
;
294 int l
; /* screen loop variable */
296 int editpos
; /* Edit position on all screens */
297 const int statusbar_size
= 0;
300 bool cur_blink
= true; /* Cursor on/off flag */
301 int ret
= 0; /* assume success */
302 #ifdef KBD_MORSE_INPUT
303 bool morse_reading
= false;
304 unsigned char morse_code
= 0;
308 int oldbars
= viewportmanager_set_statusbar(VP_SB_HIDE_ALL
);
311 struct keyboard_parameters
*pm
= ¶m
[l
];
312 #if LCD_WIDTH >= 160 && LCD_HEIGHT >= 96
313 struct screen
*sc
= &screens
[l
];
315 if (sc
->getwidth() >= 160 && sc
->getheight() >= 96)
318 "ABCDEFG abcdefg !?\" @#$%+'\n"
319 "HIJKLMN hijklmn 789 &_()-`\n"
320 "OPQRSTU opqrstu 456 §|{}/<\n"
321 "VWXYZ., vwxyz.,0123 ~=[]*>\n"
322 "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË ¢£¤¥¦§©®\n"
323 "àáâãäåæ ìíîï èéêë «»°ºª¹²³\n"
324 "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ ¯±×÷¡¿µ·\n"
325 "òóôõöø çðþýÿ ùúûü ¼½¾¬¶¨:;";
327 pm
->DEFAULT_LINES
= 8;
330 #endif /* LCD_WIDTH >= 160 && LCD_HEIGHT >= 96 */
333 "ABCDEFG !?\" @#$%+'\n"
334 "HIJKLMN 789 &_()-`\n"
335 "OPQRSTU 456 §|{}/<\n"
336 "VWXYZ.,0123 ~=[]*>\n"
338 "abcdefg ¢£¤¥¦§©®¬\n"
339 "hijklmn «»°ºª¹²³¶\n"
340 "opqrstu ¯±×÷¡¿µ·¨\n"
343 "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË\n"
344 "àáâãäåæ ìíîï èéêë\n"
345 "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ\n"
348 pm
->DEFAULT_LINES
= 4;
353 #ifdef HAVE_BUTTONBAR
354 struct gui_buttonbar buttonbar
;
355 bool buttonbar_config
= global_settings
.buttonbar
;
357 global_settings
.buttonbar
= true;
358 gui_buttonbar_init(&buttonbar
);
361 gui_buttonbar_set_display(&buttonbar
, &screens
[l
]);
366 struct keyboard_parameters
*pm
= ¶m
[l
];
370 /* Copy default keyboard to buffer */
371 const unsigned char *p
= pm
->default_kbd
;
374 pm
->curfont
= FONT_SYSFIXED
;
377 p
= utf8decode(p
, &pm
->kbd_buf
[i
++]);
383 pm
->curfont
= FONT_UI
;
389 struct keyboard_parameters
*pm
= ¶m
[l
];
390 struct screen
*sc
= &screens
[l
];
393 pm
->font
= font_get(pm
->curfont
);
394 pm
->font_h
= pm
->font
->height
;
396 /* check if FONT_UI fits the screen */
397 if (2*pm
->font_h
+ 3 + statusbar_size
+
398 BUTTONBAR_HEIGHT
> sc
->getheight())
400 pm
->font
= font_get(FONT_SYSFIXED
);
401 pm
->font_h
= pm
->font
->height
;
402 pm
->curfont
= FONT_SYSFIXED
;
405 sc
->setfont(pm
->curfont
);
406 pm
->font_w
= 0; /* reset font width */
407 /* find max width of keyboard glyphs */
408 for (i
= 0; i
< pm
->nchars
; i
++)
410 w
= font_get_width(pm
->font
, pm
->kbd_buf
[i
]);
411 if ( w
> pm
->font_w
)
415 /* Since we're going to be adding spaces, make sure that we check
417 w
= font_get_width( pm
->font
, ' ' );
418 if ( w
> pm
->font_w
)
424 struct keyboard_parameters
*pm
= ¶m
[l
];
425 struct screen
*sc
= &screens
[l
];
428 /* Pad lines with spaces */
429 while (i
< pm
->nchars
)
431 if (pm
->kbd_buf
[i
] == '\n')
433 int k
= sc
->getwidth() / pm
->font_w
434 - i
% ( sc
->getwidth() / pm
->font_w
) - 1;
437 if (k
== sc
->getwidth() / pm
->font_w
- 1)
441 for (j
= i
; j
< pm
->nchars
; j
++)
443 pm
->kbd_buf
[j
] = pm
->kbd_buf
[j
+ 1];
448 if (pm
->nchars
+ k
- 1 >= KBD_BUF_SIZE
)
449 { /* We don't want to overflow the buffer */
450 k
= KBD_BUF_SIZE
- pm
->nchars
;
453 for (j
= pm
->nchars
+ k
- 1; j
> i
+ k
; j
--)
455 pm
->kbd_buf
[j
] = pm
->kbd_buf
[j
-k
];
463 pm
->kbd_buf
[i
++] = ' ';
474 /* Find max width for text string */
478 struct keyboard_parameters
*pm
= ¶m
[l
];
479 struct screen
*sc
= &screens
[l
];
485 int w
= font_get_width(pm
->font
, ch
);
486 utf8
= (unsigned char*)utf8decode(utf8
, &ch
);
492 pm
->max_chars_text
= sc
->getwidth() / text_w
- 2;
494 /* Calculate keyboard grid size */
495 pm
->max_chars
= sc
->getwidth() / pm
->font_w
;
499 pm
->lines
= pm
->DEFAULT_LINES
;
500 pm
->keyboard_margin
= DEFAULT_MARGIN
;
504 pm
->lines
= (sc
->getheight() - BUTTONBAR_HEIGHT
- statusbar_size
)
506 pm
->keyboard_margin
= sc
->getheight() - BUTTONBAR_HEIGHT
-
507 statusbar_size
- (pm
->lines
+1)*pm
->font_h
;
509 if (pm
->keyboard_margin
< 3)
512 pm
->keyboard_margin
+= pm
->font_h
;
515 if (pm
->keyboard_margin
> 6)
516 pm
->keyboard_margin
= 6;
519 pm
->pages
= (pm
->nchars
+ (pm
->lines
*pm
->max_chars
-1))
520 / (pm
->lines
*pm
->max_chars
);
522 if (pm
->pages
== 1 && kbd_loaded
)
523 pm
->lines
= (pm
->nchars
+ pm
->max_chars
- 1) / pm
->max_chars
;
525 pm
->main_y
= pm
->font_h
*pm
->lines
+ pm
->keyboard_margin
+ statusbar_size
;
527 pm
->keyboard_margin
-= pm
->keyboard_margin
/2;
529 #ifdef KBD_MORSE_INPUT
530 pm
->old_main_y
= pm
->main_y
;
532 pm
->main_y
= sc
->getheight() - pm
->font_h
;
536 /* Initial edit position is after last character */
537 editpos
= utf8length(text
);
539 if (global_settings
.talk_menu
) /* voice UI? */
540 talk_spell(text
, true); /* spell initial text */
545 /* These declarations are assigned to the screen on which the key
546 action occurred - pointers save a lot of space over array notation
547 when accessing the same array element countless times */
552 const int button_screen
= 0;
554 struct keyboard_parameters
*pm
;
557 int len_utf8
= utf8length(text
);
560 screens
[l
].clear_display();
562 #ifdef KBD_MORSE_INPUT
567 /* declare scoped pointers inside screen loops - hide the
568 declarations from previous block level */
569 const int w
= 6; /* sysfixed font width */
570 struct keyboard_parameters
*pm
= ¶m
[l
];
571 struct screen
*sc
= &screens
[l
];
574 sc
->setfont(FONT_SYSFIXED
); /* Draw morse code screen with sysfont */
576 pm
->y
= statusbar_size
;
579 /* Draw morse code table with code descriptions. */
580 for (i
= 0; morse_alphabets
[i
] != '\0'; i
++)
585 buf
[0] = morse_alphabets
[i
];
586 sc
->putsxy(pm
->x
, pm
->y
, buf
);
588 for (j
= 0; (morse_codes
[i
] >> j
) > 0x01; j
++) ;
592 for (j
= 0; j
< morse_len
; j
++)
594 if ((morse_codes
[i
] >> (morse_len
-j
-1)) & 0x01)
595 sc
->fillrect(pm
->x
+ j
*4, pm
->y
+ 2, 3, 4);
597 sc
->fillrect(pm
->x
+ j
*4, pm
->y
+ 3, 1, 2);
601 if (pm
->x
>= sc
->getwidth() - w
*6)
604 pm
->y
+= 8; /* sysfixed font height */
610 #endif /* KBD_MORSE_INPUT */
615 struct keyboard_parameters
*pm
= ¶m
[l
];
616 struct screen
*sc
= &screens
[l
];
619 sc
->setfont(pm
->curfont
);
621 k
= pm
->page
*pm
->max_chars
*pm
->lines
;
623 for (i
= j
= 0; j
< pm
->lines
&& k
< pm
->nchars
; k
++)
626 utf8
= utf8encode(pm
->kbd_buf
[k
], outline
);
629 sc
->getstringsize(outline
, &w
, NULL
);
630 sc
->putsxy(i
*pm
->font_w
+ (pm
->font_w
-w
) / 2,
631 j
*pm
->font_h
+ statusbar_size
, outline
);
633 if (++i
>= pm
->max_chars
)
645 struct keyboard_parameters
*pm
= ¶m
[l
];
646 struct screen
*sc
= &screens
[l
];
649 /* Clear text area one pixel above separator line so any overdraw
651 sc
->set_drawmode(DRMODE_SOLID
| DRMODE_INVERSEVID
);
652 sc
->fillrect(0, pm
->main_y
- pm
->keyboard_margin
- 1,
653 sc
->getwidth(), pm
->font_h
+ 4);
654 sc
->set_drawmode(DRMODE_SOLID
);
656 sc
->hline(0, sc
->getwidth() - 1, pm
->main_y
- pm
->keyboard_margin
);
658 /* write out the text */
659 sc
->setfont(pm
->curfont
);
661 pm
->curpos
= MIN(editpos
, pm
->max_chars_text
662 - MIN(len_utf8
- editpos
, 2));
663 pm
->leftpos
= editpos
- pm
->curpos
;
664 utf8
= text
+ utf8seek(text
, pm
->leftpos
);
668 while (*utf8
&& i
< pm
->max_chars_text
)
670 outline
[j
++] = *utf8
++;
672 if ((*utf8
& MASK
) != COMP
)
678 sc
->getstringsize(outline
, &w
, NULL
);
679 sc
->putsxy(i
*text_w
+ (text_w
-w
)/2, pm
->main_y
, outline
);
685 /* Draw nicer bitmap arrow if room, else settle for "<". */
686 if (text_w
>= 6 && pm
->font_h
>= 8)
688 screen_put_iconxy(sc
, (text_w
- 6) / 2,
689 pm
->main_y
+ (pm
->font_h
- 8) / 2 ,
690 Icon_Reverse_Cursor
);
695 sc
->getstringsize("<", &w
, NULL
);
696 sc
->putsxy(text_w
- w
, pm
->main_y
, "<");
700 if (len_utf8
- pm
->leftpos
> pm
->max_chars_text
)
702 /* Draw nicer bitmap arrow if room, else settle for ">". */
703 if (text_w
>= 6 && pm
->font_h
>= 8)
705 screen_put_iconxy(sc
, sc
->getwidth() - text_w
+
707 pm
->main_y
+ (pm
->font_h
- 8) / 2,
712 sc
->putsxy(sc
->getwidth() - text_w
, pm
->main_y
, ">");
717 i
= (pm
->curpos
+ 1) * text_w
;
720 sc
->vline(i
, pm
->main_y
, pm
->main_y
+ pm
->font_h
- 1);
722 if (pm
->hangul
) /* draw underbar */
723 sc
->hline(pm
->curpos
*text_w
, (pm
->curpos
+1)*text_w
,
724 pm
->main_y
+ pm
->font_h
- 1);
727 cur_blink
= !cur_blink
;
729 #ifdef HAVE_BUTTONBAR
730 /* draw the button bar */
731 gui_buttonbar_set(&buttonbar
, "Shift", "OK", "Del");
732 gui_buttonbar_draw(&buttonbar
);
737 struct keyboard_parameters
*pm
= ¶m
[l
];
738 struct screen
*sc
= &screens
[l
];
740 sc
->set_drawmode(DRMODE_COMPLEMENT
);
743 sc
->fillrect(0, pm
->main_y
- pm
->keyboard_margin
+ 2,
744 sc
->getwidth(), pm
->font_h
+ 2);
745 else /* highlight the key that has focus */
747 sc
->fillrect(pm
->font_w
*pm
->x
,
748 statusbar_size
+ pm
->font_h
*pm
->y
,
749 pm
->font_w
, pm
->font_h
);
750 sc
->set_drawmode(DRMODE_SOLID
);
756 button
= get_action(CONTEXT_KEYBOARD
, HZ
/2);
758 button_screen
= (get_action_statuscode(NULL
) & ACTION_REMOTE
) ? 1 : 0;
760 pm
= ¶m
[button_screen
];
761 sc
= &screens
[button_screen
];
763 #if defined KBD_MORSE_INPUT && !defined KBD_MODES
766 /* Remap some buttons for morse mode. */
767 if (button
== ACTION_KBD_LEFT
)
768 button
= ACTION_KBD_CURSOR_LEFT
;
769 if (button
== ACTION_KBD_RIGHT
)
770 button
= ACTION_KBD_CURSOR_RIGHT
;
776 case ACTION_KBD_ABORT
:
778 screens
[l
].setfont(FONT_UI
);
779 ret
= -1; done
= true;
782 case ACTION_KBD_PAGE_FLIP
:
785 #ifdef KBD_MORSE_INPUT
789 if (++pm
->page
>= pm
->pages
)
793 kbd_spellchar(pm
->kbd_buf
[k
]);
797 #ifdef KBD_MORSE_INPUT
798 case ACTION_KBD_MORSE_INPUT
:
799 morse_mode
= !morse_mode
;
803 struct keyboard_parameters
*pm
= ¶m
[l
];
804 struct screen
*sc
= &screens
[l
];
806 pm
->x
= pm
->y
= pm
->page
= 0;
810 pm
->old_main_y
= pm
->main_y
;
811 pm
->main_y
= sc
->getheight() - pm
->font_h
;
815 pm
->main_y
= pm
->old_main_y
;
818 /* FIXME: We should talk something like Morse mode.. */
820 #endif /* KBD_MORSE_INPUT */
822 case ACTION_KBD_RIGHT
:
824 #ifdef KBD_MORSE_INPUT
825 /* allow cursor change in non line edit morse mode */
826 if (pm
->line_edit
|| morse_mode
)
828 /* right doubles as cursor_right in line_edit */
834 if (editpos
< len_utf8
)
836 int c
= utf8seek(text
, ++editpos
);
837 kbd_spellchar(text
[c
]);
839 #if CONFIG_CODEC == SWCODEC
840 else if (global_settings
.talk_menu
)
841 pcmbuf_beep(1000, 150, 1500);
845 #endif /* KBD_MODES */
848 #ifdef KBD_MORSE_INPUT
852 if (++pm
->x
>= pm
->max_chars
)
854 #ifndef KBD_PAGE_FLIP
855 /* no dedicated flip key - flip page on wrap */
856 if (++pm
->page
>= pm
->pages
)
863 kbd_spellchar(pm
->kbd_buf
[k
]);
867 case ACTION_KBD_LEFT
:
869 #ifdef KBD_MORSE_INPUT
870 /* allow cursor change in non line edit morse mode */
871 if (pm
->line_edit
|| morse_mode
)
873 /* left doubles as cursor_left in line_edit */
881 int c
= utf8seek(text
, --editpos
);
882 kbd_spellchar(text
[c
]);
884 #if CONFIG_CODEC == SWCODEC
885 else if (global_settings
.talk_menu
)
886 pcmbuf_beep(1000, 150, 1500);
890 #endif /* KBD_MODES */
893 #ifdef KBD_MORSE_INPUT
899 #ifndef KBD_PAGE_FLIP
900 /* no dedicated flip key - flip page on wrap */
902 pm
->page
= pm
->pages
- 1;
904 pm
->x
= pm
->max_chars
- 1;
908 kbd_spellchar(pm
->kbd_buf
[k
]);
912 case ACTION_KBD_DOWN
:
913 #ifdef KBD_MORSE_INPUT
917 pm
->line_edit
= !pm
->line_edit
;
926 #endif /* KBD_MORSE_INPUT */
932 pm
->line_edit
= false;
936 if (++pm
->y
>= pm
->lines
)
939 pm
->line_edit
= true;
950 int k
= get_param_k(pm
);
951 kbd_spellchar(pm
->kbd_buf
[k
]);
956 #ifdef KBD_MORSE_INPUT
960 pm
->line_edit
= !pm
->line_edit
;
969 #endif /* KBD_MORSE_INPUT */
974 pm
->y
= pm
->lines
- 1;
975 pm
->line_edit
= false;
982 pm
->line_edit
= true;
986 pm
->y
= pm
->lines
- 1;
993 int k
= get_param_k(pm
);
994 kbd_spellchar(pm
->kbd_buf
[k
]);
998 case ACTION_KBD_DONE
:
999 /* accepts what was entered and continues */
1004 #ifdef KBD_MORSE_INPUT
1005 case ACTION_KBD_MORSE_SELECT
:
1006 if (morse_mode
&& morse_reading
)
1009 if ((current_tick
- morse_tick
) > HZ
/5)
1014 #endif /* KBD_MORSE_INPUT */
1016 case ACTION_KBD_SELECT
:
1017 case ACTION_KBD_SELECT_REM
:
1018 #ifdef KBD_MORSE_INPUT
1020 if (morse_mode
&& !pm
->line_edit
)
1025 morse_tick
= current_tick
;
1029 morse_reading
= true;
1034 #endif /* KBD_MORSE_INPUT */
1036 /* inserts the selected char */
1039 { /* select doubles as backspace in line_edit */
1044 else if (pm
->hvowel
)
1050 kbd_delchar(text
, &editpos
);
1055 ch
= hangul_join(pm
->hlead
, pm
->hvowel
, pm
->htail
);
1058 kbd_inschar(text
, buflen
, &editpos
, ch
);
1062 #endif /* KBD_MODES */
1064 /* find input char */
1065 int k
= get_param_k(pm
);
1066 ch
= (k
< pm
->nchars
) ? pm
->kbd_buf
[k
] : ' ';
1068 /* check for hangul input */
1069 if (ch
>= 0x3131 && ch
<= 0x3163)
1075 pm
->hlead
= pm
->hvowel
= pm
->htail
= 0;
1083 else if (!pm
->htail
)
1088 { /* previous hangul complete */
1089 /* check whether tail is actually lead of next char */
1090 tmp
= hangul_join(pm
->htail
, ch
, 0);
1094 tmp
= hangul_join(pm
->hlead
, pm
->hvowel
, 0);
1095 kbd_delchar(text
, &editpos
);
1096 kbd_inschar(text
, buflen
, &editpos
, tmp
);
1097 /* insert dummy char */
1098 kbd_inschar(text
, buflen
, &editpos
, ' ');
1099 pm
->hlead
= pm
->htail
;
1105 pm
->hvowel
= pm
->htail
= 0;
1110 /* combine into hangul */
1111 tmp
= hangul_join(pm
->hlead
, pm
->hvowel
, pm
->htail
);
1115 kbd_delchar(text
, &editpos
);
1120 pm
->hvowel
= pm
->htail
= 0;
1130 kbd_inschar(text
, buflen
, &editpos
, ch
);
1133 if (global_settings
.talk_menu
) /* voice UI? */
1134 talk_spell(text
, false);
1136 /* speak revised text */
1139 #if !defined (KBD_MODES) || defined (KBD_CURSOR_KEYS)
1140 case ACTION_KBD_BACKSPACE
:
1145 else if (pm
->hvowel
)
1151 kbd_delchar(text
, &editpos
);
1156 ch
= hangul_join(pm
->hlead
, pm
->hvowel
, pm
->htail
);
1159 kbd_inschar(text
, buflen
, &editpos
, ch
);
1162 if (global_settings
.talk_menu
) /* voice UI? */
1163 talk_spell(text
, false); /* speak revised text */
1166 case ACTION_KBD_CURSOR_RIGHT
:
1169 if (editpos
< len_utf8
)
1171 int c
= utf8seek(text
, ++editpos
);
1172 kbd_spellchar(text
[c
]);
1174 #if CONFIG_CODEC == SWCODEC
1175 else if (global_settings
.talk_menu
)
1176 pcmbuf_beep(1000, 150, 1500);
1180 case ACTION_KBD_CURSOR_LEFT
:
1185 int c
= utf8seek(text
, --editpos
);
1186 kbd_spellchar(text
[c
]);
1188 #if CONFIG_CODEC == SWCODEC
1189 else if (global_settings
.talk_menu
)
1190 pcmbuf_beep(1000, 150, 1500);
1193 #endif /* !defined (KBD_MODES) || defined (KBD_CURSOR_KEYS) */
1196 #ifdef KBD_MORSE_INPUT
1200 logf("Morse: 0x%02x", morse_code
);
1201 morse_reading
= false;
1203 for (j
= 0; morse_alphabets
[j
] != '\0'; j
++)
1205 if (morse_codes
[j
] == morse_code
)
1209 if (morse_alphabets
[j
] == '\0')
1211 logf("Morse code not found");
1215 /* turn off hangul input */
1217 param
[l
].hangul
= false;
1218 kbd_inschar(text
, buflen
, &editpos
, morse_alphabets
[j
]);
1220 if (global_settings
.talk_menu
) /* voice UI? */
1221 talk_spell(text
, false); /* speak revised text */
1223 #endif /* KBD_MORSE_INPUT */
1227 if (default_event_handler(button
) == SYS_USB_CONNECTED
)
1230 screens
[l
].setfont(FONT_SYSFIXED
);
1236 if (button
!= BUTTON_NONE
)
1242 #ifdef HAVE_BUTTONBAR
1243 global_settings
.buttonbar
= buttonbar_config
;
1247 screens
[l
].setfont(FONT_UI
);
1248 viewportmanager_set_statusbar(oldbars
);
1251 splash(HZ
/2, ID2P(LANG_CANCEL
));