Statistics
| Branch: | Revision:

root / console.c @ dc1c13d9

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