|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.