Index: apps/action.h =================================================================== --- apps/action.h (revision 24931) +++ apps/action.h (working copy) @@ -237,6 +237,8 @@ ACTION_KBD_DOWN, ACTION_KBD_MORSE_INPUT, ACTION_KBD_MORSE_SELECT, + ACTION_KBD_SCROLL_FWD, + ACTION_KBD_SCROLL_BACK, #ifdef HAVE_TOUCHSCREEN /* the following are helper actions for touchscreen targets, Index: apps/recorder/keyboard.c =================================================================== --- apps/recorder/keyboard.c (revision 24931) +++ apps/recorder/keyboard.c (working copy) @@ -43,10 +43,13 @@ #define O_BINARY 0 #endif - #define DEFAULT_MARGIN 6 #define KBD_BUF_SIZE 500 +#define PRED_TEXT +#define MAX_DICT 85000 +#define MAX_DICT_WORD 50 + #if (CONFIG_KEYPAD == ONDIO_PAD) \ || (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ || (CONFIG_KEYPAD == IPOD_3G_PAD) \ @@ -55,11 +58,8 @@ || (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) \ || (CONFIG_KEYPAD == IAUDIO_M3_PAD) \ || (CONFIG_KEYPAD == IRIVER_H10_PAD) \ - || (CONFIG_KEYPAD == PBELL_VIBE500_PAD) -/* no key combos to move the cursor if not in line edit mode */ -#define KBD_MODES /* uses 2 modes, picker and line edit */ - -#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) \ + || (CONFIG_KEYPAD == PBELL_VIBE500_PAD) \ + || (CONFIG_KEYPAD == IRIVER_H100_PAD) \ || (CONFIG_KEYPAD == IRIVER_H300_PAD) \ || (CONFIG_KEYPAD == GIGABEAT_PAD) \ || (CONFIG_KEYPAD == GIGABEAT_S_PAD) \ @@ -67,12 +67,7 @@ || (CONFIG_KEYPAD == SANSA_FUZE_PAD) \ || (CONFIG_KEYPAD == SANSA_C200_PAD) \ || (CONFIG_KEYPAD == SAMSUNG_YH_PAD) -/* certain key combos move the cursor even if not in line edit mode */ -#define KBD_CURSOR_KEYS #define KBD_MODES /* uses 2 modes, picker and line edit */ - -#else -#define KBD_CURSOR_KEYS /* certain keys move the cursor, no line edit mode */ #endif #if (CONFIG_KEYPAD == IRIVER_H100_PAD) \ @@ -85,17 +80,14 @@ || (CONFIG_KEYPAD == GIGABEAT_S_PAD) \ || (CONFIG_KEYPAD == MROBE100_PAD) \ || (CONFIG_KEYPAD == SANSA_E200_PAD) \ + || (CONFIG_KEYPAD == SANSA_FUZE_PAD) \ || (CONFIG_KEYPAD == PHILIPS_HDD1630_PAD) \ || (CONFIG_KEYPAD == PHILIPS_SA9200_PAD) \ || (CONFIG_KEYPAD == PBELL_VIBE500_PAD) -/* certain key combos toggle input mode between keyboard input and Morse input */ +/* certain key combos change keyboard entry modes */ #define KBD_TOGGLE_INPUT #endif -#define CHANGED_PICKER 1 -#define CHANGED_CURSOR 2 -#define CHANGED_TEXT 3 - struct keyboard_parameters { unsigned short kbd_buf[KBD_BUF_SIZE]; @@ -125,6 +117,20 @@ #endif }; +enum { KBD_MODE_STANDARD=0, +#ifdef HAVE_SCROLLWHEEL + KBD_MODE_SIDEWAYS, + KBD_MODE_KEEP_ROLLIN, + KBD_MODE_SCROLL_1D, + KBD_MODE_ROWCOL, +#endif +#ifdef HAVE_MORSE_INPUT + KBD_MODE_MORSE, +#endif + KBD_MODE_END +}; + + struct edit_state { char* text; @@ -135,12 +141,21 @@ bool hangul; unsigned short hlead, hvowel, htail; #ifdef HAVE_MORSE_INPUT - bool morse_mode; bool morse_reading; unsigned char morse_code; int morse_tick; #endif - int changed; +#if defined (HAVE_MORSE_INPUT) || defined (HAVE_SCROLLWHEEL) + int keyboard_mode; +#endif +#ifdef HAVE_SCROLLWHEEL + int prev_button; + bool row; +#endif +#ifdef PRED_TEXT + char pred_word[MAX_DICT_WORD+1]; + int pred_input_len; +#endif }; static struct keyboard_parameters kbd_param[NB_SCREENS]; @@ -157,6 +172,59 @@ 0x73,0x55,0x4c,0x61,0x5a,0x80 }; #endif +static void kbd_calc_params(struct keyboard_parameters *pm, + struct screen *sc, struct edit_state *state); +static void kbd_draw_picker(struct keyboard_parameters *pm, + struct screen *sc, struct edit_state *state); +static void kbd_draw_edit_line(struct keyboard_parameters *pm, + struct screen *sc, struct edit_state *state); +#ifdef PRED_TEXT +static void kbd_draw_predicted(struct keyboard_parameters *pm, + struct screen *sc, struct edit_state *state); +#endif +static void kbd_inschar(struct edit_state *state, unsigned short ch); + +static void kbd_delchar(struct edit_state *state); + +#ifdef HAVE_MORSE_INPUT +static void kbd_morse_select(struct edit_state *state); +#endif /* HAVE_MORSE_INPUT */ +#ifdef HAVE_SCROLLWHEEL +static void kbd_scroll_fwd( struct edit_state *state, + struct keyboard_parameters *pm); +static void kbd_scroll_back(struct edit_state *state, + struct keyboard_parameters *pm); +#endif +#ifdef PRED_TEXT +static void kbd_draw_predicted(struct keyboard_parameters *pm, + struct screen *sc, struct edit_state *state); +static void kbd_insert_predicted(struct edit_state *state); +#endif +static void kbd_picker_right( struct edit_state *state, + struct keyboard_parameters *pm ); + +static void kbd_right( struct edit_state *state, + struct keyboard_parameters *pm ); +static void kbd_picker_left( struct edit_state *state, + struct keyboard_parameters *pm ); +static void kbd_left( struct edit_state *state, + struct keyboard_parameters *pm ); +static void kbd_down(struct edit_state *state, + struct keyboard_parameters *pm); +static void kbd_up (struct edit_state *state, + struct keyboard_parameters *pm); +static void kbd_cursor_right(struct edit_state *state); + +static void kbd_cursor_left(struct edit_state *state); + +static void kbd_backspace(struct edit_state *state); + +static void kbd_insert_current_char(struct edit_state *state, + struct keyboard_parameters *pm); +static void kbd_select(struct edit_state *state, + struct keyboard_parameters *pm); +static void kbd_none(struct edit_state *state); + /* Loads a custom keyboard into memory call with NULL to reset keyboard */ int load_kbd(unsigned char* filename) @@ -237,20 +305,31 @@ return 0; } -/* helper function to spell a char */ +/* helper function to spell a char if voice UI is enabled */ static void kbd_spellchar(unsigned short c) { - unsigned char tmp[5]; - /* store char to pass to talk_spell */ - unsigned char* utf8 = utf8encode(c, tmp); - *utf8 = 0; + if (global_settings.talk_menu) /* voice UI? */ + { + unsigned char tmp[5]; + /* store char to pass to talk_spell */ + unsigned char* utf8 = utf8encode(c, tmp); + *utf8 = 0; - if (c == ' ') - talk_id(VOICE_BLANK, false); - else - talk_spell(tmp, false); + if (c == ' ') + talk_id(VOICE_BLANK, false); + else + 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) { int i, j, len; @@ -268,7 +347,6 @@ memmove(utf8 + j, utf8, len - i + 1); memcpy(utf8, tmp, j); state->editpos++; - state->changed = CHANGED_TEXT; } } @@ -285,7 +363,6 @@ utf8 = state->text + i; j = utf8seek(utf8, 1); memmove(utf8, utf8 + j, len - i - j + 1); - state->changed = CHANGED_TEXT; } } @@ -296,19 +373,617 @@ return (k < pm->nchars)? pm->kbd_buf[k]: ' '; } -static void kbd_calc_params(struct keyboard_parameters *pm, - struct screen *sc, struct edit_state *state); -static void kbd_draw_picker(struct keyboard_parameters *pm, - struct screen *sc, struct edit_state *state); -static void kbd_draw_edit_line(struct keyboard_parameters *pm, - 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); +#ifdef KBD_TOGGLE_INPUT +static void kbd_switch_mode ( struct edit_state *state ) +{ + char *mode_labels[] = { ID2P(LANG_KBD_MODE_STANDARD), +#ifdef HAVE_SCROLLWHEEL + ID2P(LANG_KBD_MODE_SIDEWAYS), + ID2P(LANG_KBD_MODE_KEEP_ROLLIN), + ID2P(LANG_KBD_MODE_SCROLL_1D), + ID2P(LANG_KBD_MODE_ROW_COL), +#endif +#ifdef HAVE_MORSE_INPUT + ID2P(LANG_KBD_MODE_MORSE), +#endif + "Bad Mode!" }; + + int l; + FOR_NB_SCREENS(l) + { +#ifdef KBD_MODES + kbd_param[l].line_edit = false; +#endif + kbd_param[l].x = 0; + kbd_param[l].y = 0; + kbd_param[l].page = 0; + } + state->keyboard_mode++; + if ( state->keyboard_mode == KBD_MODE_END ) + state->keyboard_mode = KBD_MODE_STANDARD; + splash(HZ,mode_labels[state->keyboard_mode-KBD_MODE_STANDARD] ); +} +#endif +static void kbd_page_flip ( struct edit_state *state, + struct keyboard_parameters *pm ) +{ + (void) state; +#ifdef HAVE_MORSE_INPUT + if (state->keyboard_mode == KBD_MODE_MORSE) + return; +#endif + if (++pm->page >= pm->pages) + pm->page = 0; + + kbd_spellchar( get_kbd_ch(pm) ); +} + +#ifdef HAVE_SCROLLWHEEL +static void kbd_scroll_fwd( struct edit_state *state, + struct keyboard_parameters *pm ) +{ + switch ( state->keyboard_mode ) + { + case KBD_MODE_ROWCOL: + if ( state->row ) + kbd_down( state, pm ); + else + kbd_picker_right( state, pm ); + break; + + case KBD_MODE_KEEP_ROLLIN: + if ( state->prev_button == ACTION_KBD_SCROLL_FWD ) + kbd_picker_right( state, pm ); + break; + + case KBD_MODE_MORSE: + kbd_cursor_right( state ); + break; + + case KBD_MODE_SCROLL_1D: + kbd_picker_right( state, pm ); + break; + + case KBD_MODE_SIDEWAYS: +#ifdef KBD_MODES + if ( pm->line_edit ) + kbd_cursor_right( state ); + else +#endif + kbd_picker_right( state, pm ); + break; + case KBD_MODE_STANDARD: + default: + kbd_down( state, pm ); + break; + } + state->prev_button = ACTION_KBD_SCROLL_FWD; +} + +static void kbd_scroll_back( struct edit_state *state, + struct keyboard_parameters *pm ) +{ + switch ( state->keyboard_mode ) + { + case KBD_MODE_ROWCOL: + if ( state->row ) + kbd_up( state, pm ); + else + kbd_picker_left( state, pm ); + break; + case KBD_MODE_KEEP_ROLLIN: + if ( state->prev_button == ACTION_KBD_SCROLL_FWD ) + { + kbd_insert_current_char( state, pm ); + pm->x = pm->y = 0; + } + else + kbd_down( state, pm ); + break; + case KBD_MODE_SCROLL_1D: + kbd_picker_left( state, pm ); + break; + + case KBD_MODE_MORSE: + kbd_cursor_left( state ); + break; + + case KBD_MODE_SIDEWAYS: +#ifdef KBD_MODES + if ( pm->line_edit ) + kbd_cursor_left( state ); + else +#endif + kbd_picker_left( state, pm ); + break; + + case KBD_MODE_STANDARD: + default: + kbd_up( state, pm ); + } + state->prev_button = ACTION_KBD_SCROLL_BACK; +} +#endif + +static void kbd_picker_right( struct edit_state *state, + struct keyboard_parameters *pm ) +{ + (void) state; + if (++pm->x >= pm->max_chars) + { +#ifdef HAVE_SCROLLWHEEL + switch ( state->keyboard_mode ) + { + case KBD_MODE_ROWCOL: + pm->x = pm->max_chars-1; + state->row = true; + return; + case KBD_MODE_SCROLL_1D: + kbd_down( state, pm ); + case KBD_MODE_KEEP_ROLLIN: + pm->x = 0; + return; + /* FIXME: */ + #ifdef HAVE_KBD_MODES + case KBD_MODE_SIDEWAYS: + #endif + default: + break; + } +#endif + if (++pm->page >= pm->pages) + pm->page = 0; + pm->x = 0; + } + kbd_spellchar( get_kbd_ch(pm) ); +} + +static void kbd_right( struct edit_state *state, + struct keyboard_parameters *pm ) +{ +#ifdef HAVE_SCROLLWHEEL + switch ( state->keyboard_mode ) + { + case KBD_MODE_STANDARD: +#ifdef KBD_MODES + if ( pm->line_edit ) + kbd_cursor_right( state ); + else +#endif /* KBD_MODES */ + kbd_picker_right( state, pm ); + return; + + case KBD_MODE_SIDEWAYS: + kbd_down( state, pm ); + return; + + case KBD_MODE_KEEP_ROLLIN: + case KBD_MODE_SCROLL_1D: + case KBD_MODE_ROWCOL: + case KBD_MODE_MORSE: + kbd_cursor_right( state ); + return; + default: + break; + } +#else /* (not) HAVE_SCROLLWHEEL */ + +#ifdef KBD_MODES + if ( pm->line_edit ) + kbd_cursor_right( state ); + else +#endif /* KBD_MODES */ + + kbd_picker_right( state, pm ); +#endif /* HAVE_SCROLLWHEEL */ +} + +static void kbd_picker_left( struct edit_state *state, + struct keyboard_parameters *pm ) +{ + (void) state; + if (--pm->x < 0) + { +#ifdef HAVE_SCROLLWHEEL + switch ( state->keyboard_mode ) + { + case KBD_MODE_ROWCOL: + pm->x = 0; + state->row = true; + return; + case KBD_MODE_SCROLL_1D: + kbd_up( state, pm ); + case KBD_MODE_KEEP_ROLLIN: + pm->x = pm->max_chars - 1; + return; + default: + break; + } +#endif + + if (--pm->page < 0) + pm->page = pm->pages - 1; + pm->x = pm->max_chars - 1; + } + kbd_spellchar( get_kbd_ch(pm) ); +} + +static void kbd_left( struct edit_state *state, + struct keyboard_parameters *pm ) +{ +#ifdef HAVE_SCROLLWHEEL + switch ( state->keyboard_mode ) + { + case KBD_MODE_STANDARD: +#ifdef KBD_MODES + if ( pm->line_edit ) + kbd_cursor_left( state ); + else +#endif + kbd_picker_left( state, pm ); + return; + + case KBD_MODE_SIDEWAYS: + kbd_up( state, pm ); + return; + case KBD_MODE_KEEP_ROLLIN: + case KBD_MODE_SCROLL_1D: + case KBD_MODE_ROWCOL: + case KBD_MODE_MORSE: + kbd_cursor_left( state ); + return; + default: + return; + } +#else /* (not) HAVE_SCROLLWHEEL */ + +#ifdef KBD_MODES + if ( pm->line_edit ) + kbd_cursor_left( state ); + else +#endif /* KBD_MODES */ + + kbd_picker_left( state, pm ); +#endif /* HAVE_SCROLLWHEEL */ + +} + +static void kbd_down( struct edit_state *state, + struct keyboard_parameters *pm ) +{ +#ifdef HAVE_SCROLLWHEEL + if ( state->keyboard_mode == KBD_MODE_KEEP_ROLLIN || + state->keyboard_mode == KBD_MODE_SCROLL_1D || + state->keyboard_mode == KBD_MODE_ROWCOL ) + { + if (++pm->y >= pm->lines) + { + if (++pm->page >= pm->pages) + pm->page = 0; + pm->y = 0; + } + return; + } +#endif +#ifdef HAVE_MORSE_INPUT + if (state->keyboard_mode == KBD_MODE_MORSE) + { +#ifdef KBD_MODES + pm->line_edit = !pm->line_edit; + if (pm->line_edit) + say_edit(); +#endif + return; + } +#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(); + } + if (!pm->line_edit) + { + kbd_spellchar( get_kbd_ch(pm) ); + } + return; +#else /* KBD_MODES */ + + if (++pm->y >= pm->lines) + pm->y = 0; + + kbd_spellchar( get_kbd_ch(pm) ); +#endif +} + +static void kbd_up ( struct edit_state *state, + struct keyboard_parameters *pm ) +{ +#ifdef HAVE_SCROLLWHEEL + if ( state->keyboard_mode == KBD_MODE_KEEP_ROLLIN || + state->keyboard_mode == KBD_MODE_SCROLL_1D || + state->keyboard_mode == KBD_MODE_ROWCOL ) + { + if (--pm->y < 0) + { + pm->y = pm->lines - 1; + if (--pm->page < 0) + pm->page = pm->pages - 1; + } + return; + } +#endif +#ifdef HAVE_MORSE_INPUT + if (state->keyboard_mode == KBD_MODE_MORSE) + { +#ifdef KBD_MODES + pm->line_edit = !pm->line_edit; + if (pm->line_edit) + say_edit(); +#endif + return; + } +#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(); + } + if (!pm->line_edit) + kbd_spellchar( get_kbd_ch(pm) ); +#else /* KBD_MODES */ + + if (--pm->y < 0) + pm->y = pm->lines - 1; + + kbd_spellchar( get_kbd_ch(pm) ); +#endif +} + +static void kbd_cursor_right( struct edit_state *state ) +{ + state->hangul = false; + + if (state->editpos < state->len_utf8) + { + int c = utf8seek(state->text, ++state->editpos); + kbd_spellchar(state->text[c]); + return; + } +#ifdef PRED_TEXT + if( state->pred_word[0] ) + { + kbd_insert_predicted( state ); + return; + } +#endif +#if CONFIG_CODEC == SWCODEC + if (global_settings.talk_menu) + pcmbuf_beep(1000, 150, 1500); +#endif +} + +static void kbd_cursor_left( struct edit_state *state ) +{ + state->hangul = false; + + 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 +} + +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); + } + + if (global_settings.talk_menu) /* voice UI? */ + talk_spell(state->text, false); /* speak revised text */ +} + +static void kbd_insert_current_char( struct edit_state *state, + struct keyboard_parameters *pm ) +{ + + /* inserts the selected char */ + /* find input char */ + unsigned short ch; + 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 */ +} + +static void kbd_select( struct edit_state *state, + struct keyboard_parameters *pm ) +{ +#ifdef HAVE_SCROLLWHEEL + if ( state->keyboard_mode == KBD_MODE_ROWCOL ) + { + if ( state->row ) + { + state->row = false; + return; + } + else + { + kbd_insert_current_char( state, pm ); + return; + } + } +#endif /* HAVE_SCROLLWHEEL */ +#ifdef KBD_MODES + if ( pm->line_edit ) + { + kbd_backspace( state ); + return; + } +#endif +#ifdef HAVE_MORSE_INPUT + if (state->keyboard_mode == KBD_MODE_MORSE) + { + state->morse_tick = current_tick; + + if (!state->morse_reading) + { + logf("Morse char start:\n"); + state->morse_reading = true; + state->morse_code = 1; + } + } + else +#endif /* HAVE_MORSE_INPUT */ + kbd_insert_current_char( state, pm ); +} + +#ifdef HAVE_MORSE_INPUT +static void kbd_morse_select( struct edit_state *state ) +{ + if (state->keyboard_mode == KBD_MODE_MORSE && state->morse_reading) + { + state->morse_code <<= 1; + if ((current_tick - state->morse_tick) > HZ/5) + state->morse_code |= 0x01; + } +} +#endif /* HAVE_MORSE_INPUT */ + +static void kbd_none( struct edit_state *state ) +{ + (void) state; +#ifdef HAVE_MORSE_INPUT + if (state->morse_reading) + { + int j; + logf("Morse: 0x%02x", state->morse_code); + state->morse_reading = false; + + for (j = 0; morse_alphabets[j] != '\0'; j++) + { + if (morse_codes[j] == state->morse_code) + break; + } + + if (morse_alphabets[j] == '\0') + { + logf("Morse code not found"); + return; + } + + /* turn off hangul input */ + state->hangul = false; + 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 */ +} + int kbd_input(char* text, int buflen) { bool done = false; @@ -320,7 +995,6 @@ #endif struct edit_state state; int l; /* screen loop variable */ - unsigned short ch; int ret = 0; /* assume success */ FOR_NB_SCREENS(l) { @@ -339,15 +1013,23 @@ /* initialize state */ state.text = text; state.buflen = buflen; +#ifdef HAVE_SCROLLWHEEL + state.prev_button = BUTTON_NONE; + state.row = true; +#endif +#ifdef PRED_TEXT + state.pred_word[0] = 0; +#endif /* Initial edit position is after last character */ state.editpos = utf8length(state.text); state.cur_blink = true; +#if defined (HAVE_MORSE_INPUT) || defined (HAVE_SCROLLWHEEL) + state.keyboard_mode = global_settings.keyboard_mode; +#endif #ifdef HAVE_MORSE_INPUT - state.morse_mode = global_settings.morse_input; state.morse_reading = false; #endif state.hangul = false; - state.changed = 0; if (!kbd_loaded) { @@ -412,6 +1094,12 @@ struct keyboard_parameters *pm = ¶m[l]; struct screen *sc = &screens[l]; kbd_calc_params(pm, sc, &state); +#ifdef HAVE_SCROLLWHEEL + pm->x = pm->y = pm->page = 0; +#ifdef KBD_MODES + pm->line_edit = false; +#endif +#endif } if (global_settings.talk_menu) /* voice UI? */ @@ -442,8 +1130,14 @@ sc->clear_display(); kbd_draw_picker(pm, sc, &state); kbd_draw_edit_line(pm, sc, &state); +#ifdef PRED_TEXT + //if ( state.keyboard_mode == KBD_MODE_KEEP_ROLLIN ) + kbd_draw_predicted(pm, sc, &state); +#endif } + state.cur_blink = !state.cur_blink; + #ifdef HAVE_BUTTONBAR /* draw the button bar */ gui_buttonbar_set(&buttonbar, "Shift", "OK", "Del"); @@ -453,42 +1147,19 @@ FOR_NB_SCREENS(l) screens[l].update(); - state.cur_blink = !state.cur_blink; - - button = get_action( #ifdef HAVE_MORSE_INPUT - state.morse_mode? CONTEXT_MORSE_INPUT: + button = get_action( state.keyboard_mode == KBD_MODE_MORSE ? + CONTEXT_MORSE_INPUT: CONTEXT_KEYBOARD, HZ/2 ); +#else + button = get_action( CONTEXT_KEYBOARD, HZ/2 ); #endif - CONTEXT_KEYBOARD, HZ/2); + #if NB_SCREENS > 1 button_screen = (get_action_statuscode(NULL) & ACTION_REMOTE) ? 1 : 0; #endif pm = ¶m[button_screen]; sc = &screens[button_screen]; -#if defined(KBD_MODES) || defined(HAVE_MORSE_INPUT) - /* Remap some buttons to allow to move - * cursor in line edit mode and morse mode. */ -#if defined(KBD_MODES) && defined(HAVE_MORSE_INPUT) - if (pm->line_edit || state.morse_mode) -#elif defined(KBD_MODES) - if (pm->line_edit) -#else /* defined(HAVE_MORSE_INPUT) */ - if (state.morse_mode) -#endif - { - if (button == ACTION_KBD_LEFT) - button = ACTION_KBD_CURSOR_LEFT; - if (button == ACTION_KBD_RIGHT) - button = ACTION_KBD_CURSOR_RIGHT; -#ifdef KBD_MODES - /* select doubles as backspace in line_edit */ - if (pm->line_edit && button == ACTION_KBD_SELECT) - button = ACTION_KBD_BACKSPACE; -#endif - } -#endif /* defined(KBD_MODES) || defined(HAVE_MORSE_INPUT) */ - switch ( button ) { case ACTION_KBD_DONE: @@ -501,134 +1172,64 @@ ret = -1; done = true; break; - +#ifdef HAVE_SCROLLWHEEL + case ACTION_KBD_SCROLL_FWD: + kbd_scroll_fwd( &state, pm ); + break; + + case ACTION_KBD_SCROLL_BACK: + kbd_scroll_back( &state, pm ); + break; +#endif case ACTION_KBD_PAGE_FLIP: -#ifdef HAVE_MORSE_INPUT - if (state.morse_mode) - break; -#endif - if (++pm->page >= pm->pages) - pm->page = 0; + kbd_page_flip( &state, pm ); + break; - state.changed = CHANGED_PICKER; +#ifdef KBD_TOGGLE_INPUT + case ACTION_KBD_MORSE_INPUT: + kbd_switch_mode( &state ); break; +#endif +#ifdef HAVE_MORSE_INPUT + case ACTION_KBD_MORSE_SELECT: + kbd_morse_select( &state ); + break; +#endif /* HAVE_MORSE_INPUT */ case ACTION_KBD_RIGHT: - if (++pm->x >= pm->max_chars) - { -#ifndef KBD_PAGE_FLIP - /* no dedicated flip key - flip page on wrap */ - if (++pm->page >= pm->pages) - pm->page = 0; -#endif - pm->x = 0; - } - - state.changed = CHANGED_PICKER; + kbd_right( &state, pm ); break; case ACTION_KBD_LEFT: - if (--pm->x < 0) - { -#ifndef KBD_PAGE_FLIP - /* no dedicated flip key - flip page on wrap */ - if (--pm->page < 0) - pm->page = pm->pages - 1; -#endif - pm->x = pm->max_chars - 1; - } - - state.changed = CHANGED_PICKER; + kbd_left( &state, pm ); break; case ACTION_KBD_DOWN: - kbd_move_picker_vertical(pm, &state, 1); + kbd_down( &state, pm ); break; case ACTION_KBD_UP: - kbd_move_picker_vertical(pm, &state, -1); + kbd_up( &state, pm ); break; -#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 = ¶m[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: - if (state.morse_mode && state.morse_reading) - { - state.morse_code <<= 1; - if ((current_tick - state.morse_tick) > HZ/5) - state.morse_code |= 0x01; - } - break; -#endif /* HAVE_MORSE_INPUT */ - case ACTION_KBD_SELECT: -#ifdef HAVE_MORSE_INPUT - if (state.morse_mode) - { - state.morse_tick = current_tick; - - if (!state.morse_reading) - { - state.morse_reading = true; - state.morse_code = 1; - } - } - else -#endif /* HAVE_MORSE_INPUT */ - kbd_insert_selected(pm, &state); + kbd_select( &state, pm ); break; case ACTION_KBD_BACKSPACE: - kbd_backspace(&state); + kbd_backspace( &state ); break; case ACTION_KBD_CURSOR_RIGHT: - kbd_move_cursor(&state, 1); + kbd_cursor_right( &state ); break; case ACTION_KBD_CURSOR_LEFT: - kbd_move_cursor(&state, -1); + kbd_cursor_left( &state ); break; case ACTION_NONE: -#ifdef HAVE_MORSE_INPUT - if (state.morse_reading) - { - int j; - logf("Morse: 0x%02x", state.morse_code); - state.morse_reading = false; - - for (j = 0; morse_alphabets[j] != '\0'; j++) - { - if (morse_codes[j] == state.morse_code) - break ; - } - - if (morse_alphabets[j] == '\0') - { - logf("Morse code not found"); - break ; - } - - /* turn off hangul input */ - state.hangul = false; - kbd_inschar(&state, morse_alphabets[j]); - } -#endif /* HAVE_MORSE_INPUT */ + kbd_none( &state ); break; default: @@ -640,39 +1241,10 @@ break; } /* end switch */ - if (button != ACTION_NONE) { 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 @@ -681,11 +1253,10 @@ if (ret < 0) splash(HZ/2, ID2P(LANG_CANCEL)); - -#if defined(HAVE_MORSE_INPUT) && defined(KBD_TOGGLE_INPUT) - if (global_settings.morse_input != state.morse_mode) +#if defined(HAVE_MORSE_INPUT) || defined(HAVE_SCROLLWHEEL) + if (global_settings.keyboard_mode != state.keyboard_mode) { - global_settings.morse_input = state.morse_mode; + global_settings.keyboard_mode = state.keyboard_mode; settings_save(); } #endif /* HAVE_MORSE_INPUT && KBD_TOGGLE_INPUT */ @@ -804,8 +1375,12 @@ /* calculate pm->pages and pm->lines */ sc_h = sc->getheight(); +#ifdef PRED_TEXT + /* reserve a line for predicted text */ + sc_h -= pm->font_h; +#endif pm->lines = (sc_h - BUTTONBAR_HEIGHT) / pm->font_h - 1; - + if (pm->default_lines && pm->lines > pm->default_lines) pm->lines = pm->default_lines; @@ -830,7 +1405,7 @@ #ifdef HAVE_MORSE_INPUT pm->old_main_y = sc_h - pm->font_h - BUTTONBAR_HEIGHT; - if (state->morse_mode) + if (state->keyboard_mode == KBD_MODE_MORSE) { int y = pm->main_y; pm->main_y = pm->old_main_y; @@ -844,7 +1419,7 @@ { char outline[8]; #ifdef HAVE_MORSE_INPUT - if (state->morse_mode) + if (state->keyboard_mode == KBD_MODE_MORSE) { const int w = 6, h = 8; /* sysfixed font width, height */ int i, j, x, y; @@ -926,6 +1501,20 @@ { /* highlight the key that has focus */ sc->set_drawmode(DRMODE_COMPLEMENT); +#ifdef HAVE_SCROLLWHEEL + if ( (state->keyboard_mode == KBD_MODE_ROWCOL && state->row) || + (state->keyboard_mode == KBD_MODE_KEEP_ROLLIN && + state->prev_button != ACTION_KBD_SCROLL_FWD )) +/* define this if you want selected row inversed instead of underlined */ +#ifdef KBD_INVERSE_ROW + sc->fillrect(0,pm->font_h*pm->y, + pm->font_w*pm->max_chars, pm->font_h); +#else /* underline current row */ + sc->hline(pm->font_w, pm->font_w*(pm->max_chars-1), + pm->font_h*(pm->y+1)); +#endif + else +#endif /* HAVE_SCROLLWHEEL */ sc->fillrect(pm->font_w*pm->x, pm->font_h*pm->y, pm->font_w, pm->font_h); sc->set_drawmode(DRMODE_SOLID); @@ -1019,152 +1608,151 @@ #endif } -/* inserts the selected char */ -static void kbd_insert_selected(struct keyboard_parameters *pm, - struct edit_state *state) +#ifdef PRED_TEXT +/* This is a very simple dictionary based text predictor. + The dictionary file is one word per line (\n terminated.) + at /.rockbox/pred_dict.txt. + + The first word in the file that matches the letters input + will be offered for completion. The dictionary should be + ordered with most common words first for better matching. + Dictionary words can be phrases containing spaces but the + code will only match the first phrase with the same first + word. + + Needs to reboot to reload dictionary. + +*/ +#include "ctype.h" + +static void kbd_draw_predicted(struct keyboard_parameters *pm, + struct screen *sc, struct edit_state *state) { - /* find input char */ - unsigned short ch = get_kbd_ch(pm); + int i, left = -1, length; + static int last_editpos = 0; + static bool dict_loaded = false; + static char dictionary[MAX_DICT]; + char *partial, *dict; - /* check for hangul input */ - if (ch >= 0x3131 && ch <= 0x3163) + /* be lazy if edit cursor hasn't moved */ + if ( state->editpos == last_editpos ) { - unsigned short tmp; - - if (!state->hangul) - { - state->hlead = state->hvowel = state->htail = 0; - state->hangul = true; + sc->putsxy(0, pm->main_y+pm->font_h, state->pred_word); + return; + } + else + last_editpos = state->editpos; + + /* Start with nothing predicted */ + state->pred_word[0] = 0; + + /* Load the dictionary */ + if ( ! dict_loaded ) + { + int fd = open_utf8("/.rockbox/pred_dict.txt", O_RDONLY|O_BINARY); + if (fd < 0) + return; /* File Open Error */ + length = read(fd, dictionary, MAX_DICT); + if (length < 0) + return; /* Read Error */ + else { + dictionary[length] = 0; + dict_loaded = true; } + } - if (!state->hvowel) + dict = dictionary; /* Points to current dictionary word */ + i = state->editpos; + + if ( state->editpos != state->len_utf8 ) + return; + + while( --i >= 0 ) /* find left of word */ + if ( state->text[utf8seek(state->text,i)] != ' ' ) + left = i; + else + break; + + if ( left == -1 ) /* whitespace */ + return; + + /* search for matching word */ + length = utf8seek(state->text,state->editpos) - + utf8seek(state->text,left); + + partial = &state->text[utf8seek(state->text,left)]; + for ( i = 0; i <= length ; ) + { + if ( dict[i] == '\n' ) { - state->hvowel = ch; + /* already typed out this whole word, look for another */ + dict += i +1; + i = 0; + continue; } - else if (!state->htail) + if ( dict[i] == 0 ) { - state->htail = ch; + /* end of dictionary, give up */ + return; } - else + if ( partial[i] == dict[i] ) { - /* 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; - } + i++; + continue; } - - /* combine into hangul */ - tmp = hangul_join(state->hlead, state->hvowel, state->htail); - - if (tmp != 0xfffd) + /* Case fuzz on first letter */ + if ( !i && tolower(partial[i]) == tolower(dict[i]) ) { - kbd_delchar(state); - ch = tmp; + i++; + continue; } - else + if ( i == length ) /* got a match */ { - state->hvowel = state->htail = 0; - state->hlead = ch; + break; } + /* mismatch, reset to next word */ + while ( dict[++i] != '\n' ) + if ( dict[i] == 0 ) + return; + dict += i + 1; + i = 0; } - else - { - state->hangul = false; - } - /* insert char */ - kbd_inschar(state, ch); -} + /* get length of dictionary word in bytes */ + for ( i = 0 ; dict[i] != '\n' && dict[i] != 0 ; + i += utf8seek( dict,1) ) + if ( i >= MAX_DICT_WORD ) + { + i = MAX_DICT_WORD; + break; + } + /* copy */ + state->pred_word[i] = 0; + while ( --i >= 0 ) + state->pred_word[i] = dict[i]; + state->pred_input_len = length; -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); - } + sc->putsxy(0, pm->main_y+pm->font_h, state->pred_word); + } -static void kbd_move_cursor(struct edit_state *state, int dir) +static void kbd_insert_predicted(struct edit_state *state) { - state->hangul = false; - state->editpos += dir; - - if (state->editpos >= 0 && state->editpos <= state->len_utf8) + int i; + + i = utf8seek(state->text,state->editpos); + if ( i + (int)strlen(state->pred_word) - + state->pred_input_len >= state->buflen ) + return; + + if( state->pred_word[0] ) { - state->changed = CHANGED_CURSOR; - } - else - { - state->editpos -= dir; -#if CONFIG_CODEC == SWCODEC - if (global_settings.talk_menu) - pcmbuf_beep(1000, 150, 1500); -#endif - } -} + strcpy( i + state->text, + state->pred_word + state->pred_input_len ); -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 + while ( state->text[utf8seek(state->text,state->editpos )] != 0 ) + state->editpos++; 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 -} Index: apps/lang/english.lang =================================================================== --- apps/lang/english.lang (revision 24931) +++ apps/lang/english.lang (working copy) @@ -13349,3 +13349,101 @@ remote: "Remote Screen" + + id: LANG_KBD_MODE + desc: in settings.general.system + user: core + + *: "Keyboard Mode" + + + *: "Keyboard Mode" + + + *: "Keyboard Mode" + + + + id: LANG_KBD_MODE_STANDARD + desc: in settings.general.system + user: core + + *: "Standard" + + + *: "Standard" + + + *: "Standard" + + + + id: LANG_KBD_MODE_SIDEWAYS + desc: in settings.general.system + user: core + + *: "Sideways" + + + *: "Sideways" + + + *: "Sideways" + + + + id: LANG_KBD_MODE_MORSE + desc: in settings.general.system + user: core + + *: "Morse" + + + *: "Morse" + + + *: "Morse" + + + + id: LANG_KBD_MODE_KEEP_ROLLIN + desc: in settings.general.system + user: core + + *: "Keep Rollin" + + + *: "Keep Rollin" + + + *: "Keep Rollin" + + + + id: LANG_KBD_MODE_SCROLL_1D + desc: in settings.general.system + user: core + + *: "Scroll 1D" + + + *: "Scroll 1D" + + + *: "Scroll won dee" + + + + id: LANG_KBD_MODE_ROW_COL + desc: in settings.general.system + user: core + + *: "Row-Column" + + + *: "Row-Column" + + + *: "Row Colum" + + Index: apps/settings.h =================================================================== --- apps/settings.h (revision 24931) +++ apps/settings.h (working copy) @@ -806,8 +806,8 @@ int compressor_release_time; #endif -#ifdef HAVE_MORSE_INPUT - bool morse_input; /* text input method setting */ +#if defined(HAVE_MORSE_INPUT) || defined(HAVE_SCROLLWHEEL) + int keyboard_mode; #endif }; Index: apps/menus/settings_menu.c =================================================================== --- apps/menus/settings_menu.c (revision 24931) +++ apps/menus/settings_menu.c (working copy) @@ -257,8 +257,8 @@ MENUITEM_SETTING(usb_keypad_mode, &global_settings.usb_keypad_mode, NULL); #endif -#ifdef HAVE_MORSE_INPUT -MENUITEM_SETTING(morse_input, &global_settings.morse_input, NULL); +#if defined(HAVE_MORSE_INPUT) || defined(HAVE_SCROLLWHEEL) +MENUITEM_SETTING(keyboard_mode, &global_settings.keyboard_mode, NULL); #endif #ifdef HAVE_BUTTON_LIGHT @@ -284,8 +284,8 @@ #endif &poweroff, &limits_menu, -#ifdef HAVE_MORSE_INPUT - &morse_input, +#if defined(HAVE_MORSE_INPUT) || defined(HAVE_SCROLLWHEEL) + &keyboard_mode, #endif #if CONFIG_CODEC == MAS3507D &line_in, Index: apps/settings_list.c =================================================================== --- apps/settings_list.c (revision 24931) +++ apps/settings_list.c (working copy) @@ -1646,9 +1646,26 @@ #endif #endif -#ifdef HAVE_MORSE_INPUT - OFFON_SETTING(0, morse_input, LANG_MORSE_INPUT, false, "morse input", NULL), +#if defined (HAVE_SCROLLWHEEL) && defined (HAVE_MORSE_INPUT) + CHOICE_SETTING(0, keyboard_mode, LANG_KBD_MODE, 0, "keyboard mode", + "Standard,Sideways,Keep_Rollin,Scroll_1D,Row_Column,Morse", NULL, 6, + ID2P(LANG_KBD_MODE_STANDARD), ID2P(LANG_KBD_MODE_SIDEWAYS), + ID2P(LANG_KBD_MODE_KEEP_ROLLIN), ID2P(LANG_KBD_MODE_SCROLL_1D), + ID2P(LANG_KBD_MODE_ROW_COL), ID2P(LANG_KBD_MODE_MORSE) ) +#else +#ifdef HAVE_MORSE_INPUT /* No scrollwheel */ + CHOICE_SETTING(0, keyboard_mode, LANG_KBD_MODE, 0, "keyboard mode", + "Standard,Morse", NULL, 2, + ID2P(LANG_KBD_MODE_STANDARD), ID2P(LANG_KBD_MODE_MORSE)), #endif +#ifdef HAVE_SCROLLWHEEL /* No Morse */ + CHOICE_SETTING(0, keyboard_mode, LANG_KBD_MODE, 0, "keyboard mode", + "Standard,Sideways,Keep_Rollin,Scroll_1D,Row_Column", NULL, 5, + ID2P(LANG_KBD_MODE_STANDARD), ID2P(LANG_KBD_MODE_SIDEWAYS), + ID2P(LANG_KBD_MODE_KEEP_ROLLIN), ID2P(LANG_KBD_MODE_SCROLL_1D), + ID2P(LANG_KBD_MODE_ROW_COL)), +#endif +#endif }; const int nb_settings = sizeof(settings)/sizeof(*settings); Index: apps/keymaps/keymap-e200.c =================================================================== --- apps/keymaps/keymap-e200.c (revision 24931) +++ apps/keymaps/keymap-e200.c (working copy) @@ -256,10 +256,10 @@ { ACTION_KBD_CURSOR_RIGHT, BUTTON_REC|BUTTON_RIGHT, BUTTON_NONE }, { ACTION_KBD_CURSOR_RIGHT, BUTTON_REC|BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_SCROLL_BACK, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_SCROLL_FWD, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_SCROLL_BACK, BUTTON_SCROLL_BACK, BUTTON_NONE }, + { ACTION_KBD_SCROLL_BACK, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_SCROLL_FWD, BUTTON_SCROLL_FWD, BUTTON_NONE }, + { ACTION_KBD_SCROLL_FWD, BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_KBD_PAGE_FLIP, BUTTON_REC|BUTTON_SELECT, BUTTON_REC }, { ACTION_KBD_BACKSPACE, BUTTON_DOWN, BUTTON_NONE }, { ACTION_KBD_BACKSPACE, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, Index: apps/keymaps/keymap-ipod.c =================================================================== --- apps/keymaps/keymap-ipod.c (revision 24931) +++ apps/keymaps/keymap-ipod.c (working copy) @@ -161,12 +161,13 @@ { ACTION_KBD_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, { ACTION_KBD_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_KBD_SELECT, BUTTON_SELECT, BUTTON_NONE }, - { ACTION_KBD_DONE, BUTTON_PLAY, BUTTON_NONE }, - { ACTION_KBD_ABORT, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - { ACTION_KBD_UP, BUTTON_SCROLL_BACK, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_SCROLL_FWD, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_DONE, BUTTON_PLAY|BUTTON_REL, BUTTON_NONE }, + { ACTION_KBD_ABORT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_SCROLL_BACK, BUTTON_SCROLL_BACK, BUTTON_NONE }, + { ACTION_KBD_SCROLL_BACK, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_SCROLL_FWD, BUTTON_SCROLL_FWD, BUTTON_NONE }, + { ACTION_KBD_SCROLL_FWD, BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_BACKSPACE, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, { ACTION_KBD_MORSE_INPUT, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, { ACTION_KBD_MORSE_SELECT, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE }, LAST_ITEM_IN_LIST Index: apps/keymaps/keymap-fuze.c =================================================================== --- apps/keymaps/keymap-fuze.c (revision 24931) +++ apps/keymaps/keymap-fuze.c (working copy) @@ -257,13 +257,13 @@ { ACTION_KBD_CURSOR_RIGHT, BUTTON_HOME|BUTTON_RIGHT, BUTTON_NONE }, { ACTION_KBD_CURSOR_RIGHT, BUTTON_HOME|BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_SCROLL_BACK, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_SCROLL_FWD, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_SCROLL_BACK, BUTTON_SCROLL_BACK, BUTTON_NONE }, + { ACTION_KBD_SCROLL_BACK, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_SCROLL_FWD, BUTTON_SCROLL_FWD, BUTTON_NONE }, + { ACTION_KBD_SCROLL_FWD, BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_KBD_PAGE_FLIP, BUTTON_HOME|BUTTON_SELECT, BUTTON_HOME }, - { ACTION_KBD_BACKSPACE, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_KBD_BACKSPACE, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_BACKSPACE, BUTTON_DOWN|BUTTON_REL, BUTTON_DOWN }, + { ACTION_KBD_MORSE_INPUT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_DOWN }, { ACTION_KBD_SELECT, BUTTON_SELECT, BUTTON_NONE }, { ACTION_KBD_DONE, BUTTON_UP, BUTTON_NONE }, { ACTION_KBD_ABORT, BUTTON_HOME|BUTTON_REPEAT, BUTTON_NONE },