Statistics
| Branch: | Revision:

root / console.c @ 19bf7c87

History | View | Annotate | Download (46.9 kB)

1 e7f0ad58 bellard
/*
2 e7f0ad58 bellard
 * QEMU graphical console
3 5fafdf24 ths
 *
4 e7f0ad58 bellard
 * Copyright (c) 2004 Fabrice Bellard
5 5fafdf24 ths
 *
6 e7f0ad58 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 e7f0ad58 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 e7f0ad58 bellard
 * in the Software without restriction, including without limitation the rights
9 e7f0ad58 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 e7f0ad58 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 e7f0ad58 bellard
 * furnished to do so, subject to the following conditions:
12 e7f0ad58 bellard
 *
13 e7f0ad58 bellard
 * The above copyright notice and this permission notice shall be included in
14 e7f0ad58 bellard
 * all copies or substantial portions of the Software.
15 e7f0ad58 bellard
 *
16 e7f0ad58 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 e7f0ad58 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 e7f0ad58 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 e7f0ad58 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 e7f0ad58 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 e7f0ad58 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 e7f0ad58 bellard
 * THE SOFTWARE.
23 e7f0ad58 bellard
 */
24 87ecb68b pbrook
#include "qemu-common.h"
25 87ecb68b pbrook
#include "console.h"
26 87ecb68b pbrook
#include "qemu-timer.h"
27 e7f0ad58 bellard
28 6d6f7c28 pbrook
//#define DEBUG_CONSOLE
29 e7f0ad58 bellard
#define DEFAULT_BACKSCROLL 512
30 e7f0ad58 bellard
#define MAX_CONSOLES 12
31 e7f0ad58 bellard
32 26489844 bellard
#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
33 26489844 bellard
#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff)
34 e7f0ad58 bellard
35 6d6f7c28 pbrook
typedef struct TextAttributes {
36 6d6f7c28 pbrook
    uint8_t fgcol:4;
37 6d6f7c28 pbrook
    uint8_t bgcol:4;
38 6d6f7c28 pbrook
    uint8_t bold:1;
39 6d6f7c28 pbrook
    uint8_t uline:1;
40 6d6f7c28 pbrook
    uint8_t blink:1;
41 6d6f7c28 pbrook
    uint8_t invers:1;
42 6d6f7c28 pbrook
    uint8_t unvisible:1;
43 6d6f7c28 pbrook
} TextAttributes;
44 6d6f7c28 pbrook
45 e7f0ad58 bellard
typedef struct TextCell {
46 e7f0ad58 bellard
    uint8_t ch;
47 6d6f7c28 pbrook
    TextAttributes t_attrib;
48 e7f0ad58 bellard
} TextCell;
49 e7f0ad58 bellard
50 e7f0ad58 bellard
#define MAX_ESC_PARAMS 3
51 e7f0ad58 bellard
52 e7f0ad58 bellard
enum TTYState {
53 e7f0ad58 bellard
    TTY_STATE_NORM,
54 e7f0ad58 bellard
    TTY_STATE_ESC,
55 e7f0ad58 bellard
    TTY_STATE_CSI,
56 e7f0ad58 bellard
};
57 e7f0ad58 bellard
58 e15d7371 bellard
typedef struct QEMUFIFO {
59 e15d7371 bellard
    uint8_t *buf;
60 e15d7371 bellard
    int buf_size;
61 e15d7371 bellard
    int count, wptr, rptr;
62 e15d7371 bellard
} QEMUFIFO;
63 e15d7371 bellard
64 9596ebb7 pbrook
static int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
65 e15d7371 bellard
{
66 e15d7371 bellard
    int l, len;
67 e15d7371 bellard
68 e15d7371 bellard
    l = f->buf_size - f->count;
69 e15d7371 bellard
    if (len1 > l)
70 e15d7371 bellard
        len1 = l;
71 e15d7371 bellard
    len = len1;
72 e15d7371 bellard
    while (len > 0) {
73 e15d7371 bellard
        l = f->buf_size - f->wptr;
74 e15d7371 bellard
        if (l > len)
75 e15d7371 bellard
            l = len;
76 e15d7371 bellard
        memcpy(f->buf + f->wptr, buf, l);
77 e15d7371 bellard
        f->wptr += l;
78 e15d7371 bellard
        if (f->wptr >= f->buf_size)
79 e15d7371 bellard
            f->wptr = 0;
80 e15d7371 bellard
        buf += l;
81 e15d7371 bellard
        len -= l;
82 e15d7371 bellard
    }
83 e15d7371 bellard
    f->count += len1;
84 e15d7371 bellard
    return len1;
85 e15d7371 bellard
}
86 e15d7371 bellard
87 9596ebb7 pbrook
static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
88 e15d7371 bellard
{
89 e15d7371 bellard
    int l, len;
90 e15d7371 bellard
91 e15d7371 bellard
    if (len1 > f->count)
92 e15d7371 bellard
        len1 = f->count;
93 e15d7371 bellard
    len = len1;
94 e15d7371 bellard
    while (len > 0) {
95 e15d7371 bellard
        l = f->buf_size - f->rptr;
96 e15d7371 bellard
        if (l > len)
97 e15d7371 bellard
            l = len;
98 e15d7371 bellard
        memcpy(buf, f->buf + f->rptr, l);
99 e15d7371 bellard
        f->rptr += l;
100 e15d7371 bellard
        if (f->rptr >= f->buf_size)
101 e15d7371 bellard
            f->rptr = 0;
102 e15d7371 bellard
        buf += l;
103 e15d7371 bellard
        len -= l;
104 e15d7371 bellard
    }
105 e15d7371 bellard
    f->count -= len1;
106 e15d7371 bellard
    return len1;
107 e15d7371 bellard
}
108 e15d7371 bellard
109 af3a9031 ths
typedef enum {
110 af3a9031 ths
    GRAPHIC_CONSOLE,
111 c21bbcfa balrog
    TEXT_CONSOLE,
112 c21bbcfa balrog
    TEXT_CONSOLE_FIXED_SIZE
113 c227f099 Anthony Liguori
} console_type_t;
114 af3a9031 ths
115 95219897 pbrook
/* ??? This is mis-named.
116 95219897 pbrook
   It is used for both text and graphical consoles.  */
117 e7f0ad58 bellard
struct TextConsole {
118 f81bdefb Jan Kiszka
    int index;
119 c227f099 Anthony Liguori
    console_type_t console_type;
120 e7f0ad58 bellard
    DisplayState *ds;
121 95219897 pbrook
    /* Graphic console state.  */
122 95219897 pbrook
    vga_hw_update_ptr hw_update;
123 95219897 pbrook
    vga_hw_invalidate_ptr hw_invalidate;
124 95219897 pbrook
    vga_hw_screen_dump_ptr hw_screen_dump;
125 4d3b6f6e balrog
    vga_hw_text_update_ptr hw_text_update;
126 95219897 pbrook
    void *hw;
127 95219897 pbrook
128 e7f0ad58 bellard
    int g_width, g_height;
129 e7f0ad58 bellard
    int width;
130 e7f0ad58 bellard
    int height;
131 e7f0ad58 bellard
    int total_height;
132 e7f0ad58 bellard
    int backscroll_height;
133 e7f0ad58 bellard
    int x, y;
134 adb47967 ths
    int x_saved, y_saved;
135 e7f0ad58 bellard
    int y_displayed;
136 e7f0ad58 bellard
    int y_base;
137 6d6f7c28 pbrook
    TextAttributes t_attrib_default; /* default text attributes */
138 6d6f7c28 pbrook
    TextAttributes t_attrib; /* currently active text attributes */
139 e7f0ad58 bellard
    TextCell *cells;
140 4d3b6f6e balrog
    int text_x[2], text_y[2], cursor_invalidate;
141 4104833f Paolo Bonzini
    int echo;
142 e7f0ad58 bellard
143 14778c20 pbrook
    int update_x0;
144 14778c20 pbrook
    int update_y0;
145 14778c20 pbrook
    int update_x1;
146 14778c20 pbrook
    int update_y1;
147 14778c20 pbrook
148 e7f0ad58 bellard
    enum TTYState state;
149 e7f0ad58 bellard
    int esc_params[MAX_ESC_PARAMS];
150 e7f0ad58 bellard
    int nb_esc_params;
151 e7f0ad58 bellard
152 e5b0bc44 pbrook
    CharDriverState *chr;
153 e15d7371 bellard
    /* fifo for key pressed */
154 e15d7371 bellard
    QEMUFIFO out_fifo;
155 e15d7371 bellard
    uint8_t out_fifo_buf[16];
156 e15d7371 bellard
    QEMUTimer *kbd_timer;
157 e7f0ad58 bellard
};
158 e7f0ad58 bellard
159 98b50080 Paolo Bonzini
static DisplayState *display_state;
160 e7f0ad58 bellard
static TextConsole *active_console;
161 e7f0ad58 bellard
static TextConsole *consoles[MAX_CONSOLES];
162 e7f0ad58 bellard
static int nb_consoles = 0;
163 e7f0ad58 bellard
164 95219897 pbrook
void vga_hw_update(void)
165 95219897 pbrook
{
166 adb47967 ths
    if (active_console && active_console->hw_update)
167 95219897 pbrook
        active_console->hw_update(active_console->hw);
168 95219897 pbrook
}
169 95219897 pbrook
170 95219897 pbrook
void vga_hw_invalidate(void)
171 95219897 pbrook
{
172 26572b8a Gerd Hoffmann
    if (active_console && active_console->hw_invalidate)
173 95219897 pbrook
        active_console->hw_invalidate(active_console->hw);
174 95219897 pbrook
}
175 95219897 pbrook
176 95219897 pbrook
void vga_hw_screen_dump(const char *filename)
177 95219897 pbrook
{
178 8571c055 balrog
    TextConsole *previous_active_console;
179 8571c055 balrog
180 8571c055 balrog
    previous_active_console = active_console;
181 f81bdefb Jan Kiszka
182 8571c055 balrog
    /* There is currently no way of specifying which screen we want to dump,
183 7b455225 aurel32
       so always dump the first one.  */
184 f81bdefb Jan Kiszka
    console_select(0);
185 f81bdefb Jan Kiszka
    if (consoles[0] && consoles[0]->hw_screen_dump) {
186 95219897 pbrook
        consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
187 f81bdefb Jan Kiszka
    }
188 f81bdefb Jan Kiszka
189 33bcd98c Alexander Graf
    if (previous_active_console) {
190 33bcd98c Alexander Graf
        console_select(previous_active_console->index);
191 33bcd98c Alexander Graf
    }
192 95219897 pbrook
}
193 95219897 pbrook
194 c227f099 Anthony Liguori
void vga_hw_text_update(console_ch_t *chardata)
195 4d3b6f6e balrog
{
196 4d3b6f6e balrog
    if (active_console && active_console->hw_text_update)
197 4d3b6f6e balrog
        active_console->hw_text_update(active_console->hw, chardata);
198 4d3b6f6e balrog
}
199 4d3b6f6e balrog
200 e7f0ad58 bellard
/* convert a RGBA color to a color index usable in graphic primitives */
201 e7f0ad58 bellard
static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
202 e7f0ad58 bellard
{
203 e7f0ad58 bellard
    unsigned int r, g, b, color;
204 e7f0ad58 bellard
205 0e1f5a0c aliguori
    switch(ds_get_bits_per_pixel(ds)) {
206 e7f0ad58 bellard
#if 0
207 e7f0ad58 bellard
    case 8:
208 e7f0ad58 bellard
        r = (rgba >> 16) & 0xff;
209 e7f0ad58 bellard
        g = (rgba >> 8) & 0xff;
210 e7f0ad58 bellard
        b = (rgba) & 0xff;
211 5fafdf24 ths
        color = (rgb_to_index[r] * 6 * 6) +
212 5fafdf24 ths
            (rgb_to_index[g] * 6) +
213 e7f0ad58 bellard
            (rgb_to_index[b]);
214 e7f0ad58 bellard
        break;
215 e7f0ad58 bellard
#endif
216 e7f0ad58 bellard
    case 15:
217 e7f0ad58 bellard
        r = (rgba >> 16) & 0xff;
218 e7f0ad58 bellard
        g = (rgba >> 8) & 0xff;
219 e7f0ad58 bellard
        b = (rgba) & 0xff;
220 e7f0ad58 bellard
        color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
221 e7f0ad58 bellard
        break;
222 e7f0ad58 bellard
    case 16:
223 e7f0ad58 bellard
        r = (rgba >> 16) & 0xff;
224 e7f0ad58 bellard
        g = (rgba >> 8) & 0xff;
225 e7f0ad58 bellard
        b = (rgba) & 0xff;
226 e7f0ad58 bellard
        color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
227 e7f0ad58 bellard
        break;
228 e7f0ad58 bellard
    case 32:
229 e7f0ad58 bellard
    default:
230 e7f0ad58 bellard
        color = rgba;
231 e7f0ad58 bellard
        break;
232 e7f0ad58 bellard
    }
233 e7f0ad58 bellard
    return color;
234 e7f0ad58 bellard
}
235 e7f0ad58 bellard
236 5fafdf24 ths
static void vga_fill_rect (DisplayState *ds,
237 e7f0ad58 bellard
                           int posx, int posy, int width, int height, uint32_t color)
