Annotation of qemu/roms/openbios/libopenbios/console_common.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *     <console.c>
                      3:  *
                      4:  *     Simple text console
                      5:  *
                      6:  *   Copyright (C) 2002, 2003 Samuel Rydh ([email protected])
                      7:  *   Copyright (C) 2005 Stefan Reinauer <[email protected]>
                      8:  *
                      9:  *   This program is free software; you can redistribute it and/or
                     10:  *   modify it under the terms of the GNU General Public License
                     11:  *   as published by the Free Software Foundation
                     12:  *
                     13:  */
                     14: 
                     15: #include "config.h"
                     16: #include "libopenbios/bindings.h"
                     17: #include "libopenbios/fontdata.h"
                     18: #include "libopenbios/console.h"
                     19: #include "packages/video.h"
                     20: 
                     21: #define FONT_ADJ_HEIGHT         (FONT_HEIGHT + 2)
                     22: 
                     23: // Warning: will hang on purpose when encountering unknown codes
                     24: //#define DEBUG_CONSOLE
                     25: #ifdef DEBUG_CONSOLE
                     26: #define DPRINTF(fmt, args...)                   \
                     27:     do {                                        \
                     28:         printk(fmt , ##args);                   \
                     29:         for (;;);                               \
                     30:     } while (0)
                     31: #else
                     32: #define DPRINTF(fmt, args...) do {} while(0)
                     33: #endif
                     34: 
                     35: typedef enum {
                     36:     ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
                     37:     EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
                     38:     ESpalette
                     39: } vc_state_t;
                     40: 
                     41: #define NPAR 16
                     42: static struct {
                     43:        int     inited;
                     44:        int     physw, physh;
                     45:        int     w,h;
                     46: 
                     47:        int     x,y;
                     48:        char    *buf;
                     49: 
                     50:        int     cursor_on;
                     51:        vc_state_t vc_state;
                     52:        unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current
                     53:                                               escape sequence */
                     54: } cons;
                     55: 
                     56: static int
                     57: get_conschar( int x, int y )
                     58: {
                     59:        if( (unsigned int)x < cons.w && (unsigned int)y < cons.h )
                     60:                return cons.buf[y*cons.w + x];
                     61:        return ' ';
                     62: }
                     63: 
                     64: static void
                     65: draw_char( unsigned int h, unsigned int v )
                     66: {
                     67:         const unsigned char *c = fontdata;
                     68:        int x, y, xx, rskip, m;
                     69:        int invert = (h==cons.x && v==cons.y && cons.cursor_on);
                     70:        int ch = get_conschar( h, v );
                     71: 
                     72:        while( h >= cons.w || v >= cons.h )
                     73:                return;
                     74: 
                     75:        h *= FONT_WIDTH;
                     76:        v *= FONT_ADJ_HEIGHT;
                     77: 
                     78:        rskip = (FONT_WIDTH > 8)? 2 : 1;
                     79:        c += rskip * (unsigned int)(ch & 0xff) * FONT_HEIGHT;
                     80: 
                     81:        for( x=0; x<FONT_WIDTH; x++ ) {
                     82:                xx = x % 8;
                     83:                if( x && !xx )
                     84:                        c++;
                     85:                m = (1<<(7-xx));
                     86:                for( y=0; y<FONT_HEIGHT; y++ ){
                     87:                        int col = ((!(c[rskip*y] & m)) != invert) ? 254 : 0;
                     88:                        draw_pixel( h+x, v+y+1, col );
                     89:                }
                     90:                draw_pixel( h+x, v, 254 );
                     91:                draw_pixel( h+x, v+FONT_HEIGHT+1, 254 );
                     92:        }
                     93: }
                     94: 
                     95: static void
                     96: show_cursor( int show )
                     97: {
                     98:        if( cons.cursor_on == show )
                     99:                return;
                    100:        cons.cursor_on = show;
                    101:        draw_char( cons.x, cons.y );
                    102: }
                    103: 
                    104: 
                    105: static void
                    106: draw_line( int n )
                    107: {
                    108:        int i;
                    109: 
                    110:        if( n >= cons.h || n < 0 )
                    111:                return;
                    112:        for( i=0; i<cons.w; i++ )
                    113:                draw_char( i, n );
                    114: }
                    115: 
                    116: #if 0
                    117: static void
                    118: refresh( void )
                    119: {
                    120:        int i;
                    121:        for( i=0; i<cons.h; i++ )
                    122:                draw_line(i);
                    123: }
                    124: #endif
                    125: 
                    126: int
                    127: console_init( void )
                    128: {
                    129:        if( video_get_res(&cons.physw,&cons.physh) < 0 )
                    130:                return -1;
                    131: 
                    132:        set_color( 0, 0 );
                    133: 
                    134:        cons.w = cons.physw/FONT_WIDTH;
                    135:        cons.h = cons.physh/FONT_ADJ_HEIGHT;
                    136:        cons.buf = malloc( cons.w * cons.h );
                    137:        cons.inited = 1;
                    138:        cons.x = cons.y = 0;
                    139:         cons.vc_state = ESnormal;
                    140:        return 0;
                    141: }
                    142: 
                    143: void
                    144: console_close( void )
                    145: {
                    146:        if( !cons.inited )
                    147:                return;
                    148:        free( cons.buf );
                    149:        cons.inited = 0;
                    150: }
                    151: 
                    152: static void
                    153: rec_char( int ch, int x, int y )
                    154: {
                    155:        if( (unsigned int)x < cons.w && (unsigned int)y < cons.h ) {
                    156:                cons.buf[y*cons.w + x] = ch;
                    157:                draw_char( x, y );
                    158:        }
                    159: }
                    160: 
                    161: static void
                    162: scroll1( void )
                    163: {
                    164:     int x, y;
                    165: 
                    166:     video_scroll(FONT_ADJ_HEIGHT);
                    167: 
                    168:     for (y = 1; y < cons.h - 1; y++) {
                    169:         for (x = 0; x < cons.w; x++)
                    170:             cons.buf[(y - 1) * cons.w + x] = cons.buf[y * cons.w + x];
                    171:     }
                    172:     for (x = 0; x < cons.w; x++)
                    173:         cons.buf[(cons.h - 1) * cons.w + x] = ' ';
                    174:     draw_line(cons.h - 1);
                    175: }
                    176: 
                    177: // Insert char
                    178: static void csi_at(unsigned int nr)
                    179: {
                    180:     unsigned int x;
                    181: 
                    182:     if (nr > cons.w - cons.x)
                    183:         nr = cons.w - cons.x;
                    184:     else if (!nr)
                    185:         return;
                    186: 
                    187:     for (x = cons.x + nr; x < cons.w - 1; x++)
                    188:         cons.buf[cons.y * cons.w + x - nr] = cons.buf[cons.y * cons.w + x];
                    189:     for (x = cons.x; x < cons.x + nr; x++)
                    190:         cons.buf[cons.y * cons.w + x] = ' ';
                    191:     draw_line(cons.y);
                    192: }
                    193: 
                    194: static void
                    195: do_con_trol(unsigned char ch)
                    196: {
                    197:     unsigned int i, j;
                    198: 
                    199:     switch (ch) {
                    200:     case 7:
                    201:         // BEL
                    202:         return;
                    203:     case 8:
                    204:         // BS
                    205:         if (cons.x)
                    206:             cons.x--;
                    207:         return;
                    208:     case 9:
                    209:         // HT
                    210:         cons.x = (cons.x + 8) & ~7;
                    211:         return;
                    212:     case 10:
                    213:         // LF
                    214:         cons.x = 0;
                    215:         cons.y++;
                    216:         return;
                    217:     case 12:
                    218:         // FF
                    219:         for (i = 0; i < cons.h; i++) {
                    220:             for (j = 0; j < cons.w; j++)
                    221:                 cons.buf[i * cons.w + j] = ' ';
                    222:             draw_line(i);
                    223:         }
                    224:         cons.x = cons.y = 0;
                    225:         return;
                    226:     case 13:
                    227:         // CR
                    228:         cons.x = 0;
                    229:         return;
                    230:     case 25:
                    231:         // EM
                    232:         return;
                    233:     case 24: // CAN
                    234:     case 26: // SUB
                    235:         cons.vc_state = ESnormal;
                    236:         return;
                    237:     case 27:
                    238:         // ESC
                    239:         cons.vc_state = ESesc;
                    240:         return;
                    241:     }
                    242:     if (ch < 32)
                    243:         DPRINTF("Unhandled control char %d\n", ch);
                    244: 
                    245:     switch (cons.vc_state) {
                    246:     case ESesc:
                    247:         cons.vc_state = ESnormal;
                    248:         switch (ch) {
                    249:         case '[':
                    250:             cons.vc_state = ESsquare;
                    251:             return;
                    252:         case 'M':
                    253:             scroll1();
                    254:             return;
                    255:         default:
                    256:             DPRINTF("Unhandled basic escape code '%c'\n", ch);
                    257:             return;
                    258:         }
                    259:         return;
                    260:     case ESsquare:
                    261:         for(cons.vc_npar = 0; cons.vc_npar < NPAR ; cons.vc_npar++)
                    262:             cons.vc_par[cons.vc_npar] = 0;
                    263:         cons.vc_npar = 0;
                    264:         cons.vc_state = ESgetpars;
                    265:         // Fall through
                    266:     case ESgetpars:
                    267:         if (ch == ';' && cons.vc_npar < NPAR - 1) {
                    268:             cons.vc_npar++;
                    269:             return;
                    270:         } else if (ch >= '0' && ch <= '9') {
                    271:             cons.vc_par[cons.vc_npar] *= 10;
                    272:             cons.vc_par[cons.vc_npar] += ch - '0';
                    273:             return;
                    274:         } else
                    275:             cons.vc_state=ESgotpars;
                    276:         // Fall through
                    277:     case ESgotpars:
                    278:         cons.vc_state = ESnormal;
                    279:         switch(ch) {
                    280:         case 'A':
                    281:             // Cursor up
                    282:             if (cons.vc_par[0] == 0)
                    283:                 cons.vc_par[0] = 1;
                    284:             if (cons.y - cons.vc_par[0] > 0)
                    285:                 cons.y -= cons.vc_par[0];
                    286:             return;
                    287:         case 'B':
                    288:             // Cursor down
                    289:             if (cons.vc_par[0] == 0)
                    290:                 cons.vc_par[0] = 1;
                    291:             if (cons.y + cons.vc_par[0] < cons.h - 1)
                    292:                 cons.y += cons.vc_par[0];
                    293:             return;
                    294:         case 'C':
                    295:             // Cursor right
                    296:             if (cons.vc_par[0] == 0)
                    297:                 cons.vc_par[0] = 1;
                    298:             if (cons.x + cons.vc_par[0] < cons.w - 1)
                    299:                 cons.x += cons.vc_par[0];
                    300:             return;
                    301:         case 'D':
                    302:             // Cursor left
                    303:             if (cons.vc_par[0] == 0)
                    304:                 cons.vc_par[0] = 1;
                    305:             if (cons.x - cons.vc_par[0] > 0)
                    306:                 cons.x -= cons.vc_par[0];
                    307:             return;
                    308:         case 'H':
                    309:         case 'f':
                    310:             // Set cursor position
                    311:             if (cons.vc_par[0])
                    312:                 cons.vc_par[0]--;
                    313: 
                    314:             if (cons.vc_par[1])
                    315:                 cons.vc_par[1]--;
                    316: 
                    317:             cons.x = cons.vc_par[1];
                    318:             cons.y = cons.vc_par[0];
                    319:             return;
                    320:         case 'J':
                    321:             if (cons.vc_par[0] == 0 && (unsigned int)cons.y < (unsigned int)cons.h &&
                    322:                 (unsigned int)cons.x < (unsigned int)cons.w) {
                    323:                 // erase from cursor to end of display
                    324:                 for (i = cons.x; i < cons.w; i++)
                    325:                     cons.buf[cons.y * cons.w + i] = ' ';
                    326:                 draw_line(cons.y);
                    327:                 for (j = cons.y + 1; j < cons.h; j++) {
                    328:                     for (i = 0; i < cons.w; i++)
                    329:                         cons.buf[j * cons.w + i] = ' ';
                    330:                     draw_line(j);
                    331:                 }
                    332:             } else {
                    333:                 DPRINTF("Unhandled CSI J code '%c'\n", cons.vc_par[0]);
                    334:             }
                    335:             return;
                    336:         case 'K':
                    337:             switch (cons.vc_par[0]) {
                    338:             case 0: /* erase from cursor to end of line */
                    339:                 for (i = cons.x; i < cons.w; i++)
                    340:                     cons.buf[cons.y * cons.w + i] = ' ';
                    341:                 draw_line(cons.y);
                    342:                 return;
                    343:             case 1: /* erase from start of line to cursor */
                    344:                 for (i = 0; i <= cons.x; i++)
                    345:                     cons.buf[cons.y * cons.w + i] = ' ';
                    346:                 draw_line(cons.y);
                    347:                 return;
                    348:             case 2: /* erase whole line */
                    349:                 for (i = 0; i < cons.w; i++)
                    350:                     cons.buf[cons.y * cons.w + i] = ' ';
                    351:                 draw_line(cons.y);
                    352:                 return;
                    353:             default:
                    354:                 DPRINTF("Unhandled CSI K code '%c'\n", cons.vc_par[0]);
                    355:                 return;
                    356:             }
                    357:             return;
                    358:         case 'M':
                    359:             if (cons.vc_par[0] == 1)
                    360:                 scroll1();
                    361:             else
                    362:                 DPRINTF("Unhandled CSI M %d\n", cons.vc_par[0]);
                    363:             return;
                    364:         case 'm':
                    365:             // Attributes are ignored
                    366:             return;
                    367:         case '@':
                    368:             csi_at(cons.vc_par[0]);
                    369:             return;
                    370:         default:
                    371:             DPRINTF("Unhandled escape code '%c', par[%d, %d, %d, %d, %d]\n",
                    372:                     ch, cons.vc_par[0], cons.vc_par[1], cons.vc_par[2],
                    373:                     cons.vc_par[3], cons.vc_par[4]);
                    374:             return;
                    375:         }
                    376:         return;
                    377:     default:
                    378:         cons.vc_state = ESnormal;
                    379:         rec_char(ch, cons.x++, cons.y);
                    380:         return;
                    381:     }
                    382: }
                    383: 
                    384: int
                    385: console_draw_fstr(const char *str, int len)
                    386: {
                    387:         unsigned int y, x;
                    388:         unsigned char ch;
                    389: 
                    390:         if (!str || len <= 0) {
                    391:                return 0;
                    392:        }
                    393: 
                    394:        if( !cons.inited && console_init() )
                    395:                return -1;
                    396: 
                    397:        show_cursor(0);
                    398:         while((ch = *str++) && len--) {
                    399:                do_con_trol(ch);
                    400: 
                    401:                if( cons.x >= cons.w ) {
                    402:                        cons.x=0, cons.y++;
                    403:                }
                    404:                if( cons.y >= cons.h ) {
                    405:                        for( y=0; y<cons.h-1; y++ )
                    406:                                for( x=0; x<cons.w; x++ )
                    407:                                        cons.buf[y*cons.w + x] = cons.buf[(y+1)*cons.w + x];
                    408:                        cons.y = cons.h-1;
                    409:                        cons.x = 0;
                    410:                        scroll1();
                    411:                }
                    412:        }
                    413:        show_cursor(1);
                    414:        return 0;
                    415: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.