Statistics
| Branch: | Revision:

root / console.c @ b5dc7732

History | View | Annotate | Download (36.6 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 af3a9031 ths
    TEXT_CONSOLE,
112 af3a9031 ths
    TEXT_CONSOLE_FIXED_SIZE
113 af3a9031 ths
} 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 af3a9031 ths
    console_type_t console_type;
119 e7f0ad58 bellard
    DisplayState *ds;
120 95219897 pbrook
    /* Graphic console state.  */
121 95219897 pbrook
    vga_hw_update_ptr hw_update;
122 95219897 pbrook
    vga_hw_invalidate_ptr hw_invalidate;
123 95219897 pbrook
    vga_hw_screen_dump_ptr hw_screen_dump;
124 4d3b6f6e balrog
    vga_hw_text_update_ptr hw_text_update;
125 95219897 pbrook
    void *hw;
126 95219897 pbrook
127 e7f0ad58 bellard
    int g_width, g_height;
128 e7f0ad58 bellard
    int width;
129 e7f0ad58 bellard
    int height;
130 e7f0ad58 bellard
    int total_height;
131 e7f0ad58 bellard
    int backscroll_height;
132 e7f0ad58 bellard
    int x, y;
133 adb47967 ths
    int x_saved, y_saved;
134 e7f0ad58 bellard
    int y_displayed;
135 e7f0ad58 bellard
    int y_base;
136 6d6f7c28 pbrook
    TextAttributes t_attrib_default; /* default text attributes */
137 6d6f7c28 pbrook
    TextAttributes t_attrib; /* currently active text attributes */
138 e7f0ad58 bellard
    TextCell *cells;
139 4d3b6f6e balrog
    int text_x[2], text_y[2], cursor_invalidate;
140 e7f0ad58 bellard
141 e7f0ad58 bellard
    enum TTYState state;
142 e7f0ad58 bellard
    int esc_params[MAX_ESC_PARAMS];
143 e7f0ad58 bellard
    int nb_esc_params;
144 e7f0ad58 bellard
145 e5b0bc44 pbrook
    CharDriverState *chr;
146 e15d7371 bellard
    /* fifo for key pressed */
147 e15d7371 bellard
    QEMUFIFO out_fifo;
148 e15d7371 bellard
    uint8_t out_fifo_buf[16];
149 e15d7371 bellard
    QEMUTimer *kbd_timer;
150 e7f0ad58 bellard
};
151 e7f0ad58 bellard
152 e7f0ad58 bellard
static TextConsole *active_console;
153 e7f0ad58 bellard
static TextConsole *consoles[MAX_CONSOLES];
154 e7f0ad58 bellard
static int nb_consoles = 0;
155 e7f0ad58 bellard
156 95219897 pbrook
void vga_hw_update(void)
157 95219897 pbrook
{
158 adb47967 ths
    if (active_console && active_console->hw_update)
159 95219897 pbrook
        active_console->hw_update(active_console->hw);
160 95219897 pbrook
}
161 95219897 pbrook
162 95219897 pbrook
void vga_hw_invalidate(void)
163 95219897 pbrook
{
164 95219897 pbrook
    if (active_console->hw_invalidate)
165 95219897 pbrook
        active_console->hw_invalidate(active_console->hw);
166 95219897 pbrook
}
167 95219897 pbrook
168 95219897 pbrook
void vga_hw_screen_dump(const char *filename)
169 95219897 pbrook
{
170 95219897 pbrook
    /* There is currently no was of specifying which screen we want to dump,
171 95219897 pbrook
       so always dump the dirst one.  */
172 95219897 pbrook
    if (consoles[0]->hw_screen_dump)
173 95219897 pbrook
        consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
174 95219897 pbrook
}
175 95219897 pbrook
176 4d3b6f6e balrog
void vga_hw_text_update(console_ch_t *chardata)
177 4d3b6f6e balrog
{
178 4d3b6f6e balrog
    if (active_console && active_console->hw_text_update)
179 4d3b6f6e balrog
        active_console->hw_text_update(active_console->hw, chardata);
180 4d3b6f6e balrog
}
181 4d3b6f6e balrog
182 e7f0ad58 bellard
/* convert a RGBA color to a color index usable in graphic primitives */
183 e7f0ad58 bellard
static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
184 e7f0ad58 bellard
{
185 e7f0ad58 bellard
    unsigned int r, g, b, color;
186 e7f0ad58 bellard
187 e7f0ad58 bellard
    switch(ds->depth) {
188 e7f0ad58 bellard
#if 0
189 e7f0ad58 bellard
    case 8:
190 e7f0ad58 bellard
        r = (rgba >> 16) & 0xff;
191 e7f0ad58 bellard
        g = (rgba >> 8) & 0xff;
192 e7f0ad58 bellard
        b = (rgba) & 0xff;
193 5fafdf24 ths
        color = (rgb_to_index[r] * 6 * 6) +
194 5fafdf24 ths
            (rgb_to_index[g] * 6) +
195 e7f0ad58 bellard
            (rgb_to_index[b]);
196 e7f0ad58 bellard
        break;
197 e7f0ad58 bellard
#endif
198 e7f0ad58 bellard
    case 15:
199 e7f0ad58 bellard
        r = (rgba >> 16) & 0xff;
200 e7f0ad58 bellard
        g = (rgba >> 8) & 0xff;
201 e7f0ad58 bellard
        b = (rgba) & 0xff;
202 e7f0ad58 bellard
        color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
203 e7f0ad58 bellard
        break;
204 e7f0ad58 bellard
    case 16:
205 e7f0ad58 bellard
        r = (rgba >> 16) & 0xff;
206 e7f0ad58 bellard
        g = (rgba >> 8) & 0xff;
207 e7f0ad58 bellard
        b = (rgba) & 0xff;
208 e7f0ad58 bellard
        color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
209 e7f0ad58 bellard
        break;
210 e7f0ad58 bellard
    case 32:
211 e7f0ad58 bellard
    default:
212 e7f0ad58 bellard
        color = rgba;
213 e7f0ad58 bellard
        break;
214 e7f0ad58 bellard
    }
215 e7f0ad58 bellard
    return color;
216 e7f0ad58 bellard
}
217 e7f0ad58 bellard
218 5fafdf24 ths
static void vga_fill_rect (DisplayState *ds,
219 e7f0ad58 bellard
                           int posx, int posy, int width, int height, uint32_t color)
