Statistics
| Branch: | Revision:

root / ui / console.c @ dccfcd0e

History | View | Annotate | Download (50.9 kB)

1 e7f0ad58 bellard
/*
2 e7f0ad58 bellard
 * QEMU graphical console
3 5fafdf24 ths
 *
4 e7f0ad58 bellard
 * Copyright (c) 2004 Fabrice Bellard
5 5fafdf24 ths
 *
6 e7f0ad58 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 e7f0ad58 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 e7f0ad58 bellard
 * in the Software without restriction, including without limitation the rights
9 e7f0ad58 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 e7f0ad58 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 e7f0ad58 bellard
 * furnished to do so, subject to the following conditions:
12 e7f0ad58 bellard
 *
13 e7f0ad58 bellard
 * The above copyright notice and this permission notice shall be included in
14 e7f0ad58 bellard
 * all copies or substantial portions of the Software.
15 e7f0ad58 bellard
 *
16 e7f0ad58 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 e7f0ad58 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 e7f0ad58 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 e7f0ad58 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 e7f0ad58 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 e7f0ad58 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 e7f0ad58 bellard
 * THE SOFTWARE.
23 e7f0ad58 bellard
 */
24 87ecb68b pbrook
#include "qemu-common.h"
25 28ecbaee Paolo Bonzini
#include "ui/console.h"
26 1de7afc9 Paolo Bonzini
#include "qemu/timer.h"
27 ad39cf6d Luiz Capitulino
#include "qmp-commands.h"
28 dccfcd0e Paolo Bonzini
#include "sysemu/char.h"
29 e7f0ad58 bellard
30 6d6f7c28 pbrook
//#define DEBUG_CONSOLE
31 e7f0ad58 bellard
#define DEFAULT_BACKSCROLL 512
32 e7f0ad58 bellard
#define MAX_CONSOLES 12
33 bf1bed81 Jan Kiszka
#define CONSOLE_CURSOR_PERIOD 500
34 e7f0ad58 bellard
35 26489844 bellard
#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
36 26489844 bellard
#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff)
37 e7f0ad58 bellard
38 6d6f7c28 pbrook
typedef struct TextAttributes {
39 6d6f7c28 pbrook
    uint8_t fgcol:4;
40 6d6f7c28 pbrook
    uint8_t bgcol:4;
41 6d6f7c28 pbrook
    uint8_t bold:1;
42 6d6f7c28 pbrook
    uint8_t uline:1;
43 6d6f7c28 pbrook
    uint8_t blink:1;
44 6d6f7c28 pbrook
    uint8_t invers:1;
45 6d6f7c28 pbrook
    uint8_t unvisible:1;
46 6d6f7c28 pbrook
} TextAttributes;
47 6d6f7c28 pbrook
48 e7f0ad58 bellard
typedef struct TextCell {
49 e7f0ad58 bellard
    uint8_t ch;
50 6d6f7c28 pbrook
    TextAttributes t_attrib;
51 e7f0ad58 bellard
} TextCell;
52 e7f0ad58 bellard
53 e7f0ad58 bellard
#define MAX_ESC_PARAMS 3
54 e7f0ad58 bellard
55 e7f0ad58 bellard
enum TTYState {
56 e7f0ad58 bellard
    TTY_STATE_NORM,
57 e7f0ad58 bellard
    TTY_STATE_ESC,
58 e7f0ad58 bellard
    TTY_STATE_CSI,
59 e7f0ad58 bellard
};
60 e7f0ad58 bellard
61 e15d7371 bellard
typedef struct QEMUFIFO {
62 e15d7371 bellard
    uint8_t *buf;
63 e15d7371 bellard
    int buf_size;
64 e15d7371 bellard
    int count, wptr, rptr;
65 e15d7371 bellard
} QEMUFIFO;
66 e15d7371 bellard
67 9596ebb7 pbrook
static int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
68 e15d7371 bellard
{
69 e15d7371 bellard
    int l, len;
70 e15d7371 bellard
71 e15d7371 bellard
    l = f->buf_size - f->count;
72 e15d7371 bellard
    if (len1 > l)
73 e15d7371 bellard
        len1 = l;
74 e15d7371 bellard
    len = len1;
75 e15d7371 bellard
    while (len > 0) {
76 e15d7371 bellard
        l = f->buf_size - f->wptr;
77 e15d7371 bellard
        if (l > len)
78 e15d7371 bellard
            l = len;
79 e15d7371 bellard
        memcpy(f->buf + f->wptr, buf, l);
80 e15d7371 bellard
        f->wptr += l;
81 e15d7371 bellard
        if (f->wptr >= f->buf_size)
82 e15d7371 bellard
            f->wptr = 0;
83 e15d7371 bellard
        buf += l;
84 e15d7371 bellard
        len -= l;
85 e15d7371 bellard
    }
86 e15d7371 bellard
    f->count += len1;
87 e15d7371 bellard
    return len1;
88 e15d7371 bellard
}
89 e15d7371 bellard
90 9596ebb7 pbrook
static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
91 e15d7371 bellard
{
92 e15d7371 bellard
    int l, len;
93 e15d7371 bellard
94 e15d7371 bellard
    if (len1 > f->count)
95 e15d7371 bellard
        len1 = f->count;
96 e15d7371 bellard
    len = len1;
97 e15d7371 bellard
    while (len > 0) {
98 e15d7371 bellard
        l = f->buf_size - f->rptr;
99 e15d7371 bellard
        if (l > len)
100 e15d7371 bellard
            l = len;
101 e15d7371 bellard
        memcpy(buf, f->buf + f->rptr, l);
102 e15d7371 bellard
        f->rptr += l;
103 e15d7371 bellard
        if (f->rptr >= f->buf_size)
104 e15d7371 bellard
            f->rptr = 0;
105 e15d7371 bellard
        buf += l;
106 e15d7371 bellard
        len -= l;
107 e15d7371 bellard
    }
108 e15d7371 bellard
    f->count -= len1;
109 e15d7371 bellard
    return len1;
110 e15d7371 bellard
}
111 e15d7371 bellard
112 af3a9031 ths
typedef enum {
113 af3a9031 ths
    GRAPHIC_CONSOLE,
114 c21bbcfa balrog
    TEXT_CONSOLE,
115 c21bbcfa balrog
    TEXT_CONSOLE_FIXED_SIZE
116 c227f099 Anthony Liguori
} console_type_t;
117 af3a9031 ths
118 76ffb0b4 Gerd Hoffmann
struct QemuConsole {
119 f81bdefb Jan Kiszka
    int index;
120 c227f099 Anthony Liguori
    console_type_t console_type;
121 e7f0ad58 bellard
    DisplayState *ds;
122 76ffb0b4 Gerd Hoffmann
123 95219897 pbrook
    /* Graphic console state.  */
124 95219897 pbrook
    vga_hw_update_ptr hw_update;
125 95219897 pbrook
    vga_hw_invalidate_ptr hw_invalidate;
126 95219897 pbrook
    vga_hw_screen_dump_ptr hw_screen_dump;
127 4d3b6f6e balrog
    vga_hw_text_update_ptr hw_text_update;
128 95219897 pbrook
    void *hw;
129 e7f0ad58 bellard
    int g_width, g_height;
130 76ffb0b4 Gerd Hoffmann
131 76ffb0b4 Gerd Hoffmann
    /* Text console state */
132 e7f0ad58 bellard
    int width;
133 e7f0ad58 bellard
    int height;
134 e7f0ad58 bellard
    int total_height;
135 e7f0ad58 bellard
    int backscroll_height;
136 e7f0ad58 bellard
    int x, y;
137 adb47967 ths
    int x_saved, y_saved;
138 e7f0ad58 bellard
    int y_displayed;
139 e7f0ad58 bellard
    int y_base;
140 6d6f7c28 pbrook
    TextAttributes t_attrib_default; /* default text attributes */
141 6d6f7c28 pbrook
    TextAttributes t_attrib; /* currently active text attributes */
142 e7f0ad58 bellard
    TextCell *cells;
143 4d3b6f6e balrog
    int text_x[2], text_y[2], cursor_invalidate;
144 4104833f Paolo Bonzini
    int echo;
145 bf1bed81 Jan Kiszka
    bool cursor_visible_phase;
146 bf1bed81 Jan Kiszka
    QEMUTimer *cursor_timer;
147 e7f0ad58 bellard
148 14778c20 pbrook
    int update_x0;
149 14778c20 pbrook
    int update_y0;
150 14778c20 pbrook
    int update_x1;
151 14778c20 pbrook
    int update_y1;
152 14778c20 pbrook
153 e7f0ad58 bellard
    enum TTYState state;
154 e7f0ad58 bellard
    int esc_params[MAX_ESC_PARAMS];
155 e7f0ad58 bellard
    int nb_esc_params;
156 e7f0ad58 bellard
157 e5b0bc44 pbrook
    CharDriverState *chr;
158 e15d7371 bellard
    /* fifo for key pressed */
159 e15d7371 bellard
    QEMUFIFO out_fifo;
160 e15d7371 bellard
    uint8_t out_fifo_buf[16];
161 e15d7371 bellard
    QEMUTimer *kbd_timer;
162 e7f0ad58 bellard
};
163 e7f0ad58 bellard
164 98b50080 Paolo Bonzini
static DisplayState *display_state;
165 76ffb0b4 Gerd Hoffmann
static QemuConsole *active_console;
166 76ffb0b4 Gerd Hoffmann
static QemuConsole *consoles[MAX_CONSOLES];
167 e7f0ad58 bellard
static int nb_consoles = 0;
168 e7f0ad58 bellard
169 95219897 pbrook
void vga_hw_update(void)
170 95219897 pbrook
{
171 adb47967 ths
    if (active_console && active_console->hw_update)
172 95219897 pbrook
        active_console->hw_update(active_console->hw);
173 95219897 pbrook
}
174 95219897 pbrook
175 95219897 pbrook
void vga_hw_invalidate(void)
176 95219897 pbrook
{
177 26572b8a Gerd Hoffmann
    if (active_console && active_console->hw_invalidate)
178 95219897 pbrook
        active_console->hw_invalidate(active_console->hw);
179 95219897 pbrook
}
180 95219897 pbrook
181 ad39cf6d Luiz Capitulino
void qmp_screendump(const char *filename, Error **errp)
182 95219897 pbrook
{
183 76ffb0b4 Gerd Hoffmann
    QemuConsole *previous_active_console;
184 45efb161 Gerd Hoffmann
    bool cswitch;
185 8571c055 balrog
186 8571c055 balrog
    previous_active_console = active_console;
187 45efb161 Gerd Hoffmann
    cswitch = previous_active_console && previous_active_console->index != 0;
188 f81bdefb Jan Kiszka
189 8571c055 balrog
    /* There is currently no way of specifying which screen we want to dump,
190 7b455225 aurel32
       so always dump the first one.  */
191 45efb161 Gerd Hoffmann
    if (cswitch) {
192 45efb161 Gerd Hoffmann
        console_select(0);
193 45efb161 Gerd Hoffmann
    }
194 f81bdefb Jan Kiszka
    if (consoles[0] && consoles[0]->hw_screen_dump) {
195 ad39cf6d Luiz Capitulino
        consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch, errp);
196 16735102 Gerd Hoffmann
    } else {
197 312fd5f2 Markus Armbruster
        error_setg(errp, "device doesn't support screendump");
198 f81bdefb Jan Kiszka
    }
199 f81bdefb Jan Kiszka
200 45efb161 Gerd Hoffmann
    if (cswitch) {
201 33bcd98c Alexander Graf
        console_select(previous_active_console->index);
202 33bcd98c Alexander Graf
    }
203 95219897 pbrook
}
204 95219897 pbrook
205 c227f099 Anthony Liguori
void vga_hw_text_update(console_ch_t *chardata)
206 4d3b6f6e balrog
{
207 4d3b6f6e balrog
    if (active_console && active_console->hw_text_update)
208 4d3b6f6e balrog
        active_console->hw_text_update(active_console->hw, chardata);
209 4d3b6f6e balrog
}
210 4d3b6f6e balrog
211 1562e531 Gerd Hoffmann
static void vga_fill_rect(QemuConsole *con,
212 1562e531 Gerd Hoffmann
                          int posx, int posy, int width, int height,
213 1562e531 Gerd Hoffmann
                          uint32_t color)
