Statistics
| Branch: | Revision:

root / console.c @ 29eee86f

History | View | Annotate | Download (47.6 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 c10600af Laszlo Ersek
                int *param = &s->esc_params[s->nb_esc_params];
942 c10600af Laszlo Ersek
                int digit = (ch - '0');
943 c10600af Laszlo Ersek
944 c10600af Laszlo Ersek
                *param = (*param <= (INT_MAX - digit) / 10) ?
945 c10600af Laszlo Ersek
                         *param * 10 + digit : INT_MAX;
946 e7f0ad58 bellard
            }
947 e7f0ad58 bellard
        } else {
948 3eea5498 Ian Campbell
            if (s->nb_esc_params < MAX_ESC_PARAMS)
949 3eea5498 Ian Campbell
                s->nb_esc_params++;
950 e7f0ad58 bellard
            if (ch == ';')
951 e7f0ad58 bellard
                break;
952 adb47967 ths
#ifdef DEBUG_CONSOLE
953 adb47967 ths
            fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
954 adb47967 ths
                    s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
955 adb47967 ths
#endif
956 e7f0ad58 bellard
            s->state = TTY_STATE_NORM;
957 e7f0ad58 bellard
            switch(ch) {
958 adb47967 ths
            case 'A':
959 adb47967 ths
                /* move cursor up */
960 adb47967 ths
                if (s->esc_params[0] == 0) {
961 adb47967 ths
                    s->esc_params[0] = 1;
962 adb47967 ths
                }
963 3eea5498 Ian Campbell
                set_cursor(s, s->x, s->y - s->esc_params[0]);
964 adb47967 ths
                break;
965 adb47967 ths
            case 'B':
966 adb47967 ths
                /* move cursor down */
967 adb47967 ths
                if (s->esc_params[0] == 0) {
968 adb47967 ths
                    s->esc_params[0] = 1;
969 adb47967 ths
                }
970 3eea5498 Ian Campbell
                set_cursor(s, s->x, s->y + s->esc_params[0]);
971 e7f0ad58 bellard
                break;
972 e7f0ad58 bellard
            case 'C':
973 adb47967 ths
                /* move cursor right */
974 adb47967 ths
                if (s->esc_params[0] == 0) {
975 adb47967 ths
                    s->esc_params[0] = 1;
976 adb47967 ths
                }
977 3eea5498 Ian Campbell
                set_cursor(s, s->x + s->esc_params[0], s->y);
978 e7f0ad58 bellard
                break;
979 adb47967 ths
            case 'D':
980 adb47967 ths
                /* move cursor left */
981 adb47967 ths
                if (s->esc_params[0] == 0) {
982 adb47967 ths
                    s->esc_params[0] = 1;
983 adb47967 ths
                }
984 3eea5498 Ian Campbell
                set_cursor(s, s->x - s->esc_params[0], s->y);
985 adb47967 ths
                break;
986 adb47967 ths
            case 'G':
987 adb47967 ths
                /* move cursor to column */
988 3eea5498 Ian Campbell
                set_cursor(s, s->esc_params[0] - 1, s->y);
989 adb47967 ths
                break;
990 adb47967 ths
            case 'f':
991 adb47967 ths
            case 'H':
992 adb47967 ths
                /* move cursor to row, column */
993 3eea5498 Ian Campbell
                set_cursor(s, s->esc_params[1] - 1, s->esc_params[0] - 1);
994 adb47967 ths
                break;
995 adb47967 ths
            case 'J':
996 adb47967 ths
                switch (s->esc_params[0]) {
997 adb47967 ths
                case 0:
998 adb47967 ths
                    /* clear to end of screen */
999 adb47967 ths
                    for (y = s->y; y < s->height; y++) {
1000 adb47967 ths
                        for (x = 0; x < s->width; x++) {
1001 adb47967 ths
                            if (y == s->y && x < s->x) {
1002 adb47967 ths
                                continue;
1003 adb47967 ths
                            }
1004 adb47967 ths
                            console_clear_xy(s, x, y);
1005 adb47967 ths
                        }
1006 adb47967 ths
                    }
1007 adb47967 ths
                    break;
1008 adb47967 ths
                case 1:
1009 adb47967 ths
                    /* clear from beginning of screen */
1010 adb47967 ths
                    for (y = 0; y <= s->y; y++) {
1011 adb47967 ths
                        for (x = 0; x < s->width; x++) {
1012 adb47967 ths
                            if (y == s->y && x > s->x) {
1013 adb47967 ths
                                break;
1014 adb47967 ths
                            }
1015 adb47967 ths
                            console_clear_xy(s, x, y);
1016 adb47967 ths
                        }
1017 adb47967 ths
                    }
1018 adb47967 ths
                    break;
1019 adb47967 ths
                case 2:
1020 adb47967 ths
                    /* clear entire screen */
1021 adb47967 ths
                    for (y = 0; y <= s->height; y++) {
1022 adb47967 ths
                        for (x = 0; x < s->width; x++) {
1023 adb47967 ths
                            console_clear_xy(s, x, y);
1024 adb47967 ths
                        }
1025 adb47967 ths
                    }
1026 f94a950f Markus Armbruster
                    break;
1027 adb47967 ths
                }
1028 95d8f9f4 Markus Armbruster
                break;
1029 e7f0ad58 bellard
            case 'K':
1030 adb47967 ths
                switch (s->esc_params[0]) {
1031 adb47967 ths
                case 0:
1032 f94a950f Markus Armbruster
                    /* clear to eol */
1033 f94a950f Markus Armbruster
                    for(x = s->x; x < s->width; x++) {
1034 adb47967 ths
                        console_clear_xy(s, x, s->y);
1035 f94a950f Markus Armbruster
                    }
1036 f94a950f Markus Armbruster
                    break;
1037 adb47967 ths
                case 1:
1038 adb47967 ths
                    /* clear from beginning of line */
1039 adb47967 ths
                    for (x = 0; x <= s->x; x++) {
1040 adb47967 ths
                        console_clear_xy(s, x, s->y);
1041 adb47967 ths
                    }
1042 adb47967 ths
                    break;
1043 adb47967 ths
                case 2:
1044 adb47967 ths
                    /* clear entire line */
1045 adb47967 ths
                    for(x = 0; x < s->width; x++) {
1046 adb47967 ths
                        console_clear_xy(s, x, s->y);
1047 adb47967 ths
                    }
1048 f94a950f Markus Armbruster
                    break;
1049 f94a950f Markus Armbruster
                }
1050 adb47967 ths
                break;
1051 adb47967 ths
            case 'm':
1052 f94a950f Markus Armbruster
                console_handle_escape(s);
1053 f94a950f Markus Armbruster
                break;
1054 adb47967 ths
            case 'n':
1055 adb47967 ths
                /* report cursor position */
1056 adb47967 ths
                /* TODO: send ESC[row;colR */
1057 adb47967 ths
                break;
1058 adb47967 ths
            case 's':
1059 adb47967 ths
                /* save cursor position */
1060 adb47967 ths
                s->x_saved = s->x;
1061 adb47967 ths
                s->y_saved = s->y;
1062 adb47967 ths
                break;
1063 adb47967 ths
            case 'u':
1064 adb47967 ths
                /* restore cursor position */
1065 adb47967 ths
                s->x = s->x_saved;
1066 adb47967 ths
                s->y = s->y_saved;
1067 adb47967 ths
                break;
1068 adb47967 ths
            default:
1069 adb47967 ths
#ifdef DEBUG_CONSOLE
1070 adb47967 ths
                fprintf(stderr, "unhandled escape character '%c'\n", ch);
1071 adb47967 ths
#endif
1072 adb47967 ths
                break;
1073 adb47967 ths
            }
1074 adb47967 ths
            break;
1075 e7f0ad58 bellard
        }