220 e7f0ad58 bellard
{
221 e7f0ad58 bellard
    uint8_t *d, *d1;
222 e7f0ad58 bellard
    int x, y, bpp;
223 3b46e624 ths
224 e7f0ad58 bellard
    bpp = (ds->depth + 7) >> 3;
225 5fafdf24 ths
    d1 = ds->data +
226 e7f0ad58 bellard
        ds->linesize * posy + bpp * posx;
227 e7f0ad58 bellard
    for (y = 0; y < height; y++) {
228 e7f0ad58 bellard
        d = d1;
229 e7f0ad58 bellard
        switch(bpp) {
230 e7f0ad58 bellard
        case 1:
231 e7f0ad58 bellard
            for (x = 0; x < width; x++) {
232 e7f0ad58 bellard
                *((uint8_t *)d) = color;
233 e7f0ad58 bellard
                d++;
234 e7f0ad58 bellard
            }
235 e7f0ad58 bellard
            break;
236 e7f0ad58 bellard
        case 2:
237 e7f0ad58 bellard
            for (x = 0; x < width; x++) {
238 e7f0ad58 bellard
                *((uint16_t *)d) = color;
239 e7f0ad58 bellard
                d += 2;
240 e7f0ad58 bellard
            }
241 e7f0ad58 bellard
            break;
242 e7f0ad58 bellard
        case 4:
243 e7f0ad58 bellard
            for (x = 0; x < width; x++) {
244 e7f0ad58 bellard
                *((uint32_t *)d) = color;
245 e7f0ad58 bellard
                d += 4;
246 e7f0ad58 bellard
            }
247 e7f0ad58 bellard
            break;
248 e7f0ad58 bellard
        }
249 e7f0ad58 bellard
        d1 += ds->linesize;
250 e7f0ad58 bellard
    }
251 e7f0ad58 bellard
}
252 e7f0ad58 bellard
253 e7f0ad58 bellard
/* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
254 e7f0ad58 bellard
static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h)
255 e7f0ad58 bellard
{
256 e7f0ad58 bellard
    const uint8_t *s;
257 e7f0ad58 bellard
    uint8_t *d;
258 e7f0ad58 bellard
    int wb, y, bpp;
259 e7f0ad58 bellard
260 e7f0ad58 bellard
    bpp = (ds->depth + 7) >> 3;
261 e7f0ad58 bellard
    wb = w * bpp;
262 e7f0ad58 bellard
    if (yd <= ys) {
263 5fafdf24 ths
        s = ds->data +
264 e7f0ad58 bellard
            ds->linesize * ys + bpp * xs;
265 5fafdf24 ths
        d = ds->data +
266 e7f0ad58 bellard
            ds->linesize * yd + bpp * xd;
267 e7f0ad58 bellard
        for (y = 0; y < h; y++) {
268 e7f0ad58 bellard
            memmove(d, s, wb);
269 e7f0ad58 bellard
            d += ds->linesize;
270 e7f0ad58 bellard
            s += ds->linesize;
271 e7f0ad58 bellard
        }
272 e7f0ad58 bellard
    } else {
273 5fafdf24 ths
        s = ds->data +
274 e7f0ad58 bellard
            ds->linesize * (ys + h - 1) + bpp * xs;
275 5fafdf24 ths
        d = ds->data +
276 e7f0ad58 bellard
            ds->linesize * (yd + h - 1) + bpp * xd;
277 e7f0ad58 bellard
       for (y = 0; y < h; y++) {
278 e7f0ad58 bellard
            memmove(d, s, wb);
279 e7f0ad58 bellard
            d -= ds->linesize;
280 e7f0ad58 bellard
            s -= ds->linesize;
281 e7f0ad58 bellard
        }
282 e7f0ad58 bellard
    }
283 e7f0ad58 bellard
}
284 e7f0ad58 bellard
285 e7f0ad58 bellard
/***********************************************************/
286 e7f0ad58 bellard
/* basic char display */
287 e7f0ad58 bellard
288 e7f0ad58 bellard
#define FONT_HEIGHT 16
289 e7f0ad58 bellard
#define FONT_WIDTH 8
290 e7f0ad58 bellard
291 e7f0ad58 bellard
#include "vgafont.h"
292 e7f0ad58 bellard
293 e7f0ad58 bellard
#define cbswap_32(__x) \
294 e7f0ad58 bellard
((uint32_t)( \
295 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
296 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
297 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
298 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
299 e7f0ad58 bellard
300 e7f0ad58 bellard
#ifdef WORDS_BIGENDIAN
301 e7f0ad58 bellard
#define PAT(x) x
302 e7f0ad58 bellard
#else
303 e7f0ad58 bellard
#define PAT(x) cbswap_32(x)
304 e7f0ad58 bellard
#endif
305 e7f0ad58 bellard
306 e7f0ad58 bellard
static const uint32_t dmask16[16] = {
307 e7f0ad58 bellard
    PAT(0x00000000),
308 e7f0ad58 bellard
    PAT(0x000000ff),
309 e7f0ad58 bellard
    PAT(0x0000ff00),
310 e7f0ad58 bellard
    PAT(0x0000ffff),
311 e7f0ad58 bellard
    PAT(0x00ff0000),
312 e7f0ad58 bellard
    PAT(0x00ff00ff),
313 e7f0ad58 bellard
    PAT(0x00ffff00),
314 e7f0ad58 bellard
    PAT(0x00ffffff),
315 e7f0ad58 bellard
    PAT(0xff000000),
316 e7f0ad58 bellard
    PAT(0xff0000ff),
317 e7f0ad58 bellard
    PAT(0xff00ff00),
318 e7f0ad58 bellard
    PAT(0xff00ffff),
319 e7f0ad58 bellard
    PAT(0xffff0000),
320 e7f0ad58 bellard
    PAT(0xffff00ff),
321 e7f0ad58 bellard
    PAT(0xffffff00),
322 e7f0ad58 bellard
    PAT(0xffffffff),
323 e7f0ad58 bellard
};
324 e7f0ad58 bellard
325 e7f0ad58 bellard
static const uint32_t dmask4[4] = {
326 e7f0ad58 bellard
    PAT(0x00000000),
327 e7f0ad58 bellard
    PAT(0x0000ffff),
328 e7f0ad58 bellard
    PAT(0xffff0000),
329 e7f0ad58 bellard
    PAT(0xffffffff),
330 e7f0ad58 bellard
};
331 e7f0ad58 bellard
332 6d6f7c28 pbrook
static uint32_t color_table[2][8];
333 6d6f7c28 pbrook
334 6d6f7c28 pbrook
enum color_names {
335 6d6f7c28 pbrook
    COLOR_BLACK   = 0,
336 6d6f7c28 pbrook
    COLOR_RED     = 1,
337 6d6f7c28 pbrook
    COLOR_GREEN   = 2,
338 6d6f7c28 pbrook
    COLOR_YELLOW  = 3,
339 6d6f7c28 pbrook
    COLOR_BLUE    = 4,
340 6d6f7c28 pbrook
    COLOR_MAGENTA = 5,
341 6d6f7c28 pbrook
    COLOR_CYAN    = 6,
342 6d6f7c28 pbrook
    COLOR_WHITE   = 7
343 6d6f7c28 pbrook
};
344 6d6f7c28 pbrook
345 6d6f7c28 pbrook
static const uint32_t color_table_rgb[2][8] = {
346 6d6f7c28 pbrook
    {   /* dark */
347 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0x00),  /* black */
348 26489844 bellard
        QEMU_RGB(0xaa, 0x00, 0x00),  /* red */
349 26489844 bellard
        QEMU_RGB(0x00, 0xaa, 0x00),  /* green */
350 26489844 bellard
        QEMU_RGB(0xaa, 0xaa, 0x00),  /* yellow */
351 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0xaa),  /* blue */
352 26489844 bellard
        QEMU_RGB(0xaa, 0x00, 0xaa),  /* magenta */
353 26489844 bellard
        QEMU_RGB(0x00, 0xaa, 0xaa),  /* cyan */
354 26489844 bellard
        QEMU_RGB(0xaa, 0xaa, 0xaa),  /* white */
355 6d6f7c28 pbrook
    },
356 6d6f7c28 pbrook
    {   /* bright */
357 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0x00),  /* black */
358 26489844 bellard
        QEMU_RGB(0xff, 0x00, 0x00),  /* red */
359 26489844 bellard
        QEMU_RGB(0x00, 0xff, 0x00),  /* green */
360 26489844 bellard
        QEMU_RGB(0xff, 0xff, 0x00),  /* yellow */
361 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0xff),  /* blue */
362 26489844 bellard
        QEMU_RGB(0xff, 0x00, 0xff),  /* magenta */
363 26489844 bellard
        QEMU_RGB(0x00, 0xff, 0xff),  /* cyan */
364 26489844 bellard
        QEMU_RGB(0xff, 0xff, 0xff),  /* white */
365 6d6f7c28 pbrook
    }
366 e7f0ad58 bellard
};
367 e7f0ad58 bellard
368 e7f0ad58 bellard
static inline unsigned int col_expand(DisplayState *ds, unsigned int col)
369 e7f0ad58 bellard
{
370 e7f0ad58 bellard
    switch(ds->depth) {
371 e7f0ad58 bellard
    case 8:
372 e7f0ad58 bellard
        col |= col << 8;
373 e7f0ad58 bellard
        col |= col << 16;
374 e7f0ad58 bellard
        break;
375 e7f0ad58 bellard
    case 15:
376 e7f0ad58 bellard
    case 16:
377 e7f0ad58 bellard
        col |= col << 16;
378 e7f0ad58 bellard
        break;
379 e7f0ad58 bellard
    default:
380 e7f0ad58 bellard
        break;
381 e7f0ad58 bellard
    }
382 e7f0ad58 bellard
383 e7f0ad58 bellard
    return col;
384 e7f0ad58 bellard
}
385 6d6f7c28 pbrook
#ifdef DEBUG_CONSOLE
386 6d6f7c28 pbrook
static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
387 6d6f7c28 pbrook
{
388 6d6f7c28 pbrook
    if (t_attrib->bold) {
389 6d6f7c28 pbrook
        printf("b");
390 6d6f7c28 pbrook
    } else {
391 6d6f7c28 pbrook
        printf(" ");
392 6d6f7c28 pbrook
    }
393 6d6f7c28 pbrook
    if (t_attrib->uline) {
394 6d6f7c28 pbrook
        printf("u");
395 6d6f7c28 pbrook
    } else {
396 6d6f7c28 pbrook
        printf(" ");
397 6d6f7c28 pbrook
    }
398 6d6f7c28 pbrook
    if (t_attrib->blink) {
399 6d6f7c28 pbrook
        printf("l");
400 6d6f7c28 pbrook
    } else {
401 6d6f7c28 pbrook
        printf(" ");
402 6d6f7c28 pbrook
    }
403 6d6f7c28 pbrook
    if (t_attrib->invers) {
404 6d6f7c28 pbrook
        printf("i");
405 6d6f7c28 pbrook
    } else {
406 6d6f7c28 pbrook
        printf(" ");
407 6d6f7c28 pbrook
    }
408 6d6f7c28 pbrook
    if (t_attrib->unvisible) {
409 6d6f7c28 pbrook
        printf("n");
410 6d6f7c28 pbrook
    } else {
411 6d6f7c28 pbrook
        printf(" ");
412 6d6f7c28 pbrook
    }
413 6d6f7c28 pbrook
414 6d6f7c28 pbrook
    printf(" fg: %d bg: %d ch:'%2X' '%c'\n", t_attrib->fgcol, t_attrib->bgcol, ch, ch);
415 6d6f7c28 pbrook
}
416 6d6f7c28 pbrook
#endif
417 e7f0ad58 bellard
418 5fafdf24 ths
static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
419 6d6f7c28 pbrook
                          TextAttributes *t_attrib)
