Annotation of qemu/console.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com