1076 e7f0ad58 bellard
    }
1077 e7f0ad58 bellard
}
1078 e7f0ad58 bellard
1079 e7f0ad58 bellard
void console_select(unsigned int index)
1080 e7f0ad58 bellard
{
1081 e7f0ad58 bellard
    TextConsole *s;
1082 6d6f7c28 pbrook
1083 e7f0ad58 bellard
    if (index >= MAX_CONSOLES)
1084 e7f0ad58 bellard
        return;
1085 358664cc Stefan Hajnoczi
    if (active_console) {
1086 358664cc Stefan Hajnoczi
        active_console->g_width = ds_get_width(active_console->ds);
1087 358664cc Stefan Hajnoczi
        active_console->g_height = ds_get_height(active_console->ds);
1088 358664cc Stefan Hajnoczi
    }
1089 e7f0ad58 bellard
    s = consoles[index];
1090 e7f0ad58 bellard
    if (s) {
1091 7d957bd8 aliguori
        DisplayState *ds = s->ds;
1092 bf1bed81 Jan Kiszka
1093 8bd6b06d Stefan Weil
        if (active_console && active_console->cursor_timer) {
1094 bf1bed81 Jan Kiszka
            qemu_del_timer(active_console->cursor_timer);
1095 bf1bed81 Jan Kiszka
        }
1096 e7f0ad58 bellard
        active_console = s;
1097 68f00996 aliguori
        if (ds_get_bits_per_pixel(s->ds)) {
1098 7b5d76da aliguori
            ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
1099 68f00996 aliguori
        } else {
1100 68f00996 aliguori
            s->ds->surface->width = s->width;
1101 68f00996 aliguori
            s->ds->surface->height = s->height;
1102 68f00996 aliguori
        }
1103 bf1bed81 Jan Kiszka
        if (s->cursor_timer) {
1104 bf1bed81 Jan Kiszka
            qemu_mod_timer(s->cursor_timer,
1105 bf1bed81 Jan Kiszka
                   qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
1106 bf1bed81 Jan Kiszka
        }
1107 7d957bd8 aliguori
        dpy_resize(s->ds);
1108 4d3b6f6e balrog
        vga_hw_invalidate();
1109 e7f0ad58 bellard
    }
1110 e7f0ad58 bellard
}
1111 e7f0ad58 bellard
1112 e7f0ad58 bellard
static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
1113 e7f0ad58 bellard
{
1114 e7f0ad58 bellard
    TextConsole *s = chr->opaque;
1115 e7f0ad58 bellard
    int i;
1116 e7f0ad58 bellard
1117 14778c20 pbrook
    s->update_x0 = s->width * FONT_WIDTH;
1118 14778c20 pbrook
    s->update_y0 = s->height * FONT_HEIGHT;
1119 14778c20 pbrook
    s->update_x1 = 0;
1120 14778c20 pbrook
    s->update_y1 = 0;
1121 e7f0ad58 bellard
    console_show_cursor(s, 0);
1122 e7f0ad58 bellard
    for(i = 0; i < len; i++) {
1123 e7f0ad58 bellard
        console_putchar(s, buf[i]);
1124 e7f0ad58 bellard
    }
1125 e7f0ad58 bellard
    console_show_cursor(s, 1);
1126 14778c20 pbrook
    if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) {
1127 14778c20 pbrook
        dpy_update(s->ds, s->update_x0, s->update_y0,
1128 14778c20 pbrook
                   s->update_x1 - s->update_x0,
1129 14778c20 pbrook
                   s->update_y1 - s->update_y0);
1130 14778c20 pbrook
    }
1131 e7f0ad58 bellard
    return len;
1132 e7f0ad58 bellard
}
1133 e7f0ad58 bellard
1134 e15d7371 bellard
static void kbd_send_chars(void *opaque)
1135 e15d7371 bellard
{
1136 e15d7371 bellard
    TextConsole *s = opaque;
1137 e15d7371 bellard
    int len;
1138 e15d7371 bellard
    uint8_t buf[16];
1139 3b46e624 ths
1140 909cda12 Anthony Liguori
    len = qemu_chr_be_can_write(s->chr);
1141 e15d7371 bellard
    if (len > s->out_fifo.count)
1142 e15d7371 bellard
        len = s->out_fifo.count;
1143 e15d7371 bellard
    if (len > 0) {
1144 e15d7371 bellard
        if (len > sizeof(buf))
1145 e15d7371 bellard
            len = sizeof(buf);
1146 e15d7371 bellard
        qemu_fifo_read(&s->out_fifo, buf, len);
1147 fa5efccb Anthony Liguori
        qemu_chr_be_write(s->chr, buf, len);
1148 e15d7371 bellard
    }
1149 e15d7371 bellard
    /* characters are pending: we send them a bit later (XXX:
1150 e15d7371 bellard
       horrible, should change char device API) */
1151 e15d7371 bellard
    if (s->out_fifo.count > 0) {
1152 7bd427d8 Paolo Bonzini
        qemu_mod_timer(s->kbd_timer, qemu_get_clock_ms(rt_clock) + 1);
1153 e15d7371 bellard
    }
1154 e15d7371 bellard
}
1155 e15d7371 bellard
1156 e7f0ad58 bellard
/* called when an ascii key is pressed */
1157 e7f0ad58 bellard
void kbd_put_keysym(int keysym)
1158 e7f0ad58 bellard
{
1159 e7f0ad58 bellard
    TextConsole *s;
1160 e7f0ad58 bellard
    uint8_t buf[16], *q;
1161 e7f0ad58 bellard
    int c;
1162 e7f0ad58 bellard
1163 e7f0ad58 bellard
    s = active_console;
1164 af3a9031 ths
    if (!s || (s->console_type == GRAPHIC_CONSOLE))
1165 e7f0ad58 bellard
        return;
1166 e7f0ad58 bellard
1167 e7f0ad58 bellard
    switch(keysym) {
1168 e7f0ad58 bellard
    case QEMU_KEY_CTRL_UP:
1169 e7f0ad58 bellard
        console_scroll(-1);
1170 e7f0ad58 bellard
        break;
1171 e7f0ad58 bellard
    case QEMU_KEY_CTRL_DOWN:
1172 e7f0ad58 bellard
        console_scroll(1);
1173 e7f0ad58 bellard
        break;
1174 e7f0ad58 bellard
    case QEMU_KEY_CTRL_PAGEUP:
1175 e7f0ad58 bellard
        console_scroll(-10);
1176 e7f0ad58 bellard
        break;
1177 e7f0ad58 bellard
    case QEMU_KEY_CTRL_PAGEDOWN:
1178 e7f0ad58 bellard
        console_scroll(10);
1179 e7f0ad58 bellard
        break;
1180 e7f0ad58 bellard
    default:
1181 e15d7371 bellard
        /* convert the QEMU keysym to VT100 key string */
1182 e15d7371 bellard
        q = buf;
1183 e15d7371 bellard
        if (keysym >= 0xe100 && keysym <= 0xe11f) {
1184 e15d7371 bellard
            *q++ = '\033';
1185 e15d7371 bellard
            *q++ = '[';
1186 e15d7371 bellard
            c = keysym - 0xe100;
1187 e15d7371 bellard
            if (c >= 10)
1188 e15d7371 bellard
                *q++ = '0' + (c / 10);
1189 e15d7371 bellard
            *q++ = '0' + (c % 10);
1190 e15d7371 bellard
            *q++ = '~';
1191 e15d7371 bellard
        } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
1192 e15d7371 bellard
            *q++ = '\033';
1193 e15d7371 bellard
            *q++ = '[';
1194 e15d7371 bellard
            *q++ = keysym & 0xff;
1195 4104833f Paolo Bonzini
        } else if (s->echo && (keysym == '\r' || keysym == '\n')) {
1196 4104833f Paolo Bonzini
            console_puts(s->chr, (const uint8_t *) "\r", 1);
1197 4104833f Paolo Bonzini
            *q++ = '\n';
1198 e15d7371 bellard
        } else {
1199 4104833f Paolo Bonzini
            *q++ = keysym;
1200 4104833f Paolo Bonzini
        }
1201 4104833f Paolo Bonzini
        if (s->echo) {
1202 4104833f Paolo Bonzini
            console_puts(s->chr, buf, q - buf);
1203 e15d7371 bellard
        }
1204 e5b0bc44 pbrook
        if (s->chr->chr_read) {
1205 e15d7371 bellard
            qemu_fifo_write(&s->out_fifo, buf, q - buf);
1206 e15d7371 bellard
            kbd_send_chars(s);
1207 e7f0ad58 bellard
        }
1208 e7f0ad58 bellard
        break;
1209 e7f0ad58 bellard
    }
