Statistics
| Branch: | Revision:

root / console.c @ 95219897

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