Statistics
| Branch: | Revision:

root / ui / console.c @ 396d2cfc

History | View | Annotate | Download (47.2 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 927d4878 Paolo Bonzini
#include "char/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 ad39cf6d Luiz Capitulino
        error_setg(errp, "device doesn't support screendump\n");
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 e7f0ad58 bellard
/* convert a RGBA color to a color index usable in graphic primitives */
212 e7f0ad58 bellard
static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
213 e7f0ad58 bellard
{
214 e7f0ad58 bellard
    unsigned int r, g, b, color;
215 e7f0ad58 bellard
216 0e1f5a0c aliguori
    switch(ds_get_bits_per_pixel(ds)) {
217 e7f0ad58 bellard
#if 0
218 e7f0ad58 bellard
    case 8:
219 e7f0ad58 bellard
        r = (rgba >> 16) & 0xff;
220 e7f0ad58 bellard
        g = (rgba >> 8) & 0xff;
221 e7f0ad58 bellard
        b = (rgba) & 0xff;
222 5fafdf24 ths
        color = (rgb_to_index[r] * 6 * 6) +
223 5fafdf24 ths
            (rgb_to_index[g] * 6) +
224 e7f0ad58 bellard
            (rgb_to_index[b]);
225 e7f0ad58 bellard
        break;
226 e7f0ad58 bellard
#endif
227 e7f0ad58 bellard
    case 15:
228 e7f0ad58 bellard
        r = (rgba >> 16) & 0xff;
229 e7f0ad58 bellard
        g = (rgba >> 8) & 0xff;
230 e7f0ad58 bellard
        b = (rgba) & 0xff;
231 e7f0ad58 bellard
        color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
232 e7f0ad58 bellard
        break;
233 e7f0ad58 bellard
    case 16:
234 e7f0ad58 bellard
        r = (rgba >> 16) & 0xff;
235 e7f0ad58 bellard
        g = (rgba >> 8) & 0xff;
236 e7f0ad58 bellard
        b = (rgba) & 0xff;
237 e7f0ad58 bellard
        color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
238 e7f0ad58 bellard
        break;
239 e7f0ad58 bellard
    case 32:
240 e7f0ad58 bellard
    default:
241 e7f0ad58 bellard
        color = rgba;
242 e7f0ad58 bellard
        break;
243 e7f0ad58 bellard
    }
244 e7f0ad58 bellard
    return color;
245 e7f0ad58 bellard
}
246 e7f0ad58 bellard
247 5fafdf24 ths
static void vga_fill_rect (DisplayState *ds,
248 e7f0ad58 bellard
                           int posx, int posy, int width, int height, uint32_t color)
249 e7f0ad58 bellard
{
250 e7f0ad58 bellard
    uint8_t *d, *d1;
251 e7f0ad58 bellard
    int x, y, bpp;
252 3b46e624 ths
253 0e1f5a0c aliguori
    bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
254 0e1f5a0c aliguori
    d1 = ds_get_data(ds) +
255 0e1f5a0c aliguori
        ds_get_linesize(ds) * posy + bpp * posx;
256 e7f0ad58 bellard
    for (y = 0; y < height; y++) {
257 e7f0ad58 bellard
        d = d1;
258 e7f0ad58 bellard
        switch(bpp) {
259 e7f0ad58 bellard
        case 1:
260 e7f0ad58 bellard
            for (x = 0; x < width; x++) {
261 e7f0ad58 bellard
                *((uint8_t *)d) = color;
262 e7f0ad58 bellard
                d++;
263 e7f0ad58 bellard
            }
264 e7f0ad58 bellard
            break;
265 e7f0ad58 bellard
        case 2:
266 e7f0ad58 bellard
            for (x = 0; x < width; x++) {
267 e7f0ad58 bellard
                *((uint16_t *)d) = color;
268 e7f0ad58 bellard
                d += 2;
269 e7f0ad58 bellard
            }
270 e7f0ad58 bellard
            break;
271 e7f0ad58 bellard
        case 4:
272 e7f0ad58 bellard
            for (x = 0; x < width; x++) {
273 e7f0ad58 bellard
                *((uint32_t *)d) = color;
274 e7f0ad58 bellard
                d += 4;
275 e7f0ad58 bellard
            }
276 e7f0ad58 bellard
            break;
277 e7f0ad58 bellard
        }
278 0e1f5a0c aliguori
        d1 += ds_get_linesize(ds);
279 e7f0ad58 bellard
    }
280 e7f0ad58 bellard
}
281 e7f0ad58 bellard
282 e7f0ad58 bellard
/* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
283 e7f0ad58 bellard
static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h)
284 e7f0ad58 bellard
{
285 e7f0ad58 bellard
    const uint8_t *s;
286 e7f0ad58 bellard
    uint8_t *d;
287 e7f0ad58 bellard
    int wb, y, bpp;
288 e7f0ad58 bellard
289 0e1f5a0c aliguori
    bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
290 e7f0ad58 bellard
    wb = w * bpp;
291 e7f0ad58 bellard
    if (yd <= ys) {
292 0e1f5a0c aliguori
        s = ds_get_data(ds) +
293 0e1f5a0c aliguori
            ds_get_linesize(ds) * ys + bpp * xs;
294 0e1f5a0c aliguori
        d = ds_get_data(ds) +
295 0e1f5a0c aliguori
            ds_get_linesize(ds) * yd + bpp * xd;
296 e7f0ad58 bellard
        for (y = 0; y < h; y++) {
297 e7f0ad58 bellard
            memmove(d, s, wb);
298 0e1f5a0c aliguori
            d += ds_get_linesize(ds);
299 0e1f5a0c aliguori
            s += ds_get_linesize(ds);
300 e7f0ad58 bellard
        }
301 e7f0ad58 bellard
    } else {
302 0e1f5a0c aliguori
        s = ds_get_data(ds) +
303 0e1f5a0c aliguori
            ds_get_linesize(ds) * (ys + h - 1) + bpp * xs;
304 0e1f5a0c aliguori
        d = ds_get_data(ds) +
305 0e1f5a0c aliguori
            ds_get_linesize(ds) * (yd + h - 1) + bpp * xd;
306 e7f0ad58 bellard
       for (y = 0; y < h; y++) {
307 e7f0ad58 bellard
            memmove(d, s, wb);
308 0e1f5a0c aliguori
            d -= ds_get_linesize(ds);
309 0e1f5a0c aliguori
            s -= ds_get_linesize(ds);
310 e7f0ad58 bellard
        }
311 e7f0ad58 bellard
    }
312 e7f0ad58 bellard
}
313 e7f0ad58 bellard
314 e7f0ad58 bellard
/***********************************************************/
315 e7f0ad58 bellard
/* basic char display */
316 e7f0ad58 bellard
317 e7f0ad58 bellard
#define FONT_HEIGHT 16
318 e7f0ad58 bellard
#define FONT_WIDTH 8
319 e7f0ad58 bellard
320 e7f0ad58 bellard
#include "vgafont.h"
321 e7f0ad58 bellard
322 e7f0ad58 bellard
#define cbswap_32(__x) \
323 e7f0ad58 bellard
((uint32_t)( \
324 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
325 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
326 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
327 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
328 e7f0ad58 bellard
329 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
330 e7f0ad58 bellard
#define PAT(x) x
331 e7f0ad58 bellard
#else
332 e7f0ad58 bellard
#define PAT(x) cbswap_32(x)
333 e7f0ad58 bellard
#endif
334 e7f0ad58 bellard
335 e7f0ad58 bellard
static const uint32_t dmask16[16] = {
336 e7f0ad58 bellard
    PAT(0x00000000),
337 e7f0ad58 bellard
    PAT(0x000000ff),
338 e7f0ad58 bellard
    PAT(0x0000ff00),
339 e7f0ad58 bellard
    PAT(0x0000ffff),
340 e7f0ad58 bellard
    PAT(0x00ff0000),
341 e7f0ad58 bellard
    PAT(0x00ff00ff),
342 e7f0ad58 bellard
    PAT(0x00ffff00),
343 e7f0ad58 bellard
    PAT(0x00ffffff),
344 e7f0ad58 bellard
    PAT(0xff000000),
345 e7f0ad58 bellard
    PAT(0xff0000ff),
346 e7f0ad58 bellard
    PAT(0xff00ff00),
347 e7f0ad58 bellard
    PAT(0xff00ffff),
348 e7f0ad58 bellard
    PAT(0xffff0000),
349 e7f0ad58 bellard
    PAT(0xffff00ff),
350 e7f0ad58 bellard
    PAT(0xffffff00),
351 e7f0ad58 bellard
    PAT(0xffffffff),
352 e7f0ad58 bellard
};
353 e7f0ad58 bellard
354 e7f0ad58 bellard
static const uint32_t dmask4[4] = {
355 e7f0ad58 bellard
    PAT(0x00000000),
356 e7f0ad58 bellard
    PAT(0x0000ffff),
357 e7f0ad58 bellard
    PAT(0xffff0000),
358 e7f0ad58 bellard
    PAT(0xffffffff),
359 e7f0ad58 bellard
};
360 e7f0ad58 bellard
361 6d6f7c28 pbrook
static uint32_t color_table[2][8];
362 6d6f7c28 pbrook
363 df00bed0 Devin J. Pohly
#ifndef CONFIG_CURSES
364 6d6f7c28 pbrook
enum color_names {
365 6d6f7c28 pbrook
    COLOR_BLACK   = 0,
366 6d6f7c28 pbrook
    COLOR_RED     = 1,
367 6d6f7c28 pbrook
    COLOR_GREEN   = 2,
368 6d6f7c28 pbrook
    COLOR_YELLOW  = 3,
369 6d6f7c28 pbrook
    COLOR_BLUE    = 4,
370 6d6f7c28 pbrook
    COLOR_MAGENTA = 5,
371 6d6f7c28 pbrook
    COLOR_CYAN    = 6,
372 6d6f7c28 pbrook
    COLOR_WHITE   = 7
373 6d6f7c28 pbrook
};
374 df00bed0 Devin J. Pohly
#endif
375 6d6f7c28 pbrook
376 6d6f7c28 pbrook
static const uint32_t color_table_rgb[2][8] = {
377 6d6f7c28 pbrook
    {   /* dark */
378 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0x00),  /* black */
379 26489844 bellard
        QEMU_RGB(0xaa, 0x00, 0x00),  /* red */
380 26489844 bellard
        QEMU_RGB(0x00, 0xaa, 0x00),  /* green */
381 26489844 bellard
        QEMU_RGB(0xaa, 0xaa, 0x00),  /* yellow */
382 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0xaa),  /* blue */
383 26489844 bellard
        QEMU_RGB(0xaa, 0x00, 0xaa),  /* magenta */
384 26489844 bellard
        QEMU_RGB(0x00, 0xaa, 0xaa),  /* cyan */
385 26489844 bellard
        QEMU_RGB(0xaa, 0xaa, 0xaa),  /* white */
386 6d6f7c28 pbrook
    },
387 6d6f7c28 pbrook
    {   /* bright */
388 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0x00),  /* black */
389 26489844 bellard
        QEMU_RGB(0xff, 0x00, 0x00),  /* red */
390 26489844 bellard
        QEMU_RGB(0x00, 0xff, 0x00),  /* green */
391 26489844 bellard
        QEMU_RGB(0xff, 0xff, 0x00),  /* yellow */
392 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0xff),  /* blue */
393 26489844 bellard
        QEMU_RGB(0xff, 0x00, 0xff),  /* magenta */
394 26489844 bellard
        QEMU_RGB(0x00, 0xff, 0xff),  /* cyan */
395 26489844 bellard
        QEMU_RGB(0xff, 0xff, 0xff),  /* white */
396 6d6f7c28 pbrook
    }
