[Qemu-devel] [PATCH 3/5] curses: use wide output functions

2016-10-15 Thread Samuel Thibault
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

2016-06-22 Thread Samuel Thibault
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]