238 e7f0ad58 bellard
{
239 e7f0ad58 bellard
    uint8_t *d, *d1;
240 e7f0ad58 bellard
    int x, y, bpp;
241 3b46e624 ths
242 0e1f5a0c aliguori
    bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
243 0e1f5a0c aliguori
    d1 = ds_get_data(ds) +
244 0e1f5a0c aliguori
        ds_get_linesize(ds) * posy + bpp * posx;
245 e7f0ad58 bellard
    for (y = 0; y < height; y++) {
246 e7f0ad58 bellard
        d = d1;
247 e7f0ad58 bellard
        switch(bpp) {
248 e7f0ad58 bellard
        case 1:
249 e7f0ad58 bellard
            for (x = 0; x < width; x++) {
250 e7f0ad58 bellard
                *((uint8_t *)d) = color;
251 e7f0ad58 bellard
                d++;
252 e7f0ad58 bellard
            }
253 e7f0ad58 bellard
            break;
254 e7f0ad58 bellard
        case 2:
255 e7f0ad58 bellard
            for (x = 0; x < width; x++) {
256 e7f0ad58 bellard
                *((uint16_t *)d) = color;
257 e7f0ad58 bellard
                d += 2;
258 e7f0ad58 bellard
            }
259 e7f0ad58 bellard
            break;
260 e7f0ad58 bellard
        case 4:
261 e7f0ad58 bellard
            for (x = 0; x < width; x++) {
262 e7f0ad58 bellard
                *((uint32_t *)d) = color;
263 e7f0ad58 bellard
                d += 4;
264 e7f0ad58 bellard
            }
265 e7f0ad58 bellard
            break;
266 e7f0ad58 bellard
        }
267 0e1f5a0c aliguori
        d1 += ds_get_linesize(ds);
268 e7f0ad58 bellard
    }
269 e7f0ad58 bellard
}
270 e7f0ad58 bellard
271 e7f0ad58 bellard
/* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
272 e7f0ad58 bellard
static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h)
273 e7f0ad58 bellard
{
274 e7f0ad58 bellard
    const uint8_t *s;
275 e7f0ad58 bellard
    uint8_t *d;
276 e7f0ad58 bellard
    int wb, y, bpp;
277 e7f0ad58 bellard
278 0e1f5a0c aliguori
    bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
279 e7f0ad58 bellard
    wb = w * bpp;
280 e7f0ad58 bellard
    if (yd <= ys) {
281 0e1f5a0c aliguori
        s = ds_get_data(ds) +
282 0e1f5a0c aliguori
            ds_get_linesize(ds) * ys + bpp * xs;
283 0e1f5a0c aliguori
        d = ds_get_data(ds) +
284 0e1f5a0c aliguori
            ds_get_linesize(ds) * yd + bpp * xd;
285 e7f0ad58 bellard
        for (y = 0; y < h; y++) {
286 e7f0ad58 bellard
            memmove(d, s, wb);
287 0e1f5a0c aliguori
            d += ds_get_linesize(ds);
288 0e1f5a0c aliguori
            s += ds_get_linesize(ds);
289 e7f0ad58 bellard
        }
290 e7f0ad58 bellard
    } else {
291 0e1f5a0c aliguori
        s = ds_get_data(ds) +
292 0e1f5a0c aliguori
            ds_get_linesize(ds) * (ys + h - 1) + bpp * xs;
293 0e1f5a0c aliguori
        d = ds_get_data(ds) +
294 0e1f5a0c aliguori
            ds_get_linesize(ds) * (yd + h - 1) + bpp * xd;
295 e7f0ad58 bellard
       for (y = 0; y < h; y++) {
296 e7f0ad58 bellard
            memmove(d, s, wb);
297 0e1f5a0c aliguori
            d -= ds_get_linesize(ds);
298 0e1f5a0c aliguori
            s -= ds_get_linesize(ds);
299 e7f0ad58 bellard
        }
300 e7f0ad58 bellard
    }
301 e7f0ad58 bellard
}
302 e7f0ad58 bellard
303 e7f0ad58 bellard
/***********************************************************/
304 e7f0ad58 bellard
/* basic char display */
305 e7f0ad58 bellard
306 e7f0ad58 bellard
#define FONT_HEIGHT 16
307 e7f0ad58 bellard
#define FONT_WIDTH 8
308 e7f0ad58 bellard
309 e7f0ad58 bellard
#include "vgafont.h"
310 e7f0ad58 bellard
311 e7f0ad58 bellard
#define cbswap_32(__x) \
312 e7f0ad58 bellard
((uint32_t)( \
313 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
314 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
315 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
316 e7f0ad58 bellard
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
317 e7f0ad58 bellard
318 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
319 e7f0ad58 bellard
#define PAT(x) x
320 e7f0ad58 bellard
#else
321 e7f0ad58 bellard
#define PAT(x) cbswap_32(x)
322 e7f0ad58 bellard
#endif
323 e7f0ad58 bellard
324 e7f0ad58 bellard
static const uint32_t dmask16[16] = {
325 e7f0ad58 bellard
    PAT(0x00000000),
326 e7f0ad58 bellard
    PAT(0x000000ff),
327 e7f0ad58 bellard
    PAT(0x0000ff00),
328 e7f0ad58 bellard
    PAT(0x0000ffff),
329 e7f0ad58 bellard
    PAT(0x00ff0000),
330 e7f0ad58 bellard
    PAT(0x00ff00ff),
331 e7f0ad58 bellard
    PAT(0x00ffff00),
332 e7f0ad58 bellard
    PAT(0x00ffffff),
333 e7f0ad58 bellard
    PAT(0xff000000),
334 e7f0ad58 bellard
    PAT(0xff0000ff),
335 e7f0ad58 bellard
    PAT(0xff00ff00),
336 e7f0ad58 bellard
    PAT(0xff00ffff),
337 e7f0ad58 bellard
    PAT(0xffff0000),
338 e7f0ad58 bellard
    PAT(0xffff00ff),
339 e7f0ad58 bellard
    PAT(0xffffff00),
340 e7f0ad58 bellard
    PAT(0xffffffff),
341 e7f0ad58 bellard
};
342 e7f0ad58 bellard
343 e7f0ad58 bellard
static const uint32_t dmask4[4] = {
344 e7f0ad58 bellard
    PAT(0x00000000),
345 e7f0ad58 bellard
    PAT(0x0000ffff),
346 e7f0ad58 bellard
    PAT(0xffff0000),
347 e7f0ad58 bellard
    PAT(0xffffffff),
348 e7f0ad58 bellard
};
349 e7f0ad58 bellard
350 6d6f7c28 pbrook
static uint32_t color_table[2][8];
351 6d6f7c28 pbrook
352 df00bed0 Devin J. Pohly
#ifndef CONFIG_CURSES
353 6d6f7c28 pbrook
enum color_names {
354 6d6f7c28 pbrook
    COLOR_BLACK   = 0,
355 6d6f7c28 pbrook
    COLOR_RED     = 1,
356 6d6f7c28 pbrook
    COLOR_GREEN   = 2,
357 6d6f7c28 pbrook
    COLOR_YELLOW  = 3,
358 6d6f7c28 pbrook
    COLOR_BLUE    = 4,
359 6d6f7c28 pbrook
    COLOR_MAGENTA = 5,
360 6d6f7c28 pbrook
    COLOR_CYAN    = 6,
361 6d6f7c28 pbrook
    COLOR_WHITE   = 7
362 6d6f7c28 pbrook
};
363 df00bed0 Devin J. Pohly
#endif
364 6d6f7c28 pbrook
365 6d6f7c28 pbrook
static const uint32_t color_table_rgb[2][8] = {
366 6d6f7c28 pbrook
    {   /* dark */
367 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0x00),  /* black */
368 26489844 bellard
        QEMU_RGB(0xaa, 0x00, 0x00),  /* red */
369 26489844 bellard
        QEMU_RGB(0x00, 0xaa, 0x00),  /* green */
370 26489844 bellard
        QEMU_RGB(0xaa, 0xaa, 0x00),  /* yellow */
371 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0xaa),  /* blue */
372 26489844 bellard
        QEMU_RGB(0xaa, 0x00, 0xaa),  /* magenta */
373 26489844 bellard
        QEMU_RGB(0x00, 0xaa, 0xaa),  /* cyan */
374 26489844 bellard
        QEMU_RGB(0xaa, 0xaa, 0xaa),  /* white */
375 6d6f7c28 pbrook
    },
376 6d6f7c28 pbrook
    {   /* bright */
377 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0x00),  /* black */
378 26489844 bellard
        QEMU_RGB(0xff, 0x00, 0x00),  /* red */
379 26489844 bellard
        QEMU_RGB(0x00, 0xff, 0x00),  /* green */
380 26489844 bellard
        QEMU_RGB(0xff, 0xff, 0x00),  /* yellow */
381 26489844 bellard
        QEMU_RGB(0x00, 0x00, 0xff),  /* blue */
382 26489844 bellard
        QEMU_RGB(0xff, 0x00, 0xff),  /* magenta */
383 26489844 bellard
        QEMU_RGB(0x00, 0xff, 0xff),  /* cyan */
384 26489844 bellard
        QEMU_RGB(0xff, 0xff, 0xff),  /* white */
385 6d6f7c28 pbrook
    }
386 e7f0ad58 bellard
};
387 e7f0ad58 bellard
388 e7f0ad58 bellard
static inline unsigned int col_expand(DisplayState *ds, unsigned int col)
389 e7f0ad58 bellard
{
390 0e1f5a0c aliguori
    switch(ds_get_bits_per_pixel(ds)) {
391 e7f0ad58 bellard
    case 8:
392 e7f0ad58 bellard
        col |= col << 8;
393 e7f0ad58 bellard
        col |= col << 16;
394 e7f0ad58 bellard
        break;
395 e7f0ad58 bellard
    case 15:
396 e7f0ad58 bellard
    case 16:
397 e7f0ad58 bellard
        col |= col << 16;
398 e7f0ad58 bellard
        break;
399 e7f0ad58 bellard
    default:
400 e7f0ad58 bellard
        break;
401 e7f0ad58 bellard
    }
402 e7f0ad58 bellard
403 e7f0ad58 bellard
    return col;
404 e7f0ad58 bellard
}
405 6d6f7c28 pbrook
#ifdef DEBUG_CONSOLE
406 6d6f7c28 pbrook
static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
407 6d6f7c28 pbrook
{
408 6d6f7c28 pbrook
    if (t_attrib->bold) {
409 6d6f7c28 pbrook
        printf("b");
410 6d6f7c28 pbrook
    } else {
411 6d6f7c28 pbrook
        printf(" ");
412 6d6f7c28 pbrook
    }
413 6d6f7c28 pbrook
    if (t_attrib->uline) {
414 6d6f7c28 pbrook
        printf("u");
415 6d6f7c28 pbrook
    } else {
416 6d6f7c28 pbrook
        printf(" ");
417 6d6f7c28 pbrook
    }
418 6d6f7c28 pbrook
    if (t_attrib->blink) {
419 6d6f7c28 pbrook
        printf("l");
420 6d6f7c28 pbrook
    } else {
421 6d6f7c28 pbrook
        printf(" ");
422 6d6f7c28 pbrook
    }
423 6d6f7c28 pbrook
    if (t_attrib->invers) {
424 6d6f7c28 pbrook
        printf("i");
425 6d6f7c28 pbrook
    } else {
426 6d6f7c28 pbrook
        printf(" ");
427 6d6f7c28 pbrook
    }
428 6d6f7c28 pbrook
    if (t_attrib->unvisible) {
429 6d6f7c28 pbrook
        printf("n");
430 6d6f7c28 pbrook
    } else {
431 6d6f7c28 pbrook
        printf(" ");
432 6d6f7c28 pbrook
    }
433 6d6f7c28 pbrook
434 6d6f7c28 pbrook
    printf(" fg: %d bg: %d ch:'%2X' '%c'\n", t_attrib->fgcol, t_attrib->bgcol, ch, ch);
435 6d6f7c28 pbrook
}
436 6d6f7c28 pbrook
#endif
437 e7f0ad58 bellard
438 5fafdf24 ths
static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
439 6d6f7c28 pbrook
                          TextAttributes *t_attrib)