397 e7f0ad58 bellard
};
398 e7f0ad58 bellard
399 e7f0ad58 bellard
static inline unsigned int col_expand(DisplayState *ds, unsigned int col)
400 e7f0ad58 bellard
{
401 0e1f5a0c aliguori
    switch(ds_get_bits_per_pixel(ds)) {
402 e7f0ad58 bellard
    case 8:
403 e7f0ad58 bellard
        col |= col << 8;
404 e7f0ad58 bellard
        col |= col << 16;
405 e7f0ad58 bellard
        break;
406 e7f0ad58 bellard
    case 15:
407 e7f0ad58 bellard
    case 16:
408 e7f0ad58 bellard
        col |= col << 16;
409 e7f0ad58 bellard
        break;
410 e7f0ad58 bellard
    default:
411 e7f0ad58 bellard
        break;
412 e7f0ad58 bellard
    }
413 e7f0ad58 bellard
414 e7f0ad58 bellard
    return col;
415 e7f0ad58 bellard
}
416 6d6f7c28 pbrook
#ifdef DEBUG_CONSOLE
417 6d6f7c28 pbrook
static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
418 6d6f7c28 pbrook
{
419 6d6f7c28 pbrook
    if (t_attrib->bold) {
420 6d6f7c28 pbrook
        printf("b");
421 6d6f7c28 pbrook
    } else {
422 6d6f7c28 pbrook
        printf(" ");
423 6d6f7c28 pbrook
    }
424 6d6f7c28 pbrook
    if (t_attrib->uline) {
425 6d6f7c28 pbrook
        printf("u");
426 6d6f7c28 pbrook
    } else {
427 6d6f7c28 pbrook
        printf(" ");
428 6d6f7c28 pbrook
    }
429 6d6f7c28 pbrook
    if (t_attrib->blink) {
430 6d6f7c28 pbrook
        printf("l");
431 6d6f7c28 pbrook
    } else {
432 6d6f7c28 pbrook
        printf(" ");
433 6d6f7c28 pbrook
    }
434 6d6f7c28 pbrook
    if (t_attrib->invers) {
435 6d6f7c28 pbrook
        printf("i");
436 6d6f7c28 pbrook
    } else {
437 6d6f7c28 pbrook
        printf(" ");
438 6d6f7c28 pbrook
    }
439 6d6f7c28 pbrook
    if (t_attrib->unvisible) {
440 6d6f7c28 pbrook
        printf("n");
441 6d6f7c28 pbrook
    } else {
442 6d6f7c28 pbrook
        printf(" ");
443 6d6f7c28 pbrook
    }
444 6d6f7c28 pbrook
445 6d6f7c28 pbrook
    printf(" fg: %d bg: %d ch:'%2X' '%c'\n", t_attrib->fgcol, t_attrib->bgcol, ch, ch);
446 6d6f7c28 pbrook
}
447 6d6f7c28 pbrook
#endif
448 e7f0ad58 bellard
449 5fafdf24 ths
static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
450 6d6f7c28 pbrook
                          TextAttributes *t_attrib)
451 e7f0ad58 bellard
{
452 e7f0ad58 bellard
    uint8_t *d;
453 e7f0ad58 bellard
    const uint8_t *font_ptr;
454 e7f0ad58 bellard
    unsigned int font_data, linesize, xorcol, bpp;
455 e7f0ad58 bellard
    int i;
456 6d6f7c28 pbrook
    unsigned int fgcol, bgcol;
457 6d6f7c28 pbrook
458 6d6f7c28 pbrook
#ifdef DEBUG_CONSOLE
459 6d6f7c28 pbrook
    printf("x: %2i y: %2i", x, y);
460 6d6f7c28 pbrook
    console_print_text_attributes(t_attrib, ch);
461 6d6f7c28 pbrook
#endif
462 6d6f7c28 pbrook
463 6d6f7c28 pbrook
    if (t_attrib->invers) {
464 6d6f7c28 pbrook
        bgcol = color_table[t_attrib->bold][t_attrib->fgcol];
465 6d6f7c28 pbrook
        fgcol = color_table[t_attrib->bold][t_attrib->bgcol];
466 6d6f7c28 pbrook
    } else {
467 6d6f7c28 pbrook
        fgcol = color_table[t_attrib->bold][t_attrib->fgcol];
468 6d6f7c28 pbrook
        bgcol = color_table[t_attrib->bold][t_attrib->bgcol];
469 6d6f7c28 pbrook
    }
470 e7f0ad58 bellard
471 0e1f5a0c aliguori
    bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
472 0e1f5a0c aliguori
    d = ds_get_data(ds) +
473 0e1f5a0c aliguori
        ds_get_linesize(ds) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
474 0e1f5a0c aliguori
    linesize = ds_get_linesize(ds);
475 e7f0ad58 bellard
    font_ptr = vgafont16 + FONT_HEIGHT * ch;
476 e7f0ad58 bellard
    xorcol = bgcol ^ fgcol;
477 0e1f5a0c aliguori
    switch(ds_get_bits_per_pixel(ds)) {
478 e7f0ad58 bellard
    case 8:
479 e7f0ad58 bellard
        for(i = 0; i < FONT_HEIGHT; i++) {
480 e7f0ad58 bellard
            font_data = *font_ptr++;
481 6d6f7c28 pbrook
            if (t_attrib->uline
482 6d6f7c28 pbrook
                && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
483 439229c7 Markus Armbruster
                font_data = 0xFF;
484 6d6f7c28 pbrook
            }
485 e7f0ad58 bellard
            ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
486 e7f0ad58 bellard
            ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
487 e7f0ad58 bellard
            d += linesize;
488 e7f0ad58 bellard
        }
489 e7f0ad58 bellard
        break;
490 e7f0ad58 bellard
    case 16:
491 e7f0ad58 bellard
    case 15:
492 e7f0ad58 bellard
        for(i = 0; i < FONT_HEIGHT; i++) {
493 e7f0ad58 bellard
            font_data = *font_ptr++;
494 6d6f7c28 pbrook
            if (t_attrib->uline
495 6d6f7c28 pbrook
                && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
496 439229c7 Markus Armbruster
                font_data = 0xFF;
497 6d6f7c28 pbrook
            }
498 e7f0ad58 bellard
            ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
499 e7f0ad58 bellard
            ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
500 e7f0ad58 bellard
            ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
501 e7f0ad58 bellard
            ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
502 e7f0ad58 bellard
            d += linesize;
503 e7f0ad58 bellard
        }
504 e7f0ad58 bellard
        break;
505 e7f0ad58 bellard
    case 32:
506 e7f0ad58 bellard
        for(i = 0; i < FONT_HEIGHT; i++) {
507 e7f0ad58 bellard
            font_data = *font_ptr++;
508 6d6f7c28 pbrook
            if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
509 439229c7 Markus Armbruster
                font_data = 0xFF;
510 6d6f7c28 pbrook
            }
511 e7f0ad58 bellard
            ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
512 e7f0ad58 bellard
            ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
513 e7f0ad58 bellard
            ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
514 e7f0ad58 bellard
            ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
515 e7f0ad58 bellard
            ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
516 e7f0ad58 bellard
            ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
517 e7f0ad58 bellard
            ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
518 e7f0ad58 bellard
            ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
519 e7f0ad58 bellard
            d += linesize;
520 e7f0ad58 bellard
        }
521 e7f0ad58 bellard
        break;
522 e7f0ad58 bellard
    }
523 e7f0ad58 bellard
}
524 e7f0ad58 bellard
525 76ffb0b4 Gerd Hoffmann
static void text_console_resize(QemuConsole *s)
526 e7f0ad58 bellard
{
527 e7f0ad58 bellard
    TextCell *cells, *c, *c1;
528 e7f0ad58 bellard
    int w1, x, y, last_width;
529 e7f0ad58 bellard
530 e7f0ad58 bellard
    last_width = s->width;
531 e7f0ad58 bellard
    s->width = s->g_width / FONT_WIDTH;
532 e7f0ad58 bellard
    s->height = s->g_height / FONT_HEIGHT;
533 e7f0ad58 bellard
534 e7f0ad58 bellard
    w1 = last_width;
535 e7f0ad58 bellard
    if (s->width < w1)
536 e7f0ad58 bellard
        w1 = s->width;
537 e7f0ad58 bellard
538 7267c094 Anthony Liguori
    cells = g_malloc(s->width * s->total_height * sizeof(TextCell));
539 e7f0ad58 bellard
    for(y = 0; y < s->total_height; y++) {
540 e7f0ad58 bellard
        c = &cells[y * s->width];
541 e7f0ad58 bellard
        if (w1 > 0) {
542 e7f0ad58 bellard
            c1 = &s->cells[y * last_width];
543 e7f0ad58 bellard
            for(x = 0; x < w1; x++) {
544 e7f0ad58 bellard
                *c++ = *c1++;
545 e7f0ad58 bellard
            }
546 e7f0ad58 bellard
        }
547 e7f0ad58 bellard
        for(x = w1; x < s->width; x++) {
548 e7f0ad58 bellard
            c->ch = ' ';
549 6d6f7c28 pbrook
            c->t_attrib = s->t_attrib_default;
550 e7f0ad58 bellard
            c++;
551 e7f0ad58 bellard
        }
552 e7f0ad58 bellard
    }
553 7267c094 Anthony Liguori
    g_free(s->cells);
554 e7f0ad58 bellard
    s->cells = cells;
555 e7f0ad58 bellard
}
556 e7f0ad58 bellard
557 76ffb0b4 Gerd Hoffmann
static inline void text_update_xy(QemuConsole *s, int x, int y)
558 4d3b6f6e balrog
{
559 4d3b6f6e balrog
    s->text_x[0] = MIN(s->text_x[0], x);
560 4d3b6f6e balrog
    s->text_x[1] = MAX(s->text_x[1], x);
561 4d3b6f6e balrog
    s->text_y[0] = MIN(s->text_y[0], y);
562 4d3b6f6e balrog
    s->text_y[1] = MAX(s->text_y[1], y);
563 4d3b6f6e balrog
}
564 4d3b6f6e balrog
565 76ffb0b4 Gerd Hoffmann
static void invalidate_xy(QemuConsole *s, int x, int y)
566 14778c20 pbrook
{
567 14778c20 pbrook
    if (s->update_x0 > x * FONT_WIDTH)
568 14778c20 pbrook
        s->update_x0 = x * FONT_WIDTH;
569 14778c20 pbrook
    if (s->update_y0 > y * FONT_HEIGHT)
570 14778c20 pbrook
        s->update_y0 = y * FONT_HEIGHT;
571 14778c20 pbrook
    if (s->update_x1 < (x + 1) * FONT_WIDTH)
572 14778c20 pbrook
        s->update_x1 = (x + 1) * FONT_WIDTH;
573 14778c20 pbrook
    if (s->update_y1 < (y + 1) * FONT_HEIGHT)
574 14778c20 pbrook
        s->update_y1 = (y + 1) * FONT_HEIGHT;
575 14778c20 pbrook
}
576 14778c20 pbrook
577 76ffb0b4 Gerd Hoffmann
static void update_xy(QemuConsole *s, int x, int y)
578 e7f0ad58 bellard
{
579 e7f0ad58 bellard
    TextCell *c;
580 e7f0ad58 bellard
    int y1, y2;
581 e7f0ad58 bellard
582 e7f0ad58 bellard
    if (s == active_console) {
583 0e1f5a0c aliguori
        if (!ds_get_bits_per_pixel(s->ds)) {
584 4d3b6f6e balrog
            text_update_xy(s, x, y);
585 4d3b6f6e balrog
            return;
586 4d3b6f6e balrog
        }
587 4d3b6f6e balrog
588 e7f0ad58 bellard
        y1 = (s->y_base + y) % s->total_height;
589 e7f0ad58 bellard
        y2 = y1 - s->y_displayed;
590 e7f0ad58 bellard
        if (y2 < 0)
591 e7f0ad58 bellard
            y2 += s->total_height;
592 e7f0ad58 bellard
        if (y2 < s->height) {
593 e7f0ad58 bellard
            c = &s->cells[y1 * s->width + x];
594 5fafdf24 ths
            vga_putcharxy(s->ds, x, y2, c->ch,
595 6d6f7c28 pbrook
                          &(c->t_attrib));
596 14778c20 pbrook
            invalidate_xy(s, x, y2);
597 e7f0ad58 bellard
        }
598 e7f0ad58 bellard
    }
599 e7f0ad58 bellard
}
600 e7f0ad58 bellard
601 76ffb0b4 Gerd Hoffmann
static void console_show_cursor(QemuConsole *s, int show)
602 e7f0ad58 bellard
{
603 e7f0ad58 bellard
    TextCell *c;
604 e7f0ad58 bellard
    int y, y1;
605 e7f0ad58 bellard
606 e7f0ad58 bellard
    if (s == active_console) {
607 ed8276ac ths
        int x = s->x;
608 4d3b6f6e balrog
609 0e1f5a0c aliguori
        if (!ds_get_bits_per_pixel(s->ds)) {
610 4d3b6f6e balrog
            s->cursor_invalidate = 1;
611 4d3b6f6e balrog
            return;
612 4d3b6f6e balrog
        }
613 4d3b6f6e balrog
614 ed8276ac ths
        if (x >= s->width) {
615 ed8276ac ths
            x = s->width - 1;
616 ed8276ac ths
        }
617 e7f0ad58 bellard
        y1 = (s->y_base + s->y) % s->total_height;
618 e7f0ad58 bellard
        y = y1 - s->y_displayed;
619 e7f0ad58 bellard
        if (y < 0)
620 e7f0ad58 bellard
            y += s->total_height;
621 e7f0ad58 bellard
        if (y < s->height) {
622 ed8276ac ths
            c = &s->cells[y1 * s->width + x];
623 bf1bed81 Jan Kiszka
            if (show && s->cursor_visible_phase) {
624 6d6f7c28 pbrook
                TextAttributes t_attrib = s->t_attrib_default;
625 6d6f7c28 pbrook
                t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
626 ed8276ac ths
                vga_putcharxy(s->ds, x, y, c->ch, &t_attrib);
627 e7f0ad58 bellard
            } else {
628 ed8276ac ths
                vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib));
629 e7f0ad58 bellard
            }
630 14778c20 pbrook
            invalidate_xy(s, x, y);
631 e7f0ad58 bellard
        }