420 e7f0ad58 bellard
{
421 e7f0ad58 bellard
    uint8_t *d;
422 e7f0ad58 bellard
    const uint8_t *font_ptr;
423 e7f0ad58 bellard
    unsigned int font_data, linesize, xorcol, bpp;
424 e7f0ad58 bellard
    int i;
425 6d6f7c28 pbrook
    unsigned int fgcol, bgcol;
426 6d6f7c28 pbrook
427 6d6f7c28 pbrook
#ifdef DEBUG_CONSOLE
428 6d6f7c28 pbrook
    printf("x: %2i y: %2i", x, y);
429 6d6f7c28 pbrook
    console_print_text_attributes(t_attrib, ch);
430 6d6f7c28 pbrook
#endif
431 6d6f7c28 pbrook
432 6d6f7c28 pbrook
    if (t_attrib->invers) {
433 6d6f7c28 pbrook
        bgcol = color_table[t_attrib->bold][t_attrib->fgcol];
434 6d6f7c28 pbrook
        fgcol = color_table[t_attrib->bold][t_attrib->bgcol];
435 6d6f7c28 pbrook
    } else {
436 6d6f7c28 pbrook
        fgcol = color_table[t_attrib->bold][t_attrib->fgcol];
437 6d6f7c28 pbrook
        bgcol = color_table[t_attrib->bold][t_attrib->bgcol];
438 6d6f7c28 pbrook
    }
439 e7f0ad58 bellard
440 e7f0ad58 bellard
    bpp = (ds->depth + 7) >> 3;
441 5fafdf24 ths
    d = ds->data +
442 e7f0ad58 bellard
        ds->linesize * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
443 e7f0ad58 bellard
    linesize = ds->linesize;
444 e7f0ad58 bellard
    font_ptr = vgafont16 + FONT_HEIGHT * ch;
445 e7f0ad58 bellard
    xorcol = bgcol ^ fgcol;
446 e7f0ad58 bellard
    switch(ds->depth) {
447 e7f0ad58 bellard
    case 8:
448 e7f0ad58 bellard
        for(i = 0; i < FONT_HEIGHT; i++) {
449 e7f0ad58 bellard
            font_data = *font_ptr++;
450 6d6f7c28 pbrook
            if (t_attrib->uline
451 6d6f7c28 pbrook
                && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
452 6d6f7c28 pbrook
                font_data = 0xFFFF;
453 6d6f7c28 pbrook
            }
454 e7f0ad58 bellard
            ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
455 e7f0ad58 bellard
            ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
456 e7f0ad58 bellard
            d += linesize;
457 e7f0ad58 bellard
        }
458 e7f0ad58 bellard
        break;
459 e7f0ad58 bellard
    case 16:
460 e7f0ad58 bellard
    case 15:
461 e7f0ad58 bellard
        for(i = 0; i < FONT_HEIGHT; i++) {
462 e7f0ad58 bellard
            font_data = *font_ptr++;
463 6d6f7c28 pbrook
            if (t_attrib->uline
464 6d6f7c28 pbrook
                && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
465 6d6f7c28 pbrook
                font_data = 0xFFFF;
466 6d6f7c28 pbrook
            }
467 e7f0ad58 bellard
            ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
468 e7f0ad58 bellard
            ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
469 e7f0ad58 bellard
            ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
470 e7f0ad58 bellard
            ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
471 e7f0ad58 bellard
            d += linesize;
472 e7f0ad58 bellard
        }
473 e7f0ad58 bellard
        break;
474 e7f0ad58 bellard
    case 32:
475 e7f0ad58 bellard
        for(i = 0; i < FONT_HEIGHT; i++) {
476 e7f0ad58 bellard
            font_data = *font_ptr++;
477 6d6f7c28 pbrook
            if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
478 6d6f7c28 pbrook
                font_data = 0xFFFF;
479 6d6f7c28 pbrook
            }
480 e7f0ad58 bellard
            ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
481 e7f0ad58 bellard
            ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
482 e7f0ad58 bellard
            ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
483 e7f0ad58 bellard
            ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
484 e7f0ad58 bellard
            ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
485 e7f0ad58 bellard
            ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
486 e7f0ad58 bellard
            ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
487 e7f0ad58 bellard
            ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
488 e7f0ad58 bellard
            d += linesize;
489 e7f0ad58 bellard
        }
490 e7f0ad58 bellard
        break;
491 e7f0ad58 bellard
    }
492 e7f0ad58 bellard
}
493 e7f0ad58 bellard
494 e7f0ad58 bellard
static void text_console_resize(TextConsole *s)
495 e7f0ad58 bellard
{
496 e7f0ad58 bellard
    TextCell *cells, *c, *c1;
497 e7f0ad58 bellard
    int w1, x, y, last_width;
498 e7f0ad58 bellard
499 e7f0ad58 bellard
    last_width = s->width;
500 e7f0ad58 bellard
    s->width = s->g_width / FONT_WIDTH;
501 e7f0ad58 bellard
    s->height = s->g_height / FONT_HEIGHT;
502 e7f0ad58 bellard
503 e7f0ad58 bellard
    w1 = last_width;
504 e7f0ad58 bellard
    if (s->width < w1)
505 e7f0ad58 bellard
        w1 = s->width;
506 e7f0ad58 bellard
507 e7f0ad58 bellard
    cells = qemu_malloc(s->width * s->total_height * sizeof(TextCell));
508 e7f0ad58 bellard
    for(y = 0; y < s->total_height; y++) {
509 e7f0ad58 bellard
        c = &cells[y * s->width];
510 e7f0ad58 bellard
        if (w1 > 0) {
511 e7f0ad58 bellard
            c1 = &s->cells[y * last_width];
512 e7f0ad58 bellard
            for(x = 0; x < w1; x++) {
513 e7f0ad58 bellard
                *c++ = *c1++;
514 e7f0ad58 bellard
            }
515 e7f0ad58 bellard
        }
516 e7f0ad58 bellard
        for(x = w1; x < s->width; x++) {
517 e7f0ad58 bellard
            c->ch = ' ';
518 6d6f7c28 pbrook
            c->t_attrib = s->t_attrib_default;
519 e7f0ad58 bellard
            c++;
520 e7f0ad58 bellard
        }
521 e7f0ad58 bellard
    }
522 a528b80c balrog
    qemu_free(s->cells);
523 e7f0ad58 bellard
    s->cells = cells;
524 e7f0ad58 bellard
}
525 e7f0ad58 bellard
526 4d3b6f6e balrog
static inline void text_update_xy(TextConsole *s, int x, int y)
527 4d3b6f6e balrog
{
528 4d3b6f6e balrog
    s->text_x[0] = MIN(s->text_x[0], x);
529 4d3b6f6e balrog
    s->text_x[1] = MAX(s->text_x[1], x);
530 4d3b6f6e balrog
    s->text_y[0] = MIN(s->text_y[0], y);
531 4d3b6f6e balrog
    s->text_y[1] = MAX(s->text_y[1], y);
532 4d3b6f6e balrog
}
533 4d3b6f6e balrog
534 e7f0ad58 bellard
static void update_xy(TextConsole *s, int x, int y)
535 e7f0ad58 bellard
{
536 e7f0ad58 bellard
    TextCell *c;
537 e7f0ad58 bellard
    int y1, y2;
538 e7f0ad58 bellard
539 e7f0ad58 bellard
    if (s == active_console) {
540 4d3b6f6e balrog
        if (!s->ds->depth) {
541 4d3b6f6e balrog
            text_update_xy(s, x, y);
542 4d3b6f6e balrog
            return;
543 4d3b6f6e balrog
        }
544 4d3b6f6e balrog
545 e7f0ad58 bellard
        y1 = (s->y_base + y) % s->total_height;
546 e7f0ad58 bellard
        y2 = y1 - s->y_displayed;
547 e7f0ad58 bellard
        if (y2 < 0)
548 e7f0ad58 bellard
            y2 += s->total_height;
549 e7f0ad58 bellard
        if (y2 < s->height) {
550 e7f0ad58 bellard
            c = &s->cells[y1 * s->width + x];
551 5fafdf24 ths
            vga_putcharxy(s->ds, x, y2, c->ch,
552 6d6f7c28 pbrook
                          &(c->t_attrib));
553 5fafdf24 ths
            dpy_update(s->ds, x * FONT_WIDTH, y2 * FONT_HEIGHT,
554 e7f0ad58 bellard
                       FONT_WIDTH, FONT_HEIGHT);
555 e7f0ad58 bellard
        }
556 e7f0ad58 bellard
    }
557 e7f0ad58 bellard
}
558 e7f0ad58 bellard
559 e7f0ad58 bellard
static void console_show_cursor(TextConsole *s, int show)
560 e7f0ad58 bellard
{
561 e7f0ad58 bellard
    TextCell *c;
562 e7f0ad58 bellard
    int y, y1;
563 e7f0ad58 bellard
564 e7f0ad58 bellard
    if (s == active_console) {
565 ed8276ac ths
        int x = s->x;
566 4d3b6f6e balrog
567 4d3b6f6e balrog
        if (!s->ds->depth) {
568 4d3b6f6e balrog
            s->cursor_invalidate = 1;
569 4d3b6f6e balrog
            return;
570 4d3b6f6e balrog
        }
571 4d3b6f6e balrog
572 ed8276ac ths
        if (x >= s->width) {
573 ed8276ac ths
            x = s->width - 1;
574 ed8276ac ths
        }
575 e7f0ad58 bellard
        y1 = (s->y_base + s->y) % s->total_height;
576 e7f0ad58 bellard
        y = y1 - s->y_displayed;
577 e7f0ad58 bellard
        if (y < 0)
578 e7f0ad58 bellard
            y += s->total_height;
579 e7f0ad58 bellard
        if (y < s->height) {
580 ed8276ac ths
            c = &s->cells[y1 * s->width + x];
581 e7f0ad58 bellard
            if (show) {
582 6d6f7c28 pbrook
                TextAttributes t_attrib = s->t_attrib_default;
583 6d6f7c28 pbrook
                t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
584 ed8276ac ths
                vga_putcharxy(s->ds, x, y, c->ch, &t_attrib);
585 e7f0ad58 bellard
            } else {
586 ed8276ac ths
                vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib));
587 e7f0ad58 bellard
            }
588 5fafdf24 ths
            dpy_update(s->ds, x * FONT_WIDTH, y * FONT_HEIGHT,
589 e7f0ad58 bellard
                       FONT_WIDTH, FONT_HEIGHT);
590 e7f0ad58 bellard
        }