214 e7f0ad58 bellard
{
215 1562e531 Gerd Hoffmann
    DisplaySurface *surface = qemu_console_surface(con);
216 e7f0ad58 bellard
    uint8_t *d, *d1;
217 e7f0ad58 bellard
    int x, y, bpp;
218 3b46e624 ths
219 1562e531 Gerd Hoffmann
    bpp = surface_bytes_per_pixel(surface);
220 1562e531 Gerd Hoffmann
    d1 = surface_data(surface) +
221 1562e531 Gerd Hoffmann
        surface_stride(surface) * posy + bpp * posx;
222 e7f0ad58 bellard
    for (y = 0; y < height; y++) {
223 e7f0ad58 bellard
        d = d1;
224 e7f0ad58 bellard
        switch(bpp) {
225 e7f0ad58 bellard
        case 1:
226 e7f0ad58 bellard
            for (x = 0; x < width; x++) {
227 e7f0ad58 bellard
                *((uint8_t *)d) = color;
228 e7f0ad58 bellard
                d++;
229 e7f0ad58 bellard
            }
230 e7f0ad58 bellard
            break;
231 e7f0ad58 bellard
        case 2:
232 e7f0ad58 bellard
            for (x = 0; x < width; x++) {
233 e7f0ad58 bellard
                *((uint16_t *)d) = color;
234 e7f0ad58 bellard
                d += 2;
235 e7f0ad58 bellard
            }
236 e7f0ad58 bellard
            break;
237 e7f0ad58 bellard
        case 4:
238 e7f0ad58 bellard
            for (x = 0; x < width; x++) {
239 e7f0ad58 bellard
                *((uint32_t *)d) = color;
240 e7f0ad58 bellard
                d += 4;
241 e7f0ad58 bellard
            }
242 e7f0ad58 bellard
            break;
243 e7f0ad58 bellard
        }
244 1562e531 Gerd Hoffmann
        d1 += surface_stride(surface);
245 e7f0ad58 bellard
    }
246 e7f0ad58 bellard
}
247 e7f0ad58 bellard
248 e7f0ad58 bellard
/* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
249 1562e531 Gerd Hoffmann
static void vga_bitblt(QemuConsole *con,
250 1562e531 Gerd Hoffmann
                       int xs, int ys, int xd, int yd, int w, int h)
251 e7f0ad58 bellard
{
252 1562e531 Gerd Hoffmann
    DisplaySurface *surface = qemu_console_surface(con);
253 e7f0ad58 bellard
    const uint8_t *s;
254 e7f0ad58 bellard
    uint8_t *d;
255 e7f0ad58 bellard
    int wb, y, bpp;
256 e7f0ad58 bellard
257 1562e531 Gerd Hoffmann
    bpp = surface_bytes_per_pixel(surface);
258 e7f0ad58 bellard
    wb = w * bpp;
259 e7f0ad58 bellard
    if (yd <= ys) {
260 1562e531 Gerd Hoffmann
        s = surface_data(surface) +
261 1562e531 Gerd Hoffmann
            surface_stride(surface) * ys + bpp * xs;
262 1562e531 Gerd Hoffmann
        d = surface_data(surface) +
263 1562e531 Gerd Hoffmann
            surface_stride(surface) * yd + bpp * xd;
264 e7f0ad58 bellard
        for (y = 0; y < h; y++) {
265 e7f0ad58 bellard
            memmove(d, s, wb);
266 1562e531 Gerd Hoffmann
            d += surface_stride(surface);
267 1562e531 Gerd Hoffmann
            s += surface_stride(surface);
268 e7f0ad58 bellard
        }
269 e7f0ad58 bellard
    } else {
270 1562e531 Gerd Hoffmann
        s = surface_data(surface) +
271 1562e531 Gerd Hoffmann
            surface_stride(surface) * (ys + h - 1) + bpp * xs;
272 1562e531 Gerd Hoffmann
        d = surface_data(surface) +
273 1562e531 Gerd Hoffmann
            surface_stride(surface) * (yd + h - 1) + bpp * xd;
274 e7f0ad58 bellard
       for (y = 0; y < h; y++) {
275 e7f0ad58 bellard
            memmove(d, s, wb);
276 1562e531 Gerd Hoffmann
            d -= surface_stride(surface);
277 1562e531 Gerd Hoffmann
            s -= surface_stride(surface);
278 e7f0ad58 bellard
        }
279 e7f0ad58 bellard
    }
280 e7f0ad58 bellard
}
281 e7f0ad58 bellard
282 e7f0ad58 bellard
/***********************************************************/
283 e7f0ad58 bellard
/* basic char display */
284 e7f0ad58 bellard
285 e7f0ad58 bellard
#define FONT_HEIGHT 16
286 e7f0ad58 bellard
#define FONT_WIDTH 8
287 e7f0ad58 bellard
288 e7f0ad58 bellard
#include "vgafont.h"
289 e7f0ad58 bellard
290 e7f0ad58 bellard
#define cbswap_32(__x) \
291 e7f0ad58 bellard
((uint32_t)( \
292 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
293 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
294 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
295 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
296 e7f0ad58 bellard
297 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
298 e7f0ad58 bellard
#define PAT(x) x
299 e7f0ad58 bellard
#else
300 e7f0ad58 bellard
#define PAT(x) cbswap_32(x)
301 e7f0ad58 bellard
#endif
302 e7f0ad58 bellard
303 e7f0ad58 bellard
static const uint32_t dmask16[16] = {
304 e7f0ad58 bellard
    PAT(0x00000000),
305 e7f0ad58 bellard
    PAT(0x000000ff),
306 e7f0ad58 bellard
    PAT(0x0000ff00),
307 e7f0ad58 bellard
    PAT(0x0000ffff),
308 e7f0ad58 bellard
    PAT(0x00ff0000),
309 e7f0ad58 bellard
    PAT(0x00ff00ff),
310 e7f0ad58 bellard
    PAT(0x00ffff00),
311 e7f0ad58 bellard
    PAT(0x00ffffff),
312 e7f0ad58 bellard
    PAT(0xff000000),
313 e7f0ad58 bellard
    PAT(0xff0000ff),
314 e7f0ad58 bellard
    PAT(0xff00ff00),
315 e7f0ad58 bellard
    PAT(0xff00ffff),
316 e7f0ad58 bellard
    PAT(0xffff0000),
317 e7f0ad58 bellard
    PAT(0xffff00ff),
318 e7f0ad58 bellard
    PAT(0xffffff00),
319 e7f0ad58 bellard
    PAT(0xffffffff),
320 e7f0ad58 bellard
};
321 e7f0ad58 bellard
322 e7f0ad58 bellard
static const uint32_t dmask4[4] = {
323 e7f0ad58 bellard
    PAT(0x00000000),
324 e7f0ad58 bellard
    PAT(0x0000ffff),
325 e7f0ad58 bellard
    PAT(0xffff0000),
326 e7f0ad58 bellard
    PAT(0xffffffff),
327 e7f0ad58 bellard
};
328 e7f0ad58 bellard
329 df00bed0 Devin J. Pohly
#ifndef CONFIG_CURSES
330 6d6f7c28 pbrook
enum color_names {
331 6d6f7c28 pbrook
    COLOR_BLACK   = 0,
332 6d6f7c28 pbrook
    COLOR_RED     = 1,
333 6d6f7c28 pbrook
    COLOR_GREEN   = 2,
334 6d6f7c28 pbrook
    COLOR_YELLOW  = 3,
335 6d6f7c28 pbrook
    COLOR_BLUE    = 4,
336 6d6f7c28 pbrook
    COLOR_MAGENTA = 5,
337 6d6f7c28 pbrook
    COLOR_CYAN    = 6,
338 6d6f7c28 pbrook
    COLOR_WHITE   = 7
339 6d6f7c28 pbrook
};
340 df00bed0 Devin J. Pohly
#endif
341 6d6f7c28 pbrook
342 6d6f7c28 pbrook
static const uint32_t color_table_rgb[2][8] = {
343 6d6f7c28 pbrook
    {   /* dark */
344 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0x00),  /* black */
345 26489844 bellard
        QEMU_RGB(0xaa, 0x00, 0x00),  /* red */
346 26489844 bellard
        QEMU_RGB(0x00, 0xaa, 0x00),  /* green */
347 26489844 bellard
        QEMU_RGB(0xaa, 0xaa, 0x00),  /* yellow */
348 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0xaa),  /* blue */
349 26489844 bellard
        QEMU_RGB(0xaa, 0x00, 0xaa),  /* magenta */
350 26489844 bellard
        QEMU_RGB(0x00, 0xaa, 0xaa),  /* cyan */
351 26489844 bellard
        QEMU_RGB(0xaa, 0xaa, 0xaa),  /* white */
352 6d6f7c28 pbrook
    },
353 6d6f7c28 pbrook
    {   /* bright */
354 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0x00),  /* black */
355 26489844 bellard
        QEMU_RGB(0xff, 0x00, 0x00),  /* red */
356 26489844 bellard
        QEMU_RGB(0x00, 0xff, 0x00),  /* green */
357 26489844 bellard
        QEMU_RGB(0xff, 0xff, 0x00),  /* yellow */
358 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0xff),  /* blue */
359 26489844 bellard
        QEMU_RGB(0xff, 0x00, 0xff),  /* magenta */
360 26489844 bellard
        QEMU_RGB(0x00, 0xff, 0xff),  /* cyan */
361 26489844 bellard
        QEMU_RGB(0xff, 0xff, 0xff),  /* white */
362 6d6f7c28 pbrook
    }
363 e7f0ad58 bellard
};
364 e7f0ad58 bellard
365 6d6f7c28 pbrook
#ifdef DEBUG_CONSOLE
366 6d6f7c28 pbrook
static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
367 6d6f7c28 pbrook
{
368 6d6f7c28 pbrook
    if (t_attrib->bold) {
369 6d6f7c28 pbrook
        printf("b");
370 6d6f7c28 pbrook
    } else {
371 6d6f7c28 pbrook
        printf(" ");
372 6d6f7c28 pbrook
    }
373 6d6f7c28 pbrook
    if (t_attrib->uline) {
374 6d6f7c28 pbrook
        printf("u");
375 6d6f7c28 pbrook
    } else {
376 6d6f7c28 pbrook
        printf(" ");
377 6d6f7c28 pbrook
    }
378 6d6f7c28 pbrook
    if (t_attrib->blink) {
379 6d6f7c28 pbrook
        printf("l");
380 6d6f7c28 pbrook
    } else {
381 6d6f7c28 pbrook
        printf(" ");
382 6d6f7c28 pbrook
    }
383 6d6f7c28 pbrook
    if (t_attrib->invers) {
384 6d6f7c28 pbrook
        printf("i");
385 6d6f7c28 pbrook
    } else {
386 6d6f7c28 pbrook
        printf(" ");
387 6d6f7c28 pbrook
    }
388 6d6f7c28 pbrook
    if (t_attrib->unvisible) {
389 6d6f7c28 pbrook
        printf("n");
390 6d6f7c28 pbrook
    } else {
391 6d6f7c28 pbrook
        printf(" ");
392 6d6f7c28 pbrook
    }
393 6d6f7c28 pbrook
394 6d6f7c28 pbrook
    printf(" fg: %d bg: %d ch:'%2X' '%c'\n", t_attrib->fgcol, t_attrib->bgcol, ch, ch);
395 6d6f7c28 pbrook
}
396 6d6f7c28 pbrook
#endif
397 e7f0ad58 bellard
398 1562e531 Gerd Hoffmann
static void vga_putcharxy(QemuConsole *s, int x, int y, int ch,
399 6d6f7c28 pbrook
                          TextAttributes *t_attrib)
400 e7f0ad58 bellard
{
401 1562e531 Gerd Hoffmann
    DisplaySurface *surface = qemu_console_surface(s);
402 e7f0ad58 bellard
    uint8_t *d;
403 e7f0ad58 bellard
    const uint8_t *font_ptr;
404 e7f0ad58 bellard
    unsigned int font_data, linesize, xorcol, bpp;
405 e7f0ad58 bellard
    int i;
406 6d6f7c28 pbrook
    unsigned int fgcol, bgcol;
407 6d6f7c28 pbrook
408 6d6f7c28 pbrook
#ifdef DEBUG_CONSOLE
409 6d6f7c28 pbrook
    printf("x: %2i y: %2i", x, y);
410 6d6f7c28 pbrook
    console_print_text_attributes(t_attrib, ch);
411 6d6f7c28 pbrook
#endif
412 6d6f7c28 pbrook
413 6d6f7c28 pbrook
    if (t_attrib->invers) {
414 cf6f0548 Gerd Hoffmann
        bgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
415 cf6f0548 Gerd Hoffmann
        fgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol];
416 6d6f7c28 pbrook
    } else {
417 cf6f0548 Gerd Hoffmann
        fgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
418 cf6f0548 Gerd Hoffmann
        bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol];
419 6d6f7c28 pbrook
    }
420 e7f0ad58 bellard
421 1562e531 Gerd Hoffmann
    bpp = surface_bytes_per_pixel(surface);
422 1562e531 Gerd Hoffmann
    d = surface_data(surface) +
423 1562e531 Gerd Hoffmann
        surface_stride(surface) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
424 1562e531 Gerd Hoffmann
    linesize = surface_stride(surface);
425 e7f0ad58 bellard
    font_ptr = vgafont16 + FONT_HEIGHT * ch;
426 e7f0ad58 bellard
    xorcol = bgcol ^ fgcol;
427 1562e531 Gerd Hoffmann
    switch (surface_bits_per_pixel(surface)) {
428 e7f0ad58 bellard
    case 8:
429 e7f0ad58 bellard
        for(i = 0; i < FONT_HEIGHT; i++) {
430 e7f0ad58 bellard
            font_data = *font_ptr++;
431 6d6f7c28 pbrook
            if (t_attrib->uline
432 6d6f7c28 pbrook
                && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
433 439229c7 Markus Armbruster
                font_data = 0xFF;
434 6d6f7c28 pbrook
            }
435 e7f0ad58 bellard
            ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
436 e7f0ad58 bellard
            ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
437 e7f0ad58 bellard
            d += linesize;
438 e7f0ad58 bellard
        }
439 e7f0ad58 bellard
        break;
440 e7f0ad58 bellard
    case 16:
441 e7f0ad58 bellard
    case 15:
442 e7f0ad58 bellard
        for(i = 0; i < FONT_HEIGHT; i++) {
443 e7f0ad58 bellard
            font_data = *font_ptr++;
444 6d6f7c28 pbrook
            if (t_attrib->uline
445 6d6f7c28 pbrook
                && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
446 439229c7 Markus Armbruster
                font_data = 0xFF;
447 6d6f7c28 pbrook
            }
448 e7f0ad58 bellard
            ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
449 e7f0ad58 bellard
            ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
450 e7f0ad58 bellard
            ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
451 e7f0ad58 bellard
            ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
452 e7f0ad58 bellard
            d += linesize;
453 e7f0ad58 bellard
        }
454 e7f0ad58 bellard
        break;
455 e7f0ad58 bellard
    case 32:
456 e7f0ad58 bellard
        for(i = 0; i < FONT_HEIGHT; i++) {
457 e7f0ad58 bellard
            font_data = *font_ptr++;
458 6d6f7c28 pbrook
            if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
459 439229c7 Markus Armbruster
                font_data = 0xFF;
460 6d6f7c28 pbrook
            }
461 e7f0ad58 bellard
            ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
462 e7f0ad58 bellard
            ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
463 e7f0ad58 bellard
            ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
464 e7f0ad58 bellard
            ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
465 e7f0ad58 bellard
            ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
466 e7f0ad58 bellard
            ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
467 e7f0ad58 bellard
            ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
468 e7f0ad58 bellard
            ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
469 e7f0ad58 bellard
            d += linesize;
470 e7f0ad58 bellard
        }
471 e7f0ad58 bellard
        break;
472 e7f0ad58 bellard
    }
