Statistics
| Branch: | Revision:

root / console.c @ 05332d70

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