@@ -203,6 +203,7 @@ bluez=""
brlapi=""
curl=""
curses=""
+cursesw=""
docs=""
fdt=""
netmap="no"
@@ -984,6 +985,10 @@ for opt do
;;
--enable-curses) curses="yes"
;;
+ --disable-iconv) iconv="no"
+ ;;
+ --enable-iconv) iconv="yes"
+ ;;
--disable-curl) curl="no"
;;
--enable-curl) curl="yes"
@@ -1351,6 +1356,7 @@ disabled with --disable-FEATURE, default is enabled if available:
--with-gtkabi select preferred GTK ABI 2.0 or 3.0
vte vte support for the gtk UI
curses curses 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
@@ -2938,6 +2944,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
@@ -4860,6 +4893,7 @@ echo "nettle $nettle $(echo_version $nettle $nettle_version)"
echo "nettle kdf $nettle_kdf"
echo "libtasn1 $tasn1"
echo "curses support $curses"
+echo "iconv support $iconv"
echo "virgl support $virglrenderer"
echo "curl support $curl"
echo "mingw32 support $mingw32"
@@ -5120,6 +5154,9 @@ fi
if test "$curses" = "yes" ; then
echo "CONFIG_CURSES=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
@@ -148,6 +148,7 @@ extern int graphic_height;
extern int graphic_depth;
extern int display_opengl;
extern const char *keyboard_layout;
+extern const char *font_charset;
extern int win2k_install_hack;
extern int alt_grab;
extern int ctrl_grab;
@@ -930,7 +930,7 @@ DEF("display", HAS_ARG, QEMU_OPTION_display,
" [,window_close=on|off][,gl=on|off]|curses|none|\n"
"-display gtk[,grab_on_hover=on|off][,gl=on|off]|\n"
"-display vnc=<display>[,<optargs>]\n"
- "-display curses\n"
+ "-display curses[,charset=<encoding>]\n"
"-display none"
" select display type\n"
"The default display is equivalent to\n"
@@ -961,6 +961,9 @@ support a text mode, QEMU can display this output using a
curses/ncurses interface. Nothing is displayed when the graphics
device is in graphical mode or if the graphics device does not support
a text mode. Generally only the VGA device models support text mode.
+The font charset used by the guest can be specified with the
+@code{charset} option, for example @code{charset=CP850} for IBM CP850
+encoding. The default is @code{CP437}.
@item none
Do not display video output. The guest will still see an emulated
graphics card, but its output will not be displayed to the QEMU
@@ -31,6 +31,9 @@
#include <locale.h>
#include <wchar.h>
#include <langinfo.h>
+#ifdef CONFIG_ICONV
+#include <iconv.h>
+#endif
#include "qemu-common.h"
#include "ui/console.h"
@@ -397,6 +400,44 @@ 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_charset) {
+ unsigned char ch;
+ wchar_t wch;
+ char *pch, *pwch;
+ size_t sch, swch;
+ iconv_t conv;
+
+ conv = iconv_open("WCHAR_T", font_charset);
+ if (conv == (iconv_t) -1) {
+ fprintf(stderr, "Could not convert font glyphs from %s: '%s'\n",
+ font_charset, 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_charset, strerror(errno));
+ } else {
+ vga_to_curses[ch].chars[0] = wch;
+ }
+ }
+ } else
+#else
+ if (font_charset) {
+ if (strcmp(font_charset, "CP437")) {
+ fprintf(stderr, "iconv support not enabled for converting from %s, "
+ "only CP437 supported\n", font_charset);
+ exit(1);
+ }
+ }
+#endif
{
/* Hardcode CP437 to unicode */
vga_to_curses[0x80].chars[0] = L'\u00C7';
@@ -132,7 +132,8 @@ const char *bios_name = NULL;
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
int request_opengl = -1;
int display_opengl;
-const char* keyboard_layout = NULL;
+const char *keyboard_layout;
+const char *font_charset;
ram_addr_t ram_size;
const char *mem_path = NULL;
int mem_prealloc = 0; /* force preallocation of physical target memory */
@@ -2140,6 +2141,24 @@ static DisplayType select_display(const char *p)
} else if (strstart(p, "curses", &opts)) {
#ifdef CONFIG_CURSES
display = DT_CURSES;
+ while (*opts) {
+ const char *nextopt, *name;
+
+ if (strstart(opts, ",charset=", &name)) {
+ nextopt = strchr(name, ',');
+ if (nextopt) {
+ font_charset = g_strndup(name, nextopt - name);
+ nextopt++;
+ } else {
+ font_charset = g_strdup(name);
+ nextopt = name + strlen(name);
+ }
+ } else {
+ error_report("invalid curses option string");
+ exit(1);
+ }
+ opts = nextopt;
+ }
#else
error_report("curses support is disabled");
exit(1);
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 | 5 ++++- ui/curses.c | 41 +++++++++++++++++++++++++++++++++++++++++ vl.c | 21 ++++++++++++++++++++- 5 files changed, 103 insertions(+), 2 deletions(-)