1210 e7f0ad58 bellard
}
1211 e7f0ad58 bellard
1212 4d3b6f6e balrog
static void text_console_invalidate(void *opaque)
1213 4d3b6f6e balrog
{
1214 4d3b6f6e balrog
    TextConsole *s = (TextConsole *) opaque;
1215 68f00996 aliguori
    if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) {
1216 68f00996 aliguori
        s->g_width = ds_get_width(s->ds);
1217 68f00996 aliguori
        s->g_height = ds_get_height(s->ds);
1218 68f00996 aliguori
        text_console_resize(s);
1219 68f00996 aliguori
    }
1220 4d3b6f6e balrog
    console_refresh(s);
1221 4d3b6f6e balrog
}
1222 4d3b6f6e balrog
1223 c227f099 Anthony Liguori
static void text_console_update(void *opaque, console_ch_t *chardata)
1224 4d3b6f6e balrog
{
1225 4d3b6f6e balrog
    TextConsole *s = (TextConsole *) opaque;
1226 4d3b6f6e balrog
    int i, j, src;
1227 4d3b6f6e balrog
1228 4d3b6f6e balrog
    if (s->text_x[0] <= s->text_x[1]) {
1229 4d3b6f6e balrog
        src = (s->y_base + s->text_y[0]) * s->width;
1230 4d3b6f6e balrog
        chardata += s->text_y[0] * s->width;
1231 4d3b6f6e balrog
        for (i = s->text_y[0]; i <= s->text_y[1]; i ++)
1232 4d3b6f6e balrog
            for (j = 0; j < s->width; j ++, src ++)
1233 4d3b6f6e balrog
                console_write_ch(chardata ++, s->cells[src].ch |
1234 4d3b6f6e balrog
                                (s->cells[src].t_attrib.fgcol << 12) |
1235 4d3b6f6e balrog
                                (s->cells[src].t_attrib.bgcol << 8) |
1236 4d3b6f6e balrog
                                (s->cells[src].t_attrib.bold << 21));
1237 4d3b6f6e balrog
        dpy_update(s->ds, s->text_x[0], s->text_y[0],
1238 4d3b6f6e balrog
                   s->text_x[1] - s->text_x[0], i - s->text_y[0]);
1239 4d3b6f6e balrog
        s->text_x[0] = s->width;
1240 4d3b6f6e balrog
        s->text_y[0] = s->height;
1241 4d3b6f6e balrog
        s->text_x[1] = 0;
1242 4d3b6f6e balrog
        s->text_y[1] = 0;
1243 4d3b6f6e balrog
    }
1244 4d3b6f6e balrog
    if (s->cursor_invalidate) {
1245 4d3b6f6e balrog
        dpy_cursor(s->ds, s->x, s->y);
1246 4d3b6f6e balrog
        s->cursor_invalidate = 0;
1247 4d3b6f6e balrog
    }
1248 4d3b6f6e balrog
}
1249 4d3b6f6e balrog
1250 42aa98e8 aliguori
static TextConsole *get_graphic_console(DisplayState *ds)
1251 a147d62b blueswir1
{
1252 3023f332 aliguori
    int i;
1253 3023f332 aliguori
    TextConsole *s;
1254 3023f332 aliguori
    for (i = 0; i < nb_consoles; i++) {
1255 3023f332 aliguori
        s = consoles[i];
1256 42aa98e8 aliguori
        if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds)
1257 3023f332 aliguori
            return s;
1258 3023f332 aliguori
    }
