diff mbox

[4/5] curses: add option to specify VGA font encoding

Message ID 1466634202-24616-5-git-send-email-samuel.thibault@ens-lyon.org (mailing list archive)
State New, archived
Headers show

Commit Message

Samuel Thibault June 22, 2016, 10:23 p.m. UTC
This detects and uses iconv to convert glyphs from the specified VGA font
encoding to unicode.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
---
 configure               | 37 +++++++++++++++++++++++++++++++++++++
 include/sysemu/sysemu.h |  1 +
 qemu-options.hx         | 20 ++++++++++++++++++++
 ui/curses.c             | 40 ++++++++++++++++++++++++++++++++++++++++
 vl.c                    |  4 ++++
 5 files changed, 102 insertions(+)

Comments

Markus Armbruster June 23, 2016, 7:34 a.m. UTC | #1
Samuel Thibault <samuel.thibault@ens-lyon.org> writes:

> This detects and uses iconv to convert glyphs from the specified VGA font
> encoding to unicode.
>
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
[...]
> diff --git a/qemu-options.hx b/qemu-options.hx
> index ce535a9..2187886 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -321,6 +321,26 @@ The default is @code{en-us}.
>  ETEXI
>  
>  
> +DEF("f", HAS_ARG, QEMU_OPTION_f,
> +    "-f encoding     use font encoding (for example 'CP850' for IBM CP850 encoding)\n",
> +    QEMU_ARCH_ALL)
> +STEXI
> +@item -h @var{encoding}
> +@findex -h
> +Use font encoding @var{encoding} (for example @code{CP850} for
> +IBM CP/850 encoding). This option is only needed where output is text-only, i.e.
> +with the curses display, to convert from text-mode output from the guest to
> +proper text glyphs.
> +
> +The available encoding are provided by the libc, the full list can be obtained by
> +@example
> +iconv -l
> +@end example
> +
> +The default is @code{CP437}.
> +ETEXI
> +
> +

Since this option applies only to the curses display, it should be a
-display curses parameter, like this: -display curses,charset=CP850.

>  DEF("audio-help", 0, QEMU_OPTION_audio_help,
>      "-audio-help     print list of audio drivers and their options\n",
>      QEMU_ARCH_ALL)
[...]
diff mbox

Patch

diff --git a/configure b/configure
index ff10012..14e98f5 100755
--- a/configure
+++ b/configure
@@ -204,6 +204,7 @@  brlapi=""
 curl=""
 curses=""
 cursesw=""
+iconv=""
 docs=""
 fdt=""
 netmap="no"
@@ -983,6 +984,10 @@  for opt do
   ;;
   --enable-cursesw) cursesw="yes"
   ;;
+  --disable-iconv) iconv="no"
+  ;;
+  --enable-iconv) iconv="yes"
+  ;;
   --disable-curl) curl="no"
   ;;
   --enable-curl) curl="yes"
@@ -1333,6 +1338,7 @@  disabled with --disable-FEATURE, default is enabled if available:
   vte             vte support for the gtk UI
   curses          curses UI
   cursesw         cursesw UI
+  iconv           font glyph conversion support
   vnc             VNC UI support
   vnc-sasl        SASL encryption for VNC server
   vnc-jpeg        JPEG lossy compression for VNC server
@@ -2968,6 +2974,33 @@  EOF
 fi
 
 ##########################################
+# iconv probe
+if test "$iconv" != "no" ; then
+  cat > $TMPC << EOF
+#include <iconv.h>
+int main(void) {
+  iconv_t conv = iconv_open("ISO-8859-1", "ISO-8859-1");
+  return conv != (iconv_t) -1;
+}
+EOF
+  for iconv_lib in '' -liconv; do
+    if compile_prog "" "$iconv_lib" ; then
+      iconv_found=yes
+      libs_softmmu="$iconv_lib $libs_softmmu"
+      break
+    fi
+  done
+  if test "$iconv_found" = "yes" ; then
+    iconv=yes
+  else
+    if test "$iconv" = "yes" ; then
+      feature_not_found "iconv" "Install iconv devel"
+    fi
+    iconv=no
+  fi
+fi
+
+##########################################
 # curl probe
 if test "$curl" != "no" ; then
   if $pkg_config libcurl --exists; then
@@ -4859,6 +4892,7 @@  echo "nettle kdf        $nettle_kdf"
 echo "libtasn1          $tasn1"
 echo "curses support    $curses"
 echo "cursesw support   $cursesw"