440 e7f0ad58 bellard
{
441 e7f0ad58 bellard
    uint8_t *d;
442 e7f0ad58 bellard
    const uint8_t *font_ptr;
443 e7f0ad58 bellard
    unsigned int font_data, linesize, xorcol, bpp;
444 e7f0ad58 bellard
    int i;
445 6d6f7c28 pbrook
    unsigned int fgcol, bgcol;
446 6d6f7c28 pbrook
447 6d6f7c28 pbrook
#ifdef DEBUG_CONSOLE
448 6d6f7c28 pbrook
    printf("x: %2i y: %2i", x, y);
449 6d6f7c28 pbrook
    console_print_text_attributes(t_attrib, ch);
450 6d6f7c28 pbrook
#endif
451 6d6f7c28 pbrook
452 6d6f7c28 pbrook
    if (t_attrib->invers) {
453 6d6f7c28 pbrook
        bgcol = color_table[t_attrib->bold][t_attrib->fgcol];
454 6d6f7c28 pbrook
        fgcol = color_table[t_attrib->bold][t_attrib->bgcol];
455 6d6f7c28 pbrook
    } else {
456 6d6f7c28 pbrook
        fgcol = color_table[t_attrib->bold][t_attrib->fgcol];
457 6d6f7c28 pbrook
        bgcol = color_table[t_attrib->bold][t_attrib->bgcol];
458 6d6f7c28 pbrook
    }
459 e7f0ad58 bellard
460 0e1f5a0c aliguori
    bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
461 0e1f5a0c aliguori
    d = ds_get_data(ds) +
462 0e1f5a0c aliguori
        ds_get_linesize(ds) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
463 0e1f5a0c aliguori
    linesize = ds_get_linesize(ds);
464 e7f0ad58 bellard
    font_ptr = vgafont16 + FONT_HEIGHT * ch;
465 e7f0ad58 bellard
    xorcol = bgcol ^ fgcol;
466 0e1f5a0c aliguori
    switch(ds_get_bits_per_pixel(ds)) {
467 e7f0ad58 bellard
    case 8:
468 e7f0ad58 bellard
        for(i = 0; i < FONT_HEIGHT; i++) {
469 e7f0ad58 bellard
            font_data = *font_ptr++;
470 6d6f7c28 pbrook
            if (t_attrib->uline
471 6d6f7c28 pbrook
                && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
472 439229c7 Markus Armbruster
                font_data = 0xFF;
473 6d6f7c28 pbrook
            }
474 e7f0ad58 bellard
            ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
475 e7f0ad58 bellard
            ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
476 e7f0ad58 bellard
            d += linesize;
477 e7f0ad58 bellard
        }
478 e7f0ad58 bellard
        break;
479 e7f0ad58 bellard
    case 16:
480 e7f0ad58 bellard
    case 15:
481 e7f0ad58 bellard
        for(i = 0; i < FONT_HEIGHT; i++) {
482 e7f0ad58 bellard
            font_data = *font_ptr++;
483 6d6f7c28 pbrook
            if (t_attrib->uline
484 6d6f7c28 pbrook
                && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
485 439229c7 Markus Armbruster
                font_data = 0xFF;
486 6d6f7c28 pbrook
            }
487 e7f0ad58 bellard
            ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
488 e7f0ad58 bellard
            ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
489 e7f0ad58 bellard
            ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
490 e7f0ad58 bellard
            ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
491 e7f0ad58 bellard
            d += linesize;
492 e7f0ad58 bellard
        }
493 e7f0ad58 bellard
        break;
494 e7f0ad58 bellard
    case 32:
495 e7f0ad58 bellard
        for(i = 0; i < FONT_HEIGHT; i++) {
496 e7f0ad58 bellard
            font_data = *font_ptr++;
497 6d6f7c28 pbrook
            if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
498 439229c7 Markus Armbruster
                font_data = 0xFF;
499 6d6f7c28 pbrook
            }
500 e7f0ad58 bellard
            ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
501 e7f0ad58 bellard
            ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
502 e7f0ad58 bellard
            ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
503 e7f0ad58 bellard
            ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
504 e7f0ad58 bellard
            ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
505 e7f0ad58 bellard
            ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
506 e7f0ad58 bellard
            ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
507 e7f0ad58 bellard
            ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
508 e7f0ad58 bellard
            d += linesize;
509 e7f0ad58 bellard
        }
510 e7f0ad58 bellard
        break;
511 e7f0ad58 bellard
    }
512 e7f0ad58 bellard
}
513 e7f0ad58 bellard
514 e7f0ad58 bellard
static void text_console_resize(TextConsole *s)
515 e7f0ad58 bellard
{
516 e7f0ad58 bellard
    TextCell *cells, *c, *c1;
517 e7f0ad58 bellard
    int w1, x, y, last_width;
518 e7f0ad58 bellard
519 e7f0ad58 bellard
    last_width = s->width;
520 e7f0ad58 bellard
    s->width = s->g_width / FONT_WIDTH;
521 e7f0ad58 bellard
    s->height = s->g_height / FONT_HEIGHT;
522 e7f0ad58 bellard
523 e7f0ad58 bellard
    w1 = last_width;
524 e7f0ad58 bellard
    if (s->width < w1)
525 e7f0ad58 bellard
        w1 = s->width;
526 e7f0ad58 bellard
527 7267c094 Anthony Liguori
    cells = g_malloc(s->width * s->total_height * sizeof(TextCell));
528 e7f0ad58 bellard
    for(y = 0; y < s->total_height; y++) {
529 e7f0ad58 bellard
        c = &cells[y * s->width];
530 e7f0ad58 bellard
        if (w1 > 0) {
531 e7f0ad58 bellard
            c1 = &s->cells[y * last_width];
532 e7f0ad58 bellard
            for(x = 0; x < w1; x++) {
533 e7f0ad58 bellard
                *c++ = *c1++;
534 e7f0ad58 bellard
            }
535 e7f0ad58 bellard
        }
536 e7f0ad58 bellard
        for(x = w1; x < s->width; x++) {
537 e7f0ad58 bellard
            c->ch = ' ';
538 6d6f7c28 pbrook
            c->t_attrib = s->t_attrib_default;
539 e7f0ad58 bellard
            c++;
540 e7f0ad58 bellard
        }
541 e7f0ad58 bellard
    }
542 7267c094 Anthony Liguori
    g_free(s->cells);
543 e7f0ad58 bellard
    s->cells = cells;
544 e7f0ad58 bellard
}
545 e7f0ad58 bellard
546 4d3b6f6e balrog
static inline void text_update_xy(TextConsole *s, int x, int y)
547 4d3b6f6e balrog
{
548 4d3b6f6e balrog
    s->text_x[0] = MIN(s->text_x[0], x);
549 4d3b6f6e balrog
    s->text_x[1] = MAX(s->text_x[1], x);
550 4d3b6f6e balrog
    s->text_y[0] = MIN(s->text_y[0], y);
551 4d3b6f6e balrog
    s->text_y[1] = MAX(s->text_y[1], y);
552 4d3b6f6e balrog
}
553 4d3b6f6e balrog
554 14778c20 pbrook
static void invalidate_xy(TextConsole *s, int x, int y)
555 14778c20 pbrook
{
556 14778c20 pbrook
    if (s->update_x0 > x * FONT_WIDTH)
557 14778c20 pbrook
        s->update_x0 = x * FONT_WIDTH;
558 14778c20 pbrook
    if (s->update_y0 > y * FONT_HEIGHT)
559 14778c20 pbrook
        s->update_y0 = y * FONT_HEIGHT;
560 14778c20 pbrook
    if (s->update_x1 < (x + 1) * FONT_WIDTH)
561 14778c20 pbrook
        s->update_x1 = (x + 1) * FONT_WIDTH;
562 14778c20 pbrook
    if (s->update_y1 < (y + 1) * FONT_HEIGHT)
563 14778c20 pbrook
        s->update_y1 = (y + 1) * FONT_HEIGHT;
564 14778c20 pbrook
}
565 14778c20 pbrook
566 e7f0ad58 bellard
static void update_xy(TextConsole *s, int x, int y)
567 e7f0ad58 bellard
{
568 e7f0ad58 bellard
    TextCell *c;
569 e7f0ad58 bellard
    int y1, y2;
570 e7f0ad58 bellard
571 e7f0ad58 bellard
    if (s == active_console) {
572 0e1f5a0c aliguori
        if (!ds_get_bits_per_pixel(s->ds)) {
573 4d3b6f6e balrog
            text_update_xy(s, x, y);
574 4d3b6f6e balrog
            return;
575 4d3b6f6e balrog
        }
576 4d3b6f6e balrog
577 e7f0ad58 bellard
        y1 = (s->y_base + y) % s->total_height;
578 e7f0ad58 bellard
        y2 = y1 - s->y_displayed;
579 e7f0ad58 bellard
        if (y2 < 0)
580 e7f0ad58 bellard
            y2 += s->total_height;
581 e7f0ad58 bellard
        if (y2 < s->height) {
582 e7f0ad58 bellard
            c = &s->cells[y1 * s->width + x];
583 5fafdf24 ths
            vga_putcharxy(s->ds, x, y2, c->ch,
584 6d6f7c28 pbrook
                          &(c->t_attrib));
585 14778c20 pbrook
            invalidate_xy(s, x, y2);
586 e7f0ad58 bellard
        }
587 e7f0ad58 bellard
    }
588 e7f0ad58 bellard
}
589 e7f0ad58 bellard
590 e7f0ad58 bellard
static void console_show_cursor(TextConsole *s, int show)
591 e7f0ad58 bellard
{
592 e7f0ad58 bellard
    TextCell *c;
593 e7f0ad58 bellard
    int y, y1;
594 e7f0ad58 bellard
595 e7f0ad58 bellard
    if (s == active_console) {
596 ed8276ac ths
        int x = s->x;
597 4d3b6f6e balrog
598 0e1f5a0c aliguori
        if (!ds_get_bits_per_pixel(s->ds)) {
599 4d3b6f6e balrog
            s->cursor_invalidate = 1;
600 4d3b6f6e balrog
            return;
601 4d3b6f6e balrog
        }
602 4d3b6f6e balrog
603 ed8276ac ths
        if (x >= s->width) {
604 ed8276ac ths
            x = s->width - 1;
605 ed8276ac ths
        }
606 e7f0ad58 bellard
        y1 = (s->y_base + s->y) % s->total_height;
607 e7f0ad58 bellard
        y = y1 - s->y_displayed;
608 e7f0ad58 bellard
        if (y < 0)
609 e7f0ad58 bellard
            y += s->total_height;
610 e7f0ad58 bellard
        if (y < s->height) {
611 ed8276ac ths
            c = &s->cells[y1 * s->width + x];
612 e7f0ad58 bellard
            if (show) {
613 6d6f7c28 pbrook
                TextAttributes t_attrib = s->t_attrib_default;
614 6d6f7c28 pbrook
                t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
615 ed8276ac ths
                vga_putcharxy(s->ds, x, y, c->ch, &t_attrib);
616 e7f0ad58 bellard
            } else {
617 ed8276ac ths
                vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib));
618 e7f0ad58 bellard
            }
619 14778c20 pbrook
            invalidate_xy(s, x, y);
620 e7f0ad58 bellard
        }
621 e7f0ad58 bellard
    }
622 e7f0ad58 bellard
}
623 e7f0ad58 bellard
624 e7f0ad58 bellard
static void console_refresh(TextConsole *s)
625 e7f0ad58 bellard
{
626 e7f0ad58 bellard
    TextCell *c;
627 e7f0ad58 bellard
    int x, y, y1;
628 e7f0ad58 bellard
629 5fafdf24 ths
    if (s != active_console)
630 e7f0ad58 bellard
        return;
631 0e1f5a0c aliguori
    if (!ds_get_bits_per_pixel(s->ds)) {
632 4d3b6f6e balrog
        s->text_x[0] = 0;
633 4d3b6f6e balrog
        s->text_y[0] = 0;
634 4d3b6f6e balrog
        s->text_x[1] = s->width - 1;
635 4d3b6f6e balrog
        s->text_y[1] = s->height - 1;
636 4d3b6f6e balrog
        s->cursor_invalidate = 1;
637 4d3b6f6e balrog
        return;
638 4d3b6f6e balrog
    }
639 e7f0ad58 bellard
640 0e1f5a0c aliguori
    vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
641 6d6f7c28 pbrook
                  color_table[0][COLOR_BLACK]);
642 e7f0ad58 bellard
    y1 = s->y_displayed;
643 e7f0ad58 bellard
    for(y = 0; y < s->height; y++) {
644 e7f0ad58 bellard
        c = s->cells + y1 * s->width;
645 e7f0ad58 bellard
        for(x = 0; x < s->width; x++) {
646 5fafdf24 ths
            vga_putcharxy(s->ds, x, y, c->ch,
647 6d6f7c28 pbrook
                          &(c->t_attrib));
648 e7f0ad58 bellard
            c++;
649 e7f0ad58 bellard
        }
650 e7f0ad58 bellard
        if (++y1 == s->total_height)
651 e7f0ad58 bellard
            y1 = 0;
652 e7f0ad58 bellard
    }
653 e7f0ad58 bellard
    console_show_cursor(s, 1);
654 14778c20 pbrook
    dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