632 e7f0ad58 bellard
    }
633 e7f0ad58 bellard
}
634 e7f0ad58 bellard
635 76ffb0b4 Gerd Hoffmann
static void console_refresh(QemuConsole *s)
636 e7f0ad58 bellard
{
637 e7f0ad58 bellard
    TextCell *c;
638 e7f0ad58 bellard
    int x, y, y1;
639 e7f0ad58 bellard
640 5fafdf24 ths
    if (s != active_console)
641 e7f0ad58 bellard
        return;
642 a93a4a22 Gerd Hoffmann
643 a93a4a22 Gerd Hoffmann
    if (s->ds->have_text) {
644 4d3b6f6e balrog
        s->text_x[0] = 0;
645 4d3b6f6e balrog
        s->text_y[0] = 0;
646 4d3b6f6e balrog
        s->text_x[1] = s->width - 1;
647 4d3b6f6e balrog
        s->text_y[1] = s->height - 1;
648 4d3b6f6e balrog
        s->cursor_invalidate = 1;
649 4d3b6f6e balrog
    }
650 e7f0ad58 bellard
651 a93a4a22 Gerd Hoffmann
    if (s->ds->have_gfx) {
652 a93a4a22 Gerd Hoffmann
        vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
653 a93a4a22 Gerd Hoffmann
                      color_table[0][COLOR_BLACK]);
654 a93a4a22 Gerd Hoffmann
        y1 = s->y_displayed;
655 a93a4a22 Gerd Hoffmann
        for (y = 0; y < s->height; y++) {
656 a93a4a22 Gerd Hoffmann
            c = s->cells + y1 * s->width;
657 a93a4a22 Gerd Hoffmann
            for (x = 0; x < s->width; x++) {
658 a93a4a22 Gerd Hoffmann
                vga_putcharxy(s->ds, x, y, c->ch,
659 a93a4a22 Gerd Hoffmann
                              &(c->t_attrib));
660 a93a4a22 Gerd Hoffmann
                c++;
661 a93a4a22 Gerd Hoffmann
            }
662 a93a4a22 Gerd Hoffmann
            if (++y1 == s->total_height) {
663 a93a4a22 Gerd Hoffmann
                y1 = 0;
664 a93a4a22 Gerd Hoffmann
            }
665 e7f0ad58 bellard
        }
666 a93a4a22 Gerd Hoffmann
        console_show_cursor(s, 1);
667 a93a4a22 Gerd Hoffmann
        dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
668 e7f0ad58 bellard
    }
669 e7f0ad58 bellard
}
670 e7f0ad58 bellard
671 e7f0ad58 bellard
static void console_scroll(int ydelta)
672 e7f0ad58 bellard
{
673 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
674 e7f0ad58 bellard
    int i, y1;
675 3b46e624 ths
676 e7f0ad58 bellard
    s = active_console;
677 af3a9031 ths
    if (!s || (s->console_type == GRAPHIC_CONSOLE))
678 e7f0ad58 bellard
        return;
679 e7f0ad58 bellard
680 e7f0ad58 bellard
    if (ydelta > 0) {
681 e7f0ad58 bellard
        for(i = 0; i < ydelta; i++) {
682 e7f0ad58 bellard
            if (s->y_displayed == s->y_base)
683 e7f0ad58 bellard
                break;
684 e7f0ad58 bellard
            if (++s->y_displayed == s->total_height)
685 e7f0ad58 bellard
                s->y_displayed = 0;
686 e7f0ad58 bellard
        }
687 e7f0ad58 bellard
    } else {
688 e7f0ad58 bellard
        ydelta = -ydelta;
689 e7f0ad58 bellard
        i = s->backscroll_height;
690 e7f0ad58 bellard
        if (i > s->total_height - s->height)
691 e7f0ad58 bellard
            i = s->total_height - s->height;
692 e7f0ad58 bellard
        y1 = s->y_base - i;
693 e7f0ad58 bellard
        if (y1 < 0)
694 e7f0ad58 bellard
            y1 += s->total_height;
695 e7f0ad58 bellard
        for(i = 0; i < ydelta; i++) {
696 e7f0ad58 bellard
            if (s->y_displayed == y1)
697 e7f0ad58 bellard
                break;
698 e7f0ad58 bellard
            if (--s->y_displayed < 0)
699 e7f0ad58 bellard
                s->y_displayed = s->total_height - 1;
700 e7f0ad58 bellard
        }
701 e7f0ad58 bellard
    }
702 e7f0ad58 bellard
    console_refresh(s);
703 e7f0ad58 bellard
}
704 e7f0ad58 bellard
705 76ffb0b4 Gerd Hoffmann
static void console_put_lf(QemuConsole *s)
706 e7f0ad58 bellard
{
707 e7f0ad58 bellard
    TextCell *c;
708 e7f0ad58 bellard
    int x, y1;
709 e7f0ad58 bellard
710 e7f0ad58 bellard
    s->y++;
711 e7f0ad58 bellard
    if (s->y >= s->height) {
712 e7f0ad58 bellard
        s->y = s->height - 1;
713 6d6f7c28 pbrook
714 e7f0ad58 bellard
        if (s->y_displayed == s->y_base) {
715 e7f0ad58 bellard
            if (++s->y_displayed == s->total_height)
716 e7f0ad58 bellard
                s->y_displayed = 0;
717 e7f0ad58 bellard
        }
718 e7f0ad58 bellard
        if (++s->y_base == s->total_height)
719 e7f0ad58 bellard
            s->y_base = 0;
720 e7f0ad58 bellard
        if (s->backscroll_height < s->total_height)
721 e7f0ad58 bellard
            s->backscroll_height++;
722 e7f0ad58 bellard
        y1 = (s->y_base + s->height - 1) % s->total_height;
723 e7f0ad58 bellard
        c = &s->cells[y1 * s->width];
724 e7f0ad58 bellard
        for(x = 0; x < s->width; x++) {
725 e7f0ad58 bellard
            c->ch = ' ';
726 6d6f7c28 pbrook
            c->t_attrib = s->t_attrib_default;
727 e7f0ad58 bellard
            c++;
728 e7f0ad58 bellard
        }
729 e7f0ad58 bellard
        if (s == active_console && s->y_displayed == s->y_base) {
730 0e1f5a0c aliguori
            if (!ds_get_bits_per_pixel(s->ds)) {
731 4d3b6f6e balrog
                s->text_x[0] = 0;
732 4d3b6f6e balrog
                s->text_y[0] = 0;
733 4d3b6f6e balrog
                s->text_x[1] = s->width - 1;
734 4d3b6f6e balrog
                s->text_y[1] = s->height - 1;
735 4d3b6f6e balrog
                return;
736 4d3b6f6e balrog
            }
737 4d3b6f6e balrog
738 5fafdf24 ths
            vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0,
739 5fafdf24 ths
                       s->width * FONT_WIDTH,
740 e7f0ad58 bellard
                       (s->height - 1) * FONT_HEIGHT);
741 e7f0ad58 bellard
            vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
742 5fafdf24 ths
                          s->width * FONT_WIDTH, FONT_HEIGHT,
743 6d6f7c28 pbrook
                          color_table[0][s->t_attrib_default.bgcol]);
744 14778c20 pbrook
            s->update_x0 = 0;
745 14778c20 pbrook
            s->update_y0 = 0;
746 14778c20 pbrook
            s->update_x1 = s->width * FONT_WIDTH;
747 14778c20 pbrook
            s->update_y1 = s->height * FONT_HEIGHT;
748 e7f0ad58 bellard
        }
749 e7f0ad58 bellard
    }
750 e7f0ad58 bellard
}
751 e7f0ad58 bellard
752 6d6f7c28 pbrook
/* Set console attributes depending on the current escape codes.
753 6d6f7c28 pbrook
 * NOTE: I know this code is not very efficient (checking every color for it
754 6d6f7c28 pbrook
 * self) but it is more readable and better maintainable.
755 6d6f7c28 pbrook
 */
