diff options
Diffstat (limited to 'apps/plugins/zxbox/zxbox_keyb.c')
-rw-r--r-- | apps/plugins/zxbox/zxbox_keyb.c | 497 |
1 files changed, 497 insertions, 0 deletions
diff --git a/apps/plugins/zxbox/zxbox_keyb.c b/apps/plugins/zxbox/zxbox_keyb.c new file mode 100644 index 0000000000..685d9ce6bb --- /dev/null +++ b/apps/plugins/zxbox/zxbox_keyb.c | |||
@@ -0,0 +1,497 @@ | |||
1 | #include "zxconfig.h" | ||
2 | |||
3 | #ifndef O_BINARY | ||
4 | #define O_BINARY 0 | ||
5 | #endif | ||
6 | |||
7 | #if CONFIG_KEYPAD == RECORDER_PAD | ||
8 | #define BUTTONBAR_HEIGHT 8 | ||
9 | #else | ||
10 | #define BUTTONBAR_HEIGHT 0 | ||
11 | #endif | ||
12 | |||
13 | #define DEFAULT_MARGIN 6 | ||
14 | #define KBD_BUF_SIZE 500 | ||
15 | #define kbd_loaded false | ||
16 | #define statusbar_size 0 | ||
17 | |||
18 | #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ | ||
19 | (CONFIG_KEYPAD == IRIVER_H300_PAD) | ||
20 | #define KBD_SELECT BUTTON_SELECT | ||
21 | #define KBD_ABORT BUTTON_OFF | ||
22 | #define KBD_LEFT BUTTON_LEFT | ||
23 | #define KBD_RIGHT BUTTON_RIGHT | ||
24 | #define KBD_UP BUTTON_UP | ||
25 | #define KBD_DOWN BUTTON_DOWN | ||
26 | |||
27 | #elif CONFIG_KEYPAD == RECORDER_PAD | ||
28 | #define KBD_SELECT BUTTON_PLAY | ||
29 | #define KBD_ABORT BUTTON_OFF | ||
30 | #define KBD_LEFT BUTTON_LEFT | ||
31 | #define KBD_RIGHT BUTTON_RIGHT | ||
32 | #define KBD_UP BUTTON_UP | ||
33 | #define KBD_DOWN BUTTON_DOWN | ||
34 | |||
35 | #elif CONFIG_KEYPAD == ONDIO_PAD /* restricted Ondio keypad */ | ||
36 | #define KBD_SELECT BUTTON_MENU | ||
37 | #define KBD_ABORT BUTTON_OFF | ||
38 | #define KBD_LEFT BUTTON_LEFT | ||
39 | #define KBD_RIGHT BUTTON_RIGHT | ||
40 | #define KBD_UP BUTTON_UP | ||
41 | #define KBD_DOWN BUTTON_DOWN | ||
42 | |||
43 | #elif CONFIG_KEYPAD == GMINI100_PAD | ||
44 | #define KBD_SELECT BUTTON_PLAY | ||
45 | #define KBD_ABORT BUTTON_OFF | ||
46 | #define KBD_LEFT BUTTON_LEFT | ||
47 | #define KBD_RIGHT BUTTON_RIGHT | ||
48 | #define KBD_UP BUTTON_UP | ||
49 | #define KBD_DOWN BUTTON_DOWN | ||
50 | |||
51 | #elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) | ||
52 | |||
53 | #define KBD_SELECT BUTTON_SELECT | ||
54 | #define KBD_ABORT BUTTON_MENU | ||
55 | #define KBD_LEFT BUTTON_LEFT | ||
56 | #define KBD_RIGHT BUTTON_RIGHT | ||
57 | #define KBD_UP BUTTON_SCROLL_BACK | ||
58 | #define KBD_DOWN BUTTON_SCROLL_FWD | ||
59 | |||
60 | #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD | ||
61 | |||
62 | /* TODO: Check keyboard mappings */ | ||
63 | |||
64 | #define KBD_SELECT BUTTON_SELECT | ||
65 | #define KBD_ABORT BUTTON_PLAY | ||
66 | #define KBD_LEFT BUTTON_LEFT | ||
67 | #define KBD_RIGHT BUTTON_RIGHT | ||
68 | #define KBD_UP BUTTON_UP | ||
69 | #define KBD_DOWN BUTTON_DOWN | ||
70 | |||
71 | #elif CONFIG_KEYPAD == IAUDIO_X5_PAD | ||
72 | |||
73 | /* TODO: Check keyboard mappings */ | ||
74 | |||
75 | #define KBD_SELECT BUTTON_SELECT | ||
76 | #define KBD_ABORT BUTTON_REC | ||
77 | #define KBD_LEFT BUTTON_LEFT | ||
78 | #define KBD_RIGHT BUTTON_RIGHT | ||
79 | #define KBD_UP BUTTON_UP | ||
80 | #define KBD_DOWN BUTTON_DOWN | ||
81 | |||
82 | #elif CONFIG_KEYPAD == GIGABEAT_PAD | ||
83 | |||
84 | #define KBD_SELECT BUTTON_SELECT | ||
85 | #define KBD_ABORT BUTTON_A | ||
86 | #define KBD_LEFT BUTTON_LEFT | ||
87 | #define KBD_RIGHT BUTTON_RIGHT | ||
88 | #define KBD_UP BUTTON_UP | ||
89 | #define KBD_DOWN BUTTON_DOWN | ||
90 | |||
91 | #elif CONFIG_KEYPAD == IRIVER_H10_PAD | ||
92 | |||
93 | /* TODO: Check keyboard mappings */ | ||
94 | |||
95 | #define KBD_SELECT BUTTON_REW | ||
96 | #define KBD_ABORT BUTTON_FF | ||
97 | #define KBD_LEFT BUTTON_LEFT | ||
98 | #define KBD_RIGHT BUTTON_RIGHT | ||
99 | #define KBD_UP BUTTON_SCROLL_UP | ||
100 | #define KBD_DOWN BUTTON_SCROLL_DOWN | ||
101 | |||
102 | #endif | ||
103 | |||
104 | |||
105 | struct keyboard_parameters { | ||
106 | const unsigned char* default_kbd; | ||
107 | int DEFAULT_LINES; | ||
108 | unsigned short kbd_buf[KBD_BUF_SIZE]; | ||
109 | int nchars; | ||
110 | int font_w; | ||
111 | int font_h; | ||
112 | struct font* font; | ||
113 | int curfont; | ||
114 | int main_x; | ||
115 | int main_y; | ||
116 | int max_chars; | ||
117 | int max_chars_text; | ||
118 | int lines; | ||
119 | int pages; | ||
120 | int keyboard_margin; | ||
121 | int old_main_y; | ||
122 | int curpos; | ||
123 | int leftpos; | ||
124 | int page; | ||
125 | int x; | ||
126 | int y; | ||
127 | }; | ||
128 | |||
129 | struct keyboard_parameters param[NB_SCREENS]; | ||
130 | |||
131 | int zx_kbd_input(char* text/*, int buflen*/) | ||
132 | { | ||
133 | bool done = false; | ||
134 | int i, j, k, w, l; | ||
135 | int text_w = 0; | ||
136 | int len_utf8/*, c = 0*/; | ||
137 | int editpos; | ||
138 | /* int statusbar_size = global_settings.statusbar ? STATUSBAR_HEIGHT : 0;*/ | ||
139 | unsigned short ch/*, tmp, hlead = 0, hvowel = 0, htail = 0*/; | ||
140 | /*bool hangul = false;*/ | ||
141 | unsigned char *utf8; | ||
142 | const unsigned char *p; | ||
143 | bool cur_blink = true; | ||
144 | int char_screen = 0; | ||
145 | |||
146 | FOR_NB_SCREENS(l) | ||
147 | { | ||
148 | param[l].default_kbd = | ||
149 | "1234567890\n" | ||
150 | "qwertyuiop\n" | ||
151 | "asdfghjkl\n" | ||
152 | "zxcvbnm\n" | ||
153 | "S\n" | ||
154 | "E"; | ||
155 | |||
156 | param[l].DEFAULT_LINES = 7; | ||
157 | } | ||
158 | |||
159 | char outline[256]; | ||
160 | int button, lastbutton = 0; | ||
161 | FOR_NB_SCREENS(l) | ||
162 | { | ||
163 | /* Copy default keyboard to buffer */ | ||
164 | i = 0; | ||
165 | param[l].curfont = FONT_SYSFIXED; | ||
166 | p = param[l].default_kbd; | ||
167 | while (*p != 0) | ||
168 | p = rb->utf8decode(p, ¶m[l].kbd_buf[i++]); | ||
169 | param[l].nchars = i; | ||
170 | /* param[l].curfont = FONT_UI;*/ | ||
171 | } | ||
172 | FOR_NB_SCREENS(l) | ||
173 | { | ||
174 | param[l].font = rb->font_get(param[l].curfont); | ||
175 | param[l].font_h = param[l].font->height; | ||
176 | |||
177 | /* check if FONT_UI fits the screen */ | ||
178 | if (2*param[l].font_h+3 + BUTTONBAR_HEIGHT > rb->screens[l]->height) { | ||
179 | param[l].font = rb->font_get(FONT_SYSFIXED); | ||
180 | param[l].font_h = param[l].font->height; | ||
181 | param[l].curfont = FONT_SYSFIXED; | ||
182 | } | ||
183 | |||
184 | rb->screens[l]->setfont(param[l].curfont); | ||
185 | /* find max width of keyboard glyphs */ | ||
186 | for (i=0; i<param[l].nchars; i++) { | ||
187 | w = rb->font_get_width(param[l].font, param[l].kbd_buf[i]); | ||
188 | if (w > param[l].font_w) | ||
189 | param[l].font_w = w; | ||
190 | } | ||
191 | /* Since we're going to be adding spaces, make sure that we check | ||
192 | * their width too */ | ||
193 | w = rb->font_get_width( param[l].font, ' ' ); | ||
194 | if( w > param[l].font_w ) | ||
195 | param[l].font_w = w; | ||
196 | } | ||
197 | FOR_NB_SCREENS(l) | ||
198 | { | ||
199 | i = 0; | ||
200 | /* Pad lines with spaces */ | ||
201 | while( i < param[l].nchars ) | ||
202 | { | ||
203 | if( param[l].kbd_buf[i] == '\n' ) | ||
204 | { | ||
205 | k = ( rb->screens[l]->width / param[l].font_w ) | ||
206 | - i % ( rb->screens[l]->width / param[l].font_w ) - 1; | ||
207 | if( k == ( rb->screens[l]->width / param[l].font_w ) - 1 ) | ||
208 | { | ||
209 | param[l].nchars--; | ||
210 | for( j = i; j < param[l].nchars; j++ ) | ||
211 | { | ||
212 | param[l].kbd_buf[j] = param[l].kbd_buf[j+1]; | ||
213 | } | ||
214 | } | ||
215 | else | ||
216 | { | ||
217 | if( param[l].nchars + k - 1 >= KBD_BUF_SIZE ) | ||
218 | { /* We don't want to overflow the buffer */ | ||
219 | k = KBD_BUF_SIZE - param[l].nchars; | ||
220 | } | ||
221 | for( j = param[l].nchars + k - 1; j > i+k; j-- ) | ||
222 | { | ||
223 | param[l].kbd_buf[j] = param[l].kbd_buf[j-k]; | ||
224 | } | ||
225 | param[l].nchars += k; | ||
226 | k++; | ||
227 | while( k-- ) | ||
228 | { | ||
229 | param[l].kbd_buf[i++] = ' '; | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | else | ||
234 | i++; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | /* find max width for text string */ | ||
239 | utf8 = text; | ||
240 | FOR_NB_SCREENS(l) | ||
241 | { | ||
242 | text_w = param[l].font_w; | ||
243 | while (*utf8) { | ||
244 | utf8 = (unsigned char*)rb->utf8decode(utf8, &ch); | ||
245 | w = rb->font_get_width(param[l].font, ch); | ||
246 | if (w > text_w) | ||
247 | text_w = w; | ||
248 | } | ||
249 | param[l].max_chars_text = rb->screens[l]->width / text_w - 2; | ||
250 | |||
251 | /* calculate keyboard grid size */ | ||
252 | param[l].max_chars = rb->screens[l]->width / param[l].font_w; | ||
253 | if (!kbd_loaded) { | ||
254 | param[l].lines = param[l].DEFAULT_LINES; | ||
255 | param[l].keyboard_margin = DEFAULT_MARGIN; | ||
256 | } else { | ||
257 | param[l].lines = (rb->screens[l]->height - BUTTONBAR_HEIGHT - statusbar_size) / param[l].font_h - 1; | ||
258 | param[l].keyboard_margin = rb->screens[l]->height - BUTTONBAR_HEIGHT - | ||
259 | statusbar_size - (param[l].lines+1)*param[l].font_h; | ||
260 | if (param[l].keyboard_margin < 3) { | ||
261 | param[l].lines--; | ||
262 | param[l].keyboard_margin += param[l].font_h; | ||
263 | } | ||
264 | if (param[l].keyboard_margin > 6) | ||
265 | param[l].keyboard_margin = 6; | ||
266 | } | ||
267 | |||
268 | param[l].pages = (param[l].nchars + (param[l].lines*param[l].max_chars-1)) | ||
269 | /(param[l].lines*param[l].max_chars); | ||
270 | if (param[l].pages == 1 && kbd_loaded) | ||
271 | param[l].lines = (param[l].nchars + param[l].max_chars - 1) / param[l].max_chars; | ||
272 | |||
273 | param[l].main_y = param[l].font_h*param[l].lines + param[l].keyboard_margin + statusbar_size; | ||
274 | param[l].main_x = 0; | ||
275 | param[l].keyboard_margin -= param[l].keyboard_margin/2; | ||
276 | |||
277 | } | ||
278 | editpos = rb->utf8length(text); | ||
279 | |||
280 | |||
281 | |||
282 | while(!done) | ||
283 | { | ||
284 | len_utf8 = rb->utf8length(text); | ||
285 | FOR_NB_SCREENS(l) | ||
286 | rb->screens[l]->clear_display(); | ||
287 | |||
288 | |||
289 | /* draw page */ | ||
290 | FOR_NB_SCREENS(l) | ||
291 | { | ||
292 | rb->screens[l]->setfont(param[l].curfont); | ||
293 | k = param[l].page*param[l].max_chars*param[l].lines; | ||
294 | for (i=j=0; j < param[l].lines && k < param[l].nchars; k++) { | ||
295 | utf8 = rb->utf8encode(param[l].kbd_buf[k], outline); | ||
296 | *utf8 = 0; | ||
297 | rb->screens[l]->getstringsize(outline, &w, NULL); | ||
298 | rb->screens[l]->putsxy(i*param[l].font_w + (param[l].font_w-w)/2, j*param[l].font_h | ||
299 | + statusbar_size, outline); | ||
300 | if (++i == param[l].max_chars) { | ||
301 | i = 0; | ||
302 | j++; | ||
303 | } | ||
304 | } | ||
305 | } | ||
306 | |||
307 | |||
308 | /* separator */ | ||
309 | FOR_NB_SCREENS(l) | ||
310 | { | ||
311 | rb->screens[l]->hline(0, rb->screens[l]->width - 1, param[l].main_y - param[l].keyboard_margin); | ||
312 | |||
313 | /* write out the text */ | ||
314 | #if 0 | ||
315 | rb->screens[l]->setfont(param[l].curfont); | ||
316 | |||
317 | i=j=0; | ||
318 | param[l].curpos = MIN(editpos, param[l].max_chars_text | ||
319 | - MIN(len_utf8 - editpos, 2)); | ||
320 | param[l].leftpos = editpos - param[l].curpos; | ||
321 | utf8 = text + rb->utf8seek(text, param[l].leftpos); | ||
322 | |||
323 | text_w = param[l].font_w; | ||
324 | while (*utf8 && i < param[l].max_chars_text) { | ||
325 | outline[j++] = *utf8++; | ||
326 | if ((*utf8 & MASK) != COMP) { | ||
327 | outline[j] = 0; | ||
328 | j=0; | ||
329 | i++; | ||
330 | rb->screens[l]->getstringsize(outline, &w, NULL); | ||
331 | rb->screens[l]->putsxy(i*text_w + (text_w-w)/2, param[l].main_y, outline); | ||
332 | } | ||
333 | } | ||
334 | |||
335 | if (param[l].leftpos) { | ||
336 | rb->screens[l]->getstringsize("<", &w, NULL); | ||
337 | rb->screens[l]->putsxy(text_w - w, param[l].main_y, "<"); | ||
338 | } | ||
339 | if (len_utf8 - param[l].leftpos > param[l].max_chars_text) | ||
340 | rb->screens[l]->putsxy(rb->screens[l]->width - text_w, param[l].main_y, ">"); | ||
341 | |||
342 | /* cursor */ | ||
343 | i = (param[l].curpos + 1) * text_w; | ||
344 | if (cur_blink) | ||
345 | rb->screens[l]->vline(i, param[l].main_y, param[l].main_y + param[l].font_h-1); | ||
346 | |||
347 | if (hangul) /* draw underbar */ | ||
348 | rb->screens[l]->hline(param[l].curpos*text_w, (param[l].curpos+1)*text_w, | ||
349 | param[l].main_y+param[l].font_h-1); | ||
350 | #endif | ||
351 | } | ||
352 | cur_blink = !cur_blink; | ||
353 | |||
354 | |||
355 | /* highlight the key that has focus */ | ||
356 | FOR_NB_SCREENS(l) | ||
357 | { | ||
358 | rb->screens[l]->set_drawmode(DRMODE_COMPLEMENT); | ||
359 | rb->screens[l]->fillrect(param[l].font_w * param[l].x, | ||
360 | statusbar_size + param[l].font_h * param[l].y, | ||
361 | param[l].font_w, param[l].font_h); | ||
362 | rb->screens[l]->set_drawmode(DRMODE_SOLID); | ||
363 | } | ||
364 | |||
365 | |||
366 | /* gui_syncstatusbar_draw(&statusbars, true);*/ | ||
367 | FOR_NB_SCREENS(l) | ||
368 | rb->screens[l]->update(); | ||
369 | |||
370 | button = rb->button_get_w_tmo(HZ/2); | ||
371 | |||
372 | switch ( button ) { | ||
373 | |||
374 | case KBD_ABORT: | ||
375 | FOR_NB_SCREENS(l) | ||
376 | rb->screens[l]->setfont(FONT_UI); | ||
377 | |||
378 | return -1; | ||
379 | break; | ||
380 | |||
381 | case KBD_RIGHT: | ||
382 | case KBD_RIGHT | BUTTON_REPEAT: | ||
383 | { | ||
384 | FOR_NB_SCREENS(l) | ||
385 | { | ||
386 | if (++param[l].x == param[l].max_chars) { | ||
387 | param[l].x = 0; | ||
388 | /* no dedicated flip key - flip page on wrap */ | ||
389 | if (++param[l].page == param[l].pages) | ||
390 | param[l].page = 0; | ||
391 | } | ||
392 | k = (param[l].page*param[l].lines + param[l].y)*param[l].max_chars + param[l].x; | ||
393 | /*kbd_spellchar(param[l].kbd_buf[k]);*/ | ||
394 | } | ||
395 | } | ||
396 | break; | ||
397 | case KBD_LEFT: | ||
398 | case KBD_LEFT | BUTTON_REPEAT: | ||
399 | { | ||
400 | FOR_NB_SCREENS(l) | ||
401 | { | ||
402 | if (param[l].x) | ||
403 | param[l].x--; | ||
404 | else | ||
405 | { | ||
406 | /* no dedicated flip key - flip page on wrap */ | ||
407 | if (--param[l].page < 0) | ||
408 | param[l].page = (param[l].pages-1); | ||
409 | param[l].x = param[l].max_chars - 1; | ||
410 | } | ||
411 | k = (param[l].page*param[l].lines + | ||
412 | param[l].y)*param[l].max_chars + param[l].x; | ||
413 | /* kbd_spellchar(param[l].kbd_buf[k]);*/ | ||
414 | } | ||
415 | } | ||
416 | break; | ||
417 | |||
418 | case KBD_DOWN: | ||
419 | case KBD_DOWN | BUTTON_REPEAT: | ||
420 | { | ||
421 | FOR_NB_SCREENS(l) | ||
422 | { | ||
423 | if (param[l].y < param[l].lines - 1) | ||
424 | param[l].y++; | ||
425 | else | ||
426 | param[l].y=0; | ||
427 | } | ||
428 | FOR_NB_SCREENS(l) | ||
429 | { | ||
430 | k = (param[l].page*param[l].lines + param[l].y)* | ||
431 | param[l].max_chars + param[l].x; | ||
432 | /*kbd_spellchar(param[l].kbd_buf[k]);*/ | ||
433 | } | ||
434 | } | ||
435 | break; | ||
436 | |||
437 | case KBD_UP: | ||
438 | case KBD_UP | BUTTON_REPEAT: | ||
439 | { | ||
440 | FOR_NB_SCREENS(l) | ||
441 | { | ||
442 | if (param[l].y) | ||
443 | param[l].y--; | ||
444 | else | ||
445 | param[l].y = param[l].lines - 1; | ||
446 | } | ||
447 | FOR_NB_SCREENS(l) | ||
448 | { | ||
449 | k = (param[l].page*param[l].lines + param[l].y)* | ||
450 | param[l].max_chars + param[l].x; | ||
451 | /*kbd_spellchar(param[l].kbd_buf[k]);*/ | ||
452 | } | ||
453 | } | ||
454 | break; | ||
455 | |||
456 | case KBD_SELECT: | ||
457 | { | ||
458 | if (button == KBD_SELECT) | ||
459 | char_screen = 0; | ||
460 | |||
461 | /* inserts the selected char */ | ||
462 | |||
463 | /* find input char */ | ||
464 | k = (param[char_screen].page*param[char_screen].lines + | ||
465 | param[char_screen].y)*param[char_screen].max_chars + | ||
466 | param[char_screen].x; | ||
467 | if (k < param[char_screen].nchars) | ||
468 | ch = param[char_screen].kbd_buf[k]; | ||
469 | else | ||
470 | ch = ' '; | ||
471 | text[0]=ch; | ||
472 | done = true; | ||
473 | } | ||
474 | break; | ||
475 | |||
476 | case BUTTON_NONE: | ||
477 | /*gui_syncstatusbar_draw(&statusbars, false);*/ | ||
478 | |||
479 | break; | ||
480 | |||
481 | default: | ||
482 | if(rb->default_event_handler(button) == SYS_USB_CONNECTED) | ||
483 | FOR_NB_SCREENS(l) | ||
484 | rb->screens[l]->setfont(FONT_SYSFIXED); | ||
485 | break; | ||
486 | |||
487 | } | ||
488 | if (button != BUTTON_NONE) | ||
489 | { | ||
490 | lastbutton = button; | ||
491 | cur_blink = true; | ||
492 | } | ||
493 | } | ||
494 | FOR_NB_SCREENS(l) | ||
495 | rb->screens[l]->setfont(FONT_UI); | ||
496 | return 0; | ||
497 | } | ||