591 e7f0ad58 bellard
    }
592 e7f0ad58 bellard
}
593 e7f0ad58 bellard
594 e7f0ad58 bellard
static void console_refresh(TextConsole *s)
595 e7f0ad58 bellard
{
596 e7f0ad58 bellard
    TextCell *c;
597 e7f0ad58 bellard
    int x, y, y1;
598 e7f0ad58 bellard
599 5fafdf24 ths
    if (s != active_console)
600 e7f0ad58 bellard
        return;
601 4d3b6f6e balrog
    if (!s->ds->depth) {
602 4d3b6f6e balrog
        s->text_x[0] = 0;
603 4d3b6f6e balrog
        s->text_y[0] = 0;
604 4d3b6f6e balrog
        s->text_x[1] = s->width - 1;
605 4d3b6f6e balrog
        s->text_y[1] = s->height - 1;
606 4d3b6f6e balrog
        s->cursor_invalidate = 1;
607 4d3b6f6e balrog
        return;
608 4d3b6f6e balrog
    }
609 e7f0ad58 bellard
610 e7f0ad58 bellard
    vga_fill_rect(s->ds, 0, 0, s->ds->width, s->ds->height,
611 6d6f7c28 pbrook
                  color_table[0][COLOR_BLACK]);
612 e7f0ad58 bellard
    y1 = s->y_displayed;
613 e7f0ad58 bellard
    for(y = 0; y < s->height; y++) {
614 e7f0ad58 bellard
        c = s->cells + y1 * s->width;
615 e7f0ad58 bellard
        for(x = 0; x < s->width; x++) {
616 5fafdf24 ths
            vga_putcharxy(s->ds, x, y, c->ch,
617 6d6f7c28 pbrook
                          &(c->t_attrib));
618 e7f0ad58 bellard
            c++;
619 e7f0ad58 bellard
        }
620 e7f0ad58 bellard
        if (++y1 == s->total_height)
621 e7f0ad58 bellard
            y1 = 0;
622 e7f0ad58 bellard
    }
623 e7f0ad58 bellard
    dpy_update(s->ds, 0, 0, s->ds->width, s->ds->height);
624 e7f0ad58 bellard
    console_show_cursor(s, 1);
625 e7f0ad58 bellard
}
626 e7f0ad58 bellard
627 e7f0ad58 bellard
static void console_scroll(int ydelta)
628 e7f0ad58 bellard
{
629 e7f0ad58 bellard
    TextConsole *s;
630 e7f0ad58 bellard
    int i, y1;
631 3b46e624 ths
632 e7f0ad58 bellard
    s = active_console;
633 af3a9031 ths
    if (!s || (s->console_type == GRAPHIC_CONSOLE))
634 e7f0ad58 bellard
        return;
635 e7f0ad58 bellard
636 e7f0ad58 bellard
    if (ydelta > 0) {
637 e7f0ad58 bellard
        for(i = 0; i < ydelta; i++) {
638 e7f0ad58 bellard
            if (s->y_displayed == s->y_base)
639 e7f0ad58 bellard
                break;
640 e7f0ad58 bellard
            if (++s->y_displayed == s->total_height)
641 e7f0ad58 bellard
                s->y_displayed = 0;
642 e7f0ad58 bellard
        }
643 e7f0ad58 bellard
    } else {
644 e7f0ad58 bellard
        ydelta = -ydelta;
645 e7f0ad58 bellard
        i = s->backscroll_height;
646 e7f0ad58 bellard
        if (i > s->total_height - s->height)
647 e7f0ad58 bellard
            i = s->total_height - s->height;
648 e7f0ad58 bellard
        y1 = s->y_base - i;
649 e7f0ad58 bellard
        if (y1 < 0)
650 e7f0ad58 bellard
            y1 += s->total_height;
651 e7f0ad58 bellard
        for(i = 0; i < ydelta; i++) {
652 e7f0ad58 bellard
            if (s->y_displayed == y1)
653 e7f0ad58 bellard
                break;
654 e7f0ad58 bellard
            if (--s->y_displayed < 0)
655 e7f0ad58 bellard
                s->y_displayed = s->total_height - 1;
656 e7f0ad58 bellard
        }
657 e7f0ad58 bellard
    }
658 e7f0ad58 bellard
    console_refresh(s);
659 e7f0ad58 bellard
}
660 e7f0ad58 bellard
661 e7f0ad58 bellard
static void console_put_lf(TextConsole *s)
662 e7f0ad58 bellard
{
663 e7f0ad58 bellard
    TextCell *c;
664 e7f0ad58 bellard
    int x, y1;
665 e7f0ad58 bellard
666 e7f0ad58 bellard
    s->y++;
667 e7f0ad58 bellard
    if (s->y >= s->height) {
668 e7f0ad58 bellard
        s->y = s->height - 1;
669 6d6f7c28 pbrook
670 e7f0ad58 bellard
        if (s->y_displayed == s->y_base) {
671 e7f0ad58 bellard
            if (++s->y_displayed == s->total_height)
672 e7f0ad58 bellard
                s->y_displayed = 0;
673 e7f0ad58 bellard
        }
674 e7f0ad58 bellard
        if (++s->y_base == s->total_height)
675 e7f0ad58 bellard
            s->y_base = 0;
676 e7f0ad58 bellard
        if (s->backscroll_height < s->total_height)
677 e7f0ad58 bellard
            s->backscroll_height++;
678 e7f0ad58 bellard
        y1 = (s->y_base + s->height - 1) % s->total_height;
679 e7f0ad58 bellard
        c = &s->cells[y1 * s->width];
680 e7f0ad58 bellard
        for(x = 0; x < s->width; x++) {
681 e7f0ad58 bellard
            c->ch = ' ';
682 6d6f7c28 pbrook
            c->t_attrib = s->t_attrib_default;
683 e7f0ad58 bellard
            c++;
684 e7f0ad58 bellard
        }
685 e7f0ad58 bellard
        if (s == active_console && s->y_displayed == s->y_base) {
686 4d3b6f6e balrog
            if (!s->ds->depth) {
687 4d3b6f6e balrog
                s->text_x[0] = 0;
688 4d3b6f6e balrog
                s->text_y[0] = 0;
689 4d3b6f6e balrog
                s->text_x[1] = s->width - 1;
690 4d3b6f6e balrog
                s->text_y[1] = s->height - 1;
691 4d3b6f6e balrog
                return;
692 4d3b6f6e balrog
            }
693 4d3b6f6e balrog
694 5fafdf24 ths
            vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0,
695 5fafdf24 ths
                       s->width * FONT_WIDTH,
696 e7f0ad58 bellard
                       (s->height - 1) * FONT_HEIGHT);
697 e7f0ad58 bellard
            vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
698 5fafdf24 ths
                          s->width * FONT_WIDTH, FONT_HEIGHT,
699 6d6f7c28 pbrook
                          color_table[0][s->t_attrib_default.bgcol]);
700 5fafdf24 ths
            dpy_update(s->ds, 0, 0,
701 e7f0ad58 bellard
                       s->width * FONT_WIDTH, s->height * FONT_HEIGHT);
702 e7f0ad58 bellard
        }
703 e7f0ad58 bellard
    }
704 e7f0ad58 bellard
}
705 e7f0ad58 bellard
706 6d6f7c28 pbrook
/* Set console attributes depending on the current escape codes.
707 6d6f7c28 pbrook
 * NOTE: I know this code is not very efficient (checking every color for it
708 6d6f7c28 pbrook
 * self) but it is more readable and better maintainable.
709 6d6f7c28 pbrook
 */