473 e7f0ad58 bellard
}
474 e7f0ad58 bellard
475 76ffb0b4 Gerd Hoffmann
static void text_console_resize(QemuConsole *s)
476 e7f0ad58 bellard
{
477 e7f0ad58 bellard
    TextCell *cells, *c, *c1;
478 e7f0ad58 bellard
    int w1, x, y, last_width;
479 e7f0ad58 bellard
480 e7f0ad58 bellard
    last_width = s->width;
481 e7f0ad58 bellard
    s->width = s->g_width / FONT_WIDTH;
482 e7f0ad58 bellard
    s->height = s->g_height / FONT_HEIGHT;
483 e7f0ad58 bellard
484 e7f0ad58 bellard
    w1 = last_width;
485 e7f0ad58 bellard
    if (s->width < w1)
486 e7f0ad58 bellard
        w1 = s->width;
487 e7f0ad58 bellard
488 7267c094 Anthony Liguori
    cells = g_malloc(s->width * s->total_height * sizeof(TextCell));
489 e7f0ad58 bellard
    for(y = 0; y < s->total_height; y++) {
490 e7f0ad58 bellard
        c = &cells[y * s->width];
491 e7f0ad58 bellard
        if (w1 > 0) {
492 e7f0ad58 bellard
            c1 = &s->cells[y * last_width];
493 e7f0ad58 bellard
            for(x = 0; x < w1; x++) {
494 e7f0ad58 bellard
                *c++ = *c1++;
495 e7f0ad58 bellard
            }
496 e7f0ad58 bellard
        }
497 e7f0ad58 bellard
        for(x = w1; x < s->width; x++) {
498 e7f0ad58 bellard
            c->ch = ' ';
499 6d6f7c28 pbrook
            c->t_attrib = s->t_attrib_default;
500 e7f0ad58 bellard
            c++;
501 e7f0ad58 bellard
        }
502 e7f0ad58 bellard
    }
503 7267c094 Anthony Liguori
    g_free(s->cells);
504 e7f0ad58 bellard
    s->cells = cells;
505 e7f0ad58 bellard
}
506 e7f0ad58 bellard
507 76ffb0b4 Gerd Hoffmann
static inline void text_update_xy(QemuConsole *s, int x, int y)
508 4d3b6f6e balrog
{
509 4d3b6f6e balrog
    s->text_x[0] = MIN(s->text_x[0], x);
510 4d3b6f6e balrog
    s->text_x[1] = MAX(s->text_x[1], x);
511 4d3b6f6e balrog
    s->text_y[0] = MIN(s->text_y[0], y);
512 4d3b6f6e balrog
    s->text_y[1] = MAX(s->text_y[1], y);
513 4d3b6f6e balrog
}
514 4d3b6f6e balrog
515 76ffb0b4 Gerd Hoffmann
static void invalidate_xy(QemuConsole *s, int x, int y)
516 14778c20 pbrook
{
517 14778c20 pbrook
    if (s->update_x0 > x * FONT_WIDTH)
518 14778c20 pbrook
        s->update_x0 = x * FONT_WIDTH;
519 14778c20 pbrook
    if (s->update_y0 > y * FONT_HEIGHT)
520 14778c20 pbrook
        s->update_y0 = y * FONT_HEIGHT;
521 14778c20 pbrook
    if (s->update_x1 < (x + 1) * FONT_WIDTH)
522 14778c20 pbrook
        s->update_x1 = (x + 1) * FONT_WIDTH;
523 14778c20 pbrook
    if (s->update_y1 < (y + 1) * FONT_HEIGHT)
524 14778c20 pbrook
        s->update_y1 = (y + 1) * FONT_HEIGHT;
525 14778c20 pbrook
}
526 14778c20 pbrook
527 76ffb0b4 Gerd Hoffmann
static void update_xy(QemuConsole *s, int x, int y)
528 e7f0ad58 bellard
{
529 e7f0ad58 bellard
    TextCell *c;
530 e7f0ad58 bellard
    int y1, y2;
531 e7f0ad58 bellard
532 1562e531 Gerd Hoffmann
    if (s != active_console) {
533 1562e531 Gerd Hoffmann
        return;
534 1562e531 Gerd Hoffmann
    }
535 1562e531 Gerd Hoffmann
536 1562e531 Gerd Hoffmann
    if (s->ds->have_text) {
537 1562e531 Gerd Hoffmann
        text_update_xy(s, x, y);
538 1562e531 Gerd Hoffmann
    }
539 4d3b6f6e balrog
540 1562e531 Gerd Hoffmann
    if (s->ds->have_gfx) {
541 e7f0ad58 bellard
        y1 = (s->y_base + y) % s->total_height;
542 e7f0ad58 bellard
        y2 = y1 - s->y_displayed;
543 e7f0ad58 bellard
        if (y2 < 0)
544 e7f0ad58 bellard
            y2 += s->total_height;
545 e7f0ad58 bellard
        if (y2 < s->height) {
546 e7f0ad58 bellard
            c = &s->cells[y1 * s->width + x];
547 1562e531 Gerd Hoffmann
            vga_putcharxy(s, x, y2, c->ch,
548 6d6f7c28 pbrook
                          &(c->t_attrib));
549 14778c20 pbrook
            invalidate_xy(s, x, y2);
550 e7f0ad58 bellard
        }
551 e7f0ad58 bellard
    }
552 e7f0ad58 bellard
}
553 e7f0ad58 bellard
554 76ffb0b4 Gerd Hoffmann
static void console_show_cursor(QemuConsole *s, int show)
555 e7f0ad58 bellard
{
556 e7f0ad58 bellard
    TextCell *c;
557 e7f0ad58 bellard
    int y, y1;
558 1562e531 Gerd Hoffmann
    int x = s->x;
559 e7f0ad58 bellard
560 1562e531 Gerd Hoffmann
    if (s != active_console) {
561 1562e531 Gerd Hoffmann
        return;
562 1562e531 Gerd Hoffmann
    }
563 4d3b6f6e balrog
564 1562e531 Gerd Hoffmann
    if (s->ds->have_text) {
565 1562e531 Gerd Hoffmann
        s->cursor_invalidate = 1;
566 1562e531 Gerd Hoffmann
    }
567 4d3b6f6e balrog
568 1562e531 Gerd Hoffmann
    if (s->ds->have_gfx) {
569 ed8276ac ths
        if (x >= s->width) {
570 ed8276ac ths
            x = s->width - 1;
571 ed8276ac ths
        }
572 e7f0ad58 bellard
        y1 = (s->y_base + s->y) % s->total_height;
573 e7f0ad58 bellard
        y = y1 - s->y_displayed;
574 e7f0ad58 bellard
        if (y < 0)
575 e7f0ad58 bellard
            y += s->total_height;
576 e7f0ad58 bellard
        if (y < s->height) {
577 ed8276ac ths
            c = &s->cells[y1 * s->width + x];
578 bf1bed81 Jan Kiszka
            if (show && s->cursor_visible_phase) {
579 6d6f7c28 pbrook
                TextAttributes t_attrib = s->t_attrib_default;
580 6d6f7c28 pbrook
                t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
581 1562e531 Gerd Hoffmann
                vga_putcharxy(s, x, y, c->ch, &t_attrib);
582 e7f0ad58 bellard
            } else {
583 1562e531 Gerd Hoffmann
                vga_putcharxy(s, x, y, c->ch, &(c->t_attrib));
584 e7f0ad58 bellard
            }
585 14778c20 pbrook
            invalidate_xy(s, x, y);
586 e7f0ad58 bellard
        }
587 e7f0ad58 bellard
    }
588 e7f0ad58 bellard
}
589 e7f0ad58 bellard
590 76ffb0b4 Gerd Hoffmann
static void console_refresh(QemuConsole *s)
591 e7f0ad58 bellard
{
592 1562e531 Gerd Hoffmann
    DisplaySurface *surface = qemu_console_surface(s);
593 e7f0ad58 bellard
    TextCell *c;
594 e7f0ad58 bellard
    int x, y, y1;
595 e7f0ad58 bellard
596 5fafdf24 ths
    if (s != active_console)
597 e7f0ad58 bellard
        return;
598 a93a4a22 Gerd Hoffmann
599 a93a4a22 Gerd Hoffmann
    if (s->ds->have_text) {
600 4d3b6f6e balrog
        s->text_x[0] = 0;
601 4d3b6f6e balrog
        s->text_y[0] = 0;
602 4d3b6f6e balrog
        s->text_x[1] = s->width - 1;
603 4d3b6f6e balrog
        s->text_y[1] = s->height - 1;
604 4d3b6f6e balrog
        s->cursor_invalidate = 1;
605 4d3b6f6e balrog
    }
606 e7f0ad58 bellard
607 a93a4a22 Gerd Hoffmann
    if (s->ds->have_gfx) {
608 1562e531 Gerd Hoffmann
        vga_fill_rect(s, 0, 0, surface_width(surface), surface_height(surface),
609 cf6f0548 Gerd Hoffmann
                      color_table_rgb[0][COLOR_BLACK]);
610 a93a4a22 Gerd Hoffmann
        y1 = s->y_displayed;
611 a93a4a22 Gerd Hoffmann
        for (y = 0; y < s->height; y++) {
612 a93a4a22 Gerd Hoffmann
            c = s->cells + y1 * s->width;
613 a93a4a22 Gerd Hoffmann
            for (x = 0; x < s->width; x++) {
614 1562e531 Gerd Hoffmann
                vga_putcharxy(s, x, y, c->ch,
615 a93a4a22 Gerd Hoffmann
                              &(c->t_attrib));
616 a93a4a22 Gerd Hoffmann
                c++;
617 a93a4a22 Gerd Hoffmann
            }
618 a93a4a22 Gerd Hoffmann
            if (++y1 == s->total_height) {
619 a93a4a22 Gerd Hoffmann
                y1 = 0;
620 a93a4a22 Gerd Hoffmann
            }
621 e7f0ad58 bellard
        }
622 a93a4a22 Gerd Hoffmann
        console_show_cursor(s, 1);
623 1562e531 Gerd Hoffmann
        dpy_gfx_update(s, 0, 0,
624 1562e531 Gerd Hoffmann
                       surface_width(surface), surface_height(surface));
625 e7f0ad58 bellard
    }
626 e7f0ad58 bellard
}
627 e7f0ad58 bellard
628 e7f0ad58 bellard
static void console_scroll(int ydelta)
629 e7f0ad58 bellard
{
630 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
631 e7f0ad58 bellard
    int i, y1;
632 3b46e624 ths
633 e7f0ad58 bellard
    s = active_console;
634 af3a9031 ths
    if (!s || (s->console_type == GRAPHIC_CONSOLE))
635 e7f0ad58 bellard
        return;
636 e7f0ad58 bellard
637 e7f0ad58 bellard
    if (ydelta > 0) {
638 e7f0ad58 bellard
        for(i = 0; i < ydelta; i++) {
639 e7f0ad58 bellard
            if (s->y_displayed == s->y_base)
640 e7f0ad58 bellard
                break;
641 e7f0ad58 bellard
            if (++s->y_displayed == s->total_height)
642 e7f0ad58 bellard
                s->y_displayed = 0;
643 e7f0ad58 bellard
        }
644 e7f0ad58 bellard
    } else {
645 e7f0ad58 bellard
        ydelta = -ydelta;
646 e7f0ad58 bellard
        i = s->backscroll_height;
647 e7f0ad58 bellard
        if (i > s->total_height - s->height)
648 e7f0ad58 bellard
            i = s->total_height - s->height;
649 e7f0ad58 bellard
        y1 = s->y_base - i;
650 e7f0ad58 bellard
        if (y1 < 0)
651 e7f0ad58 bellard
            y1 += s->total_height;
652 e7f0ad58 bellard
        for(i = 0; i < ydelta; i++) {
653 e7f0ad58 bellard
            if (s->y_displayed == y1)
654 e7f0ad58 bellard
                break;
655 e7f0ad58 bellard
            if (--s->y_displayed < 0)
656 e7f0ad58 bellard
                s->y_displayed = s->total_height - 1;
657 e7f0ad58 bellard
        }
658 e7f0ad58 bellard
    }
659 e7f0ad58 bellard
    console_refresh(s);
660 e7f0ad58 bellard
}
661 e7f0ad58 bellard
662 76ffb0b4 Gerd Hoffmann
static void console_put_lf(QemuConsole *s)
663 e7f0ad58 bellard
{
664 e7f0ad58 bellard
    TextCell *c;
665 e7f0ad58 bellard
    int x, y1;
666 e7f0ad58 bellard
667 e7f0ad58 bellard
    s->y++;
668 e7f0ad58 bellard
    if (s->y >= s->height) {
669 e7f0ad58 bellard
        s->y = s->height - 1;
670 6d6f7c28 pbrook
671 e7f0ad58 bellard
        if (s->y_displayed == s->y_base) {
672 e7f0ad58 bellard
            if (++s->y_displayed == s->total_height)
673 e7f0ad58 bellard
                s->y_displayed = 0;
674 e7f0ad58 bellard
        }
675 e7f0ad58 bellard
        if (++s->y_base == s->total_height)
676 e7f0ad58 bellard
            s->y_base = 0;
677 e7f0ad58 bellard
        if (s->backscroll_height < s->total_height)
678 e7f0ad58 bellard
            s->backscroll_height++;
679 e7f0ad58 bellard
        y1 = (s->y_base + s->height - 1) % s->total_height;
680 e7f0ad58 bellard
        c = &s->cells[y1 * s->width];
681 e7f0ad58 bellard
        for(x = 0; x < s->width; x++) {
682 e7f0ad58 bellard
            c->ch = ' ';
683 6d6f7c28 pbrook
            c->t_attrib = s->t_attrib_default;
684 e7f0ad58 bellard
            c++;
685 e7f0ad58 bellard
        }
686 e7f0ad58 bellard
        if (s == active_console && s->y_displayed == s->y_base) {
687 1562e531 Gerd Hoffmann
            if (s->ds->have_text) {
688 4d3b6f6e balrog
                s->text_x[0] = 0;
689 4d3b6f6e balrog
                s->text_y[0] = 0;
690 4d3b6f6e balrog
                s->text_x[1] = s->width - 1;
691 4d3b6f6e balrog
                s->text_y[1] = s->height - 1;
692 4d3b6f6e balrog
            }
693 4d3b6f6e balrog
694 1562e531 Gerd Hoffmann
            if (s->ds->have_gfx) {
695 1562e531 Gerd Hoffmann
                vga_bitblt(s, 0, FONT_HEIGHT, 0, 0,
696 1562e531 Gerd Hoffmann
                           s->width * FONT_WIDTH,
697 1562e531 Gerd Hoffmann
                           (s->height - 1) * FONT_HEIGHT);
698 1562e531 Gerd Hoffmann
                vga_fill_rect(s, 0, (s->height - 1) * FONT_HEIGHT,
699 1562e531 Gerd Hoffmann
                              s->width * FONT_WIDTH, FONT_HEIGHT,
700 1562e531 Gerd Hoffmann
                              color_table_rgb[0][s->t_attrib_default.bgcol]);
701 1562e531 Gerd Hoffmann
                s->update_x0 = 0;
702 1562e531 Gerd Hoffmann
                s->update_y0 = 0;
703 1562e531 Gerd Hoffmann
                s->update_x1 = s->width * FONT_WIDTH;
704 1562e531 Gerd Hoffmann
                s->update_y1 = s->height * FONT_HEIGHT;
705 1562e531 Gerd Hoffmann
            }
706 e7f0ad58 bellard
        }
707 e7f0ad58 bellard
    }
708 e7f0ad58 bellard
}
709 e7f0ad58 bellard
710 6d6f7c28 pbrook
/* Set console attributes depending on the current escape codes.
711 6d6f7c28 pbrook
 * NOTE: I know this code is not very efficient (checking every color for it
712 6d6f7c28 pbrook
 * self) but it is more readable and better maintainable.
713 6d6f7c28 pbrook
 */
