Statistics
| Branch: | Revision:

root / console.c @ 16735102

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