710 6d6f7c28 pbrook
static void console_handle_escape(TextConsole *s)
711 6d6f7c28 pbrook
{
712 6d6f7c28 pbrook
    int i;
713 6d6f7c28 pbrook
714 6d6f7c28 pbrook
    for (i=0; i<s->nb_esc_params; i++) {
715 6d6f7c28 pbrook
        switch (s->esc_params[i]) {
716 6d6f7c28 pbrook
            case 0: /* reset all console attributes to default */
717 6d6f7c28 pbrook
                s->t_attrib = s->t_attrib_default;
718 6d6f7c28 pbrook
                break;
719 6d6f7c28 pbrook
            case 1:
720 6d6f7c28 pbrook
                s->t_attrib.bold = 1;
721 6d6f7c28 pbrook
                break;
722 6d6f7c28 pbrook
            case 4:
723 6d6f7c28 pbrook
                s->t_attrib.uline = 1;
724 6d6f7c28 pbrook
                break;
725 6d6f7c28 pbrook
            case 5:
726 6d6f7c28 pbrook
                s->t_attrib.blink = 1;
727 6d6f7c28 pbrook
                break;
728 6d6f7c28 pbrook
            case 7:
729 6d6f7c28 pbrook
                s->t_attrib.invers = 1;
730 6d6f7c28 pbrook
                break;
731 6d6f7c28 pbrook
            case 8:
732 6d6f7c28 pbrook
                s->t_attrib.unvisible = 1;
733 6d6f7c28 pbrook
                break;
734 6d6f7c28 pbrook
            case 22:
735 6d6f7c28 pbrook
                s->t_attrib.bold = 0;
736 6d6f7c28 pbrook
                break;
737 6d6f7c28 pbrook
            case 24:
738 6d6f7c28 pbrook
                s->t_attrib.uline = 0;
739 6d6f7c28 pbrook
                break;
740 6d6f7c28 pbrook
            case 25:
741 6d6f7c28 pbrook
                s->t_attrib.blink = 0;
742 6d6f7c28 pbrook
                break;
743 6d6f7c28 pbrook
            case 27:
744 6d6f7c28 pbrook
                s->t_attrib.invers = 0;
745 6d6f7c28 pbrook
                break;
746 6d6f7c28 pbrook
            case 28:
747 6d6f7c28 pbrook
                s->t_attrib.unvisible = 0;
748 6d6f7c28 pbrook
                break;
749 6d6f7c28 pbrook
            /* set foreground color */
750 6d6f7c28 pbrook
            case 30:
751 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_BLACK;
752 6d6f7c28 pbrook
                break;
753 6d6f7c28 pbrook
            case 31:
754 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_RED;
755 6d6f7c28 pbrook
                break;
756 6d6f7c28 pbrook
            case 32:
757 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_GREEN;
758 6d6f7c28 pbrook
                break;
759 6d6f7c28 pbrook
            case 33:
760 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_YELLOW;
761 6d6f7c28 pbrook
                break;
762 6d6f7c28 pbrook
            case 34:
763 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_BLUE;
764 6d6f7c28 pbrook
                break;
765 6d6f7c28 pbrook
            case 35:
766 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_MAGENTA;
767 6d6f7c28 pbrook
                break;
768 6d6f7c28 pbrook
            case 36:
769 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_CYAN;
770 6d6f7c28 pbrook
                break;
771 6d6f7c28 pbrook
            case 37:
772 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_WHITE;
773 6d6f7c28 pbrook
                break;
774 6d6f7c28 pbrook
            /* set background color */
775 6d6f7c28 pbrook
            case 40:
776 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_BLACK;
777 6d6f7c28 pbrook
                break;
778 6d6f7c28 pbrook
            case 41:
779 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_RED;
780 6d6f7c28 pbrook
                break;
781 6d6f7c28 pbrook
            case 42:
782 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_GREEN;
783 6d6f7c28 pbrook
                break;
784 6d6f7c28 pbrook
            case 43:
785 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_YELLOW;
786 6d6f7c28 pbrook
                break;
787 6d6f7c28 pbrook
            case 44:
788 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_BLUE;
789 6d6f7c28 pbrook
                break;
790 6d6f7c28 pbrook
            case 45:
791 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_MAGENTA;
792 6d6f7c28 pbrook
                break;
793 6d6f7c28 pbrook
            case 46:
794 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_CYAN;
795 6d6f7c28 pbrook
                break;
796 6d6f7c28 pbrook
            case 47:
797 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_WHITE;
798 6d6f7c28 pbrook
                break;
799 6d6f7c28 pbrook
        }
800 6d6f7c28 pbrook
    }
801 6d6f7c28 pbrook
}
802 6d6f7c28 pbrook
803 adb47967 ths
static void console_clear_xy(TextConsole *s, int x, int y)
804 adb47967 ths
{
805 adb47967 ths
    int y1 = (s->y_base + y) % s->total_height;
806 adb47967 ths
    TextCell *c = &s->cells[y1 * s->width + x];
807 adb47967 ths
    c->ch = ' ';
808 adb47967 ths
    c->t_attrib = s->t_attrib_default;
809 adb47967 ths
    c++;
810 adb47967 ths
    update_xy(s, x, y);
811 adb47967 ths
}
812 adb47967 ths
813 e7f0ad58 bellard
static void console_putchar(TextConsole *s, int ch)
814 e7f0ad58 bellard
{
815 e7f0ad58 bellard
    TextCell *c;
816 adb47967 ths
    int y1, i;
817 adb47967 ths
    int x, y;
818 e7f0ad58 bellard
819 e7f0ad58 bellard
    switch(s->state) {
820 e7f0ad58 bellard
    case TTY_STATE_NORM:
821 e7f0ad58 bellard
        switch(ch) {
822 6d6f7c28 pbrook
        case '\r':  /* carriage return */
823 e7f0ad58 bellard
            s->x = 0;
824 e7f0ad58 bellard
            break;
825 6d6f7c28 pbrook
        case '\n':  /* newline */
826 e7f0ad58 bellard
            console_put_lf(s);
827 e7f0ad58 bellard
            break;
828 6d6f7c28 pbrook
        case '\b':  /* backspace */
829 5fafdf24 ths
            if (s->x > 0)
830 e15d7371 bellard
                s->x--;
831 6d6f7c28 pbrook
            break;
832 6d6f7c28 pbrook
        case '\t':  /* tabspace */
833 6d6f7c28 pbrook
            if (s->x + (8 - (s->x % 8)) > s->width) {
834 bd468840 bellard
                s->x = 0;
835 6d6f7c28 pbrook
                console_put_lf(s);
836 6d6f7c28 pbrook
            } else {
837 6d6f7c28 pbrook
                s->x = s->x + (8 - (s->x % 8));
838 6d6f7c28 pbrook
            }
839 6d6f7c28 pbrook
            break;
840 6d6f7c28 pbrook
        case '\a':  /* alert aka. bell */
841 6d6f7c28 pbrook
            /* TODO: has to be implemented */
842 6d6f7c28 pbrook
            break;
843 adb47967 ths
        case 14:
844 adb47967 ths
            /* SI (shift in), character set 0 (ignored) */
845 adb47967 ths
            break;
846 adb47967 ths
        case 15:
847 adb47967 ths
            /* SO (shift out), character set 1 (ignored) */
848 adb47967 ths
            break;
849 6d6f7c28 pbrook
        case 27:    /* esc (introducing an escape sequence) */
850 e7f0ad58 bellard
            s->state = TTY_STATE_ESC;
851 e7f0ad58 bellard
            break;
852 e7f0ad58 bellard
        default:
853 ed8276ac ths
            if (s->x >= s->width) {
854 ed8276ac ths
                /* line wrap */
855 ed8276ac ths
                s->x = 0;
856 ed8276ac ths
                console_put_lf(s);
857 adb47967 ths
            }
858 e7f0ad58 bellard
            y1 = (s->y_base + s->y) % s->total_height;
859 e7f0ad58 bellard
            c = &s->cells[y1 * s->width + s->x];
860 e7f0ad58 bellard
            c->ch = ch;
861 6d6f7c28 pbrook
            c->t_attrib = s->t_attrib;
862 e7f0ad58 bellard
            update_xy(s, s->x, s->y);
863 e7f0ad58 bellard
            s->x++;
864 e7f0ad58 bellard
            break;
865 e7f0ad58 bellard
        }
866 e7f0ad58 bellard
        break;
867 6d6f7c28 pbrook
    case TTY_STATE_ESC: /* check if it is a terminal escape sequence */
868 e7f0ad58 bellard
        if (ch == '[') {
869 e7f0ad58 bellard
            for(i=0;i<MAX_ESC_PARAMS;i++)
870 e7f0ad58 bellard
                s->esc_params[i] = 0;
871 e7f0ad58 bellard
            s->nb_esc_params = 0;
872 e7f0ad58 bellard
            s->state = TTY_STATE_CSI;
873 e7f0ad58 bellard
        } else {
874 e7f0ad58 bellard
            s->state = TTY_STATE_NORM;
875 e7f0ad58 bellard
        }
876 e7f0ad58 bellard
        break;
877 6d6f7c28 pbrook
    case TTY_STATE_CSI: /* handle escape sequence parameters */
878 e7f0ad58 bellard
        if (ch >= '0' && ch <= '9') {
879 e7f0ad58 bellard
            if (s->nb_esc_params < MAX_ESC_PARAMS) {
880 5fafdf24 ths
                s->esc_params[s->nb_esc_params] =
881 e7f0ad58 bellard
                    s->esc_params[s->nb_esc_params] * 10 + ch - '0';
882 e7f0ad58 bellard
            }
883 e7f0ad58 bellard
        } else {
884 e7f0ad58 bellard
            s->nb_esc_params++;
885 e7f0ad58 bellard
            if (ch == ';')
886 e7f0ad58 bellard
                break;
887 adb47967 ths
#ifdef DEBUG_CONSOLE
888 adb47967 ths
            fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
889 adb47967 ths
                    s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
890 adb47967 ths
#endif
891 e7f0ad58 bellard
            s->state = TTY_STATE_NORM;
892 e7f0ad58 bellard
            switch(ch) {
893 adb47967 ths
            case 'A':
894 adb47967 ths
                /* move cursor up */
895 adb47967 ths
                if (s->esc_params[0] == 0) {
896 adb47967 ths
                    s->esc_params[0] = 1;
897 adb47967 ths
                }
898 adb47967 ths
                s->y -= s->esc_params[0];
899 adb47967 ths
                if (s->y < 0) {
900 adb47967 ths
                    s->y = 0;
901 adb47967 ths
                }
902 adb47967 ths
                break;
903 adb47967 ths
            case 'B':
904 adb47967 ths
                /* move cursor down */
905 adb47967 ths
                if (s->esc_params[0] == 0) {
906 adb47967 ths
                    s->esc_params[0] = 1;
907 adb47967 ths
                }
908 adb47967 ths
                s->y += s->esc_params[0];
909 adb47967 ths
                if (s->y >= s->height) {
910 adb47967 ths
                    s->y = s->height - 1;
911 adb47967 ths
                }
912 e7f0ad58 bellard
                break;
913 e7f0ad58 bellard
            case 'C':
914 adb47967 ths
                /* move cursor right */
915 adb47967 ths
                if (s->esc_params[0] == 0) {
916 adb47967 ths
                    s->esc_params[0] = 1;
917 adb47967 ths
                }
918 adb47967 ths
                s->x += s->esc_params[0];
919 adb47967 ths
                if (s->x >= s->width) {
920 adb47967 ths
                    s->x = s->width - 1;
921 adb47967 ths
                }
922 e7f0ad58 bellard
                break;
923 adb47967 ths
            case 'D':
924 adb47967 ths
                /* move cursor left */
925 adb47967 ths
                if (s->esc_params[0] == 0) {
926 adb47967 ths
                    s->esc_params[0] = 1;
927 adb47967 ths
                }
928 adb47967 ths
                s->x -= s->esc_params[0];
929 adb47967 ths
                if (s->x < 0) {
930 adb47967 ths
                    s->x = 0;
931 adb47967 ths
                }
932 adb47967 ths
                break;
933 adb47967 ths
            case 'G':
934 adb47967 ths
                /* move cursor to column */
935 adb47967 ths
                s->x = s->esc_params[0] - 1;
936 adb47967 ths
                if (s->x < 0) {
937 adb47967 ths
                    s->x = 0;
938 adb47967 ths
                }
939 adb47967 ths
                break;
940 adb47967 ths
            case 'f':
941 adb47967 ths
            case 'H':
942 adb47967 ths
                /* move cursor to row, column */
943 adb47967 ths
                s->x = s->esc_params[1] - 1;
944 adb47967 ths
                if (s->x < 0) {
945 adb47967 ths
                    s->x = 0;
946 adb47967 ths
                }
947 adb47967 ths
                s->y = s->esc_params[0] - 1;
948 adb47967 ths
                if (s->y < 0) {
949 adb47967 ths
                    s->y = 0;
950 adb47967 ths
                }
951 adb47967 ths
                break;
952 adb47967 ths
            case 'J':
953 adb47967 ths
                switch (s->esc_params[0]) {
954 adb47967 ths
                case 0:
955 adb47967 ths
                    /* clear to end of screen */
956 adb47967 ths
                    for (y = s->y; y < s->height; y++) {
957 adb47967 ths
                        for (x = 0; x < s->width; x++) {
958 adb47967 ths
                            if (y == s->y && x < s->x) {
959 adb47967 ths
                                continue;
960 adb47967 ths
                            }
961 adb47967 ths
                            console_clear_xy(s, x, y);
962 adb47967 ths
                        }
963 adb47967 ths
                    }
964 adb47967 ths
                    break;
965 adb47967 ths
                case 1:
966 adb47967 ths
                    /* clear from beginning of screen */
967 adb47967 ths
                    for (y = 0; y <= s->y; y++) {
968 adb47967 ths
                        for (x = 0; x < s->width; x++) {
969 adb47967 ths
                            if (y == s->y && x > s->x) {
970 adb47967 ths
                                break;
971 adb47967 ths
                            }
972 adb47967 ths
                            console_clear_xy(s, x, y);
973 adb47967 ths
                        }
974 adb47967 ths
                    }
975 adb47967 ths
                    break;
976 adb47967 ths
                case 2:
977 adb47967 ths
                    /* clear entire screen */
978 adb47967 ths
                    for (y = 0; y <= s->height; y++) {
979 adb47967 ths
                        for (x = 0; x < s->width; x++) {
980 adb47967 ths
                            console_clear_xy(s, x, y);
981 adb47967 ths
                        }
982 adb47967 ths
                    }
983 adb47967 ths
                break;
984 adb47967 ths
                }
985 e7f0ad58 bellard
            case 'K':
986 adb47967 ths
                switch (s->esc_params[0]) {
987 adb47967 ths
                case 0:
988 e7f0ad58 bellard
                /* clear to eol */
989 e7f0ad58 bellard
                for(x = s->x; x < s->width; x++) {
990 adb47967 ths
                        console_clear_xy(s, x, s->y);
991 e7f0ad58 bellard
                }
992 e7f0ad58 bellard
                break;
993 adb47967 ths
                case 1:
994 adb47967 ths
                    /* clear from beginning of line */
995 adb47967 ths
                    for (x = 0; x <= s->x; x++) {
996 adb47967 ths
                        console_clear_xy(s, x, s->y);
997 adb47967 ths
                    }
998 adb47967 ths
                    break;
999 adb47967 ths
                case 2:
1000 adb47967 ths
                    /* clear entire line */
1001 adb47967 ths
                    for(x = 0; x < s->width; x++) {
1002 adb47967 ths
                        console_clear_xy(s, x, s->y);
1003 adb47967 ths
                    }
1004 e7f0ad58 bellard
                break;
1005 e7f0ad58 bellard
            }
1006 adb47967 ths
                break;
1007 adb47967 ths
            case 'm':
1008 6d6f7c28 pbrook
            console_handle_escape(s);
1009 e7f0ad58 bellard
            break;
1010 adb47967 ths
            case 'n':
1011 adb47967 ths
                /* report cursor position */
1012 adb47967 ths
                /* TODO: send ESC[row;colR */
1013 adb47967 ths
                break;
1014 adb47967 ths
            case 's':
1015 adb47967 ths
                /* save cursor position */
1016 adb47967 ths
                s->x_saved = s->x;
1017 adb47967 ths
                s->y_saved = s->y;
1018 adb47967 ths
                break;
1019 adb47967 ths
            case 'u':
1020 adb47967 ths
                /* restore cursor position */
1021 adb47967 ths
                s->x = s->x_saved;
1022 adb47967 ths
                s->y = s->y_saved;
1023 adb47967 ths
                break;
1024 adb47967 ths
            default:
1025 adb47967 ths
#ifdef DEBUG_CONSOLE
1026 adb47967 ths
                fprintf(stderr, "unhandled escape character '%c'\n", ch);
1027 adb47967 ths
#endif
1028 adb47967 ths
                break;
1029 adb47967 ths
            }
1030 adb47967 ths
            break;
1031 e7f0ad58 bellard
        }
1032 e7f0ad58 bellard
    }
1033 e7f0ad58 bellard
}
1034 e7f0ad58 bellard
1035 e7f0ad58 bellard
void console_select(unsigned int index)
1036 e7f0ad58 bellard
{
1037 e7f0ad58 bellard
    TextConsole *s;
1038 6d6f7c28 pbrook
1039 e7f0ad58 bellard
    if (index >= MAX_CONSOLES)
1040 e7f0ad58 bellard
        return;
1041 e7f0ad58 bellard
    s = consoles[index];
1042 e7f0ad58 bellard
    if (s) {
1043 e7f0ad58 bellard
        active_console = s;
1044 4d3b6f6e balrog
        vga_hw_invalidate();
1045 e7f0ad58 bellard
    }
1046 e7f0ad58 bellard
}
1047 e7f0ad58 bellard
1048 e7f0ad58 bellard
static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
1049 e7f0ad58 bellard
{
1050 e7f0ad58 bellard
    TextConsole *s = chr->opaque;
1051 e7f0ad58 bellard
    int i;
1052 e7f0ad58 bellard
1053 e7f0ad58 bellard
    console_show_cursor(s, 0);
1054 e7f0ad58 bellard
    for(i = 0; i < len; i++) {
1055 e7f0ad58 bellard
        console_putchar(s, buf[i]);
1056 e7f0ad58 bellard
    }
1057 e7f0ad58 bellard
    console_show_cursor(s, 1);
1058 e7f0ad58 bellard
    return len;
1059 e7f0ad58 bellard
}
1060 e7f0ad58 bellard
1061 6fcfafb7 bellard
static void console_send_event(CharDriverState *chr, int event)
1062 6fcfafb7 bellard
{
1063 6fcfafb7 bellard
    TextConsole *s = chr->opaque;
1064 6fcfafb7 bellard
    int i;
1065 6fcfafb7 bellard
1066 6fcfafb7 bellard
    if (event == CHR_EVENT_FOCUS) {
1067 6fcfafb7 bellard
        for(i = 0; i < nb_consoles; i++) {
1068 6fcfafb7 bellard
            if (consoles[i] == s) {
1069 6fcfafb7 bellard
                console_select(i);
1070 6fcfafb7 bellard
                break;
1071 6fcfafb7 bellard
            }
1072 6fcfafb7 bellard
        }
1073 6fcfafb7 bellard
    }
1074 6fcfafb7 bellard
}
1075 6fcfafb7 bellard
1076 e15d7371 bellard
static void kbd_send_chars(void *opaque)
1077 e15d7371 bellard
{
1078 e15d7371 bellard
    TextConsole *s = opaque;
1079 e15d7371 bellard
    int len;
1080 e15d7371 bellard
    uint8_t buf[16];
1081 3b46e624 ths
1082 e5b0bc44 pbrook
    len = qemu_chr_can_read(s->chr);
1083 e15d7371 bellard
    if (len > s->out_fifo.count)
1084 e15d7371 bellard
        len = s->out_fifo.count;
1085 e15d7371 bellard
    if (len > 0) {
1086 e15d7371 bellard
        if (len > sizeof(buf))
1087 e15d7371 bellard
            len = sizeof(buf);
1088 e15d7371 bellard
        qemu_fifo_read(&s->out_fifo, buf, len);
1089 e5b0bc44 pbrook
        qemu_chr_read(s->chr, buf, len);
1090 e15d7371 bellard
    }
1091 e15d7371 bellard
    /* characters are pending: we send them a bit later (XXX:
1092 e15d7371 bellard
       horrible, should change char device API) */
1093 e15d7371 bellard
    if (s->out_fifo.count > 0) {
1094 e15d7371 bellard
        qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
1095 e15d7371 bellard
    }
1096 e15d7371 bellard
}
1097 e15d7371 bellard
1098 e7f0ad58 bellard
/* called when an ascii key is pressed */
1099 e7f0ad58 bellard
void kbd_put_keysym(int keysym)
1100 e7f0ad58 bellard
{
1101 e7f0ad58 bellard
    TextConsole *s;
1102 e7f0ad58 bellard
    uint8_t buf[16], *q;
1103 e7f0ad58 bellard
    int c;
1104 e7f0ad58 bellard
1105 e7f0ad58 bellard
    s = active_console;
1106 af3a9031 ths
    if (!s || (s->console_type == GRAPHIC_CONSOLE))
1107 e7f0ad58 bellard
        return;
1108 e7f0ad58 bellard
1109 e7f0ad58 bellard
    switch(keysym) {
1110 e7f0ad58 bellard
    case QEMU_KEY_CTRL_UP:
1111 e7f0ad58 bellard
        console_scroll(-1);
1112 e7f0ad58 bellard
        break;
1113 e7f0ad58 bellard
    case QEMU_KEY_CTRL_DOWN:
1114 e7f0ad58 bellard
        console_scroll(1);
1115 e7f0ad58 bellard
        break;
1116 e7f0ad58 bellard
    case QEMU_KEY_CTRL_PAGEUP:
1117 e7f0ad58 bellard
        console_scroll(-10);
1118 e7f0ad58 bellard
        break;
1119 e7f0ad58 bellard
    case QEMU_KEY_CTRL_PAGEDOWN:
1120 e7f0ad58 bellard
        console_scroll(10);
1121 e7f0ad58 bellard
        break;
1122 e7f0ad58 bellard
    default:
1123 e15d7371 bellard
        /* convert the QEMU keysym to VT100 key string */
1124 e15d7371 bellard
        q = buf;
1125 e15d7371 bellard
        if (keysym >= 0xe100 && keysym <= 0xe11f) {
1126 e15d7371 bellard
            *q++ = '\033';
1127 e15d7371 bellard
            *q++ = '[';
1128 e15d7371 bellard
            c = keysym - 0xe100;
1129 e15d7371 bellard
            if (c >= 10)
1130 e15d7371 bellard
                *q++ = '0' + (c / 10);
1131 e15d7371 bellard
            *q++ = '0' + (c % 10);
1132 e15d7371 bellard
            *q++ = '~';
1133 e15d7371 bellard
        } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
1134 e15d7371 bellard
            *q++ = '\033';
1135 e15d7371 bellard
            *q++ = '[';
1136 e15d7371 bellard
            *q++ = keysym & 0xff;
1137 e15d7371 bellard
        } else {
1138 e7f0ad58 bellard
                *q++ = keysym;
1139 e15d7371 bellard
        }
1140 e5b0bc44 pbrook
        if (s->chr->chr_read) {
1141 e15d7371 bellard
            qemu_fifo_write(&s->out_fifo, buf, q - buf);
1142 e15d7371 bellard
            kbd_send_chars(s);
1143 e7f0ad58 bellard
        }
1144 e7f0ad58 bellard
        break;
1145 e7f0ad58 bellard
    }
