Annotation of qemu/console.c, revision 1.1.1.4

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

unix.superglobalmegacorp.com