summaryrefslogtreecommitdiff
path: root/apps/recorder/keyboard.c
diff options
context:
space:
mode:
authorFrank Dischner <phaedrus961@rockbox.org>2006-03-29 16:21:42 +0000
committerFrank Dischner <phaedrus961@rockbox.org>2006-03-29 16:21:42 +0000
commit75c3d0b9f10ea30b827052b7a6f894734e705c4f (patch)
treeec6bfd1a7f7812bf1d7523b597bada006646cb82 /apps/recorder/keyboard.c
parent0fec4711d5ba5fff1b321568fb45651e11d79b08 (diff)
downloadrockbox-75c3d0b9f10ea30b827052b7a6f894734e705c4f.zip
rockbox-75c3d0b9f10ea30b827052b7a6f894734e705c4f.tar.gz
rockbox-75c3d0b9f10ea30b827052b7a6f894734e705c4f.tar.bz2
rockbox-75c3d0b9f10ea30b827052b7a6f894734e705c4f.tar.xz
Add support for loadable vkeyboard layouts
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9347 a1c6a512-1295-4272-9138-f99709370657
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 cb982e3..47deb3a 100644
--- a/apps/recorder/keyboard.c
+++ b/apps/recorder/keyboard.c
@@ -33,19 +33,28 @@
#include "rbunicode.h"
#include "buttonbar.h"
#include "logf.h"
+#include "icons.h"
+#include "file.h"
+#include "hangul.h"
-#define KEYBOARD_MARGIN 3
-
-#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 96)
-#define KEYBOARD_LINES 8
-#define KEYBOARD_PAGES 1
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+#if CONFIG_KEYPAD == RECORDER_PAD
+#define BUTTONBAR_HEIGHT 8
#else
-#define KEYBOARD_LINES 4
-#define KEYBOARD_PAGES 3
+#define BUTTONBAR_HEIGHT 0
+#endif
+#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 96)
+#define DEFAULT_LINES 8
+#else
+#define DEFAULT_LINES 4
#endif
+#define DEFAULT_MARGIN 6
+#define KBD_BUF_SIZE 500
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
(CONFIG_KEYPAD == IRIVER_H300_PAD)
@@ -61,7 +70,7 @@
#define KBD_RIGHT BUTTON_RIGHT
#define KBD_UP BUTTON_UP
#define KBD_DOWN BUTTON_DOWN
-#define HAVE_MORSE_INPUT
+#define KBD_MORSE_INPUT (BUTTON_ON | BUTTON_MODE)
#elif CONFIG_KEYPAD == RECORDER_PAD
#define KBD_CURSOR_RIGHT (BUTTON_ON | BUTTON_RIGHT)
@@ -172,39 +181,39 @@
#endif
-#if KEYBOARD_PAGES == 1
-static const char * const kbdpages[KEYBOARD_PAGES][KEYBOARD_LINES] = {
- { "ABCDEFG abcdefg !?\" @#$%+'",
- "HIJKLMN hijklmn 789 &_()-`",
- "OPQRSTU opqrstu 456 §|{}/<",
- "VWXYZ., vwxyz.,0123 ~=[]*>",
- "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË ¢£¤¥¦§©®",
- "àáâãäåæ ìíîï èéêë «»°ºª¹²³",
- "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ ¯±×÷¡¿µ·",
- "òóôõöø çðþýÿ ùúûü ¼½¾¬¶¨ " },
-};
-
+#if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 96)
+static const unsigned char * default_kbd =
+ "ABCDEFG abcdefg !?\" @#$%+'\n"
+ "HIJKLMN hijklmn 789 &_()-`\n"
+ "OPQRSTU opqrstu 456 §|{}/<\n"
+ "VWXYZ., vwxyz.,0123 ~=[]*>\n"
+ "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË ¢£¤¥¦§©®\n"
+ "àáâãäåæ ìíîï èéêë «»°ºª¹²³\n"
+ "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ ¯±×÷¡¿µ·\n"
+ "òóôõöø çðþýÿ ùúûü ¼½¾¬¶¨";
#else
-static const char * const kbdpages[KEYBOARD_PAGES][KEYBOARD_LINES] = {
- { "ABCDEFG !?\" @#$%+'",
- "HIJKLMN 789 &_()-`",
- "OPQRSTU 456 §|{}/<",
- "VWXYZ.,0123 ~=[]*>" },
+static const unsigned char * default_kbd =
+ "ABCDEFG !?\" @#$%+'\n"
+ "HIJKLMN 789 &_()-`\n"
+ "OPQRSTU 456 §|{}/<\n"
+ "VWXYZ.,0123 ~=[]*>\n"
- { "abcdefg ¢£¤¥¦§©®¬",
- "hijklmn «»°ºª¹²³¶",
- "opqrstu ¯±×÷¡¿µ·¨",
- "vwxyz., ¼½¾ " },
-
- { "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË",
- "àáâãäåæ ìíîï èéêë",
- "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ",
- "òóôõöø çðþýÿ ùúûü" },
-};
+ "abcdefg ¢£¤¥¦§©®¬\n"
+ "hijklmn «»°ºª¹²³¶\n"
+ "opqrstu ¯±×÷¡¿µ·¨\n"
+ "vwxyz., ¼½¾ \n"
+ "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË\n"
+ "àáâãäåæ ìíîï èéêë\n"
+ "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ\n"
+ "òóôõöø çðþýÿ ùúûü";
#endif
-#ifdef HAVE_MORSE_INPUT
+static unsigned short kbd_buf[KBD_BUF_SIZE];
+static bool kbd_loaded = false;
+static int nchars = 0;
+
+#ifdef KBD_MORSE_INPUT
/* FIXME: We should put this to a configuration file. */
static const char *morse_alphabets =
"abcdefghijklmnopqrstuvwxyz1234567890,.?-@ ";
@@ -217,37 +226,139 @@ static const unsigned char morse_codes[] = {
static bool morse_mode = false;
#endif
+/* Loads a custom keyboard into memory
+ call with NULL to reset keyboard */
+int load_kbd(unsigned char* filename)
+{
+ int fd, count;
+ int i = 0;
+ unsigned char buf[4];
+
+ if (filename == NULL) {
+ kbd_loaded = false;
+ return 0;
+ }
+
+ fd = open(filename, O_RDONLY|O_BINARY);
+ if (fd < 0)
+ return 1;
+
+ while (read(fd, buf, 1) == 1 && i < KBD_BUF_SIZE) {
+ /* check how many bytes to read */
+ if (buf[0] < 0x80) {
+ count = 0;
+ } else if (buf[0] < 0xe0) {
+ count = 1;
+ } else if (buf[0] < 0xf0) {
+ count = 2;
+ } else if (buf[0] < 0xf5) {
+ count = 3;
+ } else {
+ /* Invalid size. */
+ continue;
+ }
+
+ if (read(fd, &buf[1], count) != count) {
+ close(fd);
+ kbd_loaded = false;
+ return 1;
+ }
+
+ utf8decode(buf, &kbd_buf[i]);
+ if (kbd_buf[i] != 0xFEFF && kbd_buf[i] != '\n' &&
+ kbd_buf[i] != '\r') /*skip BOM & newlines */
+ i++;
+ }
+
+ close(fd);
+ kbd_loaded = true;
+ nchars = i;
+ return 0;
+
+}
+
/* helper function to spell a char if voice UI is enabled */
-static void kbd_spellchar(char c)
+static void kbd_spellchar(unsigned short c)
{
static char spell_char[2] = "\0\0"; /* store char to pass to talk_spell */
- if (global_settings.talk_menu) /* voice UI? */
+ if (global_settings.talk_menu && c < 128) /* voice UI? */
{
- spell_char[0] = c;
+ spell_char[0] = (char)c;
talk_spell(spell_char, false);
}
}
+void kbd_inschar(unsigned char* text, int buflen, int* editpos, unsigned short ch)
+{
+ int i, j, k, len;
+ unsigned char tmp[4];
+ unsigned char* utf8;
+
+ len = strlen(text);
+ k = utf8length(text);
+ utf8 = utf8encode(ch, tmp);
+ j = (long)utf8 - (long)tmp;
+
+ if (len + j < buflen)
+ {
+ for (i = len+j; k >= *editpos; i--) {
+ text[i] = text[i-j];
+ if ((text[i] & MASK) != COMP)
+ k--;
+ }
+ while (j--)
+ text[i--] = tmp[j];
+ (*editpos)++;
+ }
+ return;
+}
+
+void kbd_delchar(unsigned char* text, int* editpos)
+{
+ int i = 0;
+ unsigned char* utf8;
+
+ if (*editpos > 0)
+ {
+ utf8 = text + utf8seek(text, *editpos);
+ do {
+ i++;
+ utf8--;
+ } while ((*utf8 & MASK) == COMP);
+ while (utf8[i]) {
+ *utf8 = utf8[i];
+ utf8++;
+ }
+ *utf8 = 0;
+ (*editpos)--;
+ }
+
+ return;
+}
+
int kbd_input(char* text, int buflen)
{
bool done = false;
-#if defined(KBD_PAGE_FLIP) || (KEYBOARD_PAGES > 1)
int page = 0;
-#endif
- int font_w = 0, font_h = 0, i, j;
+ int font_w = 0, font_h = 0, text_w = 0;
+ int i = 0, j, k, w;
int x = 0, y = 0;
- int main_x, main_y, max_chars;
- int status_y1, status_y2;
- int len, len_utf8, c = 0;
+ int main_x, main_y, max_chars, max_chars_text;
+ int len_utf8, c = 0;
int editpos, curpos, leftpos;
+ int lines, pages, keyboard_margin;
+ int curfont;
+ int statusbar_size = global_settings.statusbar ? STATUSBAR_HEIGHT : 0;
+ unsigned short ch, tmp, hlead = 0, hvowel = 0, htail = 0;
+ bool hangul = false;
bool redraw = true;
unsigned char *utf8;
- const char * const *line;
-#ifdef HAVE_MORSE_INPUT
+ const unsigned char *p;
+#ifdef KBD_MORSE_INPUT
bool morse_reading = false;
unsigned char morse_code = 0;
- int morse_tick = 0, morse_len;
+ int morse_tick = 0, morse_len, old_main_y;
char buf[2];
#endif
#ifdef KBD_MODES
@@ -255,7 +366,7 @@ int kbd_input(char* text, int buflen)
#endif
char outline[256];
- struct font* font = font_get(FONT_SYSFIXED);
+ struct font* font;
int button, lastbutton = 0;
#ifdef HAS_BUTTONBAR
struct gui_buttonbar buttonbar;
@@ -264,44 +375,103 @@ int kbd_input(char* text, int buflen)
gui_buttonbar_init(&buttonbar);
gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) );
#endif
- lcd_setfont(FONT_SYSFIXED);
- font_w = font->maxwidth;
+
+ if (!kbd_loaded) {
+ curfont = FONT_SYSFIXED;
+ p = default_kbd;
+ while (*p != 0) {
+ p = utf8decode(p, &kbd_buf[i]);
+ if (kbd_buf[i] == '\n')
+ while (i % (LCD_WIDTH/6))
+ kbd_buf[i++] = ' ';
+ else
+ i++;
+ }
+ nchars = i;
+ }
+ else
+ curfont = FONT_UI;
+
+ font = font_get(curfont);
font_h = font->height;
-#ifdef HAVE_MORSE_INPUT
+ /* check if FONT_UI fits the screen */
+ if (2*font_h+3+statusbar_size + BUTTONBAR_HEIGHT > LCD_HEIGHT) {
+ font = font_get(FONT_SYSFIXED);
+ font_h = font->height;
+ curfont = FONT_SYSFIXED;
+ }
+
+ lcd_setfont(curfont);
+
+ /* find max width of keyboard glyphs */
+ for (i=0; i<nchars; i++) {
+ w = font_get_width(font, kbd_buf[i]);
+ if (w > font_w)
+ font_w = w;
+ }
+
+ /* find max width for text string */
+ utf8 = text;
+ text_w = font_w;
+ while (*utf8) {
+ utf8 = (unsigned char*)utf8decode(utf8, &ch);
+ w = font_get_width(font, ch);
+ if (w > text_w)
+ text_w = w;
+ }
+ max_chars_text = LCD_WIDTH / text_w - 2;
+
+ /* calculate keyboard grid size */
+ max_chars = LCD_WIDTH / font_w;
+ if (!kbd_loaded) {
+ lines = DEFAULT_LINES;
+ keyboard_margin = DEFAULT_MARGIN;
+ } else {
+ lines = (LCD_HEIGHT - BUTTONBAR_HEIGHT - statusbar_size) / font_h - 1;
+ keyboard_margin = LCD_HEIGHT - BUTTONBAR_HEIGHT - statusbar_size - (lines+1)*font_h;
+ if (keyboard_margin < 3) {
+ lines--;
+ keyboard_margin += font_h;
+ }
+ if (keyboard_margin > 6)
+ keyboard_margin = 6;
+ }
+
+ pages = (nchars + (lines*max_chars-1))/(lines*max_chars);
+ if (pages == 1 && kbd_loaded)
+ lines = (nchars + max_chars - 1) / max_chars;
+
+ main_y = font_h*lines + keyboard_margin + statusbar_size;
+ main_x = 0;
+ keyboard_margin -= keyboard_margin/2;
+
+#ifdef KBD_MORSE_INPUT
+ old_main_y = main_y;
if (morse_mode)
main_y = LCD_HEIGHT - font_h;
- else
#endif
- main_y = (KEYBOARD_LINES + 1) * font_h + (2*KEYBOARD_MARGIN);
- main_x = 0;
- status_y1 = LCD_HEIGHT - font_h;
- status_y2 = LCD_HEIGHT;
editpos = utf8length(text);
-
- max_chars = LCD_WIDTH / font_w - 2; /* leave room for < and > */
- line = kbdpages[0];
if (global_settings.talk_menu) /* voice UI? */
talk_spell(text, true); /* spell initial text */
while(!done)
{
- len = strlen(text);
len_utf8 = utf8length(text);
if(redraw)
{
lcd_clear_display();
- lcd_setfont(FONT_SYSFIXED);
-
-#ifdef HAVE_MORSE_INPUT
+#ifdef KBD_MORSE_INPUT
if (morse_mode)
{
+ lcd_setfont(FONT_SYSFIXED); /* Draw morse code screen with sysfont */
+ w = 6; /* sysfixed font width */
x = 0;
- y = font_h;
+ y = statusbar_size;
buf[1] = '\0';
/* Draw morse code table with code descriptions. */
for (i = 0; morse_alphabets[i] != '\0'; i++)
@@ -312,7 +482,7 @@ int kbd_input(char* text, int buflen)
for (j = 0; (morse_codes[i] >> j) > 0x01; j++) ;
morse_len = j;
- x += font_w + 3;
+ x += w + 3;
for (j = 0; j < morse_len; j++)
{
if ((morse_codes[i] >> (morse_len-j-1)) & 0x01)
@@ -321,11 +491,11 @@ int kbd_input(char* text, int buflen)
lcd_fillrect(x + j*4, y + 3, 1, 2);
}
- x += font_w * 5 - 3;
- if (x >= LCD_WIDTH - (font_w*6))
+ x += w * 5 - 3;
+ if (x >= LCD_WIDTH - (w*6))
{
x = 0;
- y += font_h;
+ y += 8; /* sysfixed font height */
}
}
}
@@ -333,50 +503,67 @@ int kbd_input(char* text, int buflen)
#endif
{
/* draw page */
- for (i=0; i < KEYBOARD_LINES; i++)
- lcd_putsxy(0, 8+i * font_h, line[i]);
-
+ lcd_setfont(curfont);
+ k = page*max_chars*lines;
+ for (i=j=0; j < lines && k < nchars; k++) {
+ utf8 = utf8encode(kbd_buf[k], outline);
+ *utf8 = 0;
+ lcd_getstringsize(outline, &w, NULL);
+ lcd_putsxy(i*font_w + (font_w-w)/2, j*font_h + statusbar_size, outline);
+ if (++i == max_chars) {
+ i = 0;
+ j++;
+ }
+ }
}
/* separator */
- lcd_hline(0, LCD_WIDTH - 1, main_y - KEYBOARD_MARGIN);
+ lcd_hline(0, LCD_WIDTH - 1, main_y - keyboard_margin);
/* write out the text */
- curpos = MIN(editpos, max_chars - MIN(len_utf8 - editpos, 2));
+ lcd_setfont(curfont);
+ i=j=0;
+ curpos = MIN(editpos, max_chars_text - MIN(len_utf8 - editpos, 2));
leftpos = editpos - curpos;
utf8 = text + utf8seek(text, leftpos);
- i=j=0;
- while (*utf8 && i < max_chars) {
+
+ while (*utf8 && i < max_chars_text) {
outline[j++] = *utf8++;
- if ((*utf8 & MASK) != COMP)
+ if ((*utf8 & MASK) != COMP) {
+ outline[j] = 0;
+ j=0;
i++;
+ lcd_getstringsize(outline, &w, NULL);
+ lcd_putsxy(i*text_w + (text_w-w)/2, main_y, outline);
+ }
+ }
+
+ if (leftpos) {
+ lcd_getstringsize("<", &w, NULL);
+ lcd_putsxy(text_w - w, main_y, "<");
}
- outline[j] = 0;
-
- lcd_putsxy(font_w, main_y, outline);
-
- if (leftpos)
- lcd_putsxy(0, main_y, "<");
- if (len_utf8 - leftpos > max_chars)
- lcd_putsxy(LCD_WIDTH - font_w, main_y, ">");
-
+ if (len_utf8 - leftpos > max_chars_text)
+ lcd_putsxy(LCD_WIDTH - text_w, main_y, ">");
+
/* cursor */
- i = (curpos + 1) * font_w;
+ i = (curpos + 1) * text_w;
lcd_vline(i, main_y, main_y + font_h);
-
+ if (hangul) /* draw underbar */
+ lcd_hline(curpos*text_w, (curpos+1)*text_w, main_y+font_h-1);
+
#ifdef HAS_BUTTONBAR
/* draw the status bar */
gui_buttonbar_set(&buttonbar, "Shift", "OK", "Del");
gui_buttonbar_draw(&buttonbar);
#endif
-
+
#ifdef KBD_MODES
if (!line_edit)
#endif
{
/* highlight the key that has focus */
lcd_set_drawmode(DRMODE_COMPLEMENT);
- lcd_fillrect(font_w * x, 8 + font_h * y, font_w, font_h);
+ lcd_fillrect(font_w * x, statusbar_size + font_h * y, font_w, font_h);
lcd_set_drawmode(DRMODE_SOLID);
}
@@ -388,7 +575,7 @@ int kbd_input(char* text, int buflen)
redraw = true;
button = button_get_w_tmo(HZ/2);
-#ifdef HAVE_MORSE_INPUT
+#ifdef KBD_MORSE_INPUT
if (morse_mode)
{
/* Remap some buttons for morse mode. */
@@ -411,40 +598,43 @@ int kbd_input(char* text, int buflen)
#if defined(KBD_PAGE_FLIP)
case KBD_PAGE_FLIP:
-#ifdef HAVE_MORSE_INPUT
+#ifdef KBD_MORSE_INPUT
if (morse_mode)
- {
- main_y = (KEYBOARD_LINES + 1) * font_h + (2*KEYBOARD_MARGIN);
- morse_mode = false;
- x = y = 0;
- }
- else
+ break;
#endif
- if (++page == KEYBOARD_PAGES)
- {
+ if (++page == pages)
page = 0;
-#ifdef HAVE_MORSE_INPUT
- main_y = LCD_HEIGHT - font_h;
- morse_mode = true;
- /* FIXME: We should talk something like Morse mode.. */
- break ;
-#endif
- }
- line = kbdpages[page];
- c = utf8seek(line[y], x);
- kbd_spellchar(line[y][c]);
+ k = (page*lines + y)*max_chars + x;
+ kbd_spellchar(kbd_buf[k]);
break;
#endif
+#ifdef KBD_MORSE_INPUT
+ case KBD_MORSE_INPUT:
+ morse_mode = !morse_mode;
+ x = y = page = 0;
+ if (morse_mode) {
+ old_main_y = main_y;
+ main_y = LCD_HEIGHT - font_h;
+ } else
+ main_y = old_main_y;
+ /* FIXME: We should talk something like Morse mode.. */
+ break;
+#endif
case KBD_RIGHT:
case KBD_RIGHT | BUTTON_REPEAT:
-#ifdef HAVE_MORSE_INPUT
+#ifdef KBD_MORSE_INPUT
if (morse_mode)
break;
#endif
#ifdef KBD_MODES
if (line_edit) /* right doubles as cursor_right in line_edit */
{
+ if (hangul) {
+ hangul = false;
+ hlead=hvowel=htail=0;
+ break;
+ }
if (editpos < len_utf8)
{
editpos++;
@@ -455,32 +645,33 @@ int kbd_input(char* text, int buflen)
else
#endif
{
- if (x < (int)utf8length(line[y]) - 1)
- x++;
- else
- {
+ if (++x == max_chars) {
x = 0;
-#if !defined(KBD_PAGE_FLIP) && KEYBOARD_PAGES > 1
+#if !defined(KBD_PAGE_FLIP)
/* no dedicated flip key - flip page on wrap */
- if (++page == KEYBOARD_PAGES)
+ if (++page == pages)
page = 0;
- line = kbdpages[page];
#endif
}
- c = utf8seek(line[y], x);
- kbd_spellchar(line[y][c]);
+ k = (page*lines + y)*max_chars + x;
+ kbd_spellchar(kbd_buf[k]);
}
break;
case KBD_LEFT:
case KBD_LEFT | BUTTON_REPEAT:
-#ifdef HAVE_MORSE_INPUT
+#ifdef KBD_MORSE_INPUT
if (morse_mode)
break;
#endif
#ifdef KBD_MODES
if (line_edit) /* left doubles as cursor_left in line_edit */
{
+ if (hangul) {
+ hangul = false;
+ hlead=hvowel=htail=0;
+ break;
+ }
if (editpos)
{
editpos--;
@@ -490,27 +681,26 @@ int kbd_input(char* text, int buflen)
}
else
#endif
- {
+ {
if (x)
x--;
else
{
-#if !defined(KBD_PAGE_FLIP) && KEYBOARD_PAGES > 1
+#if !defined(KBD_PAGE_FLIP)
/* no dedicated flip key - flip page on wrap */
if (--page < 0)
- page = (KEYBOARD_PAGES-1);
- line = kbdpages[page];
+ page = (pages-1);
#endif
- x = utf8length(line[y]) - 1;
+ x = max_chars - 1;
}
- c = utf8seek(line[y], x);
- kbd_spellchar(line[y][c]);
+ k = (page*lines + y)*max_chars + x;
+ kbd_spellchar(kbd_buf[k]);
}
break;
case KBD_DOWN:
case KBD_DOWN | BUTTON_REPEAT:
-#ifdef HAVE_MORSE_INPUT
+#ifdef KBD_MORSE_INPUT
if (morse_mode)
break;
#endif
@@ -523,7 +713,7 @@ int kbd_input(char* text, int buflen)
else
{
#endif
- if (y < KEYBOARD_LINES - 1)
+ if (y < lines - 1)
y++;
else
#ifndef KBD_MODES
@@ -533,20 +723,22 @@ int kbd_input(char* text, int buflen)
}
if (!line_edit)
#endif
- c = utf8seek(line[y], x);
- kbd_spellchar(line[y][c]);
+ {
+ k = (page*lines + y)*max_chars + x;
+ kbd_spellchar(kbd_buf[k]);
+ }
break;
case KBD_UP:
case KBD_UP | BUTTON_REPEAT:
-#ifdef HAVE_MORSE_INPUT
+#ifdef KBD_MORSE_INPUT
if (morse_mode)
break;
#endif
#ifdef KBD_MODES
if (line_edit)
{
- y = KEYBOARD_LINES - 1;
+ y = lines - 1;
line_edit = false;
}
else
@@ -556,14 +748,16 @@ int kbd_input(char* text, int buflen)
y--;
else
#ifndef KBD_MODES
- y = KEYBOARD_LINES - 1;
+ y = lines - 1;
#else
line_edit = true;
}
if (!line_edit)
#endif
- c = utf8seek(line[y], x);
- kbd_spellchar(line[y][c]);
+ {
+ k = (page*lines + y)*max_chars + x;
+ kbd_spellchar(kbd_buf[k]);
+ }
break;
case KBD_DONE:
@@ -575,7 +769,7 @@ int kbd_input(char* text, int buflen)
done = true;
break;
-#ifdef HAVE_MORSE_INPUT
+#ifdef KBD_MORSE_INPUT
case KBD_SELECT | BUTTON_REL:
if (morse_mode && morse_reading)
{
@@ -588,7 +782,7 @@ int kbd_input(char* text, int buflen)
#endif
case KBD_SELECT:
-#ifdef HAVE_MORSE_INPUT
+#ifdef KBD_MORSE_INPUT
if (morse_mode)
{
morse_tick = current_tick;
@@ -607,44 +801,94 @@ int kbd_input(char* text, int buflen)
break;
#endif
#ifdef KBD_MODES
- if (line_edit) /* select doubles as backspace in line_edit */
- {
- if (editpos > 0)
- {
- utf8 = text + utf8seek(text, editpos);
- i = 0;
- do {
- i++;
- utf8--;
- } while ((*utf8 & MASK) == COMP);
- while (utf8[i]) {
- *utf8 = utf8[i];
- utf8++;
+ if (line_edit) { /* select doubles as backspace in line_edit */
+ if (hangul) {
+ if (htail != 0)
+ htail = 0;
+ else if (hvowel != 0)
+ hvowel = 0;
+ else {
+ hlead = 0;
+ hangul = false;
}
- *utf8 = 0;
- editpos--;
+ }
+ kbd_delchar(text, &editpos);
+ if (hangul) {
+ if (hvowel != 0)
+ ch = hangul_join(hlead, hvowel, htail);
+ else
+ ch = hlead;
+ kbd_inschar(text, buflen, &editpos, ch);
}
}
else
#endif
{
- const unsigned char *inschar = line[y] + utf8seek(line[y], x);
- j = 0;
- do {
- j++;
- } while ((inschar[j] & MASK) == COMP);
- if (len + j < buflen)
- {
- int k = len_utf8;
- for (i = len+j; k >= editpos; i--) {
- text[i] = text[i-j];
- if ((text[i] & MASK) != COMP)
- k--;
+ /* find input char */
+ k = (page*lines + y)*max_chars + x;
+ if (k < nchars)
+ ch = kbd_buf[k];
+ else
+ ch = ' ';
+
+ /* check for hangul input */
+ if (ch >= 0x3131 && ch <= 0x3163) {
+ if (hangul) {
+ if ((hvowel == 0) && (jamo_table[ch-0x3131][1] != 0)) {
+ hvowel = ch;
+ ch = hangul_join(hlead, hvowel, htail);
+ kbd_delchar(text, &editpos);
+ }
+ else if ((htail == 0) && (hvowel != 0) && (jamo_table[ch-0x3131][2] != 0)) {
+ htail = ch;
+ /* combine into hangul */
+ ch = hangul_join(hlead, hvowel, htail);
+ kbd_delchar(text, &editpos);
+ }
+ else { /* invalid following char or hangul complete */
+ /* check whether tail is actually lead of next char */
+ if (htail != 0 && (jamo_table[htail-0x3131][0] != 0)
+ && (jamo_table[ch-0x3131][1] != 0)) {
+ tmp = hangul_join(hlead, hvowel, 0);
+ kbd_delchar(text, &editpos);
+ kbd_inschar(text, buflen, &editpos, tmp);
+ hlead = htail;
+ hvowel = ch;
+ htail = 0;
+ ch = hangul_join(hlead, hvowel, htail);
+ }
+ else if (hlead != 0 && hvowel != 0) {
+ /* finish previous hangul */
+ tmp = hangul_join(hlead, hvowel, htail);
+ kbd_delchar(text, &editpos);
+ kbd_inschar(text, buflen, &editpos, tmp);
+ hlead=hvowel=htail=0;
+ /* start of new hangul? */
+ if (jamo_table[ch-0x3131][0] != 0) {
+ hlead = ch;
+ }
+ else
+ hangul = false;
+ }
+ }
}
- while (j--)
- text[i--] = inschar[j];
- editpos++;
+ else if (jamo_table[ch-0x3131][0] != 0) {
+ hlead = ch;
+ hangul = true;
+ }
+ }
+ else if (hangul) {
+ /* finish previous hangul */
+ if (hlead != 0 && hvowel != 0) {
+ tmp = hangul_join(hlead, hvowel, htail);
+ kbd_delchar(text, &editpos);
+ kbd_inschar(text, buflen, &editpos, tmp);
+ }
+ hangul = false;
+ hlead=hvowel=htail=0;
}
+ /* insert char */
+ kbd_inschar(text, buflen, &editpos, ch);
}
if (global_settings.talk_menu) /* voice UI? */
talk_spell(text, false); /* speak revised text */
@@ -653,20 +897,23 @@ int kbd_input(char* text, int buflen)
#ifndef KBD_MODES
case KBD_BACKSPACE:
case KBD_BACKSPACE | BUTTON_REPEAT:
- if (editpos > 0)
- {
- utf8 = text + utf8seek(text, editpos);
- i = 0;
- do {
- i++;
- utf8--;
- } while ((*utf8 & MASK) == COMP);
- while (utf8[i]) {
- *utf8 = utf8[i];
- utf8++;
+ if (hangul) {
+ if (htail != 0)
+ htail = 0;
+ else if (hvowel != 0)
+ hvowel = 0;
+ else {
+ hlead = 0;
+ hangul = false;
}
- *utf8 = 0;
- editpos--;
+ }
+ kbd_delchar(text, &editpos);
+ if (hangul) {
+ if (hvowel != 0)
+ ch = hangul_join(hlead, hvowel, htail);
+ else
+ ch = hlead;
+ kbd_inschar(text, buflen, &editpos, ch);
}
if (global_settings.talk_menu) /* voice UI? */
talk_spell(text, false); /* speak revised text */
@@ -674,6 +921,11 @@ int kbd_input(char* text, int buflen)
case KBD_CURSOR_RIGHT:
case KBD_CURSOR_RIGHT | BUTTON_REPEAT:
+ if (hangul) {
+ hangul = false;
+ hlead=hvowel=htail=0;
+ break;
+ }
if (editpos < len_utf8)
{
editpos++;
@@ -684,6 +936,11 @@ int kbd_input(char* text, int buflen)
case KBD_CURSOR_LEFT:
case KBD_CURSOR_LEFT | BUTTON_REPEAT:
+ if (hangul) {
+ hangul = false;
+ hlead=hvowel=htail=0;
+ break;
+ }
if (editpos)
{
editpos--;
@@ -696,7 +953,7 @@ int kbd_input(char* text, int buflen)
case BUTTON_NONE:
gui_syncstatusbar_draw(&statusbars, false);
redraw = false;
-#ifdef HAVE_MORSE_INPUT
+#ifdef KBD_MORSE_INPUT
if (morse_reading)
{
logf("Morse: 0x%02x", morse_code);
@@ -713,15 +970,15 @@ int kbd_input(char* text, int buflen)
logf("Morse code not found");
break ;
}
-
- if (len + 1 < buflen)
- {
- for (i = len ; i > editpos; i--)
- text[i] = text[i-1];
- text[len+1] = 0;
- text[editpos] = morse_alphabets[j];
- editpos++;
+
+ /* finish hangul char if necessary */
+ if (hangul) {
+ hangul = false;
+ hlead=hvowel=htail=0;
}
+
+ kbd_inschar(text, buflen, &editpos, morse_alphabets[j]);
+
if (global_settings.talk_menu) /* voice UI? */
talk_spell(text, false); /* speak revised text */
redraw = true;