1259 3023f332 aliguori
    return NULL;
1260 3023f332 aliguori
}
1261 3023f332 aliguori
1262 c227f099 Anthony Liguori
static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
1263 e7f0ad58 bellard
{
1264 e7f0ad58 bellard
    TextConsole *s;
1265 95219897 pbrook
    int i;
1266 e7f0ad58 bellard
1267 e7f0ad58 bellard
    if (nb_consoles >= MAX_CONSOLES)
1268 e7f0ad58 bellard
        return NULL;
1269 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(TextConsole));
1270 af3a9031 ths
    if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
1271 af3a9031 ths
        (console_type == GRAPHIC_CONSOLE))) {
1272 e7f0ad58 bellard
        active_console = s;
1273 af3a9031 ths
    }
1274 e7f0ad58 bellard
    s->ds = ds;
1275 af3a9031 ths
    s->console_type = console_type;
1276 af3a9031 ths
    if (console_type != GRAPHIC_CONSOLE) {
1277 f81bdefb Jan Kiszka
        s->index = nb_consoles;
1278 95219897 pbrook
        consoles[nb_consoles++] = s;
1279 95219897 pbrook
    } else {
1280 95219897 pbrook
        /* HACK: Put graphical consoles before text consoles.  */
1281 95219897 pbrook
        for (i = nb_consoles; i > 0; i--) {
1282 af3a9031 ths
            if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
1283 95219897 pbrook
                break;
1284 95219897 pbrook
            consoles[i] = consoles[i - 1];
1285 f81bdefb Jan Kiszka
            consoles[i]->index = i;
1286 95219897 pbrook
        }
1287 f81bdefb Jan Kiszka
        s->index = i;
1288 95219897 pbrook
        consoles[i] = s;
1289 3023f332 aliguori
        nb_consoles++;
1290 95219897 pbrook
    }
1291 95219897 pbrook
    return s;
1292 95219897 pbrook
}
1293 95219897 pbrook
1294 98b50080 Paolo Bonzini
static DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
1295 98b50080 Paolo Bonzini
{
1296 7267c094 Anthony Liguori
    DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
1297 98b50080 Paolo Bonzini
1298 ffe8b821 Jes Sorensen
    int linesize = width * 4;
1299 ffe8b821 Jes Sorensen
    qemu_alloc_display(surface, width, height, linesize,
1300 ffe8b821 Jes Sorensen
                       qemu_default_pixelformat(32), 0);
1301 98b50080 Paolo Bonzini
    return surface;
1302 98b50080 Paolo Bonzini
}
1303 98b50080 Paolo Bonzini
1304 98b50080 Paolo Bonzini
static DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
1305 98b50080 Paolo Bonzini
                                          int width, int height)
1306 98b50080 Paolo Bonzini
{
1307 ffe8b821 Jes Sorensen
    int linesize = width * 4;
1308 ffe8b821 Jes Sorensen
    qemu_alloc_display(surface, width, height, linesize,
1309 ffe8b821 Jes Sorensen
                       qemu_default_pixelformat(32), 0);
1310 ffe8b821 Jes Sorensen
    return surface;
1311 ffe8b821 Jes Sorensen
}
1312 ffe8b821 Jes Sorensen
1313 ffe8b821 Jes Sorensen
void qemu_alloc_display(DisplaySurface *surface, int width, int height,
1314 ffe8b821 Jes Sorensen
                        int linesize, PixelFormat pf, int newflags)
1315 ffe8b821 Jes Sorensen
{
1316 ffe8b821 Jes Sorensen
    void *data;
1317 98b50080 Paolo Bonzini
    surface->width = width;
1318 98b50080 Paolo Bonzini
    surface->height = height;
1319 ffe8b821 Jes Sorensen
    surface->linesize = linesize;
1320 ffe8b821 Jes Sorensen
    surface->pf = pf;
1321 ffe8b821 Jes Sorensen
    if (surface->flags & QEMU_ALLOCATED_FLAG) {
1322 7267c094 Anthony Liguori
        data = g_realloc(surface->data,
1323 ffe8b821 Jes Sorensen
                            surface->linesize * surface->height);
1324 ffe8b821 Jes Sorensen
    } else {
1325 7267c094 Anthony Liguori
        data = g_malloc(surface->linesize * surface->height);
1326 ffe8b821 Jes Sorensen
    }
1327 ffe8b821 Jes Sorensen
    surface->data = (uint8_t *)data;
1328 ffe8b821 Jes Sorensen
    surface->flags = newflags | QEMU_ALLOCATED_FLAG;
1329 98b50080 Paolo Bonzini
#ifdef HOST_WORDS_BIGENDIAN
1330 ffe8b821 Jes Sorensen
    surface->flags |= QEMU_BIG_ENDIAN_FLAG;
1331 98b50080 Paolo Bonzini
#endif
1332 98b50080 Paolo Bonzini
}
1333 98b50080 Paolo Bonzini
1334 98b50080 Paolo Bonzini
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
1335 98b50080 Paolo Bonzini
                                              int linesize, uint8_t *data)