756 76ffb0b4 Gerd Hoffmann
static void console_handle_escape(QemuConsole *s)
757 6d6f7c28 pbrook
{
758 6d6f7c28 pbrook
    int i;
759 6d6f7c28 pbrook
760 6d6f7c28 pbrook
    for (i=0; i<s->nb_esc_params; i++) {
761 6d6f7c28 pbrook
        switch (s->esc_params[i]) {
762 6d6f7c28 pbrook
            case 0: /* reset all console attributes to default */
763 6d6f7c28 pbrook
                s->t_attrib = s->t_attrib_default;
764 6d6f7c28 pbrook
                break;
765 6d6f7c28 pbrook
            case 1:
766 6d6f7c28 pbrook
                s->t_attrib.bold = 1;
767 6d6f7c28 pbrook
                break;
768 6d6f7c28 pbrook
            case 4:
769 6d6f7c28 pbrook
                s->t_attrib.uline = 1;
770 6d6f7c28 pbrook
                break;
771 6d6f7c28 pbrook
            case 5:
772 6d6f7c28 pbrook
                s->t_attrib.blink = 1;
773 6d6f7c28 pbrook
                break;
774 6d6f7c28 pbrook
            case 7:
775 6d6f7c28 pbrook
                s->t_attrib.invers = 1;
776 6d6f7c28 pbrook
                break;
777 6d6f7c28 pbrook
            case 8:
778 6d6f7c28 pbrook
                s->t_attrib.unvisible = 1;
779 6d6f7c28 pbrook
                break;
780 6d6f7c28 pbrook
            case 22:
781 6d6f7c28 pbrook
                s->t_attrib.bold = 0;
782 6d6f7c28 pbrook
                break;
783 6d6f7c28 pbrook
            case 24:
784 6d6f7c28 pbrook
                s->t_attrib.uline = 0;
785 6d6f7c28 pbrook
                break;
786 6d6f7c28 pbrook
            case 25:
787 6d6f7c28 pbrook
                s->t_attrib.blink = 0;
788 6d6f7c28 pbrook
                break;
789 6d6f7c28 pbrook
            case 27:
790 6d6f7c28 pbrook
                s->t_attrib.invers = 0;
791 6d6f7c28 pbrook
                break;
792 6d6f7c28 pbrook
            case 28:
793 6d6f7c28 pbrook
                s->t_attrib.unvisible = 0;
794 6d6f7c28 pbrook
                break;
795 6d6f7c28 pbrook
            /* set foreground color */
796 6d6f7c28 pbrook
            case 30:
797 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_BLACK;
798 6d6f7c28 pbrook
                break;
799 6d6f7c28 pbrook
            case 31:
800 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_RED;
801 6d6f7c28 pbrook
                break;
802 6d6f7c28 pbrook
            case 32:
803 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_GREEN;
804 6d6f7c28 pbrook
                break;
805 6d6f7c28 pbrook
            case 33:
806 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_YELLOW;
807 6d6f7c28 pbrook
                break;
808 6d6f7c28 pbrook
            case 34:
809 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_BLUE;
810 6d6f7c28 pbrook
                break;
811 6d6f7c28 pbrook
            case 35:
812 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_MAGENTA;
813 6d6f7c28 pbrook
                break;
814 6d6f7c28 pbrook
            case 36:
815 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_CYAN;
816 6d6f7c28 pbrook
                break;
817 6d6f7c28 pbrook
            case 37:
818 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_WHITE;
819 6d6f7c28 pbrook
                break;
820 6d6f7c28 pbrook
            /* set background color */
821 6d6f7c28 pbrook
            case 40:
822 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_BLACK;
823 6d6f7c28 pbrook
                break;
824 6d6f7c28 pbrook
            case 41:
825 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_RED;
826 6d6f7c28 pbrook
                break;
827 6d6f7c28 pbrook
            case 42:
828 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_GREEN;
829 6d6f7c28 pbrook
                break;
830 6d6f7c28 pbrook
            case 43:
831 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_YELLOW;
832 6d6f7c28 pbrook
                break;
833 6d6f7c28 pbrook
            case 44:
834 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_BLUE;
835 6d6f7c28 pbrook
                break;
836 6d6f7c28 pbrook
            case 45:
837 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_MAGENTA;
838 6d6f7c28 pbrook
                break;
839 6d6f7c28 pbrook
            case 46:
840 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_CYAN;
841 6d6f7c28 pbrook
                break;
842 6d6f7c28 pbrook
            case 47:
843 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_WHITE;
844 6d6f7c28 pbrook
                break;
845 6d6f7c28 pbrook
        }
846 6d6f7c28 pbrook
    }
847 6d6f7c28 pbrook
}
848 6d6f7c28 pbrook
849 76ffb0b4 Gerd Hoffmann
static void console_clear_xy(QemuConsole *s, int x, int y)
850 adb47967 ths
{
851 adb47967 ths
    int y1 = (s->y_base + y) % s->total_height;
852 adb47967 ths
    TextCell *c = &s->cells[y1 * s->width + x];
853 adb47967 ths
    c->ch = ' ';
854 adb47967 ths
    c->t_attrib = s->t_attrib_default;
855 adb47967 ths
    update_xy(s, x, y);
856 adb47967 ths
}
857 adb47967 ths
858 3eea5498 Ian Campbell
/* set cursor, checking bounds */
859 76ffb0b4 Gerd Hoffmann
static void set_cursor(QemuConsole *s, int x, int y)
860 3eea5498 Ian Campbell
{
861 3eea5498 Ian Campbell
    if (x < 0) {
862 3eea5498 Ian Campbell
        x = 0;
863 3eea5498 Ian Campbell
    }
864 3eea5498 Ian Campbell
    if (y < 0) {
865 3eea5498 Ian Campbell
        y = 0;
866 3eea5498 Ian Campbell
    }
867 3eea5498 Ian Campbell
    if (y >= s->height) {
868 3eea5498 Ian Campbell
        y = s->height - 1;
869 3eea5498 Ian Campbell
    }
870 3eea5498 Ian Campbell
    if (x >= s->width) {
871 3eea5498 Ian Campbell
        x = s->width - 1;
872 3eea5498 Ian Campbell
    }
873 3eea5498 Ian Campbell
874 3eea5498 Ian Campbell
    s->x = x;
875 3eea5498 Ian Campbell
    s->y = y;
876 3eea5498 Ian Campbell
}
877 3eea5498 Ian Campbell
878 76ffb0b4 Gerd Hoffmann
static void console_putchar(QemuConsole *s, int ch)
879 e7f0ad58 bellard
{
880 e7f0ad58 bellard
    TextCell *c;
881 adb47967 ths
    int y1, i;
882 adb47967 ths
    int x, y;
883 e7f0ad58 bellard
884 e7f0ad58 bellard
    switch(s->state) {
885 e7f0ad58 bellard
    case TTY_STATE_NORM:
886 e7f0ad58 bellard
        switch(ch) {
887 6d6f7c28 pbrook
        case '\r':  /* carriage return */
888 e7f0ad58 bellard
            s->x = 0;
889 e7f0ad58 bellard
            break;
890 6d6f7c28 pbrook
        case '\n':  /* newline */
891 e7f0ad58 bellard
            console_put_lf(s);
892 e7f0ad58 bellard
            break;
893 6d6f7c28 pbrook
        case '\b':  /* backspace */
894 5fafdf24 ths
            if (s->x > 0)
895 e15d7371 bellard
                s->x--;
896 6d6f7c28 pbrook
            break;
897 6d6f7c28 pbrook
        case '\t':  /* tabspace */
898 6d6f7c28 pbrook
            if (s->x + (8 - (s->x % 8)) > s->width) {
899 bd468840 bellard
                s->x = 0;
900 6d6f7c28 pbrook
                console_put_lf(s);
901 6d6f7c28 pbrook
            } else {
902 6d6f7c28 pbrook
                s->x = s->x + (8 - (s->x % 8));
903 6d6f7c28 pbrook
            }
904 6d6f7c28 pbrook
            break;
905 6d6f7c28 pbrook
        case '\a':  /* alert aka. bell */
906 6d6f7c28 pbrook
            /* TODO: has to be implemented */
907 6d6f7c28 pbrook
            break;
908 adb47967 ths
        case 14:
909 adb47967 ths
            /* SI (shift in), character set 0 (ignored) */
910 adb47967 ths
            break;
911 adb47967 ths
        case 15:
912 adb47967 ths
            /* SO (shift out), character set 1 (ignored) */
913 adb47967 ths
            break;
914 6d6f7c28 pbrook
        case 27:    /* esc (introducing an escape sequence) */
915 e7f0ad58 bellard
            s->state = TTY_STATE_ESC;
916 e7f0ad58 bellard
            break;
917 e7f0ad58 bellard
        default:
918 ed8276ac ths
            if (s->x >= s->width) {
919 ed8276ac ths
                /* line wrap */
920 ed8276ac ths
                s->x = 0;
921 ed8276ac ths
                console_put_lf(s);
922 adb47967 ths
            }
923 e7f0ad58 bellard
            y1 = (s->y_base + s->y) % s->total_height;
924 e7f0ad58 bellard
            c = &s->cells[y1 * s->width + s->x];
925 e7f0ad58 bellard
            c->ch = ch;
926 6d6f7c28 pbrook
            c->t_attrib = s->t_attrib;
927 e7f0ad58 bellard
            update_xy(s, s->x, s->y);
928 e7f0ad58 bellard
            s->x++;
929 e7f0ad58 bellard
            break;
930 e7f0ad58 bellard
        }
931 e7f0ad58 bellard
        break;
932 6d6f7c28 pbrook
    case TTY_STATE_ESC: /* check if it is a terminal escape sequence */
933 e7f0ad58 bellard
        if (ch == '[') {
934 e7f0ad58 bellard
            for(i=0;i<MAX_ESC_PARAMS;i++)
935 e7f0ad58 bellard
                s->esc_params[i] = 0;
936 e7f0ad58 bellard
            s->nb_esc_params = 0;
937 e7f0ad58 bellard
            s->state = TTY_STATE_CSI;
938 e7f0ad58 bellard
        } else {
939 e7f0ad58 bellard
            s->state = TTY_STATE_NORM;
940 e7f0ad58 bellard
        }
941 e7f0ad58 bellard
        break;
942 6d6f7c28 pbrook
    case TTY_STATE_CSI: /* handle escape sequence parameters */
943 e7f0ad58 bellard
        if (ch >= '0' && ch <= '9') {
944 e7f0ad58 bellard
            if (s->nb_esc_params < MAX_ESC_PARAMS) {
945 c10600af Laszlo Ersek
                int *param = &s->esc_params[s->nb_esc_params];
946 c10600af Laszlo Ersek
                int digit = (ch - '0');
947 c10600af Laszlo Ersek
948 c10600af Laszlo Ersek
                *param = (*param <= (INT_MAX - digit) / 10) ?
949 c10600af Laszlo Ersek
                         *param * 10 + digit : INT_MAX;
950 e7f0ad58 bellard
            }
951 e7f0ad58 bellard
        } else {
952 3eea5498 Ian Campbell
            if (s->nb_esc_params < MAX_ESC_PARAMS)
953 3eea5498 Ian Campbell
                s->nb_esc_params++;
954 e7f0ad58 bellard
            if (ch == ';')
955 e7f0ad58 bellard
                break;
956 adb47967 ths
#ifdef DEBUG_CONSOLE
957 adb47967 ths
            fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
958 adb47967 ths
                    s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
959 adb47967 ths
#endif
960 e7f0ad58 bellard
            s->state = TTY_STATE_NORM;
961 e7f0ad58 bellard
            switch(ch) {
962 adb47967 ths
            case 'A':
963 adb47967 ths
                /* move cursor up */
964 adb47967 ths
                if (s->esc_params[0] == 0) {
965 adb47967 ths
                    s->esc_params[0] = 1;
966 adb47967 ths
                }
967 3eea5498 Ian Campbell
                set_cursor(s, s->x, s->y - s->esc_params[0]);
968 adb47967 ths
                break;
969 adb47967 ths
            case 'B':
970 adb47967 ths
                /* move cursor down */
971 adb47967 ths
                if (s->esc_params[0] == 0) {
972 adb47967 ths
                    s->esc_params[0] = 1;
973 adb47967 ths
                }
974 3eea5498 Ian Campbell
                set_cursor(s, s->x, s->y + s->esc_params[0]);
975 e7f0ad58 bellard
                break;
976 e7f0ad58 bellard
            case 'C':
977 adb47967 ths
                /* move cursor right */
978 adb47967 ths
                if (s->esc_params[0] == 0) {
979 adb47967 ths
                    s->esc_params[0] = 1;
980 adb47967 ths
                }
981 3eea5498 Ian Campbell
                set_cursor(s, s->x + s->esc_params[0], s->y);
982 e7f0ad58 bellard
                break;
983 adb47967 ths
            case 'D':
984 adb47967 ths
                /* move cursor left */
985 adb47967 ths
                if (s->esc_params[0] == 0) {
986 adb47967 ths
                    s->esc_params[0] = 1;
987 adb47967 ths
                }
988 3eea5498 Ian Campbell
                set_cursor(s, s->x - s->esc_params[0], s->y);
989 adb47967 ths
                break;
990 adb47967 ths
            case 'G':
991 adb47967 ths
                /* move cursor to column */
992 3eea5498 Ian Campbell
                set_cursor(s, s->esc_params[0] - 1, s->y);
993 adb47967 ths
                break;
994 adb47967 ths
            case 'f':
995 adb47967 ths
            case 'H':
996 adb47967 ths
                /* move cursor to row, column */
997 3eea5498 Ian Campbell
                set_cursor(s, s->esc_params[1] - 1, s->esc_params[0] - 1);
998 adb47967 ths
                break;
999 adb47967 ths
            case 'J':
1000 adb47967 ths
                switch (s->esc_params[0]) {
1001 adb47967 ths
                case 0:
1002 adb47967 ths
                    /* clear to end of screen */
1003 adb47967 ths
                    for (y = s->y; y < s->height; y++) {
1004 adb47967 ths
                        for (x = 0; x < s->width; x++) {
1005 adb47967 ths
                            if (y == s->y && x < s->x) {
1006 adb47967 ths
                                continue;
1007 adb47967 ths
                            }
1008 adb47967 ths
                            console_clear_xy(s, x, y);
1009 adb47967 ths
                        }
1010 adb47967 ths
                    }
1011 adb47967 ths
                    break;
1012 adb47967 ths
                case 1:
1013 adb47967 ths
                    /* clear from beginning of screen */
1014 adb47967 ths
                    for (y = 0; y <= s->y; y++) {
1015 adb47967 ths
                        for (x = 0; x < s->width; x++) {
1016 adb47967 ths
                            if (y == s->y && x > s->x) {
1017 adb47967 ths
                                break;
1018 adb47967 ths
                            }
1019 adb47967 ths
                            console_clear_xy(s, x, y);
1020 adb47967 ths
                        }
1021 adb47967 ths
                    }
1022 adb47967 ths
                    break;
1023 adb47967 ths
                case 2:
1024 adb47967 ths
                    /* clear entire screen */
1025 adb47967 ths
                    for (y = 0; y <= s->height; y++) {
1026 adb47967 ths
                        for (x = 0; x < s->width; x++) {
1027 adb47967 ths
                            console_clear_xy(s, x, y);
1028 adb47967 ths
                        }
1029 adb47967 ths
                    }
1030 f94a950f Markus Armbruster
                    break;
1031 adb47967 ths
                }
1032 95d8f9f4 Markus Armbruster
                break;
1033 e7f0ad58 bellard
            case 'K':
1034 adb47967 ths
                switch (s->esc_params[0]) {
1035 adb47967 ths
                case 0:
1036 f94a950f Markus Armbruster
                    /* clear to eol */
1037 f94a950f Markus Armbruster
                    for(x = s->x; x < s->width; x++) {
1038 adb47967 ths
                        console_clear_xy(s, x, s->y);
1039 f94a950f Markus Armbruster
                    }
1040 f94a950f Markus Armbruster
                    break;
1041 adb47967 ths
                case 1:
1042 adb47967 ths
                    /* clear from beginning of line */
1043 adb47967 ths
                    for (x = 0; x <= s->x; x++) {
1044 adb47967 ths
                        console_clear_xy(s, x, s->y);
1045 adb47967 ths
                    }
1046 adb47967 ths
                    break;
1047 adb47967 ths
                case 2:
1048 adb47967 ths
                    /* clear entire line */
1049 adb47967 ths
                    for(x = 0; x < s->width; x++) {
1050 adb47967 ths
                        console_clear_xy(s, x, s->y);
1051 adb47967 ths
                    }
1052 f94a950f Markus Armbruster
                    break;
1053 f94a950f Markus Armbruster
                }
1054 adb47967 ths
                break;
1055 adb47967 ths
            case 'm':
1056 f94a950f Markus Armbruster
                console_handle_escape(s);
1057 f94a950f Markus Armbruster
                break;
1058 adb47967 ths
            case 'n':
1059 adb47967 ths
                /* report cursor position */
1060 adb47967 ths
                /* TODO: send ESC[row;colR */
1061 adb47967 ths
                break;
1062 adb47967 ths
            case 's':
1063 adb47967 ths
                /* save cursor position */
1064 adb47967 ths
                s->x_saved = s->x;
1065 adb47967 ths
                s->y_saved = s->y;
1066 adb47967 ths
                break;
1067 adb47967 ths
            case 'u':
1068 adb47967 ths
                /* restore cursor position */
1069 adb47967 ths
                s->x = s->x_saved;
1070 adb47967 ths
                s->y = s->y_saved;
1071 adb47967 ths
                break;
1072 adb47967 ths
            default:
1073 adb47967 ths
#ifdef DEBUG_CONSOLE
1074 adb47967 ths
                fprintf(stderr, "unhandled escape character '%c'\n", ch);
1075 adb47967 ths
#endif
1076 adb47967 ths
                break;
1077 adb47967 ths
            }
1078 adb47967 ths
            break;
1079 e7f0ad58 bellard
        }
1080 e7f0ad58 bellard
    }
1081 e7f0ad58 bellard
}
1082 e7f0ad58 bellard
1083 e7f0ad58 bellard
void console_select(unsigned int index)
1084 e7f0ad58 bellard
{
1085 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1086 6d6f7c28 pbrook
1087 e7f0ad58 bellard
    if (index >= MAX_CONSOLES)
1088 e7f0ad58 bellard
        return;
1089 358664cc Stefan Hajnoczi
    if (active_console) {
1090 358664cc Stefan Hajnoczi
        active_console->g_width = ds_get_width(active_console->ds);
1091 358664cc Stefan Hajnoczi
        active_console->g_height = ds_get_height(active_console->ds);
1092 358664cc Stefan Hajnoczi
    }
1093 e7f0ad58 bellard
    s = consoles[index];
1094 e7f0ad58 bellard
    if (s) {
1095 7d957bd8 aliguori
        DisplayState *ds = s->ds;
1096 bf1bed81 Jan Kiszka
1097 8bd6b06d Stefan Weil
        if (active_console && active_console->cursor_timer) {
1098 bf1bed81 Jan Kiszka
            qemu_del_timer(active_console->cursor_timer);
1099 bf1bed81 Jan Kiszka
        }
1100 e7f0ad58 bellard
        active_console = s;
1101 a93a4a22 Gerd Hoffmann
        if (ds->have_gfx) {
1102 7b5d76da aliguori
            ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
1103 a93a4a22 Gerd Hoffmann
            dpy_gfx_resize(ds);
1104 a93a4a22 Gerd Hoffmann
        }
1105 a93a4a22 Gerd Hoffmann
        if (ds->have_text) {
1106 a93a4a22 Gerd Hoffmann
            dpy_text_resize(ds, s->width, s->height);
1107 68f00996 aliguori
        }
1108 bf1bed81 Jan Kiszka
        if (s->cursor_timer) {
1109 bf1bed81 Jan Kiszka
            qemu_mod_timer(s->cursor_timer,
1110 bf1bed81 Jan Kiszka
                   qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
1111 bf1bed81 Jan Kiszka
        }
1112 4d3b6f6e balrog
        vga_hw_invalidate();
1113 e7f0ad58 bellard
    }
1114 e7f0ad58 bellard
}
1115 e7f0ad58 bellard
1116 e7f0ad58 bellard
static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
1117 e7f0ad58 bellard
{
1118 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = chr->opaque;
1119 e7f0ad58 bellard
    int i;
1120 e7f0ad58 bellard
1121 14778c20 pbrook
    s->update_x0 = s->width * FONT_WIDTH;
1122 14778c20 pbrook
    s->update_y0 = s->height * FONT_HEIGHT;
1123 14778c20 pbrook
    s->update_x1 = 0;
1124 14778c20 pbrook
    s->update_y1 = 0;
1125 e7f0ad58 bellard
    console_show_cursor(s, 0);
1126 e7f0ad58 bellard
    for(i = 0; i < len; i++) {
1127 e7f0ad58 bellard
        console_putchar(s, buf[i]);
1128 e7f0ad58 bellard
    }
1129 e7f0ad58 bellard
    console_show_cursor(s, 1);
1130 a93a4a22 Gerd Hoffmann
    if (s->ds->have_gfx && s->update_x0 < s->update_x1) {
1131 a93a4a22 Gerd Hoffmann
        dpy_gfx_update(s->ds, s->update_x0, s->update_y0,
1132 a93a4a22 Gerd Hoffmann
                       s->update_x1 - s->update_x0,
1133 a93a4a22 Gerd Hoffmann
                       s->update_y1 - s->update_y0);
1134 14778c20 pbrook
    }
1135 e7f0ad58 bellard
    return len;
1136 e7f0ad58 bellard
}
1137 e7f0ad58 bellard
1138 e15d7371 bellard
static void kbd_send_chars(void *opaque)
1139 e15d7371 bellard
{
1140 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = opaque;
1141 e15d7371 bellard
    int len;
1142 e15d7371 bellard
    uint8_t buf[16];
1143 3b46e624 ths
1144 909cda12 Anthony Liguori
    len = qemu_chr_be_can_write(s->chr);
1145 e15d7371 bellard
    if (len > s->out_fifo.count)
1146 e15d7371 bellard
        len = s->out_fifo.count;
1147 e15d7371 bellard
    if (len > 0) {
1148 e15d7371 bellard
        if (len > sizeof(buf))
1149 e15d7371 bellard
            len = sizeof(buf);
1150 e15d7371 bellard
        qemu_fifo_read(&s->out_fifo, buf, len);
1151 fa5efccb Anthony Liguori
        qemu_chr_be_write(s->chr, buf, len);
1152 e15d7371 bellard
    }
1153 e15d7371 bellard
    /* characters are pending: we send them a bit later (XXX:
1154 e15d7371 bellard
       horrible, should change char device API) */
1155 e15d7371 bellard
    if (s->out_fifo.count > 0) {
1156 7bd427d8 Paolo Bonzini
        qemu_mod_timer(s->kbd_timer, qemu_get_clock_ms(rt_clock) + 1);
1157 e15d7371 bellard
    }
1158 e15d7371 bellard
}
1159 e15d7371 bellard
1160 e7f0ad58 bellard
/* called when an ascii key is pressed */
1161 e7f0ad58 bellard
void kbd_put_keysym(int keysym)
1162 e7f0ad58 bellard
{
1163 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1164 e7f0ad58 bellard
    uint8_t buf[16], *q;
1165 e7f0ad58 bellard
    int c;
1166 e7f0ad58 bellard
1167 e7f0ad58 bellard
    s = active_console;
1168 af3a9031 ths
    if (!s || (s->console_type == GRAPHIC_CONSOLE))
1169 e7f0ad58 bellard
        return;
1170 e7f0ad58 bellard
1171 e7f0ad58 bellard
    switch(keysym) {
1172 e7f0ad58 bellard
    case QEMU_KEY_CTRL_UP:
1173 e7f0ad58 bellard
        console_scroll(-1);
1174 e7f0ad58 bellard
        break;
1175 e7f0ad58 bellard
    case QEMU_KEY_CTRL_DOWN:
1176 e7f0ad58 bellard
        console_scroll(1);
1177 e7f0ad58 bellard
        break;
1178 e7f0ad58 bellard
    case QEMU_KEY_CTRL_PAGEUP:
1179 e7f0ad58 bellard
        console_scroll(-10);
1180 e7f0ad58 bellard
        break;
1181 e7f0ad58 bellard
    case QEMU_KEY_CTRL_PAGEDOWN:
1182 e7f0ad58 bellard
        console_scroll(10);
1183 e7f0ad58 bellard
        break;
1184 e7f0ad58 bellard
    default:
1185 e15d7371 bellard
        /* convert the QEMU keysym to VT100 key string */
1186 e15d7371 bellard
        q = buf;
1187 e15d7371 bellard
        if (keysym >= 0xe100 && keysym <= 0xe11f) {
1188 e15d7371 bellard
            *q++ = '\033';
1189 e15d7371 bellard
            *q++ = '[';
1190 e15d7371 bellard
            c = keysym - 0xe100;
1191 e15d7371 bellard
            if (c >= 10)
1192 e15d7371 bellard
                *q++ = '0' + (c / 10);
1193 e15d7371 bellard
            *q++ = '0' + (c % 10);
1194 e15d7371 bellard
            *q++ = '~';
1195 e15d7371 bellard
        } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
1196 e15d7371 bellard
            *q++ = '\033';
1197 e15d7371 bellard
            *q++ = '[';
1198 e15d7371 bellard
            *q++ = keysym & 0xff;
1199 4104833f Paolo Bonzini
        } else if (s->echo && (keysym == '\r' || keysym == '\n')) {
1200 4104833f Paolo Bonzini
            console_puts(s->chr, (const uint8_t *) "\r", 1);
1201 4104833f Paolo Bonzini
            *q++ = '\n';
1202 e15d7371 bellard
        } else {
1203 4104833f Paolo Bonzini
            *q++ = keysym;
1204 4104833f Paolo Bonzini
        }
1205 4104833f Paolo Bonzini
        if (s->echo) {
1206 4104833f Paolo Bonzini
            console_puts(s->chr, buf, q - buf);
1207 e15d7371 bellard
        }
1208 e5b0bc44 pbrook
        if (s->chr->chr_read) {
1209 e15d7371 bellard
            qemu_fifo_write(&s->out_fifo, buf, q - buf);
1210 e15d7371 bellard
            kbd_send_chars(s);
1211 e7f0ad58 bellard
        }
1212 e7f0ad58 bellard
        break;
1213 e7f0ad58 bellard
    }
1214 e7f0ad58 bellard
}
1215 e7f0ad58 bellard
1216 4d3b6f6e balrog
static void text_console_invalidate(void *opaque)
1217 4d3b6f6e balrog
{
1218 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = (QemuConsole *) opaque;
1219 68f00996 aliguori
    if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) {
1220 68f00996 aliguori
        s->g_width = ds_get_width(s->ds);
1221 68f00996 aliguori
        s->g_height = ds_get_height(s->ds);
1222 68f00996 aliguori
        text_console_resize(s);
1223 68f00996 aliguori
    }
