Statistics
| Branch: | Revision:

root / console.c @ e4fc8781

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