1336 98b50080 Paolo Bonzini
{
1337 7267c094 Anthony Liguori
    DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
1338 98b50080 Paolo Bonzini
1339 98b50080 Paolo Bonzini
    surface->width = width;
1340 98b50080 Paolo Bonzini
    surface->height = height;
1341 98b50080 Paolo Bonzini
    surface->linesize = linesize;
1342 98b50080 Paolo Bonzini
    surface->pf = qemu_default_pixelformat(bpp);
1343 98b50080 Paolo Bonzini
#ifdef HOST_WORDS_BIGENDIAN
1344 98b50080 Paolo Bonzini
    surface->flags = QEMU_BIG_ENDIAN_FLAG;
1345 98b50080 Paolo Bonzini
#endif
1346 98b50080 Paolo Bonzini
    surface->data = data;
1347 98b50080 Paolo Bonzini
1348 98b50080 Paolo Bonzini
    return surface;
1349 98b50080 Paolo Bonzini
}
1350 98b50080 Paolo Bonzini
1351 98b50080 Paolo Bonzini
static void defaultallocator_free_displaysurface(DisplaySurface *surface)
1352 98b50080 Paolo Bonzini
{
1353 98b50080 Paolo Bonzini
    if (surface == NULL)
1354 98b50080 Paolo Bonzini
        return;
1355 98b50080 Paolo Bonzini
    if (surface->flags & QEMU_ALLOCATED_FLAG)
1356 7267c094 Anthony Liguori
        g_free(surface->data);
1357 7267c094 Anthony Liguori
    g_free(surface);
1358 98b50080 Paolo Bonzini
}
1359 98b50080 Paolo Bonzini
1360 98b50080 Paolo Bonzini
static struct DisplayAllocator default_allocator = {
1361 98b50080 Paolo Bonzini
    defaultallocator_create_displaysurface,
1362 98b50080 Paolo Bonzini
    defaultallocator_resize_displaysurface,
1363 98b50080 Paolo Bonzini
    defaultallocator_free_displaysurface
1364 98b50080 Paolo Bonzini
};
1365 98b50080 Paolo Bonzini
1366 98b50080 Paolo Bonzini
static void dumb_display_init(void)
1367 98b50080 Paolo Bonzini
{
1368 7267c094 Anthony Liguori
    DisplayState *ds = g_malloc0(sizeof(DisplayState));
1369 1802651c Jan Kiszka
    int width = 640;
1370 1802651c Jan Kiszka
    int height = 480;
1371 1802651c Jan Kiszka
1372 98b50080 Paolo Bonzini
    ds->allocator = &default_allocator;
1373 1802651c Jan Kiszka
    if (is_fixedsize_console()) {
1374 1802651c Jan Kiszka
        width = active_console->g_width;
1375 1802651c Jan Kiszka
        height = active_console->g_height;
1376 1802651c Jan Kiszka
    }
1377 1802651c Jan Kiszka
    ds->surface = qemu_create_displaysurface(ds, width, height);
1378 98b50080 Paolo Bonzini
    register_displaystate(ds);
1379 98b50080 Paolo Bonzini
}
1380 98b50080 Paolo Bonzini
1381 98b50080 Paolo Bonzini
/***********************************************************/
1382 98b50080 Paolo Bonzini
/* register display */
1383 98b50080 Paolo Bonzini
1384 98b50080 Paolo Bonzini
void register_displaystate(DisplayState *ds)
1385 98b50080 Paolo Bonzini
{
1386 98b50080 Paolo Bonzini
    DisplayState **s;
1387 98b50080 Paolo Bonzini
    s = &display_state;
1388 98b50080 Paolo Bonzini
    while (*s != NULL)
1389 98b50080 Paolo Bonzini
        s = &(*s)->next;
1390 98b50080 Paolo Bonzini
    ds->next = NULL;
1391 98b50080 Paolo Bonzini
    *s = ds;
1392 98b50080 Paolo Bonzini
}
1393 98b50080 Paolo Bonzini
1394 98b50080 Paolo Bonzini
DisplayState *get_displaystate(void)
1395 98b50080 Paolo Bonzini
{
1396 98b50080 Paolo Bonzini
    if (!display_state) {
1397 98b50080 Paolo Bonzini
        dumb_display_init ();
1398 98b50080 Paolo Bonzini
    }
1399 98b50080 Paolo Bonzini
    return display_state;
1400 98b50080 Paolo Bonzini
}
1401 98b50080 Paolo Bonzini
1402 98b50080 Paolo Bonzini
DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
1403 98b50080 Paolo Bonzini
{
1404 98b50080 Paolo Bonzini
    if(ds->allocator ==  &default_allocator) {
1405 98b50080 Paolo Bonzini
        DisplaySurface *surf;
1406 98b50080 Paolo Bonzini
        surf = da->create_displaysurface(ds_get_width(ds), ds_get_height(ds));
1407 98b50080 Paolo Bonzini
        defaultallocator_free_displaysurface(ds->surface);
1408 98b50080 Paolo Bonzini
        ds->surface = surf;
1409 98b50080 Paolo Bonzini
        ds->allocator = da;
1410 98b50080 Paolo Bonzini
    }
1411 98b50080 Paolo Bonzini
    return ds->allocator;
1412 98b50080 Paolo Bonzini
}
1413 98b50080 Paolo Bonzini
1414 3023f332 aliguori
DisplayState *graphic_console_init(vga_hw_update_ptr update,
1415 3023f332 aliguori
                                   vga_hw_invalidate_ptr invalidate,
1416 3023f332 aliguori
                                   vga_hw_screen_dump_ptr screen_dump,
1417 3023f332 aliguori
                                   vga_hw_text_update_ptr text_update,
1418 3023f332 aliguori
                                   void *opaque)
