Index: /mnt/storage/rockbox/apps/action.h =================================================================== --- /mnt/storage/rockbox/apps/action.h (revision 24623) +++ /mnt/storage/rockbox/apps/action.h (working copy) @@ -236,6 +236,8 @@ ACTION_KBD_DOWN, ACTION_KBD_MORSE_INPUT, ACTION_KBD_MORSE_SELECT, + ACTION_KBD_SCROLL_BACK, + ACTION_KBD_SCROLL_FWD, #ifdef HAVE_TOUCHSCREEN /* the following are helper actions for touchscreen targets, Index: /mnt/storage/rockbox/apps/recorder/keyboard.c =================================================================== --- /mnt/storage/rockbox/apps/recorder/keyboard.c (revision 24623) +++ /mnt/storage/rockbox/apps/recorder/keyboard.c (working copy) @@ -39,6 +39,7 @@ #include "file.h" #include "splash.h" + #ifndef O_BINARY #define O_BINARY 0 #endif @@ -54,8 +55,7 @@ || (CONFIG_KEYPAD == IRIVER_IFP7XX_PAD) \ || (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) \ || (CONFIG_KEYPAD == IAUDIO_M3_PAD) \ - || (CONFIG_KEYPAD == IRIVER_H10_PAD) \ - || (CONFIG_KEYPAD == PBELL_VIBE500_PAD) + || (CONFIG_KEYPAD == IRIVER_H10_PAD) /* no key combos to move the cursor if not in line edit mode */ #define KBD_MODES /* uses 2 modes, picker and line edit */ @@ -86,12 +86,19 @@ || (CONFIG_KEYPAD == MROBE100_PAD) \ || (CONFIG_KEYPAD == SANSA_E200_PAD) \ || (CONFIG_KEYPAD == PHILIPS_HDD1630_PAD) \ - || (CONFIG_KEYPAD == PHILIPS_SA9200_PAD) \ - || (CONFIG_KEYPAD == PBELL_VIBE500_PAD) + || (CONFIG_KEYPAD == PHILIPS_SA9200_PAD) /* certain key combos toggle input mode between keyboard input and Morse input */ #define KBD_TOGGLE_INPUT #endif +#ifdef HAVE_SCROLLWHEEL +#define KEEP_ROLLIN +#define KBD_CURSOR_KEYS +#undef KBD_MODES +#undef KBD_TOGGLE_INPUT +#define MAX_DICT 85000 +#endif + struct keyboard_parameters { unsigned short kbd_buf[KBD_BUF_SIZE]; @@ -135,6 +142,11 @@ unsigned char morse_code; int morse_tick; #endif +#ifdef KEEP_ROLLIN + int prev_button; + char predicted_text[20]; + int predicted_len; +#endif }; static struct keyboard_parameters kbd_param[NB_SCREENS]; @@ -290,7 +302,10 @@ 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 KEEP_ROLLIN +static void kbd_draw_predicted(struct keyboard_parameters *pm, + struct screen *sc, struct edit_state *state); +#endif int kbd_input(char* text, int buflen) { bool done = false; @@ -301,6 +316,9 @@ struct keyboard_parameters * const param = kbd_param; #endif struct edit_state state; +#ifdef KEEP_ROLLIN + state.prev_button = 0; +#endif int l; /* screen loop variable */ unsigned short ch; int ret = 0; /* assume success */ @@ -421,6 +439,9 @@ sc->clear_display(); kbd_draw_picker(pm, sc, &state); kbd_draw_edit_line(pm, sc, &state); +#ifdef KEEP_ROLLIN + kbd_draw_predicted(pm, sc, &state); +#endif } state.cur_blink = !state.cur_blink; @@ -476,6 +497,27 @@ done = true; break; +#ifdef KEEP_ROLLIN + case ACTION_KBD_SCROLL_FWD: +#ifdef HAVE_MORSE_INPUT + if( state.morse_mode ) + break; +#endif + /* move cursor right */ + if (state.prev_button == ACTION_KBD_SCROLL_FWD && + ++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; + } + ch = get_kbd_ch(pm); + kbd_spellchar(ch); + state.prev_button = ACTION_KBD_SCROLL_FWD; + break; +#endif + case ACTION_KBD_ABORT: ret = -1; done = true; @@ -620,7 +662,22 @@ } break; #endif /* HAVE_MORSE_INPUT */ - +#ifdef KEEP_ROLLIN + case ACTION_KBD_SCROLL_BACK: +#ifdef HAVE_MORSE_INPUT + if( state.morse_mode ) + break; +#endif + /* next line down, wrap to top */ + if ( state.prev_button != ACTION_KBD_SCROLL_FWD ) { + if (++pm->y >= pm->lines) + pm->y=0; + state.prev_button = ACTION_KBD_SCROLL_BACK; + break; + } + /* no break here because we insert the current */ + /* character if scrolling backwards after forwards */ +#endif case ACTION_KBD_SELECT: #ifdef HAVE_MORSE_INPUT if (state.morse_mode) @@ -632,8 +689,18 @@ state.morse_reading = true; state.morse_code = 1; } + break; } - else + +#ifdef KEEP_ROLLIN + if( state.predicted_text[0] && button == ACTION_KBD_SELECT) { + strcpy(utf8seek(state.text,state.editpos)+state.text-state.predicted_len, state.predicted_text); + while ( state.text[utf8seek(state.text,state.editpos )] != 0 ) + state.editpos++; + //pm->x = pm->y = state.prev_button = 0; + break; + } +#endif #endif /* HAVE_MORSE_INPUT */ { /* inserts the selected char */ @@ -708,6 +775,10 @@ if (global_settings.talk_menu) /* voice UI? */ talk_spell(state.text, false); /* speak revised text */ } +#ifdef KEEP_ROLLIN + if ( button != ACTION_KBD_SELECT ) + pm->x = pm->y = state.prev_button = 0; +#endif break; case ACTION_KBD_BACKSPACE: @@ -1055,10 +1126,15 @@ if (!pm->line_edit) #endif { + sc->set_drawmode(DRMODE_COMPLEMENT); +#ifdef KEEP_ROLLIN + if ( state->prev_button != ACTION_KBD_SCROLL_FWD ) + /* Underline when picking rows */ + sc->hline(pm->font_w, pm->font_w*(pm->max_chars-1), pm->font_h*(pm->y+1)); + else +#endif /* highlight the key that has focus */ - sc->set_drawmode(DRMODE_COMPLEMENT); - sc->fillrect(pm->font_w*pm->x, pm->font_h*pm->y, - pm->font_w, pm->font_h); + sc->fillrect(pm->font_w*pm->x, pm->font_h*pm->y, pm->font_w, pm->font_h); sc->set_drawmode(DRMODE_SOLID); } } @@ -1149,3 +1225,84 @@ } #endif } + +#ifdef KEEP_ROLLIN +/* This is a very simple dictionary based text predictor. + The dictionary file is one word per line (\n terminated.) + The first word in the file that matches the letters input + will be offered for completion. The dictionary need not + be in alphabetical order. + + Needs to reboot to reload dictionary. +*/ + +static void kbd_draw_predicted(struct keyboard_parameters *pm, + struct screen *sc, struct edit_state *state) +{ + int i, left = -1, length; + static bool dict_loaded = false; + static char dictionary[MAX_DICT]; + char *partial, *dict; + + /* 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; + } + } + + + state->predicted_text[0] = 0; /* Start with nothing predicted */ + dict = dictionary; /* Points to current dictionary word */ + i = state->editpos; + + if ( state->text[utf8seek(state->text,i)] == 0 ) { /* at end of line */ + 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+1] == '\n' ) { /* typed out whole word, look for different word */ + dict = &dict[i+2]; + i = 0; + } + if ( partial[i] != dict[i] ) { /* mismatch, set dictionary at next comma */ + //match=false; + while ( dict[++i] != '\n' ) + if ( dict[i] == 0 ) + return; + dict = &dict[i+1]; + i = 0; + } else { + //match = true; + if ( i == length-1 ) + break; + else + i += utf8seek(&state->text[i],1); + } + } + if ( 1 ) { + for ( i = 0 ; dict[i] != '\n' && dict[i] != 0 ; i++ ) + state->predicted_text[i] = dict[i]; + state->predicted_text[i] = 0; + state->predicted_len = length; + sc->putsxy(0, pm->main_y+pm->font_h, state->predicted_text); + } + } +} +#endif \ No newline at end of file Index: /mnt/storage/rockbox/apps/keymaps/keymap-e200.c =================================================================== --- /mnt/storage/rockbox/apps/keymaps/keymap-e200.c (revision 24623) +++ /mnt/storage/rockbox/apps/keymaps/keymap-e200.c (working copy) @@ -245,20 +245,14 @@ }; /* button_context_radio */ static const struct button_mapping button_context_keyboard[] = { - { ACTION_KBD_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_KBD_CURSOR_LEFT, BUTTON_REC|BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_LEFT, BUTTON_REC|BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { 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_CURSOR_LEFT, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_RIGHT, BUTTON_RIGHT|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: /mnt/storage/rockbox/apps/keymaps/keymap-ipod.c =================================================================== --- /mnt/storage/rockbox/apps/keymaps/keymap-ipod.c (revision 24623) +++ /mnt/storage/rockbox/apps/keymaps/keymap-ipod.c (working copy) @@ -156,19 +156,21 @@ }; /* button_context_pitchscreen */ static const struct button_mapping button_context_keyboard[] = { - { ACTION_KBD_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { 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_MORSE_INPUT, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, - { ACTION_KBD_MORSE_SELECT, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE }, + { ACTION_KBD_CURSOR_LEFT, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_SELECT, BUTTON_SELECT, 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_NONE }, + { ACTION_KBD_BACKSPACE, BUTTON_MENU|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_MORSE_SELECT, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE }, + LAST_ITEM_IN_LIST }; /* button_context_keyboard */ Index: /mnt/storage/rockbox/apps/keymaps/keymap-fuze.c =================================================================== --- /mnt/storage/rockbox/apps/keymaps/keymap-fuze.c (revision 24623) +++ /mnt/storage/rockbox/apps/keymaps/keymap-fuze.c (working copy) @@ -246,20 +246,15 @@ }; /* button_context_radio */ static const struct button_mapping button_context_keyboard[] = { - { ACTION_KBD_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_LEFT, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_LEFT, BUTTON_HOME|BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_LEFT, BUTTON_HOME|BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { 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 },