diff --git a/apps/action.h b/apps/action.h
index e54d5de..e07ab17 100644
--- a/apps/action.h
+++ b/apps/action.h
@@ -243,6 +243,8 @@ enum {
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,
diff --git a/apps/keymaps/keymap-e200.c b/apps/keymaps/keymap-e200.c
index 538cd7c..f78fedb 100644
--- a/apps/keymaps/keymap-e200.c
+++ b/apps/keymaps/keymap-e200.c
@@ -254,10 +254,10 @@ static const struct button_mapping button_context_keyboard[] = {
{ 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 },
diff --git a/apps/keymaps/keymap-fuze.c b/apps/keymaps/keymap-fuze.c
index e829bef..4df8114 100644
--- a/apps/keymaps/keymap-fuze.c
+++ b/apps/keymaps/keymap-fuze.c
@@ -256,10 +256,10 @@ static const struct button_mapping button_context_keyboard[] = {
{ 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 },
diff --git a/apps/keymaps/keymap-ipod.c b/apps/keymaps/keymap-ipod.c
index a438926..44920b4 100644
--- a/apps/keymaps/keymap-ipod.c
+++ b/apps/keymaps/keymap-ipod.c
@@ -160,13 +160,14 @@ static const struct button_mapping button_context_keyboard[] = {
{ 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_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 */
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 0778ab7..4d86bb8 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -13030,6 +13030,118 @@
+ 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_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"
+
+
+
+ id: LANG_KBD_MODE_SIDEWAYS
+ desc: in settings.general.system
+ user: core
+
+ *: "Sideways"
+
+
+ *: "Sideways"
+
+
+ *: "Sideways"
+
+
+
+ id: LANG_WHEEL_SPEED
+ desc: in settings.general.system
+ user: core
+
+ *: "Wheel Speed"
+
+
+ *: "Wheel Speed"
+
+
+ *: "Wheel Speed"
+
+
+
id: LANG_USE_SHORTCUTS_INSTEAD_OF_QS
desc: in settings_menu.
user: core
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c
index 95423a2..948bf41 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -301,8 +301,8 @@ MENUITEM_SETTING(usb_keypad_mode, &global_settings.usb_keypad_mode, NULL);
MENUITEM_SETTING(usb_skip_first_drive, &global_settings.usb_skip_first_drive, 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
@@ -333,9 +333,11 @@ MAKE_MENU(system_menu, ID2P(LANG_SYSTEM),
#ifdef HAVE_QUICKSCREEN
&shortcuts_replaces_quickscreen,
#endif
-#ifdef HAVE_MORSE_INPUT
- &morse_input,
-#endif
+
+ #if defined(HAVE_MORSE_INPUT) || defined(HAVE_SCROLLWHEEL)
+ &keyboard_mode,
+ #endif
+
#if CONFIG_CODEC == MAS3507D
&line_in,
#endif
diff --git a/apps/recorder/keyboard.c b/apps/recorder/keyboard.c
index a6c015a..2129a59 100644
--- a/apps/recorder/keyboard.c
+++ b/apps/recorder/keyboard.c
@@ -18,6 +18,7 @@
* KIND, either express or implied.
*
****************************************************************************/
+#include
#include "kernel.h"
#include "system.h"
#include "string-extra.h"
@@ -43,6 +44,8 @@
#define O_BINARY 0
#endif
+/* define this if you want selected row inversed instead of underlined */
+#define KBD_INVERSE_ROW
#define DEFAULT_MARGIN 6
#define KBD_BUF_SIZE 500
@@ -53,6 +56,14 @@
((s) == SCREEN_MAIN && MIN_GRID_SIZE > (x) ? MIN_GRID_SIZE: (x))
#endif
+#ifndef BUTTONBAR_HEIGHT
+#define BUTTONBAR_HEIGHT 0
+#endif
+
+#define PRED_TEXT
+#define MAX_DICT 50000
+#define MAX_DICT_WORD 50
+
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) \
|| (CONFIG_KEYPAD == IRIVER_H300_PAD) \
|| (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
@@ -63,48 +74,70 @@
|| (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_HDD6330_PAD) \
|| (CONFIG_KEYPAD == PHILIPS_SA9200_PAD) \
|| (CONFIG_KEYPAD == PBELL_VIBE500_PAD) \
|| (CONFIG_KEYPAD == SANSA_CONNECT_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
+/* stored as {line_len;chars....;line_len;chars....;0xFEFF} */
+unsigned short kbd_buf[KBD_BUF_SIZE];
struct keyboard_parameters
{
- unsigned short kbd_buf[KBD_BUF_SIZE];
- unsigned short max_line_len;
- int default_lines;
+ int layout_width;
+ int layout_lines;
int last_k;
int last_i;
int font_w;
int font_h;
int text_w;
- int curfont;
int main_y;
#ifdef HAVE_MORSE_INPUT
int old_main_y;
#endif
- int max_chars;
- int max_chars_text;
- int lines;
- int pages;
+ int window_width;
+ int window_height;
int keyboard_margin;
int curpos;
- int leftpos;
- int page;
int x;
int y;
bool line_edit;
#ifdef HAVE_TOUCHSCREEN
bool show_buttons;
+ int button_h;
+#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
+};
+
+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!"
};
struct edit_state
@@ -117,16 +150,27 @@ struct edit_state
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];
static bool kbd_loaded = false;
+static bool kbd_uifont = false;
+
#ifdef HAVE_MORSE_INPUT
/* FIXME: We should put this to a configuration file. */
@@ -139,12 +183,71 @@ static const unsigned char morse_codes[] = {
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);
+static void kbd_inschar(struct edit_state *state, unsigned short ch);
+#ifdef HAVE_TOUCHSCREEN
+static void kbd_draw_buttons(struct keyboard_parameters *pm, struct screen *sc);
+static int keyboard_touchscreen(struct keyboard_parameters *pm,
+ struct screen *sc, struct edit_state *state);
+#endif
+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_learn_text(char *input);
+
+static void kbd_load_predicted(void);
+
+static void kbd_save_predicted(void);
+
+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,
+ struct keyboard_parameters *pm);
+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)
{
int fd;
- int i, line_len, max_line_len;
+ int i, line_len, layout_width, layout_lines=1;
unsigned char buf[4];
unsigned short *pbuf;
@@ -158,9 +261,9 @@ int load_kbd(unsigned char* filename)
if (fd < 0)
return 1;
- pbuf = kbd_param[0].kbd_buf;
+ pbuf = kbd_buf;
line_len = 0;
- max_line_len = 1;
+ layout_width = 1;
i = 1;
while (read(fd, buf, 1) == 1 && i < KBD_BUF_SIZE-1)
{
@@ -191,11 +294,12 @@ int load_kbd(unsigned char* filename)
i++;
if (ch == '\n')
{
- if (max_line_len < line_len)
- max_line_len = line_len;
+ if (layout_width < line_len)
+ layout_width = line_len;
*pbuf = line_len;
pbuf += line_len + 1;
line_len = 0;
+ layout_lines++;
}
else
pbuf[++line_len] = ch;
@@ -203,10 +307,9 @@ int load_kbd(unsigned char* filename)
}
close(fd);
- kbd_loaded = true;
- if (max_line_len < line_len)
- max_line_len = line_len;
+ if (layout_width < line_len)
+ layout_width = line_len;
if (i == 1 || line_len != 0) /* ignore last empty line */
{
*pbuf = line_len;
@@ -214,19 +317,20 @@ int load_kbd(unsigned char* filename)
}
*pbuf = 0xFEFF; /* mark end of characters */
i++;
+
FOR_NB_SCREENS(l)
{
struct keyboard_parameters *pm = &kbd_param[l];
-#if NB_SCREENS > 1
- if (l > 0)
- memcpy(pm->kbd_buf, kbd_param[0].kbd_buf, i*sizeof(unsigned short));
-#endif
+
/* initialize parameters */
- pm->x = pm->y = pm->page = 0;
- pm->default_lines = 0;
- pm->max_line_len = max_line_len;
+ pm->x = pm->y = 0;
+ pm->layout_width = layout_width;
+ pm->layout_lines = layout_lines;
}
+ kbd_loaded = true;
+ kbd_uifont = true;
+
return 0;
}
@@ -261,7 +365,6 @@ static void kbd_inschar(struct edit_state *state, unsigned short ch)
memmove(utf8 + j, utf8, len - i + 1);
memcpy(utf8, tmp, j);
state->editpos++;
- state->changed = CHANGED_TEXT;
}
}
@@ -278,61 +381,594 @@ static void kbd_delchar(struct edit_state *state)
utf8 = state->text + i;
j = utf8seek(utf8, 1);
memmove(utf8, utf8 + j, len - i - j + 1);
- state->changed = CHANGED_TEXT;
}
}
/* Lookup k value based on state of param (pm) */
static unsigned short get_kbd_ch(struct keyboard_parameters *pm, int x, int y)
{
- int i = 0, k = pm->page*pm->lines + y, n;
+ int i = 0, k = y, n;
unsigned short *pbuf;
+
if (k >= pm->last_k)
{
i = pm->last_i;
k -= pm->last_k;
}
- for (pbuf = &pm->kbd_buf[i]; (i = *pbuf) != 0xFEFF; pbuf += i + 1)
+ for (pbuf = &kbd_buf[i]; (i = *pbuf) != 0xFEFF; pbuf += i + 1)
{
- n = i ? (i + pm->max_chars - 1) / pm->max_chars : 1;
+ n = i ? (i + pm->layout_width - 1) / pm->layout_width : 1;
if (k < n) break;
k -= n;
}
if (y == 0 && i != 0xFEFF)
{
- pm->last_k = pm->page*pm->lines - k;
- pm->last_i = pbuf - pm->kbd_buf;
+ pm->last_k = - k;
+ pm->last_i = pbuf - kbd_buf;
}
- k = k * pm->max_chars + x;
+ k = k * pm->layout_width + x;
return (*pbuf != 0xFEFF && k < *pbuf)? pbuf[k+1]: ' ';
}
-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 HAVE_TOUCHSCREEN
-static void kbd_draw_buttons(struct keyboard_parameters *pm, struct screen *sc);
-static int keyboard_touchscreen(struct keyboard_parameters *pm,
- struct screen *sc, struct edit_state *state);
+#ifdef KBD_TOGGLE_INPUT
+static void kbd_switch_mode ( struct edit_state *state )
+{
+ int l;
+ (void)l;
+ FOR_NB_SCREENS(l)
+ {
+ kbd_param[l].line_edit = false;
+ kbd_param[l].x = 0;
+ kbd_param[l].y = 0;
+ }
+ state->keyboard_mode++;
+ if ( state->keyboard_mode == KBD_MODE_END )
+ state->keyboard_mode = KBD_MODE_STANDARD;
+ splash(HZ/2,mode_labels[state->keyboard_mode-KBD_MODE_STANDARD] );
+}
+#endif
+
+#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->row == false )
+ kbd_picker_right( state, pm );
+ state->row = false;
+ break;
+
+#ifdef HAVE_MORSE_INPUT
+ case KBD_MODE_MORSE:
+ kbd_cursor_right( state );
+ break;
+#endif
+
+ case KBD_MODE_SCROLL_1D:
+ kbd_picker_right( state, pm );
+ break;
+
+ case KBD_MODE_SIDEWAYS:
+ if ( pm->line_edit )
+ kbd_cursor_right( state );
+ else
+ kbd_picker_right( state, pm );
+ break;
+
+ case KBD_MODE_STANDARD:
+ default:
+ kbd_down( state, pm );
+ break;
+ }
+}
+
+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->row == false )
+ {
+ kbd_insert_current_char( state, pm );
+ pm->x = pm->y = 0;
+ state->row = true;
+ }
+ else
+ kbd_down( state, pm );
+ break;
+
+ case KBD_MODE_SCROLL_1D:
+ kbd_picker_left( state, pm );
+ break;
+
+#ifdef HAVE_MORSE_INPUT
+ case KBD_MODE_MORSE:
+ kbd_cursor_left( state );
+ break;
+#endif
+ case KBD_MODE_SIDEWAYS:
+ if ( pm->line_edit )
+ kbd_cursor_left( state );
+ else
+ kbd_picker_left( state, pm );
+ break;
+
+ case KBD_MODE_STANDARD:
+ default:
+ kbd_up( state, pm );
+ }
+}
#endif
-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_horizontal(struct keyboard_parameters *pm,
- struct edit_state *state, int dir);
-static void kbd_move_picker_vertical(struct keyboard_parameters *pm,
- struct edit_state *state, int dir);
+
+static void kbd_picker_right( struct edit_state *state,
+ struct keyboard_parameters *pm )
+{
+ (void) state;
+ if (++pm->x >= pm->layout_width)
+ {
+#ifdef HAVE_SCROLLWHEEL
+ switch ( state->keyboard_mode )
+ {
+ case KBD_MODE_ROWCOL:
+ pm->x = pm->layout_width-1;
+ state->row = true;
+ return;
+ case KBD_MODE_SCROLL_1D:
+ kbd_down( state, pm );
+ case KBD_MODE_KEEP_ROLLIN:
+ pm->x = 0;
+ return;
+ default:
+ break;
+ }
+#endif
+ pm->x = 0;
+ }
+ kbd_spellchar( get_kbd_ch(pm, pm->x, pm->y) );
+}
+
+static void kbd_right( struct edit_state *state,
+ struct keyboard_parameters *pm )
+{
+#ifdef HAVE_SCROLLWHEEL
+ switch ( state->keyboard_mode )
+ {
+ case KBD_MODE_STANDARD:
+ if ( pm->line_edit )
+ kbd_cursor_right( state );
+ else
+ 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:
+#ifdef HAVE_MORSE_INPUT
+ case KBD_MODE_MORSE:
+#endif
+ kbd_cursor_right( state );
+ return;
+ default:
+ break;
+ }
+#else /* (not) HAVE_SCROLLWHEEL */
+ if ( pm->line_edit )
+ kbd_cursor_right( state );
+ else
+ 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:
+ state->row = true;
+ pm->x = pm->layout_width - 1;
+ return;
+ default:
+ break;
+ }
+#endif
+ pm->x = pm->layout_width - 1;
+ }
+ kbd_spellchar( get_kbd_ch(pm, pm->x, pm->y) );
+}
+
+static void kbd_left( struct edit_state *state,
+ struct keyboard_parameters *pm )
+{
+#ifdef HAVE_SCROLLWHEEL
+ switch ( state->keyboard_mode )
+ {
+ case KBD_MODE_STANDARD:
+ if ( pm->line_edit )
+ kbd_cursor_left( state );
+ else
+ 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:
+#ifdef HAVE_MORSE_INPUT
+ case KBD_MODE_MORSE:
+#endif
+ kbd_cursor_left( state );
+ return;
+ default:
+ return;
+ }
+#else /* (not) HAVE_SCROLLWHEEL */
+ if ( pm->line_edit )
+ kbd_cursor_left( state );
+ else
+ 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->layout_lines)
+ {
+ pm->y = 0;
+ }
+ return;
+ }
+#endif
+#ifdef HAVE_MORSE_INPUT
+ if (state->keyboard_mode == KBD_MODE_MORSE)
+ {
+ pm->line_edit = !pm->line_edit;
+ return;
+ }
+#endif /* HAVE_MORSE_INPUT */
+
+ if (pm->line_edit)
+ {
+ pm->y = 0;
+ pm->line_edit = false;
+ }
+ else if (++pm->y >= pm->layout_lines)
+ {
+ pm->line_edit = true;
+ }
+ if (!pm->line_edit)
+ {
+ kbd_spellchar( get_kbd_ch(pm, pm->x, pm->y) );
+ }
+ return;
+}
+
+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->layout_lines - 1;
+ }
+ return;
+ }
+#endif
+#ifdef HAVE_MORSE_INPUT
+ if (state->keyboard_mode == KBD_MODE_MORSE)
+ {
+ pm->line_edit = !pm->line_edit;
+ return;
+ }
+#endif /* HAVE_MORSE_INPUT */
+ if (pm->line_edit)
+ {
+ pm->y = pm->layout_lines - 1;
+ pm->line_edit = false;
+ }
+ else if (--pm->y < 0)
+ {
+ pm->line_edit = true;
+ }
+ if (!pm->line_edit)
+ kbd_spellchar( get_kbd_ch(pm, pm->x, pm->y) );
+}
+
+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;
+ }
+#else
+ state->editpos = 0;
+#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]);
+ }
+ else
+ state->editpos = state->len_utf8;
+}
+
+static void kbd_backspace( struct edit_state *state,
+ struct keyboard_parameters *pm)
+{
+ unsigned short ch;
+
+#ifdef HAVE_SCROLLWHEEL
+ /* zero picker column, zero picker row, then backspace */
+ if ( state->keyboard_mode == KBD_MODE_KEEP_ROLLIN )
+ {
+ if ( pm->x || pm->y )
+ {
+ pm->x = 0;
+ pm->y = 0;
+ return;
+ }
+ }
+#endif
+ (void)pm;
+ 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, pm->x, pm->y);
+
+ /* 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;
+ }
+ }
+ if ( state->keyboard_mode == KBD_MODE_KEEP_ROLLIN )
+ {
+ state->row = false;
+ kbd_insert_current_char( state, pm );
+ return;
+ }
+#endif /* HAVE_SCROLLWHEEL */
+ if ( pm->line_edit )
+ {
+ kbd_backspace( state, pm );
+ return;
+ }
+#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;
struct keyboard_parameters * const param = kbd_param;
struct edit_state state;
- unsigned short ch;
+ int l; /* screen loop variable */
+ (void)l;
int ret = 0; /* assume success */
FOR_NB_SCREENS(l)
{
@@ -351,92 +987,96 @@ int kbd_input(char* text, int buflen)
/* initialize state */
state.text = text;
state.buflen = buflen;
+#ifdef HAVE_SCROLLWHEEL
+ state.prev_button = BUTTON_NONE;
+ state.row = true;
+#endif
+#ifdef PRED_TEXT
+ kbd_load_predicted();
+ 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)
{
- /* Copy default keyboard to buffer */
- FOR_NB_SCREENS(l)
- {
- struct keyboard_parameters *pm = ¶m[l];
- unsigned short *pbuf;
- const unsigned char *p;
- int len = 0;
+ unsigned short *pbuf;
+ const unsigned char *p;
+ int len = 0;
#if LCD_WIDTH >= 160 && LCD_HEIGHT >= 96
- struct screen *sc = &screens[l];
+ p = "ABCDEFG abcdefg !?\" @#$%+'\n"
+ "HIJKLMN hijklmn 789 &_()-`\n"
+ "OPQRSTU opqrstu 456 §|{}/<\n"
+ "VWXYZ., vwxyz.,0123 ~=[]*>\n"
+ "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË ¢£¤¥¦§©®\n"
+ "àáâãäåæ ìíîï èéêë «»°ºª¹²³\n"
+ "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ ¯±×÷¡¿µ·\n"
+ "òóôõöø çðþýÿ ùúûü ¼½¾¬¶¨:;";
+
+ param[0].layout_lines = 8;
+ param[0].layout_width = 26;
+
+#else /* LCD_WIDTH >= 160 && LCD_HEIGHT >= 96 */
+ p = "ABCDEFG !?\" @#$%+'\n"
+ "HIJKLMN 789 &_()-`\n"
+ "OPQRSTU 456 §|{}/<\n"
+ "VWXYZ.,0123 ~=[]*>\n"
+
+ "abcdefg ¢£¤¥¦§©®¬\n"
+ "hijklmn «»°ºª¹²³¶\n"
+ "opqrstu ¯±×÷¡¿µ·¨\n"
+ "vwxyz., :;¼½¾ \n"
+
+ "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË\n"
+ "àáâãäåæ ìíîï èéêë\n"
+ "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ\n"
+ "òóôõöø çðþýÿ ùúûü";
+
+ param[0].layout_lines = 4;
+ param[0].layout_width = 18;
+#endif
- if (sc->getwidth() >= 160 && sc->getheight() >= 96)
+ pbuf = kbd_buf;
+ while (*p)
+ {
+ p = utf8decode(p, &pbuf[len+1]);
+ if (pbuf[len+1] == '\n')
{
- p = "ABCDEFG abcdefg !?\" @#$%+'\n"
- "HIJKLMN hijklmn 789 &_()-`\n"
- "OPQRSTU opqrstu 456 §|{}/<\n"
- "VWXYZ., vwxyz.,0123 ~=[]*>\n"
- "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË ¢£¤¥¦§©®\n"
- "àáâãäåæ ìíîï èéêë «»°ºª¹²³\n"
- "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ ¯±×÷¡¿µ·\n"
- "òóôõöø çðþýÿ ùúûü ¼½¾¬¶¨:;";
-
- pm->default_lines = 8;
- pm->max_line_len = 26;
+ *pbuf = len;
+ pbuf += len+1;
+ len = 0;
}
else
-#endif /* LCD_WIDTH >= 160 && LCD_HEIGHT >= 96 */
- {
- p = "ABCDEFG !?\" @#$%+'\n"
- "HIJKLMN 789 &_()-`\n"
- "OPQRSTU 456 §|{}/<\n"
- "VWXYZ.,0123 ~=[]*>\n"
-
- "abcdefg ¢£¤¥¦§©®¬\n"
- "hijklmn «»°ºª¹²³¶\n"
- "opqrstu ¯±×÷¡¿µ·¨\n"
- "vwxyz., :;¼½¾ \n"
-
- "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË\n"
- "àáâãäåæ ìíîï èéêë\n"
- "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ\n"
- "òóôõöø çðþýÿ ùúûü";
-
- pm->default_lines = 4;
- pm->max_line_len = 18;
- }
-
- pbuf = pm->kbd_buf;
- while (*p)
- {
- p = utf8decode(p, &pbuf[len+1]);
- if (pbuf[len+1] == '\n')
- {
- *pbuf = len;
- pbuf += len+1;
- len = 0;
- }
- else
- len++;
- }
- *pbuf = len;
- pbuf[len+1] = 0xFEFF; /* mark end of characters */
-
- /* initialize parameters */
- pm->x = pm->y = pm->page = 0;
+ len++;
}
- kbd_loaded = true;
+ *pbuf = len;
+ pbuf[len+1] = 0xFEFF; /* mark end of characters */
}
+ kbd_loaded = true;
FOR_NB_SCREENS(l)
{
struct keyboard_parameters *pm = ¶m[l];
struct screen *sc = &screens[l];
+
+ pm->x = pm->y = 0;
+ pm->line_edit = false;
+ pm->layout_lines = param[0].layout_lines;
+ pm->layout_width = param[0].layout_width;
kbd_calc_params(pm, sc, &state);
+#ifdef HAVE_SCROLLWHEEL
+ pm->x = pm->y = 0;
+ pm->line_edit = false;
+#endif
}
if (global_settings.talk_menu) /* voice UI? */
@@ -448,12 +1088,8 @@ int kbd_input(char* text, int buflen)
action occurred - pointers save a lot of space over array notation
when accessing the same array element countless times */
int button;
-#if NB_SCREENS > 1
- int button_screen;
-#else
- const int button_screen = 0;
-#endif
struct keyboard_parameters *pm;
+ struct screen *sc;
state.len_utf8 = utf8length(state.text);
@@ -470,6 +1106,10 @@ int kbd_input(char* text, int buflen)
if (pm->show_buttons)
kbd_draw_buttons(pm, sc);
#endif
+#ifdef PRED_TEXT
+ /* just the main screen */
+ kbd_draw_predicted(¶m[0], &screens[0], &state);
+#endif
}
#ifdef HAVE_BUTTONBAR
@@ -483,41 +1123,29 @@ int kbd_input(char* text, int buflen)
state.cur_blink = !state.cur_blink;
- button = get_action(
#ifdef HAVE_MORSE_INPUT
- state.morse_mode? CONTEXT_MORSE_INPUT:
-#endif
- CONTEXT_KEYBOARD, HZ/2);
-#if NB_SCREENS > 1
- button_screen = (get_action_statuscode(NULL) & ACTION_REMOTE) ? 1 : 0;
+ 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
- pm = ¶m[button_screen];
+
+ pm = ¶m[0];
+ sc = &screens[0];
#ifdef HAVE_TOUCHSCREEN
if (button == ACTION_TOUCHSCREEN)
- {
- struct screen *sc = &screens[button_screen];
button = keyboard_touchscreen(pm, sc, &state);
- }
#endif
-
- /* Remap some buttons to allow to move
- * cursor in line edit mode and morse mode. */
- if (pm->line_edit
-#ifdef HAVE_MORSE_INPUT
- || state.morse_mode
-#endif /* HAVE_MORSE_INPUT */
- )
- {
- if (button == ACTION_KBD_LEFT)
- button = ACTION_KBD_CURSOR_LEFT;
- if (button == ACTION_KBD_RIGHT)
- button = ACTION_KBD_CURSOR_RIGHT;
- }
-
switch ( button )
{
case ACTION_KBD_DONE:
/* accepts what was entered and continues */
+#ifdef PRED_TEXT
+ /* learn if cursor at end of line */
+ if( state.editpos == state.len_utf8 )
+ kbd_learn_text( state.text );
+ kbd_save_predicted();
+#endif
ret = 0;
done = true;
break;
@@ -526,118 +1154,60 @@ int kbd_input(char* text, int buflen)
ret = -1;
done = true;
break;
+#ifdef HAVE_SCROLLWHEEL
+ case ACTION_KBD_SCROLL_FWD:
+ kbd_scroll_fwd(&state, pm);
+ break;
- case ACTION_KBD_PAGE_FLIP:
-#ifdef HAVE_MORSE_INPUT
- if (state.morse_mode)
- break;
+ case ACTION_KBD_SCROLL_BACK:
+ kbd_scroll_back(&state, pm);
+ break;
#endif
- if (++pm->page >= pm->pages)
- pm->page = 0;
-
- 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:
- kbd_move_picker_horizontal(pm, &state, 1);
+ kbd_right(&state, pm);
break;
case ACTION_KBD_LEFT:
- kbd_move_picker_horizontal(pm, &state, -1);
+ 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);
- break;
-
-#ifdef HAVE_MORSE_INPUT
-#ifdef KBD_TOGGLE_INPUT
- case ACTION_KBD_MORSE_INPUT:
- state.morse_mode = !state.morse_mode;
- state.changed = CHANGED_PICKER;
-
- 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;
- }
- 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;
- }
+ kbd_up(&state, pm);
break;
-#endif /* HAVE_MORSE_INPUT */
case ACTION_KBD_SELECT:
- /* select doubles as backspace in line_edit */
- if (pm->line_edit)
- kbd_backspace(&state);
- else
-#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, pm);
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:
@@ -649,38 +1219,19 @@ int kbd_input(char* text, int buflen)
break;
} /* end switch */
-
+ FOR_NB_SCREENS(l)
+ {
+ param[l].x = param[0].x;
+ param[l].y = param[0].y;
+ param[l].line_edit = param[0].line_edit;
+ }
if (button != ACTION_NONE)
{
- state.cur_blink = true;
- }
- if (global_settings.talk_menu) /* voice UI? */
- {
- if (state.changed == CHANGED_PICKER)
- {
- if (pm->line_edit)
- {
- talk_id(VOICE_EDIT, false);
- }
- else
-#ifdef HAVE_MORSE_INPUT
- /* FIXME: We should talk something like Morse mode.. */
- if (!state.morse_mode)
+#ifdef HAVE_SCROLLWHEEL
+ state.prev_button = button;
#endif
- {
- ch = get_kbd_ch(pm, pm->x, pm->y);
- 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.cur_blink = true;
}
- state.changed = 0;
}
#ifdef HAVE_BUTTONBAR
@@ -689,11 +1240,10 @@ int kbd_input(char* text, int buflen)
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 */
@@ -712,23 +1262,26 @@ static void kbd_calc_params(struct keyboard_parameters *pm,
struct font* font;
const unsigned char *p;
unsigned short ch, *pbuf;
- int icon_w, sc_w, sc_h, w;
- int i, total_lines;
+ int sc_w, sc_h, w;
+ int i, total_lines, font_id;
#ifdef HAVE_TOUCHSCREEN
int button_h = 0;
- bool flippage_button = false;
pm->show_buttons = (sc->screen_type == SCREEN_MAIN &&
(touchscreen_get_mode() == TOUCHSCREEN_POINT));
#endif
+ if( kbd_uifont )
+ font_id = sc->getuifont();
+ else
+ font_id = FONT_SYSFIXED;
+
+ font = font_get( font_id );
- pm->curfont = pm->default_lines ? FONT_SYSFIXED : sc->getuifont();
- font = font_get(pm->curfont);
pm->font_h = font->height;
/* check if FONT_UI fits the screen */
if (2*pm->font_h + 3 + BUTTONBAR_HEIGHT > sc->getheight())
{
- pm->curfont = FONT_SYSFIXED;
+ kbd_uifont = false;
font = font_get(FONT_SYSFIXED);
pm->font_h = font->height;
}
@@ -740,7 +1293,7 @@ static void kbd_calc_params(struct keyboard_parameters *pm,
* since we're going to be adding spaces,
* max width is at least their width */
pm->font_w = font_get_width(font, ' ');
- for (pbuf = pm->kbd_buf; *pbuf != 0xFEFF; pbuf += i)
+ for (pbuf = kbd_buf; *pbuf != 0xFEFF; pbuf += i)
{
for (i = 0; ++i <= *pbuf; )
{
@@ -765,38 +1318,42 @@ static void kbd_calc_params(struct keyboard_parameters *pm,
pm->font_w = GRID_SIZE(sc->screen_type, pm->font_w);
#endif
/* calculate how many characters to put in a row. */
- icon_w = get_icon_width(sc->screen_type);
sc_w = sc->getwidth();
- if (pm->font_w < sc_w / pm->max_line_len)
- pm->font_w = sc_w / pm->max_line_len;
- pm->max_chars = sc_w / pm->font_w;
- pm->max_chars_text = (sc_w - icon_w * 2 - 2) / pm->text_w;
- if (pm->max_chars_text < 3 && icon_w > pm->text_w)
- pm->max_chars_text = sc_w / pm->text_w - 2;
-
- /* calculate pm->pages and pm->lines */
+ if (pm->font_w < sc_w / pm->layout_width)
+ pm->font_w = sc_w / pm->layout_width;
+ pm->window_width = sc_w / pm->font_w;
+ if ( pm->window_width > pm->layout_width )
+ pm->window_width = pm->layout_width;
+
+ /* calculate and pm->window_height */
sc_h = sc->getheight();
+#ifdef PRED_TEXT
+ if ( sc == &screens[0] )
+ /* reserve a line for predicted text on main screen */
+ sc_h -= pm->font_h;
+#endif
#ifdef HAVE_TOUCHSCREEN
/* add space for buttons */
if (pm->show_buttons)
{
/* reserve place for OK/Del/Cancel buttons, use ui font for them */
button_h = GRID_SIZE(sc->screen_type, sc->getcharheight());
- sc_h -= MAX(MIN_GRID_SIZE*2, button_h);
+ pm->button_h = MAX(MIN_GRID_SIZE*2, button_h);
+ sc_h -= pm->button_h;
}
recalc_param:
#endif
- pm->lines = (sc_h - BUTTONBAR_HEIGHT) / pm->font_h - 1;
+ pm->window_height = (sc_h - BUTTONBAR_HEIGHT) / pm->font_h - 1;
- if (pm->default_lines && pm->lines > pm->default_lines)
- pm->lines = pm->default_lines;
+ if (pm->layout_lines && pm->window_height > pm->layout_lines)
+ pm->window_height = pm->layout_lines;
pm->keyboard_margin = sc_h - BUTTONBAR_HEIGHT
- - (pm->lines+1)*pm->font_h;
+ - (pm->window_height+1)*pm->font_h;
- if (pm->keyboard_margin < 3 && pm->lines > 1)
+ if (pm->keyboard_margin < 3 && pm->window_height > 1)
{
- pm->lines--;
+ pm->window_height--;
pm->keyboard_margin += pm->font_h;
}
@@ -804,34 +1361,24 @@ recalc_param:
pm->keyboard_margin = DEFAULT_MARGIN;
total_lines = 0;
- for (pbuf = pm->kbd_buf; (i = *pbuf) != 0xFEFF; pbuf += i + 1)
- total_lines += (i ? (i + pm->max_chars - 1) / pm->max_chars : 1);
+ for (pbuf = kbd_buf; (i = *pbuf) != 0xFEFF; pbuf += i + 1)
+ total_lines += (i ? (i + pm->layout_width - 1) / pm->layout_width : 1);
+ pm->layout_lines = total_lines;
- pm->pages = (total_lines + pm->lines - 1) / pm->lines;
- pm->lines = (total_lines + pm->pages - 1) / pm->pages;
#ifdef HAVE_TOUCHSCREEN
- if (pm->pages > 1 && pm->show_buttons && !flippage_button)
- {
- /* add space for flip page button */
- sc_h -= button_h;
- flippage_button = true;
- goto recalc_param;
- }
+ pm->window_height = ( (sc_h -BUTTONBAR_HEIGHT -button_h -pm->font_h -2*pm->keyboard_margin) /
+ pm->font_h );
+#else
+ pm->window_height = ( (sc_h -BUTTONBAR_HEIGHT -pm->font_h -2*pm->keyboard_margin) /
+ pm->font_h );
#endif
- if (pm->page >= pm->pages)
- pm->x = pm->y = pm->page = 0;
- pm->main_y = pm->font_h*pm->lines + pm->keyboard_margin;
+ pm->main_y = pm->font_h*pm->window_height + pm->keyboard_margin;
pm->keyboard_margin -= pm->keyboard_margin/2;
-#ifdef HAVE_TOUCHSCREEN
- /* flip page button is put between piker and edit line */
- if (flippage_button)
- pm->main_y += button_h;
-#endif
#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;
@@ -845,7 +1392,7 @@ static void kbd_draw_picker(struct keyboard_parameters *pm,
{
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;
@@ -900,14 +1447,36 @@ static void kbd_draw_picker(struct keyboard_parameters *pm,
int w, h;
unsigned short ch;
unsigned char *utf8;
+ int x_offset = 0, y_offset = 0;
- sc->setfont(pm->curfont);
-
- for (j = 0; j < pm->lines; j++)
+ if(kbd_uifont)
+ sc->setfont(FONT_UI);
+ else
+ sc->setfont(FONT_SYSFIXED);
+
+ if( pm->window_width < pm->layout_width )
+ {
+ x_offset = pm->x - pm->window_width/2;
+ if( x_offset > pm->layout_width - pm->window_width )
+ x_offset = pm->layout_width - pm->window_width;
+ }
+ if( x_offset < 0 )
+ x_offset = 0;
+
+ if( pm->window_height < pm->layout_lines )
+ {
+ y_offset = pm->y - pm->window_height/2;
+ if (y_offset > pm->layout_lines - pm->window_height )
+ y_offset = pm->layout_lines - pm->window_height;
+ }
+ if ( y_offset < 0 )
+ y_offset = 0;
+
+ for (j = 0; j < pm->window_height && j < pm->layout_lines; j++)
{
- for (i = 0; i < pm->max_chars; i++)
+ for (i = 0; i < pm->window_width && i < pm->layout_width; i++)
{
- ch = get_kbd_ch(pm, i, j);
+ ch = get_kbd_ch(pm, i+x_offset, j+y_offset);
utf8 = utf8encode(ch, outline);
*utf8 = 0;
@@ -921,7 +1490,20 @@ static void kbd_draw_picker(struct keyboard_parameters *pm,
{
/* highlight the key that has focus */
sc->set_drawmode(DRMODE_COMPLEMENT);
- sc->fillrect(pm->font_w*pm->x, pm->font_h*pm->y,
+#ifdef HAVE_SCROLLWHEEL
+ if ( (state->keyboard_mode == KBD_MODE_ROWCOL && state->row) ||
+ (state->keyboard_mode == KBD_MODE_KEEP_ROLLIN && state->row ))
+#ifdef KBD_INVERSE_ROW
+ sc->fillrect(0,pm->font_h*(pm->y-y_offset),
+ sc->getwidth(), pm->font_h);
+#else /* underline current row */
+ sc->hline(0, sc->getwidth(),
+ pm->font_h*(pm->y+1-y_offset));
+#endif
+ else
+#endif /* HAVE_SCROLLWHEEL */
+ sc->fillrect(pm->font_w*(pm->x-x_offset),
+ pm->font_h*(pm->y-y_offset),
pm->font_w, pm->font_h);
sc->set_drawmode(DRMODE_SOLID);
}
@@ -931,12 +1513,11 @@ static void kbd_draw_picker(struct keyboard_parameters *pm,
static void kbd_draw_edit_line(struct keyboard_parameters *pm,
struct screen *sc, struct edit_state *state)
{
- char outline[8];
- unsigned char *utf8;
- int i = 0, j = 0, icon_w, w;
+ int total_w, tail_w, x_offset,cursor;
int sc_w = sc->getwidth();
int y = pm->main_y - pm->keyboard_margin;
- int text_margin = (sc_w - pm->text_w * pm->max_chars_text) / 2;
+ int text_margin = 5;
+ int window_w = sc_w-2*text_margin;
/* Clear text area one pixel above separator line so any overdraw
doesn't collide */
@@ -944,76 +1525,38 @@ static void kbd_draw_edit_line(struct keyboard_parameters *pm,
sc->hline(0, sc_w - 1, y);
- /* write out the text */
- sc->setfont(pm->curfont);
-
- pm->leftpos = MAX(0, MIN(state->len_utf8, state->editpos + 2)
- - pm->max_chars_text);
- pm->curpos = state->editpos - pm->leftpos;
- utf8 = state->text + utf8seek(state->text, pm->leftpos);
-
- while (*utf8 && i < pm->max_chars_text)
- {
- j = utf8seek(utf8, 1);
- strlcpy(outline, utf8, j+1);
- sc->getstringsize(outline, &w, NULL);
- sc->putsxy(text_margin + i*pm->text_w + (pm->text_w-w)/2,
- pm->main_y, outline);
- utf8 += j;
- i++;
- }
-
- icon_w = get_icon_width(sc->screen_type);
- if (pm->leftpos > 0)
- {
- /* Draw nicer bitmap arrow if room, else settle for "<". */
- if (text_margin >= icon_w)
- {
- screen_put_icon_with_offset(sc, 0, 0,
- (text_margin - icon_w) / 2,
- pm->main_y, Icon_Reverse_Cursor);
- }
- else
- {
- sc->getstringsize("<", &w, NULL);
- sc->putsxy(text_margin - w, pm->main_y, "<");
- }
- }
-
- if (state->len_utf8 - pm->leftpos > pm->max_chars_text)
- {
- /* Draw nicer bitmap arrow if room, else settle for ">". */
- if (text_margin >= icon_w)
- {
- screen_put_icon_with_offset(sc, 0, 0,
- sc_w - (text_margin + icon_w) / 2,
- pm->main_y, Icon_Cursor);
- }
- else
- {
- sc->putsxy(sc_w - text_margin, pm->main_y, ">");
- }
- }
-
- /* cursor */
- i = text_margin + pm->curpos * pm->text_w;
-
+ if(kbd_uifont)
+ sc->setfont(FONT_UI);
+ else
+ sc->setfont(FONT_SYSFIXED);
+ /* check length of edit line */
+ sc->getstringsize(state->text, &total_w, NULL);
+ /* check length of line from cursor to end */
+ sc->getstringsize(&state->text[utf8seek(state->text,state->editpos)], &tail_w, NULL);
+
+ x_offset = (window_w-total_w+tail_w);
+ if ( total_w-tail_w < window_w ) x_offset = 0;
+ sc->putsxy( x_offset+text_margin,pm->main_y, state->text);
+ cursor = x_offset+total_w-tail_w+text_margin;
if (state->cur_blink)
- sc->vline(i, pm->main_y, pm->main_y + pm->font_h - 1);
-
+ sc->vline(cursor, pm->main_y, pm->main_y + pm->font_h - 1);
if (state->hangul) /* draw underbar */
- sc->hline(i - pm->text_w, i, pm->main_y + pm->font_h - 1);
+ sc->hline(cursor-pm->text_w, cursor,
+ pm->main_y + pm->font_h - 1);
+#ifdef KBD_TOGGLE_INPUT
if (pm->line_edit)
{
sc->set_drawmode(DRMODE_COMPLEMENT);
sc->fillrect(0, y + 2, sc_w, pm->font_h + 2);
sc->set_drawmode(DRMODE_SOLID);
}
+#endif
}
#ifdef HAVE_TOUCHSCREEN
-static void kbd_draw_buttons(struct keyboard_parameters *pm, struct screen *sc)
+static void kbd_draw_buttons(struct keyboard_parameters *pm,
+ struct screen *sc)
{
struct viewport vp;
int button_h, text_h, text_y;
@@ -1029,13 +1572,6 @@ static void kbd_draw_buttons(struct keyboard_parameters *pm, struct screen *sc)
vp.width = sc_w;
vp.height = button_h;
/* draw buttons */
- if (pm->pages > 1)
- {
- /* button to flip page. */
- vp.y = pm->lines*pm->font_h;
- sc->hline(0, sc_w - 1, 0);
- sc->putsxy(0, text_y, ">");
- }
/* OK/Del/Cancel buttons */
button_h = MAX(MIN_GRID_SIZE*2, button_h);
text_y = (button_h - text_h) / 2 + 1;
@@ -1061,7 +1597,8 @@ static int keyboard_touchscreen(struct keyboard_parameters *pm,
const int sc_w = sc->getwidth(), sc_h = sc->getheight();
int button_h = MAX(MIN_GRID_SIZE*2, sc->getcharheight());
#ifdef HAVE_MORSE_INPUT
- if (state->morse_mode && y < pm->main_y - pm->keyboard_margin)
+ if (state->keyboard_mode == KBD_MODE_MORSE &&
+ y < pm->main_y - pm->keyboard_margin)
{
/* don't return ACTION_NONE since it has effect in morse mode. */
return button == BUTTON_TOUCHSCREEN? ACTION_KBD_SELECT:
@@ -1072,12 +1609,11 @@ static int keyboard_touchscreen(struct keyboard_parameters *pm,
#endif
if (x < 0 || y < 0)
return ACTION_NONE;
- if (y < pm->lines*pm->font_h)
+ if (y < pm->window_height*pm->font_h)
{
- if (x/pm->font_w < pm->max_chars)
+ if (x/pm->font_w < pm->window_width)
{
/* picker area */
- state->changed = CHANGED_PICKER;
pm->x = x/pm->font_w;
pm->y = y/pm->font_h;
pm->line_edit = false;
@@ -1085,12 +1621,6 @@ static int keyboard_touchscreen(struct keyboard_parameters *pm,
return ACTION_KBD_SELECT;
}
}
- else if (y < pm->main_y - pm->keyboard_margin)
- {
- /* button to flip page */
- if (button == BUTTON_REL)
- return ACTION_KBD_PAGE_FLIP;
- }
else if (y < sc_h - button_h)
{
/* edit line */
@@ -1119,164 +1649,248 @@ static int keyboard_touchscreen(struct keyboard_parameters *pm,
}
#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"
+#include "string.h"
+
+static bool dict_loaded = false, dict_changed = false;
+static char dictionary[MAX_DICT];
+
+static void kbd_learn_text(char *input)
{
- /* find input char */
- unsigned short ch = get_kbd_ch(pm, pm->x, pm->y);
+ /* dictionary end, word start, word end */
+ int de,ws,we,i,len;
+ char *line, word[MAX_DICT_WORD+1];
- /* check for hangul input */
- if (ch >= 0x3131 && ch <= 0x3163)
- {
- unsigned short tmp;
+ if ( ! dict_loaded )
+ return;
- if (!state->hangul)
- {
- state->hlead = state->hvowel = state->htail = 0;
- state->hangul = true;
- }
+ for ( de = 0; dictionary[de]; de++ )
+ if ( de == MAX_DICT )
+ return;
- if (!state->hvowel)
+ line = input;
+
+ while(1)
+ {
+ /* find word start */
+ for ( ws = 0; line[ws] == ' '; ws++ );
+ if ( line[ws] == 0 )
+ return;
+ /* find word end */
+ for ( we = ws; line[we] != ' ' && line[we] != 0 ; we++ );
+ len = we-ws;
+ if ( de+len >= MAX_DICT ) {
+ splash(HZ,"No room.");return;}
+
+ if ( len >= MAX_DICT_WORD ) {
+ splash(HZ,"Word too big.");return;}
+
+ /* don't save small words */
+ if ( len < 3 )
{
- state->hvowel = ch;
+ line += we;
+ continue;
}
- else if (!state->htail)
+
+ /* check if it's in there already */
+ /* FIXME: do something smart about case ?*/
+ for ( i=0; i < len; i++ )
+ word[i] = line[i+ws];
+ word[len]=0;
+ if ( strcasestr( dictionary, word ) != NULL )
{
- state->htail = ch;
+ line += we;
+ continue;
}
- 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;
- }
- }
+ splashf(HZ/3,"Adding %s",word);
+ dict_changed = true;
- /* combine into hangul */
- tmp = hangul_join(state->hlead, state->hvowel, state->htail);
+ /* shift dictionary forward */
+ memmove( dictionary+len+1, dictionary, de );
- if (tmp != 0xfffd)
+ /* copy word */
+ strcpy( dictionary, word );
+ dictionary[len]='\n';
+ de += len;
+ line += we;
+ }
+}
+
+static void kbd_save_predicted()
+{
+ int length;
+
+ if ( dict_loaded && dict_changed )
+ {
+ int fd = open("/.rockbox/pred_dict.txt", O_WRONLY|O_BINARY);
+ if (fd < 0)
{
- kbd_delchar(state);
- ch = tmp;
+ splash(HZ,"Can't open file");
+ return;
}
- else
+ for ( length = 0; dictionary[length]; length++ )
+ if ( length == MAX_DICT )
+ break;
+
+ if ( write( fd, dictionary, length ) != length )
{
- state->hvowel = state->htail = 0;
- state->hlead = ch;
+ splash(HZ,"Write error");
}
+ close(fd);
}
- else
- {
- state->hangul = false;
- }
-
- /* insert char */
- kbd_inschar(state, ch);
+ return;
}
-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);
+static void kbd_load_predicted()
+{
+ int length;
- if (state->hangul)
+ if ( ! dict_loaded )
{
- if (state->hvowel)
- ch = hangul_join(state->hlead, state->hvowel, state->htail);
- else
- ch = state->hlead;
- kbd_inschar(state, ch);
+ int fd = open("/.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;
+ }
+ close(fd);
}
}
-static void kbd_move_cursor(struct edit_state *state, int dir)
+static void kbd_draw_predicted(struct keyboard_parameters *pm,
+ struct screen *sc, struct edit_state *state)
{
- state->hangul = false;
- state->editpos += dir;
+ int i, left = -1, length;
+ static int last_editpos = -1;
+ char *partial, *dict;
+
+ if ( !dict_loaded )
+ return;
- if (state->editpos >= 0 && state->editpos <= state->len_utf8)
+ /* be lazy if edit cursor hasn't moved */
+ if ( state->editpos == last_editpos )
{
- state->changed = CHANGED_CURSOR;
+ sc->putsxy(0, pm->main_y+pm->font_h, state->pred_word);
+ return;
}
else
- {
- state->editpos -= dir;
-#if CONFIG_CODEC == SWCODEC
- if (global_settings.talk_menu)
- beep_play(1000, 150, 1500);
-#endif
- }
-}
+ last_editpos = state->editpos;
-static void kbd_move_picker_horizontal(struct keyboard_parameters *pm,
- struct edit_state *state, int dir)
-{
- state->changed = CHANGED_PICKER;
+ /* Start with nothing predicted */
+ state->pred_word[0] = 0;
- pm->x += dir;
- if (pm->x < 0)
- {
- if (--pm->page < 0)
- pm->page = pm->pages - 1;
- pm->x = pm->max_chars - 1;
- }
- else if (pm->x >= pm->max_chars)
+ 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 (++pm->page >= pm->pages)
- pm->page = 0;
- pm->x = 0;
+ if ( dict[i] == '\n' )
+ {
+ /* already typed out this whole word, look for another */
+ dict += i +1;
+ i = 0;
+ continue;
+ }
+ if ( dict[i] == 0 )
+ {
+ /* end of dictionary, give up */
+ return;
+ }
+ if ( partial[i] == dict[i] )
+ {
+ i++;
+ continue;
+ }
+ /* Case fuzz on first letter */
+ if ( !i && tolower(partial[i]) == tolower(dict[i]) )
+ {
+ i++;
+ continue;
+ }
+ if ( i == length ) /* got a match */
+ {
+ break;
+ }
+ /* mismatch, reset to next word */
+ while ( dict[++i] != '\n' )
+ if ( dict[i] == 0 )
+ return;
+ dict += i + 1;
+ i = 0;
}
+
+ /* 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;
+ sc->putsxy(0, pm->main_y+pm->font_h, state->pred_word);
}
-static void kbd_move_picker_vertical(struct keyboard_parameters *pm,
- struct edit_state *state, int dir)
+static void kbd_insert_predicted(struct edit_state *state)
{
- state->changed = CHANGED_PICKER;
+ int i;
-#ifdef HAVE_MORSE_INPUT
- if (state->morse_mode)
- {
- pm->line_edit = !pm->line_edit;
+ i = utf8seek(state->text,state->editpos);
+ if ( i + (int)strlen(state->pred_word) -
+ state->pred_input_len >= state->buflen )
return;
- }
-#endif /* HAVE_MORSE_INPUT */
- pm->y += dir;
- 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)
+ if( state->pred_word[0] )
{
- pm->line_edit = true;
+ strcpy( i + state->text,
+ state->pred_word + state->pred_input_len );
+
+ while ( state->text[utf8seek(state->text,state->editpos )] != 0 )
+ state->editpos++;
+ return;
}
}
+#endif
diff --git a/apps/settings.h b/apps/settings.h
index 62ae038..8d63730 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -773,9 +773,11 @@ struct user_settings
bool sleeptimer_on_startup;
bool keypress_restarts_sleeptimer;
-#ifdef HAVE_MORSE_INPUT
- bool morse_input; /* text input method setting */
+#if defined(HAVE_MORSE_INPUT) || defined(HAVE_SCROLLWHEEL)
+ int keyboard_mode;
#endif
+ unsigned char kbd_picker_font[MAX_FILENAME+1];
+ unsigned char kbd_edit_font[MAX_FILENAME+1];
#ifdef HAVE_HOTKEY
/* hotkey assignments - acceptable values are in
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 9b1ec44..c199a1f 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -2089,8 +2089,25 @@ const struct settings_list settings[] = {
#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
#ifdef HAVE_HOTKEY