diff options
author | Teruaki Kawashima <teru@rockbox.org> | 2009-10-03 13:53:49 +0000 |
---|---|---|
committer | Teruaki Kawashima <teru@rockbox.org> | 2009-10-03 13:53:49 +0000 |
commit | ccf2078150e9ccd9edafeccd209f93ca60a7ada5 (patch) | |
tree | d8d1a86218379ac93cce6b318d2216a6335efadf | |
parent | c78e9de35abeed6bec34979ab623c0b6a0de6863 (diff) | |
download | rockbox-ccf2078150e9ccd9edafeccd209f93ca60a7ada5.tar.gz rockbox-ccf2078150e9ccd9edafeccd209f93ca60a7ada5.zip |
Fix FS#10597: Loadable keyboard layout rendered incorrectly.
Also fix out of bounds access to kbd_buf.
Reset cursor position in keyboard when loading new virtual keyboard for the case size is different from previous one.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22892 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/recorder/keyboard.c | 82 |
1 files changed, 43 insertions, 39 deletions
diff --git a/apps/recorder/keyboard.c b/apps/recorder/keyboard.c index 2911f94931..ddfbcf4585 100644 --- a/apps/recorder/keyboard.c +++ b/apps/recorder/keyboard.c | |||
@@ -98,6 +98,7 @@ struct keyboard_parameters | |||
98 | int nchars; | 98 | int nchars; |
99 | int font_w; | 99 | int font_w; |
100 | int font_h; | 100 | int font_h; |
101 | int text_w; | ||
101 | struct font* font; | 102 | struct font* font; |
102 | int curfont; | 103 | int curfont; |
103 | int main_x; | 104 | int main_x; |
@@ -144,6 +145,12 @@ int load_kbd(unsigned char* filename) | |||
144 | int i = 0; | 145 | int i = 0; |
145 | unsigned char buf[4]; | 146 | unsigned char buf[4]; |
146 | 147 | ||
148 | FOR_NB_SCREENS(l) | ||
149 | { | ||
150 | struct keyboard_parameters *pm = &kbd_param[l]; | ||
151 | pm->x = pm->y = pm->page = 0; | ||
152 | } | ||
153 | |||
147 | if (filename == NULL) | 154 | if (filename == NULL) |
148 | { | 155 | { |
149 | kbd_loaded = false; | 156 | kbd_loaded = false; |
@@ -159,6 +166,7 @@ int load_kbd(unsigned char* filename) | |||
159 | /* check how many bytes to read for this character */ | 166 | /* check how many bytes to read for this character */ |
160 | static const unsigned char sizes[4] = { 0x80, 0xe0, 0xf0, 0xf5 }; | 167 | static const unsigned char sizes[4] = { 0x80, 0xe0, 0xf0, 0xf5 }; |
161 | size_t count; | 168 | size_t count; |
169 | unsigned short ch; | ||
162 | 170 | ||
163 | for (count = 0; count < ARRAYLEN(sizes); count++) | 171 | for (count = 0; count < ARRAYLEN(sizes); count++) |
164 | { | 172 | { |
@@ -176,11 +184,11 @@ int load_kbd(unsigned char* filename) | |||
176 | return 1; | 184 | return 1; |
177 | } | 185 | } |
178 | 186 | ||
187 | utf8decode(buf, &ch); | ||
179 | FOR_NB_SCREENS(l) | 188 | FOR_NB_SCREENS(l) |
180 | utf8decode(buf, &kbd_param[l].kbd_buf[i]); | 189 | kbd_param[l].kbd_buf[i] = ch; |
181 | 190 | ||
182 | if (kbd_param[0].kbd_buf[i] != 0xFEFF && | 191 | if (ch != 0xFEFF && ch != '\r') /*skip BOM & carriage returns */ |
183 | kbd_param[0].kbd_buf[i] != '\r') /*skip BOM & carriage returns */ | ||
184 | { | 192 | { |
185 | i++; | 193 | i++; |
186 | } | 194 | } |
@@ -276,9 +284,10 @@ static void kbd_delchar(unsigned char* text, int* editpos) | |||
276 | } | 284 | } |
277 | 285 | ||
278 | /* Lookup k value based on state of param (pm) */ | 286 | /* Lookup k value based on state of param (pm) */ |
279 | static int get_param_k(const struct keyboard_parameters *pm) | 287 | static unsigned short get_kbd_ch(const struct keyboard_parameters *pm) |
280 | { | 288 | { |
281 | return (pm->page*pm->lines + pm->y)*pm->max_chars + pm->x; | 289 | int k = (pm->page*pm->lines + pm->y)*pm->max_chars + pm->x; |
290 | return (k < pm->nchars)? pm->kbd_buf[k]: ' '; | ||
282 | } | 291 | } |
283 | 292 | ||
284 | int kbd_input(char* text, int buflen) | 293 | int kbd_input(char* text, int buflen) |
@@ -291,7 +300,6 @@ int kbd_input(char* text, int buflen) | |||
291 | struct keyboard_parameters * const param = kbd_param; | 300 | struct keyboard_parameters * const param = kbd_param; |
292 | #endif | 301 | #endif |
293 | int l; /* screen loop variable */ | 302 | int l; /* screen loop variable */ |
294 | int text_w = 0; | ||
295 | int editpos; /* Edit position on all screens */ | 303 | int editpos; /* Edit position on all screens */ |
296 | const int statusbar_size = 0; | 304 | const int statusbar_size = 0; |
297 | unsigned short ch; | 305 | unsigned short ch; |
@@ -406,9 +414,12 @@ int kbd_input(char* text, int buflen) | |||
406 | /* find max width of keyboard glyphs */ | 414 | /* find max width of keyboard glyphs */ |
407 | for (i = 0; i < pm->nchars; i++) | 415 | for (i = 0; i < pm->nchars; i++) |
408 | { | 416 | { |
409 | w = font_get_width(pm->font, pm->kbd_buf[i]); | 417 | if (pm->kbd_buf[i] != '\n') |
410 | if ( w > pm->font_w ) | 418 | { |
411 | pm->font_w = w; | 419 | w = font_get_width(pm->font, pm->kbd_buf[i]); |
420 | if ( w > pm->font_w ) | ||
421 | pm->font_w = w; | ||
422 | } | ||
412 | } | 423 | } |
413 | 424 | ||
414 | /* Since we're going to be adding spaces, make sure that we check | 425 | /* Since we're going to be adding spaces, make sure that we check |
@@ -424,16 +435,17 @@ int kbd_input(char* text, int buflen) | |||
424 | struct screen *sc = &screens[l]; | 435 | struct screen *sc = &screens[l]; |
425 | int i = 0; | 436 | int i = 0; |
426 | 437 | ||
438 | pm->max_chars = sc->getwidth() / pm->font_w; | ||
439 | |||
427 | /* Pad lines with spaces */ | 440 | /* Pad lines with spaces */ |
428 | while (i < pm->nchars) | 441 | while (i < pm->nchars) |
429 | { | 442 | { |
430 | if (pm->kbd_buf[i] == '\n') | 443 | if (pm->kbd_buf[i] == '\n') |
431 | { | 444 | { |
432 | int k = sc->getwidth() / pm->font_w | 445 | int k = pm->max_chars - i % ( pm->max_chars ) - 1; |
433 | - i % ( sc->getwidth() / pm->font_w ) - 1; | ||
434 | int j; | 446 | int j; |
435 | 447 | ||
436 | if (k == sc->getwidth() / pm->font_w - 1) | 448 | if (k == pm->max_chars - 1) |
437 | { | 449 | { |
438 | pm->nchars--; | 450 | pm->nchars--; |
439 | 451 | ||
@@ -471,27 +483,24 @@ int kbd_input(char* text, int buflen) | |||
471 | } | 483 | } |
472 | 484 | ||
473 | /* Find max width for text string */ | 485 | /* Find max width for text string */ |
474 | utf8 = text; | ||
475 | FOR_NB_SCREENS(l) | 486 | FOR_NB_SCREENS(l) |
476 | { | 487 | { |
477 | struct keyboard_parameters *pm = ¶m[l]; | 488 | struct keyboard_parameters *pm = ¶m[l]; |
478 | struct screen *sc = &screens[l]; | 489 | struct screen *sc = &screens[l]; |
479 | 490 | ||
480 | text_w = pm->font_w; | 491 | pm->text_w = pm->font_w; |
481 | 492 | ||
493 | utf8 = text; | ||
482 | while (*utf8) | 494 | while (*utf8) |
483 | { | 495 | { |
484 | int w = font_get_width(pm->font, ch); | 496 | int w; |
485 | utf8 = (unsigned char*)utf8decode(utf8, &ch); | 497 | utf8 = (unsigned char*)utf8decode(utf8, &ch); |
486 | 498 | w = font_get_width(pm->font, ch); | |
487 | if (w > text_w) | 499 | if (w > pm->text_w) |
488 | text_w = w; | 500 | pm->text_w = w; |
489 | } | 501 | } |
490 | 502 | ||
491 | pm->max_chars_text = sc->getwidth() / text_w - 2; | 503 | pm->max_chars_text = sc->getwidth() / pm->text_w - 2; |
492 | |||
493 | /* Calculate keyboard grid size */ | ||
494 | pm->max_chars = sc->getwidth() / pm->font_w; | ||
495 | 504 | ||
496 | if (!kbd_loaded) | 505 | if (!kbd_loaded) |
497 | { | 506 | { |
@@ -644,6 +653,7 @@ int kbd_input(char* text, int buflen) | |||
644 | struct keyboard_parameters *pm = ¶m[l]; | 653 | struct keyboard_parameters *pm = ¶m[l]; |
645 | struct screen *sc = &screens[l]; | 654 | struct screen *sc = &screens[l]; |
646 | int i = 0, j = 0; | 655 | int i = 0, j = 0; |
656 | int text_w = pm->text_w; | ||
647 | 657 | ||
648 | /* Clear text area one pixel above separator line so any overdraw | 658 | /* Clear text area one pixel above separator line so any overdraw |
649 | doesn't collide */ | 659 | doesn't collide */ |
@@ -662,8 +672,6 @@ int kbd_input(char* text, int buflen) | |||
662 | pm->leftpos = editpos - pm->curpos; | 672 | pm->leftpos = editpos - pm->curpos; |
663 | utf8 = text + utf8seek(text, pm->leftpos); | 673 | utf8 = text + utf8seek(text, pm->leftpos); |
664 | 674 | ||
665 | text_w = pm->font_w; | ||
666 | |||
667 | while (*utf8 && i < pm->max_chars_text) | 675 | while (*utf8 && i < pm->max_chars_text) |
668 | { | 676 | { |
669 | outline[j++] = *utf8++; | 677 | outline[j++] = *utf8++; |
@@ -780,7 +788,6 @@ int kbd_input(char* text, int buflen) | |||
780 | 788 | ||
781 | case ACTION_KBD_PAGE_FLIP: | 789 | case ACTION_KBD_PAGE_FLIP: |
782 | { | 790 | { |
783 | int k; | ||
784 | #ifdef KBD_MORSE_INPUT | 791 | #ifdef KBD_MORSE_INPUT |
785 | if (morse_mode) | 792 | if (morse_mode) |
786 | break; | 793 | break; |
@@ -788,8 +795,8 @@ int kbd_input(char* text, int buflen) | |||
788 | if (++pm->page >= pm->pages) | 795 | if (++pm->page >= pm->pages) |
789 | pm->page = 0; | 796 | pm->page = 0; |
790 | 797 | ||
791 | k = get_param_k(pm); | 798 | ch = get_kbd_ch(pm); |
792 | kbd_spellchar(pm->kbd_buf[k]); | 799 | kbd_spellchar(ch); |
793 | break; | 800 | break; |
794 | } | 801 | } |
795 | 802 | ||
@@ -843,7 +850,6 @@ int kbd_input(char* text, int buflen) | |||
843 | else | 850 | else |
844 | #endif /* KBD_MODES */ | 851 | #endif /* KBD_MODES */ |
845 | { | 852 | { |
846 | int k; | ||
847 | #ifdef KBD_MORSE_INPUT | 853 | #ifdef KBD_MORSE_INPUT |
848 | if (morse_mode) | 854 | if (morse_mode) |
849 | break; | 855 | break; |
@@ -858,8 +864,8 @@ int kbd_input(char* text, int buflen) | |||
858 | pm->x = 0; | 864 | pm->x = 0; |
859 | } | 865 | } |
860 | 866 | ||
861 | k = get_param_k(pm); | 867 | ch = get_kbd_ch(pm); |
862 | kbd_spellchar(pm->kbd_buf[k]); | 868 | kbd_spellchar(ch); |
863 | } | 869 | } |
864 | break; | 870 | break; |
865 | 871 | ||
@@ -888,7 +894,6 @@ int kbd_input(char* text, int buflen) | |||
888 | else | 894 | else |
889 | #endif /* KBD_MODES */ | 895 | #endif /* KBD_MODES */ |
890 | { | 896 | { |
891 | int k; | ||
892 | #ifdef KBD_MORSE_INPUT | 897 | #ifdef KBD_MORSE_INPUT |
893 | if (morse_mode) | 898 | if (morse_mode) |
894 | break; | 899 | break; |
@@ -903,8 +908,8 @@ int kbd_input(char* text, int buflen) | |||
903 | pm->x = pm->max_chars - 1; | 908 | pm->x = pm->max_chars - 1; |
904 | } | 909 | } |
905 | 910 | ||
906 | k = get_param_k(pm); | 911 | ch = get_kbd_ch(pm); |
907 | kbd_spellchar(pm->kbd_buf[k]); | 912 | kbd_spellchar(ch); |
908 | } | 913 | } |
909 | break; | 914 | break; |
910 | 915 | ||
@@ -946,8 +951,8 @@ int kbd_input(char* text, int buflen) | |||
946 | if (!pm->line_edit) | 951 | if (!pm->line_edit) |
947 | #endif | 952 | #endif |
948 | { | 953 | { |
949 | int k = get_param_k(pm); | 954 | ch = get_kbd_ch(pm); |
950 | kbd_spellchar(pm->kbd_buf[k]); | 955 | kbd_spellchar(ch); |
951 | } | 956 | } |
952 | break; | 957 | break; |
953 | 958 | ||
@@ -989,8 +994,8 @@ int kbd_input(char* text, int buflen) | |||
989 | if (!pm->line_edit) | 994 | if (!pm->line_edit) |
990 | #endif | 995 | #endif |
991 | { | 996 | { |
992 | int k = get_param_k(pm); | 997 | ch = get_kbd_ch(pm); |
993 | kbd_spellchar(pm->kbd_buf[k]); | 998 | kbd_spellchar(ch); |
994 | } | 999 | } |
995 | break; | 1000 | break; |
996 | 1001 | ||
@@ -1061,8 +1066,7 @@ int kbd_input(char* text, int buflen) | |||
1061 | #endif /* KBD_MODES */ | 1066 | #endif /* KBD_MODES */ |
1062 | { | 1067 | { |
1063 | /* find input char */ | 1068 | /* find input char */ |
1064 | int k = get_param_k(pm); | 1069 | ch = get_kbd_ch(pm); |
1065 | ch = (k < pm->nchars) ? pm->kbd_buf[k] : ' '; | ||
1066 | 1070 | ||
1067 | /* check for hangul input */ | 1071 | /* check for hangul input */ |
1068 | if (ch >= 0x3131 && ch <= 0x3163) | 1072 | if (ch >= 0x3131 && ch <= 0x3163) |