655 e7f0ad58 bellard
}
656 e7f0ad58 bellard
657 e7f0ad58 bellard
static void console_scroll(int ydelta)
658 e7f0ad58 bellard
{
659 e7f0ad58 bellard
    TextConsole *s;
660 e7f0ad58 bellard
    int i, y1;
661 3b46e624 ths
662 e7f0ad58 bellard
    s = active_console;
663 af3a9031 ths
    if (!s || (s->console_type == GRAPHIC_CONSOLE))
664 e7f0ad58 bellard
        return;
665 e7f0ad58 bellard
666 e7f0ad58 bellard
    if (ydelta > 0) {
667 e7f0ad58 bellard
        for(i = 0; i < ydelta; i++) {
668 e7f0ad58 bellard
            if (s->y_displayed == s->y_base)
669 e7f0ad58 bellard
                break;
670 e7f0ad58 bellard
            if (++s->y_displayed == s->total_height)
671 e7f0ad58 bellard
                s->y_displayed = 0;
672 e7f0ad58 bellard
        }
673 e7f0ad58 bellard
    } else {
674 e7f0ad58 bellard
        ydelta = -ydelta;
675 e7f0ad58 bellard
        i = s->backscroll_height;
676 e7f0ad58 bellard
        if (i > s->total_height - s->height)
677 e7f0ad58 bellard
            i = s->total_height - s->height;
678 e7f0ad58 bellard
        y1 = s->y_base - i;
679 e7f0ad58 bellard
        if (y1 < 0)
680 e7f0ad58 bellard
            y1 += s->total_height;
681 e7f0ad58 bellard
        for(i = 0; i < ydelta; i++) {
682 e7f0ad58 bellard
            if (s->y_displayed == y1)
683 e7f0ad58 bellard
                break;
684 e7f0ad58 bellard
            if (--s->y_displayed < 0)
685 e7f0ad58 bellard
                s->y_displayed = s->total_height - 1;
686 e7f0ad58 bellard
        }
687 e7f0ad58 bellard
    }
688 e7f0ad58 bellard
    console_refresh(s);
689 e7f0ad58 bellard
}
690 e7f0ad58 bellard
691 e7f0ad58 bellard
static void console_put_lf(TextConsole *s)
692 e7f0ad58 bellard
{
693 e7f0ad58 bellard
    TextCell *c;
694 e7f0ad58 bellard
    int x, y1;
695 e7f0ad58 bellard
696 e7f0ad58 bellard
    s->y++;
697 e7f0ad58 bellard
    if (s->y >= s->height) {
698 e7f0ad58 bellard
        s->y = s->height - 1;
699 6d6f7c28 pbrook
700 e7f0ad58 bellard
        if (s->y_displayed == s->y_base) {
701 e7f0ad58 bellard
            if (++s->y_displayed == s->total_height)
702 e7f0ad58 bellard
                s->y_displayed = 0;
703 e7f0ad58 bellard
        }
704 e7f0ad58 bellard
        if (++s->y_base == s->total_height)
705 e7f0ad58 bellard
            s->y_base = 0;
706 e7f0ad58 bellard
        if (s->backscroll_height < s->total_height)
707 e7f0ad58 bellard
            s->backscroll_height++;
708 e7f0ad58 bellard
        y1 = (s->y_base + s->height - 1) % s->total_height;
709 e7f0ad58 bellard
        c = &s->cells[y1 * s->width];
710 e7f0ad58 bellard
        for(x = 0; x < s->width; x++) {
711 e7f0ad58 bellard
            c->ch = ' ';
712 6d6f7c28 pbrook
            c->t_attrib = s->t_attrib_default;
713 e7f0ad58 bellard
            c++;
714 e7f0ad58 bellard
        }
715 e7f0ad58 bellard
        if (s == active_console && s->y_displayed == s->y_base) {
716 0e1f5a0c aliguori
            if (!ds_get_bits_per_pixel(s->ds)) {
717 4d3b6f6e balrog
                s->text_x[0] = 0;
718 4d3b6f6e balrog
                s->text_y[0] = 0;
719 4d3b6f6e balrog
                s->text_x[1] = s->width - 1;
720 4d3b6f6e balrog
                s->text_y[1] = s->height - 1;
721 4d3b6f6e balrog
                return;
722 4d3b6f6e balrog
            }
723 4d3b6f6e balrog
724 5fafdf24 ths
            vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0,
725 5fafdf24 ths
                       s->width * FONT_WIDTH,
726 e7f0ad58 bellard
                       (s->height - 1) * FONT_HEIGHT);
727 e7f0ad58 bellard
            vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
728 5fafdf24 ths
                          s->width * FONT_WIDTH, FONT_HEIGHT,
729 6d6f7c28 pbrook
                          color_table[0][s->t_attrib_default.bgcol]);
730 14778c20 pbrook
            s->update_x0 = 0;
731 14778c20 pbrook
            s->update_y0 = 0;
732 14778c20 pbrook
            s->update_x1 = s->width * FONT_WIDTH;
733 14778c20 pbrook
            s->update_y1 = s->height * FONT_HEIGHT;
734 e7f0ad58 bellard
        }
735 e7f0ad58 bellard
    }
736 e7f0ad58 bellard
}
737 e7f0ad58 bellard
738 6d6f7c28 pbrook
/* Set console attributes depending on the current escape codes.
739 6d6f7c28 pbrook
 * NOTE: I know this code is not very efficient (checking every color for it
740 6d6f7c28 pbrook
 * self) but it is more readable and better maintainable.
741 6d6f7c28 pbrook
 */
