Statistics
| Branch: | Revision:

root / console.c @ 3bba22de

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