symbian-qemu-0.9.1-12/qemu-symbian-svp/console.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * QEMU graphical console
       
     3  *
       
     4  * Copyright (c) 2004 Fabrice Bellard
       
     5  *
       
     6  * Permission is hereby granted, free of charge, to any person obtaining a copy
       
     7  * of this software and associated documentation files (the "Software"), to deal
       
     8  * in the Software without restriction, including without limitation the rights
       
     9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
    10  * copies of the Software, and to permit persons to whom the Software is
       
    11  * furnished to do so, subject to the following conditions:
       
    12  *
       
    13  * The above copyright notice and this permission notice shall be included in
       
    14  * all copies or substantial portions of the Software.
       
    15  *
       
    16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
       
    19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       
    21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
       
    22  * THE SOFTWARE.
       
    23  */
       
    24 #include "qemu-common.h"
       
    25 #include "console.h"
       
    26 #include "qemu-timer.h"
       
    27 #include "gui_host.h"
       
    28 
       
    29 //#define DEBUG_CONSOLE
       
    30 #define DEFAULT_BACKSCROLL 512
       
    31 #define DEFAULT_MONITOR_SIZE "800x600"
       
    32 
       
    33 #define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
       
    34 #define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff)
       
    35 
       
    36 typedef struct TextAttributes {
       
    37     uint8_t fgcol:4;
       
    38     uint8_t bgcol:4;
       
    39     uint8_t bold:1;
       
    40     uint8_t uline:1;
       
    41     uint8_t blink:1;
       
    42     uint8_t invers:1;
       
    43     uint8_t unvisible:1;
       
    44 } TextAttributes;
       
    45 
       
    46 typedef struct TextCell {
       
    47     uint8_t ch;
       
    48     TextAttributes t_attrib;
       
    49 } TextCell;
       
    50 
       
    51 #define MAX_ESC_PARAMS 3
       
    52 
       
    53 enum TTYState {
       
    54     TTY_STATE_NORM,
       
    55     TTY_STATE_ESC,
       
    56     TTY_STATE_CSI,
       
    57 };
       
    58 
       
    59 typedef struct QEMUFIFO {
       
    60     uint8_t *buf;
       
    61     int buf_size;
       
    62     int count, wptr, rptr;
       
    63 } QEMUFIFO;
       
    64 
       
    65 static int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
       
    66 {
       
    67     int l, len;
       
    68 
       
    69     l = f->buf_size - f->count;
       
    70     if (len1 > l)
       
    71         len1 = l;
       
    72     len = len1;
       
    73     while (len > 0) {
       
    74         l = f->buf_size - f->wptr;
       
    75         if (l > len)
       
    76             l = len;
       
    77         memcpy(f->buf + f->wptr, buf, l);
       
    78         f->wptr += l;
       
    79         if (f->wptr >= f->buf_size)
       
    80             f->wptr = 0;
       
    81         buf += l;
       
    82         len -= l;
       
    83     }
       
    84     f->count += len1;
       
    85     return len1;
       
    86 }
       
    87 
       
    88 static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
       
    89 {
       
    90     int l, len;
       
    91 
       
    92     if (len1 > f->count)
       
    93         len1 = f->count;
       
    94     len = len1;
       
    95     while (len > 0) {
       
    96         l = f->buf_size - f->rptr;
       
    97         if (l > len)
       
    98             l = len;
       
    99         memcpy(buf, f->buf + f->rptr, l);
       
   100         f->rptr += l;
       
   101         if (f->rptr >= f->buf_size)
       
   102             f->rptr = 0;
       
   103         buf += l;
       
   104         len -= l;
       
   105     }
       
   106     f->count -= len1;
       
   107     return len1;
       
   108 }
       
   109 
       
   110 struct TextConsole {
       
   111     int fixed_size;
       
   112     DisplayState *ds;
       
   113     /* Graphic console state.  */
       
   114     vga_hw_text_update_ptr hw_text_update;
       
   115     void *hw;
       
   116 
       
   117     int g_width, g_height;
       
   118     int width;
       
   119     int height;
       
   120     int total_height;
       
   121     int backscroll_height;
       
   122     int x, y;
       
   123     int x_saved, y_saved;
       
   124     int y_displayed;
       
   125     int y_base;
       
   126     TextAttributes t_attrib_default; /* default text attributes */
       
   127     TextAttributes t_attrib; /* currently active text attributes */
       
   128     TextCell *cells;
       
   129     int text_x[2], text_y[2], cursor_invalidate;
       
   130 
       
   131     enum TTYState state;
       
   132     int esc_params[MAX_ESC_PARAMS];
       
   133     int nb_esc_params;
       
   134 
       
   135     CharDriverState *chr;
       
   136     /* fifo for key pressed */
       
   137     QEMUFIFO out_fifo;
       
   138     uint8_t out_fifo_buf[16];
       
   139     QEMUTimer *kbd_timer;
       
   140 };
       
   141 
       
   142 /* convert a RGBA color to a color index usable in graphic primitives */
       
   143 static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
       
   144 {
       
   145     unsigned int r, g, b, color;
       
   146 
       
   147     switch(ds_get_bits_per_pixel(ds)) {
       
   148 #if 0
       
   149     case 8:
       
   150         r = (rgba >> 16) & 0xff;
       
   151         g = (rgba >> 8) & 0xff;
       
   152         b = (rgba) & 0xff;
       
   153         color = (rgb_to_index[r] * 6 * 6) +
       
   154             (rgb_to_index[g] * 6) +
       
   155             (rgb_to_index[b]);
       
   156         break;
       
   157 #endif
       
   158     case 15:
       
   159         r = (rgba >> 16) & 0xff;
       
   160         g = (rgba >> 8) & 0xff;
       
   161         b = (rgba) & 0xff;
       
   162         color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
       
   163         break;
       
   164     case 16:
       
   165         r = (rgba >> 16) & 0xff;
       
   166         g = (rgba >> 8) & 0xff;
       
   167         b = (rgba) & 0xff;
       
   168         color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
       
   169         break;
       
   170     case 32:
       
   171     default:
       
   172         color = rgba;
       
   173         break;
       
   174     }
       
   175     return color;
       
   176 }
       
   177 
       
   178 static void vga_fill_rect (DisplayState *ds,
       
   179                            int posx, int posy, int width, int height, uint32_t color)
       
   180 {
       
   181     uint8_t *d, *d1;
       
   182     int x, y, bpp;
       
   183 
       
   184     bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
       
   185     d1 = ds_get_data(ds) +
       
   186         ds_get_linesize(ds) * posy + bpp * posx;
       
   187     for (y = 0; y < height; y++) {
       
   188         d = d1;
       
   189         switch(bpp) {
       
   190         case 1:
       
   191             for (x = 0; x < width; x++) {
       
   192                 *((uint8_t *)d) = color;
       
   193                 d++;
       
   194             }
       
   195             break;
       
   196         case 2:
       
   197             for (x = 0; x < width; x++) {
       
   198                 *((uint16_t *)d) = color;
       
   199                 d += 2;
       
   200             }
       
   201             break;
       
   202         case 4:
       
   203             for (x = 0; x < width; x++) {
       
   204                 *((uint32_t *)d) = color;
       
   205                 d += 4;
       
   206             }
       
   207             break;
       
   208         }
       
   209         d1 += ds_get_linesize(ds);
       
   210     }
       
   211 }
       
   212 
       
   213 /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
       
   214 static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h)
       
   215 {
       
   216     const uint8_t *s;
       
   217     uint8_t *d;
       
   218     int wb, y, bpp;
       
   219 
       
   220     bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
       
   221     wb = w * bpp;
       
   222     if (yd <= ys) {
       
   223         s = ds_get_data(ds) +
       
   224             ds_get_linesize(ds) * ys + bpp * xs;
       
   225         d = ds_get_data(ds) +
       
   226             ds_get_linesize(ds) * yd + bpp * xd;
       
   227         for (y = 0; y < h; y++) {
       
   228             memmove(d, s, wb);
       
   229             d += ds_get_linesize(ds);
       
   230             s += ds_get_linesize(ds);
       
   231         }
       
   232     } else {
       
   233         s = ds_get_data(ds) +
       
   234             ds_get_linesize(ds) * (ys + h - 1) + bpp * xs;
       
   235         d = ds_get_data(ds) +
       
   236             ds_get_linesize(ds) * (yd + h - 1) + bpp * xd;
       
   237        for (y = 0; y < h; y++) {
       
   238             memmove(d, s, wb);
       
   239             d -= ds_get_linesize(ds);
       
   240             s -= ds_get_linesize(ds);
       
   241         }
       
   242     }
       
   243 }
       
   244 
       
   245 /***********************************************************/
       
   246 /* basic char display */
       
   247 
       
   248 #define FONT_HEIGHT 16
       
   249 #define FONT_WIDTH 8
       
   250 
       
   251 #include "vgafont.h"
       
   252 
       
   253 #define cbswap_32(__x) \
       
   254 ((uint32_t)( \
       
   255 		(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
       
   256 		(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
       
   257 		(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
       
   258 		(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
       
   259 
       
   260 #ifdef WORDS_BIGENDIAN
       
   261 #define PAT(x) x
       
   262 #else
       
   263 #define PAT(x) cbswap_32(x)
       
   264 #endif
       
   265 
       
   266 static const uint32_t dmask16[16] = {
       
   267     PAT(0x00000000),
       
   268     PAT(0x000000ff),
       
   269     PAT(0x0000ff00),
       
   270     PAT(0x0000ffff),
       
   271     PAT(0x00ff0000),
       
   272     PAT(0x00ff00ff),
       
   273     PAT(0x00ffff00),
       
   274     PAT(0x00ffffff),
       
   275     PAT(0xff000000),
       
   276     PAT(0xff0000ff),
       
   277     PAT(0xff00ff00),
       
   278     PAT(0xff00ffff),
       
   279     PAT(0xffff0000),
       
   280     PAT(0xffff00ff),
       
   281     PAT(0xffffff00),
       
   282     PAT(0xffffffff),
       
   283 };
       
   284 
       
   285 static const uint32_t dmask4[4] = {
       
   286     PAT(0x00000000),
       
   287     PAT(0x0000ffff),
       
   288     PAT(0xffff0000),
       
   289     PAT(0xffffffff),
       
   290 };
       
   291 
       
   292 static uint32_t color_table[2][8];
       
   293 
       
   294 enum color_names {
       
   295     COLOR_BLACK   = 0,
       
   296     COLOR_RED     = 1,
       
   297     COLOR_GREEN   = 2,
       
   298     COLOR_YELLOW  = 3,
       
   299     COLOR_BLUE    = 4,
       
   300     COLOR_MAGENTA = 5,
       
   301     COLOR_CYAN    = 6,
       
   302     COLOR_WHITE   = 7
       
   303 };
       
   304 
       
   305 static const uint32_t color_table_rgb[2][8] = {
       
   306     {   /* dark */
       
   307         QEMU_RGB(0x00, 0x00, 0x00),  /* black */
       
   308         QEMU_RGB(0xaa, 0x00, 0x00),  /* red */
       
   309         QEMU_RGB(0x00, 0xaa, 0x00),  /* green */
       
   310         QEMU_RGB(0xaa, 0xaa, 0x00),  /* yellow */
       
   311         QEMU_RGB(0x00, 0x00, 0xaa),  /* blue */
       
   312         QEMU_RGB(0xaa, 0x00, 0xaa),  /* magenta */
       
   313         QEMU_RGB(0x00, 0xaa, 0xaa),  /* cyan */
       
   314         QEMU_RGB(0xaa, 0xaa, 0xaa),  /* white */
       
   315     },
       
   316     {   /* bright */
       
   317         QEMU_RGB(0x00, 0x00, 0x00),  /* black */
       
   318         QEMU_RGB(0xff, 0x00, 0x00),  /* red */
       
   319         QEMU_RGB(0x00, 0xff, 0x00),  /* green */
       
   320         QEMU_RGB(0xff, 0xff, 0x00),  /* yellow */
       
   321         QEMU_RGB(0x00, 0x00, 0xff),  /* blue */
       
   322         QEMU_RGB(0xff, 0x00, 0xff),  /* magenta */
       
   323         QEMU_RGB(0x00, 0xff, 0xff),  /* cyan */
       
   324         QEMU_RGB(0xff, 0xff, 0xff),  /* white */
       
   325     }
       
   326 };
       
   327 
       
   328 static inline unsigned int col_expand(DisplayState *ds, unsigned int col)
       
   329 {
       
   330     switch(ds_get_bits_per_pixel(ds)) {
       
   331     case 8:
       
   332         col |= col << 8;
       
   333         col |= col << 16;
       
   334         break;
       
   335     case 15:
       
   336     case 16:
       
   337         col |= col << 16;
       
   338         break;
       
   339     default:
       
   340         break;
       
   341     }
       
   342 
       
   343     return col;
       
   344 }
       
   345 #ifdef DEBUG_CONSOLE
       
   346 static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
       
   347 {
       
   348     if (t_attrib->bold) {
       
   349         printf("b");
       
   350     } else {
       
   351         printf(" ");
       
   352     }
       
   353     if (t_attrib->uline) {
       
   354         printf("u");
       
   355     } else {
       
   356         printf(" ");
       
   357     }
       
   358     if (t_attrib->blink) {
       
   359         printf("l");
       
   360     } else {
       
   361         printf(" ");
       
   362     }
       
   363     if (t_attrib->invers) {
       
   364         printf("i");
       
   365     } else {
       
   366         printf(" ");
       
   367     }
       
   368     if (t_attrib->unvisible) {
       
   369         printf("n");
       
   370     } else {
       
   371         printf(" ");
       
   372     }
       
   373 
       
   374     printf(" fg: %d bg: %d ch:'%2X' '%c'\n", t_attrib->fgcol, t_attrib->bgcol, ch, ch);
       
   375 }
       
   376 #endif
       
   377 
       
   378 static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
       
   379                           TextAttributes *t_attrib)
       
   380 {
       
   381     uint8_t *d;
       
   382     const uint8_t *font_ptr;
       
   383     unsigned int font_data, linesize, xorcol, bpp;
       
   384     int i;
       
   385     unsigned int fgcol, bgcol;
       
   386 
       
   387 #ifdef DEBUG_CONSOLE
       
   388     printf("x: %2i y: %2i", x, y);
       
   389     console_print_text_attributes(t_attrib, ch);
       
   390 #endif
       
   391 
       
   392     if (t_attrib->invers) {
       
   393         bgcol = color_table[t_attrib->bold][t_attrib->fgcol];
       
   394         fgcol = color_table[t_attrib->bold][t_attrib->bgcol];
       
   395     } else {
       
   396         fgcol = color_table[t_attrib->bold][t_attrib->fgcol];
       
   397         bgcol = color_table[t_attrib->bold][t_attrib->bgcol];
       
   398     }
       
   399 
       
   400     bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
       
   401     d = ds_get_data(ds) +
       
   402         ds_get_linesize(ds) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
       
   403     linesize = ds_get_linesize(ds);
       
   404     font_ptr = vgafont16 + FONT_HEIGHT * ch;
       
   405     xorcol = bgcol ^ fgcol;
       
   406     switch(ds_get_bits_per_pixel(ds)) {
       
   407     case 8:
       
   408         for(i = 0; i < FONT_HEIGHT; i++) {
       
   409             font_data = *font_ptr++;
       
   410             if (t_attrib->uline
       
   411                 && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
       
   412                 font_data = 0xFFFF;
       
   413             }
       
   414             ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
       
   415             ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
       
   416             d += linesize;
       
   417         }
       
   418         break;
       
   419     case 16:
       
   420     case 15:
       
   421         for(i = 0; i < FONT_HEIGHT; i++) {
       
   422             font_data = *font_ptr++;
       
   423             if (t_attrib->uline
       
   424                 && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
       
   425                 font_data = 0xFFFF;
       
   426             }
       
   427             ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
       
   428             ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
       
   429             ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
       
   430             ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
       
   431             d += linesize;
       
   432         }
       
   433         break;
       
   434     case 32:
       
   435         for(i = 0; i < FONT_HEIGHT; i++) {
       
   436             font_data = *font_ptr++;
       
   437             if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
       
   438                 font_data = 0xFFFF;
       
   439             }
       
   440             ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
       
   441             ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
       
   442             ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
       
   443             ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
       
   444             ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
       
   445             ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
       
   446             ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
       
   447             ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
       
   448             d += linesize;
       
   449         }
       
   450         break;
       
   451     }
       
   452 }
       
   453 
       
   454 static void text_console_resize_int(TextConsole *s)
       
   455 {
       
   456     TextCell *cells, *c, *c1;
       
   457     int w1, x, y, last_width;
       
   458 
       
   459     last_width = s->width;
       
   460     s->width = s->g_width / FONT_WIDTH;
       
   461     s->height = s->g_height / FONT_HEIGHT;
       
   462 
       
   463     w1 = last_width;
       
   464     if (s->width < w1)
       
   465         w1 = s->width;
       
   466 
       
   467     cells = qemu_malloc(s->width * s->total_height * sizeof(TextCell));
       
   468     for(y = 0; y < s->total_height; y++) {
       
   469         c = &cells[y * s->width];
       
   470         if (w1 > 0) {
       
   471             c1 = &s->cells[y * last_width];
       
   472             for(x = 0; x < w1; x++) {
       
   473                 *c++ = *c1++;
       
   474             }
       
   475         }
       
   476         for(x = w1; x < s->width; x++) {
       
   477             c->ch = ' ';
       
   478             c->t_attrib = s->t_attrib_default;
       
   479             c++;
       
   480         }
       
   481     }
       
   482     qemu_free(s->cells);
       
   483     s->cells = cells;
       
   484 }
       
   485 
       
   486 static inline void text_update_xy(TextConsole *s, int x, int y)
       
   487 {
       
   488     s->text_x[0] = MIN(s->text_x[0], x);
       
   489     s->text_x[1] = MAX(s->text_x[1], x);
       
   490     s->text_y[0] = MIN(s->text_y[0], y);
       
   491     s->text_y[1] = MAX(s->text_y[1], y);
       
   492 }
       
   493 
       
   494 static void update_xy(TextConsole *s, int x, int y)
       
   495 {
       
   496     TextCell *c;
       
   497     int y1, y2;
       
   498 
       
   499     if (gui_is_display_active(s->ds)) {
       
   500         if (!ds_get_bits_per_pixel(s->ds)) {
       
   501             text_update_xy(s, x, y);
       
   502             return;
       
   503         }
       
   504 
       
   505         y1 = (s->y_base + y) % s->total_height;
       
   506         y2 = y1 - s->y_displayed;
       
   507         if (y2 < 0)
       
   508             y2 += s->total_height;
       
   509         if (y2 < s->height) {
       
   510             c = &s->cells[y1 * s->width + x];
       
   511             vga_putcharxy(s->ds, x, y2, c->ch,
       
   512                           &(c->t_attrib));
       
   513             dpy_update(s->ds, x * FONT_WIDTH, y2 * FONT_HEIGHT,
       
   514                        FONT_WIDTH, FONT_HEIGHT);
       
   515         }
       
   516     }
       
   517 }
       
   518 
       
   519 static void console_show_cursor(TextConsole *s, int show)
       
   520 {
       
   521     TextCell *c;
       
   522     int y, y1;
       
   523 
       
   524     if (gui_is_display_active(s->ds)) {
       
   525         int x = s->x;
       
   526 
       
   527         if (!ds_get_bits_per_pixel(s->ds)) {
       
   528             s->cursor_invalidate = 1;
       
   529             return;
       
   530         }
       
   531 
       
   532         if (x >= s->width) {
       
   533             x = s->width - 1;
       
   534         }
       
   535         y1 = (s->y_base + s->y) % s->total_height;
       
   536         y = y1 - s->y_displayed;
       
   537         if (y < 0)
       
   538             y += s->total_height;
       
   539         if (y < s->height) {
       
   540             c = &s->cells[y1 * s->width + x];
       
   541             if (show) {
       
   542                 TextAttributes t_attrib = s->t_attrib_default;
       
   543                 t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
       
   544                 vga_putcharxy(s->ds, x, y, c->ch, &t_attrib);
       
   545             } else {
       
   546                 vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib));
       
   547             }
       
   548             dpy_update(s->ds, x * FONT_WIDTH, y * FONT_HEIGHT,
       
   549                        FONT_WIDTH, FONT_HEIGHT);
       
   550         }
       
   551     }
       
   552 }
       
   553 
       
   554 static void console_refresh(TextConsole *s)
       
   555 {
       
   556     TextCell *c;
       
   557     int x, y, y1;
       
   558 
       
   559     if (!gui_is_display_active(s->ds))
       
   560         return;
       
   561     if (!ds_get_bits_per_pixel(s->ds)) {
       
   562         s->text_x[0] = 0;
       
   563         s->text_y[0] = 0;
       
   564         s->text_x[1] = s->width - 1;
       
   565         s->text_y[1] = s->height - 1;
       
   566         s->cursor_invalidate = 1;
       
   567         return;
       
   568     }
       
   569 
       
   570     vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
       
   571                   color_table[0][COLOR_BLACK]);
       
   572     y1 = s->y_displayed;
       
   573     for(y = 0; y < s->height; y++) {
       
   574         c = s->cells + y1 * s->width;
       
   575         for(x = 0; x < s->width; x++) {
       
   576             vga_putcharxy(s->ds, x, y, c->ch,
       
   577                           &(c->t_attrib));
       
   578             c++;
       
   579         }
       
   580         if (++y1 == s->total_height)
       
   581             y1 = 0;
       
   582     }
       
   583     dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
       
   584     console_show_cursor(s, 1);
       
   585 }
       
   586 
       
   587 static void console_scroll(TextConsole *s, int ydelta)
       
   588 {
       
   589     
       
   590     int i, y1;
       
   591 
       
   592     if (!s)
       
   593         return;
       
   594 
       
   595     if (ydelta > 0) {
       
   596         for(i = 0; i < ydelta; i++) {
       
   597             if (s->y_displayed == s->y_base)
       
   598                 break;
       
   599             if (++s->y_displayed == s->total_height)
       
   600                 s->y_displayed = 0;
       
   601         }
       
   602     } else {
       
   603         ydelta = -ydelta;
       
   604         i = s->backscroll_height;
       
   605         if (i > s->total_height - s->height)
       
   606             i = s->total_height - s->height;
       
   607         y1 = s->y_base - i;
       
   608         if (y1 < 0)
       
   609             y1 += s->total_height;
       
   610         for(i = 0; i < ydelta; i++) {
       
   611             if (s->y_displayed == y1)
       
   612                 break;
       
   613             if (--s->y_displayed < 0)
       
   614                 s->y_displayed = s->total_height - 1;
       
   615         }
       
   616     }
       
   617     console_refresh(s);
       
   618 }
       
   619 
       
   620 static void console_put_lf(TextConsole *s)
       
   621 {
       
   622     TextCell *c;
       
   623     int x, y1;
       
   624 
       
   625     s->y++;
       
   626     if (s->y >= s->height) {
       
   627         s->y = s->height - 1;
       
   628 
       
   629         if (s->y_displayed == s->y_base) {
       
   630             if (++s->y_displayed == s->total_height)
       
   631                 s->y_displayed = 0;
       
   632         }
       
   633         if (++s->y_base == s->total_height)
       
   634             s->y_base = 0;
       
   635         if (s->backscroll_height < s->total_height)
       
   636             s->backscroll_height++;
       
   637         y1 = (s->y_base + s->height - 1) % s->total_height;
       
   638         c = &s->cells[y1 * s->width];
       
   639         for(x = 0; x < s->width; x++) {
       
   640             c->ch = ' ';
       
   641             c->t_attrib = s->t_attrib_default;
       
   642             c++;
       
   643         }
       
   644         if (gui_is_display_active(s->ds) && s->y_displayed == s->y_base) {
       
   645             if (!ds_get_bits_per_pixel(s->ds)) {
       
   646                 s->text_x[0] = 0;
       
   647                 s->text_y[0] = 0;
       
   648                 s->text_x[1] = s->width - 1;
       
   649                 s->text_y[1] = s->height - 1;
       
   650                 return;
       
   651             }
       
   652 
       
   653             vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0,
       
   654                        s->width * FONT_WIDTH,
       
   655                        (s->height - 1) * FONT_HEIGHT);
       
   656             vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
       
   657                           s->width * FONT_WIDTH, FONT_HEIGHT,
       
   658                           color_table[0][s->t_attrib_default.bgcol]);
       
   659             dpy_update(s->ds, 0, 0,
       
   660                        s->width * FONT_WIDTH, s->height * FONT_HEIGHT);
       
   661         }
       
   662     }
       
   663 }
       
   664 
       
   665 /* Set console attributes depending on the current escape codes.
       
   666  * NOTE: I know this code is not very efficient (checking every color for it
       
   667  * self) but it is more readable and better maintainable.
       
   668  */
       
   669 static void console_handle_escape(TextConsole *s)
       
   670 {
       
   671     int i;
       
   672 
       
   673     for (i=0; i<s->nb_esc_params; i++) {
       
   674         switch (s->esc_params[i]) {
       
   675             case 0: /* reset all console attributes to default */
       
   676                 s->t_attrib = s->t_attrib_default;
       
   677                 break;
       
   678             case 1:
       
   679                 s->t_attrib.bold = 1;
       
   680                 break;
       
   681             case 4:
       
   682                 s->t_attrib.uline = 1;
       
   683                 break;
       
   684             case 5:
       
   685                 s->t_attrib.blink = 1;
       
   686                 break;
       
   687             case 7:
       
   688                 s->t_attrib.invers = 1;
       
   689                 break;
       
   690             case 8:
       
   691                 s->t_attrib.unvisible = 1;
       
   692                 break;
       
   693             case 22:
       
   694                 s->t_attrib.bold = 0;
       
   695                 break;
       
   696             case 24:
       
   697                 s->t_attrib.uline = 0;
       
   698                 break;
       
   699             case 25:
       
   700                 s->t_attrib.blink = 0;
       
   701                 break;
       
   702             case 27:
       
   703                 s->t_attrib.invers = 0;
       
   704                 break;
       
   705             case 28:
       
   706                 s->t_attrib.unvisible = 0;
       
   707                 break;
       
   708             /* set foreground color */
       
   709             case 30:
       
   710                 s->t_attrib.fgcol=COLOR_BLACK;
       
   711                 break;
       
   712             case 31:
       
   713                 s->t_attrib.fgcol=COLOR_RED;
       
   714                 break;
       
   715             case 32:
       
   716                 s->t_attrib.fgcol=COLOR_GREEN;
       
   717                 break;
       
   718             case 33:
       
   719                 s->t_attrib.fgcol=COLOR_YELLOW;
       
   720                 break;
       
   721             case 34:
       
   722                 s->t_attrib.fgcol=COLOR_BLUE;
       
   723                 break;
       
   724             case 35:
       
   725                 s->t_attrib.fgcol=COLOR_MAGENTA;
       
   726                 break;
       
   727             case 36:
       
   728                 s->t_attrib.fgcol=COLOR_CYAN;
       
   729                 break;
       
   730             case 37:
       
   731                 s->t_attrib.fgcol=COLOR_WHITE;
       
   732                 break;
       
   733             /* set background color */
       
   734             case 40:
       
   735                 s->t_attrib.bgcol=COLOR_BLACK;
       
   736                 break;
       
   737             case 41:
       
   738                 s->t_attrib.bgcol=COLOR_RED;
       
   739                 break;
       
   740             case 42:
       
   741                 s->t_attrib.bgcol=COLOR_GREEN;
       
   742                 break;
       
   743             case 43:
       
   744                 s->t_attrib.bgcol=COLOR_YELLOW;
       
   745                 break;
       
   746             case 44:
       
   747                 s->t_attrib.bgcol=COLOR_BLUE;
       
   748                 break;
       
   749             case 45:
       
   750                 s->t_attrib.bgcol=COLOR_MAGENTA;
       
   751                 break;
       
   752             case 46:
       
   753                 s->t_attrib.bgcol=COLOR_CYAN;
       
   754                 break;
       
   755             case 47:
       
   756                 s->t_attrib.bgcol=COLOR_WHITE;
       
   757                 break;
       
   758         }
       
   759     }
       
   760 }
       
   761 
       
   762 static void console_clear_xy(TextConsole *s, int x, int y)
       
   763 {
       
   764     int y1 = (s->y_base + y) % s->total_height;
       
   765     TextCell *c = &s->cells[y1 * s->width + x];
       
   766     c->ch = ' ';
       
   767     c->t_attrib = s->t_attrib_default;
       
   768     c++;
       
   769     update_xy(s, x, y);
       
   770 }
       
   771 
       
   772 static void console_putchar(TextConsole *s, int ch)
       
   773 {
       
   774     TextCell *c;
       
   775     int y1, i;
       
   776     int x, y;
       
   777 
       
   778     switch(s->state) {
       
   779     case TTY_STATE_NORM:
       
   780         switch(ch) {
       
   781         case '\r':  /* carriage return */
       
   782             s->x = 0;
       
   783             break;
       
   784         case '\n':  /* newline */
       
   785             console_put_lf(s);
       
   786             break;
       
   787         case '\b':  /* backspace */
       
   788             if (s->x > 0)
       
   789                 s->x--;
       
   790             break;
       
   791         case '\t':  /* tabspace */
       
   792             if (s->x + (8 - (s->x % 8)) > s->width) {
       
   793                 s->x = 0;
       
   794                 console_put_lf(s);
       
   795             } else {
       
   796                 s->x = s->x + (8 - (s->x % 8));
       
   797             }
       
   798             break;
       
   799         case '\a':  /* alert aka. bell */
       
   800             /* TODO: has to be implemented */
       
   801             break;
       
   802         case 14:
       
   803             /* SI (shift in), character set 0 (ignored) */
       
   804             break;
       
   805         case 15:
       
   806             /* SO (shift out), character set 1 (ignored) */
       
   807             break;
       
   808         case 27:    /* esc (introducing an escape sequence) */
       
   809             s->state = TTY_STATE_ESC;
       
   810             break;
       
   811         default:
       
   812             if (s->x >= s->width) {
       
   813                 /* line wrap */
       
   814                 s->x = 0;
       
   815                 console_put_lf(s);
       
   816             }
       
   817             y1 = (s->y_base + s->y) % s->total_height;
       
   818             c = &s->cells[y1 * s->width + s->x];
       
   819             c->ch = ch;
       
   820             c->t_attrib = s->t_attrib;
       
   821             update_xy(s, s->x, s->y);
       
   822             s->x++;
       
   823             break;
       
   824         }
       
   825         break;
       
   826     case TTY_STATE_ESC: /* check if it is a terminal escape sequence */
       
   827         if (ch == '[') {
       
   828             for(i=0;i<MAX_ESC_PARAMS;i++)
       
   829                 s->esc_params[i] = 0;
       
   830             s->nb_esc_params = 0;
       
   831             s->state = TTY_STATE_CSI;
       
   832         } else {
       
   833             s->state = TTY_STATE_NORM;
       
   834         }
       
   835         break;
       
   836     case TTY_STATE_CSI: /* handle escape sequence parameters */
       
   837         if (ch >= '0' && ch <= '9') {
       
   838             if (s->nb_esc_params < MAX_ESC_PARAMS) {
       
   839                 s->esc_params[s->nb_esc_params] =
       
   840                     s->esc_params[s->nb_esc_params] * 10 + ch - '0';
       
   841             }
       
   842         } else {
       
   843             s->nb_esc_params++;
       
   844             if (ch == ';')
       
   845                 break;
       
   846 #ifdef DEBUG_CONSOLE
       
   847             fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
       
   848                     s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
       
   849 #endif
       
   850             s->state = TTY_STATE_NORM;
       
   851             switch(ch) {
       
   852             case 'A':
       
   853                 /* move cursor up */
       
   854                 if (s->esc_params[0] == 0) {
       
   855                     s->esc_params[0] = 1;
       
   856                 }
       
   857                 s->y -= s->esc_params[0];
       
   858                 if (s->y < 0) {
       
   859                     s->y = 0;
       
   860                 }
       
   861                 break;
       
   862             case 'B':
       
   863                 /* move cursor down */
       
   864                 if (s->esc_params[0] == 0) {
       
   865                     s->esc_params[0] = 1;
       
   866                 }
       
   867                 s->y += s->esc_params[0];
       
   868                 if (s->y >= s->height) {
       
   869                     s->y = s->height - 1;
       
   870                 }
       
   871                 break;
       
   872             case 'C':
       
   873                 /* move cursor right */
       
   874                 if (s->esc_params[0] == 0) {
       
   875                     s->esc_params[0] = 1;
       
   876                 }
       
   877                 s->x += s->esc_params[0];
       
   878                 if (s->x >= s->width) {
       
   879                     s->x = s->width - 1;
       
   880                 }
       
   881                 break;
       
   882             case 'D':
       
   883                 /* move cursor left */
       
   884                 if (s->esc_params[0] == 0) {
       
   885                     s->esc_params[0] = 1;
       
   886                 }
       
   887                 s->x -= s->esc_params[0];
       
   888                 if (s->x < 0) {
       
   889                     s->x = 0;
       
   890                 }
       
   891                 break;
       
   892             case 'G':
       
   893                 /* move cursor to column */
       
   894                 s->x = s->esc_params[0] - 1;
       
   895                 if (s->x < 0) {
       
   896                     s->x = 0;
       
   897                 }
       
   898                 break;
       
   899             case 'f':
       
   900             case 'H':
       
   901                 /* move cursor to row, column */
       
   902                 s->x = s->esc_params[1] - 1;
       
   903                 if (s->x < 0) {
       
   904                     s->x = 0;
       
   905                 }
       
   906                 s->y = s->esc_params[0] - 1;
       
   907                 if (s->y < 0) {
       
   908                     s->y = 0;
       
   909                 }
       
   910                 break;
       
   911             case 'J':
       
   912                 switch (s->esc_params[0]) {
       
   913                 case 0:
       
   914                     /* clear to end of screen */
       
   915                     for (y = s->y; y < s->height; y++) {
       
   916                         for (x = 0; x < s->width; x++) {
       
   917                             if (y == s->y && x < s->x) {
       
   918                                 continue;
       
   919                             }
       
   920                             console_clear_xy(s, x, y);
       
   921                         }
       
   922                     }
       
   923                     break;
       
   924                 case 1:
       
   925                     /* clear from beginning of screen */
       
   926                     for (y = 0; y <= s->y; y++) {
       
   927                         for (x = 0; x < s->width; x++) {
       
   928                             if (y == s->y && x > s->x) {
       
   929                                 break;
       
   930                             }
       
   931                             console_clear_xy(s, x, y);
       
   932                         }
       
   933                     }
       
   934                     break;
       
   935                 case 2:
       
   936                     /* clear entire screen */
       
   937                     for (y = 0; y <= s->height; y++) {
       
   938                         for (x = 0; x < s->width; x++) {
       
   939                             console_clear_xy(s, x, y);
       
   940                         }
       
   941                     }
       
   942                 break;
       
   943                 }
       
   944             case 'K':
       
   945                 switch (s->esc_params[0]) {
       
   946                 case 0:
       
   947                 /* clear to eol */
       
   948                 for(x = s->x; x < s->width; x++) {
       
   949                         console_clear_xy(s, x, s->y);
       
   950                 }
       
   951                 break;
       
   952                 case 1:
       
   953                     /* clear from beginning of line */
       
   954                     for (x = 0; x <= s->x; x++) {
       
   955                         console_clear_xy(s, x, s->y);
       
   956                     }
       
   957                     break;
       
   958                 case 2:
       
   959                     /* clear entire line */
       
   960                     for(x = 0; x < s->width; x++) {
       
   961                         console_clear_xy(s, x, s->y);
       
   962                     }
       
   963                 break;
       
   964             }
       
   965                 break;
       
   966             case 'm':
       
   967             console_handle_escape(s);
       
   968             break;
       
   969             case 'n':
       
   970                 /* report cursor position */
       
   971                 /* TODO: send ESC[row;colR */
       
   972                 break;
       
   973             case 's':
       
   974                 /* save cursor position */
       
   975                 s->x_saved = s->x;
       
   976                 s->y_saved = s->y;
       
   977                 break;
       
   978             case 'u':
       
   979                 /* restore cursor position */
       
   980                 s->x = s->x_saved;
       
   981                 s->y = s->y_saved;
       
   982                 break;
       
   983             default:
       
   984 #ifdef DEBUG_CONSOLE
       
   985                 fprintf(stderr, "unhandled escape character '%c'\n", ch);
       
   986 #endif
       
   987                 break;
       
   988             }
       
   989             break;
       
   990         }
       
   991     }
       
   992 }
       
   993 
       
   994 static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
       
   995 {
       
   996     TextConsole *s = chr->opaque;
       
   997     int i;
       
   998 
       
   999     console_show_cursor(s, 0);
       
  1000     for(i = 0; i < len; i++) {
       
  1001         console_putchar(s, buf[i]);
       
  1002     }
       
  1003     console_show_cursor(s, 1);
       
  1004     return len;
       
  1005 }
       
  1006 
       
  1007 static void console_send_event(CharDriverState *chr, int event)
       
  1008 {
       
  1009     TextConsole *s = chr->opaque;
       
  1010 
       
  1011     if (event == CHR_EVENT_FOCUS) {
       
  1012         gui_notify_activate_display(s->ds);
       
  1013     }
       
  1014 }
       
  1015 
       
  1016 static void kbd_send_chars(void *opaque)
       
  1017 {
       
  1018     TextConsole *s = opaque;
       
  1019     int len;
       
  1020     uint8_t buf[16];
       
  1021 
       
  1022     len = qemu_chr_can_read(s->chr);
       
  1023     if (len > s->out_fifo.count)
       
  1024         len = s->out_fifo.count;
       
  1025     if (len > 0) {
       
  1026         if (len > sizeof(buf))
       
  1027             len = sizeof(buf);
       
  1028         qemu_fifo_read(&s->out_fifo, buf, len);
       
  1029         qemu_chr_read(s->chr, buf, len);
       
  1030     }
       
  1031     /* characters are pending: we send them a bit later (XXX:
       
  1032        horrible, should change char device API) */
       
  1033     if (s->out_fifo.count > 0) {
       
  1034         qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
       
  1035     }
       
  1036 }
       
  1037 
       
  1038 /* called when an ascii key is pressed */
       
  1039 static void kbd_put_keysym(void *opaque, int keysym)
       
  1040 {
       
  1041     TextConsole * const s = opaque;
       
  1042     uint8_t buf[16], *q;
       
  1043     int c;
       
  1044 
       
  1045     if (!s)
       
  1046         return;
       
  1047 
       
  1048     switch(keysym) {
       
  1049     case QEMU_KEY_CTRL_UP:
       
  1050         console_scroll(s, -1);
       
  1051         break;
       
  1052     case QEMU_KEY_CTRL_DOWN:
       
  1053         console_scroll(s, 1);
       
  1054         break;
       
  1055     case QEMU_KEY_CTRL_PAGEUP:
       
  1056         console_scroll(s, -10);
       
  1057         break;
       
  1058     case QEMU_KEY_CTRL_PAGEDOWN:
       
  1059         console_scroll(s, 10);
       
  1060         break;
       
  1061     default:
       
  1062         /* convert the QEMU keysym to VT100 key string */
       
  1063         q = buf;
       
  1064         if (keysym >= 0xe100 && keysym <= 0xe11f) {
       
  1065             *q++ = '\033';
       
  1066             *q++ = '[';
       
  1067             c = keysym - 0xe100;
       
  1068             if (c >= 10)
       
  1069                 *q++ = '0' + (c / 10);
       
  1070             *q++ = '0' + (c % 10);
       
  1071             *q++ = '~';
       
  1072         } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
       
  1073             *q++ = '\033';
       
  1074             *q++ = '[';
       
  1075             *q++ = keysym & 0xff;
       
  1076         } else {
       
  1077                 *q++ = keysym;
       
  1078         }
       
  1079         if (s->chr->chr_read) {
       
  1080             qemu_fifo_write(&s->out_fifo, buf, q - buf);
       
  1081             kbd_send_chars(s);
       
  1082         }
       
  1083         break;
       
  1084     }
       
  1085 }
       
  1086 
       
  1087 static void text_console_invalidate(void *opaque)
       
  1088 {
       
  1089     TextConsole *s = (TextConsole *) opaque;
       
  1090 
       
  1091     if (s->g_width != ds_get_width(s->ds) || s->g_height != ds_get_height(s->ds)) {
       
  1092         if (s->fixed_size) {
       
  1093             gui_resize_vt(s->ds, s->g_width, s->g_height);
       
  1094         } else {
       
  1095             s->g_width = ds_get_width(s->ds);
       
  1096             s->g_height = ds_get_height(s->ds);
       
  1097             text_console_resize_int(s);
       
  1098         }
       
  1099     }
       
  1100     console_refresh(s);
       
  1101 }
       
  1102 
       
  1103 static void text_console_update(void *opaque, console_ch_t *chardata)
       
  1104 {
       
  1105     TextConsole *s = (TextConsole *) opaque;
       
  1106     int i, j, src;
       
  1107 
       
  1108     if (s->text_x[0] <= s->text_x[1]) {
       
  1109         src = (s->y_base + s->text_y[0]) * s->width;
       
  1110         chardata += s->text_y[0] * s->width;
       
  1111         for (i = s->text_y[0]; i <= s->text_y[1]; i ++)
       
  1112             for (j = 0; j < s->width; j ++, src ++)
       
  1113                 console_write_ch(chardata ++, s->cells[src].ch |
       
  1114                                 (s->cells[src].t_attrib.fgcol << 12) |
       
  1115                                 (s->cells[src].t_attrib.bgcol << 8) |
       
  1116                                 (s->cells[src].t_attrib.bold << 21));
       
  1117         dpy_update(s->ds, s->text_x[0], s->text_y[0],
       
  1118                    s->text_x[1] - s->text_x[0], i - s->text_y[0]);
       
  1119         s->text_x[0] = s->width;
       
  1120         s->text_y[0] = s->height;
       
  1121         s->text_x[1] = 0;
       
  1122         s->text_y[1] = 0;
       
  1123     }
       
  1124     if (s->cursor_invalidate) {
       
  1125         dpy_cursor(s->ds, s->x, s->y);
       
  1126         s->cursor_invalidate = 0;
       
  1127     }
       
  1128 }
       
  1129 
       
  1130 int is_fixed_size_console(const TextConsole *console)
       
  1131 {
       
  1132     return console->fixed_size;
       
  1133 }
       
  1134 
       
  1135 void console_color_init(DisplayState *ds)
       
  1136 {
       
  1137     int i, j;
       
  1138     for (j = 0; j < 2; j++) {
       
  1139         for (i = 0; i < 8; i++) {
       
  1140             color_table[j][i] = col_expand(ds, 
       
  1141                    vga_get_color(ds, color_table_rgb[j][i]));
       
  1142         }
       
  1143     }
       
  1144 }
       
  1145 
       
  1146 CharDriverState *text_console_init(DisplayState *ds, const char *p)
       
  1147 {
       
  1148     CharDriverState *chr;
       
  1149     TextConsole *s;
       
  1150     unsigned width;
       
  1151     unsigned height;
       
  1152     static int color_inited;
       
  1153     const int fixed_size = (p != 0);
       
  1154 
       
  1155     chr = qemu_mallocz(sizeof(CharDriverState));
       
  1156     if (!chr)
       
  1157         return NULL;
       
  1158 
       
  1159     s = qemu_mallocz(sizeof(TextConsole));
       
  1160     if (!s) {
       
  1161         free(chr);
       
  1162         return NULL;
       
  1163     }
       
  1164     s->ds = ds;
       
  1165     s->fixed_size = fixed_size;
       
  1166 
       
  1167     chr->opaque = s;
       
  1168     chr->chr_write = console_puts;
       
  1169     chr->chr_send_event = console_send_event;
       
  1170 
       
  1171     s->chr = chr;
       
  1172     s->out_fifo.buf = s->out_fifo_buf;
       
  1173     s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
       
  1174     s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
       
  1175     gui_register_vt_key_callback(s->ds, kbd_put_keysym, s);
       
  1176 
       
  1177     if (!color_inited) {
       
  1178         color_inited = 1;
       
  1179         console_color_init(s->ds);
       
  1180     }
       
  1181     s->y_displayed = 0;
       
  1182     s->y_base = 0;
       
  1183     s->total_height = DEFAULT_BACKSCROLL;
       
  1184     s->x = 0;
       
  1185     s->y = 0;
       
  1186     width = ds_get_width(s->ds);
       
  1187     height = ds_get_height(s->ds);
       
  1188     if (p != 0) {
       
  1189         width = strtoul(p, (char **)&p, 10);
       
  1190         if (*p == 'C') {
       
  1191             p++;
       
  1192             width *= FONT_WIDTH;
       
  1193         }
       
  1194         if (*p == 'x') {
       
  1195             p++;
       
  1196             height = strtoul(p, (char **)&p, 10);
       
  1197             if (*p == 'C') {
       
  1198                 p++;
       
  1199                 height *= FONT_HEIGHT;
       
  1200             }
       
  1201         }
       
  1202     }
       
  1203     s->g_width = width;
       
  1204     s->g_height = height;
       
  1205 
       
  1206 #if 0
       
  1207     s->hw_invalidate = text_console_invalidate;
       
  1208 #endif
       
  1209     gui_set_paint_callbacks(s->ds, NULL, text_console_invalidate, NULL, s);
       
  1210     s->hw_text_update = text_console_update;
       
  1211     s->hw = s;
       
  1212 
       
  1213     /* Set text attribute defaults */
       
  1214     s->t_attrib_default.bold = 0;
       
  1215     s->t_attrib_default.uline = 0;
       
  1216     s->t_attrib_default.blink = 0;
       
  1217     s->t_attrib_default.invers = 0;
       
  1218     s->t_attrib_default.unvisible = 0;
       
  1219     s->t_attrib_default.fgcol = COLOR_WHITE;
       
  1220     s->t_attrib_default.bgcol = COLOR_BLACK;
       
  1221 
       
  1222     /* set current text attributes to default */
       
  1223     s->t_attrib = s->t_attrib_default;
       
  1224     text_console_resize_int(s);
       
  1225 
       
  1226     qemu_chr_reset(chr);
       
  1227 
       
  1228     return chr;
       
  1229 }
       
  1230 
       
  1231 CharDriverState *new_text_console(const char *p)
       
  1232 {
       
  1233     DisplayState * const ds = gui_new_vt(SKINLESS_TEXT_VT_PRIORITY_ORDER);
       
  1234 
       
  1235     if (ds != NULL)
       
  1236         return text_console_init(ds, p);
       
  1237     else
       
  1238         return NULL;
       
  1239 }
       
  1240 
       
  1241 /* Just for unloaded GUIs. gui_resize can be used instead */
       
  1242 void text_console_resize(TextConsole *console, int width, int height)
       
  1243 {
       
  1244     if (gui_resize_vt(console->ds, width, height)) {
       
  1245         console->g_width = width;
       
  1246         console->g_height = height;
       
  1247     }
       
  1248 }
       
  1249 
       
  1250 void text_console_copy(TextConsole *console, int src_x, int src_y,
       
  1251                 int dst_x, int dst_y, int w, int h)
       
  1252 {
       
  1253     if (gui_is_display_active(console->ds)) {
       
  1254         if (console->ds->dpy_copy)
       
  1255             console->ds->dpy_copy(console->ds,
       
  1256                             src_x, src_y, dst_x, dst_y, w, h);
       
  1257         else {
       
  1258             /* TODO */
       
  1259             console->ds->dpy_update(console->ds, dst_x, dst_y, w, h);
       
  1260         }
       
  1261     }
       
  1262 }
       
  1263