[Qemu-devel] [PATCH 3/5] curses: use wide output functions
This makes use of cchar_t instead of chtype when using ncursesw, which allows to store a wide char as well as the WACS values. This also allows to complete the printable glyphs list beyond ascii and the ACS values. Signed-off-by: Samuel Thibault --- configure| 5 +- hw/display/vga.c | 4 +- include/ui/console.h | 16 ++- ui/curses.c | 321 --- 4 files changed, 294 insertions(+), 52 deletions(-) diff --git a/configure b/configure index 29649d9..ebe0599 100755 --- a/configure +++ b/configure @@ -2901,14 +2901,17 @@ if test "$curses" != "no" ; then #include #include #include +#include int main(void) { const char *s = curses_version(); + const char *codeset; wchar_t wch = L'w'; setlocale(LC_ALL, ""); resize_term(0, 0); addwstr(L"wide chars\n"); addnwstr(&wch, 1); - return s != 0; + codeset = nl_langinfo(CODESET); + return s != 0 && codeset != 0; } EOF IFS=: diff --git a/hw/display/vga.c b/hw/display/vga.c index 2a88b3c..ce225c9 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1966,7 +1966,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) for (i = 0; i < size; src ++, dst ++, i ++) { console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src))); -if (*dst != val) { +if (memcmp(dst, &val, sizeof(val))) { *dst = val; c_max = i; break; @@ -1975,7 +1975,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) c_min = i; for (; i < size; src ++, dst ++, i ++) { console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src))); -if (*dst != val) { +if (memcmp(dst, &val, sizeof(val))) { *dst = val; c_max = i; } diff --git a/include/ui/console.h b/include/ui/console.h index d9c13d2..94e3133 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -338,8 +338,8 @@ static inline pixman_format_code_t surface_format(DisplaySurface *s) #ifdef CONFIG_CURSES #include -typedef chtype console_ch_t; -extern chtype vga_to_curses[]; +typedef cchar_t console_ch_t; +extern console_ch_t vga_to_curses[]; #else typedef unsigned long console_ch_t; #endif @@ -347,16 +347,20 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch) { uint8_t c = ch; #ifdef CONFIG_CURSES -if (vga_to_curses[c]) { -ch &= ~(console_ch_t)0xff; -ch |= vga_to_curses[c]; +if (vga_to_curses[c].chars[0]) { +*dest = vga_to_curses[c]; +} else { +dest->chars[0] = c; +dest->chars[1] = 0; +dest->attr = 0; } +dest->attr |= ch & ~0xff; #else if (c == '\0') { ch |= ' '; } -#endif *dest = ch; +#endif } typedef struct GraphicHwOps { diff --git a/ui/curses.c b/ui/curses.c index 3599295..cd8ed5f 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -28,6 +28,9 @@ #include #include #endif +#include +#include +#include #include "qemu-common.h" #include "ui/console.h" @@ -43,16 +46,17 @@ static WINDOW *screenpad = NULL; static int width, height, gwidth, gheight, invalidate; static int px, py, sminx, sminy, smaxx, smaxy; -chtype vga_to_curses[256]; +console_ch_t vga_to_curses[256]; static void curses_update(DisplayChangeListener *dcl, int x, int y, int w, int h) { -chtype *line; +console_ch_t *line; -line = ((chtype *) screen) + y * width; -for (h += y; y < h; y ++, line += width) -mvwaddchnstr(screenpad, y, 0, line, width); +line = ((console_ch_t *) screen) + y * width; +for (h += y; y < h; y ++, line += width) { +mvwadd_wchnstr(screenpad, y, 0, line, width); +} pnoutrefresh(screenpad, py, px, sminy, sminx, smaxy - 1, smaxx - 1); refresh(); @@ -358,45 +362,275 @@ static void curses_setup(void) /* * Setup mapping for vga to curses line graphics. - * FIXME: for better font, have to use ncursesw and setlocale() */ -#if 0 -/* FIXME: map from where? */ -ACS_S1; -ACS_S3; -ACS_S7; -ACS_S9; -#endif -/* ACS_* is not constant. So, we can't initialize statically. */ -vga_to_curses['\0'] = ' '; -vga_to_curses[0x04] = ACS_DIAMOND; -vga_to_curses[0x18] = ACS_UARROW; -vga_to_curses[0x19] = ACS_DARROW; -vga_to_curses[0x1a] = ACS_RARROW; -vga_to_curses[0x1b] = ACS_LARROW; -vga_to_curses[0x9c] = ACS_STERLING; -vga_to_curses[0xb0] = ACS_BOARD; -vga_to_curses[0xb1] = ACS_CKBOARD; -vga_to_curses[0xb3] = ACS_VLINE; -vga_to_curses[0xb4] = ACS_RTEE; -vga_to_curses[0xbf] = ACS_URCORNER; -vga_to_curses[0xc0] = ACS_LLCORNER; -vga_to_curses[0xc1] = ACS_BTEE; -vga_to_curses[0xc2] = ACS_TTEE; -vga_to_curses[0xc3] = ACS_LTEE; -vga_to_curses[0xc4] = ACS_HLINE; -vga_to
[Qemu-devel] [PATCH 3/5] curses: use wide output functions
This makes use of cchar_t instead of chtype when using ncursesw, which allows to store a wide char as well as the WACS values. This also allows to complete the printable glyphs list beyond ascii and the ACS values. Signed-off-by: Samuel Thibault --- hw/display/vga.c | 4 +- include/ui/console.h | 19 +++- ui/curses.c | 270 --- 3 files changed, 278 insertions(+), 15 deletions(-) diff --git a/hw/display/vga.c b/hw/display/vga.c index 9ebc54f..53d3c9a 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1968,7 +1968,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) for (i = 0; i < size; src ++, dst ++, i ++) { console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src))); -if (*dst != val) { +if (memcmp(dst, &val, sizeof(val))) { *dst = val; c_max = i; break; @@ -1977,7 +1977,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) c_min = i; for (; i < size; src ++, dst ++, i ++) { console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src))); -if (*dst != val) { +if (memcmp(dst, &val, sizeof(val))) { *dst = val; c_max = i; } diff --git a/include/ui/console.h b/include/ui/console.h index 52a5f65..2939176 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -336,8 +336,12 @@ static inline pixman_format_code_t surface_format(DisplaySurface *s) #ifdef CONFIG_CURSES #include +#ifdef CONFIG_CURSESW +typedef cchar_t console_ch_t; +#else typedef chtype console_ch_t; -extern chtype vga_to_curses[]; +#endif +extern console_ch_t vga_to_curses[]; #else typedef unsigned long console_ch_t; #endif @@ -345,16 +349,27 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch) { uint8_t c = ch; #ifdef CONFIG_CURSES +#ifdef CONFIG_CURSESW +if (vga_to_curses[c].chars[0]) { +*dest = vga_to_curses[c]; +} else { +dest->chars[0] = c; +dest->attr = 0; +} +dest->attr |= ch & ~0xff; +#else if (vga_to_curses[c]) { ch &= ~(console_ch_t)0xff; ch |= vga_to_curses[c]; } +*dest = ch; +#endif #else if (c == '\0') { ch |= ' '; } -#endif *dest = ch; +#endif } typedef struct GraphicHwOps { diff --git a/ui/curses.c b/ui/curses.c index 438b8be..9ef54b5 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -28,6 +28,11 @@ #include #include #endif +#ifdef CONFIG_CURSESW +#include +#include +#include +#endif #include "qemu-common.h" #include "ui/console.h" @@ -43,16 +48,25 @@ static WINDOW *screenpad = NULL; static int width, height, gwidth, gheight, invalidate; static int px, py, sminx, sminy, smaxx, smaxy; +#ifdef CONFIG_CURSESW +console_ch_t vga_to_curses[256]; +#else chtype vga_to_curses[256]; +#endif static void curses_update(DisplayChangeListener *dcl, int x, int y, int w, int h) { -chtype *line; +console_ch_t *line; -line = ((chtype *) screen) + y * width; -for (h += y; y < h; y ++, line += width) +line = ((console_ch_t *) screen) + y * width; +for (h += y; y < h; y ++, line += width) { +#ifdef CONFIG_CURSESW +mvwadd_wchnstr(screenpad, y, 0, line, width); +#else mvwaddchnstr(screenpad, y, 0, line, width); +#endif +} pnoutrefresh(screenpad, py, px, sminy, sminx, smaxy - 1, smaxx - 1); refresh(); @@ -362,15 +376,245 @@ static void curses_setup(void) /* * Setup mapping for vga to curses line graphics. - * FIXME: for better font, have to use ncursesw and setlocale() */ -#if 0 -/* FIXME: map from where? */ -ACS_S1; -ACS_S3; -ACS_S7; -ACS_S9; -#endif + +#ifdef CONFIG_CURSESW +vga_to_curses['\0'].chars[0] = L' '; +vga_to_curses[0x01].chars[0] = L'\u263a'; +vga_to_curses[0x02].chars[0] = L'\u263b'; +vga_to_curses[0x03].chars[0] = L'\u2665'; +vga_to_curses[0x04].chars[0] = L'\u2666'; +vga_to_curses[0x05].chars[0] = L'\u2663'; +vga_to_curses[0x06].chars[0] = L'\u2660'; +vga_to_curses[0x07].chars[0] = L'\u2022'; +vga_to_curses[0x08].chars[0] = L'\u25d8'; +vga_to_curses[0x09].chars[0] = L'\u25cb'; +vga_to_curses[0x0a].chars[0] = L'\u25d9'; +vga_to_curses[0x0b].chars[0] = L'\u2642'; +vga_to_curses[0x0c].chars[0] = L'\u2640'; +vga_to_curses[0x0d].chars[0] = L'\u266a'; +vga_to_curses[0x0e].chars[0] = L'\u266b'; +vga_to_curses[0x0f].chars[0] = L'\u263c'; +vga_to_curses[0x10].chars[0] = L'\u25ba'; +vga_to_curses[0x11].chars[0] = L'\u25c4'; +vga_to_curses[0x12].chars[0] = L'\u2195'; +vga_to_curses[0x13].chars[0] = L'\u203c'; +vga_to_curses[0x14].chars[0] = L'\u00b6'; +vga_to_curses[0x15].chars[0] = L'\u00a7'; +vga_to_curses[0x16].chars[0]