714 76ffb0b4 Gerd Hoffmann
static void console_handle_escape(QemuConsole *s)
715 6d6f7c28 pbrook
{
716 6d6f7c28 pbrook
    int i;
717 6d6f7c28 pbrook
718 6d6f7c28 pbrook
    for (i=0; i<s->nb_esc_params; i++) {
719 6d6f7c28 pbrook
        switch (s->esc_params[i]) {
720 6d6f7c28 pbrook
            case 0: /* reset all console attributes to default */
721 6d6f7c28 pbrook
                s->t_attrib = s->t_attrib_default;
722 6d6f7c28 pbrook
                break;
723 6d6f7c28 pbrook
            case 1:
724 6d6f7c28 pbrook
                s->t_attrib.bold = 1;
725 6d6f7c28 pbrook
                break;
726 6d6f7c28 pbrook
            case 4:
727 6d6f7c28 pbrook
                s->t_attrib.uline = 1;
728 6d6f7c28 pbrook
                break;
729 6d6f7c28 pbrook
            case 5:
730 6d6f7c28 pbrook
                s->t_attrib.blink = 1;
731 6d6f7c28 pbrook
                break;
732 6d6f7c28 pbrook
            case 7:
733 6d6f7c28 pbrook
                s->t_attrib.invers = 1;
734 6d6f7c28 pbrook
                break;
735 6d6f7c28 pbrook
            case 8:
736 6d6f7c28 pbrook
                s->t_attrib.unvisible = 1;
737 6d6f7c28 pbrook
                break;
738 6d6f7c28 pbrook
            case 22:
739 6d6f7c28 pbrook
                s->t_attrib.bold = 0;
740 6d6f7c28 pbrook
                break;
741 6d6f7c28 pbrook
            case 24:
742 6d6f7c28 pbrook
                s->t_attrib.uline = 0;
743 6d6f7c28 pbrook
                break;
744 6d6f7c28 pbrook
            case 25:
745 6d6f7c28 pbrook
                s->t_attrib.blink = 0;
746 6d6f7c28 pbrook
                break;
747 6d6f7c28 pbrook
            case 27:
748 6d6f7c28 pbrook
                s->t_attrib.invers = 0;
749 6d6f7c28 pbrook
                break;
750 6d6f7c28 pbrook
            case 28:
751 6d6f7c28 pbrook
                s->t_attrib.unvisible = 0;
752 6d6f7c28 pbrook
                break;
753 6d6f7c28 pbrook
            /* set foreground color */
754 6d6f7c28 pbrook
            case 30:
755 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_BLACK;
756 6d6f7c28 pbrook
                break;
757 6d6f7c28 pbrook
            case 31:
758 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_RED;
759 6d6f7c28 pbrook
                break;
760 6d6f7c28 pbrook
            case 32:
761 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_GREEN;
762 6d6f7c28 pbrook
                break;
763 6d6f7c28 pbrook
            case 33:
764 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_YELLOW;
765 6d6f7c28 pbrook
                break;
766 6d6f7c28 pbrook
            case 34:
767 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_BLUE;
768 6d6f7c28 pbrook
                break;
769 6d6f7c28 pbrook
            case 35:
770 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_MAGENTA;
771 6d6f7c28 pbrook
                break;
772 6d6f7c28 pbrook
            case 36:
773 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_CYAN;
774 6d6f7c28 pbrook
                break;
775 6d6f7c28 pbrook
            case 37:
776 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_WHITE;
777 6d6f7c28 pbrook
                break;
778 6d6f7c28 pbrook
            /* set background color */
779 6d6f7c28 pbrook
            case 40:
780 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_BLACK;
781 6d6f7c28 pbrook
                break;
782 6d6f7c28 pbrook
            case 41:
783 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_RED;
784 6d6f7c28 pbrook
                break;
785 6d6f7c28 pbrook
            case 42:
786 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_GREEN;
787 6d6f7c28 pbrook
                break;
788 6d6f7c28 pbrook
            case 43:
789 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_YELLOW;
790 6d6f7c28 pbrook
                break;
791 6d6f7c28 pbrook
            case 44:
792 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_BLUE;
793 6d6f7c28 pbrook
                break;
794 6d6f7c28 pbrook
            case 45:
795 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_MAGENTA;
796 6d6f7c28 pbrook
                break;
797 6d6f7c28 pbrook
            case 46:
798 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_CYAN;
799 6d6f7c28 pbrook
                break;
800 6d6f7c28 pbrook
            case 47:
801 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_WHITE;
802 6d6f7c28 pbrook
                break;
803 6d6f7c28 pbrook
        }
804 6d6f7c28 pbrook
    }
805 6d6f7c28 pbrook
}
806 6d6f7c28 pbrook
807 76ffb0b4 Gerd Hoffmann
static void console_clear_xy(QemuConsole *s, int x, int y)
808 adb47967 ths
{
809 adb47967 ths
    int y1 = (s->y_base + y) % s->total_height;
810 adb47967 ths
    TextCell *c = &s->cells[y1 * s->width + x];
811 adb47967 ths
    c->ch = ' ';
812 adb47967 ths
    c->t_attrib = s->t_attrib_default;
813 adb47967 ths
    update_xy(s, x, y);
814 adb47967 ths
}
815 adb47967 ths
816 3eea5498 Ian Campbell
/* set cursor, checking bounds */
817 76ffb0b4 Gerd Hoffmann
static void set_cursor(QemuConsole *s, int x, int y)
818 3eea5498 Ian Campbell
{
819 3eea5498 Ian Campbell
    if (x < 0) {
820 3eea5498 Ian Campbell
        x = 0;
821 3eea5498 Ian Campbell
    }
822 3eea5498 Ian Campbell
    if (y < 0) {
823 3eea5498 Ian Campbell
        y = 0;
824 3eea5498 Ian Campbell
    }
825 3eea5498 Ian Campbell
    if (y >= s->height) {
826 3eea5498 Ian Campbell
        y = s->height - 1;
827 3eea5498 Ian Campbell
    }
828 3eea5498 Ian Campbell
    if (x >= s->width) {
829 3eea5498 Ian Campbell
        x = s->width - 1;
830 3eea5498 Ian Campbell
    }
831 3eea5498 Ian Campbell
832 3eea5498 Ian Campbell
    s->x = x;
833 3eea5498 Ian Campbell
    s->y = y;
834 3eea5498 Ian Campbell
}
835 3eea5498 Ian Campbell
836 76ffb0b4 Gerd Hoffmann
static void console_putchar(QemuConsole *s, int ch)
837 e7f0ad58 bellard
{
838 e7f0ad58 bellard
    TextCell *c;
839 adb47967 ths
    int y1, i;
840 adb47967 ths
    int x, y;
841 e7f0ad58 bellard
842 e7f0ad58 bellard
    switch(s->state) {
843 e7f0ad58 bellard
    case TTY_STATE_NORM:
844 e7f0ad58 bellard
        switch(ch) {
845 6d6f7c28 pbrook
        case '\r':  /* carriage return */
846 e7f0ad58 bellard
            s->x = 0;
847 e7f0ad58 bellard
            break;
848 6d6f7c28 pbrook
        case '\n':  /* newline */
849 e7f0ad58 bellard
            console_put_lf(s);
850 e7f0ad58 bellard
            break;
851 6d6f7c28 pbrook
        case '\b':  /* backspace */
852 5fafdf24 ths
            if (s->x > 0)
853 e15d7371 bellard
                s->x--;
854 6d6f7c28 pbrook
            break;
855 6d6f7c28 pbrook
        case '\t':  /* tabspace */
856 6d6f7c28 pbrook
            if (s->x + (8 - (s->x % 8)) > s->width) {
857 bd468840 bellard
                s->x = 0;
858 6d6f7c28 pbrook
                console_put_lf(s);
859 6d6f7c28 pbrook
            } else {
860 6d6f7c28 pbrook
                s->x = s->x + (8 - (s->x % 8));
861 6d6f7c28 pbrook
            }
862 6d6f7c28 pbrook
            break;
863 6d6f7c28 pbrook
        case '\a':  /* alert aka. bell */
864 6d6f7c28 pbrook
            /* TODO: has to be implemented */
865 6d6f7c28 pbrook
            break;
866 adb47967 ths
        case 14:
867 adb47967 ths
            /* SI (shift in), character set 0 (ignored) */
868 adb47967 ths
            break;
869 adb47967 ths
        case 15:
870 adb47967 ths
            /* SO (shift out), character set 1 (ignored) */
871 adb47967 ths
            break;
872 6d6f7c28 pbrook
        case 27:    /* esc (introducing an escape sequence) */
873 e7f0ad58 bellard
            s->state = TTY_STATE_ESC;
874 e7f0ad58 bellard
            break;
875 e7f0ad58 bellard
        default:
876 ed8276ac ths
            if (s->x >= s->width) {
877 ed8276ac ths
                /* line wrap */
878 ed8276ac ths
                s->x = 0;
879 ed8276ac ths
                console_put_lf(s);
880 adb47967 ths
            }
881 e7f0ad58 bellard
            y1 = (s->y_base + s->y) % s->total_height;
882 e7f0ad58 bellard
            c = &s->cells[y1 * s->width + s->x];
883 e7f0ad58 bellard
            c->ch = ch;
884 6d6f7c28 pbrook
            c->t_attrib = s->t_attrib;
885 e7f0ad58 bellard
            update_xy(s, s->x, s->y);
886 e7f0ad58 bellard
            s->x++;
887 e7f0ad58 bellard
            break;
888 e7f0ad58 bellard
        }
889 e7f0ad58 bellard
        break;
890 6d6f7c28 pbrook
    case TTY_STATE_ESC: /* check if it is a terminal escape sequence */
891 e7f0ad58 bellard
        if (ch == '[') {
892 e7f0ad58 bellard
            for(i=0;i<MAX_ESC_PARAMS;i++)
893 e7f0ad58 bellard
                s->esc_params[i] = 0;
894 e7f0ad58 bellard
            s->nb_esc_params = 0;
895 e7f0ad58 bellard
            s->state = TTY_STATE_CSI;
896 e7f0ad58 bellard
        } else {
897 e7f0ad58 bellard
            s->state = TTY_STATE_NORM;
898 e7f0ad58 bellard
        }
899 e7f0ad58 bellard
        break;
900 6d6f7c28 pbrook
    case TTY_STATE_CSI: /* handle escape sequence parameters */
901 e7f0ad58 bellard
        if (ch >= '0' && ch <= '9') {
902 e7f0ad58 bellard
            if (s->nb_esc_params < MAX_ESC_PARAMS) {
903 c10600af Laszlo Ersek
                int *param = &s->esc_params[s->nb_esc_params];
904 c10600af Laszlo Ersek
                int digit = (ch - '0');
905 c10600af Laszlo Ersek
906 c10600af Laszlo Ersek
                *param = (*param <= (INT_MAX - digit) / 10) ?
907 c10600af Laszlo Ersek
                         *param * 10 + digit : INT_MAX;
908 e7f0ad58 bellard
            }
909 e7f0ad58 bellard
        } else {
910 3eea5498 Ian Campbell
            if (s->nb_esc_params < MAX_ESC_PARAMS)
911 3eea5498 Ian Campbell
                s->nb_esc_params++;
912 e7f0ad58 bellard
            if (ch == ';')
913 e7f0ad58 bellard
                break;
914 adb47967 ths
#ifdef DEBUG_CONSOLE
915 adb47967 ths
            fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
916 adb47967 ths
                    s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
917 adb47967 ths
#endif
918 e7f0ad58 bellard
            s->state = TTY_STATE_NORM;
919 e7f0ad58 bellard
            switch(ch) {
920 adb47967 ths
            case 'A':
921 adb47967 ths
                /* move cursor up */
922 adb47967 ths
                if (s->esc_params[0] == 0) {
923 adb47967 ths
                    s->esc_params[0] = 1;
924 adb47967 ths
                }
925 3eea5498 Ian Campbell
                set_cursor(s, s->x, s->y - s->esc_params[0]);
926 adb47967 ths
                break;
927 adb47967 ths
            case 'B':
928 adb47967 ths
                /* move cursor down */
929 adb47967 ths
                if (s->esc_params[0] == 0) {
930 adb47967 ths
                    s->esc_params[0] = 1;
931 adb47967 ths
                }
932 3eea5498 Ian Campbell
                set_cursor(s, s->x, s->y + s->esc_params[0]);
933 e7f0ad58 bellard
                break;
934 e7f0ad58 bellard
            case 'C':
935 adb47967 ths
                /* move cursor right */
936 adb47967 ths
                if (s->esc_params[0] == 0) {
937 adb47967 ths
                    s->esc_params[0] = 1;
938 adb47967 ths
                }
939 3eea5498 Ian Campbell
                set_cursor(s, s->x + s->esc_params[0], s->y);
940 e7f0ad58 bellard
                break;
941 adb47967 ths
            case 'D':
942 adb47967 ths
                /* move cursor left */
943 adb47967 ths
                if (s->esc_params[0] == 0) {
944 adb47967 ths
                    s->esc_params[0] = 1;
945 adb47967 ths
                }
946 3eea5498 Ian Campbell
                set_cursor(s, s->x - s->esc_params[0], s->y);
947 adb47967 ths
                break;
948 adb47967 ths
            case 'G':
949 adb47967 ths
                /* move cursor to column */
950 3eea5498 Ian Campbell
                set_cursor(s, s->esc_params[0] - 1, s->y);
951 adb47967 ths
                break;
952 adb47967 ths
            case 'f':
953 adb47967 ths
            case 'H':
954 adb47967 ths
                /* move cursor to row, column */
955 3eea5498 Ian Campbell
                set_cursor(s, s->esc_params[1] - 1, s->esc_params[0] - 1);
956 adb47967 ths
                break;
957 adb47967 ths
            case 'J':
958 adb47967 ths
                switch (s->esc_params[0]) {
959 adb47967 ths
                case 0:
960 adb47967 ths
                    /* clear to end of screen */
961 adb47967 ths
                    for (y = s->y; y < s->height; y++) {
962 adb47967 ths
                        for (x = 0; x < s->width; x++) {
963 adb47967 ths
                            if (y == s->y && x < s->x) {
964 adb47967 ths
                                continue;
965 adb47967 ths
                            }
966 adb47967 ths
                            console_clear_xy(s, x, y);
967 adb47967 ths
                        }
968 adb47967 ths
                    }
969 adb47967 ths
                    break;
970 adb47967 ths
                case 1:
971 adb47967 ths
                    /* clear from beginning of screen */
972 adb47967 ths
                    for (y = 0; y <= s->y; y++) {
973 adb47967 ths
                        for (x = 0; x < s->width; x++) {
974 adb47967 ths
                            if (y == s->y && x > s->x) {
975 adb47967 ths
                                break;
976 adb47967 ths
                            }
977 adb47967 ths
                            console_clear_xy(s, x, y);
978 adb47967 ths
                        }
979 adb47967 ths
                    }
980 adb47967 ths
                    break;
981 adb47967 ths
                case 2:
982 adb47967 ths
                    /* clear entire screen */
983 adb47967 ths
                    for (y = 0; y <= s->height; y++) {
984 adb47967 ths
                        for (x = 0; x < s->width; x++) {
985 adb47967 ths
                            console_clear_xy(s, x, y);
986 adb47967 ths
                        }
987 adb47967 ths
                    }
988 f94a950f Markus Armbruster
                    break;
989 adb47967 ths
                }
990 95d8f9f4 Markus Armbruster
                break;
991 e7f0ad58 bellard
            case 'K':
992 adb47967 ths
                switch (s->esc_params[0]) {
993 adb47967 ths
                case 0:
994 f94a950f Markus Armbruster
                    /* clear to eol */
995 f94a950f Markus Armbruster
                    for(x = s->x; x < s->width; x++) {
996 adb47967 ths
                        console_clear_xy(s, x, s->y);
997 f94a950f Markus Armbruster
                    }
998 f94a950f Markus Armbruster
                    break;
999 adb47967 ths
                case 1:
1000 adb47967 ths
                    /* clear from beginning of line */
1001 adb47967 ths
                    for (x = 0; x <= s->x; x++) {
1002 adb47967 ths
                        console_clear_xy(s, x, s->y);
1003 adb47967 ths
                    }
1004 adb47967 ths
                    break;
1005 adb47967 ths
                case 2:
1006 adb47967 ths
                    /* clear entire line */
1007 adb47967 ths
                    for(x = 0; x < s->width; x++) {
1008 adb47967 ths
                        console_clear_xy(s, x, s->y);
1009 adb47967 ths
                    }
1010 f94a950f Markus Armbruster
                    break;
1011 f94a950f Markus Armbruster
                }
1012 adb47967 ths
                break;
1013 adb47967 ths
            case 'm':
1014 f94a950f Markus Armbruster
                console_handle_escape(s);
1015 f94a950f Markus Armbruster
                break;
1016 adb47967 ths
            case 'n':
1017 adb47967 ths
                /* report cursor position */
1018 adb47967 ths
                /* TODO: send ESC[row;colR */
1019 adb47967 ths
                break;
1020 adb47967 ths
            case 's':
1021 adb47967 ths
                /* save cursor position */
1022 adb47967 ths
                s->x_saved = s->x;
1023 adb47967 ths
                s->y_saved = s->y;
1024 adb47967 ths
                break;
1025 adb47967 ths
            case 'u':
1026 adb47967 ths
                /* restore cursor position */
1027 adb47967 ths
                s->x = s->x_saved;
1028 adb47967 ths
                s->y = s->y_saved;
1029 adb47967 ths
                break;
1030 adb47967 ths
            default:
1031 adb47967 ths
#ifdef DEBUG_CONSOLE
1032 adb47967 ths
                fprintf(stderr, "unhandled escape character '%c'\n", ch);
1033 adb47967 ths
#endif
1034 adb47967 ths
                break;
1035 adb47967 ths
            }
1036 adb47967 ths
            break;
1037 e7f0ad58 bellard
        }
1038 e7f0ad58 bellard
    }
1039 e7f0ad58 bellard
}
1040 e7f0ad58 bellard
1041 e7f0ad58 bellard
void console_select(unsigned int index)
1042 e7f0ad58 bellard
{
1043 1562e531 Gerd Hoffmann
    DisplaySurface *surface;
1044 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1045 6d6f7c28 pbrook
1046 e7f0ad58 bellard
    if (index >= MAX_CONSOLES)
1047 e7f0ad58 bellard
        return;
1048 358664cc Stefan Hajnoczi
    if (active_console) {
1049 1562e531 Gerd Hoffmann
        surface = qemu_console_surface(active_console);
1050 1562e531 Gerd Hoffmann
        active_console->g_width = surface_width(surface);
1051 1562e531 Gerd Hoffmann
        active_console->g_height = surface_height(surface);
1052 358664cc Stefan Hajnoczi
    }
1053 e7f0ad58 bellard
    s = consoles[index];
1054 e7f0ad58 bellard
    if (s) {
1055 7d957bd8 aliguori
        DisplayState *ds = s->ds;
1056 bf1bed81 Jan Kiszka
1057 8bd6b06d Stefan Weil
        if (active_console && active_console->cursor_timer) {
1058 bf1bed81 Jan Kiszka
            qemu_del_timer(active_console->cursor_timer);
1059 bf1bed81 Jan Kiszka
        }
1060 e7f0ad58 bellard
        active_console = s;
1061 a93a4a22 Gerd Hoffmann
        if (ds->have_gfx) {
1062 da229ef3 Gerd Hoffmann
            surface = qemu_create_displaysurface(s->g_width, s->g_height);
1063 c78f7137 Gerd Hoffmann
            dpy_gfx_replace_surface(s, surface);
1064 a93a4a22 Gerd Hoffmann
        }
1065 a93a4a22 Gerd Hoffmann
        if (ds->have_text) {
1066 c78f7137 Gerd Hoffmann
            dpy_text_resize(s, s->width, s->height);
1067 68f00996 aliguori
        }
1068 bf1bed81 Jan Kiszka
        if (s->cursor_timer) {
1069 bf1bed81 Jan Kiszka
            qemu_mod_timer(s->cursor_timer,
1070 bf1bed81 Jan Kiszka
                   qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
1071 bf1bed81 Jan Kiszka
        }
1072 4d3b6f6e balrog
        vga_hw_invalidate();
1073 e7f0ad58 bellard
    }
1074 e7f0ad58 bellard
}
1075 e7f0ad58 bellard
1076 e7f0ad58 bellard
static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
1077 e7f0ad58 bellard
{
1078 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = chr->opaque;
1079 e7f0ad58 bellard
    int i;
1080 e7f0ad58 bellard
1081 14778c20 pbrook
    s->update_x0 = s->width * FONT_WIDTH;
1082 14778c20 pbrook
    s->update_y0 = s->height * FONT_HEIGHT;
1083 14778c20 pbrook
    s->update_x1 = 0;
1084 14778c20 pbrook
    s->update_y1 = 0;
1085 e7f0ad58 bellard
    console_show_cursor(s, 0);
1086 e7f0ad58 bellard
    for(i = 0; i < len; i++) {
1087 e7f0ad58 bellard
        console_putchar(s, buf[i]);
1088 e7f0ad58 bellard
    }
1089 e7f0ad58 bellard
    console_show_cursor(s, 1);
1090 a93a4a22 Gerd Hoffmann
    if (s->ds->have_gfx && s->update_x0 < s->update_x1) {
1091 c78f7137 Gerd Hoffmann
        dpy_gfx_update(s, s->update_x0, s->update_y0,
1092 a93a4a22 Gerd Hoffmann
                       s->update_x1 - s->update_x0,
1093 a93a4a22 Gerd Hoffmann
                       s->update_y1 - s->update_y0);
1094 14778c20 pbrook
    }
1095 e7f0ad58 bellard
    return len;
1096 e7f0ad58 bellard
}
1097 e7f0ad58 bellard
1098 e15d7371 bellard
static void kbd_send_chars(void *opaque)
1099 e15d7371 bellard
{
1100 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = opaque;
1101 e15d7371 bellard
    int len;
1102 e15d7371 bellard
    uint8_t buf[16];
1103 3b46e624 ths
1104 909cda12 Anthony Liguori
    len = qemu_chr_be_can_write(s->chr);
1105 e15d7371 bellard
    if (len > s->out_fifo.count)
1106 e15d7371 bellard
        len = s->out_fifo.count;
1107 e15d7371 bellard
    if (len > 0) {
1108 e15d7371 bellard
        if (len > sizeof(buf))
1109 e15d7371 bellard
            len = sizeof(buf);
1110 e15d7371 bellard
        qemu_fifo_read(&s->out_fifo, buf, len);
1111 fa5efccb Anthony Liguori
        qemu_chr_be_write(s->chr, buf, len);
1112 e15d7371 bellard
    }
1113 e15d7371 bellard
    /* characters are pending: we send them a bit later (XXX:
1114 e15d7371 bellard
       horrible, should change char device API) */
1115 e15d7371 bellard
    if (s->out_fifo.count > 0) {
1116 7bd427d8 Paolo Bonzini
        qemu_mod_timer(s->kbd_timer, qemu_get_clock_ms(rt_clock) + 1);
1117 e15d7371 bellard
    }
1118 e15d7371 bellard
}
1119 e15d7371 bellard
1120 e7f0ad58 bellard
/* called when an ascii key is pressed */
1121 e7f0ad58 bellard
void kbd_put_keysym(int keysym)
1122 e7f0ad58 bellard
{
1123 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1124 e7f0ad58 bellard
    uint8_t buf[16], *q;
1125 e7f0ad58 bellard
    int c;
1126 e7f0ad58 bellard
1127 e7f0ad58 bellard
    s = active_console;
1128 af3a9031 ths
    if (!s || (s->console_type == GRAPHIC_CONSOLE))
1129 e7f0ad58 bellard
        return;
1130 e7f0ad58 bellard
1131 e7f0ad58 bellard
    switch(keysym) {
1132 e7f0ad58 bellard
    case QEMU_KEY_CTRL_UP:
1133 e7f0ad58 bellard
        console_scroll(-1);
1134 e7f0ad58 bellard
        break;
1135 e7f0ad58 bellard
    case QEMU_KEY_CTRL_DOWN:
1136 e7f0ad58 bellard
        console_scroll(1);
1137 e7f0ad58 bellard
        break;
1138 e7f0ad58 bellard
    case QEMU_KEY_CTRL_PAGEUP:
1139 e7f0ad58 bellard
        console_scroll(-10);
1140 e7f0ad58 bellard
        break;
1141 e7f0ad58 bellard
    case QEMU_KEY_CTRL_PAGEDOWN:
1142 e7f0ad58 bellard
        console_scroll(10);
1143 e7f0ad58 bellard
        break;
1144 e7f0ad58 bellard
    default:
1145 e15d7371 bellard
        /* convert the QEMU keysym to VT100 key string */
1146 e15d7371 bellard
        q = buf;
1147 e15d7371 bellard
        if (keysym >= 0xe100 && keysym <= 0xe11f) {
1148 e15d7371 bellard
            *q++ = '\033';
1149 e15d7371 bellard
            *q++ = '[';
1150 e15d7371 bellard
            c = keysym - 0xe100;
1151 e15d7371 bellard
            if (c >= 10)
1152 e15d7371 bellard
                *q++ = '0' + (c / 10);
1153 e15d7371 bellard
            *q++ = '0' + (c % 10);
1154 e15d7371 bellard
            *q++ = '~';
1155 e15d7371 bellard
        } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
1156 e15d7371 bellard
            *q++ = '\033';
1157 e15d7371 bellard
            *q++ = '[';
1158 e15d7371 bellard
            *q++ = keysym & 0xff;
1159 4104833f Paolo Bonzini
        } else if (s->echo && (keysym == '\r' || keysym == '\n')) {
1160 4104833f Paolo Bonzini
            console_puts(s->chr, (const uint8_t *) "\r", 1);
1161 4104833f Paolo Bonzini
            *q++ = '\n';
1162 e15d7371 bellard
        } else {
1163 4104833f Paolo Bonzini
            *q++ = keysym;
1164 4104833f Paolo Bonzini
        }
1165 4104833f Paolo Bonzini
        if (s->echo) {
1166 4104833f Paolo Bonzini
            console_puts(s->chr, buf, q - buf);
1167 e15d7371 bellard
        }
1168 e5b0bc44 pbrook
        if (s->chr->chr_read) {
1169 e15d7371 bellard
            qemu_fifo_write(&s->out_fifo, buf, q - buf);
1170 e15d7371 bellard
            kbd_send_chars(s);
1171 e7f0ad58 bellard
        }
1172 e7f0ad58 bellard
        break;
1173 e7f0ad58 bellard
    }
1174 e7f0ad58 bellard
}
1175 e7f0ad58 bellard
1176 4d3b6f6e balrog
static void text_console_invalidate(void *opaque)
1177 4d3b6f6e balrog
{
1178 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = (QemuConsole *) opaque;
1179 1562e531 Gerd Hoffmann
    DisplaySurface *surface = qemu_console_surface(s);
1180 1562e531 Gerd Hoffmann
1181 1562e531 Gerd Hoffmann
    if (s->ds->have_text && s->console_type == TEXT_CONSOLE) {
1182 1562e531 Gerd Hoffmann
        s->g_width = surface_width(surface);
1183 1562e531 Gerd Hoffmann
        s->g_height = surface_height(surface);
1184 68f00996 aliguori
        text_console_resize(s);
1185 68f00996 aliguori
    }
1186 4d3b6f6e balrog
    console_refresh(s);
1187 4d3b6f6e balrog
}
1188 4d3b6f6e balrog
1189 c227f099 Anthony Liguori
static void text_console_update(void *opaque, console_ch_t *chardata)
1190 4d3b6f6e balrog
{
1191 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = (QemuConsole *) opaque;
1192 4d3b6f6e balrog
    int i, j, src;
1193 4d3b6f6e balrog
1194 4d3b6f6e balrog
    if (s->text_x[0] <= s->text_x[1]) {
1195 4d3b6f6e balrog
        src = (s->y_base + s->text_y[0]) * s->width;
1196 4d3b6f6e balrog
        chardata += s->text_y[0] * s->width;
1197 4d3b6f6e balrog
        for (i = s->text_y[0]; i <= s->text_y[1]; i ++)
1198 4d3b6f6e balrog
            for (j = 0; j < s->width; j ++, src ++)
1199 4d3b6f6e balrog
                console_write_ch(chardata ++, s->cells[src].ch |
1200 4d3b6f6e balrog
                                (s->cells[src].t_attrib.fgcol << 12) |
1201 4d3b6f6e balrog
                                (s->cells[src].t_attrib.bgcol << 8) |
1202 4d3b6f6e balrog
                                (s->cells[src].t_attrib.bold << 21));
1203 c78f7137 Gerd Hoffmann
        dpy_text_update(s, s->text_x[0], s->text_y[0],
1204 a93a4a22 Gerd Hoffmann
                        s->text_x[1] - s->text_x[0], i - s->text_y[0]);
1205 4d3b6f6e balrog
        s->text_x[0] = s->width;
1206 4d3b6f6e balrog
        s->text_y[0] = s->height;
1207 4d3b6f6e balrog
        s->text_x[1] = 0;
1208 4d3b6f6e balrog
        s->text_y[1] = 0;
1209 4d3b6f6e balrog
    }
1210 4d3b6f6e balrog
    if (s->cursor_invalidate) {
1211 c78f7137 Gerd Hoffmann
        dpy_text_cursor(s, s->x, s->y);
1212 4d3b6f6e balrog
        s->cursor_invalidate = 0;
1213 4d3b6f6e balrog
    }
1214 4d3b6f6e balrog
}
1215 4d3b6f6e balrog
1216 76ffb0b4 Gerd Hoffmann
static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
1217 e7f0ad58 bellard
{
1218 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1219 95219897 pbrook
    int i;
1220 e7f0ad58 bellard
1221 e7f0ad58 bellard
    if (nb_consoles >= MAX_CONSOLES)
1222 e7f0ad58 bellard
        return NULL;
1223 76ffb0b4 Gerd Hoffmann
    s = g_malloc0(sizeof(QemuConsole));
1224 af3a9031 ths
    if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
1225 af3a9031 ths
        (console_type == GRAPHIC_CONSOLE))) {
1226 e7f0ad58 bellard
        active_console = s;
1227 af3a9031 ths
    }
