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.c639
1 files changed, 448 insertions, 191 deletions
diff --git a/apps/recorder/keyboard.c b/apps/recorder/keyboard.c
index cb982e38e6..47deb3a5b9 100644
--- a/apps/recorder/keyboard.c
+++ b/apps/recorder/keyboard.c
@@ -33,19 +33,28 @@
33#include "rbunicode.h" 33#include "rbunicode.h"
34#include "buttonbar.h" 34#include "buttonbar.h"
35#include "logf.h" 35#include "logf.h"
36#include "icons.h"
37#include "file.h"
38#include "hangul.h"
36 39
37#define KEYBOARD_MARGIN 3 40#ifndef O_BINARY
38 41#define O_BINARY 0
39#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 96) 42#endif
40#define KEYBOARD_LINES 8
41#define KEYBOARD_PAGES 1
42 43
44#if CONFIG_KEYPAD == RECORDER_PAD
45#define BUTTONBAR_HEIGHT 8
43#else 46#else
44#define KEYBOARD_LINES 4 47#define BUTTONBAR_HEIGHT 0
45#define KEYBOARD_PAGES 3 48#endif
46 49
50#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 96)
51#define DEFAULT_LINES 8
52#else
53#define DEFAULT_LINES 4
47#endif 54#endif
48 55
56#define DEFAULT_MARGIN 6
57#define KBD_BUF_SIZE 500
49 58
50#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 59#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
51 (CONFIG_KEYPAD == IRIVER_H300_PAD) 60 (CONFIG_KEYPAD == IRIVER_H300_PAD)
@@ -61,7 +70,7 @@
61#define KBD_RIGHT BUTTON_RIGHT 70#define KBD_RIGHT BUTTON_RIGHT
62#define KBD_UP BUTTON_UP 71#define KBD_UP BUTTON_UP
63#define KBD_DOWN BUTTON_DOWN 72#define KBD_DOWN BUTTON_DOWN
64#define HAVE_MORSE_INPUT 73#define KBD_MORSE_INPUT (BUTTON_ON | BUTTON_MODE)
65 74
66#elif CONFIG_KEYPAD == RECORDER_PAD 75#elif CONFIG_KEYPAD == RECORDER_PAD
67#define KBD_CURSOR_RIGHT (BUTTON_ON | BUTTON_RIGHT) 76#define KBD_CURSOR_RIGHT (BUTTON_ON | BUTTON_RIGHT)
@@ -172,39 +181,39 @@
172 181
173#endif 182#endif
174 183
175#if KEYBOARD_PAGES == 1 184#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 96)
176static const char * const kbdpages[KEYBOARD_PAGES][KEYBOARD_LINES] = { 185static const unsigned char * default_kbd =
177 { "ABCDEFG abcdefg !?\" @#$%+'", 186 "ABCDEFG abcdefg !?\" @#$%+'\n"
178 "HIJKLMN hijklmn 789 &_()-`", 187 "HIJKLMN hijklmn 789 &_()-`\n"
179 "OPQRSTU opqrstu 456 §|{}/<", 188 "OPQRSTU opqrstu 456 §|{}/<\n"
180 "VWXYZ., vwxyz.,0123 ~=[]*>", 189 "VWXYZ., vwxyz.,0123 ~=[]*>\n"
181 "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË ¢£¤¥¦§©®", 190 "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË ¢£¤¥¦§©®\n"
182 "àáâãäåæ ìíîï èéêë «»°ºª¹²³", 191 "àáâãäåæ ìíîï èéêë «»°ºª¹²³\n"
183 "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ ¯±×÷¡¿µ·", 192 "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ ¯±×÷¡¿µ·\n"
184 "òóôõöø çðþýÿ ùúûü ¼½¾¬¶¨ " }, 193 "òóôõöø çðþýÿ ùúûü ¼½¾¬¶¨";
185};
186
187#else 194#else
188static const char * const kbdpages[KEYBOARD_PAGES][KEYBOARD_LINES] = { 195static const unsigned char * default_kbd =
189 { "ABCDEFG !?\" @#$%+'", 196 "ABCDEFG !?\" @#$%+'\n"
190 "HIJKLMN 789 &_()-`", 197 "HIJKLMN 789 &_()-`\n"
191 "OPQRSTU 456 §|{}/<", 198 "OPQRSTU 456 §|{}/<\n"
192 "VWXYZ.,0123 ~=[]*>" }, 199 "VWXYZ.,0123 ~=[]*>\n"
193 200
194 { "abcdefg ¢£¤¥¦§©®¬", 201 "abcdefg ¢£¤¥¦§©®¬\n"
195 "hijklmn «»°ºª¹²³¶", 202 "hijklmn «»°ºª¹²³¶\n"
196 "opqrstu ¯±×÷¡¿µ·¨", 203 "opqrstu ¯±×÷¡¿µ·¨\n"
197 "vwxyz., ¼½¾ " }, 204 "vwxyz., ¼½¾ \n"
198
199 { "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË",
200 "àáâãäåæ ìíîï èéêë",
201 "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ",
202 "òóôõöø çðþýÿ ùúûü" },
203};
204 205
206 "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË\n"
207 "àáâãäåæ ìíîï èéêë\n"
208 "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ\n"
209 "òóôõöø çðþýÿ ùúûü";
205#endif 210#endif
206 211
207#ifdef HAVE_MORSE_INPUT 212static unsigned short kbd_buf[KBD_BUF_SIZE];
213static bool kbd_loaded = false;
214static int nchars = 0;
215
216#ifdef KBD_MORSE_INPUT
208/* FIXME: We should put this to a configuration file. */ 217/* FIXME: We should put this to a configuration file. */
209static const char *morse_alphabets = 218static const char *morse_alphabets =
210 "abcdefghijklmnopqrstuvwxyz1234567890,.?-@ "; 219 "abcdefghijklmnopqrstuvwxyz1234567890,.?-@ ";
@@ -217,37 +226,139 @@ static const unsigned char morse_codes[] = {
217static bool morse_mode = false; 226static bool morse_mode = false;
218#endif 227#endif
219 228
229/* Loads a custom keyboard into memory
230 call with NULL to reset keyboard */
231int load_kbd(unsigned char* filename)
232{
233 int fd, count;
234 int i = 0;
235 unsigned char buf[4];
236
237 if (filename == NULL) {
238 kbd_loaded = false;
239 return 0;
240 }
241
242 fd = open(filename, O_RDONLY|O_BINARY);
243 if (fd < 0)
244 return 1;
245
246 while (read(fd, buf, 1) == 1 && i < KBD_BUF_SIZE) {
247 /* check how many bytes to read */
248 if (buf[0] < 0x80) {
249 count = 0;
250 } else if (buf[0] < 0xe0) {
251 count = 1;
252 } else if (buf[0] < 0xf0) {
253 count = 2;
254 } else if (buf[0] < 0xf5) {
255 count = 3;
256 } else {
257 /* Invalid size. */
258 continue;
259 }
260
261 if (read(fd, &buf[1], count) != count) {
262 close(fd);
263 kbd_loaded = false;
264 return 1;
265 }
266
267 utf8decode(buf, &kbd_buf[i]);
268 if (kbd_buf[i] != 0xFEFF && kbd_buf[i] != '\n' &&
269 kbd_buf[i] != '\r') /*skip BOM & newlines */
270 i++;
271 }
272
273 close(fd);
274 kbd_loaded = true;
275 nchars = i;
276 return 0;
277
278}
279
220/* helper function to spell a char if voice UI is enabled */ 280/* helper function to spell a char if voice UI is enabled */
221static void kbd_spellchar(char c) 281static void kbd_spellchar(unsigned short c)
222{ 282{
223 static char spell_char[2] = "\0\0"; /* store char to pass to talk_spell */ 283 static char spell_char[2] = "\0\0"; /* store char to pass to talk_spell */
224 284
225 if (global_settings.talk_menu) /* voice UI? */ 285 if (global_settings.talk_menu && c < 128) /* voice UI? */
226 { 286 {
227 spell_char[0] = c; 287 spell_char[0] = (char)c;
228 talk_spell(spell_char, false); 288 talk_spell(spell_char, false);
229 } 289 }
230} 290}
231 291
292void kbd_inschar(unsigned char* text, int buflen, int* editpos, unsigned short ch)
293{
294 int i, j, k, len;
295 unsigned char tmp[4];
296 unsigned char* utf8;
297
298 len = strlen(text);
299 k = utf8length(text);
300 utf8 = utf8encode(ch, tmp);
301 j = (long)utf8 - (long)tmp;
302
303 if (len + j < buflen)
304 {
305 for (i = len+j; k >= *editpos; i--) {
306 text[i] = text[i-j];
307 if ((text[i] & MASK) != COMP)
308 k--;
309 }
310 while (j--)
311 text[i--] = tmp[j];
312 (*editpos)++;
313 }
314 return;
315}
316
317void kbd_delchar(unsigned char* text, int* editpos)
318{
319 int i = 0;
320 unsigned char* utf8;
321
322 if (*editpos > 0)
323 {
324 utf8 = text + utf8seek(text, *editpos);
325 do {
326 i++;
327 utf8--;
328 } while ((*utf8 & MASK) == COMP);
329 while (utf8[i]) {
330 *utf8 = utf8[i];
331 utf8++;
332 }
333 *utf8 = 0;
334 (*editpos)--;
335 }
336
337 return;
338}
339
232int kbd_input(char* text, int buflen) 340int kbd_input(char* text, int buflen)
233{ 341{
234 bool done = false; 342 bool done = false;
235#if defined(KBD_PAGE_FLIP) || (KEYBOARD_PAGES > 1)
236 int page = 0; 343 int page = 0;
237#endif 344 int font_w = 0, font_h = 0, text_w = 0;
238 int font_w = 0, font_h = 0, i, j; 345 int i = 0, j, k, w;
239 int x = 0, y = 0; 346 int x = 0, y = 0;
240 int main_x, main_y, max_chars; 347 int main_x, main_y, max_chars, max_chars_text;
241 int status_y1, status_y2; 348 int len_utf8, c = 0;
242 int len, len_utf8, c = 0;
243 int editpos, curpos, leftpos; 349 int editpos, curpos, leftpos;
350 int lines, pages, keyboard_margin;
351 int curfont;
352 int statusbar_size = global_settings.statusbar ? STATUSBAR_HEIGHT : 0;
353 unsigned short ch, tmp, hlead = 0, hvowel = 0, htail = 0;
354 bool hangul = false;
244 bool redraw = true; 355 bool redraw = true;
245 unsigned char *utf8; 356 unsigned char *utf8;
246 const char * const *line; 357 const unsigned char *p;
247#ifdef HAVE_MORSE_INPUT 358#ifdef KBD_MORSE_INPUT
248 bool morse_reading = false; 359 bool morse_reading = false;
249 unsigned char morse_code = 0; 360 unsigned char morse_code = 0;
250 int morse_tick = 0, morse_len; 361 int morse_tick = 0, morse_len, old_main_y;
251 char buf[2]; 362 char buf[2];
252#endif 363#endif
253#ifdef KBD_MODES 364#ifdef KBD_MODES
@@ -255,7 +366,7 @@ int kbd_input(char* text, int buflen)
255#endif 366#endif
256 367
257 char outline[256]; 368 char outline[256];
258 struct font* font = font_get(FONT_SYSFIXED); 369 struct font* font;
259 int button, lastbutton = 0; 370 int button, lastbutton = 0;
260#ifdef HAS_BUTTONBAR 371#ifdef HAS_BUTTONBAR
261 struct gui_buttonbar buttonbar; 372 struct gui_buttonbar buttonbar;
@@ -264,44 +375,103 @@ int kbd_input(char* text, int buflen)
264 gui_buttonbar_init(&buttonbar); 375 gui_buttonbar_init(&buttonbar);
265 gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) ); 376 gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) );
266#endif 377#endif
267 lcd_setfont(FONT_SYSFIXED); 378
268 font_w = font->maxwidth; 379 if (!kbd_loaded) {
380 curfont = FONT_SYSFIXED;
381 p = default_kbd;
382 while (*p != 0) {
383 p = utf8decode(p, &kbd_buf[i]);
384 if (kbd_buf[i] == '\n')
385 while (i % (LCD_WIDTH/6))
386 kbd_buf[i++] = ' ';
387 else
388 i++;
389 }
390 nchars = i;
391 }
392 else
393 curfont = FONT_UI;
394
395 font = font_get(curfont);
269 font_h = font->height; 396 font_h = font->height;
270 397
271#ifdef HAVE_MORSE_INPUT 398 /* check if FONT_UI fits the screen */
399 if (2*font_h+3+statusbar_size + BUTTONBAR_HEIGHT > LCD_HEIGHT) {
400 font = font_get(FONT_SYSFIXED);
401 font_h = font->height;
402 curfont = FONT_SYSFIXED;
403 }
404
405 lcd_setfont(curfont);
406
407 /* find max width of keyboard glyphs */
408 for (i=0; i<nchars; i++) {
409 w = font_get_width(font, kbd_buf[i]);
410 if (w > font_w)
411 font_w = w;
412 }
413
414 /* find max width for text string */
415 utf8 = text;
416 text_w = font_w;
417 while (*utf8) {
418 utf8 = (unsigned char*)utf8decode(utf8, &ch);
419 w = font_get_width(font, ch);
420 if (w > text_w)
421 text_w = w;
422 }
423 max_chars_text = LCD_WIDTH / text_w - 2;
424
425 /* calculate keyboard grid size */
426 max_chars = LCD_WIDTH / font_w;
427 if (!kbd_loaded) {
428 lines = DEFAULT_LINES;
429 keyboard_margin = DEFAULT_MARGIN;
430 } else {
431 lines = (LCD_HEIGHT - BUTTONBAR_HEIGHT - statusbar_size) / font_h - 1;
432 keyboard_margin = LCD_HEIGHT - BUTTONBAR_HEIGHT - statusbar_size - (lines+1)*font_h;
433 if (keyboard_margin < 3) {
434 lines--;
435 keyboard_margin += font_h;
436 }
437 if (keyboard_margin > 6)
438 keyboard_margin = 6;
439 }
440
441 pages = (nchars + (lines*max_chars-1))/(lines*max_chars);
442 if (pages == 1 && kbd_loaded)
443 lines = (nchars + max_chars - 1) / max_chars;
444
445 main_y = font_h*lines + keyboard_margin + statusbar_size;
446 main_x = 0;
447 keyboard_margin -= keyboard_margin/2;
448
449#ifdef KBD_MORSE_INPUT
450 old_main_y = main_y;
272 if (morse_mode) 451 if (morse_mode)
273 main_y = LCD_HEIGHT - font_h; 452 main_y = LCD_HEIGHT - font_h;
274 else
275#endif 453#endif
276 main_y = (KEYBOARD_LINES + 1) * font_h + (2*KEYBOARD_MARGIN);
277 main_x = 0;
278 status_y1 = LCD_HEIGHT - font_h;
279 status_y2 = LCD_HEIGHT;
280 454
281 editpos = utf8length(text); 455 editpos = utf8length(text);
282
283 max_chars = LCD_WIDTH / font_w - 2; /* leave room for < and > */
284 line = kbdpages[0];
285 456
286 if (global_settings.talk_menu) /* voice UI? */ 457 if (global_settings.talk_menu) /* voice UI? */
287 talk_spell(text, true); /* spell initial text */ 458 talk_spell(text, true); /* spell initial text */
288 459
289 while(!done) 460 while(!done)
290 { 461 {
291 len = strlen(text);
292 len_utf8 = utf8length(text); 462 len_utf8 = utf8length(text);
293 463
294 if(redraw) 464 if(redraw)
295 { 465 {
296 lcd_clear_display(); 466 lcd_clear_display();
297 467
298 lcd_setfont(FONT_SYSFIXED); 468#ifdef KBD_MORSE_INPUT
299
300#ifdef HAVE_MORSE_INPUT
301 if (morse_mode) 469 if (morse_mode)
302 { 470 {
471 lcd_setfont(FONT_SYSFIXED); /* Draw morse code screen with sysfont */
472 w = 6; /* sysfixed font width */
303 x = 0; 473 x = 0;
304 y = font_h; 474 y = statusbar_size;
305 buf[1] = '\0'; 475 buf[1] = '\0';
306 /* Draw morse code table with code descriptions. */ 476 /* Draw morse code table with code descriptions. */
307 for (i = 0; morse_alphabets[i] != '\0'; i++) 477 for (i = 0; morse_alphabets[i] != '\0'; i++)
@@ -312,7 +482,7 @@ int kbd_input(char* text, int buflen)
312 for (j = 0; (morse_codes[i] >> j) > 0x01; j++) ; 482 for (j = 0; (morse_codes[i] >> j) > 0x01; j++) ;
313 morse_len = j; 483 morse_len = j;
314 484
315 x += font_w + 3; 485 x += w + 3;
316 for (j = 0; j < morse_len; j++) 486 for (j = 0; j < morse_len; j++)
317 { 487 {
318 if ((morse_codes[i] >> (morse_len-j-1)) & 0x01) 488 if ((morse_codes[i] >> (morse_len-j-1)) & 0x01)
@@ -321,11 +491,11 @@ int kbd_input(char* text, int buflen)
321 lcd_fillrect(x + j*4, y + 3, 1, 2); 491 lcd_fillrect(x + j*4, y + 3, 1, 2);
322 } 492 }
323 493
324 x += font_w * 5 - 3; 494 x += w * 5 - 3;
325 if (x >= LCD_WIDTH - (font_w*6)) 495 if (x >= LCD_WIDTH - (w*6))
326 { 496 {
327 x = 0; 497 x = 0;
328 y += font_h; 498 y += 8; /* sysfixed font height */
329 } 499 }
330 } 500 }
331 } 501 }
@@ -333,50 +503,67 @@ int kbd_input(char* text, int buflen)
333#endif 503#endif
334 { 504 {
335 /* draw page */ 505 /* draw page */
336 for (i=0; i < KEYBOARD_LINES; i++) 506 lcd_setfont(curfont);
337 lcd_putsxy(0, 8+i * font_h, line[i]); 507 k = page*max_chars*lines;
338 508 for (i=j=0; j < lines && k < nchars; k++) {
509 utf8 = utf8encode(kbd_buf[k], outline);
510 *utf8 = 0;
511 lcd_getstringsize(outline, &w, NULL);
512 lcd_putsxy(i*font_w + (font_w-w)/2, j*font_h + statusbar_size, outline);
513 if (++i == max_chars) {
514 i = 0;
515 j++;
516 }
517 }
339 } 518 }
340 519
341 /* separator */ 520 /* separator */
342 lcd_hline(0, LCD_WIDTH - 1, main_y - KEYBOARD_MARGIN); 521 lcd_hline(0, LCD_WIDTH - 1, main_y - keyboard_margin);
343 522
344 /* write out the text */ 523 /* write out the text */
345 curpos = MIN(editpos, max_chars - MIN(len_utf8 - editpos, 2)); 524 lcd_setfont(curfont);
525 i=j=0;
526 curpos = MIN(editpos, max_chars_text - MIN(len_utf8 - editpos, 2));
346 leftpos = editpos - curpos; 527 leftpos = editpos - curpos;
347 utf8 = text + utf8seek(text, leftpos); 528 utf8 = text + utf8seek(text, leftpos);
348 i=j=0; 529
349 while (*utf8 && i < max_chars) { 530 while (*utf8 && i < max_chars_text) {
350 outline[j++] = *utf8++; 531 outline[j++] = *utf8++;
351 if ((*utf8 & MASK) != COMP) 532 if ((*utf8 & MASK) != COMP) {
533 outline[j] = 0;
534 j=0;
352 i++; 535 i++;
536 lcd_getstringsize(outline, &w, NULL);
537 lcd_putsxy(i*text_w + (text_w-w)/2, main_y, outline);
538 }
539 }
540
541 if (leftpos) {
542 lcd_getstringsize("<", &w, NULL);
543 lcd_putsxy(text_w - w, main_y, "<");
353 } 544 }
354 outline[j] = 0; 545 if (len_utf8 - leftpos > max_chars_text)
355 546 lcd_putsxy(LCD_WIDTH - text_w, main_y, ">");
356 lcd_putsxy(font_w, main_y, outline); 547
357
358 if (leftpos)
359 lcd_putsxy(0, main_y, "<");
360 if (len_utf8 - leftpos > max_chars)
361 lcd_putsxy(LCD_WIDTH - font_w, main_y, ">");
362
363 /* cursor */ 548 /* cursor */
364 i = (curpos + 1) * font_w; 549 i = (curpos + 1) * text_w;
365 lcd_vline(i, main_y, main_y + font_h); 550 lcd_vline(i, main_y, main_y + font_h);
366 551 if (hangul) /* draw underbar */
552 lcd_hline(curpos*text_w, (curpos+1)*text_w, main_y+font_h-1);
553
367#ifdef HAS_BUTTONBAR 554#ifdef HAS_BUTTONBAR
368 /* draw the status bar */ 555 /* draw the status bar */
369 gui_buttonbar_set(&buttonbar, "Shift", "OK", "Del"); 556 gui_buttonbar_set(&buttonbar, "Shift", "OK", "Del");
370 gui_buttonbar_draw(&buttonbar); 557 gui_buttonbar_draw(&buttonbar);
371#endif 558#endif
372 559
373#ifdef KBD_MODES 560#ifdef KBD_MODES
374 if (!line_edit) 561 if (!line_edit)
375#endif 562#endif
376 { 563 {
377 /* highlight the key that has focus */ 564 /* highlight the key that has focus */
378 lcd_set_drawmode(DRMODE_COMPLEMENT); 565 lcd_set_drawmode(DRMODE_COMPLEMENT);
379 lcd_fillrect(font_w * x, 8 + font_h * y, font_w, font_h); 566 lcd_fillrect(font_w * x, statusbar_size + font_h * y, font_w, font_h);
380 lcd_set_drawmode(DRMODE_SOLID); 567 lcd_set_drawmode(DRMODE_SOLID);
381 } 568 }
382 569
@@ -388,7 +575,7 @@ int kbd_input(char* text, int buflen)
388 redraw = true; 575 redraw = true;
389 576
390 button = button_get_w_tmo(HZ/2); 577 button = button_get_w_tmo(HZ/2);
391#ifdef HAVE_MORSE_INPUT 578#ifdef KBD_MORSE_INPUT
392 if (morse_mode) 579 if (morse_mode)
393 { 580 {
394 /* Remap some buttons for morse mode. */ 581 /* Remap some buttons for morse mode. */
@@ -411,40 +598,43 @@ int kbd_input(char* text, int buflen)
411 598
412#if defined(KBD_PAGE_FLIP) 599#if defined(KBD_PAGE_FLIP)
413 case KBD_PAGE_FLIP: 600 case KBD_PAGE_FLIP:
414#ifdef HAVE_MORSE_INPUT 601#ifdef KBD_MORSE_INPUT
415 if (morse_mode) 602 if (morse_mode)
416 { 603 break;
417 main_y = (KEYBOARD_LINES + 1) * font_h + (2*KEYBOARD_MARGIN);
418 morse_mode = false;
419 x = y = 0;
420 }
421 else
422#endif 604#endif
423 if (++page == KEYBOARD_PAGES) 605 if (++page == pages)
424 {
425 page = 0; 606 page = 0;
426#ifdef HAVE_MORSE_INPUT 607 k = (page*lines + y)*max_chars + x;
427 main_y = LCD_HEIGHT - font_h; 608 kbd_spellchar(kbd_buf[k]);
428 morse_mode = true;
429 /* FIXME: We should talk something like Morse mode.. */
430 break ;
431#endif
432 }
433 line = kbdpages[page];
434 c = utf8seek(line[y], x);
435 kbd_spellchar(line[y][c]);
436 break; 609 break;
437#endif 610#endif
438 611
612#ifdef KBD_MORSE_INPUT
613 case KBD_MORSE_INPUT:
614 morse_mode = !morse_mode;
615 x = y = page = 0;
616 if (morse_mode) {
617 old_main_y = main_y;
618 main_y = LCD_HEIGHT - font_h;
619 } else
620 main_y = old_main_y;
621 /* FIXME: We should talk something like Morse mode.. */
622 break;
623#endif
439 case KBD_RIGHT: 624 case KBD_RIGHT:
440 case KBD_RIGHT | BUTTON_REPEAT: 625 case KBD_RIGHT | BUTTON_REPEAT:
441#ifdef HAVE_MORSE_INPUT 626#ifdef KBD_MORSE_INPUT
442 if (morse_mode) 627 if (morse_mode)
443 break; 628 break;
444#endif 629#endif
445#ifdef KBD_MODES 630#ifdef KBD_MODES
446 if (line_edit) /* right doubles as cursor_right in line_edit */ 631 if (line_edit) /* right doubles as cursor_right in line_edit */
447 { 632 {
633 if (hangul) {
634 hangul = false;
635 hlead=hvowel=htail=0;
636 break;
637 }
448 if (editpos < len_utf8) 638 if (editpos < len_utf8)
449 { 639 {
450 editpos++; 640 editpos++;
@@ -455,32 +645,33 @@ int kbd_input(char* text, int buflen)
455 else 645 else
456#endif 646#endif
457 { 647 {
458 if (x < (int)utf8length(line[y]) - 1) 648 if (++x == max_chars) {
459 x++;
460 else
461 {
462 x = 0; 649 x = 0;
463#if !defined(KBD_PAGE_FLIP) && KEYBOARD_PAGES > 1 650#if !defined(KBD_PAGE_FLIP)
464 /* no dedicated flip key - flip page on wrap */ 651 /* no dedicated flip key - flip page on wrap */
465 if (++page == KEYBOARD_PAGES) 652 if (++page == pages)
466 page = 0; 653 page = 0;
467 line = kbdpages[page];
468#endif 654#endif
469 } 655 }
470 c = utf8seek(line[y], x); 656 k = (page*lines + y)*max_chars + x;
471 kbd_spellchar(line[y][c]); 657 kbd_spellchar(kbd_buf[k]);
472 } 658 }
473 break; 659 break;
474 660
475 case KBD_LEFT: 661 case KBD_LEFT:
476 case KBD_LEFT | BUTTON_REPEAT: 662 case KBD_LEFT | BUTTON_REPEAT:
477#ifdef HAVE_MORSE_INPUT 663#ifdef KBD_MORSE_INPUT
478 if (morse_mode) 664 if (morse_mode)
479 break; 665 break;
480#endif 666#endif
481#ifdef KBD_MODES 667#ifdef KBD_MODES
482 if (line_edit) /* left doubles as cursor_left in line_edit */ 668 if (line_edit) /* left doubles as cursor_left in line_edit */
483 { 669 {
670 if (hangul) {
671 hangul = false;
672 hlead=hvowel=htail=0;
673 break;
674 }
484 if (editpos) 675 if (editpos)
485 { 676 {
486 editpos--; 677 editpos--;
@@ -490,27 +681,26 @@ int kbd_input(char* text, int buflen)
490 } 681 }
491 else 682 else
492#endif 683#endif
493 { 684 {
494 if (x) 685 if (x)
495 x--; 686 x--;
496 else 687 else
497 { 688 {
498#if !defined(KBD_PAGE_FLIP) && KEYBOARD_PAGES > 1 689#if !defined(KBD_PAGE_FLIP)
499 /* no dedicated flip key - flip page on wrap */ 690 /* no dedicated flip key - flip page on wrap */
500 if (--page < 0) 691 if (--page < 0)
501 page = (KEYBOARD_PAGES-1); 692 page = (pages-1);
502 line = kbdpages[page];
503#endif 693#endif
504 x = utf8length(line[y]) - 1; 694 x = max_chars - 1;
505 } 695 }
506 c = utf8seek(line[y], x); 696 k = (page*lines + y)*max_chars + x;
507 kbd_spellchar(line[y][c]); 697 kbd_spellchar(kbd_buf[k]);
508 } 698 }
509 break; 699 break;
510 700
511 case KBD_DOWN: 701 case KBD_DOWN:
512 case KBD_DOWN | BUTTON_REPEAT: 702 case KBD_DOWN | BUTTON_REPEAT:
513#ifdef HAVE_MORSE_INPUT 703#ifdef KBD_MORSE_INPUT
514 if (morse_mode) 704 if (morse_mode)
515 break; 705 break;
516#endif 706#endif
@@ -523,7 +713,7 @@ int kbd_input(char* text, int buflen)
523 else 713 else
524 { 714 {
525#endif 715#endif
526 if (y < KEYBOARD_LINES - 1) 716 if (y < lines - 1)
527 y++; 717 y++;
528 else 718 else
529#ifndef KBD_MODES 719#ifndef KBD_MODES
@@ -533,20 +723,22 @@ int kbd_input(char* text, int buflen)
533 } 723 }
534 if (!line_edit) 724 if (!line_edit)
535#endif 725#endif
536 c = utf8seek(line[y], x); 726 {
537 kbd_spellchar(line[y][c]); 727 k = (page*lines + y)*max_chars + x;
728 kbd_spellchar(kbd_buf[k]);
729 }
538 break; 730 break;
539 731
540 case KBD_UP: 732 case KBD_UP:
541 case KBD_UP | BUTTON_REPEAT: 733 case KBD_UP | BUTTON_REPEAT:
542#ifdef HAVE_MORSE_INPUT 734#ifdef KBD_MORSE_INPUT
543 if (morse_mode) 735 if (morse_mode)
544 break; 736 break;
545#endif 737#endif
546#ifdef KBD_MODES 738#ifdef KBD_MODES
547 if (line_edit) 739 if (line_edit)
548 { 740 {
549 y = KEYBOARD_LINES - 1; 741 y = lines - 1;
550 line_edit = false; 742 line_edit = false;
551 } 743 }
552 else 744 else
@@ -556,14 +748,16 @@ int kbd_input(char* text, int buflen)
556 y--; 748 y--;
557 else 749 else
558#ifndef KBD_MODES 750#ifndef KBD_MODES
559 y = KEYBOARD_LINES - 1; 751 y = lines - 1;
560#else 752#else
561 line_edit = true; 753 line_edit = true;
562 } 754 }
563 if (!line_edit) 755 if (!line_edit)
564#endif 756#endif
565 c = utf8seek(line[y], x); 757 {
566 kbd_spellchar(line[y][c]); 758 k = (page*lines + y)*max_chars + x;
759 kbd_spellchar(kbd_buf[k]);
760 }
567 break; 761 break;
568 762
569 case KBD_DONE: 763 case KBD_DONE:
@@ -575,7 +769,7 @@ int kbd_input(char* text, int buflen)
575 done = true; 769 done = true;
576 break; 770 break;
577 771
578#ifdef HAVE_MORSE_INPUT 772#ifdef KBD_MORSE_INPUT
579 case KBD_SELECT | BUTTON_REL: 773 case KBD_SELECT | BUTTON_REL:
580 if (morse_mode && morse_reading) 774 if (morse_mode && morse_reading)
581 { 775 {
@@ -588,7 +782,7 @@ int kbd_input(char* text, int buflen)
588#endif 782#endif
589 783
590 case KBD_SELECT: 784 case KBD_SELECT:
591#ifdef HAVE_MORSE_INPUT 785#ifdef KBD_MORSE_INPUT
592 if (morse_mode) 786 if (morse_mode)
593 { 787 {
594 morse_tick = current_tick; 788 morse_tick = current_tick;
@@ -607,44 +801,94 @@ int kbd_input(char* text, int buflen)
607 break; 801 break;
608#endif 802#endif
609#ifdef KBD_MODES 803#ifdef KBD_MODES
610 if (line_edit) /* select doubles as backspace in line_edit */ 804 if (line_edit) { /* select doubles as backspace in line_edit */
611 { 805 if (hangul) {
612 if (editpos > 0) 806 if (htail != 0)
613 { 807 htail = 0;
614 utf8 = text + utf8seek(text, editpos); 808 else if (hvowel != 0)
615 i = 0; 809 hvowel = 0;
616 do { 810 else {
617 i++; 811 hlead = 0;
618 utf8--; 812 hangul = false;
619 } while ((*utf8 & MASK) == COMP);
620 while (utf8[i]) {
621 *utf8 = utf8[i];
622 utf8++;
623 } 813 }
624 *utf8 = 0; 814 }
625 editpos--; 815 kbd_delchar(text, &editpos);
816 if (hangul) {
817 if (hvowel != 0)
818 ch = hangul_join(hlead, hvowel, htail);
819 else
820 ch = hlead;
821 kbd_inschar(text, buflen, &editpos, ch);
626 } 822 }
627 } 823 }
628 else 824 else
629#endif 825#endif
630 { 826 {
631 const unsigned char *inschar = line[y] + utf8seek(line[y], x); 827 /* find input char */
632 j = 0; 828 k = (page*lines + y)*max_chars + x;
633 do { 829 if (k < nchars)
634 j++; 830 ch = kbd_buf[k];
635 } while ((inschar[j] & MASK) == COMP); 831 else
636 if (len + j < buflen) 832 ch = ' ';
637 { 833
638 int k = len_utf8; 834 /* check for hangul input */
639 for (i = len+j; k >= editpos; i--) { 835 if (ch >= 0x3131 && ch <= 0x3163) {
640 text[i] = text[i-j]; 836 if (hangul) {
641 if ((text[i] & MASK) != COMP) 837 if ((hvowel == 0) && (jamo_table[ch-0x3131][1] != 0)) {
642 k--; 838 hvowel = ch;
839 ch = hangul_join(hlead, hvowel, htail);
840 kbd_delchar(text, &editpos);
841 }
842 else if ((htail == 0) && (hvowel != 0) && (jamo_table[ch-0x3131][2] != 0)) {
843 htail = ch;
844 /* combine into hangul */
845 ch = hangul_join(hlead, hvowel, htail);
846 kbd_delchar(text, &editpos);
847 }
848 else { /* invalid following char or hangul complete */
849 /* check whether tail is actually lead of next char */
850 if (htail != 0 && (jamo_table[htail-0x3131][0] != 0)
851 && (jamo_table[ch-0x3131][1] != 0)) {
852 tmp = hangul_join(hlead, hvowel, 0);
853 kbd_delchar(text, &editpos);
854 kbd_inschar(text, buflen, &editpos, tmp);
855 hlead = htail;
856 hvowel = ch;
857 htail = 0;
858 ch = hangul_join(hlead, hvowel, htail);
859 }
860 else if (hlead != 0 && hvowel != 0) {
861 /* finish previous hangul */
862 tmp = hangul_join(hlead, hvowel, htail);
863 kbd_delchar(text, &editpos);
864 kbd_inschar(text, buflen, &editpos, tmp);
865 hlead=hvowel=htail=0;
866 /* start of new hangul? */
867 if (jamo_table[ch-0x3131][0] != 0) {
868 hlead = ch;
869 }
870 else
871 hangul = false;
872 }
873 }
643 } 874 }
644 while (j--) 875 else if (jamo_table[ch-0x3131][0] != 0) {
645 text[i--] = inschar[j]; 876 hlead = ch;
646 editpos++; 877 hangul = true;
878 }
879 }
880 else if (hangul) {
881 /* finish previous hangul */
882 if (hlead != 0 && hvowel != 0) {
883 tmp = hangul_join(hlead, hvowel, htail);
884 kbd_delchar(text, &editpos);
885 kbd_inschar(text, buflen, &editpos, tmp);
886 }
887 hangul = false;
888 hlead=hvowel=htail=0;
647 } 889 }
890 /* insert char */
891 kbd_inschar(text, buflen, &editpos, ch);
648 } 892 }
649 if (global_settings.talk_menu) /* voice UI? */ 893 if (global_settings.talk_menu) /* voice UI? */
650 talk_spell(text, false); /* speak revised text */ 894 talk_spell(text, false); /* speak revised text */
@@ -653,20 +897,23 @@ int kbd_input(char* text, int buflen)
653#ifndef KBD_MODES 897#ifndef KBD_MODES
654 case KBD_BACKSPACE: 898 case KBD_BACKSPACE:
655 case KBD_BACKSPACE | BUTTON_REPEAT: 899 case KBD_BACKSPACE | BUTTON_REPEAT:
656 if (editpos > 0) 900 if (hangul) {
657 { 901 if (htail != 0)
658 utf8 = text + utf8seek(text, editpos); 902 htail = 0;
659 i = 0; 903 else if (hvowel != 0)
660 do { 904 hvowel = 0;
661 i++; 905 else {
662 utf8--; 906 hlead = 0;
663 } while ((*utf8 & MASK) == COMP); 907 hangul = false;
664 while (utf8[i]) {
665 *utf8 = utf8[i];
666 utf8++;
667 } 908 }
668 *utf8 = 0; 909 }
669 editpos--; 910 kbd_delchar(text, &editpos);
911 if (hangul) {
912 if (hvowel != 0)
913 ch = hangul_join(hlead, hvowel, htail);
914 else
915 ch = hlead;
916 kbd_inschar(text, buflen, &editpos, ch);
670 } 917 }
671 if (global_settings.talk_menu) /* voice UI? */ 918 if (global_settings.talk_menu) /* voice UI? */
672 talk_spell(text, false); /* speak revised text */ 919 talk_spell(text, false); /* speak revised text */
@@ -674,6 +921,11 @@ int kbd_input(char* text, int buflen)
674 921
675 case KBD_CURSOR_RIGHT: 922 case KBD_CURSOR_RIGHT:
676 case KBD_CURSOR_RIGHT | BUTTON_REPEAT: 923 case KBD_CURSOR_RIGHT | BUTTON_REPEAT:
924 if (hangul) {
925 hangul = false;
926 hlead=hvowel=htail=0;
927 break;
928 }
677 if (editpos < len_utf8) 929 if (editpos < len_utf8)
678 { 930 {
679 editpos++; 931 editpos++;
@@ -684,6 +936,11 @@ int kbd_input(char* text, int buflen)
684 936
685 case KBD_CURSOR_LEFT: 937 case KBD_CURSOR_LEFT:
686 case KBD_CURSOR_LEFT | BUTTON_REPEAT: 938 case KBD_CURSOR_LEFT | BUTTON_REPEAT:
939 if (hangul) {
940 hangul = false;
941 hlead=hvowel=htail=0;
942 break;
943 }
687 if (editpos) 944 if (editpos)
688 { 945 {
689 editpos--; 946 editpos--;
@@ -696,7 +953,7 @@ int kbd_input(char* text, int buflen)
696 case BUTTON_NONE: 953 case BUTTON_NONE:
697 gui_syncstatusbar_draw(&statusbars, false); 954 gui_syncstatusbar_draw(&statusbars, false);
698 redraw = false; 955 redraw = false;
699#ifdef HAVE_MORSE_INPUT 956#ifdef KBD_MORSE_INPUT
700 if (morse_reading) 957 if (morse_reading)
701 { 958 {
702 logf("Morse: 0x%02x", morse_code); 959 logf("Morse: 0x%02x", morse_code);
@@ -713,15 +970,15 @@ int kbd_input(char* text, int buflen)
713 logf("Morse code not found"); 970 logf("Morse code not found");
714 break ; 971 break ;
715 } 972 }
716 973
717 if (len + 1 < buflen) 974 /* finish hangul char if necessary */
718 { 975 if (hangul) {
719 for (i = len ; i > editpos; i--) 976 hangul = false;
720 text[i] = text[i-1]; 977 hlead=hvowel=htail=0;
721 text[len+1] = 0;
722 text[editpos] = morse_alphabets[j];
723 editpos++;
724 } 978 }
979
980 kbd_inschar(text, buflen, &editpos, morse_alphabets[j]);
981
725 if (global_settings.talk_menu) /* voice UI? */ 982 if (global_settings.talk_menu) /* voice UI? */
726 talk_spell(text, false); /* speak revised text */ 983 talk_spell(text, false); /* speak revised text */
727 redraw = true; 984 redraw = true;