mirror of https://github.com/xemu-project/xemu.git
ui: bugfixes for curses, opengl console and kbd state tracker.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJc3t1uAAoJEEy22O7T6HE4+QAP/3Z3na7+L/qBNclvAZZpIBm3 35BX47SxHi6po3SD8ad2tXm9NIZhxIoVidOYLAS2VHxnEJmIY3xxHQCnSbkBfRtW O3o0QPE4g5DAF2AGccPpPhe/8oBOLyMyCdkilQly6w/GJzgGAJr9AuXaszUkrB5u TY5pn9pcjDQpdXJP1cQoGciYJSBUBvYlEPCClhiRZhB7PCJN8xfLhBB8VbMZRM+h iW2IoFpQVYHHHXEM8HgzavWmbixOAp5OV+ZYyUG/ISxUbIaPPz+JXhd+xydqHhA3 sQstTtgIWIZRQDDyUpv+vtWyKfet9SImK6DuJaJnP7CndvJIRmKBHMhxzaZzdVmk 5PWfo58eDs2ir/BQgcbhMpy8YbvMNn5sK17qb/N2XCeYhejviHK/N6tkDrH5FRa5 emc1jjr9RojhtwUTYKluVHibPMs2bxlVFyfbfaYxN9apBAkZS2DXxk2xaPgmgbiB E/DAb53UAkm8hgwCG7S7La3BLhzDCWLBi0j/elYotfXcizA9brsE+XiBnf/4GyFY Xg08igSRUBByutvPPTvHqTMi1Iy5h0DpeT/PFDYYNidF0KrHzTF7Eo1shAsY0K6q cNmXIaMge08PXPeCICcVWKPI/xKxfIuwqtzsC0C2LhxKk5ty+oQ+t5kwleKb0Wbw MTEPVV/ELUyp5Fi7pge9 =u85u -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
1b46b4daa6
|
@ -92,13 +92,17 @@ void surface_gl_update_texture(QemuGLShader *gls,
|
||||||
|
|
||||||
assert(gls);
|
assert(gls);
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT,
|
if (surface->texture) {
|
||||||
surface_stride(surface) / surface_bytes_per_pixel(surface));
|
glBindTexture(GL_TEXTURE_2D, surface->texture);
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT,
|
||||||
x, y, w, h,
|
surface_stride(surface)
|
||||||
surface->glformat, surface->gltype,
|
/ surface_bytes_per_pixel(surface));
|
||||||
data + surface_stride(surface) * y
|
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||||
+ surface_bytes_per_pixel(surface) * x);
|
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,
|
void surface_gl_render_texture(QemuGLShader *gls,
|
||||||
|
|
184
ui/curses.c
184
ui/curses.c
|
@ -66,20 +66,22 @@ static void curses_update(DisplayChangeListener *dcl,
|
||||||
{
|
{
|
||||||
console_ch_t *line;
|
console_ch_t *line;
|
||||||
cchar_t curses_line[width];
|
cchar_t curses_line[width];
|
||||||
|
wchar_t wch[CCHARW_MAX];
|
||||||
|
attr_t attrs;
|
||||||
|
short colors;
|
||||||
|
int ret;
|
||||||
|
|
||||||
line = screen + y * width;
|
line = screen + y * width;
|
||||||
for (h += y; y < h; y ++, line += width) {
|
for (h += y; y < h; y ++, line += width) {
|
||||||
for (x = 0; x < width; x++) {
|
for (x = 0; x < width; x++) {
|
||||||
chtype ch = line[x] & 0xff;
|
chtype ch = line[x] & 0xff;
|
||||||
chtype at = line[x] & ~0xff;
|
chtype at = line[x] & ~0xff;
|
||||||
if (vga_to_curses[ch].chars[0]) {
|
ret = getcchar(&vga_to_curses[ch], wch, &attrs, &colors, NULL);
|
||||||
curses_line[x] = vga_to_curses[ch];
|
if (ret == ERR || wch[0] == 0) {
|
||||||
} else {
|
wch[0] = ch;
|
||||||
curses_line[x] = (cchar_t) {
|
wch[1] = 0;
|
||||||
.chars[0] = ch,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
curses_line[x].attr |= at;
|
setcchar(&curses_line[x], wch, at, 0, NULL);
|
||||||
}
|
}
|
||||||
mvwadd_wchnstr(screenpad, y, 0, curses_line, width);
|
mvwadd_wchnstr(screenpad, y, 0, curses_line, width);
|
||||||
}
|
}
|
||||||
|
@ -400,65 +402,112 @@ static void curses_atexit(void)
|
||||||
endwin();
|
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 */
|
/* 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 mbch[MB_LEN_MAX];
|
||||||
char *pch, *pwch;
|
wchar_t wch[2];
|
||||||
size_t sch, swch;
|
char *puch, *pmbch;
|
||||||
|
size_t such, smbch;
|
||||||
|
mbstate_t ps;
|
||||||
|
|
||||||
pch = (char *) &ch;
|
puch = (char *) &uch;
|
||||||
pwch = (char *) &wch;
|
pmbch = (char *) mbch;
|
||||||
sch = sizeof(ch);
|
such = sizeof(uch);
|
||||||
swch = sizeof(wch);
|
smbch = sizeof(mbch);
|
||||||
|
|
||||||
if (iconv(conv, &pch, &sch, &pwch, &swch) == (size_t) -1) {
|
if (iconv(conv, &puch, &such, &pmbch, &smbch) == (size_t) -1) {
|
||||||
fprintf(stderr, "Could not convert 0x%04x from UCS-2 to WCHAR_T: %s\n",
|
fprintf(stderr, "Could not convert 0x%04x "
|
||||||
ch, strerror(errno));
|
"from UCS-2 to a multibyte character: %s\n",
|
||||||
} else {
|
uch, strerror(errno));
|
||||||
vga_to_curses[glyph].chars[0] = wch;
|
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 */
|
/* 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 mbch[MB_LEN_MAX];
|
||||||
char *pch, *pwch;
|
wchar_t wch[2];
|
||||||
size_t sch, swch;
|
char *pfch, *pmbch;
|
||||||
|
size_t sfch, smbch;
|
||||||
|
mbstate_t ps;
|
||||||
|
|
||||||
pch = (char *) &ch;
|
pfch = (char *) &fch;
|
||||||
pwch = (char *) &wch;
|
pmbch = (char *) &mbch;
|
||||||
sch = sizeof(ch);
|
sfch = sizeof(fch);
|
||||||
swch = sizeof(wch);
|
smbch = sizeof(mbch);
|
||||||
|
|
||||||
if (iconv(conv, &pch, &sch, &pwch, &swch) == (size_t) -1) {
|
if (iconv(conv, &pfch, &sfch, &pmbch, &smbch) == (size_t) -1) {
|
||||||
fprintf(stderr, "Could not convert 0x%02x from %s to WCHAR_T: %s\n",
|
fprintf(stderr, "Could not convert font glyph 0x%02x "
|
||||||
ch, font_charset, strerror(errno));
|
"from %s to a multibyte character: %s\n",
|
||||||
} else {
|
fch, font_charset, strerror(errno));
|
||||||
vga_to_curses[ch].chars[0] = wch;
|
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 */
|
/* Convert one wchar to UCS-2 */
|
||||||
static uint16_t get_ucs(wchar_t wch, iconv_t conv)
|
static uint16_t get_ucs(wchar_t wch, iconv_t conv)
|
||||||
{
|
{
|
||||||
uint16_t ch;
|
char mbch[MB_LEN_MAX];
|
||||||
char *pch, *pwch;
|
uint16_t uch;
|
||||||
size_t sch, swch;
|
char *pmbch, *puch;
|
||||||
|
size_t smbch, such;
|
||||||
|
mbstate_t ps;
|
||||||
|
int ret;
|
||||||
|
|
||||||
pch = (char *) &ch;
|
memset(&ps, 0, sizeof(ps));
|
||||||
pwch = (char *) &wch;
|
ret = wcrtomb(mbch, wch, &ps);
|
||||||
sch = sizeof(ch);
|
if (ret == -1) {
|
||||||
swch = sizeof(wch);
|
fprintf(stderr, "Could not convert 0x%04x "
|
||||||
|
"from wchar_t to a multibyte character: %s\n",
|
||||||
if (iconv(conv, &pwch, &swch, &pch, &sch) == (size_t) -1) {
|
wch, strerror(errno));
|
||||||
fprintf(stderr, "Could not convert 0x%02lx from WCHAR_T to UCS-2: %s\n",
|
|
||||||
(unsigned long)wch, strerror(errno));
|
|
||||||
return 0xFFFD;
|
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)
|
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
|
* Control characters are normally non-printable, but VGA does have
|
||||||
* well-known glyphs for them.
|
* well-known glyphs for them.
|
||||||
|
@ -505,30 +559,25 @@ static void font_setup(void)
|
||||||
0x25bc
|
0x25bc
|
||||||
};
|
};
|
||||||
|
|
||||||
iconv_t ucs_to_wchar_conv;
|
ucs2_to_nativecharset = iconv_open(nl_langinfo(CODESET), "UCS-2");
|
||||||
iconv_t wchar_to_ucs_conv;
|
if (ucs2_to_nativecharset == (iconv_t) -1) {
|
||||||
iconv_t font_conv;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
ucs_to_wchar_conv = iconv_open("WCHAR_T", "UCS-2");
|
|
||||||
if (ucs_to_wchar_conv == (iconv_t) -1) {
|
|
||||||
fprintf(stderr, "Could not convert font glyphs from UCS-2: '%s'\n",
|
fprintf(stderr, "Could not convert font glyphs from UCS-2: '%s'\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_to_ucs_conv = iconv_open("UCS-2", "WCHAR_T");
|
nativecharset_to_ucs2 = iconv_open("UCS-2", nl_langinfo(CODESET));
|
||||||
if (wchar_to_ucs_conv == (iconv_t) -1) {
|
if (nativecharset_to_ucs2 == (iconv_t) -1) {
|
||||||
iconv_close(ucs_to_wchar_conv);
|
iconv_close(ucs2_to_nativecharset);
|
||||||
fprintf(stderr, "Could not convert font glyphs to UCS-2: '%s'\n",
|
fprintf(stderr, "Could not convert font glyphs to UCS-2: '%s'\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
exit(1);
|
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) {
|
if (font_conv == (iconv_t) -1) {
|
||||||
iconv_close(ucs_to_wchar_conv);
|
iconv_close(ucs2_to_nativecharset);
|
||||||
iconv_close(wchar_to_ucs_conv);
|
iconv_close(nativecharset_to_ucs2);
|
||||||
fprintf(stderr, "Could not convert font glyphs from %s: '%s'\n",
|
fprintf(stderr, "Could not convert font glyphs from %s: '%s'\n",
|
||||||
font_charset, strerror(errno));
|
font_charset, strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -536,7 +585,7 @@ static void font_setup(void)
|
||||||
|
|
||||||
/* Control characters */
|
/* Control characters */
|
||||||
for (i = 0; i <= 0x1F; i++) {
|
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++) {
|
for (i = 0x20; i <= 0xFF; i++) {
|
||||||
|
@ -544,12 +593,21 @@ static void font_setup(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DEL */
|
/* DEL */
|
||||||
convert_ucs(0x7F, 0x2302, ucs_to_wchar_conv);
|
convert_ucs(0x7F, 0x2302, ucs2_to_nativecharset);
|
||||||
|
|
||||||
if (strcmp(nl_langinfo(CODESET), "UTF-8")) {
|
if (strcmp(nl_langinfo(CODESET), "UTF-8")) {
|
||||||
/* Non-Unicode capable, use termcap equivalents for those available */
|
/* Non-Unicode capable, use termcap equivalents for those available */
|
||||||
for (i = 0; i <= 0xFF; i++) {
|
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:
|
case 0x00a3:
|
||||||
vga_to_curses[i] = *WACS_STERLING;
|
vga_to_curses[i] = *WACS_STERLING;
|
||||||
break;
|
break;
|
||||||
|
@ -649,8 +707,8 @@ static void font_setup(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iconv_close(ucs_to_wchar_conv);
|
iconv_close(ucs2_to_nativecharset);
|
||||||
iconv_close(wchar_to_ucs_conv);
|
iconv_close(nativecharset_to_ucs2);
|
||||||
iconv_close(font_conv);
|
iconv_close(font_conv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,11 @@ void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update key and modifier state */
|
/* 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) {
|
switch (qcode) {
|
||||||
case Q_KEY_CODE_SHIFT:
|
case Q_KEY_CODE_SHIFT:
|
||||||
case Q_KEY_CODE_SHIFT_R:
|
case Q_KEY_CODE_SHIFT_R:
|
||||||
|
|
Loading…
Reference in New Issue