Statistics
| Branch: | Revision:

root / console.c @ 10781c09

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