Annotation of qemu/console.c, revision 1.1.1.5

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

unix.superglobalmegacorp.com