Statistics
| Branch: | Revision:

root / console.c @ 33189d31

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