742 6d6f7c28 pbrook
static void console_handle_escape(TextConsole *s)
743 6d6f7c28 pbrook
{
744 6d6f7c28 pbrook
    int i;
745 6d6f7c28 pbrook
746 6d6f7c28 pbrook
    for (i=0; i<s->nb_esc_params; i++) {
747 6d6f7c28 pbrook
        switch (s->esc_params[i]) {
748 6d6f7c28 pbrook
            case 0: /* reset all console attributes to default */
749 6d6f7c28 pbrook
                s->t_attrib = s->t_attrib_default;
750 6d6f7c28 pbrook
                break;
751 6d6f7c28 pbrook
            case 1:
752 6d6f7c28 pbrook
                s->t_attrib.bold = 1;
753 6d6f7c28 pbrook
                break;
754 6d6f7c28 pbrook
            case 4:
755 6d6f7c28 pbrook
                s->t_attrib.uline = 1;
756 6d6f7c28 pbrook
                break;
757 6d6f7c28 pbrook
            case 5:
758 6d6f7c28 pbrook
                s->t_attrib.blink = 1;
759 6d6f7c28 pbrook
                break;
760 6d6f7c28 pbrook
            case 7:
761 6d6f7c28 pbrook
                s->t_attrib.invers = 1;
762 6d6f7c28 pbrook
                break;
763 6d6f7c28 pbrook
            case 8:
764 6d6f7c28 pbrook
                s->t_attrib.unvisible = 1;
765 6d6f7c28 pbrook
                break;
766 6d6f7c28 pbrook
            case 22:
767 6d6f7c28 pbrook
                s->t_attrib.bold = 0;
768 6d6f7c28 pbrook
                break;
769 6d6f7c28 pbrook
            case 24:
770 6d6f7c28 pbrook
                s->t_attrib.uline = 0;
771 6d6f7c28 pbrook
                break;
772 6d6f7c28 pbrook
            case 25:
773 6d6f7c28 pbrook
                s->t_attrib.blink = 0;
774 6d6f7c28 pbrook
                break;
775 6d6f7c28 pbrook
            case 27:
776 6d6f7c28 pbrook
                s->t_attrib.invers = 0;
777 6d6f7c28 pbrook
                break;
778 6d6f7c28 pbrook
            case 28:
779 6d6f7c28 pbrook
                s->t_attrib.unvisible = 0;
780 6d6f7c28 pbrook
                break;
781 6d6f7c28 pbrook
            /* set foreground color */
782 6d6f7c28 pbrook
            case 30:
783 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_BLACK;
784 6d6f7c28 pbrook
                break;
785 6d6f7c28 pbrook
            case 31:
786 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_RED;
787 6d6f7c28 pbrook
                break;
788 6d6f7c28 pbrook
            case 32:
789 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_GREEN;
790 6d6f7c28 pbrook
                break;
791 6d6f7c28 pbrook
            case 33:
792 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_YELLOW;
793 6d6f7c28 pbrook
                break;
794 6d6f7c28 pbrook
            case 34:
795 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_BLUE;
796 6d6f7c28 pbrook
                break;
797 6d6f7c28 pbrook
            case 35:
798 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_MAGENTA;
799 6d6f7c28 pbrook
                break;
800 6d6f7c28 pbrook
            case 36:
801 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_CYAN;
802 6d6f7c28 pbrook
                break;
803 6d6f7c28 pbrook
            case 37:
804 6d6f7c28 pbrook
                s->t_attrib.fgcol=COLOR_WHITE;
805 6d6f7c28 pbrook
                break;
806 6d6f7c28 pbrook
            /* set background color */
807 6d6f7c28 pbrook
            case 40:
808 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_BLACK;
809 6d6f7c28 pbrook
                break;
810 6d6f7c28 pbrook
            case 41:
811 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_RED;
812 6d6f7c28 pbrook
                break;
813 6d6f7c28 pbrook
            case 42:
814 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_GREEN;
815 6d6f7c28 pbrook
                break;
816 6d6f7c28 pbrook
            case 43:
817 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_YELLOW;
818 6d6f7c28 pbrook
                break;
819 6d6f7c28 pbrook
            case 44:
820 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_BLUE;
821 6d6f7c28 pbrook
                break;
822 6d6f7c28 pbrook
            case 45:
823 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_MAGENTA;
824 6d6f7c28 pbrook
                break;
825 6d6f7c28 pbrook
            case 46:
826 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_CYAN;
827 6d6f7c28 pbrook
                break;
828 6d6f7c28 pbrook
            case 47:
829 6d6f7c28 pbrook
                s->t_attrib.bgcol=COLOR_WHITE;
830 6d6f7c28 pbrook
                break;
831 6d6f7c28 pbrook
        }
832 6d6f7c28 pbrook
    }
833 6d6f7c28 pbrook
}
834 6d6f7c28 pbrook
835 adb47967 ths
static void console_clear_xy(TextConsole *s, int x, int y)
836 adb47967 ths
{
837 adb47967 ths
    int y1 = (s->y_base + y) % s->total_height;
838 adb47967 ths
    TextCell *c = &s->cells[y1 * s->width + x];
839 adb47967 ths
    c->ch = ' ';
840 adb47967 ths
    c->t_attrib = s->t_attrib_default;
841 adb47967 ths
    update_xy(s, x, y);
842 adb47967 ths
}
843 adb47967 ths
844 e7f0ad58 bellard
static void console_putchar(TextConsole *s, int ch)
845 e7f0ad58 bellard
{
846 e7f0ad58 bellard
    TextCell *c;
847 adb47967 ths
    int y1, i;
848 adb47967 ths
    int x, y;
849 e7f0ad58 bellard
850 e7f0ad58 bellard
    switch(s->state) {
851 e7f0ad58 bellard
    case TTY_STATE_NORM:
852 e7f0ad58 bellard
        switch(ch) {
853 6d6f7c28 pbrook
        case '\r':  /* carriage return */
854 e7f0ad58 bellard
            s->x = 0;
855 e7f0ad58 bellard
            break;
856 6d6f7c28 pbrook
        case '\n':  /* newline */
857 e7f0ad58 bellard
            console_put_lf(s);
858 e7f0ad58 bellard
            break;
859 6d6f7c28 pbrook
        case '\b':  /* backspace */
860 5fafdf24 ths
            if (s->x > 0)
861 e15d7371 bellard
                s->x--;
862 6d6f7c28 pbrook
            break;
863 6d6f7c28 pbrook
        case '\t':  /* tabspace */
864 6d6f7c28 pbrook
            if (s->x + (8 - (s->x % 8)) > s->width) {
865 bd468840 bellard
                s->x = 0;
866 6d6f7c28 pbrook
                console_put_lf(s);
867 6d6f7c28 pbrook
            } else {
868 6d6f7c28 pbrook
                s->x = s->x + (8 - (s->x % 8));
869 6d6f7c28 pbrook
            }
870 6d6f7c28 pbrook
            break;
871 6d6f7c28 pbrook
        case '\a':  /* alert aka. bell */
872 6d6f7c28 pbrook
            /* TODO: has to be implemented */
873 6d6f7c28 pbrook
            break;
874 adb47967 ths
        case 14:
875 adb47967 ths
            /* SI (shift in), character set 0 (ignored) */
876 adb47967 ths
            break;
877 adb47967 ths
        case 15:
878 adb47967 ths
            /* SO (shift out), character set 1 (ignored) */
879 adb47967 ths
            break;
880 6d6f7c28 pbrook
        case 27:    /* esc (introducing an escape sequence) */
881 e7f0ad58 bellard
            s->state = TTY_STATE_ESC;
882 e7f0ad58 bellard
            break;
883 e7f0ad58 bellard
        default:
884 ed8276ac ths
            if (s->x >= s->width) {
885 ed8276ac ths
                /* line wrap */
886 ed8276ac ths
                s->x = 0;
887 ed8276ac ths
                console_put_lf(s);
888 adb47967 ths
            }
889 e7f0ad58 bellard
            y1 = (s->y_base + s->y) % s->total_height;
890 e7f0ad58 bellard
            c = &s->cells[y1 * s->width + s->x];
891 e7f0ad58 bellard
            c->ch = ch;
892 6d6f7c28 pbrook
            c->t_attrib = s->t_attrib;
893 e7f0ad58 bellard
            update_xy(s, s->x, s->y);
894 e7f0ad58 bellard
            s->x++;
895 e7f0ad58 bellard
            break;
896 e7f0ad58 bellard
        }
897 e7f0ad58 bellard
        break;
898 6d6f7c28 pbrook
    case TTY_STATE_ESC: /* check if it is a terminal escape sequence */
899 e7f0ad58 bellard
        if (ch == '[') {
900 e7f0ad58 bellard
            for(i=0;i<MAX_ESC_PARAMS;i++)
901 e7f0ad58 bellard
                s->esc_params[i] = 0;
902 e7f0ad58 bellard
            s->nb_esc_params = 0;
903 e7f0ad58 bellard
            s->state = TTY_STATE_CSI;
904 e7f0ad58 bellard
        } else {
905 e7f0ad58 bellard
            s->state = TTY_STATE_NORM;
906 e7f0ad58 bellard
        }
907 e7f0ad58 bellard
        break;
908 6d6f7c28 pbrook
    case TTY_STATE_CSI: /* handle escape sequence parameters */
909 e7f0ad58 bellard
        if (ch >= '0' && ch <= '9') {
910 e7f0ad58 bellard
            if (s->nb_esc_params < MAX_ESC_PARAMS) {
911 5fafdf24 ths
                s->esc_params[s->nb_esc_params] =
912 e7f0ad58 bellard
                    s->esc_params[s->nb_esc_params] * 10 + ch - '0';
913 e7f0ad58 bellard
            }
914 e7f0ad58 bellard
        } else {
915 e7f0ad58 bellard
            s->nb_esc_params++;
916 e7f0ad58 bellard
            if (ch == ';')
917 e7f0ad58 bellard
                break;
918 adb47967 ths
#ifdef DEBUG_CONSOLE
919 adb47967 ths
            fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
920 adb47967 ths
                    s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
921 adb47967 ths
#endif
922 e7f0ad58 bellard
            s->state = TTY_STATE_NORM;
923 e7f0ad58 bellard
            switch(ch) {
924 adb47967 ths
            case 'A':
925 adb47967 ths
                /* move cursor up */
926 adb47967 ths
                if (s->esc_params[0] == 0) {
927 adb47967 ths
                    s->esc_params[0] = 1;
928 adb47967 ths
                }
929 adb47967 ths
                s->y -= s->esc_params[0];
930 adb47967 ths
                if (s->y < 0) {
931 adb47967 ths
                    s->y = 0;
932 adb47967 ths
                }
933 adb47967 ths
                break;
934 adb47967 ths
            case 'B':
935 adb47967 ths
                /* move cursor down */
936 adb47967 ths
                if (s->esc_params[0] == 0) {
937 adb47967 ths
                    s->esc_params[0] = 1;
938 adb47967 ths
                }
939 adb47967 ths
                s->y += s->esc_params[0];
940 adb47967 ths
                if (s->y >= s->height) {
941 adb47967 ths
                    s->y = s->height - 1;
942 adb47967 ths
                }
943 e7f0ad58 bellard
                break;
944 e7f0ad58 bellard
            case 'C':
945 adb47967 ths
                /* move cursor right */
946 adb47967 ths
                if (s->esc_params[0] == 0) {
947 adb47967 ths
                    s->esc_params[0] = 1;
948 adb47967 ths
                }
949 adb47967 ths
                s->x += s->esc_params[0];
950 adb47967 ths
                if (s->x >= s->width) {
951 adb47967 ths
                    s->x = s->width - 1;
952 adb47967 ths
                }
953 e7f0ad58 bellard
                break;
954 adb47967 ths
            case 'D':
955 adb47967 ths
                /* move cursor left */
956 adb47967 ths
                if (s->esc_params[0] == 0) {
957 adb47967 ths
                    s->esc_params[0] = 1;
958 adb47967 ths
                }
959 adb47967 ths
                s->x -= s->esc_params[0];
960 adb47967 ths
                if (s->x < 0) {
961 adb47967 ths
                    s->x = 0;
962 adb47967 ths
                }
963 adb47967 ths
                break;
964 adb47967 ths
            case 'G':
965 adb47967 ths
                /* move cursor to column */
966 adb47967 ths
                s->x = s->esc_params[0] - 1;
967 adb47967 ths
                if (s->x < 0) {
968 adb47967 ths
                    s->x = 0;
969 adb47967 ths
                }
970 adb47967 ths
                break;
971 adb47967 ths
            case 'f':
972 adb47967 ths
            case 'H':
973 adb47967 ths
                /* move cursor to row, column */
974 adb47967 ths
                s->x = s->esc_params[1] - 1;
975 adb47967 ths
                if (s->x < 0) {
976 adb47967 ths
                    s->x = 0;
977 adb47967 ths
                }
978 adb47967 ths
                s->y = s->esc_params[0] - 1;
979 adb47967 ths
                if (s->y < 0) {
980 adb47967 ths
                    s->y = 0;
981 adb47967 ths
                }
982 adb47967 ths
                break;
983 adb47967 ths
            case 'J':
984 adb47967 ths
                switch (s->esc_params[0]) {
985 adb47967 ths
                case 0:
986 adb47967 ths
                    /* clear to end of screen */
987 adb47967 ths
                    for (y = s->y; y < s->height; y++) {
988 adb47967 ths
                        for (x = 0; x < s->width; x++) {
989 adb47967 ths
                            if (y == s->y && x < s->x) {
990 adb47967 ths
                                continue;
991 adb47967 ths
                            }
992 adb47967 ths
                            console_clear_xy(s, x, y);
993 adb47967 ths
                        }
994 adb47967 ths
                    }
995 adb47967 ths
                    break;
996 adb47967 ths
                case 1:
997 adb47967 ths
                    /* clear from beginning of screen */
998 adb47967 ths
                    for (y = 0; y <= s->y; y++) {
999 adb47967 ths
                        for (x = 0; x < s->width; x++) {
1000 adb47967 ths
                            if (y == s->y && x > s->x) {
1001 adb47967 ths
                                break;
1002 adb47967 ths
                            }
1003 adb47967 ths
                            console_clear_xy(s, x, y);
1004 adb47967 ths
                        }
1005 adb47967 ths
                    }
1006 adb47967 ths
                    break;
1007 adb47967 ths
                case 2:
1008 adb47967 ths
                    /* clear entire screen */
1009 adb47967 ths
                    for (y = 0; y <= s->height; y++) {
1010 adb47967 ths
                        for (x = 0; x < s->width; x++) {
1011 adb47967 ths
                            console_clear_xy(s, x, y);
1012 adb47967 ths
                        }
1013 adb47967 ths
                    }
1014 f94a950f Markus Armbruster
                    break;
1015 adb47967 ths
                }
1016 95d8f9f4 Markus Armbruster
                break;
1017 e7f0ad58 bellard
            case 'K':
1018 adb47967 ths
                switch (s->esc_params[0]) {
1019 adb47967 ths
                case 0:
1020 f94a950f Markus Armbruster
                    /* clear to eol */
1021 f94a950f Markus Armbruster
                    for(x = s->x; x < s->width; x++) {
1022 adb47967 ths
                        console_clear_xy(s, x, s->y);
1023 f94a950f Markus Armbruster
                    }
1024 f94a950f Markus Armbruster
                    break;
1025 adb47967 ths
                case 1:
1026 adb47967 ths
                    /* clear from beginning of line */
1027 adb47967 ths
                    for (x = 0; x <= s->x; x++) {
1028 adb47967 ths
                        console_clear_xy(s, x, s->y);
1029 adb47967 ths
                    }
1030 adb47967 ths
                    break;
1031 adb47967 ths
                case 2:
1032 adb47967 ths
                    /* clear entire line */
1033 adb47967 ths
                    for(x = 0; x < s->width; x++) {
1034 adb47967 ths
                        console_clear_xy(s, x, s->y);
1035 adb47967 ths
                    }
1036 f94a950f Markus Armbruster
                    break;
1037 f94a950f Markus Armbruster
                }
1038 adb47967 ths
                break;
1039 adb47967 ths
            case 'm':
1040 f94a950f Markus Armbruster
                console_handle_escape(s);
1041 f94a950f Markus Armbruster
                break;
1042 adb47967 ths
            case 'n':
1043 adb47967 ths
                /* report cursor position */
1044 adb47967 ths
                /* TODO: send ESC[row;colR */
1045 adb47967 ths
                break;
1046 adb47967 ths
            case 's':
1047 adb47967 ths
                /* save cursor position */
1048 adb47967 ths
                s->x_saved = s->x;
1049 adb47967 ths
                s->y_saved = s->y;
1050 adb47967 ths
                break;
1051 adb47967 ths
            case 'u':
1052 adb47967 ths
                /* restore cursor position */
1053 adb47967 ths
                s->x = s->x_saved;
1054 adb47967 ths
                s->y = s->y_saved;
1055 adb47967 ths
                break;
1056 adb47967 ths
            default:
1057 adb47967 ths
#ifdef DEBUG_CONSOLE
1058 adb47967 ths
                fprintf(stderr, "unhandled escape character '%c'\n", ch);
1059 adb47967 ths
#endif
1060 adb47967 ths
                break;
1061 adb47967 ths
            }
1062 adb47967 ths
            break;
1063 e7f0ad58 bellard
        }
1064 e7f0ad58 bellard
    }
1065 e7f0ad58 bellard
}
1066 e7f0ad58 bellard
1067 e7f0ad58 bellard
void console_select(unsigned int index)
1068 e7f0ad58 bellard
{
1069 e7f0ad58 bellard
    TextConsole *s;
1070 6d6f7c28 pbrook
1071 e7f0ad58 bellard
    if (index >= MAX_CONSOLES)
1072 e7f0ad58 bellard
        return;
1073 358664cc Stefan Hajnoczi
    if (active_console) {
1074 358664cc Stefan Hajnoczi
        active_console->g_width = ds_get_width(active_console->ds);
1075 358664cc Stefan Hajnoczi
        active_console->g_height = ds_get_height(active_console->ds);
1076 358664cc Stefan Hajnoczi
    }
1077 e7f0ad58 bellard
    s = consoles[index];
1078 e7f0ad58 bellard
    if (s) {
1079 7d957bd8 aliguori
        DisplayState *ds = s->ds;
1080 e7f0ad58 bellard
        active_console = s;
1081 68f00996 aliguori
        if (ds_get_bits_per_pixel(s->ds)) {
1082 7b5d76da aliguori
            ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
1083 68f00996 aliguori
        } else {
1084 68f00996 aliguori
            s->ds->surface->width = s->width;
1085 68f00996 aliguori
            s->ds->surface->height = s->height;
1086 68f00996 aliguori
        }
1087 7d957bd8 aliguori
        dpy_resize(s->ds);
1088 4d3b6f6e balrog
        vga_hw_invalidate();
1089 e7f0ad58 bellard
    }
1090 e7f0ad58 bellard
}
1091 e7f0ad58 bellard
1092 e7f0ad58 bellard
static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
1093 e7f0ad58 bellard
{
1094 e7f0ad58 bellard
    TextConsole *s = chr->opaque;
1095 e7f0ad58 bellard
    int i;
1096 e7f0ad58 bellard
1097 14778c20 pbrook
    s->update_x0 = s->width * FONT_WIDTH;
1098 14778c20 pbrook
    s->update_y0 = s->height * FONT_HEIGHT;
1099 14778c20 pbrook
    s->update_x1 = 0;
1100 14778c20 pbrook
    s->update_y1 = 0;
1101 e7f0ad58 bellard
    console_show_cursor(s, 0);
1102 e7f0ad58 bellard
    for(i = 0; i < len; i++) {
1103 e7f0ad58 bellard
        console_putchar(s, buf[i]);
1104 e7f0ad58 bellard
    }
1105 e7f0ad58 bellard
    console_show_cursor(s, 1);
1106 14778c20 pbrook
    if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) {
1107 14778c20 pbrook
        dpy_update(s->ds, s->update_x0, s->update_y0,
1108 14778c20 pbrook
                   s->update_x1 - s->update_x0,
1109 14778c20 pbrook
                   s->update_y1 - s->update_y0);
1110 14778c20 pbrook
    }
1111 e7f0ad58 bellard
    return len;