1228 e7f0ad58 bellard
    s->ds = ds;
1229 af3a9031 ths
    s->console_type = console_type;
1230 af3a9031 ths
    if (console_type != GRAPHIC_CONSOLE) {
1231 f81bdefb Jan Kiszka
        s->index = nb_consoles;
1232 95219897 pbrook
        consoles[nb_consoles++] = s;
1233 95219897 pbrook
    } else {
1234 95219897 pbrook
        /* HACK: Put graphical consoles before text consoles.  */
1235 95219897 pbrook
        for (i = nb_consoles; i > 0; i--) {
1236 af3a9031 ths
            if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
1237 95219897 pbrook
                break;
1238 95219897 pbrook
            consoles[i] = consoles[i - 1];
1239 f81bdefb Jan Kiszka
            consoles[i]->index = i;
1240 95219897 pbrook
        }
1241 f81bdefb Jan Kiszka
        s->index = i;
1242 95219897 pbrook
        consoles[i] = s;
1243 3023f332 aliguori
        nb_consoles++;
1244 95219897 pbrook
    }
1245 95219897 pbrook
    return s;
1246 95219897 pbrook
}
1247 95219897 pbrook
1248 537a4391 Gerd Hoffmann
static void qemu_alloc_display(DisplaySurface *surface, int width, int height,
1249 537a4391 Gerd Hoffmann
                               int linesize, PixelFormat pf, int newflags)
