root / console.c @ 3e11db9a
History | View | Annotate | Download (18.7 kB)
1 | e7f0ad58 | bellard | /*
|
---|---|---|---|
2 | e7f0ad58 | bellard | * QEMU graphical console
|
3 | e7f0ad58 | bellard | *
|
4 | e7f0ad58 | bellard | * Copyright (c) 2004 Fabrice Bellard
|
5 | e7f0ad58 | bellard | *
|
6 | e7f0ad58 | bellard | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | e7f0ad58 | bellard | * of this software and associated documentation files (the "Software"), to deal
|
8 | e7f0ad58 | bellard | * in the Software without restriction, including without limitation the rights
|
9 | e7f0ad58 | bellard | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | e7f0ad58 | bellard | * copies of the Software, and to permit persons to whom the Software is
|
11 | e7f0ad58 | bellard | * furnished to do so, subject to the following conditions:
|
12 | e7f0ad58 | bellard | *
|
13 | e7f0ad58 | bellard | * The above copyright notice and this permission notice shall be included in
|
14 | e7f0ad58 | bellard | * all copies or substantial portions of the Software.
|
15 | e7f0ad58 | bellard | *
|
16 | e7f0ad58 | bellard | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | e7f0ad58 | bellard | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | e7f0ad58 | bellard | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | e7f0ad58 | bellard | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | e7f0ad58 | bellard | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | e7f0ad58 | bellard | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | e7f0ad58 | bellard | * THE SOFTWARE.
|
23 | e7f0ad58 | bellard | */
|
24 | e7f0ad58 | bellard | #include "vl.h" |
25 | e7f0ad58 | bellard | |
26 | e7f0ad58 | bellard | #define DEFAULT_BACKSCROLL 512 |
27 | e7f0ad58 | bellard | #define MAX_CONSOLES 12 |
28 | e7f0ad58 | bellard | |
29 | e7f0ad58 | bellard | #define RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) |
30 | e7f0ad58 | bellard | #define RGB(r, g, b) RGBA(r, g, b, 0xff) |
31 | e7f0ad58 | bellard | |
32 | e7f0ad58 | bellard | typedef struct TextCell { |
33 | e7f0ad58 | bellard | uint8_t ch; |
34 | e7f0ad58 | bellard | uint8_t bgcol:4;
|
35 | e7f0ad58 | bellard | uint8_t fgcol:4;
|
36 | e7f0ad58 | bellard | } TextCell; |
37 | e7f0ad58 | bellard | |
38 | e7f0ad58 | bellard | #define MAX_ESC_PARAMS 3 |
39 | e7f0ad58 | bellard | |
40 | e7f0ad58 | bellard | enum TTYState {
|
41 | e7f0ad58 | bellard | TTY_STATE_NORM, |
42 | e7f0ad58 | bellard | TTY_STATE_ESC, |
43 | e7f0ad58 | bellard | TTY_STATE_CSI, |
44 | e7f0ad58 | bellard | }; |
45 | e7f0ad58 | bellard | |
46 | e7f0ad58 | bellard | struct TextConsole {
|
47 | e7f0ad58 | bellard | int text_console; /* true if text console */ |
48 | e7f0ad58 | bellard | DisplayState *ds; |
49 | e7f0ad58 | bellard | int g_width, g_height;
|
50 | e7f0ad58 | bellard | int width;
|
51 | e7f0ad58 | bellard | int height;
|
52 | e7f0ad58 | bellard | int total_height;
|
53 | e7f0ad58 | bellard | int backscroll_height;
|
54 | e7f0ad58 | bellard | int fgcol;
|
55 | e7f0ad58 | bellard | int bgcol;
|
56 | e7f0ad58 | bellard | int x, y;
|
57 | e7f0ad58 | bellard | int y_displayed;
|
58 | e7f0ad58 | bellard | int y_base;
|
59 | e7f0ad58 | bellard | TextCell *cells; |
60 | e7f0ad58 | bellard | |
61 | e7f0ad58 | bellard | enum TTYState state;
|
62 | e7f0ad58 | bellard | int esc_params[MAX_ESC_PARAMS];
|
63 | e7f0ad58 | bellard | int nb_esc_params;
|
64 | e7f0ad58 | bellard | |
65 | e7f0ad58 | bellard | /* kbd read handler */
|
66 | e7f0ad58 | bellard | IOReadHandler *fd_read; |
67 | e7f0ad58 | bellard | void *fd_opaque;
|
68 | e7f0ad58 | bellard | }; |
69 | e7f0ad58 | bellard | |
70 | e7f0ad58 | bellard | static TextConsole *active_console;
|
71 | e7f0ad58 | bellard | static TextConsole *consoles[MAX_CONSOLES];
|
72 | e7f0ad58 | bellard | static int nb_consoles = 0; |
73 | e7f0ad58 | bellard | |
74 | e7f0ad58 | bellard | /* convert a RGBA color to a color index usable in graphic primitives */
|
75 | e7f0ad58 | bellard | static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba) |
76 | e7f0ad58 | bellard | { |
77 | e7f0ad58 | bellard | unsigned int r, g, b, color; |
78 | e7f0ad58 | bellard | |
79 | e7f0ad58 | bellard | switch(ds->depth) {
|
80 | e7f0ad58 | bellard | #if 0
|
81 | e7f0ad58 | bellard | case 8:
|
82 | e7f0ad58 | bellard | r = (rgba >> 16) & 0xff;
|
83 | e7f0ad58 | bellard | g = (rgba >> 8) & 0xff;
|
84 | e7f0ad58 | bellard | b = (rgba) & 0xff;
|
85 | e7f0ad58 | bellard | color = (rgb_to_index[r] * 6 * 6) +
|
86 | e7f0ad58 | bellard | (rgb_to_index[g] * 6) +
|
87 | e7f0ad58 | bellard | (rgb_to_index[b]);
|
88 | e7f0ad58 | bellard | break;
|
89 | e7f0ad58 | bellard | #endif
|
90 | e7f0ad58 | bellard | case 15: |
91 | e7f0ad58 | bellard | r = (rgba >> 16) & 0xff; |
92 | e7f0ad58 | bellard | g = (rgba >> 8) & 0xff; |
93 | e7f0ad58 | bellard | b = (rgba) & 0xff;
|
94 | e7f0ad58 | bellard | color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); |
95 | e7f0ad58 | bellard | break;
|
96 | e7f0ad58 | bellard | case 16: |
97 | e7f0ad58 | bellard | r = (rgba >> 16) & 0xff; |
98 | e7f0ad58 | bellard | g = (rgba >> 8) & 0xff; |
99 | e7f0ad58 | bellard | b = (rgba) & 0xff;
|
100 | e7f0ad58 | bellard | color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); |
101 | e7f0ad58 | bellard | break;
|
102 | e7f0ad58 | bellard | case 32: |
103 | e7f0ad58 | bellard | default:
|
104 | e7f0ad58 | bellard | color = rgba; |
105 | e7f0ad58 | bellard | break;
|
106 | e7f0ad58 | bellard | } |
107 | e7f0ad58 | bellard | return color;
|
108 | e7f0ad58 | bellard | } |
109 | e7f0ad58 | bellard | |
110 | e7f0ad58 | bellard | static void vga_fill_rect (DisplayState *ds, |
111 | e7f0ad58 | bellard | int posx, int posy, int width, int height, uint32_t color) |
112 | e7f0ad58 | bellard | { |
113 | e7f0ad58 | bellard | uint8_t *d, *d1; |
114 | e7f0ad58 | bellard | int x, y, bpp;
|
115 | e7f0ad58 | bellard | |
116 | e7f0ad58 | bellard | bpp = (ds->depth + 7) >> 3; |
117 | e7f0ad58 | bellard | d1 = ds->data + |
118 | e7f0ad58 | bellard | ds->linesize * posy + bpp * posx; |
119 | e7f0ad58 | bellard | for (y = 0; y < height; y++) { |
120 | e7f0ad58 | bellard | d = d1; |
121 | e7f0ad58 | bellard | switch(bpp) {
|
122 | e7f0ad58 | bellard | case 1: |
123 | e7f0ad58 | bellard | for (x = 0; x < width; x++) { |
124 | e7f0ad58 | bellard | *((uint8_t *)d) = color; |
125 | e7f0ad58 | bellard | d++; |
126 | e7f0ad58 | bellard | } |
127 | e7f0ad58 | bellard | break;
|
128 | e7f0ad58 | bellard | case 2: |
129 | e7f0ad58 | bellard | for (x = 0; x < width; x++) { |
130 | e7f0ad58 | bellard | *((uint16_t *)d) = color; |
131 | e7f0ad58 | bellard | d += 2;
|
132 | e7f0ad58 | bellard | } |
133 | e7f0ad58 | bellard | break;
|
134 | e7f0ad58 | bellard | case 4: |
135 | e7f0ad58 | bellard | for (x = 0; x < width; x++) { |
136 | e7f0ad58 | bellard | *((uint32_t *)d) = color; |
137 | e7f0ad58 | bellard | d += 4;
|
138 | e7f0ad58 | bellard | } |
139 | e7f0ad58 | bellard | break;
|
140 | e7f0ad58 | bellard | } |
141 | e7f0ad58 | bellard | d1 += ds->linesize; |
142 | e7f0ad58 | bellard | } |
143 | e7f0ad58 | bellard | } |
144 | e7f0ad58 | bellard | |
145 | e7f0ad58 | bellard | /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
|
146 | e7f0ad58 | bellard | static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h) |
147 | e7f0ad58 | bellard | { |
148 | e7f0ad58 | bellard | const uint8_t *s;
|
149 | e7f0ad58 | bellard | uint8_t *d; |
150 | e7f0ad58 | bellard | int wb, y, bpp;
|
151 | e7f0ad58 | bellard | |
152 | e7f0ad58 | bellard | bpp = (ds->depth + 7) >> 3; |
153 | e7f0ad58 | bellard | wb = w * bpp; |
154 | e7f0ad58 | bellard | if (yd <= ys) {
|
155 | e7f0ad58 | bellard | s = ds->data + |
156 | e7f0ad58 | bellard | ds->linesize * ys + bpp * xs; |
157 | e7f0ad58 | bellard | d = ds->data + |
158 | e7f0ad58 | bellard | ds->linesize * yd + bpp * xd; |
159 | e7f0ad58 | bellard | for (y = 0; y < h; y++) { |
160 | e7f0ad58 | bellard | memmove(d, s, wb); |
161 | e7f0ad58 | bellard | d += ds->linesize; |
162 | e7f0ad58 | bellard | s += ds->linesize; |
163 | e7f0ad58 | bellard | } |
164 | e7f0ad58 | bellard | } else {
|
165 | e7f0ad58 | bellard | s = ds->data + |
166 | e7f0ad58 | bellard | ds->linesize * (ys + h - 1) + bpp * xs;
|
167 | e7f0ad58 | bellard | d = ds->data + |
168 | e7f0ad58 | bellard | ds->linesize * (yd + h - 1) + bpp * xd;
|
169 | e7f0ad58 | bellard | for (y = 0; y < h; y++) { |
170 | e7f0ad58 | bellard | memmove(d, s, wb); |
171 | e7f0ad58 | bellard | d -= ds->linesize; |
172 | e7f0ad58 | bellard | s -= ds->linesize; |
173 | e7f0ad58 | bellard | } |
174 | e7f0ad58 | bellard | } |
175 | e7f0ad58 | bellard | } |
176 | e7f0ad58 | bellard | |
177 | e7f0ad58 | bellard | /***********************************************************/
|
178 | e7f0ad58 | bellard | /* basic char display */
|
179 | e7f0ad58 | bellard | |
180 | e7f0ad58 | bellard | #define FONT_HEIGHT 16 |
181 | e7f0ad58 | bellard | #define FONT_WIDTH 8 |
182 | e7f0ad58 | bellard | |
183 | e7f0ad58 | bellard | #include "vgafont.h" |
184 | e7f0ad58 | bellard | |
185 | e7f0ad58 | bellard | #define cbswap_32(__x) \
|
186 | e7f0ad58 | bellard | ((uint32_t)( \ |
187 | e7f0ad58 | bellard | (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ |
188 | e7f0ad58 | bellard | (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ |
189 | e7f0ad58 | bellard | (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ |
190 | e7f0ad58 | bellard | (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )) |
191 | e7f0ad58 | bellard | |
192 | e7f0ad58 | bellard | #ifdef WORDS_BIGENDIAN
|
193 | e7f0ad58 | bellard | #define PAT(x) x
|
194 | e7f0ad58 | bellard | #else
|
195 | e7f0ad58 | bellard | #define PAT(x) cbswap_32(x)
|
196 | e7f0ad58 | bellard | #endif
|
197 | e7f0ad58 | bellard | |
198 | e7f0ad58 | bellard | static const uint32_t dmask16[16] = { |
199 | e7f0ad58 | bellard | PAT(0x00000000),
|
200 | e7f0ad58 | bellard | PAT(0x000000ff),
|
201 | e7f0ad58 | bellard | PAT(0x0000ff00),
|
202 | e7f0ad58 | bellard | PAT(0x0000ffff),
|
203 | e7f0ad58 | bellard | PAT(0x00ff0000),
|
204 | e7f0ad58 | bellard | PAT(0x00ff00ff),
|
205 | e7f0ad58 | bellard | PAT(0x00ffff00),
|
206 | e7f0ad58 | bellard | PAT(0x00ffffff),
|
207 | e7f0ad58 | bellard | PAT(0xff000000),
|
208 | e7f0ad58 | bellard | PAT(0xff0000ff),
|
209 | e7f0ad58 | bellard | PAT(0xff00ff00),
|
210 | e7f0ad58 | bellard | PAT(0xff00ffff),
|
211 | e7f0ad58 | bellard | PAT(0xffff0000),
|
212 | e7f0ad58 | bellard | PAT(0xffff00ff),
|
213 | e7f0ad58 | bellard | PAT(0xffffff00),
|
214 | e7f0ad58 | bellard | PAT(0xffffffff),
|
215 | e7f0ad58 | bellard | }; |
216 | e7f0ad58 | bellard | |
217 | e7f0ad58 | bellard | static const uint32_t dmask4[4] = { |
218 | e7f0ad58 | bellard | PAT(0x00000000),
|
219 | e7f0ad58 | bellard | PAT(0x0000ffff),
|
220 | e7f0ad58 | bellard | PAT(0xffff0000),
|
221 | e7f0ad58 | bellard | PAT(0xffffffff),
|
222 | e7f0ad58 | bellard | }; |
223 | e7f0ad58 | bellard | |
224 | e7f0ad58 | bellard | static uint32_t color_table[8]; |
225 | e7f0ad58 | bellard | |
226 | e7f0ad58 | bellard | static const uint32_t color_table_rgb[8] = { |
227 | e7f0ad58 | bellard | RGB(0x00, 0x00, 0x00), |
228 | e7f0ad58 | bellard | RGB(0xff, 0x00, 0x00), |
229 | e7f0ad58 | bellard | RGB(0x00, 0xff, 0x00), |
230 | e7f0ad58 | bellard | RGB(0xff, 0xff, 0x00), |
231 | e7f0ad58 | bellard | RGB(0x00, 0x00, 0xff), |
232 | e7f0ad58 | bellard | RGB(0xff, 0x00, 0xff), |
233 | e7f0ad58 | bellard | RGB(0x00, 0xff, 0xff), |
234 | e7f0ad58 | bellard | RGB(0xff, 0xff, 0xff), |
235 | e7f0ad58 | bellard | }; |
236 | e7f0ad58 | bellard | |
237 | e7f0ad58 | bellard | static inline unsigned int col_expand(DisplayState *ds, unsigned int col) |
238 | e7f0ad58 | bellard | { |
239 | e7f0ad58 | bellard | switch(ds->depth) {
|
240 | e7f0ad58 | bellard | case 8: |
241 | e7f0ad58 | bellard | col |= col << 8;
|
242 | e7f0ad58 | bellard | col |= col << 16;
|
243 | e7f0ad58 | bellard | break;
|
244 | e7f0ad58 | bellard | case 15: |
245 | e7f0ad58 | bellard | case 16: |
246 | e7f0ad58 | bellard | col |= col << 16;
|
247 | e7f0ad58 | bellard | break;
|
248 | e7f0ad58 | bellard | default:
|
249 | e7f0ad58 | bellard | break;
|
250 | e7f0ad58 | bellard | } |
251 | e7f0ad58 | bellard | |
252 | e7f0ad58 | bellard | return col;
|
253 | e7f0ad58 | bellard | } |
254 | e7f0ad58 | bellard | |
255 | e7f0ad58 | bellard | static void vga_putcharxy(DisplayState *ds, int x, int y, int ch, |
256 | e7f0ad58 | bellard | unsigned int fgcol, unsigned int bgcol) |
257 | e7f0ad58 | bellard | { |
258 | e7f0ad58 | bellard | uint8_t *d; |
259 | e7f0ad58 | bellard | const uint8_t *font_ptr;
|
260 | e7f0ad58 | bellard | unsigned int font_data, linesize, xorcol, bpp; |
261 | e7f0ad58 | bellard | int i;
|
262 | e7f0ad58 | bellard | |
263 | e7f0ad58 | bellard | bpp = (ds->depth + 7) >> 3; |
264 | e7f0ad58 | bellard | d = ds->data + |
265 | e7f0ad58 | bellard | ds->linesize * y * FONT_HEIGHT + bpp * x * FONT_WIDTH; |
266 | e7f0ad58 | bellard | linesize = ds->linesize; |
267 | e7f0ad58 | bellard | font_ptr = vgafont16 + FONT_HEIGHT * ch; |
268 | e7f0ad58 | bellard | xorcol = bgcol ^ fgcol; |
269 | e7f0ad58 | bellard | switch(ds->depth) {
|
270 | e7f0ad58 | bellard | case 8: |
271 | e7f0ad58 | bellard | for(i = 0; i < FONT_HEIGHT; i++) { |
272 | e7f0ad58 | bellard | font_data = *font_ptr++; |
273 | e7f0ad58 | bellard | ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol; |
274 | e7f0ad58 | bellard | ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; |
275 | e7f0ad58 | bellard | d += linesize; |
276 | e7f0ad58 | bellard | } |
277 | e7f0ad58 | bellard | break;
|
278 | e7f0ad58 | bellard | case 16: |
279 | e7f0ad58 | bellard | case 15: |
280 | e7f0ad58 | bellard | for(i = 0; i < FONT_HEIGHT; i++) { |
281 | e7f0ad58 | bellard | font_data = *font_ptr++; |
282 | e7f0ad58 | bellard | ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol; |
283 | e7f0ad58 | bellard | ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol; |
284 | e7f0ad58 | bellard | ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol; |
285 | e7f0ad58 | bellard | ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; |
286 | e7f0ad58 | bellard | d += linesize; |
287 | e7f0ad58 | bellard | } |
288 | e7f0ad58 | bellard | break;
|
289 | e7f0ad58 | bellard | case 32: |
290 | e7f0ad58 | bellard | for(i = 0; i < FONT_HEIGHT; i++) { |
291 | e7f0ad58 | bellard | font_data = *font_ptr++; |
292 | e7f0ad58 | bellard | ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; |
293 | e7f0ad58 | bellard | ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; |
294 | e7f0ad58 | bellard | ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; |
295 | e7f0ad58 | bellard | ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; |
296 | e7f0ad58 | bellard | ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; |
297 | e7f0ad58 | bellard | ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; |
298 | e7f0ad58 | bellard | ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; |
299 | e7f0ad58 | bellard | ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; |
300 | e7f0ad58 | bellard | d += linesize; |
301 | e7f0ad58 | bellard | } |
302 | e7f0ad58 | bellard | break;
|
303 | e7f0ad58 | bellard | } |
304 | e7f0ad58 | bellard | } |
305 | e7f0ad58 | bellard | |
306 | e7f0ad58 | bellard | static void text_console_resize(TextConsole *s) |
307 | e7f0ad58 | bellard | { |
308 | e7f0ad58 | bellard | TextCell *cells, *c, *c1; |
309 | e7f0ad58 | bellard | int w1, x, y, last_width;
|
310 | e7f0ad58 | bellard | |
311 | e7f0ad58 | bellard | last_width = s->width; |
312 | e7f0ad58 | bellard | s->width = s->g_width / FONT_WIDTH; |
313 | e7f0ad58 | bellard | s->height = s->g_height / FONT_HEIGHT; |
314 | e7f0ad58 | bellard | |
315 | e7f0ad58 | bellard | w1 = last_width; |
316 | e7f0ad58 | bellard | if (s->width < w1)
|
317 | e7f0ad58 | bellard | w1 = s->width; |
318 | e7f0ad58 | bellard | |
319 | e7f0ad58 | bellard | cells = qemu_malloc(s->width * s->total_height * sizeof(TextCell));
|
320 | e7f0ad58 | bellard | for(y = 0; y < s->total_height; y++) { |
321 | e7f0ad58 | bellard | c = &cells[y * s->width]; |
322 | e7f0ad58 | bellard | if (w1 > 0) { |
323 | e7f0ad58 | bellard | c1 = &s->cells[y * last_width]; |
324 | e7f0ad58 | bellard | for(x = 0; x < w1; x++) { |
325 | e7f0ad58 | bellard | *c++ = *c1++; |
326 | e7f0ad58 | bellard | } |
327 | e7f0ad58 | bellard | } |
328 | e7f0ad58 | bellard | for(x = w1; x < s->width; x++) {
|
329 | e7f0ad58 | bellard | c->ch = ' ';
|
330 | e7f0ad58 | bellard | c->fgcol = 7;
|
331 | e7f0ad58 | bellard | c->bgcol = 0;
|
332 | e7f0ad58 | bellard | c++; |
333 | e7f0ad58 | bellard | } |
334 | e7f0ad58 | bellard | } |
335 | e7f0ad58 | bellard | free(s->cells); |
336 | e7f0ad58 | bellard | s->cells = cells; |
337 | e7f0ad58 | bellard | } |
338 | e7f0ad58 | bellard | |
339 | e7f0ad58 | bellard | static void update_xy(TextConsole *s, int x, int y) |
340 | e7f0ad58 | bellard | { |
341 | e7f0ad58 | bellard | TextCell *c; |
342 | e7f0ad58 | bellard | int y1, y2;
|
343 | e7f0ad58 | bellard | |
344 | e7f0ad58 | bellard | if (s == active_console) {
|
345 | e7f0ad58 | bellard | y1 = (s->y_base + y) % s->total_height; |
346 | e7f0ad58 | bellard | y2 = y1 - s->y_displayed; |
347 | e7f0ad58 | bellard | if (y2 < 0) |
348 | e7f0ad58 | bellard | y2 += s->total_height; |
349 | e7f0ad58 | bellard | if (y2 < s->height) {
|
350 | e7f0ad58 | bellard | c = &s->cells[y1 * s->width + x]; |
351 | e7f0ad58 | bellard | vga_putcharxy(s->ds, x, y2, c->ch, |
352 | e7f0ad58 | bellard | color_table[c->fgcol], color_table[c->bgcol]); |
353 | e7f0ad58 | bellard | dpy_update(s->ds, x * FONT_WIDTH, y2 * FONT_HEIGHT, |
354 | e7f0ad58 | bellard | FONT_WIDTH, FONT_HEIGHT); |
355 | e7f0ad58 | bellard | } |
356 | e7f0ad58 | bellard | } |
357 | e7f0ad58 | bellard | } |
358 | e7f0ad58 | bellard | |
359 | e7f0ad58 | bellard | static void console_show_cursor(TextConsole *s, int show) |
360 | e7f0ad58 | bellard | { |
361 | e7f0ad58 | bellard | TextCell *c; |
362 | e7f0ad58 | bellard | int y, y1;
|
363 | e7f0ad58 | bellard | |
364 | e7f0ad58 | bellard | if (s == active_console) {
|
365 | e7f0ad58 | bellard | y1 = (s->y_base + s->y) % s->total_height; |
366 | e7f0ad58 | bellard | y = y1 - s->y_displayed; |
367 | e7f0ad58 | bellard | if (y < 0) |
368 | e7f0ad58 | bellard | y += s->total_height; |
369 | e7f0ad58 | bellard | if (y < s->height) {
|
370 | e7f0ad58 | bellard | c = &s->cells[y1 * s->width + s->x]; |
371 | e7f0ad58 | bellard | if (show) {
|
372 | e7f0ad58 | bellard | vga_putcharxy(s->ds, s->x, y, c->ch, |
373 | e7f0ad58 | bellard | color_table[0], color_table[7]); |
374 | e7f0ad58 | bellard | } else {
|
375 | e7f0ad58 | bellard | vga_putcharxy(s->ds, s->x, y, c->ch, |
376 | e7f0ad58 | bellard | color_table[c->fgcol], color_table[c->bgcol]); |
377 | e7f0ad58 | bellard | } |
378 | e7f0ad58 | bellard | dpy_update(s->ds, s->x * FONT_WIDTH, y * FONT_HEIGHT, |
379 | e7f0ad58 | bellard | FONT_WIDTH, FONT_HEIGHT); |
380 | e7f0ad58 | bellard | } |
381 | e7f0ad58 | bellard | } |
382 | e7f0ad58 | bellard | } |
383 | e7f0ad58 | bellard | |
384 | e7f0ad58 | bellard | static void console_refresh(TextConsole *s) |
385 | e7f0ad58 | bellard | { |
386 | e7f0ad58 | bellard | TextCell *c; |
387 | e7f0ad58 | bellard | int x, y, y1;
|
388 | e7f0ad58 | bellard | |
389 | e7f0ad58 | bellard | if (s != active_console)
|
390 | e7f0ad58 | bellard | return;
|
391 | e7f0ad58 | bellard | |
392 | e7f0ad58 | bellard | vga_fill_rect(s->ds, 0, 0, s->ds->width, s->ds->height, |
393 | e7f0ad58 | bellard | color_table[0]);
|
394 | e7f0ad58 | bellard | y1 = s->y_displayed; |
395 | e7f0ad58 | bellard | for(y = 0; y < s->height; y++) { |
396 | e7f0ad58 | bellard | c = s->cells + y1 * s->width; |
397 | e7f0ad58 | bellard | for(x = 0; x < s->width; x++) { |
398 | e7f0ad58 | bellard | vga_putcharxy(s->ds, x, y, c->ch, |
399 | e7f0ad58 | bellard | color_table[c->fgcol], color_table[c->bgcol]); |
400 | e7f0ad58 | bellard | c++; |
401 | e7f0ad58 | bellard | } |
402 | e7f0ad58 | bellard | if (++y1 == s->total_height)
|
403 | e7f0ad58 | bellard | y1 = 0;
|
404 | e7f0ad58 | bellard | } |
405 | e7f0ad58 | bellard | dpy_update(s->ds, 0, 0, s->ds->width, s->ds->height); |
406 | e7f0ad58 | bellard | console_show_cursor(s, 1);
|
407 | e7f0ad58 | bellard | } |
408 | e7f0ad58 | bellard | |
409 | e7f0ad58 | bellard | static void console_scroll(int ydelta) |
410 | e7f0ad58 | bellard | { |
411 | e7f0ad58 | bellard | TextConsole *s; |
412 | e7f0ad58 | bellard | int i, y1;
|
413 | e7f0ad58 | bellard | |
414 | e7f0ad58 | bellard | s = active_console; |
415 | e7f0ad58 | bellard | if (!s || !s->text_console)
|
416 | e7f0ad58 | bellard | return;
|
417 | e7f0ad58 | bellard | |
418 | e7f0ad58 | bellard | if (ydelta > 0) { |
419 | e7f0ad58 | bellard | for(i = 0; i < ydelta; i++) { |
420 | e7f0ad58 | bellard | if (s->y_displayed == s->y_base)
|
421 | e7f0ad58 | bellard | break;
|
422 | e7f0ad58 | bellard | if (++s->y_displayed == s->total_height)
|
423 | e7f0ad58 | bellard | s->y_displayed = 0;
|
424 | e7f0ad58 | bellard | } |
425 | e7f0ad58 | bellard | } else {
|
426 | e7f0ad58 | bellard | ydelta = -ydelta; |
427 | e7f0ad58 | bellard | i = s->backscroll_height; |
428 | e7f0ad58 | bellard | if (i > s->total_height - s->height)
|
429 | e7f0ad58 | bellard | i = s->total_height - s->height; |
430 | e7f0ad58 | bellard | y1 = s->y_base - i; |
431 | e7f0ad58 | bellard | if (y1 < 0) |
432 | e7f0ad58 | bellard | y1 += s->total_height; |
433 | e7f0ad58 | bellard | for(i = 0; i < ydelta; i++) { |
434 | e7f0ad58 | bellard | if (s->y_displayed == y1)
|
435 | e7f0ad58 | bellard | break;
|
436 | e7f0ad58 | bellard | if (--s->y_displayed < 0) |
437 | e7f0ad58 | bellard | s->y_displayed = s->total_height - 1;
|
438 | e7f0ad58 | bellard | } |
439 | e7f0ad58 | bellard | } |
440 | e7f0ad58 | bellard | console_refresh(s); |
441 | e7f0ad58 | bellard | } |
442 | e7f0ad58 | bellard | |
443 | e7f0ad58 | bellard | static void console_put_lf(TextConsole *s) |
444 | e7f0ad58 | bellard | { |
445 | e7f0ad58 | bellard | TextCell *c; |
446 | e7f0ad58 | bellard | int x, y1;
|
447 | e7f0ad58 | bellard | |
448 | e7f0ad58 | bellard | s->x = 0;
|
449 | e7f0ad58 | bellard | s->y++; |
450 | e7f0ad58 | bellard | if (s->y >= s->height) {
|
451 | e7f0ad58 | bellard | s->y = s->height - 1;
|
452 | e7f0ad58 | bellard | |
453 | e7f0ad58 | bellard | if (s->y_displayed == s->y_base) {
|
454 | e7f0ad58 | bellard | if (++s->y_displayed == s->total_height)
|
455 | e7f0ad58 | bellard | s->y_displayed = 0;
|
456 | e7f0ad58 | bellard | } |
457 | e7f0ad58 | bellard | if (++s->y_base == s->total_height)
|
458 | e7f0ad58 | bellard | s->y_base = 0;
|
459 | e7f0ad58 | bellard | if (s->backscroll_height < s->total_height)
|
460 | e7f0ad58 | bellard | s->backscroll_height++; |
461 | e7f0ad58 | bellard | y1 = (s->y_base + s->height - 1) % s->total_height;
|
462 | e7f0ad58 | bellard | c = &s->cells[y1 * s->width]; |
463 | e7f0ad58 | bellard | for(x = 0; x < s->width; x++) { |
464 | e7f0ad58 | bellard | c->ch = ' ';
|
465 | e7f0ad58 | bellard | c->fgcol = s->fgcol; |
466 | e7f0ad58 | bellard | c->bgcol = s->bgcol; |
467 | e7f0ad58 | bellard | c++; |
468 | e7f0ad58 | bellard | } |
469 | e7f0ad58 | bellard | if (s == active_console && s->y_displayed == s->y_base) {
|
470 | e7f0ad58 | bellard | vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0, |
471 | e7f0ad58 | bellard | s->width * FONT_WIDTH, |
472 | e7f0ad58 | bellard | (s->height - 1) * FONT_HEIGHT);
|
473 | e7f0ad58 | bellard | vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT, |
474 | e7f0ad58 | bellard | s->width * FONT_WIDTH, FONT_HEIGHT, |
475 | e7f0ad58 | bellard | color_table[s->bgcol]); |
476 | e7f0ad58 | bellard | dpy_update(s->ds, 0, 0, |
477 | e7f0ad58 | bellard | s->width * FONT_WIDTH, s->height * FONT_HEIGHT); |
478 | e7f0ad58 | bellard | } |
479 | e7f0ad58 | bellard | } |
480 | e7f0ad58 | bellard | } |
481 | e7f0ad58 | bellard | |
482 | e7f0ad58 | bellard | static void console_putchar(TextConsole *s, int ch) |
483 | e7f0ad58 | bellard | { |
484 | e7f0ad58 | bellard | TextCell *c; |
485 | e7f0ad58 | bellard | int y1, i, x;
|
486 | e7f0ad58 | bellard | |
487 | e7f0ad58 | bellard | switch(s->state) {
|
488 | e7f0ad58 | bellard | case TTY_STATE_NORM:
|
489 | e7f0ad58 | bellard | switch(ch) {
|
490 | e7f0ad58 | bellard | case '\r': |
491 | e7f0ad58 | bellard | s->x = 0;
|
492 | e7f0ad58 | bellard | break;
|
493 | e7f0ad58 | bellard | case '\n': |
494 | e7f0ad58 | bellard | console_put_lf(s); |
495 | e7f0ad58 | bellard | break;
|
496 | e7f0ad58 | bellard | case 27: |
497 | e7f0ad58 | bellard | s->state = TTY_STATE_ESC; |
498 | e7f0ad58 | bellard | break;
|
499 | e7f0ad58 | bellard | default:
|
500 | e7f0ad58 | bellard | y1 = (s->y_base + s->y) % s->total_height; |
501 | e7f0ad58 | bellard | c = &s->cells[y1 * s->width + s->x]; |
502 | e7f0ad58 | bellard | c->ch = ch; |
503 | e7f0ad58 | bellard | c->fgcol = s->fgcol; |
504 | e7f0ad58 | bellard | c->bgcol = s->bgcol; |
505 | e7f0ad58 | bellard | update_xy(s, s->x, s->y); |
506 | e7f0ad58 | bellard | s->x++; |
507 | e7f0ad58 | bellard | if (s->x >= s->width)
|
508 | e7f0ad58 | bellard | console_put_lf(s); |
509 | e7f0ad58 | bellard | break;
|
510 | e7f0ad58 | bellard | } |
511 | e7f0ad58 | bellard | break;
|
512 | e7f0ad58 | bellard | case TTY_STATE_ESC:
|
513 | e7f0ad58 | bellard | if (ch == '[') { |
514 | e7f0ad58 | bellard | for(i=0;i<MAX_ESC_PARAMS;i++) |
515 | e7f0ad58 | bellard | s->esc_params[i] = 0;
|
516 | e7f0ad58 | bellard | s->nb_esc_params = 0;
|
517 | e7f0ad58 | bellard | s->state = TTY_STATE_CSI; |
518 | e7f0ad58 | bellard | } else {
|
519 | e7f0ad58 | bellard | s->state = TTY_STATE_NORM; |
520 | e7f0ad58 | bellard | } |
521 | e7f0ad58 | bellard | break;
|
522 | e7f0ad58 | bellard | case TTY_STATE_CSI:
|
523 | e7f0ad58 | bellard | if (ch >= '0' && ch <= '9') { |
524 | e7f0ad58 | bellard | if (s->nb_esc_params < MAX_ESC_PARAMS) {
|
525 | e7f0ad58 | bellard | s->esc_params[s->nb_esc_params] = |
526 | e7f0ad58 | bellard | s->esc_params[s->nb_esc_params] * 10 + ch - '0'; |
527 | e7f0ad58 | bellard | } |
528 | e7f0ad58 | bellard | } else {
|
529 | e7f0ad58 | bellard | s->nb_esc_params++; |
530 | e7f0ad58 | bellard | if (ch == ';') |
531 | e7f0ad58 | bellard | break;
|
532 | e7f0ad58 | bellard | s->state = TTY_STATE_NORM; |
533 | e7f0ad58 | bellard | switch(ch) {
|
534 | e7f0ad58 | bellard | case 'D': |
535 | e7f0ad58 | bellard | if (s->x > 0) |
536 | e7f0ad58 | bellard | s->x--; |
537 | e7f0ad58 | bellard | break;
|
538 | e7f0ad58 | bellard | case 'C': |
539 | e7f0ad58 | bellard | if (s->x < (s->width - 1)) |
540 | e7f0ad58 | bellard | s->x++; |
541 | e7f0ad58 | bellard | break;
|
542 | e7f0ad58 | bellard | case 'K': |
543 | e7f0ad58 | bellard | /* clear to eol */
|
544 | e7f0ad58 | bellard | y1 = (s->y_base + s->y) % s->total_height; |
545 | e7f0ad58 | bellard | for(x = s->x; x < s->width; x++) {
|
546 | e7f0ad58 | bellard | c = &s->cells[y1 * s->width + x]; |
547 | e7f0ad58 | bellard | c->ch = ' ';
|
548 | e7f0ad58 | bellard | c->fgcol = s->fgcol; |
549 | e7f0ad58 | bellard | c->bgcol = s->bgcol; |
550 | e7f0ad58 | bellard | c++; |
551 | e7f0ad58 | bellard | update_xy(s, x, s->y); |
552 | e7f0ad58 | bellard | } |
553 | e7f0ad58 | bellard | break;
|
554 | e7f0ad58 | bellard | default:
|
555 | e7f0ad58 | bellard | break;
|
556 | e7f0ad58 | bellard | } |
557 | e7f0ad58 | bellard | break;
|
558 | e7f0ad58 | bellard | } |
559 | e7f0ad58 | bellard | } |
560 | e7f0ad58 | bellard | } |
561 | e7f0ad58 | bellard | |
562 | e7f0ad58 | bellard | void console_select(unsigned int index) |
563 | e7f0ad58 | bellard | { |
564 | e7f0ad58 | bellard | TextConsole *s; |
565 | e7f0ad58 | bellard | |
566 | e7f0ad58 | bellard | if (index >= MAX_CONSOLES)
|
567 | e7f0ad58 | bellard | return;
|
568 | e7f0ad58 | bellard | s = consoles[index]; |
569 | e7f0ad58 | bellard | if (s) {
|
570 | e7f0ad58 | bellard | active_console = s; |
571 | e7f0ad58 | bellard | if (s->text_console) {
|
572 | e7f0ad58 | bellard | if (s->g_width != s->ds->width ||
|
573 | e7f0ad58 | bellard | s->g_height != s->ds->height) |
574 | e7f0ad58 | bellard | text_console_resize(s); |
575 | e7f0ad58 | bellard | console_refresh(s); |
576 | e7f0ad58 | bellard | } |
577 | e7f0ad58 | bellard | } |
578 | e7f0ad58 | bellard | } |
579 | e7f0ad58 | bellard | |
580 | e7f0ad58 | bellard | static int console_puts(CharDriverState *chr, const uint8_t *buf, int len) |
581 | e7f0ad58 | bellard | { |
582 | e7f0ad58 | bellard | TextConsole *s = chr->opaque; |
583 | e7f0ad58 | bellard | int i;
|
584 | e7f0ad58 | bellard | |
585 | e7f0ad58 | bellard | console_show_cursor(s, 0);
|
586 | e7f0ad58 | bellard | for(i = 0; i < len; i++) { |
587 | e7f0ad58 | bellard | console_putchar(s, buf[i]); |
588 | e7f0ad58 | bellard | } |
589 | e7f0ad58 | bellard | console_show_cursor(s, 1);
|
590 | e7f0ad58 | bellard | return len;
|
591 | e7f0ad58 | bellard | } |
592 | e7f0ad58 | bellard | |
593 | e7f0ad58 | bellard | static void console_chr_add_read_handler(CharDriverState *chr, |
594 | e7f0ad58 | bellard | IOCanRWHandler *fd_can_read, |
595 | e7f0ad58 | bellard | IOReadHandler *fd_read, void *opaque)
|
596 | e7f0ad58 | bellard | { |
597 | e7f0ad58 | bellard | TextConsole *s = chr->opaque; |
598 | e7f0ad58 | bellard | s->fd_read = fd_read; |
599 | e7f0ad58 | bellard | s->fd_opaque = opaque; |
600 | e7f0ad58 | bellard | } |
601 | e7f0ad58 | bellard | |
602 | e7f0ad58 | bellard | /* called when an ascii key is pressed */
|
603 | e7f0ad58 | bellard | void kbd_put_keysym(int keysym) |
604 | e7f0ad58 | bellard | { |
605 | e7f0ad58 | bellard | TextConsole *s; |
606 | e7f0ad58 | bellard | uint8_t buf[16], *q;
|
607 | e7f0ad58 | bellard | int c;
|
608 | e7f0ad58 | bellard | |
609 | e7f0ad58 | bellard | s = active_console; |
610 | e7f0ad58 | bellard | if (!s || !s->text_console)
|
611 | e7f0ad58 | bellard | return;
|
612 | e7f0ad58 | bellard | |
613 | e7f0ad58 | bellard | switch(keysym) {
|
614 | e7f0ad58 | bellard | case QEMU_KEY_CTRL_UP:
|
615 | e7f0ad58 | bellard | console_scroll(-1);
|
616 | e7f0ad58 | bellard | break;
|
617 | e7f0ad58 | bellard | case QEMU_KEY_CTRL_DOWN:
|
618 | e7f0ad58 | bellard | console_scroll(1);
|
619 | e7f0ad58 | bellard | break;
|
620 | e7f0ad58 | bellard | case QEMU_KEY_CTRL_PAGEUP:
|
621 | e7f0ad58 | bellard | console_scroll(-10);
|
622 | e7f0ad58 | bellard | break;
|
623 | e7f0ad58 | bellard | case QEMU_KEY_CTRL_PAGEDOWN:
|
624 | e7f0ad58 | bellard | console_scroll(10);
|
625 | e7f0ad58 | bellard | break;
|
626 | e7f0ad58 | bellard | default:
|
627 | e7f0ad58 | bellard | if (s->fd_read) {
|
628 | e7f0ad58 | bellard | /* convert the QEMU keysym to VT100 key string */
|
629 | e7f0ad58 | bellard | q = buf; |
630 | e7f0ad58 | bellard | if (keysym >= 0xe100 && keysym <= 0xe11f) { |
631 | e7f0ad58 | bellard | *q++ = '\033';
|
632 | e7f0ad58 | bellard | *q++ = '[';
|
633 | e7f0ad58 | bellard | c = keysym - 0xe100;
|
634 | e7f0ad58 | bellard | if (c >= 10) |
635 | e7f0ad58 | bellard | *q++ = '0' + (c / 10); |
636 | e7f0ad58 | bellard | *q++ = '0' + (c % 10); |
637 | e7f0ad58 | bellard | *q++ = '~';
|
638 | e7f0ad58 | bellard | } else if (keysym >= 0xe120 && keysym <= 0xe17f) { |
639 | e7f0ad58 | bellard | *q++ = '\033';
|
640 | e7f0ad58 | bellard | *q++ = '[';
|
641 | e7f0ad58 | bellard | *q++ = keysym & 0xff;
|
642 | e7f0ad58 | bellard | } else {
|
643 | e7f0ad58 | bellard | *q++ = keysym; |
644 | e7f0ad58 | bellard | } |
645 | e7f0ad58 | bellard | s->fd_read(s->fd_opaque, buf, q - buf); |
646 | e7f0ad58 | bellard | } |
647 | e7f0ad58 | bellard | break;
|
648 | e7f0ad58 | bellard | } |
649 | e7f0ad58 | bellard | } |
650 | e7f0ad58 | bellard | |
651 | e7f0ad58 | bellard | TextConsole *graphic_console_init(DisplayState *ds) |
652 | e7f0ad58 | bellard | { |
653 | e7f0ad58 | bellard | TextConsole *s; |
654 | e7f0ad58 | bellard | |
655 | e7f0ad58 | bellard | if (nb_consoles >= MAX_CONSOLES)
|
656 | e7f0ad58 | bellard | return NULL; |
657 | e7f0ad58 | bellard | s = qemu_mallocz(sizeof(TextConsole));
|
658 | e7f0ad58 | bellard | if (!s) {
|
659 | e7f0ad58 | bellard | return NULL; |
660 | e7f0ad58 | bellard | } |
661 | e7f0ad58 | bellard | if (!active_console)
|
662 | e7f0ad58 | bellard | active_console = s; |
663 | e7f0ad58 | bellard | s->ds = ds; |
664 | e7f0ad58 | bellard | consoles[nb_consoles++] = s; |
665 | e7f0ad58 | bellard | return s;
|
666 | e7f0ad58 | bellard | } |
667 | e7f0ad58 | bellard | |
668 | e7f0ad58 | bellard | int is_active_console(TextConsole *s)
|
669 | e7f0ad58 | bellard | { |
670 | e7f0ad58 | bellard | return s == active_console;
|
671 | e7f0ad58 | bellard | } |
672 | e7f0ad58 | bellard | |
673 | e7f0ad58 | bellard | CharDriverState *text_console_init(DisplayState *ds) |
674 | e7f0ad58 | bellard | { |
675 | e7f0ad58 | bellard | CharDriverState *chr; |
676 | e7f0ad58 | bellard | TextConsole *s; |
677 | e7f0ad58 | bellard | int i;
|
678 | e7f0ad58 | bellard | static int color_inited; |
679 | e7f0ad58 | bellard | |
680 | e7f0ad58 | bellard | chr = qemu_mallocz(sizeof(CharDriverState));
|
681 | e7f0ad58 | bellard | if (!chr)
|
682 | e7f0ad58 | bellard | return NULL; |
683 | e7f0ad58 | bellard | s = graphic_console_init(ds); |
684 | e7f0ad58 | bellard | if (!s) {
|
685 | e7f0ad58 | bellard | free(chr); |
686 | e7f0ad58 | bellard | return NULL; |
687 | e7f0ad58 | bellard | } |
688 | e7f0ad58 | bellard | s->text_console = 1;
|
689 | e7f0ad58 | bellard | chr->opaque = s; |
690 | e7f0ad58 | bellard | chr->chr_write = console_puts; |
691 | e7f0ad58 | bellard | chr->chr_add_read_handler = console_chr_add_read_handler; |
692 | e7f0ad58 | bellard | if (!color_inited) {
|
693 | e7f0ad58 | bellard | color_inited = 1;
|
694 | e7f0ad58 | bellard | for(i = 0; i < 8; i++) { |
695 | e7f0ad58 | bellard | color_table[i] = col_expand(s->ds, |
696 | e7f0ad58 | bellard | vga_get_color(s->ds, color_table_rgb[i])); |
697 | e7f0ad58 | bellard | } |
698 | e7f0ad58 | bellard | } |
699 | e7f0ad58 | bellard | s->y_displayed = 0;
|
700 | e7f0ad58 | bellard | s->y_base = 0;
|
701 | e7f0ad58 | bellard | s->total_height = DEFAULT_BACKSCROLL; |
702 | e7f0ad58 | bellard | s->x = 0;
|
703 | e7f0ad58 | bellard | s->y = 0;
|
704 | e7f0ad58 | bellard | s->fgcol = 7;
|
705 | e7f0ad58 | bellard | s->bgcol = 0;
|
706 | e7f0ad58 | bellard | s->g_width = s->ds->width; |
707 | e7f0ad58 | bellard | s->g_height = s->ds->height; |
708 | e7f0ad58 | bellard | text_console_resize(s); |
709 | e7f0ad58 | bellard | |
710 | e7f0ad58 | bellard | return chr;
|
711 | e7f0ad58 | bellard | } |