Statistics
| Branch: | Revision:

root / console.c @ e3e87df4

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