1250 ffe8b821 Jes Sorensen
{
1251 ffe8b821 Jes Sorensen
    surface->pf = pf;
1252 69c77777 Gerd Hoffmann
1253 69c77777 Gerd Hoffmann
    qemu_pixman_image_unref(surface->image);
1254 69c77777 Gerd Hoffmann
    surface->image = NULL;
1255 69c77777 Gerd Hoffmann
1256 69c77777 Gerd Hoffmann
    surface->format = qemu_pixman_get_format(&pf);
1257 69c77777 Gerd Hoffmann
    assert(surface->format != 0);
1258 69c77777 Gerd Hoffmann
    surface->image = pixman_image_create_bits(surface->format,
1259 69c77777 Gerd Hoffmann
                                              width, height,
1260 69c77777 Gerd Hoffmann
                                              NULL, linesize);
1261 69c77777 Gerd Hoffmann
    assert(surface->image != NULL);
1262 69c77777 Gerd Hoffmann
1263 ffe8b821 Jes Sorensen
    surface->flags = newflags | QEMU_ALLOCATED_FLAG;
1264 98b50080 Paolo Bonzini
#ifdef HOST_WORDS_BIGENDIAN
1265 ffe8b821 Jes Sorensen
    surface->flags |= QEMU_BIG_ENDIAN_FLAG;
1266 98b50080 Paolo Bonzini
#endif
1267 98b50080 Paolo Bonzini
}
1268 98b50080 Paolo Bonzini
1269 da229ef3 Gerd Hoffmann
DisplaySurface *qemu_create_displaysurface(int width, int height)
1270 537a4391 Gerd Hoffmann
{
1271 537a4391 Gerd Hoffmann
    DisplaySurface *surface = g_new0(DisplaySurface, 1);
1272 537a4391 Gerd Hoffmann
    int linesize = width * 4;
1273 da229ef3 Gerd Hoffmann
1274 da229ef3 Gerd Hoffmann
    trace_displaysurface_create(surface, width, height);
1275 537a4391 Gerd Hoffmann
    qemu_alloc_display(surface, width, height, linesize,
1276 537a4391 Gerd Hoffmann
                       qemu_default_pixelformat(32), 0);
1277 537a4391 Gerd Hoffmann
    return surface;
1278 537a4391 Gerd Hoffmann
}
1279 537a4391 Gerd Hoffmann
1280 187cd1d9 Gerd Hoffmann
DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
1281 b1424e03 Gerd Hoffmann
                                                int linesize, uint8_t *data,
1282 b1424e03 Gerd Hoffmann
                                                bool byteswap)
1283 98b50080 Paolo Bonzini
{
1284 69c77777 Gerd Hoffmann
    DisplaySurface *surface = g_new0(DisplaySurface, 1);
1285 98b50080 Paolo Bonzini
1286 da229ef3 Gerd Hoffmann
    trace_displaysurface_create_from(surface, width, height, bpp, byteswap);
1287 b1424e03 Gerd Hoffmann
    if (byteswap) {
1288 b1424e03 Gerd Hoffmann
        surface->pf = qemu_different_endianness_pixelformat(bpp);
1289 b1424e03 Gerd Hoffmann
    } else {
1290 b1424e03 Gerd Hoffmann
        surface->pf = qemu_default_pixelformat(bpp);
1291 b1424e03 Gerd Hoffmann
    }
1292 69c77777 Gerd Hoffmann
1293 69c77777 Gerd Hoffmann
    surface->format = qemu_pixman_get_format(&surface->pf);
1294 69c77777 Gerd Hoffmann
    assert(surface->format != 0);
1295 69c77777 Gerd Hoffmann
    surface->image = pixman_image_create_bits(surface->format,
1296 69c77777 Gerd Hoffmann
                                              width, height,
1297 69c77777 Gerd Hoffmann
                                              (void *)data, linesize);
1298 69c77777 Gerd Hoffmann
    assert(surface->image != NULL);
1299 69c77777 Gerd Hoffmann
1300 98b50080 Paolo Bonzini
#ifdef HOST_WORDS_BIGENDIAN
1301 98b50080 Paolo Bonzini
    surface->flags = QEMU_BIG_ENDIAN_FLAG;
1302 98b50080 Paolo Bonzini
#endif
1303 98b50080 Paolo Bonzini
1304 98b50080 Paolo Bonzini
    return surface;
1305 98b50080 Paolo Bonzini
}
1306 98b50080 Paolo Bonzini
1307 da229ef3 Gerd Hoffmann
void qemu_free_displaysurface(DisplaySurface *surface)
1308 98b50080 Paolo Bonzini
{
1309 da229ef3 Gerd Hoffmann
    if (surface == NULL) {
1310 98b50080 Paolo Bonzini
        return;
1311 187cd1d9 Gerd Hoffmann
    }
1312 da229ef3 Gerd Hoffmann
    trace_displaysurface_free(surface);
1313 da229ef3 Gerd Hoffmann
    qemu_pixman_image_unref(surface->image);
1314 da229ef3 Gerd Hoffmann
    g_free(surface);
1315 98b50080 Paolo Bonzini
}
1316 98b50080 Paolo Bonzini
1317 7c20b4a3 Gerd Hoffmann
void register_displaychangelistener(DisplayState *ds,
1318 7c20b4a3 Gerd Hoffmann
                                    DisplayChangeListener *dcl)
1319 7c20b4a3 Gerd Hoffmann
{
1320 7c20b4a3 Gerd Hoffmann
    trace_displaychangelistener_register(dcl, dcl->ops->dpy_name);
1321 7c20b4a3 Gerd Hoffmann
    dcl->ds = ds;
1322 7c20b4a3 Gerd Hoffmann
    QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
1323 7c20b4a3 Gerd Hoffmann
    gui_setup_refresh(ds);
1324 c12aeb86 Gerd Hoffmann
    if (dcl->ops->dpy_gfx_switch) {
1325 bc2ed970 Gerd Hoffmann
        dcl->ops->dpy_gfx_switch(dcl, ds->surface);
1326 7c20b4a3 Gerd Hoffmann
    }
1327 7c20b4a3 Gerd Hoffmann
}
1328 7c20b4a3 Gerd Hoffmann
1329 7c20b4a3 Gerd Hoffmann
void unregister_displaychangelistener(DisplayChangeListener *dcl)
1330 7c20b4a3 Gerd Hoffmann
{
1331 7c20b4a3 Gerd Hoffmann
    DisplayState *ds = dcl->ds;
1332 7c20b4a3 Gerd Hoffmann
    trace_displaychangelistener_unregister(dcl, dcl->ops->dpy_name);
1333 7c20b4a3 Gerd Hoffmann
    QLIST_REMOVE(dcl, next);
1334 7c20b4a3 Gerd Hoffmann
    gui_setup_refresh(ds);
1335 7c20b4a3 Gerd Hoffmann
}
1336 7c20b4a3 Gerd Hoffmann
1337 c78f7137 Gerd Hoffmann
void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
1338 7c20b4a3 Gerd Hoffmann
{
1339 c78f7137 Gerd Hoffmann
    DisplayState *s = con->ds;
1340 7c20b4a3 Gerd Hoffmann
    struct DisplayChangeListener *dcl;
1341 7c20b4a3 Gerd Hoffmann
    int width = pixman_image_get_width(s->surface->image);
1342 7c20b4a3 Gerd Hoffmann
    int height = pixman_image_get_height(s->surface->image);
1343 7c20b4a3 Gerd Hoffmann
1344 7c20b4a3 Gerd Hoffmann
    x = MAX(x, 0);
1345 7c20b4a3 Gerd Hoffmann
    y = MAX(y, 0);
1346 7c20b4a3 Gerd Hoffmann
    x = MIN(x, width);
1347 7c20b4a3 Gerd Hoffmann
    y = MIN(y, height);
1348 7c20b4a3 Gerd Hoffmann
    w = MIN(w, width - x);
1349 7c20b4a3 Gerd Hoffmann
    h = MIN(h, height - y);
1350 7c20b4a3 Gerd Hoffmann
1351 7c20b4a3 Gerd Hoffmann
    QLIST_FOREACH(dcl, &s->listeners, next) {
1352 7c20b4a3 Gerd Hoffmann
        if (dcl->ops->dpy_gfx_update) {
1353 bc2ed970 Gerd Hoffmann
            dcl->ops->dpy_gfx_update(dcl, x, y, w, h);
1354 7c20b4a3 Gerd Hoffmann
        }
1355 7c20b4a3 Gerd Hoffmann
    }
1356 7c20b4a3 Gerd Hoffmann
}
1357 7c20b4a3 Gerd Hoffmann
1358 c78f7137 Gerd Hoffmann
void dpy_gfx_replace_surface(QemuConsole *con,
1359 da229ef3 Gerd Hoffmann
                             DisplaySurface *surface)
1360 7c20b4a3 Gerd Hoffmann
{
1361 c78f7137 Gerd Hoffmann
    DisplayState *s = con->ds;
1362 da229ef3 Gerd Hoffmann
    DisplaySurface *old_surface = s->surface;
1363 7c20b4a3 Gerd Hoffmann
    struct DisplayChangeListener *dcl;
1364 da229ef3 Gerd Hoffmann
1365 da229ef3 Gerd Hoffmann
    s->surface = surface;
1366 7c20b4a3 Gerd Hoffmann
    QLIST_FOREACH(dcl, &s->listeners, next) {
1367 c12aeb86 Gerd Hoffmann
        if (dcl->ops->dpy_gfx_switch) {
1368 bc2ed970 Gerd Hoffmann
            dcl->ops->dpy_gfx_switch(dcl, surface);
1369 7c20b4a3 Gerd Hoffmann
        }
1370 7c20b4a3 Gerd Hoffmann
    }
1371 da229ef3 Gerd Hoffmann
    qemu_free_displaysurface(old_surface);
1372 7c20b4a3 Gerd Hoffmann
}
1373 7c20b4a3 Gerd Hoffmann
1374 7c20b4a3 Gerd Hoffmann
void dpy_refresh(DisplayState *s)
1375 7c20b4a3 Gerd Hoffmann
{
1376 7c20b4a3 Gerd Hoffmann
    struct DisplayChangeListener *dcl;
1377 7c20b4a3 Gerd Hoffmann
    QLIST_FOREACH(dcl, &s->listeners, next) {
1378 7c20b4a3 Gerd Hoffmann
        if (dcl->ops->dpy_refresh) {
1379 bc2ed970 Gerd Hoffmann
            dcl->ops->dpy_refresh(dcl);
1380 7c20b4a3 Gerd Hoffmann
        }
1381 7c20b4a3 Gerd Hoffmann
    }
1382 7c20b4a3 Gerd Hoffmann
}
1383 7c20b4a3 Gerd Hoffmann
1384 c78f7137 Gerd Hoffmann
void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
1385 c78f7137 Gerd Hoffmann
                  int dst_x, int dst_y, int w, int h)
1386 7c20b4a3 Gerd Hoffmann
{
1387 c78f7137 Gerd Hoffmann
    DisplayState *s = con->ds;
1388 7c20b4a3 Gerd Hoffmann
    struct DisplayChangeListener *dcl;
1389 7c20b4a3 Gerd Hoffmann
    QLIST_FOREACH(dcl, &s->listeners, next) {
1390 7c20b4a3 Gerd Hoffmann
        if (dcl->ops->dpy_gfx_copy) {
1391 bc2ed970 Gerd Hoffmann
            dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
1392 7c20b4a3 Gerd Hoffmann
        } else { /* TODO */
1393 bc2ed970 Gerd Hoffmann
            dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h);
1394 7c20b4a3 Gerd Hoffmann
        }
1395 7c20b4a3 Gerd Hoffmann
    }
