forked from len0rd/rockbox
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
This commit is contained in:
parent
c78e9de35a
commit
ccf2078150
1 changed files with 43 additions and 39 deletions
|
@ -98,6 +98,7 @@ struct keyboard_parameters
|
||||||
int nchars;
|
int nchars;
|
||||||
int font_w;
|
int font_w;
|
||||||
int font_h;
|
int font_h;
|
||||||
|
int text_w;
|
||||||
struct font* font;
|
struct font* font;
|
||||||
int curfont;
|
int curfont;
|
||||||
int main_x;
|
int main_x;
|
||||||
|
@ -144,6 +145,12 @@ int load_kbd(unsigned char* filename)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
unsigned char buf[4];
|
unsigned char buf[4];
|
||||||
|
|
||||||
|
FOR_NB_SCREENS(l)
|
||||||
|
{
|
||||||
|
struct keyboard_parameters *pm = &kbd_param[l];
|
||||||
|
pm->x = pm->y = pm->page = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (filename == NULL)
|
if (filename == NULL)
|
||||||
{
|
{
|
||||||
kbd_loaded = false;
|
kbd_loaded = false;
|
||||||
|
@ -159,6 +166,7 @@ int load_kbd(unsigned char* filename)
|
||||||
/* check how many bytes to read for this character */
|
/* check how many bytes to read for this character */
|
||||||
static const unsigned char sizes[4] = { 0x80, 0xe0, 0xf0, 0xf5 };
|
static const unsigned char sizes[4] = { 0x80, 0xe0, 0xf0, 0xf5 };
|
||||||
size_t count;
|
size_t count;
|
||||||
|
unsigned short ch;
|
||||||
|
|
||||||
for (count = 0; count < ARRAYLEN(sizes); count++)
|
for (count = 0; count < ARRAYLEN(sizes); count++)
|
||||||
{
|
{
|
||||||
|
@ -176,11 +184,11 @@ int load_kbd(unsigned char* filename)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utf8decode(buf, &ch);
|
||||||
FOR_NB_SCREENS(l)
|
FOR_NB_SCREENS(l)
|
||||||
utf8decode(buf, &kbd_param[l].kbd_buf[i]);
|
kbd_param[l].kbd_buf[i] = ch;
|
||||||
|
|
||||||
if (kbd_param[0].kbd_buf[i] != 0xFEFF &&
|
if (ch != 0xFEFF && ch != '\r') /*skip BOM & carriage returns */
|
||||||
kbd_param[0].kbd_buf[i] != '\r') /*skip BOM & carriage returns */
|
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -276,9 +284,10 @@ static void kbd_delchar(unsigned char* text, int* editpos)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lookup k value based on state of param (pm) */
|
/* Lookup k value based on state of param (pm) */
|
||||||
static int get_param_k(const struct keyboard_parameters *pm)
|
static unsigned short get_kbd_ch(const struct keyboard_parameters *pm)
|
||||||
{
|
{
|
||||||
return (pm->page*pm->lines + pm->y)*pm->max_chars + pm->x;
|
int k = (pm->page*pm->lines + pm->y)*pm->max_chars + pm->x;
|
||||||
|
return (k < pm->nchars)? pm->kbd_buf[k]: ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
int kbd_input(char* text, int buflen)
|
int kbd_input(char* text, int buflen)
|
||||||
|
@ -291,7 +300,6 @@ int kbd_input(char* text, int buflen)
|
||||||
struct keyboard_parameters * const param = kbd_param;
|
struct keyboard_parameters * const param = kbd_param;
|
||||||
#endif
|
#endif
|
||||||
int l; /* screen loop variable */
|
int l; /* screen loop variable */
|
||||||
int text_w = 0;
|
|
||||||
int editpos; /* Edit position on all screens */
|
int editpos; /* Edit position on all screens */
|
||||||
const int statusbar_size = 0;
|
const int statusbar_size = 0;
|
||||||
unsigned short ch;
|
unsigned short ch;
|
||||||
|
@ -406,9 +414,12 @@ int kbd_input(char* text, int buflen)
|
||||||
/* find max width of keyboard glyphs */
|
/* find max width of keyboard glyphs */
|
||||||
for (i = 0; i < pm->nchars; i++)
|
for (i = 0; i < pm->nchars; i++)
|
||||||
{
|
{
|
||||||
w = font_get_width(pm->font, pm->kbd_buf[i]);
|
if (pm->kbd_buf[i] != '\n')
|
||||||
if ( w > pm->font_w )
|
{
|
||||||
pm->font_w = w;
|
w = font_get_width(pm->font, pm->kbd_buf[i]);
|
||||||
|
if ( w > pm->font_w )
|
||||||
|
pm->font_w = w;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Since we're going to be adding spaces, make sure that we check
|
/* Since we're going to be adding spaces, make sure that we check
|
||||||
|
@ -424,16 +435,17 @@ int kbd_input(char* text, int buflen)
|
||||||
struct screen *sc = &screens[l];
|
struct screen *sc = &screens[l];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
pm->max_chars = sc->getwidth() / pm->font_w;
|
||||||
|
|
||||||
/* Pad lines with spaces */
|
/* Pad lines with spaces */
|
||||||
while (i < pm->nchars)
|
while (i < pm->nchars)
|
||||||
{
|
{
|
||||||
if (pm->kbd_buf[i] == '\n')
|
if (pm->kbd_buf[i] == '\n')
|
||||||
{
|
{
|
||||||
int k = sc->getwidth() / pm->font_w
|
int k = pm->max_chars - i % ( pm->max_chars ) - 1;
|
||||||
- i % ( sc->getwidth() / pm->font_w ) - 1;
|
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
if (k == sc->getwidth() / pm->font_w - 1)
|
if (k == pm->max_chars - 1)
|
||||||
{
|
{
|
||||||
pm->nchars--;
|
pm->nchars--;
|
||||||
|
|
||||||
|
@ -471,27 +483,24 @@ int kbd_input(char* text, int buflen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find max width for text string */
|
/* Find max width for text string */
|
||||||
utf8 = text;
|
|
||||||
FOR_NB_SCREENS(l)
|
FOR_NB_SCREENS(l)
|
||||||
{
|
{
|
||||||
struct keyboard_parameters *pm = ¶m[l];
|
struct keyboard_parameters *pm = ¶m[l];
|
||||||
struct screen *sc = &screens[l];
|
struct screen *sc = &screens[l];
|
||||||
|
|
||||||
text_w = pm->font_w;
|
pm->text_w = pm->font_w;
|
||||||
|
|
||||||
|
utf8 = text;
|
||||||
while (*utf8)
|
while (*utf8)
|
||||||
{
|
{
|
||||||
int w = font_get_width(pm->font, ch);
|
int w;
|
||||||
utf8 = (unsigned char*)utf8decode(utf8, &ch);
|
utf8 = (unsigned char*)utf8decode(utf8, &ch);
|
||||||
|
w = font_get_width(pm->font, ch);
|
||||||
if (w > text_w)
|
if (w > pm->text_w)
|
||||||
text_w = w;
|
pm->text_w = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
pm->max_chars_text = sc->getwidth() / text_w - 2;
|
pm->max_chars_text = sc->getwidth() / pm->text_w - 2;
|
||||||
|
|
||||||
/* Calculate keyboard grid size */
|
|
||||||
pm->max_chars = sc->getwidth() / pm->font_w;
|
|
||||||
|
|
||||||
if (!kbd_loaded)
|
if (!kbd_loaded)
|
||||||
{
|
{
|
||||||
|
@ -644,6 +653,7 @@ int kbd_input(char* text, int buflen)
|
||||||
struct keyboard_parameters *pm = ¶m[l];
|
struct keyboard_parameters *pm = ¶m[l];
|
||||||
struct screen *sc = &screens[l];
|
struct screen *sc = &screens[l];
|
||||||
int i = 0, j = 0;
|
int i = 0, j = 0;
|
||||||
|
int text_w = pm->text_w;
|
||||||
|
|
||||||
/* Clear text area one pixel above separator line so any overdraw
|
/* Clear text area one pixel above separator line so any overdraw
|
||||||
doesn't collide */
|
doesn't collide */
|
||||||
|
@ -662,8 +672,6 @@ int kbd_input(char* text, int buflen)
|
||||||
pm->leftpos = editpos - pm->curpos;
|
pm->leftpos = editpos - pm->curpos;
|
||||||
utf8 = text + utf8seek(text, pm->leftpos);
|
utf8 = text + utf8seek(text, pm->leftpos);
|
||||||
|
|
||||||
text_w = pm->font_w;
|
|
||||||
|
|
||||||
while (*utf8 && i < pm->max_chars_text)
|
while (*utf8 && i < pm->max_chars_text)
|
||||||
{
|
{
|
||||||
outline[j++] = *utf8++;
|
outline[j++] = *utf8++;
|
||||||
|
@ -780,7 +788,6 @@ int kbd_input(char* text, int buflen)
|
||||||
|
|
||||||
case ACTION_KBD_PAGE_FLIP:
|
case ACTION_KBD_PAGE_FLIP:
|
||||||
{
|
{
|
||||||
int k;
|
|
||||||
#ifdef KBD_MORSE_INPUT
|
#ifdef KBD_MORSE_INPUT
|
||||||
if (morse_mode)
|
if (morse_mode)
|
||||||
break;
|
break;
|
||||||
|
@ -788,8 +795,8 @@ int kbd_input(char* text, int buflen)
|
||||||
if (++pm->page >= pm->pages)
|
if (++pm->page >= pm->pages)
|
||||||
pm->page = 0;
|
pm->page = 0;
|
||||||
|
|
||||||
k = get_param_k(pm);
|
ch = get_kbd_ch(pm);
|
||||||
kbd_spellchar(pm->kbd_buf[k]);
|
kbd_spellchar(ch);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -843,7 +850,6 @@ int kbd_input(char* text, int buflen)
|
||||||
else
|
else
|
||||||
#endif /* KBD_MODES */
|
#endif /* KBD_MODES */
|
||||||
{
|
{
|
||||||
int k;
|
|
||||||
#ifdef KBD_MORSE_INPUT
|
#ifdef KBD_MORSE_INPUT
|
||||||
if (morse_mode)
|
if (morse_mode)
|
||||||
break;
|
break;
|
||||||
|
@ -858,8 +864,8 @@ int kbd_input(char* text, int buflen)
|
||||||
pm->x = 0;
|
pm->x = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
k = get_param_k(pm);
|
ch = get_kbd_ch(pm);
|
||||||
kbd_spellchar(pm->kbd_buf[k]);
|
kbd_spellchar(ch);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -888,7 +894,6 @@ int kbd_input(char* text, int buflen)
|
||||||
else
|
else
|
||||||
#endif /* KBD_MODES */
|
#endif /* KBD_MODES */
|
||||||
{
|
{
|
||||||
int k;
|
|
||||||
#ifdef KBD_MORSE_INPUT
|
#ifdef KBD_MORSE_INPUT
|
||||||
if (morse_mode)
|
if (morse_mode)
|
||||||
break;
|
break;
|
||||||
|
@ -903,8 +908,8 @@ int kbd_input(char* text, int buflen)
|
||||||
pm->x = pm->max_chars - 1;
|
pm->x = pm->max_chars - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
k = get_param_k(pm);
|
ch = get_kbd_ch(pm);
|
||||||
kbd_spellchar(pm->kbd_buf[k]);
|
kbd_spellchar(ch);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -946,8 +951,8 @@ int kbd_input(char* text, int buflen)
|
||||||
if (!pm->line_edit)
|
if (!pm->line_edit)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int k = get_param_k(pm);
|
ch = get_kbd_ch(pm);
|
||||||
kbd_spellchar(pm->kbd_buf[k]);
|
kbd_spellchar(ch);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -989,8 +994,8 @@ int kbd_input(char* text, int buflen)
|
||||||
if (!pm->line_edit)
|
if (!pm->line_edit)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int k = get_param_k(pm);
|
ch = get_kbd_ch(pm);
|
||||||
kbd_spellchar(pm->kbd_buf[k]);
|
kbd_spellchar(ch);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1061,8 +1066,7 @@ int kbd_input(char* text, int buflen)
|
||||||
#endif /* KBD_MODES */
|
#endif /* KBD_MODES */
|
||||||
{
|
{
|
||||||
/* find input char */
|
/* find input char */
|
||||||
int k = get_param_k(pm);
|
ch = get_kbd_ch(pm);
|
||||||
ch = (k < pm->nchars) ? pm->kbd_buf[k] : ' ';
|
|
||||||
|
|
||||||
/* check for hangul input */
|
/* check for hangul input */
|
||||||
if (ch >= 0x3131 && ch <= 0x3163)
|
if (ch >= 0x3131 && ch <= 0x3163)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue