Statistics
| Branch: | Revision:

root / console.c @ a171fe39

History | View | Annotate | Download (33.2 kB)

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