diff options
author | Teruaki Kawashima <teru@rockbox.org> | 2010-07-10 13:09:39 +0000 |
---|---|---|
committer | Teruaki Kawashima <teru@rockbox.org> | 2010-07-10 13:09:39 +0000 |
commit | 3d29faa0116f6354df04679987906153ff0a6d17 (patch) | |
tree | 781fff1ef5e4e1dfa012f7c64f88e544750a821d | |
parent | 14238740074945d8f61e445c5d6211e1c7a50566 (diff) | |
download | rockbox-3d29faa0116f6354df04679987906153ff0a6d17.tar.gz rockbox-3d29faa0116f6354df04679987906153ff0a6d17.zip |
keyboard: change how charactars are stored in the buffer.
* try to keep the layout when font is changed or when the buffer is fully used.
* don't waste the buffer by filling by spaces.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27370 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/recorder/keyboard.c | 168 |
1 files changed, 82 insertions, 86 deletions
diff --git a/apps/recorder/keyboard.c b/apps/recorder/keyboard.c index 2ec14a8d09..8dea52799f 100644 --- a/apps/recorder/keyboard.c +++ b/apps/recorder/keyboard.c | |||
@@ -79,7 +79,8 @@ struct keyboard_parameters | |||
79 | unsigned short kbd_buf[KBD_BUF_SIZE]; | 79 | unsigned short kbd_buf[KBD_BUF_SIZE]; |
80 | unsigned short max_line_len; | 80 | unsigned short max_line_len; |
81 | int default_lines; | 81 | int default_lines; |
82 | int nchars; | 82 | int last_k; |
83 | int last_i; | ||
83 | int font_w; | 84 | int font_w; |
84 | int font_h; | 85 | int font_h; |
85 | int text_w; | 86 | int text_w; |
@@ -143,6 +144,7 @@ int load_kbd(unsigned char* filename) | |||
143 | int fd, l; | 144 | int fd, l; |
144 | int i, line_len, max_line_len; | 145 | int i, line_len, max_line_len; |
145 | unsigned char buf[4]; | 146 | unsigned char buf[4]; |
147 | unsigned short *pbuf; | ||
146 | 148 | ||
147 | if (filename == NULL) | 149 | if (filename == NULL) |
148 | { | 150 | { |
@@ -154,10 +156,11 @@ int load_kbd(unsigned char* filename) | |||
154 | if (fd < 0) | 156 | if (fd < 0) |
155 | return 1; | 157 | return 1; |
156 | 158 | ||
159 | pbuf = kbd_param[0].kbd_buf; | ||
157 | line_len = 0; | 160 | line_len = 0; |
158 | max_line_len = 1; | 161 | max_line_len = 1; |
159 | i = 0; | 162 | i = 1; |
160 | while (read(fd, buf, 1) == 1 && i < KBD_BUF_SIZE) | 163 | while (read(fd, buf, 1) == 1 && i < KBD_BUF_SIZE-1) |
161 | { | 164 | { |
162 | /* check how many bytes to read for this character */ | 165 | /* check how many bytes to read for this character */ |
163 | static const unsigned char sizes[4] = { 0x80, 0xe0, 0xf0, 0xf5 }; | 166 | static const unsigned char sizes[4] = { 0x80, 0xe0, 0xf0, 0xf5 }; |
@@ -183,17 +186,17 @@ int load_kbd(unsigned char* filename) | |||
183 | utf8decode(buf, &ch); | 186 | utf8decode(buf, &ch); |
184 | if (ch != 0xFEFF && ch != '\r') /* skip BOM & carriage returns */ | 187 | if (ch != 0xFEFF && ch != '\r') /* skip BOM & carriage returns */ |
185 | { | 188 | { |
186 | FOR_NB_SCREENS(l) | ||
187 | kbd_param[l].kbd_buf[i] = ch; | ||
188 | i++; | 189 | i++; |
189 | if (ch == '\n') | 190 | if (ch == '\n') |
190 | { | 191 | { |
191 | if (max_line_len < line_len) | 192 | if (max_line_len < line_len) |
192 | max_line_len = line_len; | 193 | max_line_len = line_len; |
194 | *pbuf = line_len; | ||
195 | pbuf += line_len + 1; | ||
193 | line_len = 0; | 196 | line_len = 0; |
194 | } | 197 | } |
195 | else | 198 | else |
196 | line_len++; | 199 | pbuf[++line_len] = ch; |
197 | } | 200 | } |
198 | } | 201 | } |
199 | 202 | ||
@@ -202,11 +205,20 @@ int load_kbd(unsigned char* filename) | |||
202 | 205 | ||
203 | if (max_line_len < line_len) | 206 | if (max_line_len < line_len) |
204 | max_line_len = line_len; | 207 | max_line_len = line_len; |
205 | 208 | if (i == 1 || line_len != 0) /* ignore last empty line */ | |
209 | { | ||
210 | *pbuf = line_len; | ||
211 | pbuf += line_len + 1; | ||
212 | } | ||
213 | *pbuf = 0xFEFF; /* mark end of characters */ | ||
214 | i++; | ||
206 | FOR_NB_SCREENS(l) | 215 | FOR_NB_SCREENS(l) |
207 | { | 216 | { |
208 | struct keyboard_parameters *pm = &kbd_param[l]; | 217 | struct keyboard_parameters *pm = &kbd_param[l]; |
209 | pm->nchars = i; | 218 | #if NB_SCREENS > 1 |
219 | if (l > 0) | ||
220 | memcpy(pm->kbd_buf, kbd_param[0].kbd_buf, i*sizeof(unsigned short)); | ||
221 | #endif | ||
210 | /* initialize parameters */ | 222 | /* initialize parameters */ |
211 | pm->x = pm->y = pm->page = 0; | 223 | pm->x = pm->y = pm->page = 0; |
212 | pm->default_lines = 0; | 224 | pm->default_lines = 0; |
@@ -269,10 +281,28 @@ static void kbd_delchar(struct edit_state *state) | |||
269 | } | 281 | } |
270 | 282 | ||
271 | /* Lookup k value based on state of param (pm) */ | 283 | /* Lookup k value based on state of param (pm) */ |
272 | static unsigned short get_kbd_ch(const struct keyboard_parameters *pm) | 284 | static unsigned short get_kbd_ch(struct keyboard_parameters *pm, int x, int y) |
273 | { | 285 | { |
274 | int k = (pm->page*pm->lines + pm->y)*pm->max_chars + pm->x; | 286 | int i = 0, k = pm->page*pm->lines + y, n; |
275 | return (k < pm->nchars)? pm->kbd_buf[k]: ' '; | 287 | unsigned short *pbuf; |
288 | if (k >= pm->last_k) | ||
289 | { | ||
290 | i = pm->last_i; | ||
291 | k -= pm->last_k; | ||
292 | } | ||
293 | for (pbuf = &pm->kbd_buf[i]; (i = *pbuf) != 0xFEFF; pbuf += i + 1) | ||
294 | { | ||
295 | n = i ? (i + pm->max_chars - 1) / pm->max_chars : 1; | ||
296 | if (k < n) break; | ||
297 | k -= n; | ||
298 | } | ||
299 | if (y == 0 && i != 0xFEFF) | ||
300 | { | ||
301 | pm->last_k = pm->page*pm->lines - k; | ||
302 | pm->last_i = pbuf - pm->kbd_buf; | ||
303 | } | ||
304 | k = k * pm->max_chars + x; | ||
305 | return (*pbuf != 0xFEFF && k < *pbuf)? pbuf[k+1]: ' '; | ||
276 | } | 306 | } |
277 | 307 | ||
278 | static void kbd_calc_params(struct keyboard_parameters *pm, | 308 | static void kbd_calc_params(struct keyboard_parameters *pm, |
@@ -341,8 +371,9 @@ int kbd_input(char* text, int buflen) | |||
341 | FOR_NB_SCREENS(l) | 371 | FOR_NB_SCREENS(l) |
342 | { | 372 | { |
343 | struct keyboard_parameters *pm = ¶m[l]; | 373 | struct keyboard_parameters *pm = ¶m[l]; |
374 | unsigned short *pbuf; | ||
344 | const unsigned char *p; | 375 | const unsigned char *p; |
345 | int i = 0; | 376 | int len = 0; |
346 | 377 | ||
347 | #if LCD_WIDTH >= 160 && LCD_HEIGHT >= 96 | 378 | #if LCD_WIDTH >= 160 && LCD_HEIGHT >= 96 |
348 | struct screen *sc = &screens[l]; | 379 | struct screen *sc = &screens[l]; |
@@ -383,10 +414,22 @@ int kbd_input(char* text, int buflen) | |||
383 | pm->max_line_len = 18; | 414 | pm->max_line_len = 18; |
384 | } | 415 | } |
385 | 416 | ||
417 | pbuf = pm->kbd_buf; | ||
386 | while (*p) | 418 | while (*p) |
387 | p = utf8decode(p, &pm->kbd_buf[i++]); | 419 | { |
420 | p = utf8decode(p, &pbuf[len+1]); | ||
421 | if (pbuf[len+1] == '\n') | ||
422 | { | ||
423 | *pbuf = len; | ||
424 | pbuf += len+1; | ||
425 | len = 0; | ||
426 | } | ||
427 | else | ||
428 | len++; | ||
429 | } | ||
430 | *pbuf = len; | ||
431 | pbuf[len+1] = 0xFEFF; /* mark end of characters */ | ||
388 | 432 | ||
389 | pm->nchars = i; | ||
390 | /* initialize parameters */ | 433 | /* initialize parameters */ |
391 | pm->x = pm->y = pm->page = 0; | 434 | pm->x = pm->y = pm->page = 0; |
392 | } | 435 | } |
@@ -628,7 +671,7 @@ int kbd_input(char* text, int buflen) | |||
628 | if (!state.morse_mode) | 671 | if (!state.morse_mode) |
629 | #endif | 672 | #endif |
630 | { | 673 | { |
631 | ch = get_kbd_ch(pm); | 674 | ch = get_kbd_ch(pm, pm->x, pm->y); |
632 | kbd_spellchar(ch); | 675 | kbd_spellchar(ch); |
633 | } | 676 | } |
634 | } | 677 | } |
@@ -671,7 +714,7 @@ static void kbd_calc_params(struct keyboard_parameters *pm, | |||
671 | { | 714 | { |
672 | struct font* font; | 715 | struct font* font; |
673 | const unsigned char *p; | 716 | const unsigned char *p; |
674 | unsigned short ch; | 717 | unsigned short ch, *pbuf; |
675 | int icon_w, sc_w, sc_h, w; | 718 | int icon_w, sc_w, sc_h, w; |
676 | int i, total_lines; | 719 | int i, total_lines; |
677 | #ifdef HAVE_TOUCHSCREEN | 720 | #ifdef HAVE_TOUCHSCREEN |
@@ -700,11 +743,11 @@ static void kbd_calc_params(struct keyboard_parameters *pm, | |||
700 | * since we're going to be adding spaces, | 743 | * since we're going to be adding spaces, |
701 | * max width is at least their width */ | 744 | * max width is at least their width */ |
702 | pm->font_w = font_get_width(font, ' '); | 745 | pm->font_w = font_get_width(font, ' '); |
703 | for (i = 0; i < pm->nchars; i++) | 746 | for (pbuf = pm->kbd_buf; *pbuf != 0xFEFF; pbuf += i) |
704 | { | 747 | { |
705 | if (pm->kbd_buf[i] != '\n') | 748 | for (i = 0; ++i <= *pbuf; ) |
706 | { | 749 | { |
707 | w = font_get_width(font, pm->kbd_buf[i]); | 750 | w = font_get_width(font, pbuf[i]); |
708 | if (pm->font_w < w) | 751 | if (pm->font_w < w) |
709 | pm->font_w = w; | 752 | pm->font_w = w; |
710 | } | 753 | } |
@@ -734,54 +777,6 @@ static void kbd_calc_params(struct keyboard_parameters *pm, | |||
734 | if (pm->max_chars_text < 3 && icon_w > pm->text_w) | 777 | if (pm->max_chars_text < 3 && icon_w > pm->text_w) |
735 | pm->max_chars_text = sc_w / pm->text_w - 2; | 778 | pm->max_chars_text = sc_w / pm->text_w - 2; |
736 | 779 | ||
737 | |||
738 | i = 0; | ||
739 | /* Pad lines with spaces */ | ||
740 | while (i < pm->nchars) | ||
741 | { | ||
742 | if (pm->kbd_buf[i] == '\n') | ||
743 | { | ||
744 | int k = pm->max_chars - i % ( pm->max_chars ) - 1; | ||
745 | int j; | ||
746 | |||
747 | if (k == pm->max_chars - 1) | ||
748 | { | ||
749 | pm->nchars--; | ||
750 | |||
751 | for (j = i; j < pm->nchars; j++) | ||
752 | { | ||
753 | pm->kbd_buf[j] = pm->kbd_buf[j + 1]; | ||
754 | } | ||
755 | } | ||
756 | else | ||
757 | { | ||
758 | if (pm->nchars + k - 1 >= KBD_BUF_SIZE) | ||
759 | { /* We don't want to overflow the buffer */ | ||
760 | k = KBD_BUF_SIZE - pm->nchars; | ||
761 | } | ||
762 | |||
763 | for (j = pm->nchars + k - 1; j > i + k; j--) | ||
764 | { | ||
765 | pm->kbd_buf[j] = pm->kbd_buf[j-k]; | ||
766 | } | ||
767 | |||
768 | pm->nchars += k; | ||
769 | k++; | ||
770 | |||
771 | while (k--) | ||
772 | { | ||
773 | pm->kbd_buf[i++] = ' '; | ||
774 | } | ||
775 | } | ||
776 | } | ||
777 | else | ||
778 | { | ||
779 | i++; | ||
780 | } | ||
781 | } | ||
782 | if (pm->nchars == 0) | ||
783 | pm->kbd_buf[pm->nchars++] = ' '; | ||
784 | |||
785 | /* calculate pm->pages and pm->lines */ | 780 | /* calculate pm->pages and pm->lines */ |
786 | sc_h = sc->getheight(); | 781 | sc_h = sc->getheight(); |
787 | #ifdef HAVE_TOUCHSCREEN | 782 | #ifdef HAVE_TOUCHSCREEN |
@@ -811,7 +806,10 @@ recalc_param: | |||
811 | if (pm->keyboard_margin > DEFAULT_MARGIN) | 806 | if (pm->keyboard_margin > DEFAULT_MARGIN) |
812 | pm->keyboard_margin = DEFAULT_MARGIN; | 807 | pm->keyboard_margin = DEFAULT_MARGIN; |
813 | 808 | ||
814 | total_lines = (pm->nchars + pm->max_chars - 1) / pm->max_chars; | 809 | total_lines = 0; |
810 | for (pbuf = pm->kbd_buf; (i = *pbuf) != 0xFEFF; pbuf += i + 1) | ||
811 | total_lines += (i ? (i + pm->max_chars - 1) / pm->max_chars : 1); | ||
812 | |||
815 | pm->pages = (total_lines + pm->lines - 1) / pm->lines; | 813 | pm->pages = (total_lines + pm->lines - 1) / pm->lines; |
816 | pm->lines = (total_lines + pm->pages - 1) / pm->pages; | 814 | pm->lines = (total_lines + pm->pages - 1) / pm->pages; |
817 | #ifdef HAVE_TOUCHSCREEN | 815 | #ifdef HAVE_TOUCHSCREEN |
@@ -823,6 +821,8 @@ recalc_param: | |||
823 | goto recalc_param; | 821 | goto recalc_param; |
824 | } | 822 | } |
825 | #endif | 823 | #endif |
824 | if (pm->page >= pm->pages) | ||
825 | pm->x = pm->y = pm->page = 0; | ||
826 | 826 | ||
827 | pm->main_y = pm->font_h*pm->lines + pm->keyboard_margin; | 827 | pm->main_y = pm->font_h*pm->lines + pm->keyboard_margin; |
828 | pm->keyboard_margin -= pm->keyboard_margin/2; | 828 | pm->keyboard_margin -= pm->keyboard_margin/2; |
@@ -899,28 +899,24 @@ static void kbd_draw_picker(struct keyboard_parameters *pm, | |||
899 | #endif /* HAVE_MORSE_INPUT */ | 899 | #endif /* HAVE_MORSE_INPUT */ |
900 | { | 900 | { |
901 | /* draw page */ | 901 | /* draw page */ |
902 | int i, j, k; | 902 | int i, j; |
903 | int w, h; | ||
904 | unsigned short ch; | ||
905 | unsigned char *utf8; | ||
903 | 906 | ||
904 | sc->setfont(pm->curfont); | 907 | sc->setfont(pm->curfont); |
905 | 908 | ||
906 | k = pm->page*pm->max_chars*pm->lines; | 909 | for (j = 0; j < pm->lines; j++) |
907 | |||
908 | for (i = j = 0; k < pm->nchars; k++) | ||
909 | { | 910 | { |
910 | int w, h; | 911 | for (i = 0; i < pm->max_chars; i++) |
911 | unsigned char *utf8; | ||
912 | utf8 = utf8encode(pm->kbd_buf[k], outline); | ||
913 | *utf8 = 0; | ||
914 | |||
915 | sc->getstringsize(outline, &w, &h); | ||
916 | sc->putsxy(i*pm->font_w + (pm->font_w-w) / 2, | ||
917 | j*pm->font_h + (pm->font_h-h) / 2, outline); | ||
918 | |||
919 | if (++i >= pm->max_chars) | ||
920 | { | 912 | { |
921 | i = 0; | 913 | ch = get_kbd_ch(pm, i, j); |
922 | if (++j >= pm->lines) | 914 | utf8 = utf8encode(ch, outline); |
923 | break; | 915 | *utf8 = 0; |
916 | |||
917 | sc->getstringsize(outline, &w, &h); | ||
918 | sc->putsxy(i*pm->font_w + (pm->font_w-w) / 2, | ||
919 | j*pm->font_h + (pm->font_h-h) / 2, outline); | ||
924 | } | 920 | } |
925 | } | 921 | } |
926 | 922 | ||
@@ -1131,7 +1127,7 @@ static void kbd_insert_selected(struct keyboard_parameters *pm, | |||
1131 | struct edit_state *state) | 1127 | struct edit_state *state) |
1132 | { | 1128 | { |
1133 | /* find input char */ | 1129 | /* find input char */ |
1134 | unsigned short ch = get_kbd_ch(pm); | 1130 | unsigned short ch = get_kbd_ch(pm, pm->x, pm->y); |
1135 | 1131 | ||
1136 | /* check for hangul input */ | 1132 | /* check for hangul input */ |
1137 | if (ch >= 0x3131 && ch <= 0x3163) | 1133 | if (ch >= 0x3131 && ch <= 0x3163) |