1224 4d3b6f6e balrog
    console_refresh(s);
1225 4d3b6f6e balrog
}
1226 4d3b6f6e balrog
1227 c227f099 Anthony Liguori
static void text_console_update(void *opaque, console_ch_t *chardata)
1228 4d3b6f6e balrog
{
1229 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = (QemuConsole *) opaque;
1230 4d3b6f6e balrog
    int i, j, src;
1231 4d3b6f6e balrog
1232 4d3b6f6e balrog
    if (s->text_x[0] <= s->text_x[1]) {
1233 4d3b6f6e balrog
        src = (s->y_base + s->text_y[0]) * s->width;
1234 4d3b6f6e balrog
        chardata += s->text_y[0] * s->width;
1235 4d3b6f6e balrog
        for (i = s->text_y[0]; i <= s->text_y[1]; i ++)
1236 4d3b6f6e balrog
            for (j = 0; j < s->width; j ++, src ++)
1237 4d3b6f6e balrog
                console_write_ch(chardata ++, s->cells[src].ch |
1238 4d3b6f6e balrog
                                (s->cells[src].t_attrib.fgcol << 12) |
1239 4d3b6f6e balrog
                                (s->cells[src].t_attrib.bgcol << 8) |
1240 4d3b6f6e balrog
                                (s->cells[src].t_attrib.bold << 21));
1241 a93a4a22 Gerd Hoffmann
        dpy_text_update(s->ds, s->text_x[0], s->text_y[0],
1242 a93a4a22 Gerd Hoffmann
                        s->text_x[1] - s->text_x[0], i - s->text_y[0]);
1243 4d3b6f6e balrog
        s->text_x[0] = s->width;
1244 4d3b6f6e balrog
        s->text_y[0] = s->height;
1245 4d3b6f6e balrog
        s->text_x[1] = 0;
1246 4d3b6f6e balrog
        s->text_y[1] = 0;
1247 4d3b6f6e balrog
    }
1248 4d3b6f6e balrog
    if (s->cursor_invalidate) {
1249 bf2fde70 Gerd Hoffmann
        dpy_text_cursor(s->ds, s->x, s->y);
1250 4d3b6f6e balrog
        s->cursor_invalidate = 0;
1251 4d3b6f6e balrog
    }
1252 4d3b6f6e balrog
}
1253 4d3b6f6e balrog
1254 76ffb0b4 Gerd Hoffmann
static QemuConsole *get_graphic_console(DisplayState *ds)
1255 a147d62b blueswir1
{
1256 3023f332 aliguori
    int i;
1257 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1258 3023f332 aliguori
    for (i = 0; i < nb_consoles; i++) {
1259 3023f332 aliguori
        s = consoles[i];
1260 42aa98e8 aliguori
        if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds)
1261 3023f332 aliguori
            return s;
1262 3023f332 aliguori
    }