1112 e7f0ad58 bellard
}
1113 e7f0ad58 bellard
1114 e15d7371 bellard
static void kbd_send_chars(void *opaque)
1115 e15d7371 bellard
{
1116 e15d7371 bellard
    TextConsole *s = opaque;
1117 e15d7371 bellard
    int len;
1118 e15d7371 bellard
    uint8_t buf[16];
1119 3b46e624 ths
1120 909cda12 Anthony Liguori
    len = qemu_chr_be_can_write(s->chr);
1121 e15d7371 bellard
    if (len > s->out_fifo.count)
1122 e15d7371 bellard
        len = s->out_fifo.count;
1123 e15d7371 bellard
    if (len > 0) {
1124 e15d7371 bellard
        if (len > sizeof(buf))
1125 e15d7371 bellard
            len = sizeof(buf);
1126 e15d7371 bellard
        qemu_fifo_read(&s->out_fifo, buf, len);
1127 fa5efccb Anthony Liguori
        qemu_chr_be_write(s->chr, buf, len);
1128 e15d7371 bellard
    }
1129 e15d7371 bellard
    /* characters are pending: we send them a bit later (XXX:
1130 e15d7371 bellard
       horrible, should change char device API) */
1131 e15d7371 bellard
    if (s->out_fifo.count > 0) {
1132 7bd427d8 Paolo Bonzini
        qemu_mod_timer(s->kbd_timer, qemu_get_clock_ms(rt_clock) + 1);
1133 e15d7371 bellard
    }
1134 e15d7371 bellard
}
1135 e15d7371 bellard
1136 e7f0ad58 bellard
/* called when an ascii key is pressed */
1137 e7f0ad58 bellard
void kbd_put_keysym(int keysym)
1138 e7f0ad58 bellard
{
1139 e7f0ad58 bellard
    TextConsole *s;
1140 e7f0ad58 bellard
    uint8_t buf[16], *q;
1141 e7f0ad58 bellard
    int c;
1142 e7f0ad58 bellard
1143 e7f0ad58 bellard
    s = active_console;
1144 af3a9031 ths
    if (!s || (s->console_type == GRAPHIC_CONSOLE))
1145 e7f0ad58 bellard
        return;
1146 e7f0ad58 bellard
1147 e7f0ad58 bellard
    switch(keysym) {
1148 e7f0ad58 bellard
    case QEMU_KEY_CTRL_UP:
1149 e7f0ad58 bellard
        console_scroll(-1);
1150 e7f0ad58 bellard
        break;
1151 e7f0ad58 bellard
    case QEMU_KEY_CTRL_DOWN:
1152 e7f0ad58 bellard
        console_scroll(1);
1153 e7f0ad58 bellard
        break;
1154 e7f0ad58 bellard
    case QEMU_KEY_CTRL_PAGEUP:
1155 e7f0ad58 bellard
        console_scroll(-10);
1156 e7f0ad58 bellard
        break;
1157 e7f0ad58 bellard
    case QEMU_KEY_CTRL_PAGEDOWN:
1158 e7f0ad58 bellard
        console_scroll(10);
1159 e7f0ad58 bellard
        break;
1160 e7f0ad58 bellard
    default:
1161 e15d7371 bellard
        /* convert the QEMU keysym to VT100 key string */
1162 e15d7371 bellard
        q = buf;
1163 e15d7371 bellard
        if (keysym >= 0xe100 && keysym <= 0xe11f) {
1164 e15d7371 bellard
            *q++ = '\033';
1165 e15d7371 bellard
            *q++ = '[';
1166 e15d7371 bellard
            c = keysym - 0xe100;
1167 e15d7371 bellard
            if (c >= 10)
1168 e15d7371 bellard
                *q++ = '0' + (c / 10);
1169 e15d7371 bellard
            *q++ = '0' + (c % 10);
1170 e15d7371 bellard
            *q++ = '~';
1171 e15d7371 bellard
        } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
1172 e15d7371 bellard
            *q++ = '\033';
1173 e15d7371 bellard
            *q++ = '[';
1174 e15d7371 bellard
            *q++ = keysym & 0xff;
1175 4104833f Paolo Bonzini
        } else if (s->echo && (keysym == '\r' || keysym == '\n')) {
1176 4104833f Paolo Bonzini
            console_puts(s->chr, (const uint8_t *) "\r", 1);
1177 4104833f Paolo Bonzini
            *q++ = '\n';
1178 e15d7371 bellard
        } else {
1179 4104833f Paolo Bonzini
            *q++ = keysym;
1180 4104833f Paolo Bonzini
        }
1181 4104833f Paolo Bonzini
        if (s->echo) {
1182 4104833f Paolo Bonzini
            console_puts(s->chr, buf, q - buf);
1183 e15d7371 bellard
        }
1184 e5b0bc44 pbrook
        if (s->chr->chr_read) {
1185 e15d7371 bellard
            qemu_fifo_write(&s->out_fifo, buf, q - buf);
1186 e15d7371 bellard
            kbd_send_chars(s);
1187 e7f0ad58 bellard
        }
1188 e7f0ad58 bellard
        break;
1189 e7f0ad58 bellard
    }
1190 e7f0ad58 bellard
}
1191 e7f0ad58 bellard
1192 4d3b6f6e balrog
static void text_console_invalidate(void *opaque)
1193 4d3b6f6e balrog
{
1194 4d3b6f6e balrog
    TextConsole *s = (TextConsole *) opaque;
1195 68f00996 aliguori
    if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) {
1196 68f00996 aliguori
        s->g_width = ds_get_width(s->ds);
1197 68f00996 aliguori
        s->g_height = ds_get_height(s->ds);
1198 68f00996 aliguori
        text_console_resize(s);
1199 68f00996 aliguori
    }
1200 4d3b6f6e balrog
    console_refresh(s);
1201 4d3b6f6e balrog
}
1202 4d3b6f6e balrog
1203 c227f099 Anthony Liguori
static void text_console_update(void *opaque, console_ch_t *chardata)
1204 4d3b6f6e balrog
{
1205 4d3b6f6e balrog
    TextConsole *s = (TextConsole *) opaque;
1206 4d3b6f6e balrog
    int i, j, src;
1207 4d3b6f6e balrog
1208 4d3b6f6e balrog
    if (s->text_x[0] <= s->text_x[1]) {
1209 4d3b6f6e balrog
        src = (s->y_base + s->text_y[0]) * s->width;
1210 4d3b6f6e balrog
        chardata += s->text_y[0] * s->width;
1211 4d3b6f6e balrog
        for (i = s->text_y[0]; i <= s->text_y[1]; i ++)
1212 4d3b6f6e balrog
            for (j = 0; j < s->width; j ++, src ++)
1213 4d3b6f6e balrog
                console_write_ch(chardata ++, s->cells[src].ch |
1214 4d3b6f6e balrog
                                (s->cells[src].t_attrib.fgcol << 12) |
1215 4d3b6f6e balrog
                                (s->cells[src].t_attrib.bgcol << 8) |
1216 4d3b6f6e balrog
                                (s->cells[src].t_attrib.bold << 21));
1217 4d3b6f6e balrog
        dpy_update(s->ds, s->text_x[0], s->text_y[0],
1218 4d3b6f6e balrog
                   s->text_x[1] - s->text_x[0], i - s->text_y[0]);
1219 4d3b6f6e balrog
        s->text_x[0] = s->width;
1220 4d3b6f6e balrog
        s->text_y[0] = s->height;
1221 4d3b6f6e balrog
        s->text_x[1] = 0;
1222 4d3b6f6e balrog
        s->text_y[1] = 0;
1223 4d3b6f6e balrog
    }
1224 4d3b6f6e balrog
    if (s->cursor_invalidate) {
1225 4d3b6f6e balrog
        dpy_cursor(s->ds, s->x, s->y);
1226 4d3b6f6e balrog
        s->cursor_invalidate = 0;
1227 4d3b6f6e balrog
    }
1228 4d3b6f6e balrog
}
1229 4d3b6f6e balrog
1230 42aa98e8 aliguori
static TextConsole *get_graphic_console(DisplayState *ds)
1231 a147d62b blueswir1
{
1232 3023f332 aliguori
    int i;
1233 3023f332 aliguori
    TextConsole *s;
1234 3023f332 aliguori
    for (i = 0; i < nb_consoles; i++) {
1235 3023f332 aliguori
        s = consoles[i];
1236 42aa98e8 aliguori
        if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds)
1237 3023f332 aliguori
            return s;
1238 3023f332 aliguori
    }
1239 3023f332 aliguori
    return NULL;
1240 3023f332 aliguori
}
1241 3023f332 aliguori
1242 c227f099 Anthony Liguori
static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
1243 e7f0ad58 bellard
{
1244 e7f0ad58 bellard
    TextConsole *s;
1245 95219897 pbrook
    int i;
1246 e7f0ad58 bellard
1247 e7f0ad58 bellard
    if (nb_consoles >= MAX_CONSOLES)
1248 e7f0ad58 bellard
        return NULL;
1249 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(TextConsole));
1250 af3a9031 ths
    if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
1251 af3a9031 ths
        (console_type == GRAPHIC_CONSOLE))) {
1252 e7f0ad58 bellard
        active_console = s;
1253 af3a9031 ths
    }
1254 e7f0ad58 bellard
    s->ds = ds;
1255 af3a9031 ths
    s->console_type = console_type;
1256 af3a9031 ths
    if (console_type != GRAPHIC_CONSOLE) {
1257 f81bdefb Jan Kiszka
        s->index = nb_consoles;
1258 95219897 pbrook
        consoles[nb_consoles++] = s;
1259 95219897 pbrook
    } else {
1260 95219897 pbrook
        /* HACK: Put graphical consoles before text consoles.  */
1261 95219897 pbrook
        for (i = nb_consoles; i > 0; i--) {
1262 af3a9031 ths
            if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
1263 95219897 pbrook
                break;
1264 95219897 pbrook
            consoles[i] = consoles[i - 1];
1265 f81bdefb Jan Kiszka
            consoles[i]->index = i;
1266 95219897 pbrook
        }
1267 f81bdefb Jan Kiszka
        s->index = i;
1268 95219897 pbrook
        consoles[i] = s;
1269 3023f332 aliguori
        nb_consoles++;
1270 95219897 pbrook
    }
1271 95219897 pbrook
    return s;
1272 95219897 pbrook
}
1273 95219897 pbrook
1274 98b50080 Paolo Bonzini
static DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
1275 98b50080 Paolo Bonzini
{
1276 7267c094 Anthony Liguori
    DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
1277 98b50080 Paolo Bonzini
1278 ffe8b821 Jes Sorensen
    int linesize = width * 4;
1279 ffe8b821 Jes Sorensen
    qemu_alloc_display(surface, width, height, linesize,
1280 ffe8b821 Jes Sorensen
                       qemu_default_pixelformat(32), 0);
1281 98b50080 Paolo Bonzini
    return surface;
1282 98b50080 Paolo Bonzini
}
1283 98b50080 Paolo Bonzini
1284 98b50080 Paolo Bonzini
static DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
1285 98b50080 Paolo Bonzini
                                          int width, int height)
1286 98b50080 Paolo Bonzini
{
1287 ffe8b821 Jes Sorensen
    int linesize = width * 4;
1288 ffe8b821 Jes Sorensen
    qemu_alloc_display(surface, width, height, linesize,
1289 ffe8b821 Jes Sorensen
                       qemu_default_pixelformat(32), 0);
1290 ffe8b821 Jes Sorensen
    return surface;
1291 ffe8b821 Jes Sorensen
}
1292 ffe8b821 Jes Sorensen
1293 ffe8b821 Jes Sorensen
void qemu_alloc_display(DisplaySurface *surface, int width, int height,
1294 ffe8b821 Jes Sorensen
                        int linesize, PixelFormat pf, int newflags)
1295 ffe8b821 Jes Sorensen
{
1296 ffe8b821 Jes Sorensen
    void *data;
1297 98b50080 Paolo Bonzini
    surface->width = width;
1298 98b50080 Paolo Bonzini
    surface->height = height;
1299 ffe8b821 Jes Sorensen
    surface->linesize = linesize;
1300 ffe8b821 Jes Sorensen
    surface->pf = pf;
1301 ffe8b821 Jes Sorensen
    if (surface->flags & QEMU_ALLOCATED_FLAG) {
1302 7267c094 Anthony Liguori
        data = g_realloc(surface->data,
1303 ffe8b821 Jes Sorensen
                            surface->linesize * surface->height);
1304 ffe8b821 Jes Sorensen
    } else {
1305 7267c094 Anthony Liguori
        data = g_malloc(surface->linesize * surface->height);
1306 ffe8b821 Jes Sorensen
    }
1307 ffe8b821 Jes Sorensen
    surface->data = (uint8_t *)data;
1308 ffe8b821 Jes Sorensen
    surface->flags = newflags | QEMU_ALLOCATED_FLAG;
1309 98b50080 Paolo Bonzini
#ifdef HOST_WORDS_BIGENDIAN
1310 ffe8b821 Jes Sorensen
    surface->flags |= QEMU_BIG_ENDIAN_FLAG;
1311 98b50080 Paolo Bonzini
#endif
1312 98b50080 Paolo Bonzini
}
1313 98b50080 Paolo Bonzini
1314 98b50080 Paolo Bonzini
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
1315 98b50080 Paolo Bonzini
                                              int linesize, uint8_t *data)
