1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Björn Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
25 #include "statusbar.h"
29 #include "rbunicode.h"
30 #include "buttonbar.h"
40 #if CONFIG_KEYPAD == RECORDER_PAD
41 #define BUTTONBAR_HEIGHT 8
43 #define BUTTONBAR_HEIGHT 0
46 #define DEFAULT_MARGIN 6
47 #define KBD_BUF_SIZE 500
49 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
50 (CONFIG_KEYPAD == IRIVER_H300_PAD)
51 #define KBD_CURSOR_KEYS /* certain key combos move the cursor even if not
53 #define KBD_MODES /* I-Rivers can use picker, line edit and cursor keys */
54 #define KBD_MORSE_INPUT /* I-Rivers have a Morse input mode */
56 #elif CONFIG_KEYPAD == ONDIO_PAD /* restricted Ondio keypad */
57 #define KBD_MODES /* Ondio uses 2 modes, picker and line edit */
59 #elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD)
60 #define KBD_MODES /* iPod uses 2 modes, picker and line edit */
61 #define KBD_MORSE_INPUT
63 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
64 #define KBD_MODES /* iFP7xx uses 2 modes, picker and line edit */
66 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
67 #define KBD_MODES /* iAudio X5 uses 2 modes, picker and line edit */
69 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
70 #define KBD_MODES /* iriver H10 uses 2 modes, picker and line edit */
71 #define KBD_MORSE_INPUT
73 #elif CONFIG_KEYPAD == GIGABEAT_PAD
74 #define KBD_CURSOR_KEYS
76 #define KBD_MORSE_INPUT
78 #elif CONFIG_KEYPAD == SANSA_E200_PAD
79 #define KBD_CURSOR_KEYS
83 struct keyboard_parameters
85 const unsigned char* default_kbd
;
87 unsigned short kbd_buf
[KBD_BUF_SIZE
];
110 unsigned short hlead
, hvowel
, htail
;
113 static struct keyboard_parameters kbd_param
[NB_SCREENS
];
114 static bool kbd_loaded
= false;
116 #ifdef KBD_MORSE_INPUT
117 /* FIXME: We should put this to a configuration file. */
118 static const char *morse_alphabets
=
119 "abcdefghijklmnopqrstuvwxyz1234567890,.?-@ ";
120 static const unsigned char morse_codes
[] = {
121 0x05,0x18,0x1a,0x0c,0x02,0x12,0x0e,0x10,0x04,0x17,0x0d,0x14,0x07,
122 0x06,0x0f,0x16,0x1d,0x0a,0x08,0x03,0x09,0x11,0x0b,0x19,0x1b,0x1c,
123 0x2f,0x27,0x23,0x21,0x20,0x30,0x38,0x3c,0x3e,0x3f,
124 0x73,0x55,0x4c,0x61,0x5a,0x80 };
126 static bool morse_mode
= false;
129 /* Loads a custom keyboard into memory
130 call with NULL to reset keyboard */
131 int load_kbd(unsigned char* filename
)
135 unsigned char buf
[4];
137 if (filename
== NULL
)
143 fd
= open(filename
, O_RDONLY
|O_BINARY
);
147 while (read(fd
, buf
, 1) == 1 && i
< KBD_BUF_SIZE
)
149 /* check how many bytes to read for this character */
150 static const unsigned char sizes
[4] = { 0x80, 0xe0, 0xf0, 0xf5 };
153 for (count
= 0; count
< ARRAYLEN(sizes
); count
++)
155 if (buf
[0] < sizes
[count
])
159 if (count
>= ARRAYLEN(sizes
))
160 continue; /* Invalid size. */
162 if (read(fd
, &buf
[1], count
) != (ssize_t
)count
)
170 utf8decode(buf
, &kbd_param
[l
].kbd_buf
[i
]);
172 if (kbd_param
[0].kbd_buf
[i
] != 0xFEFF &&
173 kbd_param
[0].kbd_buf
[i
] != '\r') /*skip BOM & carriage returns */
183 kbd_param
[l
].nchars
= i
;
188 /* helper function to spell a char if voice UI is enabled */
189 static void kbd_spellchar(unsigned short c
)
191 static char spell_char
[2] = "\0\0"; /* store char to pass to talk_spell */
193 if (talk_menus_enabled() && c
< 128) /* voice UI? */
195 spell_char
[0] = (char)c
;
196 talk_spell(spell_char
, false);
200 static void kbd_inschar(unsigned char* text
, int buflen
,
201 int* editpos
, unsigned short ch
)
204 unsigned char tmp
[4];
208 k
= utf8length(text
);
209 utf8
= utf8encode(ch
, tmp
);
210 j
= (long)utf8
- (long)tmp
;
212 if (len
+ j
< buflen
)
214 for (i
= len
+j
; k
>= *editpos
; i
--)
217 if ((text
[i
] & MASK
) != COMP
)
228 static void kbd_delchar(unsigned char* text
, int* editpos
)
235 utf8
= text
+ utf8seek(text
, *editpos
);
242 while ((*utf8
& MASK
) == COMP
);
255 /* Lookup k value based on state of param (pm) */
256 static int get_param_k(const struct keyboard_parameters
*pm
)
258 return (pm
->page
*pm
->lines
+ pm
->y
)*pm
->max_chars
+ pm
->x
;
261 int kbd_input(char* text
, int buflen
)
265 /* This seems to keep the sizes for ARM way down */
266 struct keyboard_parameters
* volatile param
= kbd_param
;
268 struct keyboard_parameters
* const param
= kbd_param
;
270 int l
; /* screen loop variable */
272 int editpos
; /* Edit position on all screens */
273 const int statusbar_size
= global_settings
.statusbar
274 ? STATUSBAR_HEIGHT
: 0;
277 bool cur_blink
= true; /* Cursor on/off flag */
278 #ifdef KBD_MORSE_INPUT
279 bool morse_reading
= false;
280 unsigned char morse_code
= 0;
287 struct keyboard_parameters
*pm
= ¶m
[l
];
288 #if LCD_WIDTH >= 160 && LCD_HEIGHT >= 96
289 struct screen
*sc
= &screens
[l
];
291 if (sc
->width
>= 160 && sc
->height
>= 96)
294 "ABCDEFG abcdefg !?\" @#$%+'\n"
295 "HIJKLMN hijklmn 789 &_()-`\n"
296 "OPQRSTU opqrstu 456 §|{}/<\n"
297 "VWXYZ., vwxyz.,0123 ~=[]*>\n"
298 "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË ¢£¤¥¦§©®\n"
299 "àáâãäåæ ìíîï èéêë «»°ºª¹²³\n"
300 "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ ¯±×÷¡¿µ·\n"
301 "òóôõöø çðþýÿ ùúûü ¼½¾¬¶¨:;";
303 pm
->DEFAULT_LINES
= 8;
306 #endif /* LCD_WIDTH >= 160 && LCD_HEIGHT >= 96 */
309 "ABCDEFG !?\" @#$%+'\n"
310 "HIJKLMN 789 &_()-`\n"
311 "OPQRSTU 456 §|{}/<\n"
312 "VWXYZ.,0123 ~=[]*>\n"
314 "abcdefg ¢£¤¥¦§©®¬\n"
315 "hijklmn «»°ºª¹²³¶\n"
316 "opqrstu ¯±×÷¡¿µ·¨\n"
319 "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË\n"
320 "àáâãäåæ ìíîï èéêë\n"
321 "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ\n"
324 pm
->DEFAULT_LINES
= 4;
330 struct gui_buttonbar buttonbar
;
331 bool buttonbar_config
= global_settings
.buttonbar
;
333 global_settings
.buttonbar
= true;
334 gui_buttonbar_init(&buttonbar
);
337 gui_buttonbar_set_display(&buttonbar
, &screens
[l
]);
342 struct keyboard_parameters
*pm
= ¶m
[l
];
346 /* Copy default keyboard to buffer */
347 const unsigned char *p
= pm
->default_kbd
;
350 pm
->curfont
= FONT_SYSFIXED
;
353 p
= utf8decode(p
, &pm
->kbd_buf
[i
++]);
359 pm
->curfont
= FONT_UI
;
365 struct keyboard_parameters
*pm
= ¶m
[l
];
366 struct screen
*sc
= &screens
[l
];
369 pm
->font
= font_get(pm
->curfont
);
370 pm
->font_h
= pm
->font
->height
;
372 /* check if FONT_UI fits the screen */
373 if (2*pm
->font_h
+ 3 + statusbar_size
+ BUTTONBAR_HEIGHT
> sc
->height
)
375 pm
->font
= font_get(FONT_SYSFIXED
);
376 pm
->font_h
= pm
->font
->height
;
377 pm
->curfont
= FONT_SYSFIXED
;
380 sc
->setfont(pm
->curfont
);
381 pm
->font_w
= 0; /* reset font width */
382 /* find max width of keyboard glyphs */
383 for (i
= 0; i
< pm
->nchars
; i
++)
385 w
= font_get_width(pm
->font
, pm
->kbd_buf
[i
]);
386 if ( w
> pm
->font_w
)
390 /* Since we're going to be adding spaces, make sure that we check
392 w
= font_get_width( pm
->font
, ' ' );
393 if ( w
> pm
->font_w
)
399 struct keyboard_parameters
*pm
= ¶m
[l
];
400 struct screen
*sc
= &screens
[l
];
403 /* Pad lines with spaces */
404 while (i
< pm
->nchars
)
406 if (pm
->kbd_buf
[i
] == '\n')
408 int k
= sc
->width
/ pm
->font_w
409 - i
% ( sc
->width
/ pm
->font_w
) - 1;
412 if (k
== sc
->width
/ pm
->font_w
- 1)
416 for (j
= i
; j
< pm
->nchars
; j
++)
418 pm
->kbd_buf
[j
] = pm
->kbd_buf
[j
+ 1];
423 if (pm
->nchars
+ k
- 1 >= KBD_BUF_SIZE
)
424 { /* We don't want to overflow the buffer */
425 k
= KBD_BUF_SIZE
- pm
->nchars
;
428 for (j
= pm
->nchars
+ k
- 1; j
> i
+ k
; j
--)
430 pm
->kbd_buf
[j
] = pm
->kbd_buf
[j
-k
];
438 pm
->kbd_buf
[i
++] = ' ';
449 /* Find max width for text string */
453 struct keyboard_parameters
*pm
= ¶m
[l
];
454 struct screen
*sc
= &screens
[l
];
460 int w
= font_get_width(pm
->font
, ch
);
461 utf8
= (unsigned char*)utf8decode(utf8
, &ch
);
467 pm
->max_chars_text
= sc
->width
/ text_w
- 2;
469 /* Calculate keyboard grid size */
470 pm
->max_chars
= sc
->width
/ pm
->font_w
;
474 pm
->lines
= pm
->DEFAULT_LINES
;
475 pm
->keyboard_margin
= DEFAULT_MARGIN
;
479 pm
->lines
= (sc
->height
- BUTTONBAR_HEIGHT
- statusbar_size
)
481 pm
->keyboard_margin
= sc
->height
- BUTTONBAR_HEIGHT
-
482 statusbar_size
- (pm
->lines
+1)*pm
->font_h
;
484 if (pm
->keyboard_margin
< 3)
487 pm
->keyboard_margin
+= pm
->font_h
;
490 if (pm
->keyboard_margin
> 6)
491 pm
->keyboard_margin
= 6;
494 pm
->pages
= (pm
->nchars
+ (pm
->lines
*pm
->max_chars
-1))
495 / (pm
->lines
*pm
->max_chars
);
497 if (pm
->pages
== 1 && kbd_loaded
)
498 pm
->lines
= (pm
->nchars
+ pm
->max_chars
- 1) / pm
->max_chars
;
500 pm
->main_y
= pm
->font_h
*pm
->lines
+ pm
->keyboard_margin
+ statusbar_size
;
502 pm
->keyboard_margin
-= pm
->keyboard_margin
/2;
504 #ifdef KBD_MORSE_INPUT
505 pm
->old_main_y
= pm
->main_y
;
507 pm
->main_y
= sc
->height
- pm
->font_h
;
511 /* Initial edit position is after last character */
512 editpos
= utf8length(text
);
514 if (talk_menus_enabled()) /* voice UI? */
515 talk_spell(text
, true); /* spell initial text */
520 /* These declarations are assigned to the screen on which the key
521 action occurred - pointers save a lot of space over array notation
522 when accessing the same array element countless times */
527 const int button_screen
= 0;
529 struct keyboard_parameters
*pm
;
532 int len_utf8
= utf8length(text
);
535 screens
[l
].clear_display();
537 #ifdef KBD_MORSE_INPUT
542 /* declare scoped pointers inside screen loops - hide the
543 declarations from previous block level */
544 const int w
= 6; /* sysfixed font width */
545 struct keyboard_parameters
*pm
= ¶m
[l
];
546 struct screen
*sc
= &screens
[l
];
549 sc
->setfont(FONT_SYSFIXED
); /* Draw morse code screen with sysfont */
551 pm
->y
= statusbar_size
;
554 /* Draw morse code table with code descriptions. */
555 for (i
= 0; morse_alphabets
[i
] != '\0'; i
++)
560 buf
[0] = morse_alphabets
[i
];
561 sc
->putsxy(pm
->x
, pm
->y
, buf
);
563 for (j
= 0; (morse_codes
[i
] >> j
) > 0x01; j
++) ;
567 for (j
= 0; j
< morse_len
; j
++)
569 if ((morse_codes
[i
] >> (morse_len
-j
-1)) & 0x01)
570 sc
->fillrect(pm
->x
+ j
*4, pm
->y
+ 2, 3, 4);
572 sc
->fillrect(pm
->x
+ j
*4, pm
->y
+ 3, 1, 2);
576 if (pm
->x
>= sc
->width
- w
*6)
579 pm
->y
+= 8; /* sysfixed font height */
585 #endif /* KBD_MORSE_INPUT */
590 struct keyboard_parameters
*pm
= ¶m
[l
];
591 struct screen
*sc
= &screens
[l
];
594 sc
->setfont(pm
->curfont
);
596 k
= pm
->page
*pm
->max_chars
*pm
->lines
;
598 for (i
= j
= 0; j
< pm
->lines
&& k
< pm
->nchars
; k
++)
601 utf8
= utf8encode(pm
->kbd_buf
[k
], outline
);
604 sc
->getstringsize(outline
, &w
, NULL
);
605 sc
->putsxy(i
*pm
->font_w
+ (pm
->font_w
-w
) / 2,
606 j
*pm
->font_h
+ statusbar_size
, outline
);
608 if (++i
>= pm
->max_chars
)
620 struct keyboard_parameters
*pm
= ¶m
[l
];
621 struct screen
*sc
= &screens
[l
];
624 /* Clear text area one pixel above separator line so any overdraw
626 sc
->set_drawmode(DRMODE_SOLID
| DRMODE_INVERSEVID
);
627 sc
->fillrect(0, pm
->main_y
- pm
->keyboard_margin
- 1,
628 sc
->width
, pm
->font_h
+ 4);
629 sc
->set_drawmode(DRMODE_SOLID
);
631 sc
->hline(0, sc
->width
- 1, pm
->main_y
- pm
->keyboard_margin
);
633 /* write out the text */
634 sc
->setfont(pm
->curfont
);
636 pm
->curpos
= MIN(editpos
, pm
->max_chars_text
637 - MIN(len_utf8
- editpos
, 2));
638 pm
->leftpos
= editpos
- pm
->curpos
;
639 utf8
= text
+ utf8seek(text
, pm
->leftpos
);
643 while (*utf8
&& i
< pm
->max_chars_text
)
645 outline
[j
++] = *utf8
++;
647 if ((*utf8
& MASK
) != COMP
)
653 sc
->getstringsize(outline
, &w
, NULL
);
654 sc
->putsxy(i
*text_w
+ (text_w
-w
)/2, pm
->main_y
, outline
);
660 /* Draw nicer bitmap arrow if room, else settle for "<". */
661 if (text_w
>= 6 && pm
->font_h
>= 8)
663 screen_put_iconxy(sc
, (text_w
- 6) / 2,
664 pm
->main_y
+ (pm
->font_h
- 8) / 2 ,
665 Icon_Reverse_Cursor
);
670 sc
->getstringsize("<", &w
, NULL
);
671 sc
->putsxy(text_w
- w
, pm
->main_y
, "<");
675 if (len_utf8
- pm
->leftpos
> pm
->max_chars_text
)
677 /* Draw nicer bitmap arrow if room, else settle for ">". */
678 if (text_w
>= 6 && pm
->font_h
>= 8)
680 screen_put_iconxy(sc
, sc
->width
- text_w
+ (text_w
- 6) / 2,
681 pm
->main_y
+ (pm
->font_h
- 8) / 2,
686 sc
->putsxy(sc
->width
- text_w
, pm
->main_y
, ">");
691 i
= (pm
->curpos
+ 1) * text_w
;
694 sc
->vline(i
, pm
->main_y
, pm
->main_y
+ pm
->font_h
- 1);
696 if (pm
->hangul
) /* draw underbar */
697 sc
->hline(pm
->curpos
*text_w
, (pm
->curpos
+1)*text_w
,
698 pm
->main_y
+ pm
->font_h
- 1);
701 cur_blink
= !cur_blink
;
704 /* draw the button bar */
705 gui_buttonbar_set(&buttonbar
, "Shift", "OK", "Del");
706 gui_buttonbar_draw(&buttonbar
);
711 struct keyboard_parameters
*pm
= ¶m
[l
];
712 struct screen
*sc
= &screens
[l
];
714 sc
->set_drawmode(DRMODE_COMPLEMENT
);
717 sc
->fillrect(0, pm
->main_y
- pm
->keyboard_margin
+ 2,
718 sc
->width
, pm
->font_h
+ 2);
719 else /* highlight the key that has focus */
721 sc
->fillrect(pm
->font_w
*pm
->x
,
722 statusbar_size
+ pm
->font_h
*pm
->y
,
723 pm
->font_w
, pm
->font_h
);
724 sc
->set_drawmode(DRMODE_SOLID
);
727 gui_syncstatusbar_draw(&statusbars
, true);
731 button
= get_action(CONTEXT_KEYBOARD
, HZ
/2);
733 button_screen
= (get_action_statuscode(NULL
) & ACTION_REMOTE
) ? 1 : 0;
735 pm
= ¶m
[button_screen
];
736 sc
= &screens
[button_screen
];
738 #if defined KBD_MORSE_INPUT && !defined KBD_MODES
741 /* Remap some buttons for morse mode. */
742 if (button
== ACTION_KBD_LEFT
)
743 button
= ACTION_KBD_CURSOR_LEFT
;
744 if (button
== ACTION_KBD_RIGHT
)
745 button
= ACTION_KBD_CURSOR_RIGHT
;
751 case ACTION_KBD_ABORT
:
753 screens
[l
].setfont(FONT_UI
);
756 global_settings
.buttonbar
=buttonbar_config
;
761 case ACTION_KBD_PAGE_FLIP
:
764 #ifdef KBD_MORSE_INPUT
768 if (++pm
->page
>= pm
->pages
)
772 kbd_spellchar(pm
->kbd_buf
[k
]);
776 #ifdef KBD_MORSE_INPUT
777 case ACTION_KBD_MORSE_INPUT
:
778 morse_mode
= !morse_mode
;
782 struct keyboard_parameters
*pm
= ¶m
[l
];
783 struct screen
*sc
= &screens
[l
];
785 pm
->x
= pm
->y
= pm
->page
= 0;
789 pm
->old_main_y
= pm
->main_y
;
790 pm
->main_y
= sc
->height
- pm
->font_h
;
794 pm
->main_y
= pm
->old_main_y
;
797 /* FIXME: We should talk something like Morse mode.. */
799 #endif /* KBD_MORSE_INPUT */
801 case ACTION_KBD_RIGHT
:
803 #ifdef KBD_MORSE_INPUT
804 /* allow cursor change in non line edit morse mode */
805 if (pm
->line_edit
|| morse_mode
)
807 /* right doubles as cursor_right in line_edit */
813 if (editpos
< len_utf8
)
815 int c
= utf8seek(text
, ++editpos
);
816 kbd_spellchar(text
[c
]);
820 #endif /* KBD_MODES */
823 #ifdef KBD_MORSE_INPUT
827 if (++pm
->x
>= pm
->max_chars
)
829 #ifndef KBD_PAGE_FLIP
830 /* no dedicated flip key - flip page on wrap */
831 if (++pm
->page
>= pm
->pages
)
838 kbd_spellchar(pm
->kbd_buf
[k
]);
842 case ACTION_KBD_LEFT
:
844 #ifdef KBD_MORSE_INPUT
845 /* allow cursor change in non line edit morse mode */
846 if (pm
->line_edit
|| morse_mode
)
848 /* left doubles as cursor_left in line_edit */
856 int c
= utf8seek(text
, --editpos
);
857 kbd_spellchar(text
[c
]);
861 #endif /* KBD_MODES */
864 #ifdef KBD_MORSE_INPUT
870 #ifndef KBD_PAGE_FLIP
871 /* no dedicated flip key - flip page on wrap */
873 pm
->page
= pm
->pages
- 1;
875 pm
->x
= pm
->max_chars
- 1;
879 kbd_spellchar(pm
->kbd_buf
[k
]);
883 case ACTION_KBD_DOWN
:
884 #ifdef KBD_MORSE_INPUT
887 pm
->line_edit
= !pm
->line_edit
;
893 #endif /* KBD_MORSE_INPUT */
899 pm
->line_edit
= false;
903 if (++pm
->y
>= pm
->lines
)
905 pm
->line_edit
= true;
914 int k
= get_param_k(pm
);
915 kbd_spellchar(pm
->kbd_buf
[k
]);
920 #ifdef KBD_MORSE_INPUT
923 pm
->line_edit
= !pm
->line_edit
;
929 #endif /* KBD_MORSE_INPUT */
934 pm
->y
= pm
->lines
- 1;
935 pm
->line_edit
= false;
941 pm
->line_edit
= true;
943 pm
->y
= pm
->lines
- 1;
950 int k
= get_param_k(pm
);
951 kbd_spellchar(pm
->kbd_buf
[k
]);
955 case ACTION_KBD_DONE
:
956 /* accepts what was entered and continues */
960 #ifdef KBD_MORSE_INPUT
961 case ACTION_KBD_MORSE_SELECT
:
962 if (morse_mode
&& morse_reading
)
965 if ((current_tick
- morse_tick
) > HZ
/5)
970 #endif /* KBD_MORSE_INPUT */
972 case ACTION_KBD_SELECT
:
973 case ACTION_KBD_SELECT_REM
:
974 #ifdef KBD_MORSE_INPUT
976 if (morse_mode
&& !pm
->line_edit
)
981 morse_tick
= current_tick
;
985 morse_reading
= true;
990 #endif /* KBD_MORSE_INPUT */
992 /* inserts the selected char */
995 { /* select doubles as backspace in line_edit */
1000 else if (pm
->hvowel
)
1006 kbd_delchar(text
, &editpos
);
1011 ch
= hangul_join(pm
->hlead
, pm
->hvowel
, pm
->htail
);
1014 kbd_inschar(text
, buflen
, &editpos
, ch
);
1018 #endif /* KBD_MODES */
1020 /* find input char */
1021 int k
= get_param_k(pm
);
1022 ch
= (k
< pm
->nchars
) ? pm
->kbd_buf
[k
] : ' ';
1024 /* check for hangul input */
1025 if (ch
>= 0x3131 && ch
<= 0x3163)
1031 pm
->hlead
= pm
->hvowel
= pm
->htail
= 0;
1039 else if (!pm
->htail
)
1044 { /* previous hangul complete */
1045 /* check whether tail is actually lead of next char */
1046 tmp
= hangul_join(pm
->htail
, ch
, 0);
1050 tmp
= hangul_join(pm
->hlead
, pm
->hvowel
, 0);
1051 kbd_delchar(text
, &editpos
);
1052 kbd_inschar(text
, buflen
, &editpos
, tmp
);
1053 /* insert dummy char */
1054 kbd_inschar(text
, buflen
, &editpos
, ' ');
1055 pm
->hlead
= pm
->htail
;
1061 pm
->hvowel
= pm
->htail
= 0;
1066 /* combine into hangul */
1067 tmp
= hangul_join(pm
->hlead
, pm
->hvowel
, pm
->htail
);
1071 kbd_delchar(text
, &editpos
);
1076 pm
->hvowel
= pm
->htail
= 0;
1086 kbd_inschar(text
, buflen
, &editpos
, ch
);
1089 if (talk_menus_enabled()) /* voice UI? */
1090 talk_spell(text
, false);
1092 /* speak revised text */
1095 #if !defined (KBD_MODES) || defined (KBD_CURSOR_KEYS)
1096 case ACTION_KBD_BACKSPACE
:
1101 else if (pm
->hvowel
)
1107 kbd_delchar(text
, &editpos
);
1112 ch
= hangul_join(pm
->hlead
, pm
->hvowel
, pm
->htail
);
1115 kbd_inschar(text
, buflen
, &editpos
, ch
);
1118 if (talk_menus_enabled()) /* voice UI? */
1119 talk_spell(text
, false); /* speak revised text */
1122 case ACTION_KBD_CURSOR_RIGHT
:
1125 if (editpos
< len_utf8
)
1127 int c
= utf8seek(text
, ++editpos
);
1128 kbd_spellchar(text
[c
]);
1132 case ACTION_KBD_CURSOR_LEFT
:
1137 int c
= utf8seek(text
, --editpos
);
1138 kbd_spellchar(text
[c
]);
1141 #endif /* !defined (KBD_MODES) || defined (KBD_CURSOR_KEYS) */
1144 gui_syncstatusbar_draw(&statusbars
, false);
1145 #ifdef KBD_MORSE_INPUT
1149 logf("Morse: 0x%02x", morse_code
);
1150 morse_reading
= false;
1152 for (j
= 0; morse_alphabets
[j
] != '\0'; j
++)
1154 if (morse_codes
[j
] == morse_code
)
1158 if (morse_alphabets
[j
] == '\0')
1160 logf("Morse code not found");
1164 /* turn off hangul input */
1166 param
[l
].hangul
= false;
1167 kbd_inschar(text
, buflen
, &editpos
, morse_alphabets
[j
]);
1169 if (talk_menus_enabled()) /* voice UI? */
1170 talk_spell(text
, false); /* speak revised text */
1172 #endif /* KBD_MORSE_INPUT */
1176 if (default_event_handler(button
) == SYS_USB_CONNECTED
)
1179 screens
[l
].setfont(FONT_SYSFIXED
);
1185 if (button
!= BUTTON_NONE
)
1191 #ifdef HAS_BUTTONBAR
1192 global_settings
.buttonbar
= buttonbar_config
;
1196 screens
[l
].setfont(FONT_UI
);