1396 7c20b4a3 Gerd Hoffmann
}
1397 7c20b4a3 Gerd Hoffmann
1398 c78f7137 Gerd Hoffmann
void dpy_text_cursor(QemuConsole *con, int x, int y)
1399 7c20b4a3 Gerd Hoffmann
{
1400 c78f7137 Gerd Hoffmann
    DisplayState *s = con->ds;
1401 7c20b4a3 Gerd Hoffmann
    struct DisplayChangeListener *dcl;
1402 7c20b4a3 Gerd Hoffmann
    QLIST_FOREACH(dcl, &s->listeners, next) {
1403 7c20b4a3 Gerd Hoffmann
        if (dcl->ops->dpy_text_cursor) {
1404 bc2ed970 Gerd Hoffmann
            dcl->ops->dpy_text_cursor(dcl, x, y);
1405 7c20b4a3 Gerd Hoffmann
        }
1406 7c20b4a3 Gerd Hoffmann
    }
1407 7c20b4a3 Gerd Hoffmann
}
1408 7c20b4a3 Gerd Hoffmann
1409 c78f7137 Gerd Hoffmann
void dpy_text_update(QemuConsole *con, int x, int y, int w, int h)
1410 7c20b4a3 Gerd Hoffmann
{
1411 c78f7137 Gerd Hoffmann
    DisplayState *s = con->ds;
1412 7c20b4a3 Gerd Hoffmann
    struct DisplayChangeListener *dcl;
1413 7c20b4a3 Gerd Hoffmann
    QLIST_FOREACH(dcl, &s->listeners, next) {
1414 7c20b4a3 Gerd Hoffmann
        if (dcl->ops->dpy_text_update) {
1415 bc2ed970 Gerd Hoffmann
            dcl->ops->dpy_text_update(dcl, x, y, w, h);
1416 7c20b4a3 Gerd Hoffmann
        }
1417 7c20b4a3 Gerd Hoffmann
    }
1418 7c20b4a3 Gerd Hoffmann
}
1419 7c20b4a3 Gerd Hoffmann
1420 c78f7137 Gerd Hoffmann
void dpy_text_resize(QemuConsole *con, int w, int h)
1421 7c20b4a3 Gerd Hoffmann
{
1422 c78f7137 Gerd Hoffmann
    DisplayState *s = con->ds;
1423 7c20b4a3 Gerd Hoffmann
    struct DisplayChangeListener *dcl;
1424 7c20b4a3 Gerd Hoffmann
    QLIST_FOREACH(dcl, &s->listeners, next) {
1425 7c20b4a3 Gerd Hoffmann
        if (dcl->ops->dpy_text_resize) {
1426 bc2ed970 Gerd Hoffmann
            dcl->ops->dpy_text_resize(dcl, w, h);
1427 7c20b4a3 Gerd Hoffmann
        }
1428 7c20b4a3 Gerd Hoffmann
    }
1429 7c20b4a3 Gerd Hoffmann
}
1430 7c20b4a3 Gerd Hoffmann
1431 c78f7137 Gerd Hoffmann
void dpy_mouse_set(QemuConsole *con, int x, int y, int on)
1432 7c20b4a3 Gerd Hoffmann
{
1433 c78f7137 Gerd Hoffmann
    DisplayState *s = con->ds;
1434 7c20b4a3 Gerd Hoffmann
    struct DisplayChangeListener *dcl;
1435 7c20b4a3 Gerd Hoffmann
    QLIST_FOREACH(dcl, &s->listeners, next) {
1436 7c20b4a3 Gerd Hoffmann
        if (dcl->ops->dpy_mouse_set) {
1437 bc2ed970 Gerd Hoffmann
            dcl->ops->dpy_mouse_set(dcl, x, y, on);
1438 7c20b4a3 Gerd Hoffmann
        }
1439 7c20b4a3 Gerd Hoffmann
    }
1440 7c20b4a3 Gerd Hoffmann
}
1441 7c20b4a3 Gerd Hoffmann
1442 c78f7137 Gerd Hoffmann
void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor)
1443 7c20b4a3 Gerd Hoffmann
{
1444 c78f7137 Gerd Hoffmann
    DisplayState *s = con->ds;
1445 7c20b4a3 Gerd Hoffmann
    struct DisplayChangeListener *dcl;
1446 7c20b4a3 Gerd Hoffmann
    QLIST_FOREACH(dcl, &s->listeners, next) {
1447 7c20b4a3 Gerd Hoffmann
        if (dcl->ops->dpy_cursor_define) {
1448 bc2ed970 Gerd Hoffmann
            dcl->ops->dpy_cursor_define(dcl, cursor);
1449 7c20b4a3 Gerd Hoffmann
        }
1450 7c20b4a3 Gerd Hoffmann
    }
1451 7c20b4a3 Gerd Hoffmann
}
1452 7c20b4a3 Gerd Hoffmann
1453 c78f7137 Gerd Hoffmann
bool dpy_cursor_define_supported(QemuConsole *con)
1454 7c20b4a3 Gerd Hoffmann
{
1455 c78f7137 Gerd Hoffmann
    DisplayState *s = con->ds;
1456 7c20b4a3 Gerd Hoffmann
    struct DisplayChangeListener *dcl;
1457 7c20b4a3 Gerd Hoffmann
    QLIST_FOREACH(dcl, &s->listeners, next) {
1458 7c20b4a3 Gerd Hoffmann
        if (dcl->ops->dpy_cursor_define) {
1459 7c20b4a3 Gerd Hoffmann
            return true;
1460 7c20b4a3 Gerd Hoffmann
        }
1461 7c20b4a3 Gerd Hoffmann
    }
1462 7c20b4a3 Gerd Hoffmann
    return false;
1463 7c20b4a3 Gerd Hoffmann
}
1464 7c20b4a3 Gerd Hoffmann
1465 98b50080 Paolo Bonzini
static void dumb_display_init(void)
1466 98b50080 Paolo Bonzini
{
1467 7267c094 Anthony Liguori
    DisplayState *ds = g_malloc0(sizeof(DisplayState));
1468 1802651c Jan Kiszka
    int width = 640;
1469 1802651c Jan Kiszka
    int height = 480;
1470 1802651c Jan Kiszka
1471 1802651c Jan Kiszka
    if (is_fixedsize_console()) {
1472 1802651c Jan Kiszka
        width = active_console->g_width;
1473 1802651c Jan Kiszka
        height = active_console->g_height;
1474 1802651c Jan Kiszka
    }
1475 c78f7137 Gerd Hoffmann
    ds->surface = qemu_create_displaysurface(width, height);
1476 da229ef3 Gerd Hoffmann
1477 98b50080 Paolo Bonzini
    register_displaystate(ds);
1478 98b50080 Paolo Bonzini
}
1479 98b50080 Paolo Bonzini
1480 98b50080 Paolo Bonzini
/***********************************************************/
1481 98b50080 Paolo Bonzini
/* register display */
1482 98b50080 Paolo Bonzini
1483 98b50080 Paolo Bonzini
void register_displaystate(DisplayState *ds)
1484 98b50080 Paolo Bonzini
{
1485 98b50080 Paolo Bonzini
    DisplayState **s;
1486 98b50080 Paolo Bonzini
    s = &display_state;
1487 98b50080 Paolo Bonzini
    while (*s != NULL)
1488 98b50080 Paolo Bonzini
        s = &(*s)->next;
1489 98b50080 Paolo Bonzini
    ds->next = NULL;
1490 98b50080 Paolo Bonzini
    *s = ds;
1491 98b50080 Paolo Bonzini
}
1492 98b50080 Paolo Bonzini
1493 98b50080 Paolo Bonzini
DisplayState *get_displaystate(void)
1494 98b50080 Paolo Bonzini
{
1495 98b50080 Paolo Bonzini
    if (!display_state) {
1496 98b50080 Paolo Bonzini
        dumb_display_init ();
1497 98b50080 Paolo Bonzini
    }
1498 98b50080 Paolo Bonzini
    return display_state;
1499 98b50080 Paolo Bonzini
}
1500 98b50080 Paolo Bonzini
1501 c78f7137 Gerd Hoffmann
QemuConsole *graphic_console_init(vga_hw_update_ptr update,
1502 c78f7137 Gerd Hoffmann
                                  vga_hw_invalidate_ptr invalidate,
1503 c78f7137 Gerd Hoffmann
                                  vga_hw_screen_dump_ptr screen_dump,
1504 c78f7137 Gerd Hoffmann
                                  vga_hw_text_update_ptr text_update,
1505 c78f7137 Gerd Hoffmann
                                  void *opaque)
1506 95219897 pbrook
{
1507 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1508 3023f332 aliguori
    DisplayState *ds;
1509 f0f2f976 aurel32
1510 7267c094 Anthony Liguori
    ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
1511 af3a9031 ths
    s = new_console(ds, GRAPHIC_CONSOLE);
1512 95219897 pbrook
    s->hw_update = update;
1513 95219897 pbrook
    s->hw_invalidate = invalidate;
1514 95219897 pbrook
    s->hw_screen_dump = screen_dump;
1515 4d3b6f6e balrog
    s->hw_text_update = text_update;
1516 95219897 pbrook
    s->hw = opaque;
1517 3023f332 aliguori
1518 c78f7137 Gerd Hoffmann
    ds->surface = qemu_create_displaysurface(640, 480);
1519 da229ef3 Gerd Hoffmann
1520 f0f2f976 aurel32
    register_displaystate(ds);
1521 c78f7137 Gerd Hoffmann
    return s;
1522 e7f0ad58 bellard
}
1523 e7f0ad58 bellard
1524 95219897 pbrook
int is_graphic_console(void)
1525 e7f0ad58 bellard
{
1526 4d3b6f6e balrog
    return active_console && active_console->console_type == GRAPHIC_CONSOLE;
1527 e7f0ad58 bellard
}
1528 e7f0ad58 bellard
1529 c21bbcfa balrog
int is_fixedsize_console(void)
1530 c21bbcfa balrog
{
1531 c21bbcfa balrog
    return active_console && active_console->console_type != TEXT_CONSOLE;
1532 c21bbcfa balrog
}
1533 c21bbcfa balrog
1534 4104833f Paolo Bonzini
static void text_console_set_echo(CharDriverState *chr, bool echo)
1535 4104833f Paolo Bonzini
{
1536 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = chr->opaque;
1537 4104833f Paolo Bonzini
1538 4104833f Paolo Bonzini
    s->echo = echo;
1539 4104833f Paolo Bonzini
}
1540 4104833f Paolo Bonzini
1541 bf1bed81 Jan Kiszka
static void text_console_update_cursor(void *opaque)
1542 bf1bed81 Jan Kiszka
{
1543 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = opaque;
1544 bf1bed81 Jan Kiszka
1545 bf1bed81 Jan Kiszka
    s->cursor_visible_phase = !s->cursor_visible_phase;
1546 bf1bed81 Jan Kiszka
    vga_hw_invalidate();
1547 bf1bed81 Jan Kiszka
    qemu_mod_timer(s->cursor_timer,
1548 bf1bed81 Jan Kiszka
                   qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
1549 bf1bed81 Jan Kiszka
}
1550 bf1bed81 Jan Kiszka
1551 44b37b93 Paolo Bonzini
static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
1552 e7f0ad58 bellard
{
1553 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1554 6d6f7c28 pbrook
1555 491e114a Paolo Bonzini
    s = chr->opaque;
1556 6ea314d9 Gerd Hoffmann
1557 e7f0ad58 bellard
    chr->chr_write = console_puts;
1558 6fcfafb7 bellard
1559 e15d7371 bellard
    s->out_fifo.buf = s->out_fifo_buf;
1560 e15d7371 bellard
    s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
1561 7bd427d8 Paolo Bonzini
    s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s);
1562 3023f332 aliguori
    s->ds = ds;
1563 3b46e624 ths
1564 e7f0ad58 bellard
    s->y_displayed = 0;
1565 e7f0ad58 bellard
    s->y_base = 0;
1566 e7f0ad58 bellard
    s->total_height = DEFAULT_BACKSCROLL;
1567 e7f0ad58 bellard
    s->x = 0;
1568 e7f0ad58 bellard
    s->y = 0;
1569 491e114a Paolo Bonzini
    if (s->console_type == TEXT_CONSOLE) {
1570 1562e531 Gerd Hoffmann
        s->g_width = surface_width(s->ds->surface);
1571 1562e531 Gerd Hoffmann
        s->g_height = surface_height(s->ds->surface);
1572 491e114a Paolo Bonzini
    }
1573 6d6f7c28 pbrook
1574 bf1bed81 Jan Kiszka
    s->cursor_timer =
1575 bf1bed81 Jan Kiszka
        qemu_new_timer_ms(rt_clock, text_console_update_cursor, s);
1576 bf1bed81 Jan Kiszka
1577 4d3b6f6e balrog
    s->hw_invalidate = text_console_invalidate;
1578 4d3b6f6e balrog
    s->hw_text_update = text_console_update;
1579 4d3b6f6e balrog
    s->hw = s;
1580 4d3b6f6e balrog
1581 6d6f7c28 pbrook
    /* Set text attribute defaults */
1582 6d6f7c28 pbrook
    s->t_attrib_default.bold = 0;
1583 6d6f7c28 pbrook
    s->t_attrib_default.uline = 0;
1584 6d6f7c28 pbrook
    s->t_attrib_default.blink = 0;
1585 6d6f7c28 pbrook
    s->t_attrib_default.invers = 0;
1586 6d6f7c28 pbrook
    s->t_attrib_default.unvisible = 0;
1587 6d6f7c28 pbrook
    s->t_attrib_default.fgcol = COLOR_WHITE;
1588 6d6f7c28 pbrook
    s->t_attrib_default.bgcol = COLOR_BLACK;
1589 6d6f7c28 pbrook
    /* set current text attributes to default */
1590 6d6f7c28 pbrook
    s->t_attrib = s->t_attrib_default;
1591 e7f0ad58 bellard
    text_console_resize(s);
1592 e7f0ad58 bellard
1593 51bfa4d3 Gerd Hoffmann
    if (chr->label) {
1594 51bfa4d3 Gerd Hoffmann
        char msg[128];
1595 51bfa4d3 Gerd Hoffmann
        int len;
1596 51bfa4d3 Gerd Hoffmann
1597 735ba588 Gerd Hoffmann
        s->t_attrib.bgcol = COLOR_BLUE;
1598 51bfa4d3 Gerd Hoffmann
        len = snprintf(msg, sizeof(msg), "%s console\r\n", chr->label);
1599 51bfa4d3 Gerd Hoffmann
        console_puts(chr, (uint8_t*)msg, len);
1600 735ba588 Gerd Hoffmann
        s->t_attrib = s->t_attrib_default;
1601 51bfa4d3 Gerd Hoffmann
    }
1602 51bfa4d3 Gerd Hoffmann
1603 fee204fd Hans de Goede
    qemu_chr_be_generic_open(chr);
1604 ceecf1d1 aurel32
    if (chr->init)
1605 ceecf1d1 aurel32
        chr->init(chr);
1606 e7f0ad58 bellard
}
1607 c60e08d9 pbrook
1608 702ec69c Gerd Hoffmann
static CharDriverState *text_console_init(ChardevVC *vc)
1609 2796dae0 aliguori
{
1610 2796dae0 aliguori
    CharDriverState *chr;
1611 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1612 702ec69c Gerd Hoffmann
    unsigned width = 0;
1613 702ec69c Gerd Hoffmann
    unsigned height = 0;
1614 2796dae0 aliguori
1615 7267c094 Anthony Liguori
    chr = g_malloc0(sizeof(CharDriverState));
1616 2796dae0 aliguori
1617 702ec69c Gerd Hoffmann
    if (vc->has_width) {
1618 702ec69c Gerd Hoffmann
        width = vc->width;
1619 702ec69c Gerd Hoffmann
    } else if (vc->has_cols) {
1620 702ec69c Gerd Hoffmann
        width = vc->cols * FONT_WIDTH;
1621 702ec69c Gerd Hoffmann
    }
1622 491e114a Paolo Bonzini
1623 702ec69c Gerd Hoffmann
    if (vc->has_height) {
1624 702ec69c Gerd Hoffmann
        height = vc->height;
1625 702ec69c Gerd Hoffmann
    } else if (vc->has_rows) {
1626 702ec69c Gerd Hoffmann
        height = vc->rows * FONT_HEIGHT;
1627 702ec69c Gerd Hoffmann
    }
1628 491e114a Paolo Bonzini
1629 491e114a Paolo Bonzini
    if (width == 0 || height == 0) {
1630 491e114a Paolo Bonzini
        s = new_console(NULL, TEXT_CONSOLE);
1631 491e114a Paolo Bonzini
    } else {
1632 491e114a Paolo Bonzini
        s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE);
1633 491e114a Paolo Bonzini
    }