1263 3023f332 aliguori
    return NULL;
1264 3023f332 aliguori
}
1265 3023f332 aliguori
1266 76ffb0b4 Gerd Hoffmann
static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
1267 e7f0ad58 bellard
{
1268 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1269 95219897 pbrook
    int i;
1270 e7f0ad58 bellard
1271 e7f0ad58 bellard
    if (nb_consoles >= MAX_CONSOLES)
1272 e7f0ad58 bellard
        return NULL;
1273 76ffb0b4 Gerd Hoffmann
    s = g_malloc0(sizeof(QemuConsole));
1274 af3a9031 ths
    if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
1275 af3a9031 ths
        (console_type == GRAPHIC_CONSOLE))) {
1276 e7f0ad58 bellard
        active_console = s;
1277 af3a9031 ths
    }
1278 e7f0ad58 bellard
    s->ds = ds;
1279 af3a9031 ths
    s->console_type = console_type;
1280 af3a9031 ths
    if (console_type != GRAPHIC_CONSOLE) {
1281 f81bdefb Jan Kiszka
        s->index = nb_consoles;
1282 95219897 pbrook
        consoles[nb_consoles++] = s;
1283 95219897 pbrook
    } else {
1284 95219897 pbrook
        /* HACK: Put graphical consoles before text consoles.  */
1285 95219897 pbrook
        for (i = nb_consoles; i > 0; i--) {
1286 af3a9031 ths
            if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
1287 95219897 pbrook
                break;
1288 95219897 pbrook
            consoles[i] = consoles[i - 1];
1289 f81bdefb Jan Kiszka
            consoles[i]->index = i;
1290 95219897 pbrook
        }
1291 f81bdefb Jan Kiszka
        s->index = i;
1292 95219897 pbrook
        consoles[i] = s;
1293 3023f332 aliguori
        nb_consoles++;
1294 95219897 pbrook
    }
1295 95219897 pbrook
    return s;
1296 95219897 pbrook
}
1297 95219897 pbrook
1298 537a4391 Gerd Hoffmann
static void qemu_alloc_display(DisplaySurface *surface, int width, int height,
1299 537a4391 Gerd Hoffmann
                               int linesize, PixelFormat pf, int newflags)
1300 ffe8b821 Jes Sorensen
{
1301 ffe8b821 Jes Sorensen
    surface->pf = pf;
1302 69c77777 Gerd Hoffmann
1303 69c77777 Gerd Hoffmann
    qemu_pixman_image_unref(surface->image);
1304 69c77777 Gerd Hoffmann
    surface->image = NULL;
1305 69c77777 Gerd Hoffmann
1306 69c77777 Gerd Hoffmann
    surface->format = qemu_pixman_get_format(&pf);
1307 69c77777 Gerd Hoffmann
    assert(surface->format != 0);
1308 69c77777 Gerd Hoffmann
    surface->image = pixman_image_create_bits(surface->format,
1309 69c77777 Gerd Hoffmann
                                              width, height,
1310 69c77777 Gerd Hoffmann
                                              NULL, linesize);
1311 69c77777 Gerd Hoffmann
    assert(surface->image != NULL);
1312 69c77777 Gerd Hoffmann
1313 ffe8b821 Jes Sorensen
    surface->flags = newflags | QEMU_ALLOCATED_FLAG;
1314 98b50080 Paolo Bonzini
#ifdef HOST_WORDS_BIGENDIAN
1315 ffe8b821 Jes Sorensen
    surface->flags |= QEMU_BIG_ENDIAN_FLAG;
1316 98b50080 Paolo Bonzini
#endif
1317 98b50080 Paolo Bonzini
}
1318 98b50080 Paolo Bonzini
1319 537a4391 Gerd Hoffmann
DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
1320 537a4391 Gerd Hoffmann
                                           int width, int height)
1321 537a4391 Gerd Hoffmann
{
1322 537a4391 Gerd Hoffmann
    DisplaySurface *surface = g_new0(DisplaySurface, 1);
1323 537a4391 Gerd Hoffmann
1324 537a4391 Gerd Hoffmann
    int linesize = width * 4;
1325 537a4391 Gerd Hoffmann
    qemu_alloc_display(surface, width, height, linesize,
1326 537a4391 Gerd Hoffmann
                       qemu_default_pixelformat(32), 0);
1327 537a4391 Gerd Hoffmann
    return surface;
1328 537a4391 Gerd Hoffmann
}
1329 537a4391 Gerd Hoffmann
1330 537a4391 Gerd Hoffmann
DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
1331 537a4391 Gerd Hoffmann
                                           int width, int height)
1332 537a4391 Gerd Hoffmann
{
1333 537a4391 Gerd Hoffmann
    int linesize = width * 4;
1334 537a4391 Gerd Hoffmann
1335 537a4391 Gerd Hoffmann
    trace_displaysurface_resize(ds, ds->surface, width, height);
1336 537a4391 Gerd Hoffmann
    qemu_alloc_display(ds->surface, width, height, linesize,
1337 537a4391 Gerd Hoffmann
                       qemu_default_pixelformat(32), 0);
1338 537a4391 Gerd Hoffmann
    return ds->surface;
1339 537a4391 Gerd Hoffmann
}
1340 537a4391 Gerd Hoffmann
1341 187cd1d9 Gerd Hoffmann
DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
1342 69c77777 Gerd Hoffmann
                                                int linesize, uint8_t *data)
