fix the last warning
[kugel-rb.git] / apps / plugins / zxbox / zxbox_keyb.c
blob2b1d171c114483fac3f83c36d7eabdbb8e755030
1 #include "zxconfig.h"
3 #ifndef O_BINARY
4 #define O_BINARY 0
5 #endif
7 #if CONFIG_KEYPAD == RECORDER_PAD
8 #define BUTTONBAR_HEIGHT 8
9 #else
10 #define BUTTONBAR_HEIGHT 0
11 #endif
13 #define DEFAULT_MARGIN 6
14 #define KBD_BUF_SIZE 500
15 #define kbd_loaded false
16 #define statusbar_size 0
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
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
35 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
36 #define KBD_SELECT BUTTON_SELECT
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
43 #elif CONFIG_KEYPAD == ONDIO_PAD /* restricted Ondio keypad */
44 #define KBD_SELECT BUTTON_MENU
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
51 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
52 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
53 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
55 #define KBD_SELECT BUTTON_SELECT
56 #define KBD_ABORT BUTTON_MENU
57 #define KBD_LEFT BUTTON_LEFT
58 #define KBD_RIGHT BUTTON_RIGHT
59 #define KBD_UP BUTTON_SCROLL_BACK
60 #define KBD_DOWN BUTTON_SCROLL_FWD
62 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
64 /* TODO: Check keyboard mappings */
66 #define KBD_SELECT BUTTON_SELECT
67 #define KBD_ABORT BUTTON_PLAY
68 #define KBD_LEFT BUTTON_LEFT
69 #define KBD_RIGHT BUTTON_RIGHT
70 #define KBD_UP BUTTON_UP
71 #define KBD_DOWN BUTTON_DOWN
73 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
75 /* TODO: Check keyboard mappings */
77 #define KBD_SELECT BUTTON_SELECT
78 #define KBD_ABORT BUTTON_REC
79 #define KBD_LEFT BUTTON_LEFT
80 #define KBD_RIGHT BUTTON_RIGHT
81 #define KBD_UP BUTTON_UP
82 #define KBD_DOWN BUTTON_DOWN
84 #elif CONFIG_KEYPAD == GIGABEAT_PAD
86 #define KBD_SELECT BUTTON_SELECT
87 #define KBD_ABORT BUTTON_POWER
88 #define KBD_LEFT BUTTON_LEFT
89 #define KBD_RIGHT BUTTON_RIGHT
90 #define KBD_UP BUTTON_UP
91 #define KBD_DOWN BUTTON_DOWN
93 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
95 /* TODO: Check keyboard mappings */
97 #define KBD_SELECT BUTTON_REW
98 #define KBD_ABORT BUTTON_FF
99 #define KBD_LEFT BUTTON_LEFT
100 #define KBD_RIGHT BUTTON_RIGHT
101 #define KBD_UP BUTTON_SCROLL_UP
102 #define KBD_DOWN BUTTON_SCROLL_DOWN
104 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
105 (CONFIG_KEYPAD == SANSA_C200_PAD)
107 /* TODO: Check keyboard mappings */
109 #define KBD_SELECT BUTTON_SELECT
110 #define KBD_ABORT BUTTON_POWER
111 #define KBD_LEFT BUTTON_LEFT
112 #define KBD_RIGHT BUTTON_RIGHT
113 #define KBD_UP BUTTON_UP
114 #define KBD_DOWN BUTTON_DOWN
116 #endif
119 struct keyboard_parameters {
120 const unsigned char* default_kbd;
121 int DEFAULT_LINES;
122 unsigned short kbd_buf[KBD_BUF_SIZE];
123 int nchars;
124 int font_w;
125 int font_h;
126 struct font* font;
127 int curfont;
128 int main_x;
129 int main_y;
130 int max_chars;
131 int max_chars_text;
132 int lines;
133 int pages;
134 int keyboard_margin;
135 int old_main_y;
136 int curpos;
137 int leftpos;
138 int page;
139 int x;
140 int y;
143 struct keyboard_parameters param[NB_SCREENS];
145 int zx_kbd_input(char* text/*, int buflen*/)
147 bool done = false;
148 int i, j, k, w, l;
149 int text_w = 0;
150 int len_utf8/*, c = 0*/;
151 int editpos;
152 /* int statusbar_size = global_settings.statusbar ? STATUSBAR_HEIGHT : 0;*/
153 unsigned short ch/*, tmp, hlead = 0, hvowel = 0, htail = 0*/;
154 /*bool hangul = false;*/
155 unsigned char *utf8;
156 const unsigned char *p;
157 bool cur_blink = true;
158 int char_screen = 0;
160 FOR_NB_SCREENS(l)
162 param[l].default_kbd =
163 "1234567890\n"
164 "qwertyuiop\n"
165 "asdfghjkl\n"
166 "zxcvbnm\n"
167 "S\n"
168 "E";
170 param[l].DEFAULT_LINES = 7;
173 char outline[256];
174 int button, lastbutton = 0;
175 FOR_NB_SCREENS(l)
177 /* Copy default keyboard to buffer */
178 i = 0;
179 param[l].curfont = FONT_SYSFIXED;
180 p = param[l].default_kbd;
181 while (*p != 0)
182 p = rb->utf8decode(p, &param[l].kbd_buf[i++]);
183 param[l].nchars = i;
184 /* param[l].curfont = FONT_UI;*/
186 FOR_NB_SCREENS(l)
188 param[l].font = rb->font_get(param[l].curfont);
189 param[l].font_h = param[l].font->height;
191 /* check if FONT_UI fits the screen */
192 if (2*param[l].font_h+3 + BUTTONBAR_HEIGHT > rb->screens[l]->height) {
193 param[l].font = rb->font_get(FONT_SYSFIXED);
194 param[l].font_h = param[l].font->height;
195 param[l].curfont = FONT_SYSFIXED;
198 rb->screens[l]->setfont(param[l].curfont);
199 /* find max width of keyboard glyphs */
200 for (i=0; i<param[l].nchars; i++) {
201 w = rb->font_get_width(param[l].font, param[l].kbd_buf[i]);
202 if (w > param[l].font_w)
203 param[l].font_w = w;
205 /* Since we're going to be adding spaces, make sure that we check
206 * their width too */
207 w = rb->font_get_width( param[l].font, ' ' );
208 if( w > param[l].font_w )
209 param[l].font_w = w;
211 FOR_NB_SCREENS(l)
213 i = 0;
214 /* Pad lines with spaces */
215 while( i < param[l].nchars )
217 if( param[l].kbd_buf[i] == '\n' )
219 k = ( rb->screens[l]->width / param[l].font_w )
220 - i % ( rb->screens[l]->width / param[l].font_w ) - 1;
221 if( k == ( rb->screens[l]->width / param[l].font_w ) - 1 )
223 param[l].nchars--;
224 for( j = i; j < param[l].nchars; j++ )
226 param[l].kbd_buf[j] = param[l].kbd_buf[j+1];
229 else
231 if( param[l].nchars + k - 1 >= KBD_BUF_SIZE )
232 { /* We don't want to overflow the buffer */
233 k = KBD_BUF_SIZE - param[l].nchars;
235 for( j = param[l].nchars + k - 1; j > i+k; j-- )
237 param[l].kbd_buf[j] = param[l].kbd_buf[j-k];
239 param[l].nchars += k;
240 k++;
241 while( k-- )
243 param[l].kbd_buf[i++] = ' ';
247 else
248 i++;
252 /* find max width for text string */
253 utf8 = text;
254 FOR_NB_SCREENS(l)
256 text_w = param[l].font_w;
257 while (*utf8) {
258 utf8 = (unsigned char*)rb->utf8decode(utf8, &ch);
259 w = rb->font_get_width(param[l].font, ch);
260 if (w > text_w)
261 text_w = w;
263 param[l].max_chars_text = rb->screens[l]->width / text_w - 2;
265 /* calculate keyboard grid size */
266 param[l].max_chars = rb->screens[l]->width / param[l].font_w;
267 if (!kbd_loaded) {
268 param[l].lines = param[l].DEFAULT_LINES;
269 param[l].keyboard_margin = DEFAULT_MARGIN;
270 } else {
271 param[l].lines = (rb->screens[l]->height - BUTTONBAR_HEIGHT - statusbar_size) / param[l].font_h - 1;
272 param[l].keyboard_margin = rb->screens[l]->height - BUTTONBAR_HEIGHT -
273 statusbar_size - (param[l].lines+1)*param[l].font_h;
274 if (param[l].keyboard_margin < 3) {
275 param[l].lines--;
276 param[l].keyboard_margin += param[l].font_h;
278 if (param[l].keyboard_margin > 6)
279 param[l].keyboard_margin = 6;
282 param[l].pages = (param[l].nchars + (param[l].lines*param[l].max_chars-1))
283 /(param[l].lines*param[l].max_chars);
284 if (param[l].pages == 1 && kbd_loaded)
285 param[l].lines = (param[l].nchars + param[l].max_chars - 1) / param[l].max_chars;
287 param[l].main_y = param[l].font_h*param[l].lines + param[l].keyboard_margin + statusbar_size;
288 param[l].main_x = 0;
289 param[l].keyboard_margin -= param[l].keyboard_margin/2;
292 editpos = rb->utf8length(text);
296 while(!done)
298 len_utf8 = rb->utf8length(text);
299 FOR_NB_SCREENS(l)
300 rb->screens[l]->clear_display();
303 /* draw page */
304 FOR_NB_SCREENS(l)
306 rb->screens[l]->setfont(param[l].curfont);
307 k = param[l].page*param[l].max_chars*param[l].lines;
308 for (i=j=0; j < param[l].lines && k < param[l].nchars; k++) {
309 utf8 = rb->utf8encode(param[l].kbd_buf[k], outline);
310 *utf8 = 0;
311 rb->screens[l]->getstringsize(outline, &w, NULL);
312 rb->screens[l]->putsxy(i*param[l].font_w + (param[l].font_w-w)/2, j*param[l].font_h
313 + statusbar_size, outline);
314 if (++i == param[l].max_chars) {
315 i = 0;
316 j++;
322 /* separator */
323 FOR_NB_SCREENS(l)
325 rb->screens[l]->hline(0, rb->screens[l]->width - 1, param[l].main_y - param[l].keyboard_margin);
327 /* write out the text */
328 #if 0
329 rb->screens[l]->setfont(param[l].curfont);
331 i=j=0;
332 param[l].curpos = MIN(editpos, param[l].max_chars_text
333 - MIN(len_utf8 - editpos, 2));
334 param[l].leftpos = editpos - param[l].curpos;
335 utf8 = text + rb->utf8seek(text, param[l].leftpos);
337 text_w = param[l].font_w;
338 while (*utf8 && i < param[l].max_chars_text) {
339 outline[j++] = *utf8++;
340 if ((*utf8 & MASK) != COMP) {
341 outline[j] = 0;
342 j=0;
343 i++;
344 rb->screens[l]->getstringsize(outline, &w, NULL);
345 rb->screens[l]->putsxy(i*text_w + (text_w-w)/2, param[l].main_y, outline);
349 if (param[l].leftpos) {
350 rb->screens[l]->getstringsize("<", &w, NULL);
351 rb->screens[l]->putsxy(text_w - w, param[l].main_y, "<");
353 if (len_utf8 - param[l].leftpos > param[l].max_chars_text)
354 rb->screens[l]->putsxy(rb->screens[l]->width - text_w, param[l].main_y, ">");
356 /* cursor */
357 i = (param[l].curpos + 1) * text_w;
358 if (cur_blink)
359 rb->screens[l]->vline(i, param[l].main_y, param[l].main_y + param[l].font_h-1);
361 if (hangul) /* draw underbar */
362 rb->screens[l]->hline(param[l].curpos*text_w, (param[l].curpos+1)*text_w,
363 param[l].main_y+param[l].font_h-1);
364 #endif
366 cur_blink = !cur_blink;
369 /* highlight the key that has focus */
370 FOR_NB_SCREENS(l)
372 rb->screens[l]->set_drawmode(DRMODE_COMPLEMENT);
373 rb->screens[l]->fillrect(param[l].font_w * param[l].x,
374 statusbar_size + param[l].font_h * param[l].y,
375 param[l].font_w, param[l].font_h);
376 rb->screens[l]->set_drawmode(DRMODE_SOLID);
380 /* gui_syncstatusbar_draw(&statusbars, true);*/
381 FOR_NB_SCREENS(l)
382 rb->screens[l]->update();
384 button = rb->button_get_w_tmo(HZ/2);
386 switch ( button ) {
388 case KBD_ABORT:
389 FOR_NB_SCREENS(l)
390 rb->screens[l]->setfont(FONT_UI);
392 return -1;
393 break;
395 case KBD_RIGHT:
396 case KBD_RIGHT | BUTTON_REPEAT:
398 FOR_NB_SCREENS(l)
400 if (++param[l].x == param[l].max_chars) {
401 param[l].x = 0;
402 /* no dedicated flip key - flip page on wrap */
403 if (++param[l].page == param[l].pages)
404 param[l].page = 0;
406 k = (param[l].page*param[l].lines + param[l].y)*param[l].max_chars + param[l].x;
407 /*kbd_spellchar(param[l].kbd_buf[k]);*/
410 break;
411 case KBD_LEFT:
412 case KBD_LEFT | BUTTON_REPEAT:
414 FOR_NB_SCREENS(l)
416 if (param[l].x)
417 param[l].x--;
418 else
420 /* no dedicated flip key - flip page on wrap */
421 if (--param[l].page < 0)
422 param[l].page = (param[l].pages-1);
423 param[l].x = param[l].max_chars - 1;
425 k = (param[l].page*param[l].lines +
426 param[l].y)*param[l].max_chars + param[l].x;
427 /* kbd_spellchar(param[l].kbd_buf[k]);*/
430 break;
432 case KBD_DOWN:
433 case KBD_DOWN | BUTTON_REPEAT:
435 FOR_NB_SCREENS(l)
437 if (param[l].y < param[l].lines - 1)
438 param[l].y++;
439 else
440 param[l].y=0;
442 FOR_NB_SCREENS(l)
444 k = (param[l].page*param[l].lines + param[l].y)*
445 param[l].max_chars + param[l].x;
446 /*kbd_spellchar(param[l].kbd_buf[k]);*/
449 break;
451 case KBD_UP:
452 case KBD_UP | BUTTON_REPEAT:
454 FOR_NB_SCREENS(l)
456 if (param[l].y)
457 param[l].y--;
458 else
459 param[l].y = param[l].lines - 1;
461 FOR_NB_SCREENS(l)
463 k = (param[l].page*param[l].lines + param[l].y)*
464 param[l].max_chars + param[l].x;
465 /*kbd_spellchar(param[l].kbd_buf[k]);*/
468 break;
470 case KBD_SELECT:
472 if (button == KBD_SELECT)
473 char_screen = 0;
475 /* inserts the selected char */
477 /* find input char */
478 k = (param[char_screen].page*param[char_screen].lines +
479 param[char_screen].y)*param[char_screen].max_chars +
480 param[char_screen].x;
481 if (k < param[char_screen].nchars)
482 ch = param[char_screen].kbd_buf[k];
483 else
484 ch = ' ';
485 text[0]=ch;
486 done = true;
488 break;
490 case BUTTON_NONE:
491 /*gui_syncstatusbar_draw(&statusbars, false);*/
493 break;
495 default:
496 if(rb->default_event_handler(button) == SYS_USB_CONNECTED)
497 FOR_NB_SCREENS(l)
498 rb->screens[l]->setfont(FONT_SYSFIXED);
499 break;
502 if (button != BUTTON_NONE)
504 lastbutton = button;
505 cur_blink = true;
508 FOR_NB_SCREENS(l)
509 rb->screens[l]->setfont(FONT_UI);
510 return 0;