1316 98b50080 Paolo Bonzini
{
1317 7267c094 Anthony Liguori
    DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
1318 98b50080 Paolo Bonzini
1319 98b50080 Paolo Bonzini
    surface->width = width;
1320 98b50080 Paolo Bonzini
    surface->height = height;
1321 98b50080 Paolo Bonzini
    surface->linesize = linesize;
1322 98b50080 Paolo Bonzini
    surface->pf = qemu_default_pixelformat(bpp);
1323 98b50080 Paolo Bonzini
#ifdef HOST_WORDS_BIGENDIAN
1324 98b50080 Paolo Bonzini
    surface->flags = QEMU_BIG_ENDIAN_FLAG;
1325 98b50080 Paolo Bonzini
#endif
1326 98b50080 Paolo Bonzini
    surface->data = data;
1327 98b50080 Paolo Bonzini
1328 98b50080 Paolo Bonzini
    return surface;
1329 98b50080 Paolo Bonzini
}
1330 98b50080 Paolo Bonzini
1331 98b50080 Paolo Bonzini
static void defaultallocator_free_displaysurface(DisplaySurface *surface)
1332 98b50080 Paolo Bonzini
{
1333 98b50080 Paolo Bonzini
    if (surface == NULL)
1334 98b50080 Paolo Bonzini
        return;
1335 98b50080 Paolo Bonzini
    if (surface->flags & QEMU_ALLOCATED_FLAG)
1336 7267c094 Anthony Liguori
        g_free(surface->data);
1337 7267c094 Anthony Liguori
    g_free(surface);
1338 98b50080 Paolo Bonzini
}
1339 98b50080 Paolo Bonzini
1340 98b50080 Paolo Bonzini
static struct DisplayAllocator default_allocator = {
1341 98b50080 Paolo Bonzini
    defaultallocator_create_displaysurface,
1342 98b50080 Paolo Bonzini
    defaultallocator_resize_displaysurface,
1343 98b50080 Paolo Bonzini
    defaultallocator_free_displaysurface
1344 98b50080 Paolo Bonzini
};
1345 98b50080 Paolo Bonzini
1346 98b50080 Paolo Bonzini
static void dumb_display_init(void)
1347 98b50080 Paolo Bonzini
{
1348 7267c094 Anthony Liguori
    DisplayState *ds = g_malloc0(sizeof(DisplayState));
1349 1802651c Jan Kiszka
    int width = 640;
1350 1802651c Jan Kiszka
    int height = 480;
1351 1802651c Jan Kiszka
1352 98b50080 Paolo Bonzini
    ds->allocator = &default_allocator;
1353 1802651c Jan Kiszka
    if (is_fixedsize_console()) {
1354 1802651c Jan Kiszka
        width = active_console->g_width;
1355 1802651c Jan Kiszka
        height = active_console->g_height;
1356 1802651c Jan Kiszka
    }
1357 1802651c Jan Kiszka
    ds->surface = qemu_create_displaysurface(ds, width, height);
1358 98b50080 Paolo Bonzini
    register_displaystate(ds);
1359 98b50080 Paolo Bonzini
}
1360 98b50080 Paolo Bonzini
1361 98b50080 Paolo Bonzini
/***********************************************************/
1362 98b50080 Paolo Bonzini
/* register display */
1363 98b50080 Paolo Bonzini
1364 98b50080 Paolo Bonzini
void register_displaystate(DisplayState *ds)
1365 98b50080 Paolo Bonzini
{
1366 98b50080 Paolo Bonzini
    DisplayState **s;
1367 98b50080 Paolo Bonzini
    s = &display_state;
1368 98b50080 Paolo Bonzini
    while (*s != NULL)
1369 98b50080 Paolo Bonzini
        s = &(*s)->next;
1370 98b50080 Paolo Bonzini
    ds->next = NULL;
1371 98b50080 Paolo Bonzini
    *s = ds;
1372 98b50080 Paolo Bonzini
}
1373 98b50080 Paolo Bonzini
1374 98b50080 Paolo Bonzini
DisplayState *get_displaystate(void)
1375 98b50080 Paolo Bonzini
{
1376 98b50080 Paolo Bonzini
    if (!display_state) {
1377 98b50080 Paolo Bonzini
        dumb_display_init ();
1378 98b50080 Paolo Bonzini
    }
1379 98b50080 Paolo Bonzini
    return display_state;
1380 98b50080 Paolo Bonzini
}
1381 98b50080 Paolo Bonzini
1382 98b50080 Paolo Bonzini
DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
1383 98b50080 Paolo Bonzini
{
1384 98b50080 Paolo Bonzini
    if(ds->allocator ==  &default_allocator) {
1385 98b50080 Paolo Bonzini
        DisplaySurface *surf;
1386 98b50080 Paolo Bonzini
        surf = da->create_displaysurface(ds_get_width(ds), ds_get_height(ds));
1387 98b50080 Paolo Bonzini
        defaultallocator_free_displaysurface(ds->surface);
1388 98b50080 Paolo Bonzini
        ds->surface = surf;
1389 98b50080 Paolo Bonzini
        ds->allocator = da;
1390 98b50080 Paolo Bonzini
    }
1391 98b50080 Paolo Bonzini
    return ds->allocator;
1392 98b50080 Paolo Bonzini
}
1393 98b50080 Paolo Bonzini
1394 3023f332 aliguori
DisplayState *graphic_console_init(vga_hw_update_ptr update,
1395 3023f332 aliguori
                                   vga_hw_invalidate_ptr invalidate,
1396 3023f332 aliguori
                                   vga_hw_screen_dump_ptr screen_dump,
1397 3023f332 aliguori
                                   vga_hw_text_update_ptr text_update,
1398 3023f332 aliguori
                                   void *opaque)
1399 95219897 pbrook
{
1400 95219897 pbrook
    TextConsole *s;
1401 3023f332 aliguori
    DisplayState *ds;
1402 f0f2f976 aurel32
1403 7267c094 Anthony Liguori
    ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
1404 7b5d76da aliguori
    ds->allocator = &default_allocator; 
1405 7b5d76da aliguori
    ds->surface = qemu_create_displaysurface(ds, 640, 480);
1406 95219897 pbrook
1407 af3a9031 ths
    s = new_console(ds, GRAPHIC_CONSOLE);
1408 3023f332 aliguori
    if (s == NULL) {
1409 7b5d76da aliguori
        qemu_free_displaysurface(ds);
1410 7267c094 Anthony Liguori
        g_free(ds);
1411 3023f332 aliguori
        return NULL;
1412 3023f332 aliguori
    }
1413 95219897 pbrook
    s->hw_update = update;
1414 95219897 pbrook
    s->hw_invalidate = invalidate;
1415 95219897 pbrook
    s->hw_screen_dump = screen_dump;
1416 4d3b6f6e balrog
    s->hw_text_update = text_update;
1417 95219897 pbrook
    s->hw = opaque;
1418 3023f332 aliguori
1419 f0f2f976 aurel32
    register_displaystate(ds);
1420 3023f332 aliguori
    return ds;
1421 e7f0ad58 bellard
}
1422 e7f0ad58 bellard
1423 95219897 pbrook
int is_graphic_console(void)
1424 e7f0ad58 bellard
{
1425 4d3b6f6e balrog
    return active_console && active_console->console_type == GRAPHIC_CONSOLE;
1426 e7f0ad58 bellard
}
1427 e7f0ad58 bellard
1428 c21bbcfa balrog
int is_fixedsize_console(void)
1429 c21bbcfa balrog
{
1430 c21bbcfa balrog
    return active_console && active_console->console_type != TEXT_CONSOLE;
1431 c21bbcfa balrog
}
1432 c21bbcfa balrog
1433 a528b80c balrog
void console_color_init(DisplayState *ds)
1434 a528b80c balrog
{
1435 a528b80c balrog
    int i, j;
1436 a528b80c balrog
    for (j = 0; j < 2; j++) {
1437 a528b80c balrog
        for (i = 0; i < 8; i++) {
1438 f0f2f976 aurel32
            color_table[j][i] = col_expand(ds,
1439 a528b80c balrog
                   vga_get_color(ds, color_table_rgb[j][i]));
1440 a528b80c balrog
        }
1441 a528b80c balrog
    }
1442 a528b80c balrog
}
1443 a528b80c balrog
1444 2796dae0 aliguori
static int n_text_consoles;
1445 2796dae0 aliguori
static CharDriverState *text_consoles[128];
1446 2796dae0 aliguori
1447 4104833f Paolo Bonzini
static void text_console_set_echo(CharDriverState *chr, bool echo)
1448 4104833f Paolo Bonzini
{
1449 4104833f Paolo Bonzini
    TextConsole *s = chr->opaque;
1450 4104833f Paolo Bonzini
1451 4104833f Paolo Bonzini
    s->echo = echo;
1452 4104833f Paolo Bonzini
}
1453 4104833f Paolo Bonzini
1454 44b37b93 Paolo Bonzini
static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
1455 e7f0ad58 bellard
{
1456 e7f0ad58 bellard
    TextConsole *s;
1457 e7f0ad58 bellard
    static int color_inited;
1458 6d6f7c28 pbrook
1459 491e114a Paolo Bonzini
    s = chr->opaque;
1460 6ea314d9 Gerd Hoffmann
1461 e7f0ad58 bellard
    chr->chr_write = console_puts;
1462 6fcfafb7 bellard
1463 e15d7371 bellard
    s->out_fifo.buf = s->out_fifo_buf;
1464 e15d7371 bellard
    s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
1465 7bd427d8 Paolo Bonzini
    s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s);
1466 3023f332 aliguori
    s->ds = ds;
1467 3b46e624 ths
1468 e7f0ad58 bellard
    if (!color_inited) {
1469 e7f0ad58 bellard
        color_inited = 1;
1470 a528b80c balrog
        console_color_init(s->ds);
1471 e7f0ad58 bellard
    }
1472 e7f0ad58 bellard
    s->y_displayed = 0;
1473 e7f0ad58 bellard
    s->y_base = 0;
1474 e7f0ad58 bellard
    s->total_height = DEFAULT_BACKSCROLL;
1475 e7f0ad58 bellard
    s->x = 0;
1476 e7f0ad58 bellard
    s->y = 0;
1477 491e114a Paolo Bonzini
    if (s->console_type == TEXT_CONSOLE) {
1478 491e114a Paolo Bonzini
        s->g_width = ds_get_width(s->ds);
1479 491e114a Paolo Bonzini
        s->g_height = ds_get_height(s->ds);
1480 491e114a Paolo Bonzini
    }
1481 6d6f7c28 pbrook
1482 4d3b6f6e balrog
    s->hw_invalidate = text_console_invalidate;
1483 4d3b6f6e balrog
    s->hw_text_update = text_console_update;
1484 4d3b6f6e balrog
    s->hw = s;
1485 4d3b6f6e balrog
1486 6d6f7c28 pbrook
    /* Set text attribute defaults */
1487 6d6f7c28 pbrook
    s->t_attrib_default.bold = 0;
1488 6d6f7c28 pbrook
    s->t_attrib_default.uline = 0;
1489 6d6f7c28 pbrook
    s->t_attrib_default.blink = 0;
1490 6d6f7c28 pbrook
    s->t_attrib_default.invers = 0;
1491 6d6f7c28 pbrook
    s->t_attrib_default.unvisible = 0;
1492 6d6f7c28 pbrook
    s->t_attrib_default.fgcol = COLOR_WHITE;
1493 6d6f7c28 pbrook
    s->t_attrib_default.bgcol = COLOR_BLACK;
1494 6d6f7c28 pbrook
    /* set current text attributes to default */
1495 6d6f7c28 pbrook
    s->t_attrib = s->t_attrib_default;
1496 e7f0ad58 bellard
    text_console_resize(s);
1497 e7f0ad58 bellard
1498 51bfa4d3 Gerd Hoffmann
    if (chr->label) {
1499 51bfa4d3 Gerd Hoffmann
        char msg[128];
1500 51bfa4d3 Gerd Hoffmann
        int len;
1501 51bfa4d3 Gerd Hoffmann
1502 735ba588 Gerd Hoffmann
        s->t_attrib.bgcol = COLOR_BLUE;
1503 51bfa4d3 Gerd Hoffmann
        len = snprintf(msg, sizeof(msg), "%s console\r\n", chr->label);
1504 51bfa4d3 Gerd Hoffmann
        console_puts(chr, (uint8_t*)msg, len);
1505 735ba588 Gerd Hoffmann
        s->t_attrib = s->t_attrib_default;
1506 51bfa4d3 Gerd Hoffmann
    }
1507 51bfa4d3 Gerd Hoffmann
1508 127338e6 Amit Shah
    qemu_chr_generic_open(chr);
1509 ceecf1d1 aurel32
    if (chr->init)