1343 98b50080 Paolo Bonzini
{
1344 69c77777 Gerd Hoffmann
    DisplaySurface *surface = g_new0(DisplaySurface, 1);
1345 98b50080 Paolo Bonzini
1346 98b50080 Paolo Bonzini
    surface->pf = qemu_default_pixelformat(bpp);
1347 69c77777 Gerd Hoffmann
1348 69c77777 Gerd Hoffmann
    surface->format = qemu_pixman_get_format(&surface->pf);
1349 69c77777 Gerd Hoffmann
    assert(surface->format != 0);
1350 69c77777 Gerd Hoffmann
    surface->image = pixman_image_create_bits(surface->format,
1351 69c77777 Gerd Hoffmann
                                              width, height,
1352 69c77777 Gerd Hoffmann
                                              (void *)data, linesize);
1353 69c77777 Gerd Hoffmann
    assert(surface->image != NULL);
1354 69c77777 Gerd Hoffmann
1355 98b50080 Paolo Bonzini
#ifdef HOST_WORDS_BIGENDIAN
1356 98b50080 Paolo Bonzini
    surface->flags = QEMU_BIG_ENDIAN_FLAG;
1357 98b50080 Paolo Bonzini
#endif
1358 98b50080 Paolo Bonzini
1359 98b50080 Paolo Bonzini
    return surface;
1360 98b50080 Paolo Bonzini
}
1361 98b50080 Paolo Bonzini
1362 187cd1d9 Gerd Hoffmann
void qemu_free_displaysurface(DisplayState *ds)
1363 98b50080 Paolo Bonzini
{
1364 187cd1d9 Gerd Hoffmann
    trace_displaysurface_free(ds, ds->surface);
1365 187cd1d9 Gerd Hoffmann
    if (ds->surface == NULL) {
1366 98b50080 Paolo Bonzini
        return;
1367 187cd1d9 Gerd Hoffmann
    }
1368 69c77777 Gerd Hoffmann
    qemu_pixman_image_unref(ds->surface->image);
1369 187cd1d9 Gerd Hoffmann
    g_free(ds->surface);
1370 98b50080 Paolo Bonzini
}
1371 98b50080 Paolo Bonzini
1372 98b50080 Paolo Bonzini
static void dumb_display_init(void)
1373 98b50080 Paolo Bonzini
{
1374 7267c094 Anthony Liguori
    DisplayState *ds = g_malloc0(sizeof(DisplayState));
1375 1802651c Jan Kiszka
    int width = 640;
1376 1802651c Jan Kiszka
    int height = 480;
1377 1802651c Jan Kiszka
1378 1802651c Jan Kiszka
    if (is_fixedsize_console()) {
1379 1802651c Jan Kiszka
        width = active_console->g_width;
1380 1802651c Jan Kiszka
        height = active_console->g_height;
1381 1802651c Jan Kiszka
    }
1382 1802651c Jan Kiszka
    ds->surface = qemu_create_displaysurface(ds, width, height);
1383 98b50080 Paolo Bonzini
    register_displaystate(ds);
1384 98b50080 Paolo Bonzini
}
1385 98b50080 Paolo Bonzini
1386 98b50080 Paolo Bonzini
/***********************************************************/
1387 98b50080 Paolo Bonzini
/* register display */
1388 98b50080 Paolo Bonzini
1389 98b50080 Paolo Bonzini
void register_displaystate(DisplayState *ds)
1390 98b50080 Paolo Bonzini
{
1391 98b50080 Paolo Bonzini
    DisplayState **s;
1392 98b50080 Paolo Bonzini
    s = &display_state;
1393 98b50080 Paolo Bonzini
    while (*s != NULL)
1394 98b50080 Paolo Bonzini
        s = &(*s)->next;
1395 98b50080 Paolo Bonzini
    ds->next = NULL;
1396 98b50080 Paolo Bonzini
    *s = ds;
1397 98b50080 Paolo Bonzini
}
1398 98b50080 Paolo Bonzini
1399 98b50080 Paolo Bonzini
DisplayState *get_displaystate(void)
1400 98b50080 Paolo Bonzini
{
1401 98b50080 Paolo Bonzini
    if (!display_state) {
1402 98b50080 Paolo Bonzini
        dumb_display_init ();
1403 98b50080 Paolo Bonzini
    }
1404 98b50080 Paolo Bonzini
    return display_state;
1405 98b50080 Paolo Bonzini
}
1406 98b50080 Paolo Bonzini
1407 3023f332 aliguori
DisplayState *graphic_console_init(vga_hw_update_ptr update,
1408 3023f332 aliguori
                                   vga_hw_invalidate_ptr invalidate,
1409 3023f332 aliguori
                                   vga_hw_screen_dump_ptr screen_dump,
1410 3023f332 aliguori
                                   vga_hw_text_update_ptr text_update,
1411 3023f332 aliguori
                                   void *opaque)
1412 95219897 pbrook
{
1413 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1414 3023f332 aliguori
    DisplayState *ds;
1415 f0f2f976 aurel32
1416 7267c094 Anthony Liguori
    ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
1417 7b5d76da aliguori
    ds->surface = qemu_create_displaysurface(ds, 640, 480);
1418 95219897 pbrook
1419 af3a9031 ths
    s = new_console(ds, GRAPHIC_CONSOLE);
1420 3023f332 aliguori
    if (s == NULL) {
1421 7b5d76da aliguori
        qemu_free_displaysurface(ds);
1422 7267c094 Anthony Liguori
        g_free(ds);
1423 3023f332 aliguori
        return NULL;
1424 3023f332 aliguori
    }
1425 95219897 pbrook
    s->hw_update = update;
1426 95219897 pbrook
    s->hw_invalidate = invalidate;
1427 95219897 pbrook
    s->hw_screen_dump = screen_dump;
1428 4d3b6f6e balrog
    s->hw_text_update = text_update;
1429 95219897 pbrook
    s->hw = opaque;
1430 3023f332 aliguori
1431 f0f2f976 aurel32
    register_displaystate(ds);
1432 3023f332 aliguori
    return ds;
1433 e7f0ad58 bellard
}
1434 e7f0ad58 bellard
1435 95219897 pbrook
int is_graphic_console(void)
1436 e7f0ad58 bellard
{
1437 4d3b6f6e balrog
    return active_console && active_console->console_type == GRAPHIC_CONSOLE;
1438 e7f0ad58 bellard
}
1439 e7f0ad58 bellard
1440 c21bbcfa balrog
int is_fixedsize_console(void)
1441 c21bbcfa balrog
{
1442 c21bbcfa balrog
    return active_console && active_console->console_type != TEXT_CONSOLE;
1443 c21bbcfa balrog
}
1444 c21bbcfa balrog
1445 a528b80c balrog
void console_color_init(DisplayState *ds)
1446 a528b80c balrog
{
1447 a528b80c balrog
    int i, j;
1448 a528b80c balrog
    for (j = 0; j < 2; j++) {
1449 a528b80c balrog
        for (i = 0; i < 8; i++) {
1450 f0f2f976 aurel32
            color_table[j][i] = col_expand(ds,
1451 a528b80c balrog
                   vga_get_color(ds, color_table_rgb[j][i]));
1452 a528b80c balrog
        }
1453 a528b80c balrog
    }
1454 a528b80c balrog
}
1455 a528b80c balrog
1456 4104833f Paolo Bonzini
static void text_console_set_echo(CharDriverState *chr, bool echo)
1457 4104833f Paolo Bonzini
{
1458 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = chr->opaque;
1459 4104833f Paolo Bonzini
1460 4104833f Paolo Bonzini
    s->echo = echo;
1461 4104833f Paolo Bonzini
}
1462 4104833f Paolo Bonzini
1463 bf1bed81 Jan Kiszka
static void text_console_update_cursor(void *opaque)
1464 bf1bed81 Jan Kiszka
{
1465 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = opaque;
1466 bf1bed81 Jan Kiszka
1467 bf1bed81 Jan Kiszka
    s->cursor_visible_phase = !s->cursor_visible_phase;
1468 bf1bed81 Jan Kiszka
    vga_hw_invalidate();
1469 bf1bed81 Jan Kiszka
    qemu_mod_timer(s->cursor_timer,
1470 bf1bed81 Jan Kiszka
                   qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
1471 bf1bed81 Jan Kiszka
}
1472 bf1bed81 Jan Kiszka
1473 44b37b93 Paolo Bonzini
static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
1474 e7f0ad58 bellard
{
1475 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1476 e7f0ad58 bellard
    static int color_inited;
1477 6d6f7c28 pbrook
1478 491e114a Paolo Bonzini
    s = chr->opaque;
1479 6ea314d9 Gerd Hoffmann
1480 e7f0ad58 bellard
    chr->chr_write = console_puts;
1481 6fcfafb7 bellard
1482 e15d7371 bellard
    s->out_fifo.buf = s->out_fifo_buf;
1483 e15d7371 bellard
    s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
1484 7bd427d8 Paolo Bonzini
    s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s);
1485 3023f332 aliguori
    s->ds = ds;
1486 3b46e624 ths
1487 e7f0ad58 bellard
    if (!color_inited) {
1488 e7f0ad58 bellard
        color_inited = 1;
1489 a528b80c balrog
        console_color_init(s->ds);
1490 e7f0ad58 bellard
    }
1491 e7f0ad58 bellard
    s->y_displayed = 0;
1492 e7f0ad58 bellard
    s->y_base = 0;
1493 e7f0ad58 bellard
    s->total_height = DEFAULT_BACKSCROLL;
1494 e7f0ad58 bellard
    s->x = 0;
1495 e7f0ad58 bellard
    s->y = 0;
1496 491e114a Paolo Bonzini
    if (s->console_type == TEXT_CONSOLE) {
1497 491e114a Paolo Bonzini
        s->g_width = ds_get_width(s->ds);
1498 491e114a Paolo Bonzini
        s->g_height = ds_get_height(s->ds);
1499 491e114a Paolo Bonzini
    }
1500 6d6f7c28 pbrook
1501 bf1bed81 Jan Kiszka
    s->cursor_timer =
1502 bf1bed81 Jan Kiszka
        qemu_new_timer_ms(rt_clock, text_console_update_cursor, s);
1503 bf1bed81 Jan Kiszka
1504 4d3b6f6e balrog
    s->hw_invalidate = text_console_invalidate;
1505 4d3b6f6e balrog
    s->hw_text_update = text_console_update;
1506 4d3b6f6e balrog
    s->hw = s;
1507 4d3b6f6e balrog
1508 6d6f7c28 pbrook
    /* Set text attribute defaults */
1509 6d6f7c28 pbrook
    s->t_attrib_default.bold = 0;
1510 6d6f7c28 pbrook
    s->t_attrib_default.uline = 0;
1511 6d6f7c28 pbrook
    s->t_attrib_default.blink = 0;
1512 6d6f7c28 pbrook
    s->t_attrib_default.invers = 0;
1513 6d6f7c28 pbrook
    s->t_attrib_default.unvisible = 0;
1514 6d6f7c28 pbrook
    s->t_attrib_default.fgcol = COLOR_WHITE;
1515 6d6f7c28 pbrook
    s->t_attrib_default.bgcol = COLOR_BLACK;
1516 6d6f7c28 pbrook
    /* set current text attributes to default */
1517 6d6f7c28 pbrook
    s->t_attrib = s->t_attrib_default;
1518 e7f0ad58 bellard
    text_console_resize(s);
1519 e7f0ad58 bellard
1520 51bfa4d3 Gerd Hoffmann
    if (chr->label) {
1521 51bfa4d3 Gerd Hoffmann
        char msg[128];
1522 51bfa4d3 Gerd Hoffmann
        int len;
1523 51bfa4d3 Gerd Hoffmann
1524 735ba588 Gerd Hoffmann
        s->t_attrib.bgcol = COLOR_BLUE;
1525 51bfa4d3 Gerd Hoffmann
        len = snprintf(msg, sizeof(msg), "%s console\r\n", chr->label);
1526 51bfa4d3 Gerd Hoffmann
        console_puts(chr, (uint8_t*)msg, len);
1527 735ba588 Gerd Hoffmann
        s->t_attrib = s->t_attrib_default;
1528 51bfa4d3 Gerd Hoffmann
    }
1529 51bfa4d3 Gerd Hoffmann
1530 127338e6 Amit Shah
    qemu_chr_generic_open(chr);
1531 ceecf1d1 aurel32
    if (chr->init)
1532 ceecf1d1 aurel32
        chr->init(chr);
1533 e7f0ad58 bellard
}
1534 c60e08d9 pbrook
1535 1f51470d Markus Armbruster
CharDriverState *text_console_init(QemuOpts *opts)
1536 2796dae0 aliguori
{
1537 2796dae0 aliguori
    CharDriverState *chr;
1538 76ffb0b4 Gerd Hoffmann
    QemuConsole *s;
1539 491e114a Paolo Bonzini
    unsigned width;
1540 491e114a Paolo Bonzini
    unsigned height;
1541 2796dae0 aliguori
1542 7267c094 Anthony Liguori
    chr = g_malloc0(sizeof(CharDriverState));
1543 2796dae0 aliguori
1544 491e114a Paolo Bonzini
    width = qemu_opt_get_number(opts, "width", 0);
1545 491e114a Paolo Bonzini
    if (width == 0)
1546 491e114a Paolo Bonzini
        width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH;
1547 491e114a Paolo Bonzini
1548 491e114a Paolo Bonzini
    height = qemu_opt_get_number(opts, "height", 0);
1549 491e114a Paolo Bonzini
    if (height == 0)
1550 491e114a Paolo Bonzini
        height = qemu_opt_get_number(opts, "rows", 0) * FONT_HEIGHT;
1551 491e114a Paolo Bonzini
1552 491e114a Paolo Bonzini
    if (width == 0 || height == 0) {
1553 491e114a Paolo Bonzini
        s = new_console(NULL, TEXT_CONSOLE);
1554 491e114a Paolo Bonzini
    } else {
1555 491e114a Paolo Bonzini
        s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE);
1556 491e114a Paolo Bonzini
    }
