Annotation of qemu/console.c, revision 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