aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-05-17 17:25:19 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-05-17 17:25:19 +0100
commit1b46b4daa6fbf45eddcf77877379a0afac341df9 (patch)
tree83ca6edb7e62f01c6d82272b970e90a1d9b05354
parent27cb89d1d321e6deb6fc7f80771bb0018af4cd49 (diff)
parent5fff13f245cddd3bc260dfe6ebe1b1f05b72116f (diff)
downloadqemu-1b46b4daa6fbf45eddcf77877379a0afac341df9.zip
qemu-1b46b4daa6fbf45eddcf77877379a0afac341df9.tar.gz
qemu-1b46b4daa6fbf45eddcf77877379a0afac341df9.tar.bz2
Merge remote-tracking branch 'remotes/kraxel/tags/ui-20190517-pull-request' into staging
ui: bugfixes for curses, opengl console and kbd state tracker. # gpg: Signature made Fri 17 May 2019 17:12:30 BST # gpg: using RSA key 4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full] # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/ui-20190517-pull-request: kbd-state: fix autorepeat handling ui/console: Precautionary glBindTexture and surface->texture validation in surface_gl_update_texture ui/curses: manipulate cchar_t with standard curses functions ui/curses: do not assume wchar_t contains unicode Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--ui/console-gl.c18
-rw-r--r--ui/curses.c194
-rw-r--r--ui/kbd-state.c6
3 files changed, 142 insertions, 76 deletions
diff --git a/ui/console-gl.c b/ui/console-gl.c
index a56e1cd..c1cb3bd 100644
--- a/ui/console-gl.c
+++ b/ui/console-gl.c
@@ -92,13 +92,17 @@ void surface_gl_update_texture(QemuGLShader *gls,
assert(gls);
- glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT,
- surface_stride(surface) / surface_bytes_per_pixel(surface));
- glTexSubImage2D(GL_TEXTURE_2D, 0,
- x, y, w, h,
- surface->glformat, surface->gltype,
- data + surface_stride(surface) * y
- + surface_bytes_per_pixel(surface) * x);
+ if (surface->texture) {
+ glBindTexture(GL_TEXTURE_2D, surface->texture);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT,
+ surface_stride(surface)
+ / surface_bytes_per_pixel(surface));
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ x, y, w, h,
+ surface->glformat, surface->gltype,
+ data + surface_stride(surface) * y
+ + surface_bytes_per_pixel(surface) * x);
+ }
}
void surface_gl_render_texture(QemuGLShader *gls,
diff --git a/ui/curses.c b/ui/curses.c
index fb63945..1f3fcab 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -66,20 +66,22 @@ static void curses_update(DisplayChangeListener *dcl,
{
console_ch_t *line;
cchar_t curses_line[width];
+ wchar_t wch[CCHARW_MAX];
+ attr_t attrs;
+ short colors;
+ int ret;
line = screen + y * width;
for (h += y; y < h; y ++, line += width) {
for (x = 0; x < width; x++) {
chtype ch = line[x] & 0xff;
chtype at = line[x] & ~0xff;
- if (vga_to_curses[ch].chars[0]) {
- curses_line[x] = vga_to_curses[ch];
- } else {
- curses_line[x] = (cchar_t) {
- .chars[0] = ch,
- };
+ ret = getcchar(&vga_to_curses[ch], wch, &attrs, &colors, NULL);
+ if (ret == ERR || wch[0] == 0) {
+ wch[0] = ch;
+ wch[1] = 0;
}
- curses_line[x].attr |= at;
+ setcchar(&curses_line[x], wch, at, 0, NULL);
}
mvwadd_wchnstr(screenpad, y, 0, curses_line, width);
}
@@ -400,65 +402,112 @@ static void curses_atexit(void)
endwin();
}
+/*
+ * In the following:
+ * - fch is the font glyph number
+ * - uch is the unicode value
+ * - wch is the wchar_t value (may not be unicode, e.g. on BSD/solaris)
+ * - mbch is the native local-dependent multibyte representation
+ */
+
/* Setup wchar glyph for one UCS-2 char */
-static void convert_ucs(int glyph, uint16_t ch, iconv_t conv)
+static void convert_ucs(unsigned char fch, uint16_t uch, iconv_t conv)
{
- wchar_t wch;
- char *pch, *pwch;
- size_t sch, swch;
-
- pch = (char *) &ch;
- pwch = (char *) &wch;
- sch = sizeof(ch);
- swch = sizeof(wch);
-
- if (iconv(conv, &pch, &sch, &pwch, &swch) == (size_t) -1) {
- fprintf(stderr, "Could not convert 0x%04x from UCS-2 to WCHAR_T: %s\n",
- ch, strerror(errno));
- } else {
- vga_to_curses[glyph].chars[0] = wch;
+ char mbch[MB_LEN_MAX];
+ wchar_t wch[2];
+ char *puch, *pmbch;
+ size_t such, smbch;
+ mbstate_t ps;
+
+ puch = (char *) &uch;
+ pmbch = (char *) mbch;
+ such = sizeof(uch);
+ smbch = sizeof(mbch);
+
+ if (iconv(conv, &puch, &such, &pmbch, &smbch) == (size_t) -1) {
+ fprintf(stderr, "Could not convert 0x%04x "
+ "from UCS-2 to a multibyte character: %s\n",
+ uch, strerror(errno));
+ return;
+ }
+
+ memset(&ps, 0, sizeof(ps));
+ if (mbrtowc(&wch[0], mbch, sizeof(mbch) - smbch, &ps) == -1) {
+ fprintf(stderr, "Could not convert 0x%04x "
+ "from a multibyte character to wchar_t: %s\n",
+ uch, strerror(errno));
+ return;
}
+
+ wch[1] = 0;
+ setcchar(&vga_to_curses[fch], wch, 0, 0, NULL);
}
/* Setup wchar glyph for one font character */
-static void convert_font(unsigned char ch, iconv_t conv)
+static void convert_font(unsigned char fch, iconv_t conv)
{
- wchar_t wch;
- char *pch, *pwch;
- size_t sch, swch;
-
- pch = (char *) &ch;
- pwch = (char *) &wch;
- sch = sizeof(ch);
- swch = sizeof(wch);
-
- if (iconv(conv, &pch, &sch, &pwch, &swch) == (size_t) -1) {
- fprintf(stderr, "Could not convert 0x%02x from %s to WCHAR_T: %s\n",
- ch, font_charset, strerror(errno));
- } else {
- vga_to_curses[ch].chars[0] = wch;
+ char mbch[MB_LEN_MAX];
+ wchar_t wch[2];
+ char *pfch, *pmbch;
+ size_t sfch, smbch;
+ mbstate_t ps;
+
+ pfch = (char *) &fch;
+ pmbch = (char *) &mbch;
+ sfch = sizeof(fch);
+ smbch = sizeof(mbch);
+
+ if (iconv(conv, &pfch, &sfch, &pmbch, &smbch) == (size_t) -1) {
+ fprintf(stderr, "Could not convert font glyph 0x%02x "
+ "from %s to a multibyte character: %s\n",
+ fch, font_charset, strerror(errno));
+ return;
+ }
+
+ memset(&ps, 0, sizeof(ps));
+ if (mbrtowc(&wch[0], mbch, sizeof(mbch) - smbch, &ps) == -1) {
+ fprintf(stderr, "Could not convert font glyph 0x%02x "
+ "from a multibyte character to wchar_t: %s\n",
+ fch, strerror(errno));
+ return;
}
+
+ wch[1] = 0;
+ setcchar(&vga_to_curses[fch], wch, 0, 0, NULL);
}
/* Convert one wchar to UCS-2 */
static uint16_t get_ucs(wchar_t wch, iconv_t conv)
{
- uint16_t ch;
- char *pch, *pwch;
- size_t sch, swch;
-
- pch = (char *) &ch;
- pwch = (char *) &wch;
- sch = sizeof(ch);
- swch = sizeof(wch);
-
- if (iconv(conv, &pwch, &swch, &pch, &sch) == (size_t) -1) {
- fprintf(stderr, "Could not convert 0x%02lx from WCHAR_T to UCS-2: %s\n",
- (unsigned long)wch, strerror(errno));
+ char mbch[MB_LEN_MAX];
+ uint16_t uch;
+ char *pmbch, *puch;
+ size_t smbch, such;
+ mbstate_t ps;
+ int ret;
+
+ memset(&ps, 0, sizeof(ps));
+ ret = wcrtomb(mbch, wch, &ps);
+ if (ret == -1) {
+ fprintf(stderr, "Could not convert 0x%04x "
+ "from wchar_t to a multibyte character: %s\n",
+ wch, strerror(errno));
return 0xFFFD;
}
- return ch;
+ pmbch = (char *) mbch;
+ puch = (char *) &uch;
+ smbch = ret;
+ such = sizeof(uch);
+
+ if (iconv(conv, &pmbch, &smbch, &puch, &such) == (size_t) -1) {
+ fprintf(stderr, "Could not convert 0x%04x "
+ "from a multibyte character to UCS-2 : %s\n",
+ wch, strerror(errno));
+ return 0xFFFD;
+ }
+
+ return uch;
}
/*
@@ -466,6 +515,11 @@ static uint16_t get_ucs(wchar_t wch, iconv_t conv)
*/
static void font_setup(void)
{
+ iconv_t ucs2_to_nativecharset;
+ iconv_t nativecharset_to_ucs2;
+ iconv_t font_conv;
+ int i;
+
/*
* Control characters are normally non-printable, but VGA does have
* well-known glyphs for them.
@@ -505,30 +559,25 @@ static void font_setup(void)
0x25bc
};
- iconv_t ucs_to_wchar_conv;
- iconv_t wchar_to_ucs_conv;
- iconv_t font_conv;
- int i;
-
- ucs_to_wchar_conv = iconv_open("WCHAR_T", "UCS-2");
- if (ucs_to_wchar_conv == (iconv_t) -1) {
+ ucs2_to_nativecharset = iconv_open(nl_langinfo(CODESET), "UCS-2");
+ if (ucs2_to_nativecharset == (iconv_t) -1) {
fprintf(stderr, "Could not convert font glyphs from UCS-2: '%s'\n",
strerror(errno));
exit(1);
}
- wchar_to_ucs_conv = iconv_open("UCS-2", "WCHAR_T");
- if (wchar_to_ucs_conv == (iconv_t) -1) {
- iconv_close(ucs_to_wchar_conv);
+ nativecharset_to_ucs2 = iconv_open("UCS-2", nl_langinfo(CODESET));
+ if (nativecharset_to_ucs2 == (iconv_t) -1) {
+ iconv_close(ucs2_to_nativecharset);
fprintf(stderr, "Could not convert font glyphs to UCS-2: '%s'\n",
strerror(errno));
exit(1);
}
- font_conv = iconv_open("WCHAR_T", font_charset);
+ font_conv = iconv_open(nl_langinfo(CODESET), font_charset);
if (font_conv == (iconv_t) -1) {
- iconv_close(ucs_to_wchar_conv);
- iconv_close(wchar_to_ucs_conv);
+ iconv_close(ucs2_to_nativecharset);
+ iconv_close(nativecharset_to_ucs2);
fprintf(stderr, "Could not convert font glyphs from %s: '%s'\n",
font_charset, strerror(errno));
exit(1);
@@ -536,7 +585,7 @@ static void font_setup(void)
/* Control characters */
for (i = 0; i <= 0x1F; i++) {
- convert_ucs(i, control_characters[i], ucs_to_wchar_conv);
+ convert_ucs(i, control_characters[i], ucs2_to_nativecharset);
}
for (i = 0x20; i <= 0xFF; i++) {
@@ -544,12 +593,21 @@ static void font_setup(void)
}
/* DEL */
- convert_ucs(0x7F, 0x2302, ucs_to_wchar_conv);
+ convert_ucs(0x7F, 0x2302, ucs2_to_nativecharset);
if (strcmp(nl_langinfo(CODESET), "UTF-8")) {
/* Non-Unicode capable, use termcap equivalents for those available */
for (i = 0; i <= 0xFF; i++) {
- switch (get_ucs(vga_to_curses[i].chars[0], wchar_to_ucs_conv)) {
+ wchar_t wch[CCHARW_MAX];
+ attr_t attr;
+ short color;
+ int ret;
+
+ ret = getcchar(&vga_to_curses[i], wch, &attr, &color, NULL);
+ if (ret == ERR)
+ continue;
+
+ switch (get_ucs(wch[0], nativecharset_to_ucs2)) {
case 0x00a3:
vga_to_curses[i] = *WACS_STERLING;
break;
@@ -649,8 +707,8 @@ static void font_setup(void)
}
}
}
- iconv_close(ucs_to_wchar_conv);
- iconv_close(wchar_to_ucs_conv);
+ iconv_close(ucs2_to_nativecharset);
+ iconv_close(nativecharset_to_ucs2);
iconv_close(font_conv);
}
diff --git a/ui/kbd-state.c b/ui/kbd-state.c
index f3ab2d7..1668d17 100644
--- a/ui/kbd-state.c
+++ b/ui/kbd-state.c
@@ -59,7 +59,11 @@ void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down)
}
/* update key and modifier state */
- change_bit(qcode, kbd->keys);
+ if (down) {
+ set_bit(qcode, kbd->keys);
+ } else {
+ clear_bit(qcode, kbd->keys);
+ }
switch (qcode) {
case Q_KEY_CODE_SHIFT:
case Q_KEY_CODE_SHIFT_R: