diff options
Diffstat (limited to 'apps/player/keyboard.c')
-rw-r--r-- | apps/player/keyboard.c | 422 |
1 files changed, 188 insertions, 234 deletions
diff --git a/apps/player/keyboard.c b/apps/player/keyboard.c index 7752ce3ff7..76f64fbc88 100644 --- a/apps/player/keyboard.c +++ b/apps/player/keyboard.c | |||
@@ -19,13 +19,16 @@ | |||
19 | #include "lcd.h" | 19 | #include "lcd.h" |
20 | #include "button.h" | 20 | #include "button.h" |
21 | #include "kernel.h" | 21 | #include "kernel.h" |
22 | #include "system.h" | ||
22 | #include "version.h" | 23 | #include "version.h" |
23 | #include "debug_menu.h" | 24 | #include "debug_menu.h" |
24 | #include "sprintf.h" | 25 | #include "sprintf.h" |
25 | #include <string.h> | 26 | #include <string.h> |
26 | #include "lcd-player-charset.h" | 27 | #include "lcd-player-charset.h" |
27 | #include "lang.h" | 28 | #include "settings.h" |
28 | #include "debug.h" | 29 | #include "status.h" |
30 | #include "talk.h" | ||
31 | #include "misc.h" | ||
29 | 32 | ||
30 | #define KEYBOARD_PAGES 3 | 33 | #define KEYBOARD_PAGES 3 |
31 | 34 | ||
@@ -38,27 +41,28 @@ static unsigned short* kbd_setupkeys(int page, int* len) | |||
38 | unsigned short ch; | 41 | unsigned short ch; |
39 | int i = 0; | 42 | int i = 0; |
40 | 43 | ||
41 | switch (page) { | 44 | switch (page) |
42 | case 0: /* Capitals */ | 45 | { |
43 | for (ch = 'A'; ch <= 'Z'; ch++) | 46 | case 0: /* Capitals */ |
44 | lines[i++] = ch; | 47 | for (ch = 'A'; ch <= 'Z'; ch++) |
45 | for (ch = 0xc0; ch <= 0xdd; ch++) | ||
46 | if (lcd_ascii[ch] != NOCHAR_NEW && lcd_ascii[ch] != NOCHAR_OLD) | ||
47 | lines[i++] = ch; | 48 | lines[i++] = ch; |
48 | break; | 49 | for (ch = 0xc0; ch <= 0xdd; ch++) |
50 | if (lcd_ascii[ch] != NOCHAR_NEW && lcd_ascii[ch] != NOCHAR_OLD) | ||
51 | lines[i++] = ch; | ||
52 | break; | ||
49 | 53 | ||
50 | case 1: /* Small */ | 54 | case 1: /* Small */ |
51 | for (ch = 'a'; ch <= 'z'; ch++) | 55 | for (ch = 'a'; ch <= 'z'; ch++) |
52 | lines[i++] = ch; | ||
53 | for (ch = 0xdf; ch <= 0xff; ch++) | ||
54 | if (lcd_ascii[ch] != NOCHAR_NEW && lcd_ascii[ch] != NOCHAR_OLD) | ||
55 | lines[i++] = ch; | 56 | lines[i++] = ch; |
56 | break; | 57 | for (ch = 0xdf; ch <= 0xff; ch++) |
58 | if (lcd_ascii[ch] != NOCHAR_NEW && lcd_ascii[ch] != NOCHAR_OLD) | ||
59 | lines[i++] = ch; | ||
60 | break; | ||
57 | 61 | ||
58 | case 2: /* Others */ | 62 | case 2: /* Others */ |
59 | for (ch = ' '; ch <= '@'; ch++) | 63 | for (ch = ' '; ch <= '@'; ch++) |
60 | lines[i++] = ch; | 64 | lines[i++] = ch; |
61 | break; | 65 | break; |
62 | } | 66 | } |
63 | 67 | ||
64 | lines[i] = 0; | 68 | lines[i] = 0; |
@@ -74,254 +78,204 @@ static unsigned short* kbd_setupkeys(int page, int* len) | |||
74 | #define KEYBOARD_CURSOR 0x7f | 78 | #define KEYBOARD_CURSOR 0x7f |
75 | #define KEYBOARD_ARROW 0x92 | 79 | #define KEYBOARD_ARROW 0x92 |
76 | 80 | ||
77 | #define MENU_LINE_INPUT 0 | 81 | /* helper function to spell a char if voice UI is enabled */ |
78 | #define MENU_LINE_NEWCHARS 1 | 82 | static void kbd_spellchar(char c) |
79 | #define MENU_LINE_BACKSPACE 2 | 83 | { |
80 | #define MENU_LINE_DELETE 3 | 84 | static char spell_char[2] = "\0\0"; /* store char to pass to talk_spell */ |
81 | #define MENU_LINE_ACCEPT 4 | 85 | |
82 | #define MENU_LINE_QUIT 5 | 86 | if (global_settings.talk_menu) /* voice UI? */ |
83 | #define MENU_LINE_LAST 5 | 87 | { |
88 | spell_char[0] = c; | ||
89 | talk_spell(spell_char, false); | ||
90 | } | ||
91 | } | ||
84 | 92 | ||
85 | int kbd_input(char* text, int buflen) | 93 | int kbd_input(char* text, int buflen) |
86 | { | 94 | { |
87 | bool done = false; | 95 | bool done = false; |
88 | int page=0, x=0; | 96 | bool redraw = true; |
97 | bool line_edit = false; | ||
98 | int page = 0, x = 0; | ||
89 | int linelen; | 99 | int linelen; |
100 | |||
101 | int len, i; | ||
102 | int editpos, curpos, leftpos; | ||
90 | unsigned short* line = kbd_setupkeys(page, &linelen); | 103 | unsigned short* line = kbd_setupkeys(page, &linelen); |
91 | int menu_line=0; | ||
92 | int cursor_pos=0; | ||
93 | int button_pressed; | ||
94 | unsigned char temptext[12]; | 104 | unsigned char temptext[12]; |
95 | int old_cursor_pos=0; /* Windowed cursor movement */ | 105 | char c; |
96 | int left_pos=0; | ||
97 | |||
98 | lcd_clear_display(); | ||
99 | |||
100 | old_cursor_pos=cursor_pos=strlen(text); | ||
101 | if (9<cursor_pos) | ||
102 | left_pos=cursor_pos-9; | ||
103 | |||
104 | while (!done) { | ||
105 | int i, p; | ||
106 | int len = strlen(text); | ||
107 | int scrpos; | ||
108 | int dir; | ||
109 | |||
110 | scrpos = cursor_pos - left_pos; | ||
111 | dir = cursor_pos - old_cursor_pos; | ||
112 | |||
113 | /* Keep the cursor on screen, with a 2 character scroll margin */ | ||
114 | if(dir < 0) { | ||
115 | if(scrpos < 2) { | ||
116 | left_pos = cursor_pos - 2; | ||
117 | if(left_pos < 0) | ||
118 | left_pos = 0; | ||
119 | } | ||
120 | } | ||
121 | if(dir > 0) { | ||
122 | if(scrpos > 7) { | ||
123 | left_pos = cursor_pos - 9; | ||
124 | if(left_pos < 0) | ||
125 | left_pos = 0; | ||
126 | if(left_pos > len - 9) | ||
127 | left_pos = len - 9; | ||
128 | } | ||
129 | } | ||
130 | 106 | ||
131 | p=0; | 107 | int button, lastbutton = 0; |
132 | i = left_pos; | 108 | |
133 | while (p<10 && text[i]) { | 109 | editpos = strlen(text); |
134 | temptext[p++]=text[i++]; | 110 | |
111 | if (global_settings.talk_menu) /* voice UI? */ | ||
112 | talk_spell(text, true); /* spell initial text */ | ||
113 | |||
114 | while (!done) | ||
115 | { | ||
116 | len = strlen(text); | ||
117 | |||
118 | if (redraw) | ||
119 | { | ||
120 | if (line_edit) | ||
121 | { | ||
122 | lcd_putc(0, 0, ' '); | ||
123 | lcd_putc(0, 1, KEYBOARD_ARROW); | ||
124 | } | ||
125 | else | ||
126 | { | ||
127 | lcd_putc(0, 0, KEYBOARD_ARROW); | ||
128 | lcd_putc(0, 1, ' '); | ||
129 | } | ||
130 | |||
131 | /* Draw insert chars */ | ||
132 | temptext[0] = KEYBOARD_INSERT_LEFT; | ||
133 | temptext[1] = line[x%linelen]; | ||
134 | temptext[2] = KEYBOARD_INSERT_RIGHT; | ||
135 | for (i = 1; i < 8; i++) | ||
136 | { | ||
137 | temptext[i+2] = line[(i+x)%linelen]; | ||
138 | } | ||
139 | temptext[i+2] = 0; | ||
140 | lcd_puts(1, 0, temptext); | ||
141 | |||
142 | /* write out the text */ | ||
143 | curpos = MIN(editpos, 9 - MIN(len - editpos, 2)); | ||
144 | leftpos = editpos - curpos; | ||
145 | strncpy(temptext, text + leftpos, 10); | ||
146 | temptext[10] = 0; | ||
147 | |||
148 | if (leftpos) | ||
149 | temptext[0] = '<'; | ||
150 | if (len - leftpos > 10) | ||
151 | temptext[9] = '>'; | ||
152 | |||
153 | lcd_remove_cursor(); | ||
154 | lcd_puts(1, 1, temptext); | ||
155 | lcd_put_cursor(curpos + 1, 1, KEYBOARD_CURSOR); | ||
156 | |||
157 | status_draw(true); | ||
135 | } | 158 | } |
136 | temptext[p]=0; | 159 | |
137 | lcd_remove_cursor(); | 160 | /* The default action is to redraw */ |
138 | lcd_puts(1, 0, temptext); | 161 | redraw = true; |
139 | lcd_put_cursor(cursor_pos-left_pos+1, 0, 0x7f); | 162 | |
140 | old_cursor_pos=cursor_pos; | 163 | button = button_get_w_tmo(HZ/2); |
141 | 164 | switch (button) | |
142 | switch (menu_line) { | 165 | { |
143 | case MENU_LINE_INPUT: | 166 | case BUTTON_STOP: /* abort */ |
144 | case MENU_LINE_NEWCHARS: | 167 | return -1; |
145 | /* Draw insert chars */ | ||
146 | temptext[0]=KEYBOARD_INSERT_LEFT; | ||
147 | temptext[1]=line[x%linelen]; | ||
148 | temptext[2]=KEYBOARD_INSERT_RIGHT; | ||
149 | for (i=1; i < 8; i++) { | ||
150 | temptext[i+2]=line[(i+x)%linelen]; | ||
151 | } | ||
152 | temptext[i+2]=0; | ||
153 | lcd_puts(1, 1, temptext); | ||
154 | break; | ||
155 | case MENU_LINE_BACKSPACE: | ||
156 | lcd_puts_scroll(1, 1, str(LANG_PLAYER_KEYBOARD_BACKSPACE)); | ||
157 | break; | ||
158 | case MENU_LINE_DELETE: | ||
159 | lcd_puts_scroll(1, 1, str(LANG_PLAYER_KEYBOARD_DELETE)); | ||
160 | break; | 168 | break; |
161 | case MENU_LINE_ACCEPT: | 169 | |
162 | lcd_puts_scroll(1, 1, str(LANG_PLAYER_KEYBOARD_ACCEPT)); | 170 | case BUTTON_MENU: /* page flip */ |
171 | if (++page == KEYBOARD_PAGES) | ||
172 | page = 0; | ||
173 | line = kbd_setupkeys(page, &linelen); | ||
174 | if (x > linelen - 1) | ||
175 | x = linelen - 1; | ||
176 | kbd_spellchar(line[x]); | ||
163 | break; | 177 | break; |
164 | case MENU_LINE_QUIT: | 178 | |
165 | lcd_puts_scroll(1, 1, str(LANG_PLAYER_KEYBOARD_ABORT)); | 179 | case BUTTON_ON: /* toggle mode */ |
180 | line_edit = !line_edit; | ||
181 | if (!line_edit) | ||
182 | kbd_spellchar(line[x]); | ||
166 | break; | 183 | break; |
167 | } | ||
168 | if (menu_line==MENU_LINE_INPUT) { | ||
169 | lcd_putc(0, 0, KEYBOARD_ARROW); | ||
170 | lcd_putc(0, 1, ' '); | ||
171 | } else { | ||
172 | lcd_putc(0, 0, ' '); | ||
173 | lcd_putc(0, 1, KEYBOARD_ARROW); | ||
174 | } | ||
175 | |||
176 | lcd_update(); | ||
177 | 184 | ||
178 | button_pressed=button_get(true); | 185 | case BUTTON_RIGHT: |
179 | switch (menu_line) | 186 | case BUTTON_RIGHT | BUTTON_REPEAT: |
180 | { | 187 | if (line_edit) |
181 | case MENU_LINE_INPUT: | ||
182 | switch (button_pressed) | ||
183 | { | 188 | { |
184 | case BUTTON_PLAY: | 189 | if (editpos < len) |
185 | case BUTTON_PLAY | BUTTON_REPEAT: | 190 | { |
186 | if (cursor_pos<len) | 191 | editpos++; |
187 | cursor_pos++; | 192 | kbd_spellchar(text[editpos]); |
188 | button_pressed=BUTTON_NONE; | 193 | } |
189 | break; | ||
190 | |||
191 | case BUTTON_STOP: | ||
192 | case BUTTON_STOP | BUTTON_REPEAT: | ||
193 | if (cursor_pos>0) | ||
194 | cursor_pos--; | ||
195 | button_pressed=BUTTON_NONE; | ||
196 | break; | ||
197 | } | 194 | } |
198 | break; | 195 | else |
199 | |||
200 | case MENU_LINE_NEWCHARS: | ||
201 | switch (button_pressed) | ||
202 | { | 196 | { |
203 | case BUTTON_PLAY: | 197 | if (x < linelen - 1) |
204 | case BUTTON_PLAY | BUTTON_REPEAT: | 198 | x++; |
205 | x=(x+1+linelen)%linelen; | 199 | else |
206 | button_pressed=BUTTON_NONE; | 200 | x = 0; |
207 | break; | 201 | kbd_spellchar(line[x]); |
208 | case BUTTON_STOP: | ||
209 | case BUTTON_STOP | BUTTON_REPEAT: | ||
210 | x=(x-1+linelen)%linelen; | ||
211 | button_pressed=BUTTON_NONE; | ||
212 | break; | ||
213 | |||
214 | case BUTTON_MENU: | ||
215 | /* shift */ | ||
216 | if (++page == KEYBOARD_PAGES) | ||
217 | page = 0; | ||
218 | line = kbd_setupkeys(page, &linelen); | ||
219 | break; | ||
220 | |||
221 | case BUTTON_ON: | ||
222 | if (len < buflen) { | ||
223 | /* ON insert the char */ | ||
224 | for (i=len+1; i>cursor_pos; i--) { | ||
225 | text[i]=text[i-1]; | ||
226 | } | ||
227 | text[cursor_pos]=line[x]; | ||
228 | button_pressed=BUTTON_NONE; | ||
229 | cursor_pos++; | ||
230 | } | ||
231 | break; | ||
232 | } | 202 | } |
233 | break; | 203 | break; |
234 | 204 | ||
235 | case MENU_LINE_BACKSPACE: | 205 | case BUTTON_LEFT: |
236 | switch (button_pressed) { | 206 | case BUTTON_LEFT | BUTTON_REPEAT: |
237 | case BUTTON_ON: | 207 | if (line_edit) |
238 | case BUTTON_PLAY: | 208 | { |
239 | case BUTTON_PLAY | BUTTON_REPEAT: | 209 | if (editpos) |
240 | button_pressed=BUTTON_NONE; | 210 | { |
241 | if (0 < cursor_pos) { | 211 | editpos--; |
242 | for (i=--cursor_pos; i<=len; i++) { | 212 | kbd_spellchar(text[editpos]); |
243 | text[i]=text[i+1]; | 213 | } |
244 | } | ||
245 | } | ||
246 | break; | ||
247 | case BUTTON_STOP: | ||
248 | case BUTTON_STOP | BUTTON_REPEAT: | ||
249 | button_pressed=BUTTON_NONE; | ||
250 | for (i=cursor_pos; i<=len; i++) { | ||
251 | text[i]=text[i+1]; | ||
252 | } | ||
253 | break; | ||
254 | } | 214 | } |
255 | break; | 215 | else |
256 | case MENU_LINE_DELETE: | 216 | { |
257 | switch (button_pressed) { | 217 | if (x) |
258 | case BUTTON_ON: | 218 | x--; |
259 | case BUTTON_PLAY: | 219 | else |
260 | case BUTTON_PLAY | BUTTON_REPEAT: | 220 | x = linelen - 1; |
261 | button_pressed=BUTTON_NONE; | 221 | kbd_spellchar(line[x]); |
262 | for (i=cursor_pos; i<=len; i++) { | ||
263 | text[i]=text[i+1]; | ||
264 | } | ||
265 | break; | ||
266 | case BUTTON_STOP: | ||
267 | case BUTTON_STOP | BUTTON_REPEAT: | ||
268 | button_pressed=BUTTON_NONE; | ||
269 | if (0 < cursor_pos) | ||
270 | for (i=--cursor_pos; i<=len; i++) { | ||
271 | text[i]=text[i+1]; | ||
272 | } | ||
273 | break; | ||
274 | } | 222 | } |
275 | break; | 223 | break; |
276 | 224 | ||
277 | case MENU_LINE_ACCEPT: | 225 | case BUTTON_PLAY | BUTTON_REPEAT: |
278 | switch (button_pressed) { | 226 | /* accepts what was entered and continues */ |
279 | case BUTTON_ON: | 227 | done = true; |
280 | case BUTTON_PLAY: | ||
281 | case BUTTON_PLAY | BUTTON_REPEAT: | ||
282 | button_pressed=BUTTON_NONE; | ||
283 | done=true; | ||
284 | break; | ||
285 | } | ||
286 | break; | 228 | break; |
287 | 229 | ||
288 | case MENU_LINE_QUIT: | 230 | case BUTTON_PLAY | BUTTON_REL: |
289 | switch (button_pressed) { | 231 | if (lastbutton != BUTTON_PLAY) |
290 | case BUTTON_ON: | 232 | break; |
291 | case BUTTON_PLAY: | 233 | if (line_edit) /* backspace in line_edit */ |
292 | case BUTTON_PLAY | BUTTON_REPEAT: | 234 | { |
293 | return 1; | 235 | if (editpos > 0) |
294 | break; | 236 | { |
237 | for (i = editpos; i < len; i++) | ||
238 | text[i-1] = text[i]; | ||
239 | text[i-1] = '\0'; | ||
240 | editpos--; | ||
241 | } | ||
295 | } | 242 | } |
243 | else /* inserts the selected char */ | ||
244 | { | ||
245 | if (len < buflen) | ||
246 | { | ||
247 | c = line[x]; | ||
248 | if (editpos == len) | ||
249 | { | ||
250 | text[len] = c; | ||
251 | text[len+1] = 0; | ||
252 | } | ||
253 | else | ||
254 | { | ||
255 | for (i = len ; i >= editpos; i--) | ||
256 | text[i+1] = text[i]; | ||
257 | text[editpos] = c; | ||
258 | } | ||
259 | editpos++; | ||
260 | } | ||
261 | } | ||
262 | if (global_settings.talk_menu) /* voice UI? */ | ||
263 | talk_spell(text, false); /* speak revised text */ | ||
296 | break; | 264 | break; |
297 | } | ||
298 | 265 | ||
299 | /* Handle unhandled events */ | ||
300 | switch (button_pressed) { | ||
301 | case BUTTON_NONE: | 266 | case BUTTON_NONE: |
302 | /* button is already handled */ | 267 | status_draw(false); |
268 | redraw = false; | ||
303 | break; | 269 | break; |
304 | 270 | ||
305 | case BUTTON_MENU | BUTTON_STOP: | 271 | default: |
306 | break; | 272 | default_event_handler(button); |
307 | |||
308 | case BUTTON_RIGHT: | ||
309 | case BUTTON_RIGHT | BUTTON_REPEAT: | ||
310 | if (menu_line<MENU_LINE_LAST) | ||
311 | menu_line++; | ||
312 | else | ||
313 | menu_line=0; | ||
314 | break; | ||
315 | |||
316 | case BUTTON_LEFT: | ||
317 | case BUTTON_LEFT | BUTTON_REPEAT: | ||
318 | if (menu_line>0) | ||
319 | menu_line--; | ||
320 | else | ||
321 | menu_line=MENU_LINE_LAST; | ||
322 | break; | 273 | break; |
323 | } | 274 | } |
275 | if (button != BUTTON_NONE) | ||
276 | lastbutton = button; | ||
324 | } | 277 | } |
325 | 278 | ||
326 | return 0; | 279 | return 0; |
327 | } | 280 | } |
281 | |||