1146 e7f0ad58 bellard
}
1147 e7f0ad58 bellard
1148 4d3b6f6e balrog
static void text_console_invalidate(void *opaque)
1149 4d3b6f6e balrog
{
1150 4d3b6f6e balrog
    TextConsole *s = (TextConsole *) opaque;
1151 4d3b6f6e balrog
1152 4d3b6f6e balrog
    if (s->console_type != GRAPHIC_CONSOLE) {
1153 4d3b6f6e balrog
        if (s->g_width != s->ds->width ||
1154 4d3b6f6e balrog
            s->g_height != s->ds->height) {
1155 4d3b6f6e balrog
            if (s->console_type == TEXT_CONSOLE_FIXED_SIZE)
1156 4d3b6f6e balrog
                dpy_resize(s->ds, s->g_width, s->g_height);
1157 4d3b6f6e balrog
            else {
1158 4d3b6f6e balrog
                s->g_width = s->ds->width;
1159 4d3b6f6e balrog
                s->g_height = s->ds->height;
1160 4d3b6f6e balrog
                text_console_resize(s);
1161 4d3b6f6e balrog
            }
1162 4d3b6f6e balrog
        }
1163 4d3b6f6e balrog
    }
1164 4d3b6f6e balrog
    console_refresh(s);
1165 4d3b6f6e balrog
}
1166 4d3b6f6e balrog
1167 4d3b6f6e balrog
static void text_console_update(void *opaque, console_ch_t *chardata)
1168 4d3b6f6e balrog
{
1169 4d3b6f6e balrog
    TextConsole *s = (TextConsole *) opaque;
1170 4d3b6f6e balrog
    int i, j, src;
1171 4d3b6f6e balrog
1172 4d3b6f6e balrog
    if (s->text_x[0] <= s->text_x[1]) {
1173 4d3b6f6e balrog
        src = (s->y_base + s->text_y[0]) * s->width;
1174 4d3b6f6e balrog
        chardata += s->text_y[0] * s->width;
1175 4d3b6f6e balrog
        for (i = s->text_y[0]; i <= s->text_y[1]; i ++)
1176 4d3b6f6e balrog
            for (j = 0; j < s->width; j ++, src ++)
1177 4d3b6f6e balrog
                console_write_ch(chardata ++, s->cells[src].ch |
1178 4d3b6f6e balrog
                                (s->cells[src].t_attrib.fgcol << 12) |
1179 4d3b6f6e balrog
                                (s->cells[src].t_attrib.bgcol << 8) |
1180 4d3b6f6e balrog
                                (s->cells[src].t_attrib.bold << 21));
1181 4d3b6f6e balrog
        dpy_update(s->ds, s->text_x[0], s->text_y[0],
1182 4d3b6f6e balrog
                   s->text_x[1] - s->text_x[0], i - s->text_y[0]);
1183 4d3b6f6e balrog
        s->text_x[0] = s->width;
1184 4d3b6f6e balrog
        s->text_y[0] = s->height;
1185 4d3b6f6e balrog
        s->text_x[1] = 0;
1186 4d3b6f6e balrog
        s->text_y[1] = 0;
1187 4d3b6f6e balrog
    }
1188 4d3b6f6e balrog
    if (s->cursor_invalidate) {
1189 4d3b6f6e balrog
        dpy_cursor(s->ds, s->x, s->y);
1190 4d3b6f6e balrog
        s->cursor_invalidate = 0;
1191 4d3b6f6e balrog
    }
1192 4d3b6f6e balrog
}
1193 4d3b6f6e balrog
1194 af3a9031 ths
static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
1195 e7f0ad58 bellard
{
1196 e7f0ad58 bellard
    TextConsole *s;
1197 95219897 pbrook
    int i;
1198 e7f0ad58 bellard
1199 e7f0ad58 bellard
    if (nb_consoles >= MAX_CONSOLES)
1200 e7f0ad58 bellard
        return NULL;
1201 e7f0ad58 bellard
    s = qemu_mallocz(sizeof(TextConsole));
1202 e7f0ad58 bellard
    if (!s) {
1203 e7f0ad58 bellard
        return NULL;
1204 e7f0ad58 bellard
    }
1205 af3a9031 ths
    if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
1206 af3a9031 ths
        (console_type == GRAPHIC_CONSOLE))) {
1207 e7f0ad58 bellard
        active_console = s;
1208 af3a9031 ths
    }
