Statistics
| Branch: | Revision:

root / console.c @ 8d7b0fbb

History | View | Annotate | Download (29.2 kB)

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