1419 95219897 pbrook
{
1420 95219897 pbrook
    TextConsole *s;
1421 3023f332 aliguori
    DisplayState *ds;
1422 f0f2f976 aurel32
1423 7267c094 Anthony Liguori
    ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
1424 7b5d76da aliguori
    ds->allocator = &default_allocator; 
1425 7b5d76da aliguori
    ds->surface = qemu_create_displaysurface(ds, 640, 480);
1426 95219897 pbrook
1427 af3a9031 ths
    s = new_console(ds, GRAPHIC_CONSOLE);
1428 3023f332 aliguori
    if (s == NULL) {
1429 7b5d76da aliguori
        qemu_free_displaysurface(ds);
1430 7267c094 Anthony Liguori
        g_free(ds);
1431 3023f332 aliguori
        return NULL;
1432 3023f332 aliguori
    }
1433 95219897 pbrook
    s->hw_update = update;
1434 95219897 pbrook
    s->hw_invalidate = invalidate;
1435 95219897 pbrook
    s->hw_screen_dump = screen_dump;
1436 4d3b6f6e balrog
    s->hw_text_update = text_update;
1437 95219897 pbrook
    s->hw = opaque;
1438 3023f332 aliguori
1439 f0f2f976 aurel32
    register_displaystate(ds);
1440 3023f332 aliguori
    return ds;
1441 e7f0ad58 bellard
}
1442 e7f0ad58 bellard
1443 95219897 pbrook
int is_graphic_console(void)
1444 e7f0ad58 bellard
{
1445 4d3b6f6e balrog
    return active_console && active_console->console_type == GRAPHIC_CONSOLE;
1446 e7f0ad58 bellard
}
1447 e7f0ad58 bellard
1448 c21bbcfa balrog
int is_fixedsize_console(void)
1449 c21bbcfa balrog
{
1450 c21bbcfa balrog
    return active_console && active_console->console_type != TEXT_CONSOLE;
1451 c21bbcfa balrog
}
1452 c21bbcfa balrog
1453 a528b80c balrog
void console_color_init(DisplayState *ds)
1454 a528b80c balrog
{
1455 a528b80c balrog
    int i, j;
1456 a528b80c balrog
    for (j = 0; j < 2; j++) {
1457 a528b80c balrog
        for (i = 0; i < 8; i++) {
1458 f0f2f976 aurel32
            color_table[j][i] = col_expand(ds,
1459 a528b80c balrog
                   vga_get_color(ds, color_table_rgb[j][i]));
1460 a528b80c balrog
        }
1461 a528b80c balrog
    }
1462 a528b80c balrog
}
1463 a528b80c balrog
1464 4104833f Paolo Bonzini
static void text_console_set_echo(CharDriverState *chr, bool echo)
1465 4104833f Paolo Bonzini
{
1466 4104833f Paolo Bonzini
    TextConsole *s = chr->opaque;
1467 4104833f Paolo Bonzini
1468 4104833f Paolo Bonzini
    s->echo = echo;
1469 4104833f Paolo Bonzini
}
1470 4104833f Paolo Bonzini
1471 bf1bed81 Jan Kiszka
static void text_console_update_cursor(void *opaque)
1472 bf1bed81 Jan Kiszka
{
1473 bf1bed81 Jan Kiszka
    TextConsole *s = opaque;
1474 bf1bed81 Jan Kiszka
1475 bf1bed81 Jan Kiszka
    s->cursor_visible_phase = !s->cursor_visible_phase;
1476 bf1bed81 Jan Kiszka
    vga_hw_invalidate();
1477 bf1bed81 Jan Kiszka
    qemu_mod_timer(s->cursor_timer,
1478 bf1bed81 Jan Kiszka
                   qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
1479 bf1bed81 Jan Kiszka
}
1480 bf1bed81 Jan Kiszka
1481 44b37b93 Paolo Bonzini
static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
1482 e7f0ad58 bellard
{
1483 e7f0ad58 bellard
    TextConsole *s;
1484 e7f0ad58 bellard
    static int color_inited;
1485 6d6f7c28 pbrook
1486 491e114a Paolo Bonzini
    s = chr->opaque;
1487 6ea314d9 Gerd Hoffmann
1488 e7f0ad58 bellard
    chr->chr_write = console_puts;
1489 6fcfafb7 bellard
1490 e15d7371 bellard
    s->out_fifo.buf = s->out_fifo_buf;
1491 e15d7371 bellard
    s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
1492 7bd427d8 Paolo Bonzini
    s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s);
1493 3023f332 aliguori
    s->ds = ds;
1494 3b46e624 ths
1495 e7f0ad58 bellard
    if (!color_inited) {
1496 e7f0ad58 bellard
        color_inited = 1;
1497 a528b80c balrog
        console_color_init(s->ds);
1498 e7f0ad58 bellard
    }
1499 e7f0ad58 bellard
    s->y_displayed = 0;
1500 e7f0ad58 bellard
    s->y_base = 0;
1501 e7f0ad58 bellard
    s->total_height = DEFAULT_BACKSCROLL;
1502 e7f0ad58 bellard
    s->x = 0;
1503 e7f0ad58 bellard
    s->y = 0;
1504 491e114a Paolo Bonzini
    if (s->console_type == TEXT_CONSOLE) {
1505 491e114a Paolo Bonzini
        s->g_width = ds_get_width(s->ds);
1506 491e114a Paolo Bonzini
        s->g_height = ds_get_height(s->ds);
1507 491e114a Paolo Bonzini
    }
1508 6d6f7c28 pbrook
1509 bf1bed81 Jan Kiszka
    s->cursor_timer =
1510 bf1bed81 Jan Kiszka
        qemu_new_timer_ms(rt_clock, text_console_update_cursor, s);
1511 bf1bed81 Jan Kiszka
1512 4d3b6f6e balrog
    s->hw_invalidate = text_console_invalidate;
1513 4d3b6f6e balrog
    s->hw_text_update = text_console_update;
1514 4d3b6f6e balrog
    s->hw = s;
1515 4d3b6f6e balrog
1516 6d6f7c28 pbrook
    /* Set text attribute defaults */
1517 6d6f7c28 pbrook
    s->t_attrib_default.bold = 0;
1518 6d6f7c28 pbrook
    s->t_attrib_default.uline = 0;
1519 6d6f7c28 pbrook
    s->t_attrib_default.blink = 0;
1520 6d6f7c28 pbrook
    s->t_attrib_default.invers = 0;
1521 6d6f7c28 pbrook
    s->t_attrib_default.unvisible = 0;
1522 6d6f7c28 pbrook
    s->t_attrib_default.fgcol = COLOR_WHITE;
1523 6d6f7c28 pbrook
    s->t_attrib_default.bgcol = COLOR_BLACK;
1524 6d6f7c28 pbrook
    /* set current text attributes to default */
1525 6d6f7c28 pbrook
    s->t_attrib = s->t_attrib_default;
1526 e7f0ad58 bellard
    text_console_resize(s);
1527 e7f0ad58 bellard
1528 51bfa4d3 Gerd Hoffmann
    if (chr->label) {
1529 51bfa4d3 Gerd Hoffmann
        char msg[128];
1530 51bfa4d3 Gerd Hoffmann
        int len;
1531 51bfa4d3 Gerd Hoffmann
1532 735ba588 Gerd Hoffmann
        s->t_attrib.bgcol = COLOR_BLUE;
1533 51bfa4d3 Gerd Hoffmann
        len = snprintf(msg, sizeof(msg), "%s console\r\n", chr->label);
1534 51bfa4d3 Gerd Hoffmann
        console_puts(chr, (uint8_t*)msg, len);
1535 735ba588 Gerd Hoffmann
        s->t_attrib = s->t_attrib_default;
1536 51bfa4d3 Gerd Hoffmann
    }
1537 51bfa4d3 Gerd Hoffmann
1538 127338e6 Amit Shah
    qemu_chr_generic_open(chr);
1539 ceecf1d1 aurel32
    if (chr->init)
1540 ceecf1d1 aurel32
        chr->init(chr);
1541 e7f0ad58 bellard
}
1542 c60e08d9 pbrook
1543 1f51470d Markus Armbruster
CharDriverState *text_console_init(QemuOpts *opts)
1544 2796dae0 aliguori
{
1545 2796dae0 aliguori
    CharDriverState *chr;
1546 491e114a Paolo Bonzini
    TextConsole *s;
1547 491e114a Paolo Bonzini
    unsigned width;
1548 491e114a Paolo Bonzini
    unsigned height;
1549 2796dae0 aliguori
1550 7267c094 Anthony Liguori
    chr = g_malloc0(sizeof(CharDriverState));
1551 2796dae0 aliguori
1552 491e114a Paolo Bonzini
    width = qemu_opt_get_number(opts, "width", 0);
1553 491e114a Paolo Bonzini
    if (width == 0)
1554 491e114a Paolo Bonzini
        width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH;
1555 491e114a Paolo Bonzini
1556 491e114a Paolo Bonzini
    height = qemu_opt_get_number(opts, "height", 0);
1557 491e114a Paolo Bonzini
    if (height == 0)
1558 491e114a Paolo Bonzini
        height = qemu_opt_get_number(opts, "rows", 0) * FONT_HEIGHT;
1559 491e114a Paolo Bonzini
1560 491e114a Paolo Bonzini
    if (width == 0 || height == 0) {
1561 491e114a Paolo Bonzini
        s = new_console(NULL, TEXT_CONSOLE);
1562 491e114a Paolo Bonzini
    } else {
1563 491e114a Paolo Bonzini
        s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE);
1564 491e114a Paolo Bonzini
    }