1209 e7f0ad58 bellard
    s->ds = ds;
1210 af3a9031 ths
    s->console_type = console_type;
1211 af3a9031 ths
    if (console_type != GRAPHIC_CONSOLE) {
1212 95219897 pbrook
        consoles[nb_consoles++] = s;
1213 95219897 pbrook
    } else {
1214 95219897 pbrook
        /* HACK: Put graphical consoles before text consoles.  */
1215 95219897 pbrook
        for (i = nb_consoles; i > 0; i--) {
1216 af3a9031 ths
            if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
1217 95219897 pbrook
                break;
1218 95219897 pbrook
            consoles[i] = consoles[i - 1];
1219 95219897 pbrook
        }
1220 95219897 pbrook
        consoles[i] = s;
1221 95219897 pbrook
    }
1222 95219897 pbrook
    return s;
1223 95219897 pbrook
}
1224 95219897 pbrook
1225 95219897 pbrook
TextConsole *graphic_console_init(DisplayState *ds, vga_hw_update_ptr update,
1226 95219897 pbrook
                                  vga_hw_invalidate_ptr invalidate,
1227 95219897 pbrook
                                  vga_hw_screen_dump_ptr screen_dump,
1228 4d3b6f6e balrog
                                  vga_hw_text_update_ptr text_update,
1229 95219897 pbrook
                                  void *opaque)
