* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
#include "qemu/osdep.h"
#ifndef _WIN32
#endif
#include <locale.h>
#include <wchar.h>
-#include <langinfo.h>
#include <iconv.h>
#include "qapi/error.h"
-#include "qemu-common.h"
+#include "qemu/module.h"
#include "ui/console.h"
#include "ui/input.h"
#include "sysemu/sysemu.h"
+#if defined(__APPLE__) || defined(__OpenBSD__)
+#define _XOPEN_SOURCE_EXTENDED 1
+#endif
+
/* KEY_EVENT is defined in wincon.h and in curses.h. Avoid redefinition. */
#undef KEY_EVENT
#include <curses.h>
};
static DisplayChangeListener *dcl;
-static console_ch_t screen[160 * 100];
+static console_ch_t *screen;
static WINDOW *screenpad = NULL;
static int width, height, gwidth, gheight, invalidate;
static int px, py, sminx, sminy, smaxx, smaxy;
static const char *font_charset = "CP437";
-static cchar_t vga_to_curses[256];
+static cchar_t *vga_to_curses;
static void curses_update(DisplayChangeListener *dcl,
int x, int y, int w, int h)
{
console_ch_t *line;
- cchar_t curses_line[width];
+ g_autofree cchar_t *curses_line = g_new(cchar_t, width);
wchar_t wch[CCHARW_MAX];
attr_t attrs;
short colors;
line = screen + y * width;
for (h += y; y < h; y ++, line += width) {
for (x = 0; x < width; x++) {
- chtype ch = line[x] & 0xff;
- chtype at = line[x] & ~0xff;
+ chtype ch = line[x] & A_CHARTEXT;
+ chtype at = line[x] & A_ATTRIBUTES;
+ short color_pair = PAIR_NUMBER(line[x]);
+
ret = getcchar(&vga_to_curses[ch], wch, &attrs, &colors, NULL);
if (ret == ERR || wch[0] == 0) {
wch[0] = ch;
wch[1] = 0;
}
- setcchar(&curses_line[x], wch, at, 0, NULL);
+ setcchar(&curses_line[x], wch, at, color_pair, NULL);
}
mvwadd_wchnstr(screenpad, y, 0, curses_line, width);
}
static void curses_calc_pad(void)
{
- if (qemu_console_is_fixedsize(NULL)) {
+ if (qemu_console_is_fixedsize(dcl->con)) {
width = gwidth;
height = gheight;
} else {
curs_set(1);
/* it seems that curs_set(1) must always be called before
* curs_set(2) for the latter to have effect */
- if (!qemu_console_is_graphic(NULL)) {
+ if (!qemu_console_is_graphic(dcl->con)) {
curs_set(2);
}
return;
case ERR:
ret = -1;
break;
+ default:
+ abort();
}
return ret;
}
static void curses_refresh(DisplayChangeListener *dcl)
{
int chr, keysym, keycode, keycode_alt;
- enum maybe_keycode maybe_keycode;
+ enum maybe_keycode maybe_keycode = CURSES_KEYCODE;
curses_winch_check();
clear();
refresh();
curses_calc_pad();
- graphic_hw_invalidate(NULL);
+ graphic_hw_invalidate(dcl->con);
invalidate = 0;
}
- graphic_hw_text_update(NULL, screen);
+ graphic_hw_text_update(dcl->con, screen);
while (1) {
/* while there are any pending key strokes to process */
/* alt or esc key */
if (keycode == 1) {
- enum maybe_keycode next_maybe_keycode;
+ enum maybe_keycode next_maybe_keycode = CURSES_KEYCODE;
int nextchr = console_getch(&next_maybe_keycode);
if (nextchr != -1) {
/* process keys reserved for qemu */
if (keycode >= QEMU_KEY_CONSOLE0 &&
keycode < QEMU_KEY_CONSOLE0 + 9) {
- erase();
- wnoutrefresh(stdscr);
- console_select(keycode - QEMU_KEY_CONSOLE0);
-
- invalidate = 1;
+ QemuConsole *con = qemu_console_lookup_by_index(keycode - QEMU_KEY_CONSOLE0);
+ if (con) {
+ erase();
+ wnoutrefresh(stdscr);
+ unregister_displaychangelistener(dcl);
+ dcl->con = con;
+ register_displaychangelistener(dcl);
+
+ invalidate = 1;
+ }
continue;
}
}
if (keycode == -1)
continue;
- if (qemu_console_is_graphic(NULL)) {
+ if (qemu_console_is_graphic(dcl->con)) {
/* since terminals don't know about key press and release
* events, we need to emit both for each key received */
if (keycode & SHIFT) {
- qemu_input_event_send_key_number(NULL, SHIFT_CODE, true);
+ qemu_input_event_send_key_number(dcl->con, SHIFT_CODE, true);
qemu_input_event_send_key_delay(0);
}
if (keycode & CNTRL) {
- qemu_input_event_send_key_number(NULL, CNTRL_CODE, true);
+ qemu_input_event_send_key_number(dcl->con, CNTRL_CODE, true);
qemu_input_event_send_key_delay(0);
}
if (keycode & ALT) {
- qemu_input_event_send_key_number(NULL, ALT_CODE, true);
+ qemu_input_event_send_key_number(dcl->con, ALT_CODE, true);
qemu_input_event_send_key_delay(0);
}
if (keycode & ALTGR) {
- qemu_input_event_send_key_number(NULL, GREY | ALT_CODE, true);
+ qemu_input_event_send_key_number(dcl->con, GREY | ALT_CODE, true);
qemu_input_event_send_key_delay(0);
}
- qemu_input_event_send_key_number(NULL, keycode & KEY_MASK, true);
+ qemu_input_event_send_key_number(dcl->con, keycode & KEY_MASK, true);
qemu_input_event_send_key_delay(0);
- qemu_input_event_send_key_number(NULL, keycode & KEY_MASK, false);
+ qemu_input_event_send_key_number(dcl->con, keycode & KEY_MASK, false);
qemu_input_event_send_key_delay(0);
if (keycode & ALTGR) {
- qemu_input_event_send_key_number(NULL, GREY | ALT_CODE, false);
+ qemu_input_event_send_key_number(dcl->con, GREY | ALT_CODE, false);
qemu_input_event_send_key_delay(0);
}
if (keycode & ALT) {
- qemu_input_event_send_key_number(NULL, ALT_CODE, false);
+ qemu_input_event_send_key_number(dcl->con, ALT_CODE, false);
qemu_input_event_send_key_delay(0);
}
if (keycode & CNTRL) {
- qemu_input_event_send_key_number(NULL, CNTRL_CODE, false);
+ qemu_input_event_send_key_number(dcl->con, CNTRL_CODE, false);
qemu_input_event_send_key_delay(0);
}
if (keycode & SHIFT) {
- qemu_input_event_send_key_number(NULL, SHIFT_CODE, false);
+ qemu_input_event_send_key_number(dcl->con, SHIFT_CODE, false);
qemu_input_event_send_key_delay(0);
}
} else {
if (keysym == -1)
keysym = chr;
- kbd_put_keysym(keysym);
+ qemu_text_console_put_keysym(QEMU_TEXT_CONSOLE(dcl->con), keysym);
}
}
}
static void curses_atexit(void)
{
endwin();
+ g_free(vga_to_curses);
+ g_free(screen);
}
/*
memset(&ps, 0, sizeof(ps));
ret = wcrtomb(mbch, wch, &ps);
if (ret == -1) {
- fprintf(stderr, "Could not convert 0x%04x "
+ fprintf(stderr, "Could not convert 0x%04lx "
"from wchar_t to a multibyte character: %s\n",
- wch, strerror(errno));
+ (unsigned long)wch, strerror(errno));
return 0xFFFD;
}
such = sizeof(uch);
if (iconv(conv, &pmbch, &smbch, &puch, &such) == (size_t) -1) {
- fprintf(stderr, "Could not convert 0x%04x "
+ fprintf(stderr, "Could not convert 0x%04lx "
"from a multibyte character to UCS-2 : %s\n",
- wch, strerror(errno));
+ (unsigned long)wch, strerror(errno));
return 0xFFFD;
}
iconv_t nativecharset_to_ucs2;
iconv_t font_conv;
int i;
+ g_autofree gchar *local_codeset = g_get_codeset();
/*
* Control characters are normally non-printable, but VGA does have
* well-known glyphs for them.
*/
- static uint16_t control_characters[0x20] = {
+ static const uint16_t control_characters[0x20] = {
0x0020,
0x263a,
0x263b,
0x25bc
};
- ucs2_to_nativecharset = iconv_open(nl_langinfo(CODESET), "UCS-2");
+ ucs2_to_nativecharset = iconv_open(local_codeset, "UCS-2");
if (ucs2_to_nativecharset == (iconv_t) -1) {
fprintf(stderr, "Could not convert font glyphs from UCS-2: '%s'\n",
strerror(errno));
exit(1);
}
- nativecharset_to_ucs2 = iconv_open("UCS-2", nl_langinfo(CODESET));
+ nativecharset_to_ucs2 = iconv_open("UCS-2", local_codeset);
if (nativecharset_to_ucs2 == (iconv_t) -1) {
iconv_close(ucs2_to_nativecharset);
fprintf(stderr, "Could not convert font glyphs to UCS-2: '%s'\n",
exit(1);
}
- font_conv = iconv_open(nl_langinfo(CODESET), font_charset);
+ font_conv = iconv_open(local_codeset, font_charset);
if (font_conv == (iconv_t) -1) {
iconv_close(ucs2_to_nativecharset);
iconv_close(nativecharset_to_ucs2);
/* DEL */
convert_ucs(0x7F, 0x2302, ucs2_to_nativecharset);
- if (strcmp(nl_langinfo(CODESET), "UTF-8")) {
+ if (strcmp(local_codeset, "UTF-8")) {
/* Non-Unicode capable, use termcap equivalents for those available */
for (i = 0; i <= 0xFF; i++) {
wchar_t wch[CCHARW_MAX];
if (opts->u.curses.charset) {
font_charset = opts->u.curses.charset;
}
+ screen = g_new0(console_ch_t, 160 * 100);
+ vga_to_curses = g_new0(cchar_t, 256);
curses_setup();
curses_keyboard_setup();
atexit(curses_atexit);
curses_winch_init();
dcl = g_new0(DisplayChangeListener, 1);
+ dcl->con = qemu_console_lookup_default();
dcl->ops = &dcl_ops;
register_displaychangelistener(dcl);