1565 491e114a Paolo Bonzini
1566 491e114a Paolo Bonzini
    if (!s) {
1567 5354d083 Stefan Weil
        g_free(chr);
1568 1f51470d Markus Armbruster
        return NULL;
1569 491e114a Paolo Bonzini
    }
1570 491e114a Paolo Bonzini
1571 491e114a Paolo Bonzini
    s->chr = chr;
1572 491e114a Paolo Bonzini
    s->g_width = width;
1573 491e114a Paolo Bonzini
    s->g_height = height;
1574 491e114a Paolo Bonzini
    chr->opaque = s;
1575 4104833f Paolo Bonzini
    chr->chr_set_echo = text_console_set_echo;
1576 1f51470d Markus Armbruster
    return chr;
1577 2796dae0 aliguori
}
1578 2796dae0 aliguori
1579 2796dae0 aliguori
void text_consoles_set_display(DisplayState *ds)
1580 2796dae0 aliguori
{
1581 2796dae0 aliguori
    int i;
1582 2796dae0 aliguori
1583 8811e1e1 Markus Armbruster
    for (i = 0; i < nb_consoles; i++) {
1584 8811e1e1 Markus Armbruster
        if (consoles[i]->console_type != GRAPHIC_CONSOLE) {
1585 8811e1e1 Markus Armbruster
            text_console_do_init(consoles[i]->chr, ds);
1586 8811e1e1 Markus Armbruster
        }
1587 2796dae0 aliguori
    }
1588 2796dae0 aliguori
}
1589 2796dae0 aliguori
1590 3023f332 aliguori
void qemu_console_resize(DisplayState *ds, int width, int height)
1591 c60e08d9 pbrook
{
1592 42aa98e8 aliguori
    TextConsole *s = get_graphic_console(ds);
1593 f497f140 aliguori
    if (!s) return;
1594 f497f140 aliguori
1595 3023f332 aliguori
    s->g_width = width;
1596 3023f332 aliguori
    s->g_height = height;
1597 3023f332 aliguori
    if (is_graphic_console()) {
1598 7b5d76da aliguori
        ds->surface = qemu_resize_displaysurface(ds, width, height);
1599 3023f332 aliguori
        dpy_resize(ds);
1600 c60e08d9 pbrook
    }
1601 c60e08d9 pbrook
}
1602 38334f76 balrog
1603 3023f332 aliguori
void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
1604 3023f332 aliguori
                       int dst_x, int dst_y, int w, int h)