1510 ceecf1d1 aurel32
        chr->init(chr);
1511 e7f0ad58 bellard
}
1512 c60e08d9 pbrook
1513 6e1db57b Kevin Wolf
int text_console_init(QemuOpts *opts, CharDriverState **_chr)
1514 2796dae0 aliguori
{
1515 2796dae0 aliguori
    CharDriverState *chr;
1516 491e114a Paolo Bonzini
    TextConsole *s;
1517 491e114a Paolo Bonzini
    unsigned width;
1518 491e114a Paolo Bonzini
    unsigned height;
1519 2796dae0 aliguori
1520 7267c094 Anthony Liguori
    chr = g_malloc0(sizeof(CharDriverState));
1521 2796dae0 aliguori
1522 2796dae0 aliguori
    if (n_text_consoles == 128) {
1523 2796dae0 aliguori
        fprintf(stderr, "Too many text consoles\n");
1524 2796dae0 aliguori
        exit(1);
1525 2796dae0 aliguori
    }
1526 2796dae0 aliguori
    text_consoles[n_text_consoles] = chr;
1527 2796dae0 aliguori
    n_text_consoles++;
1528 2796dae0 aliguori
1529 491e114a Paolo Bonzini
    width = qemu_opt_get_number(opts, "width", 0);
1530 491e114a Paolo Bonzini
    if (width == 0)
1531 491e114a Paolo Bonzini
        width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH;
1532 491e114a Paolo Bonzini
1533 491e114a Paolo Bonzini
    height = qemu_opt_get_number(opts, "height", 0);
1534 491e114a Paolo Bonzini
    if (height == 0)
1535 491e114a Paolo Bonzini
        height = qemu_opt_get_number(opts, "rows", 0) * FONT_HEIGHT;
1536 491e114a Paolo Bonzini
1537 491e114a Paolo Bonzini
    if (width == 0 || height == 0) {
1538 491e114a Paolo Bonzini
        s = new_console(NULL, TEXT_CONSOLE);
1539 491e114a Paolo Bonzini
    } else {
1540 491e114a Paolo Bonzini
        s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE);
1541 491e114a Paolo Bonzini
    }
1542 491e114a Paolo Bonzini
1543 491e114a Paolo Bonzini
    if (!s) {
1544 5354d083 Stefan Weil
        g_free(chr);
1545 6e1db57b Kevin Wolf
        return -EBUSY;
1546 491e114a Paolo Bonzini
    }
1547 491e114a Paolo Bonzini
1548 491e114a Paolo Bonzini
    s->chr = chr;
1549 491e114a Paolo Bonzini
    s->g_width = width;
1550 491e114a Paolo Bonzini
    s->g_height = height;
1551 491e114a Paolo Bonzini
    chr->opaque = s;
1552 4104833f Paolo Bonzini
    chr->chr_set_echo = text_console_set_echo;
1553 6e1db57b Kevin Wolf
1554 6e1db57b Kevin Wolf
    *_chr = chr;
1555 6e1db57b Kevin Wolf
    return 0;
1556 2796dae0 aliguori
}
1557 2796dae0 aliguori
1558 2796dae0 aliguori
void text_consoles_set_display(DisplayState *ds)
1559 2796dae0 aliguori
{
1560 2796dae0 aliguori
    int i;
1561 2796dae0 aliguori
1562 2796dae0 aliguori
    for (i = 0; i < n_text_consoles; i++) {
1563 44b37b93 Paolo Bonzini
        text_console_do_init(text_consoles[i], ds);
1564 2796dae0 aliguori
    }
1565 2796dae0 aliguori
1566 2796dae0 aliguori
    n_text_consoles = 0;
1567 2796dae0 aliguori
}
1568 2796dae0 aliguori
1569 3023f332 aliguori
void qemu_console_resize(DisplayState *ds, int width, int height)
1570 c60e08d9 pbrook
{
1571 42aa98e8 aliguori
    TextConsole *s = get_graphic_console(ds);
1572 f497f140 aliguori
    if (!s) return;
1573 f497f140 aliguori
1574 3023f332 aliguori
    s->g_width = width;
1575 3023f332 aliguori
    s->g_height = height;
1576 3023f332 aliguori
    if (is_graphic_console()) {
1577 7b5d76da aliguori
        ds->surface = qemu_resize_displaysurface(ds, width, height);
1578 3023f332 aliguori
        dpy_resize(ds);
1579 c60e08d9 pbrook
    }
1580 c60e08d9 pbrook
}
1581 38334f76 balrog
1582 3023f332 aliguori
void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
1583 3023f332 aliguori
                       int dst_x, int dst_y, int w, int h)
1584 c21bbcfa balrog
{
1585 3023f332 aliguori
    if (is_graphic_console()) {
1586 3023f332 aliguori
        dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
1587 38334f76 balrog
    }
1588 38334f76 balrog
}
1589 7d957bd8 aliguori
1590 0da2ea1b malc
PixelFormat qemu_different_endianness_pixelformat(int bpp)
1591 7d957bd8 aliguori
{
1592 7d957bd8 aliguori
    PixelFormat pf;
1593 7d957bd8 aliguori
1594 7d957bd8 aliguori
    memset(&pf, 0x00, sizeof(PixelFormat));
1595 7d957bd8 aliguori
1596 7d957bd8 aliguori
    pf.bits_per_pixel = bpp;
1597 7d957bd8 aliguori
    pf.bytes_per_pixel = bpp / 8;
1598 7d957bd8 aliguori
    pf.depth = bpp == 32 ? 24 : bpp;
1599 7d957bd8 aliguori
1600 7d957bd8 aliguori
    switch (bpp) {
1601 0da2ea1b malc
        case 24:
1602 0da2ea1b malc
            pf.rmask = 0x000000FF;
1603 0da2ea1b malc
            pf.gmask = 0x0000FF00;
1604 0da2ea1b malc
            pf.bmask = 0x00FF0000;
1605 0da2ea1b malc
            pf.rmax = 255;
1606 0da2ea1b malc
            pf.gmax = 255;
1607 0da2ea1b malc
            pf.bmax = 255;
1608 0da2ea1b malc
            pf.rshift = 0;
1609 0da2ea1b malc
            pf.gshift = 8;
1610 0da2ea1b malc
            pf.bshift = 16;
1611 90a1e3c0 aliguori
            pf.rbits = 8;
1612 90a1e3c0 aliguori
            pf.gbits = 8;
1613 90a1e3c0 aliguori
            pf.bbits = 8;
1614 7d957bd8 aliguori
            break;
1615 0da2ea1b malc
        case 32:
1616 0da2ea1b malc
            pf.rmask = 0x0000FF00;
1617 0da2ea1b malc
            pf.gmask = 0x00FF0000;
1618 0da2ea1b malc
            pf.bmask = 0xFF000000;
1619 0da2ea1b malc
            pf.amask = 0x00000000;
1620 0da2ea1b malc
            pf.amax = 255;
1621 0da2ea1b malc
            pf.rmax = 255;
1622 0da2ea1b malc
            pf.gmax = 255;
1623 0da2ea1b malc
            pf.bmax = 255;
1624 0da2ea1b malc
            pf.ashift = 0;
1625 0da2ea1b malc
            pf.rshift = 8;
1626 0da2ea1b malc
            pf.gshift = 16;
1627 0da2ea1b malc
            pf.bshift = 24;
1628 90a1e3c0 aliguori
            pf.rbits = 8;
1629 90a1e3c0 aliguori
            pf.gbits = 8;
1630 90a1e3c0 aliguori
            pf.bbits = 8;
1631 90a1e3c0 aliguori
            pf.abits = 8;
1632 0da2ea1b malc
            break;
1633 0da2ea1b malc
        default:
1634 0da2ea1b malc
            break;
1635 0da2ea1b malc
    }
1636 0da2ea1b malc
    return pf;
1637 0da2ea1b malc
}
1638 0da2ea1b malc
1639 0da2ea1b malc
PixelFormat qemu_default_pixelformat(int bpp)
1640 0da2ea1b malc
{
1641 0da2ea1b malc
    PixelFormat pf;
1642 0da2ea1b malc
1643 0da2ea1b malc
    memset(&pf, 0x00, sizeof(PixelFormat));
1644 0da2ea1b malc
1645 0da2ea1b malc
    pf.bits_per_pixel = bpp;
1646 0da2ea1b malc
    pf.bytes_per_pixel = bpp / 8;
1647 0da2ea1b malc
    pf.depth = bpp == 32 ? 24 : bpp;
1648 0da2ea1b malc
1649 0da2ea1b malc
    switch (bpp) {
1650 b6278084 Gerd Hoffmann
        case 15:
1651 b6278084 Gerd Hoffmann
            pf.bits_per_pixel = 16;
1652 b6278084 Gerd Hoffmann
            pf.bytes_per_pixel = 2;
1653 b6278084 Gerd Hoffmann
            pf.rmask = 0x00007c00;
1654 b6278084 Gerd Hoffmann
            pf.gmask = 0x000003E0;
1655 b6278084 Gerd Hoffmann
            pf.bmask = 0x0000001F;
1656 b6278084 Gerd Hoffmann
            pf.rmax = 31;
1657 b6278084 Gerd Hoffmann
            pf.gmax = 31;
1658 b6278084 Gerd Hoffmann
            pf.bmax = 31;
1659 b6278084 Gerd Hoffmann
            pf.rshift = 10;
1660 b6278084 Gerd Hoffmann
            pf.gshift = 5;
1661 b6278084 Gerd Hoffmann
            pf.bshift = 0;
1662 b6278084 Gerd Hoffmann
            pf.rbits = 5;
1663 b6278084 Gerd Hoffmann
            pf.gbits = 5;
1664 b6278084 Gerd Hoffmann
            pf.bbits = 5;
1665 b6278084 Gerd Hoffmann
            break;
1666 7d957bd8 aliguori
        case 16:
1667 7d957bd8 aliguori
            pf.rmask = 0x0000F800;
1668 7d957bd8 aliguori
            pf.gmask = 0x000007E0;
1669 7d957bd8 aliguori
            pf.bmask = 0x0000001F;
1670 7d957bd8 aliguori
            pf.rmax = 31;
1671 7d957bd8 aliguori
            pf.gmax = 63;
1672 7d957bd8 aliguori
            pf.bmax = 31;
1673 7d957bd8 aliguori
            pf.rshift = 11;
1674 7d957bd8 aliguori
            pf.gshift = 5;
1675 7d957bd8 aliguori
            pf.bshift = 0;
1676 90a1e3c0 aliguori
            pf.rbits = 5;
1677 90a1e3c0 aliguori
            pf.gbits = 6;
1678 90a1e3c0 aliguori
            pf.bbits = 5;
1679 7d957bd8 aliguori
            break;
1680 7d957bd8 aliguori
        case 24:
1681 0da2ea1b malc
            pf.rmask = 0x00FF0000;
1682 0da2ea1b malc
            pf.gmask = 0x0000FF00;
1683 0da2ea1b malc
            pf.bmask = 0x000000FF;
1684 0da2ea1b malc
            pf.rmax = 255;
1685 0da2ea1b malc
            pf.gmax = 255;
1686 0da2ea1b malc
            pf.bmax = 255;
1687 0da2ea1b malc
            pf.rshift = 16;
1688 0da2ea1b malc
            pf.gshift = 8;
1689 0da2ea1b malc
            pf.bshift = 0;
1690 90a1e3c0 aliguori
            pf.rbits = 8;
1691 90a1e3c0 aliguori
            pf.gbits = 8;
1692 90a1e3c0 aliguori
            pf.bbits = 8;
1693 0eba62e0 Markus Armbruster
            break;
1694 7d957bd8 aliguori
        case 32:
1695 7d957bd8 aliguori
            pf.rmask = 0x00FF0000;
1696 7d957bd8 aliguori
            pf.gmask = 0x0000FF00;
1697 7d957bd8 aliguori
            pf.bmask = 0x000000FF;
1698 0da2ea1b malc
            pf.amax = 255;
1699 7d957bd8 aliguori
            pf.rmax = 255;
1700 7d957bd8 aliguori
            pf.gmax = 255;
1701 7d957bd8 aliguori
            pf.bmax = 255;
1702 0da2ea1b malc
            pf.ashift = 24;
1703 7d957bd8 aliguori
            pf.rshift = 16;
1704 7d957bd8 aliguori
            pf.gshift = 8;
1705 7d957bd8 aliguori
            pf.bshift = 0;
1706 90a1e3c0 aliguori
            pf.rbits = 8;
1707 90a1e3c0 aliguori
            pf.gbits = 8;
1708 90a1e3c0 aliguori
            pf.bbits = 8;
1709 90a1e3c0 aliguori
            pf.abits = 8;
1710 7d957bd8 aliguori
            break;
1711 7d957bd8 aliguori
        default:
1712 7d957bd8 aliguori
            break;
1713 7d957bd8 aliguori
    }
1714 7d957bd8 aliguori
    return pf;
1715 7d957bd8 aliguori
}