+echo "iconv support     $iconv"
 echo "virgl support     $virglrenderer"
 echo "curl support      $curl"
 echo "mingw32 support   $mingw32"
@@ -5120,6 +5154,9 @@  fi
 if test "$cursesw" = "yes" ; then
   echo "CONFIG_CURSESW=y" >> $config_host_mak
 fi
+if test "$iconv" = "yes" ; then
+  echo "CONFIG_ICONV=y" >> $config_host_mak
+fi
 if test "$utimens" = "yes" ; then
   echo "CONFIG_UTIMENSAT=y" >> $config_host_mak
 fi
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 7313673..a690c18 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -147,6 +147,7 @@  extern int graphic_height;
 extern int graphic_depth;
 extern int display_opengl;
 extern const char *keyboard_layout;
+extern const char *font_encoding;
 extern int win2k_install_hack;
 extern int alt_grab;
 extern int ctrl_grab;
diff --git a/qemu-options.hx b/qemu-options.hx
index ce535a9..2187886 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -321,6 +321,26 @@  The default is @code{en-us}.
 ETEXI
 
 
+DEF("f", HAS_ARG, QEMU_OPTION_f,
+    "-f encoding     use font encoding (for example 'CP850' for IBM CP850 encoding)\n",
+    QEMU_ARCH_ALL)
+STEXI
+@item -h @var{encoding}
+@findex -h
+Use font encoding @var{encoding} (for example @code{CP850} for
+IBM CP/850 encoding). This option is only needed where output is text-only, i.e.
+with the curses display, to convert from text-mode output from the guest to
+proper text glyphs.
+
+The available encoding are provided by the libc, the full list can be obtained by
+@example
+iconv -l
+@end example
+
+The default is @code{CP437}.
+ETEXI
+
+
 DEF("audio-help", 0, QEMU_OPTION_audio_help,
     "-audio-help     print list of audio drivers and their options\n",
     QEMU_ARCH_ALL)
diff --git a/ui/curses.c b/ui/curses.c
index 9ef54b5..a8dada9 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -33,6 +33,9 @@ 
 #include <wchar.h>
 #include <langinfo.h>
 #endif
+#ifdef CONFIG_ICONV
+#include <iconv.h>
+#endif
 
 #include "qemu-common.h"
 #include "ui/console.h"
@@ -412,6 +415,43 @@  static void curses_setup(void)
     vga_to_curses[0x1e].chars[0] = L'\u25b2';
     vga_to_curses[0x1f].chars[0] = L'\u25bc';
 
+#ifdef CONFIG_ICONV
+    if (font_encoding) {
+        unsigned char ch;
+        wchar_t wch;
+        char *pch, *pwch;
+        size_t sch, swch;
+        iconv_t conv;
+
+        conv = iconv_open("WCHAR_T", font_encoding);
+        if (conv == (iconv_t) -1) {
+            fprintf(stderr, "Could not convert font glyphs from %s: '%s'\n", font_encoding, strerror(errno));
+            exit(1);
+        }
+
+        for (i = 0x20; i <= 0xff; i++)
+        {
+            ch = i;
+            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%2x from %s: '%s'\n", ch, font_encoding, strerror(errno));
+            } else {
+                vga_to_curses[ch].chars[0] = wch;
+            }
+        }
+    } else
+#else
+    if (font_encoding) {
+        if (strcmp(font_encoding, "CP437"))
+        {
+            fprintf(stderr,"iconv support not enabled for converting from %s, only CP437 supported\n", font_encoding);
+            exit(1);
+        }
+    }
+#endif
     {
         /* Hardcode CP437 to unicode */
         vga_to_curses[0x80].chars[0] = L'\u00C7';
diff --git a/vl.c b/vl.c
index 2f63eb4..508a59f 100644
--- a/vl.c
+++ b/vl.c
@@ -132,6 +132,7 @@  enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 int request_opengl = -1;
 int display_opengl;
 const char* keyboard_layout = NULL;
+const char* font_encoding = NULL;
 ram_addr_t ram_size;
 const char *mem_path = NULL;
 int mem_prealloc = 0; /* force preallocation of physical target memory */
@@ -3370,6 +3371,9 @@  int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_k:
                 keyboard_layout = optarg;
                 break;
+            case QEMU_OPTION_f:
+                font_encoding = optarg;
+                break;
             case QEMU_OPTION_localtime:
                 rtc_utc = 0;
                 break;