1557 491e114a Paolo Bonzini
1558 491e114a Paolo Bonzini
    if (!s) {
1559 5354d083 Stefan Weil
        g_free(chr);
1560 1f51470d Markus Armbruster
        return NULL;
1561 491e114a Paolo Bonzini
    }
1562 491e114a Paolo Bonzini
1563 491e114a Paolo Bonzini
    s->chr = chr;
1564 491e114a Paolo Bonzini
    s->g_width = width;
1565 491e114a Paolo Bonzini
    s->g_height = height;
1566 491e114a Paolo Bonzini
    chr->opaque = s;
1567 4104833f Paolo Bonzini
    chr->chr_set_echo = text_console_set_echo;
1568 1f51470d Markus Armbruster
    return chr;
1569 2796dae0 aliguori
}
1570 2796dae0 aliguori
1571 2796dae0 aliguori
void text_consoles_set_display(DisplayState *ds)
1572 2796dae0 aliguori
{
1573 2796dae0 aliguori
    int i;
1574 2796dae0 aliguori
1575 8811e1e1 Markus Armbruster
    for (i = 0; i < nb_consoles; i++) {
1576 8811e1e1 Markus Armbruster
        if (consoles[i]->console_type != GRAPHIC_CONSOLE) {
1577 8811e1e1 Markus Armbruster
            text_console_do_init(consoles[i]->chr, ds);
1578 8811e1e1 Markus Armbruster
        }
1579 2796dae0 aliguori
    }
1580 2796dae0 aliguori
}
1581 2796dae0 aliguori
1582 3023f332 aliguori
void qemu_console_resize(DisplayState *ds, int width, int height)
1583 c60e08d9 pbrook
{
1584 76ffb0b4 Gerd Hoffmann
    QemuConsole *s = get_graphic_console(ds);
1585 f497f140 aliguori
    if (!s) return;
1586 f497f140 aliguori
1587 3023f332 aliguori
    s->g_width = width;
1588 3023f332 aliguori
    s->g_height = height;
1589 3023f332 aliguori
    if (is_graphic_console()) {
1590 7b5d76da aliguori
        ds->surface = qemu_resize_displaysurface(ds, width, height);
1591 a93a4a22 Gerd Hoffmann
        dpy_gfx_resize(ds);
1592 c60e08d9 pbrook
    }
1593 c60e08d9 pbrook
}
1594 38334f76 balrog
1595 3023f332 aliguori
void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
1596 3023f332 aliguori
                       int dst_x, int dst_y, int w, int h)
1597 c21bbcfa balrog
{
1598 3023f332 aliguori
    if (is_graphic_console()) {
1599 a93a4a22 Gerd Hoffmann
        dpy_gfx_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
1600 38334f76 balrog
    }
1601 38334f76 balrog
}
1602 7d957bd8 aliguori
1603 0da2ea1b malc
PixelFormat qemu_different_endianness_pixelformat(int bpp)
1604 7d957bd8 aliguori
{
1605 7d957bd8 aliguori
    PixelFormat pf;
1606 7d957bd8 aliguori
1607 7d957bd8 aliguori
    memset(&pf, 0x00, sizeof(PixelFormat));
1608 7d957bd8 aliguori
1609 7d957bd8 aliguori
    pf.bits_per_pixel = bpp;
1610 feadf1a4 BALATON Zoltan
    pf.bytes_per_pixel = DIV_ROUND_UP(bpp, 8);
1611 7d957bd8 aliguori
    pf.depth = bpp == 32 ? 24 : bpp;
1612 7d957bd8 aliguori
1613 7d957bd8 aliguori
    switch (bpp) {
1614 0da2ea1b malc
        case 24:
1615 0da2ea1b malc
            pf.rmask = 0x000000FF;
1616 0da2ea1b malc
            pf.gmask = 0x0000FF00;
1617 0da2ea1b malc
            pf.bmask = 0x00FF0000;
1618 0da2ea1b malc
            pf.rmax = 255;
1619 0da2ea1b malc
            pf.gmax = 255;
1620 0da2ea1b malc
            pf.bmax = 255;
1621 0da2ea1b malc
            pf.rshift = 0;
1622 0da2ea1b malc
            pf.gshift = 8;
1623 0da2ea1b malc
            pf.bshift = 16;
1624 90a1e3c0 aliguori
            pf.rbits = 8;
1625 90a1e3c0 aliguori
            pf.gbits = 8;
1626 90a1e3c0 aliguori
            pf.bbits = 8;
1627 7d957bd8 aliguori
            break;
1628 0da2ea1b malc
        case 32:
1629 0da2ea1b malc
            pf.rmask = 0x0000FF00;
1630 0da2ea1b malc
            pf.gmask = 0x00FF0000;
1631 0da2ea1b malc
            pf.bmask = 0xFF000000;
1632 0da2ea1b malc
            pf.amask = 0x00000000;
1633 0da2ea1b malc
            pf.amax = 255;
1634 0da2ea1b malc
            pf.rmax = 255;
1635 0da2ea1b malc
            pf.gmax = 255;
1636 0da2ea1b malc
            pf.bmax = 255;
1637 0da2ea1b malc
            pf.ashift = 0;
1638 0da2ea1b malc
            pf.rshift = 8;
1639 0da2ea1b malc
            pf.gshift = 16;
1640 0da2ea1b malc
            pf.bshift = 24;
1641 90a1e3c0 aliguori
            pf.rbits = 8;
1642 90a1e3c0 aliguori
            pf.gbits = 8;
1643 90a1e3c0 aliguori
            pf.bbits = 8;
1644 90a1e3c0 aliguori
            pf.abits = 8;
1645 0da2ea1b malc
            break;
1646 0da2ea1b malc
        default:
1647 0da2ea1b malc
            break;
1648 0da2ea1b malc
    }
1649 0da2ea1b malc
    return pf;
1650 0da2ea1b malc
}
1651 0da2ea1b malc
1652 0da2ea1b malc
PixelFormat qemu_default_pixelformat(int bpp)
1653 0da2ea1b malc
{
1654 0da2ea1b malc
    PixelFormat pf;
1655 0da2ea1b malc
1656 0da2ea1b malc
    memset(&pf, 0x00, sizeof(PixelFormat));
1657 0da2ea1b malc
1658 0da2ea1b malc
    pf.bits_per_pixel = bpp;
1659 feadf1a4 BALATON Zoltan
    pf.bytes_per_pixel = DIV_ROUND_UP(bpp, 8);
1660 0da2ea1b malc
    pf.depth = bpp == 32 ? 24 : bpp;
1661 0da2ea1b malc
1662 0da2ea1b malc
    switch (bpp) {
1663 b6278084 Gerd Hoffmann
        case 15:
1664 b6278084 Gerd Hoffmann
            pf.bits_per_pixel = 16;
1665 b6278084 Gerd Hoffmann
            pf.rmask = 0x00007c00;
1666 b6278084 Gerd Hoffmann
            pf.gmask = 0x000003E0;
1667 b6278084 Gerd Hoffmann
            pf.bmask = 0x0000001F;
1668 b6278084 Gerd Hoffmann
            pf.rmax = 31;
1669 b6278084 Gerd Hoffmann
            pf.gmax = 31;
1670 b6278084 Gerd Hoffmann
            pf.bmax = 31;
1671 b6278084 Gerd Hoffmann
            pf.rshift = 10;
1672 b6278084 Gerd Hoffmann
            pf.gshift = 5;
1673 b6278084 Gerd Hoffmann
            pf.bshift = 0;
1674 b6278084 Gerd Hoffmann
            pf.rbits = 5;
1675 b6278084 Gerd Hoffmann
            pf.gbits = 5;
1676 b6278084 Gerd Hoffmann
            pf.bbits = 5;
1677 b6278084 Gerd Hoffmann
            break;
1678 7d957bd8 aliguori
        case 16:
1679 7d957bd8 aliguori
            pf.rmask = 0x0000F800;
1680 7d957bd8 aliguori
            pf.gmask = 0x000007E0;
1681 7d957bd8 aliguori
            pf.bmask = 0x0000001F;
1682 7d957bd8 aliguori
            pf.rmax = 31;
1683 7d957bd8 aliguori
            pf.gmax = 63;
1684 7d957bd8 aliguori
            pf.bmax = 31;
1685 7d957bd8 aliguori
            pf.rshift = 11;
1686 7d957bd8 aliguori
            pf.gshift = 5;
1687 7d957bd8 aliguori
            pf.bshift = 0;
1688 90a1e3c0 aliguori
            pf.rbits = 5;
1689 90a1e3c0 aliguori
            pf.gbits = 6;
1690 90a1e3c0 aliguori
            pf.bbits = 5;
1691 7d957bd8 aliguori
            break;
1692 7d957bd8 aliguori
        case 24:
1693 0da2ea1b malc
            pf.rmask = 0x00FF0000;
1694 0da2ea1b malc
            pf.gmask = 0x0000FF00;
1695 0da2ea1b malc
            pf.bmask = 0x000000FF;
1696 0da2ea1b malc
            pf.rmax = 255;
1697 0da2ea1b malc
            pf.gmax = 255;
1698 0da2ea1b malc
            pf.bmax = 255;
1699 0da2ea1b malc
            pf.rshift = 16;
1700 0da2ea1b malc
            pf.gshift = 8;
1701 0da2ea1b malc
            pf.bshift = 0;
1702 90a1e3c0 aliguori
            pf.rbits = 8;
1703 90a1e3c0 aliguori
            pf.gbits = 8;
1704 90a1e3c0 aliguori
            pf.bbits = 8;
1705 0eba62e0 Markus Armbruster
            break;
1706 7d957bd8 aliguori
        case 32:
1707 7d957bd8 aliguori
            pf.rmask = 0x00FF0000;
1708 7d957bd8 aliguori
            pf.gmask = 0x0000FF00;
1709 7d957bd8 aliguori
            pf.bmask = 0x000000FF;
1710 7d957bd8 aliguori
            pf.rmax = 255;
1711 7d957bd8 aliguori
            pf.gmax = 255;
1712 7d957bd8 aliguori
            pf.bmax = 255;
1713 7d957bd8 aliguori
            pf.rshift = 16;
1714 7d957bd8 aliguori
            pf.gshift = 8;
1715 7d957bd8 aliguori
            pf.bshift = 0;
1716 90a1e3c0 aliguori
            pf.rbits = 8;
1717 90a1e3c0 aliguori
            pf.gbits = 8;
1718 90a1e3c0 aliguori
            pf.bbits = 8;
1719 7d957bd8 aliguori
            break;
1720 7d957bd8 aliguori
        default:
1721 7d957bd8 aliguori
            break;
1722 7d957bd8 aliguori
    }
1723 7d957bd8 aliguori
    return pf;
1724 7d957bd8 aliguori
}