1605 c21bbcfa balrog
{
1606 3023f332 aliguori
    if (is_graphic_console()) {
1607 3023f332 aliguori
        dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
1608 38334f76 balrog
    }
1609 38334f76 balrog
}
1610 7d957bd8 aliguori
1611 0da2ea1b malc
PixelFormat qemu_different_endianness_pixelformat(int bpp)
1612 7d957bd8 aliguori
{
1613 7d957bd8 aliguori
    PixelFormat pf;
1614 7d957bd8 aliguori
1615 7d957bd8 aliguori
    memset(&pf, 0x00, sizeof(PixelFormat));
1616 7d957bd8 aliguori
1617 7d957bd8 aliguori
    pf.bits_per_pixel = bpp;
1618 feadf1a4 BALATON Zoltan
    pf.bytes_per_pixel = DIV_ROUND_UP(bpp, 8);
1619 7d957bd8 aliguori
    pf.depth = bpp == 32 ? 24 : bpp;
1620 7d957bd8 aliguori
1621 7d957bd8 aliguori
    switch (bpp) {
1622 0da2ea1b malc
        case 24:
1623 0da2ea1b malc
            pf.rmask = 0x000000FF;
1624 0da2ea1b malc
            pf.gmask = 0x0000FF00;
1625 0da2ea1b malc
            pf.bmask = 0x00FF0000;
1626 0da2ea1b malc
            pf.rmax = 255;
1627 0da2ea1b malc
            pf.gmax = 255;
1628 0da2ea1b malc
            pf.bmax = 255;
1629 0da2ea1b malc
            pf.rshift = 0;
1630 0da2ea1b malc
            pf.gshift = 8;
1631 0da2ea1b malc
            pf.bshift = 16;
1632 90a1e3c0 aliguori
            pf.rbits = 8;
1633 90a1e3c0 aliguori
            pf.gbits = 8;
1634 90a1e3c0 aliguori
            pf.bbits = 8;
1635 7d957bd8 aliguori
            break;
1636 0da2ea1b malc
        case 32:
1637 0da2ea1b malc
            pf.rmask = 0x0000FF00;
1638 0da2ea1b malc
            pf.gmask = 0x00FF0000;
1639 0da2ea1b malc
            pf.bmask = 0xFF000000;
1640 0da2ea1b malc
            pf.amask = 0x00000000;
1641 0da2ea1b malc
            pf.amax = 255;
1642 0da2ea1b malc
            pf.rmax = 255;
1643 0da2ea1b malc
            pf.gmax = 255;
1644 0da2ea1b malc
            pf.bmax = 255;
1645 0da2ea1b malc
            pf.ashift = 0;
1646 0da2ea1b malc
            pf.rshift = 8;
1647 0da2ea1b malc
            pf.gshift = 16;
1648 0da2ea1b malc
            pf.bshift = 24;
1649 90a1e3c0 aliguori
            pf.rbits = 8;
1650 90a1e3c0 aliguori
            pf.gbits = 8;
1651 90a1e3c0 aliguori
            pf.bbits = 8;
1652 90a1e3c0 aliguori
            pf.abits = 8;
1653 0da2ea1b malc
            break;
1654 0da2ea1b malc
        default:
1655 0da2ea1b malc
            break;
1656 0da2ea1b malc
    }
1657 0da2ea1b malc
    return pf;
1658 0da2ea1b malc
}
1659 0da2ea1b malc
1660 0da2ea1b malc
PixelFormat qemu_default_pixelformat(int bpp)
1661 0da2ea1b malc
{
1662 0da2ea1b malc
    PixelFormat pf;
1663 0da2ea1b malc
1664 0da2ea1b malc
    memset(&pf, 0x00, sizeof(PixelFormat));
1665 0da2ea1b malc
1666 0da2ea1b malc
    pf.bits_per_pixel = bpp;
1667 feadf1a4 BALATON Zoltan
    pf.bytes_per_pixel = DIV_ROUND_UP(bpp, 8);
1668 0da2ea1b malc
    pf.depth = bpp == 32 ? 24 : bpp;
1669 0da2ea1b malc
1670 0da2ea1b malc
    switch (bpp) {
1671 b6278084 Gerd Hoffmann
        case 15:
1672 b6278084 Gerd Hoffmann
            pf.bits_per_pixel = 16;
1673 b6278084 Gerd Hoffmann
            pf.rmask = 0x00007c00;
1674 b6278084 Gerd Hoffmann
            pf.gmask = 0x000003E0;
1675 b6278084 Gerd Hoffmann
            pf.bmask = 0x0000001F;
1676 b6278084 Gerd Hoffmann
            pf.rmax = 31;
1677 b6278084 Gerd Hoffmann
            pf.gmax = 31;
1678 b6278084 Gerd Hoffmann
            pf.bmax = 31;
1679 b6278084 Gerd Hoffmann
            pf.rshift = 10;
1680 b6278084 Gerd Hoffmann
            pf.gshift = 5;
1681 b6278084 Gerd Hoffmann
            pf.bshift = 0;
1682 b6278084 Gerd Hoffmann
            pf.rbits = 5;
1683 b6278084 Gerd Hoffmann
            pf.gbits = 5;
1684 b6278084 Gerd Hoffmann
            pf.bbits = 5;
1685 b6278084 Gerd Hoffmann
            break;
1686 7d957bd8 aliguori
        case 16:
1687 7d957bd8 aliguori
            pf.rmask = 0x0000F800;
1688 7d957bd8 aliguori
            pf.gmask = 0x000007E0;
1689 7d957bd8 aliguori
            pf.bmask = 0x0000001F;
1690 7d957bd8 aliguori
            pf.rmax = 31;
1691 7d957bd8 aliguori
            pf.gmax = 63;
1692 7d957bd8 aliguori
            pf.bmax = 31;
1693 7d957bd8 aliguori
            pf.rshift = 11;
1694 7d957bd8 aliguori
            pf.gshift = 5;
1695 7d957bd8 aliguori
            pf.bshift = 0;
1696 90a1e3c0 aliguori
            pf.rbits = 5;
1697 90a1e3c0 aliguori
            pf.gbits = 6;
1698 90a1e3c0 aliguori
            pf.bbits = 5;
1699 7d957bd8 aliguori
            break;
1700 7d957bd8 aliguori
        case 24:
1701 0da2ea1b malc
            pf.rmask = 0x00FF0000;
1702 0da2ea1b malc
            pf.gmask = 0x0000FF00;
1703 0da2ea1b malc
            pf.bmask = 0x000000FF;
1704 0da2ea1b malc
            pf.rmax = 255;
1705 0da2ea1b malc
            pf.gmax = 255;
1706 0da2ea1b malc
            pf.bmax = 255;
1707 0da2ea1b malc
            pf.rshift = 16;
1708 0da2ea1b malc
            pf.gshift = 8;
1709 0da2ea1b malc
            pf.bshift = 0;
1710 90a1e3c0 aliguori
            pf.rbits = 8;
1711 90a1e3c0 aliguori
            pf.gbits = 8;
1712 90a1e3c0 aliguori
            pf.bbits = 8;
1713 0eba62e0 Markus Armbruster
            break;
1714 7d957bd8 aliguori
        case 32:
1715 7d957bd8 aliguori
            pf.rmask = 0x00FF0000;
1716 7d957bd8 aliguori
            pf.gmask = 0x0000FF00;
1717 7d957bd8 aliguori
            pf.bmask = 0x000000FF;
1718 0da2ea1b malc
            pf.amax = 255;
1719 7d957bd8 aliguori
            pf.rmax = 255;
1720 7d957bd8 aliguori
            pf.gmax = 255;
1721 7d957bd8 aliguori
            pf.bmax = 255;
1722 0da2ea1b malc
            pf.ashift = 24;
1723 7d957bd8 aliguori
            pf.rshift = 16;
1724 7d957bd8 aliguori
            pf.gshift = 8;
1725 7d957bd8 aliguori
            pf.bshift = 0;
1726 90a1e3c0 aliguori
            pf.rbits = 8;
1727 90a1e3c0 aliguori
            pf.gbits = 8;
1728 90a1e3c0 aliguori
            pf.bbits = 8;
1729 90a1e3c0 aliguori
            pf.abits = 8;
1730 7d957bd8 aliguori
            break;
1731 7d957bd8 aliguori
        default:
1732 7d957bd8 aliguori
            break;
1733 7d957bd8 aliguori
    }
1734 7d957bd8 aliguori
    return pf;
1735 7d957bd8 aliguori
}