keyboard: accept FS#11047 partially with some modifications. make some parts in switch() in kbd_input() to separate functions.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24902 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Teruaki Kawashima 2010-02-25 06:40:36 +00:00
parent 51bc09e88e
commit 62e6a2f9d8

View file

@ -92,6 +92,10 @@
#define KBD_TOGGLE_INPUT #define KBD_TOGGLE_INPUT
#endif #endif
#define CHANGED_PICKER 1
#define CHANGED_CURSOR 2
#define CHANGED_TEXT 3
struct keyboard_parameters struct keyboard_parameters
{ {
unsigned short kbd_buf[KBD_BUF_SIZE]; unsigned short kbd_buf[KBD_BUF_SIZE];
@ -136,6 +140,7 @@ struct edit_state
unsigned char morse_code; unsigned char morse_code;
int morse_tick; int morse_tick;
#endif #endif
int changed;
}; };
static struct keyboard_parameters kbd_param[NB_SCREENS]; static struct keyboard_parameters kbd_param[NB_SCREENS];
@ -232,10 +237,8 @@ int load_kbd(unsigned char* filename)
return 0; return 0;
} }
/* helper function to spell a char if voice UI is enabled */ /* helper function to spell a char */
static void kbd_spellchar(unsigned short c) static void kbd_spellchar(unsigned short c)
{
if (global_settings.talk_menu) /* voice UI? */
{ {
unsigned char tmp[5]; unsigned char tmp[5];
/* store char to pass to talk_spell */ /* store char to pass to talk_spell */
@ -247,15 +250,6 @@ static void kbd_spellchar(unsigned short c)
else else
talk_spell(tmp, false); talk_spell(tmp, false);
} }
}
#ifdef KBD_MODES
static void say_edit(void)
{
if (global_settings.talk_menu)
talk_id(VOICE_EDIT, false);
}
#endif
static void kbd_inschar(struct edit_state *state, unsigned short ch) static void kbd_inschar(struct edit_state *state, unsigned short ch)
{ {
@ -274,6 +268,7 @@ static void kbd_inschar(struct edit_state *state, unsigned short ch)
memmove(utf8 + j, utf8, len - i + 1); memmove(utf8 + j, utf8, len - i + 1);
memcpy(utf8, tmp, j); memcpy(utf8, tmp, j);
state->editpos++; state->editpos++;
state->changed = CHANGED_TEXT;
} }
} }
@ -290,6 +285,7 @@ static void kbd_delchar(struct edit_state *state)
utf8 = state->text + i; utf8 = state->text + i;
j = utf8seek(utf8, 1); j = utf8seek(utf8, 1);
memmove(utf8, utf8 + j, len - i - j + 1); memmove(utf8, utf8 + j, len - i - j + 1);
state->changed = CHANGED_TEXT;
} }
} }
@ -306,6 +302,12 @@ static void kbd_draw_picker(struct keyboard_parameters *pm,
struct screen *sc, struct edit_state *state); struct screen *sc, struct edit_state *state);
static void kbd_draw_edit_line(struct keyboard_parameters *pm, static void kbd_draw_edit_line(struct keyboard_parameters *pm,
struct screen *sc, struct edit_state *state); struct screen *sc, struct edit_state *state);
static void kbd_insert_selected(struct keyboard_parameters *pm,
struct edit_state *state);
static void kbd_backspace(struct edit_state *state);
static void kbd_move_cursor(struct edit_state *state, int dir);
static void kbd_move_picker_vertical(struct keyboard_parameters *pm,
struct edit_state *state, int dir);
int kbd_input(char* text, int buflen) int kbd_input(char* text, int buflen)
{ {
@ -345,6 +347,7 @@ int kbd_input(char* text, int buflen)
state.morse_reading = false; state.morse_reading = false;
#endif #endif
state.hangul = false; state.hangul = false;
state.changed = 0;
if (!kbd_loaded) if (!kbd_loaded)
{ {
@ -441,8 +444,6 @@ int kbd_input(char* text, int buflen)
kbd_draw_edit_line(pm, sc, &state); kbd_draw_edit_line(pm, sc, &state);
} }
state.cur_blink = !state.cur_blink;
#ifdef HAVE_BUTTONBAR #ifdef HAVE_BUTTONBAR
/* draw the button bar */ /* draw the button bar */
gui_buttonbar_set(&buttonbar, "Shift", "OK", "Del"); gui_buttonbar_set(&buttonbar, "Shift", "OK", "Del");
@ -452,6 +453,8 @@ int kbd_input(char* text, int buflen)
FOR_NB_SCREENS(l) FOR_NB_SCREENS(l)
screens[l].update(); screens[l].update();
state.cur_blink = !state.cur_blink;
button = get_action( button = get_action(
#ifdef HAVE_MORSE_INPUT #ifdef HAVE_MORSE_INPUT
state.morse_mode? CONTEXT_MORSE_INPUT: state.morse_mode? CONTEXT_MORSE_INPUT:
@ -507,25 +510,9 @@ int kbd_input(char* text, int buflen)
if (++pm->page >= pm->pages) if (++pm->page >= pm->pages)
pm->page = 0; pm->page = 0;
ch = get_kbd_ch(pm); state.changed = CHANGED_PICKER;
kbd_spellchar(ch);
break; break;
#if defined(HAVE_MORSE_INPUT) && defined(KBD_TOGGLE_INPUT)
case ACTION_KBD_MORSE_INPUT:
state.morse_mode = !state.morse_mode;
FOR_NB_SCREENS(l)
{
struct keyboard_parameters *pm = &param[l];
int y = pm->main_y;
pm->main_y = pm->old_main_y;
pm->old_main_y = y;
}
/* FIXME: We should talk something like Morse mode.. */
break;
#endif /* HAVE_MORSE_INPUT && KBD_TOGGLE_INPUT */
case ACTION_KBD_RIGHT: case ACTION_KBD_RIGHT:
if (++pm->x >= pm->max_chars) if (++pm->x >= pm->max_chars)
{ {
@ -537,8 +524,7 @@ int kbd_input(char* text, int buflen)
pm->x = 0; pm->x = 0;
} }
ch = get_kbd_ch(pm); state.changed = CHANGED_PICKER;
kbd_spellchar(ch);
break; break;
case ACTION_KBD_LEFT: case ACTION_KBD_LEFT:
@ -552,83 +538,33 @@ int kbd_input(char* text, int buflen)
pm->x = pm->max_chars - 1; pm->x = pm->max_chars - 1;
} }
ch = get_kbd_ch(pm); state.changed = CHANGED_PICKER;
kbd_spellchar(ch);
break; break;
case ACTION_KBD_DOWN: case ACTION_KBD_DOWN:
#ifdef HAVE_MORSE_INPUT kbd_move_picker_vertical(pm, &state, 1);
if (state.morse_mode)
{
#ifdef KBD_MODES
pm->line_edit = !pm->line_edit;
if (pm->line_edit)
say_edit();
#endif
break;
}
#endif /* HAVE_MORSE_INPUT */
#ifdef KBD_MODES
if (pm->line_edit)
{
pm->y = 0;
pm->line_edit = false;
}
else if (++pm->y >= pm->lines)
{
pm->line_edit = true;
say_edit();
}
#else
if (++pm->y >= pm->lines)
pm->y = 0;
#endif
#ifdef KBD_MODES
if (!pm->line_edit)
#endif
{
ch = get_kbd_ch(pm);
kbd_spellchar(ch);
}
break; break;
case ACTION_KBD_UP: case ACTION_KBD_UP:
#ifdef HAVE_MORSE_INPUT kbd_move_picker_vertical(pm, &state, -1);
if (state.morse_mode)
{
#ifdef KBD_MODES
pm->line_edit = !pm->line_edit;
if (pm->line_edit)
say_edit();
#endif
break;
}
#endif /* HAVE_MORSE_INPUT */
#ifdef KBD_MODES
if (pm->line_edit)
{
pm->y = pm->lines - 1;
pm->line_edit = false;
}
else if (--pm->y < 0)
{
pm->line_edit = true;
say_edit();
}
#else
if (--pm->y < 0)
pm->y = pm->lines - 1;
#endif
#ifdef KBD_MODES
if (!pm->line_edit)
#endif
{
ch = get_kbd_ch(pm);
kbd_spellchar(ch);
}
break; break;
#ifdef HAVE_MORSE_INPUT #ifdef HAVE_MORSE_INPUT
#ifdef KBD_TOGGLE_INPUT
case ACTION_KBD_MORSE_INPUT:
state.morse_mode = !state.morse_mode;
FOR_NB_SCREENS(l)
{
struct keyboard_parameters *pm = &param[l];
int y = pm->main_y;
pm->main_y = pm->old_main_y;
pm->old_main_y = y;
}
/* FIXME: We should talk something like Morse mode.. */
break;
#endif /* KBD_TOGGLE_INPUT */
case ACTION_KBD_MORSE_SELECT: case ACTION_KBD_MORSE_SELECT:
if (state.morse_mode && state.morse_reading) if (state.morse_mode && state.morse_reading)
{ {
@ -653,133 +589,19 @@ int kbd_input(char* text, int buflen)
} }
else else
#endif /* HAVE_MORSE_INPUT */ #endif /* HAVE_MORSE_INPUT */
{ kbd_insert_selected(pm, &state);
/* inserts the selected char */
/* find input char */
ch = get_kbd_ch(pm);
/* check for hangul input */
if (ch >= 0x3131 && ch <= 0x3163)
{
unsigned short tmp;
if (!state.hangul)
{
state.hlead = state.hvowel = state.htail = 0;
state.hangul = true;
}
if (!state.hvowel)
{
state.hvowel = ch;
}
else if (!state.htail)
{
state.htail = ch;
}
else
{
/* previous hangul complete */
/* check whether tail is actually lead of next char */
tmp = hangul_join(state.htail, ch, 0);
if (tmp != 0xfffd)
{
tmp = hangul_join(state.hlead, state.hvowel, 0);
kbd_delchar(&state);
kbd_inschar(&state, tmp);
/* insert dummy char */
kbd_inschar(&state, ' ');
state.hlead = state.htail;
state.hvowel = ch;
state.htail = 0;
}
else
{
state.hvowel = state.htail = 0;
state.hlead = ch;
}
}
/* combine into hangul */
tmp = hangul_join(state.hlead, state.hvowel, state.htail);
if (tmp != 0xfffd)
{
kbd_delchar(&state);
ch = tmp;
}
else
{
state.hvowel = state.htail = 0;
state.hlead = ch;
}
}
else
{
state.hangul = false;
}
/* insert char */
kbd_inschar(&state, ch);
if (global_settings.talk_menu) /* voice UI? */
talk_spell(state.text, false); /* speak revised text */
}
break; break;
case ACTION_KBD_BACKSPACE: case ACTION_KBD_BACKSPACE:
if (state.hangul) kbd_backspace(&state);
{
if (state.htail)
state.htail = 0;
else if (state.hvowel)
state.hvowel = 0;
else
state.hangul = false;
}
kbd_delchar(&state);
if (state.hangul)
{
if (state.hvowel)
ch = hangul_join(state.hlead, state.hvowel, state.htail);
else
ch = state.hlead;
kbd_inschar(&state, ch);
}
if (global_settings.talk_menu) /* voice UI? */
talk_spell(state.text, false); /* speak revised text */
break; break;
case ACTION_KBD_CURSOR_RIGHT: case ACTION_KBD_CURSOR_RIGHT:
state.hangul = false; kbd_move_cursor(&state, 1);
if (state.editpos < state.len_utf8)
{
int c = utf8seek(state.text, ++state.editpos);
kbd_spellchar(state.text[c]);
}
#if CONFIG_CODEC == SWCODEC
else if (global_settings.talk_menu)
pcmbuf_beep(1000, 150, 1500);
#endif
break; break;
case ACTION_KBD_CURSOR_LEFT: case ACTION_KBD_CURSOR_LEFT:
state.hangul = false; kbd_move_cursor(&state, -1);
if (state.editpos > 0)
{
int c = utf8seek(state.text, --state.editpos);
kbd_spellchar(state.text[c]);
}
#if CONFIG_CODEC == SWCODEC
else if (global_settings.talk_menu)
pcmbuf_beep(1000, 150, 1500);
#endif
break; break;
case ACTION_NONE: case ACTION_NONE:
@ -805,9 +627,6 @@ int kbd_input(char* text, int buflen)
/* turn off hangul input */ /* turn off hangul input */
state.hangul = false; state.hangul = false;
kbd_inschar(&state, morse_alphabets[j]); kbd_inschar(&state, morse_alphabets[j]);
if (global_settings.talk_menu) /* voice UI? */
talk_spell(state.text, false); /* speak revised text */
} }
#endif /* HAVE_MORSE_INPUT */ #endif /* HAVE_MORSE_INPUT */
break; break;
@ -826,6 +645,34 @@ int kbd_input(char* text, int buflen)
{ {
state.cur_blink = true; state.cur_blink = true;
} }
if (global_settings.talk_menu) /* voice UI? */
{
if (state.changed == CHANGED_PICKER)
{
#ifdef KBD_MODES
if (pm->line_edit)
{
talk_id(VOICE_EDIT, false);
}
else
#endif
#ifdef HAVE_MORSE_INPUT
if (!state.morse_mode)
#endif
{
ch = get_kbd_ch(pm);
kbd_spellchar(ch);
}
}
else if (state.changed == CHANGED_CURSOR)
{
int c = utf8seek(state.text, state.editpos);
kbd_spellchar(state.text[c]);
}
else if (state.changed == CHANGED_TEXT)
talk_spell(state.text, false); /* speak revised text */
}
state.changed = 0;
} }
#ifdef HAVE_BUTTONBAR #ifdef HAVE_BUTTONBAR
@ -1171,3 +1018,153 @@ static void kbd_draw_edit_line(struct keyboard_parameters *pm,
} }
#endif #endif
} }
/* inserts the selected char */
static void kbd_insert_selected(struct keyboard_parameters *pm,
struct edit_state *state)
{
/* find input char */
unsigned short ch = get_kbd_ch(pm);
/* check for hangul input */
if (ch >= 0x3131 && ch <= 0x3163)
{
unsigned short tmp;
if (!state->hangul)
{
state->hlead = state->hvowel = state->htail = 0;
state->hangul = true;
}
if (!state->hvowel)
{
state->hvowel = ch;
}
else if (!state->htail)
{
state->htail = ch;
}
else
{
/* previous hangul complete */
/* check whether tail is actually lead of next char */
tmp = hangul_join(state->htail, ch, 0);
if (tmp != 0xfffd)
{
tmp = hangul_join(state->hlead, state->hvowel, 0);
kbd_delchar(state);
kbd_inschar(state, tmp);
/* insert dummy char */
kbd_inschar(state, ' ');
state->hlead = state->htail;
state->hvowel = ch;
state->htail = 0;
}
else
{
state->hvowel = state->htail = 0;
state->hlead = ch;
}
}
/* combine into hangul */
tmp = hangul_join(state->hlead, state->hvowel, state->htail);
if (tmp != 0xfffd)
{
kbd_delchar(state);
ch = tmp;
}
else
{
state->hvowel = state->htail = 0;
state->hlead = ch;
}
}
else
{
state->hangul = false;
}
/* insert char */
kbd_inschar(state, ch);
}
static void kbd_backspace(struct edit_state *state)
{
unsigned short ch;
if (state->hangul)
{
if (state->htail)
state->htail = 0;
else if (state->hvowel)
state->hvowel = 0;
else
state->hangul = false;
}
kbd_delchar(state);
if (state->hangul)
{
if (state->hvowel)
ch = hangul_join(state->hlead, state->hvowel, state->htail);
else
ch = state->hlead;
kbd_inschar(state, ch);
}
}
static void kbd_move_cursor(struct edit_state *state, int dir)
{
state->hangul = false;
state->editpos += dir;
if (state->editpos >= 0 && state->editpos <= state->len_utf8)
{
state->changed = CHANGED_CURSOR;
}
else
{
state->editpos -= dir;
#if CONFIG_CODEC == SWCODEC
if (global_settings.talk_menu)
pcmbuf_beep(1000, 150, 1500);
#endif
}
}
static void kbd_move_picker_vertical(struct keyboard_parameters *pm,
struct edit_state *state, int dir)
{
(void) state;
state->changed = CHANGED_PICKER;
#ifdef HAVE_MORSE_INPUT
if (state->morse_mode)
{
#ifdef KBD_MODES
pm->line_edit = !pm->line_edit;
#endif
return;
}
#endif /* HAVE_MORSE_INPUT */
pm->y += dir;
#ifdef KBD_MODES
if (pm->line_edit)
{
pm->y = (dir > 0 ? 0 : pm->lines - 1);
pm->line_edit = false;
}
else if (pm->y < 0 || pm->y >= pm->lines)
{
pm->line_edit = true;
}
#else
if (pm->y >= pm->lines)
pm->y = 0;
if (pm->y < 0)
pm->y = pm->lines - 1;
#endif
}