1230 95219897 pbrook
{
1231 95219897 pbrook
    TextConsole *s;
1232 95219897 pbrook
1233 af3a9031 ths
    s = new_console(ds, GRAPHIC_CONSOLE);
1234 95219897 pbrook
    if (!s)
1235 95219897 pbrook
      return NULL;
1236 95219897 pbrook
    s->hw_update = update;
1237 95219897 pbrook
    s->hw_invalidate = invalidate;
1238 95219897 pbrook
    s->hw_screen_dump = screen_dump;
1239 4d3b6f6e balrog
    s->hw_text_update = text_update;
1240 95219897 pbrook
    s->hw = opaque;
1241 e7f0ad58 bellard
    return s;
1242 e7f0ad58 bellard
}
1243 e7f0ad58 bellard
1244 95219897 pbrook
int is_graphic_console(void)
1245 e7f0ad58 bellard
{
1246 4d3b6f6e balrog
    return active_console && active_console->console_type == GRAPHIC_CONSOLE;
1247 e7f0ad58 bellard
}
1248 e7f0ad58 bellard
1249 a528b80c balrog
void console_color_init(DisplayState *ds)
1250 a528b80c balrog
{
1251 a528b80c balrog
    int i, j;
1252 a528b80c balrog
    for (j = 0; j < 2; j++) {
1253 a528b80c balrog
        for (i = 0; i < 8; i++) {
1254 a528b80c balrog
            color_table[j][i] = col_expand(ds, 
1255 a528b80c balrog
                   vga_get_color(ds, color_table_rgb[j][i]));
1256 a528b80c balrog
        }
1257 a528b80c balrog
    }
1258 a528b80c balrog
}
1259 a528b80c balrog
1260 af3a9031 ths
CharDriverState *text_console_init(DisplayState *ds, const char *p)
1261 e7f0ad58 bellard
{
1262 e7f0ad58 bellard
    CharDriverState *chr;
1263 e7f0ad58 bellard
    TextConsole *s;
1264 af3a9031 ths
    unsigned width;
1265 af3a9031 ths
    unsigned height;
1266 e7f0ad58 bellard
    static int color_inited;
1267 6d6f7c28 pbrook
1268 e7f0ad58 bellard
    chr = qemu_mallocz(sizeof(CharDriverState));
1269 e7f0ad58 bellard
    if (!chr)
1270 e7f0ad58 bellard
        return NULL;
1271 af3a9031 ths
    s = new_console(ds, (p == 0) ? TEXT_CONSOLE : TEXT_CONSOLE_FIXED_SIZE);
1272 e7f0ad58 bellard
    if (!s) {
1273 e7f0ad58 bellard
        free(chr);
1274 e7f0ad58 bellard
        return NULL;
1275 e7f0ad58 bellard
    }
1276 e7f0ad58 bellard
    chr->opaque = s;
1277 e7f0ad58 bellard
    chr->chr_write = console_puts;
1278 6fcfafb7 bellard
    chr->chr_send_event = console_send_event;
1279 6fcfafb7 bellard
1280 e5b0bc44 pbrook
    s->chr = chr;
1281 e15d7371 bellard
    s->out_fifo.buf = s->out_fifo_buf;
1282 e15d7371 bellard
    s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
1283 e15d7371 bellard
    s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
1284 3b46e624 ths
1285 e7f0ad58 bellard
    if (!color_inited) {
1286 e7f0ad58 bellard
        color_inited = 1;
1287 a528b80c balrog
        console_color_init(s->ds);
1288 e7f0ad58 bellard
    }
1289 e7f0ad58 bellard
    s->y_displayed = 0;
1290 e7f0ad58 bellard
    s->y_base = 0;
1291 e7f0ad58 bellard
    s->total_height = DEFAULT_BACKSCROLL;
1292 e7f0ad58 bellard
    s->x = 0;
1293 e7f0ad58 bellard
    s->y = 0;
1294 af3a9031 ths
    width = s->ds->width;
1295 af3a9031 ths
    height = s->ds->height;
1296 af3a9031 ths
    if (p != 0) {
1297 af3a9031 ths
        width = strtoul(p, (char **)&p, 10);
1298 af3a9031 ths
        if (*p == 'C') {
1299 af3a9031 ths
            p++;
1300 af3a9031 ths
            width *= FONT_WIDTH;
1301 af3a9031 ths
        }
1302 af3a9031 ths
        if (*p == 'x') {
1303 af3a9031 ths
            p++;
1304 af3a9031 ths
            height = strtoul(p, (char **)&p, 10);
1305 af3a9031 ths
            if (*p == 'C') {
1306 af3a9031 ths
                p++;
1307 af3a9031 ths
                height *= FONT_HEIGHT;
1308 af3a9031 ths
            }
1309 af3a9031 ths
        }
1310 af3a9031 ths
    }
1311 af3a9031 ths
    s->g_width = width;
1312 af3a9031 ths
    s->g_height = height;
1313 6d6f7c28 pbrook
1314 4d3b6f6e balrog
    s->hw_invalidate = text_console_invalidate;
1315 4d3b6f6e balrog
    s->hw_text_update = text_console_update;
1316 4d3b6f6e balrog
    s->hw = s;
1317 4d3b6f6e balrog
1318 6d6f7c28 pbrook
    /* Set text attribute defaults */
1319 6d6f7c28 pbrook
    s->t_attrib_default.bold = 0;
1320 6d6f7c28 pbrook
    s->t_attrib_default.uline = 0;
1321 6d6f7c28 pbrook
    s->t_attrib_default.blink = 0;
1322 6d6f7c28 pbrook
    s->t_attrib_default.invers = 0;
1323 6d6f7c28 pbrook
    s->t_attrib_default.unvisible = 0;
1324 6d6f7c28 pbrook
    s->t_attrib_default.fgcol = COLOR_WHITE;
1325 6d6f7c28 pbrook
    s->t_attrib_default.bgcol = COLOR_BLACK;
1326 6d6f7c28 pbrook
1327 6d6f7c28 pbrook
    /* set current text attributes to default */
1328 6d6f7c28 pbrook
    s->t_attrib = s->t_attrib_default;
1329 e7f0ad58 bellard
    text_console_resize(s);
1330 e7f0ad58 bellard
1331 86e94dea ths
    qemu_chr_reset(chr);
1332 86e94dea ths
1333 e7f0ad58 bellard
    return chr;
1334 e7f0ad58 bellard
}