1634 491e114a Paolo Bonzini
1635 491e114a Paolo Bonzini
    if (!s) {
1636 5354d083 Stefan Weil
        g_free(chr);
1637 1f51470d Markus Armbruster
        return NULL;
1638 491e114a Paolo Bonzini
    }
1639 491e114a Paolo Bonzini
1640 491e114a Paolo Bonzini
    s->chr = chr;
1641 491e114a Paolo Bonzini
    s->g_width = width;
1642 491e114a Paolo Bonzini
    s->g_height = height;
1643 491e114a Paolo Bonzini
    chr->opaque = s;
1644 4104833f Paolo Bonzini
    chr->chr_set_echo = text_console_set_echo;
1645 1f51470d Markus Armbruster
    return chr;
1646 2796dae0 aliguori
}
1647 2796dae0 aliguori
1648 d82831db Anthony Liguori
static VcHandler *vc_handler = text_console_init;
1649 d82831db Anthony Liguori
1650 702ec69c Gerd Hoffmann
CharDriverState *vc_init(ChardevVC *vc)
1651 d82831db Anthony Liguori
{
1652 702ec69c Gerd Hoffmann
    return vc_handler(vc);
1653 d82831db Anthony Liguori
}
1654 d82831db Anthony Liguori
1655 d82831db Anthony Liguori
void register_vc_handler(VcHandler *handler)
1656 d82831db Anthony Liguori
{
1657 d82831db Anthony Liguori
    vc_handler = handler;
1658 d82831db Anthony Liguori
}
1659 d82831db Anthony Liguori
1660 2796dae0 aliguori
void text_consoles_set_display(DisplayState *ds)
1661 2796dae0 aliguori
{
1662 2796dae0 aliguori
    int i;
1663 2796dae0 aliguori
1664 8811e1e1 Markus Armbruster
    for (i = 0; i < nb_consoles; i++) {
1665 8811e1e1 Markus Armbruster
        if (consoles[i]->console_type != GRAPHIC_CONSOLE) {
1666 8811e1e1 Markus Armbruster
            text_console_do_init(consoles[i]->chr, ds);
1667 8811e1e1 Markus Armbruster
        }
1668 2796dae0 aliguori
    }
1669 2796dae0 aliguori
}
1670 2796dae0 aliguori
1671 c78f7137 Gerd Hoffmann
void qemu_console_resize(QemuConsole *s, int width, int height)
1672 c60e08d9 pbrook
{
1673 3023f332 aliguori
    s->g_width = width;
1674 3023f332 aliguori
    s->g_height = height;
1675 3023f332 aliguori
    if (is_graphic_console()) {
1676 da229ef3 Gerd Hoffmann
        DisplaySurface *surface;
1677 da229ef3 Gerd Hoffmann
        surface = qemu_create_displaysurface(width, height);
1678 c78f7137 Gerd Hoffmann
        dpy_gfx_replace_surface(s, surface);
1679 c60e08d9 pbrook
    }
1680 c60e08d9 pbrook
}
1681 38334f76 balrog
1682 c78f7137 Gerd Hoffmann
void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
1683 3023f332 aliguori
                       int dst_x, int dst_y, int w, int h)
1684 c21bbcfa balrog
{
1685 3023f332 aliguori
    if (is_graphic_console()) {
1686 c78f7137 Gerd Hoffmann
        dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
1687 38334f76 balrog
    }
1688 38334f76 balrog
}
1689 7d957bd8 aliguori
1690 c78f7137 Gerd Hoffmann
DisplaySurface *qemu_console_surface(QemuConsole *console)
1691 c78f7137 Gerd Hoffmann
{
1692 c78f7137 Gerd Hoffmann
    return console->ds->surface;
1693 c78f7137 Gerd Hoffmann
}
1694 c78f7137 Gerd Hoffmann
1695 c78f7137 Gerd Hoffmann
DisplayState *qemu_console_displaystate(QemuConsole *console)
1696 c78f7137 Gerd Hoffmann
{
1697 c78f7137 Gerd Hoffmann
    return console->ds;
1698 c78f7137 Gerd Hoffmann
}
1699 c78f7137 Gerd Hoffmann
1700 0da2ea1b malc
PixelFormat qemu_different_endianness_pixelformat(int bpp)
1701 7d957bd8 aliguori
{
1702 7d957bd8 aliguori
    PixelFormat pf;
1703 7d957bd8 aliguori
1704 7d957bd8 aliguori
    memset(&pf, 0x00, sizeof(PixelFormat));
1705 7d957bd8 aliguori
1706 7d957bd8 aliguori
    pf.bits_per_pixel = bpp;
1707 feadf1a4 BALATON Zoltan
    pf.bytes_per_pixel = DIV_ROUND_UP(bpp, 8);
1708 7d957bd8 aliguori
    pf.depth = bpp == 32 ? 24 : bpp;
1709 7d957bd8 aliguori
1710 7d957bd8 aliguori
    switch (bpp) {
1711 0da2ea1b malc
        case 24:
1712 0da2ea1b malc
            pf.rmask = 0x000000FF;
1713 0da2ea1b malc
            pf.gmask = 0x0000FF00;
1714 0da2ea1b malc
            pf.bmask = 0x00FF0000;
1715 0da2ea1b malc
            pf.rmax = 255;
1716 0da2ea1b malc
            pf.gmax = 255;
1717 0da2ea1b malc
            pf.bmax = 255;
1718 0da2ea1b malc
            pf.rshift = 0;
1719 0da2ea1b malc
            pf.gshift = 8;
1720 0da2ea1b malc
            pf.bshift = 16;
1721 90a1e3c0 aliguori
            pf.rbits = 8;
1722 90a1e3c0 aliguori
            pf.gbits = 8;
1723 90a1e3c0 aliguori
            pf.bbits = 8;
1724 7d957bd8 aliguori
            break;
1725 0da2ea1b malc
        case 32:
1726 0da2ea1b malc
            pf.rmask = 0x0000FF00;
1727 0da2ea1b malc
            pf.gmask = 0x00FF0000;
1728 0da2ea1b malc
            pf.bmask = 0xFF000000;
1729 0da2ea1b malc
            pf.amask = 0x00000000;
1730 0da2ea1b malc
            pf.amax = 255;
1731 0da2ea1b malc
            pf.rmax = 255;
1732 0da2ea1b malc
            pf.gmax = 255;
1733 0da2ea1b malc
            pf.bmax = 255;
1734 0da2ea1b malc
            pf.ashift = 0;
1735 0da2ea1b malc
            pf.rshift = 8;
1736 0da2ea1b malc
            pf.gshift = 16;
1737 0da2ea1b malc
            pf.bshift = 24;
1738 90a1e3c0 aliguori
            pf.rbits = 8;
1739 90a1e3c0 aliguori
            pf.gbits = 8;
1740 90a1e3c0 aliguori
            pf.bbits = 8;
1741 90a1e3c0 aliguori
            pf.abits = 8;
1742 0da2ea1b malc
            break;
1743 0da2ea1b malc
        default:
1744 0da2ea1b malc
            break;
1745 0da2ea1b malc
    }
1746 0da2ea1b malc
    return pf;
1747 0da2ea1b malc
}
1748 0da2ea1b malc
1749 0da2ea1b malc
PixelFormat qemu_default_pixelformat(int bpp)
1750 0da2ea1b malc
{
1751 0da2ea1b malc
    PixelFormat pf;
1752 0da2ea1b malc
1753 0da2ea1b malc
    memset(&pf, 0x00, sizeof(PixelFormat));
1754 0da2ea1b malc
1755 0da2ea1b malc
    pf.bits_per_pixel = bpp;
1756 feadf1a4 BALATON Zoltan
    pf.bytes_per_pixel = DIV_ROUND_UP(bpp, 8);
1757 0da2ea1b malc
    pf.depth = bpp == 32 ? 24 : bpp;
1758 0da2ea1b malc
1759 0da2ea1b malc
    switch (bpp) {
1760 b6278084 Gerd Hoffmann
        case 15:
1761 b6278084 Gerd Hoffmann
            pf.bits_per_pixel = 16;
1762 b6278084 Gerd Hoffmann
            pf.rmask = 0x00007c00;
1763 b6278084 Gerd Hoffmann
            pf.gmask = 0x000003E0;
1764 b6278084 Gerd Hoffmann
            pf.bmask = 0x0000001F;
1765 b6278084 Gerd Hoffmann
            pf.rmax = 31;
1766 b6278084 Gerd Hoffmann
            pf.gmax = 31;
1767 b6278084 Gerd Hoffmann
            pf.bmax = 31;
1768 b6278084 Gerd Hoffmann
            pf.rshift = 10;
1769 b6278084 Gerd Hoffmann
            pf.gshift = 5;
1770 b6278084 Gerd Hoffmann
            pf.bshift = 0;
1771 b6278084 Gerd Hoffmann
            pf.rbits = 5;
1772 b6278084 Gerd Hoffmann
            pf.gbits = 5;
1773 b6278084 Gerd Hoffmann
            pf.bbits = 5;
1774 b6278084 Gerd Hoffmann
            break;
1775 7d957bd8 aliguori
        case 16:
1776 7d957bd8 aliguori
            pf.rmask = 0x0000F800;
1777 7d957bd8 aliguori
            pf.gmask = 0x000007E0;
1778 7d957bd8 aliguori
            pf.bmask = 0x0000001F;
1779 7d957bd8 aliguori
            pf.rmax = 31;
1780 7d957bd8 aliguori
            pf.gmax = 63;
1781 7d957bd8 aliguori
            pf.bmax = 31;
1782 7d957bd8 aliguori
            pf.rshift = 11;
1783 7d957bd8 aliguori
            pf.gshift = 5;
1784 7d957bd8 aliguori
            pf.bshift = 0;
1785 90a1e3c0 aliguori
            pf.rbits = 5;
1786 90a1e3c0 aliguori
            pf.gbits = 6;
1787 90a1e3c0 aliguori
            pf.bbits = 5;
1788 7d957bd8 aliguori
            break;
1789 7d957bd8 aliguori
        case 24:
1790 0da2ea1b malc
            pf.rmask = 0x00FF0000;
1791 0da2ea1b malc
            pf.gmask = 0x0000FF00;
1792 0da2ea1b malc
            pf.bmask = 0x000000FF;
1793 0da2ea1b malc
            pf.rmax = 255;
1794 0da2ea1b malc
            pf.gmax = 255;
1795 0da2ea1b malc
            pf.bmax = 255;
1796 0da2ea1b malc
            pf.rshift = 16;
1797 0da2ea1b malc
            pf.gshift = 8;
1798 0da2ea1b malc
            pf.bshift = 0;
1799 90a1e3c0 aliguori
            pf.rbits = 8;
1800 90a1e3c0 aliguori
            pf.gbits = 8;
1801 90a1e3c0 aliguori
            pf.bbits = 8;
1802 0eba62e0 Markus Armbruster
            break;
1803 7d957bd8 aliguori
        case 32:
1804 7d957bd8 aliguori
            pf.rmask = 0x00FF0000;
1805 7d957bd8 aliguori
            pf.gmask = 0x0000FF00;
1806 7d957bd8 aliguori
            pf.bmask = 0x000000FF;
1807 7d957bd8 aliguori
            pf.rmax = 255;
1808 7d957bd8 aliguori
            pf.gmax = 255;
1809 7d957bd8 aliguori
            pf.bmax = 255;
1810 7d957bd8 aliguori
            pf.rshift = 16;
1811 7d957bd8 aliguori
            pf.gshift = 8;
1812 7d957bd8 aliguori
            pf.bshift = 0;
1813 90a1e3c0 aliguori
            pf.rbits = 8;
1814 90a1e3c0 aliguori
            pf.gbits = 8;
1815 90a1e3c0 aliguori
            pf.bbits = 8;
1816 7d957bd8 aliguori
            break;
1817 7d957bd8 aliguori
        default:
1818 7d957bd8 aliguori
            break;
1819 7d957bd8 aliguori
    }
1820 7d957bd8 aliguori
    return pf;
1821 7d957bd8 aliguori
}
1822 01f45d98 Anthony Liguori
1823 702ec69c Gerd Hoffmann
static void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend,
1824 702ec69c Gerd Hoffmann
                              Error **errp)
1825 702ec69c Gerd Hoffmann
{
1826 702ec69c Gerd Hoffmann
    int val;
1827 702ec69c Gerd Hoffmann
1828 702ec69c Gerd Hoffmann
    backend->vc = g_new0(ChardevVC, 1);
1829 702ec69c Gerd Hoffmann
1830 702ec69c Gerd Hoffmann
    val = qemu_opt_get_number(opts, "width", 0);
1831 702ec69c Gerd Hoffmann
    if (val != 0) {
1832 702ec69c Gerd Hoffmann
        backend->vc->has_width = true;
1833 702ec69c Gerd Hoffmann
        backend->vc->width = val;
1834 702ec69c Gerd Hoffmann
    }
1835 702ec69c Gerd Hoffmann
1836 702ec69c Gerd Hoffmann
    val = qemu_opt_get_number(opts, "height", 0);
1837 702ec69c Gerd Hoffmann
    if (val != 0) {
1838 702ec69c Gerd Hoffmann
        backend->vc->has_height = true;
1839 702ec69c Gerd Hoffmann
        backend->vc->height = val;
1840 702ec69c Gerd Hoffmann
    }
1841 702ec69c Gerd Hoffmann
1842 702ec69c Gerd Hoffmann
    val = qemu_opt_get_number(opts, "cols", 0);
1843 702ec69c Gerd Hoffmann
    if (val != 0) {
1844 702ec69c Gerd Hoffmann
        backend->vc->has_cols = true;
1845 702ec69c Gerd Hoffmann
        backend->vc->cols = val;
1846 702ec69c Gerd Hoffmann
    }
1847 702ec69c Gerd Hoffmann
1848 702ec69c Gerd Hoffmann
    val = qemu_opt_get_number(opts, "rows", 0);
1849 702ec69c Gerd Hoffmann
    if (val != 0) {
1850 702ec69c Gerd Hoffmann
        backend->vc->has_rows = true;
1851 702ec69c Gerd Hoffmann
        backend->vc->rows = val;
1852 702ec69c Gerd Hoffmann
    }
1853 702ec69c Gerd Hoffmann
}
1854 702ec69c Gerd Hoffmann
1855 01f45d98 Anthony Liguori
static void register_types(void)
1856 01f45d98 Anthony Liguori
{
1857 702ec69c Gerd Hoffmann
    register_char_driver_qapi("vc", CHARDEV_BACKEND_KIND_VC,
1858 702ec69c Gerd Hoffmann
                              qemu_chr_parse_vc);
1859 01f45d98 Anthony Liguori
}
1860 01f45d98 Anthony Liguori
1861 01f45d98 Anthony Liguori
type_init(register_types);