18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * QEMU curses/ncurses display driver
3c005246ed03de874fdc432073ba8e5e8ebfed922David 'Digit' Turner *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2005 Andrzej Zaborowski  <balrog@zabor.org>
5c005246ed03de874fdc432073ba8e5e8ebfed922David 'Digit' Turner *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions:
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE.
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <curses.h>
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef _WIN32
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <signal.h>
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/ioctl.h>
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <termios.h>
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __OpenBSD__
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define resize_term resizeterm
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h"
371c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "ui/console.h"
3834c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/sysemu.h"
395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define FONT_HEIGHT 16
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define FONT_WIDTH 8
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic console_ch_t screen[160 * 100];
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic WINDOW *screenpad = NULL;
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int width, height, gwidth, gheight, invalidate;
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int px, py, sminx, sminy, smaxx, smaxy;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void curses_update(DisplayState *ds, int x, int y, int w, int h)
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    chtype *line;
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    line = ((chtype *) screen) + y * width;
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (h += y; y < h; y ++, line += width)
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mvwaddchnstr(screenpad, y, 0, line, width);
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pnoutrefresh(screenpad, py, px, sminy, sminx, smaxy - 1, smaxx - 1);
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    refresh();
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void curses_calc_pad(void)
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (is_fixedsize_console()) {
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        width = gwidth;
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        height = gheight;
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        width = COLS;
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        height = LINES;
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (screenpad)
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        delwin(screenpad);
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    clear();
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    refresh();
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    screenpad = newpad(height, width);
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (width > COLS) {
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        px = (width - COLS) / 2;
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sminx = 0;
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        smaxx = COLS;
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        px = 0;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sminx = (COLS - width) / 2;
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        smaxx = sminx + width;
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (height > LINES) {
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        py = (height - LINES) / 2;
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sminy = 0;
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        smaxy = LINES;
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        py = 0;
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sminy = (LINES - height) / 2;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        smaxy = sminy + height;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void curses_resize(DisplayState *ds)
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ds_get_width(ds) == gwidth && ds_get_height(ds) == gheight)
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    gwidth = ds_get_width(ds);
1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    gheight = ds_get_height(ds);
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    curses_calc_pad();
1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ds->surface->width = width * FONT_WIDTH;
1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ds->surface->height = height * FONT_HEIGHT;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef _WIN32
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(SIGWINCH) && defined(KEY_RESIZE)
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void curses_winch_handler(int signum)
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct winsize {
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unsigned short ws_row;
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unsigned short ws_col;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unsigned short ws_xpixel;   /* unused */
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unsigned short ws_ypixel;   /* unused */
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } ws;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* terminal size changed */
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ioctl(1, TIOCGWINSZ, &ws) == -1)
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    resize_term(ws.ws_row, ws.ws_col);
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    curses_calc_pad();
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    invalidate = 1;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* some systems require this */
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    signal(SIGWINCH, curses_winch_handler);
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void curses_cursor_position(DisplayState *ds, int x, int y)
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (x >= 0) {
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        x = sminx + x - px;
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        y = sminy + y - py;
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (x >= 0 && y >= 0 && x < COLS && y < LINES) {
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            move(y, x);
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            curs_set(1);
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* it seems that curs_set(1) must always be called before
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             * curs_set(2) for the latter to have effect */
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!is_graphic_console())
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                curs_set(2);
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    curs_set(0);
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* generic keyboard conversion */
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "curses_keys.h"
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1619251866320b5f8329a043bb56b3a794f78d12849David 'Digit' Turnerstatic kbd_layout_t *kbd_layout = NULL;
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int keycode2keysym[CURSES_KEYS];
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void curses_refresh(DisplayState *ds)
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int chr, nextchr, keysym, keycode;
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (invalidate) {
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        clear();
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        refresh();
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        curses_calc_pad();
1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ds->surface->width = FONT_WIDTH * width;
1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ds->surface->height = FONT_HEIGHT * height;
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        vga_hw_invalidate();
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        invalidate = 0;
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vga_hw_text_update(screen);
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nextchr = ERR;
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (1) {
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* while there are any pending key strokes to process */
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (nextchr == ERR)
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            chr = getch();
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            chr = nextchr;
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nextchr = ERR;
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (chr == ERR)
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef KEY_RESIZE
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* this shouldn't occur when we use a custom SIGWINCH handler */
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (chr == KEY_RESIZE) {
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            clear();
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            refresh();
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            curses_calc_pad();
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            curses_update(ds, 0, 0, width, height);
2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ds->surface->width = FONT_WIDTH * width;
2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ds->surface->height = FONT_HEIGHT * height;
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        keycode = curses2keycode[chr];
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (keycode == -1)
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* alt key */
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (keycode == 1) {
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nextchr = getch();
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (nextchr != ERR) {
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                keycode = curses2keycode[nextchr];
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nextchr = ERR;
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (keycode == -1)
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    continue;
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                keycode |= ALT;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* process keys reserved for qemu */
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (keycode >= QEMU_KEY_CONSOLE0 &&
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        keycode < QEMU_KEY_CONSOLE0 + 9) {
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    erase();
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    wnoutrefresh(stdscr);
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    console_select(keycode - QEMU_KEY_CONSOLE0);
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    invalidate = 1;
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    continue;
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (kbd_layout && !(keycode & GREY)) {
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            keysym = keycode2keysym[keycode & KEY_MASK];
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (keysym == -1)
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                keysym = chr;
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            keycode &= ~KEY_MASK;
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            keycode |= keysym2scancode(kbd_layout, keysym);
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (is_graphic_console()) {
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* since terminals don't know about key press and release
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             * events, we need to emit both for each key received */
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (keycode & SHIFT)
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                kbd_put_keycode(SHIFT_CODE);
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (keycode & CNTRL)
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                kbd_put_keycode(CNTRL_CODE);
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (keycode & ALT)
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                kbd_put_keycode(ALT_CODE);
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (keycode & GREY)
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                kbd_put_keycode(GREY_CODE);
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            kbd_put_keycode(keycode & KEY_MASK);
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (keycode & GREY)
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                kbd_put_keycode(GREY_CODE);
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            kbd_put_keycode((keycode & KEY_MASK) | KEY_RELEASE);
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (keycode & ALT)
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                kbd_put_keycode(ALT_CODE | KEY_RELEASE);
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (keycode & CNTRL)
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                kbd_put_keycode(CNTRL_CODE | KEY_RELEASE);
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (keycode & SHIFT)
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                kbd_put_keycode(SHIFT_CODE | KEY_RELEASE);
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            keysym = curses2keysym[chr];
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (keysym == -1)
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                keysym = chr;
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            kbd_put_keysym(keysym);
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
275c005246ed03de874fdc432073ba8e5e8ebfed922David 'Digit' Turnerstatic void curses_cleanup(void *opaque)
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    endwin();
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void curses_atexit(void)
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    curses_cleanup(NULL);
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void curses_setup(void)
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i, colour_default[8] = {
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN,
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE,
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    };
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* input as raw as possible, let everything be interpreted
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * by the guest system */
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    initscr(); noecho(); intrflush(stdscr, FALSE);
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nodelay(stdscr, TRUE); nonl(); keypad(stdscr, TRUE);
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    start_color(); raw(); scrollok(stdscr, FALSE);
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; i < 64; i ++)
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        init_pair(i, colour_default[i & 7], colour_default[i >> 3]);
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void curses_keyboard_setup(void)
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i, keycode, keysym;
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(__APPLE__)
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* always use generic keymaps */
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!keyboard_layout)
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        keyboard_layout = "en-us";
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if(keyboard_layout) {
3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!kbd_layout)
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            exit(1);
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; i < CURSES_KEYS; i ++)
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        keycode2keysym[i] = -1;
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; i < CURSES_KEYS; i ++) {
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (curses2keycode[i] == -1)
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        keycode = curses2keycode[i] & KEY_MASK;
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (keycode2keysym[keycode] >= 0)
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (keysym = 0; keysym < CURSES_KEYS; keysym ++)
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (curses2keycode[keysym] == keycode) {
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                keycode2keysym[keycode] = keysym;
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (keysym >= CURSES_KEYS)
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            keycode2keysym[keycode] = i;
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid curses_display_init(DisplayState *ds, int full_screen)
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DisplayChangeListener *dcl;
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef _WIN32
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!isatty(1)) {
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fprintf(stderr, "We need a terminal output\n");
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        exit(1);
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    curses_setup();
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    curses_keyboard_setup();
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    atexit(curses_atexit);
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef _WIN32
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(SIGWINCH) && defined(KEY_RESIZE)
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* some curses implementations provide a handler, but we
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * want to be sure this is handled regardless of the library */
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    signal(SIGWINCH, curses_winch_handler);
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
361aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    dcl = (DisplayChangeListener *) g_malloc0(sizeof(DisplayChangeListener));
3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    dcl->dpy_update = curses_update;
3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    dcl->dpy_resize = curses_resize;
3645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    dcl->dpy_refresh = curses_refresh;
3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    dcl->dpy_text_cursor = curses_cursor_position;
3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    register_displaychangelistener(ds, dcl);
3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free_displaysurface(ds);
3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ds->surface = qemu_create_displaysurface_from(640, 400, 0, 0, (uint8_t*) screen);
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    invalidate = 1;
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
372