|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. ! 26: * ! 27: * FBConsole.c - FrameBuffer based console implementation. ! 28: * ! 29: * ! 30: * HISTORY ! 31: * 01 Sep 92 Joe Pasqua ! 32: * Created. ! 33: * 25 Mar 97 Simon Douglas ! 34: * Rhapsodized. ! 35: */ ! 36: ! 37: // TO DO: ! 38: // * Implement other cases of FlipCursor, HorizLine, VertLine, ClearWindow. ! 39: // Erase ! 40: // * Find the #defines for np and del are, then get rid of our #defines. ! 41: // ! 42: // Notes: ! 43: // * This module implements the console functionality required by the ! 44: // ConsoleSupport protocol. If you have a device which is a framebuffer ! 45: // with a depth supported by this module, then you can use this code. ! 46: // * To find things that need to be fixed, search for FIX, to find questions ! 47: // to be resolved, search for ASK, to find stuff that still needs to be ! 48: // done, search for TO DO. ! 49: ! 50: #define BRINGUP 1 ! 51: ! 52: #import <sys/syslog.h> ! 53: #import <bsd/dev/ppc/FBConsole.h> ! 54: #import <bsd/dev/ppc/FBConsPriv.h> ! 55: #import <architecture/ascii_codes.h> ! 56: #import "BootImages.h" ! 57: ! 58: #if defined(NOTINKERNEL) ! 59: #define panic(str) ! 60: #define copyin(src, dst, size) bcopy(src, dst, size) ! 61: #define kalloc(size) malloc(size) ! 62: #define kfree(ptr, size) free(ptr) ! 63: #endif ! 64: ! 65: #ifdef DRIVERKIT ! 66: #else ! 67: #define IOMalloc(size) kalloc(size) ! 68: #define IOFree(ptr,size) kfree(ptr,size) ! 69: #define IOLog(s,a) printf(s,a) ! 70: #endif // DRIVERKIT ! 71: ! 72: #define TEXTURE_BACKGND 1 ! 73: ! 74: /* ! 75: * Standard font. ! 76: */ ! 77: extern char ohlfs12[][]; ! 78: ! 79: #import "ohlfs12.h" ! 80: ! 81: #define NIL (0) ! 82: ! 83: /* Window margins */ ! 84: #define BG_MARGIN 2 // pixels of background to leave as margin ! 85: #define FG_MARGIN 1 // pixels of foreground to leave as margin ! 86: #define TOTAL_MARGIN (BG_MARGIN + FG_MARGIN) ! 87: #define DROP_SHADOW 1 // pixels of dark_grey, bottom & right ! 88: #define TS_MARGIN 1 // ! 89: ! 90: #define HORIZ_BORDER 32 // 40 on VGA ! 91: #define VERT_BORDER 22 // 30 on VGA ! 92: ! 93: /* ! 94: * Ansi sequence state. ! 95: */ ! 96: typedef enum { ! 97: AS_NORMAL, ! 98: AS_ESCAPE, ! 99: AS_BRACKET, ! 100: AS_R ! 101: } ansi_state_t; ! 102: ! 103: #define ANSI_STACK_SIZE 3 ! 104: ! 105: typedef struct _t_Console { ! 106: ScreenMode window_type; ! 107: ! 108: IODisplayInfo display; ! 109: ! 110: // ! 111: // The remaining fields are window parameters. These are only ! 112: // meaningful for text-type windows (window_type == SCM_TEXT or ! 113: // SCM_ALERT). ! 114: // ! 115: ! 116: // ! 117: // Current window origin in pixels, relative to origin of screen. ! 118: // ! 119: int window_origin_x; ! 120: int window_origin_y; ! 121: ! 122: // ! 123: // Window size information, in pixels and in characters. ! 124: // ! 125: int chars_per_row; ! 126: int pixels_per_row; ! 127: int chars_per_column; ! 128: int pixels_per_column; ! 129: ! 130: // ! 131: // Cursor location, in characters. Origin is top ! 132: // left corner of window = {0,0}. ! 133: // ! 134: int curr_row; // in characters ! 135: int curr_column; // in characters ! 136: ! 137: // ! 138: // Misc. video parameters. The background and foreground fields ! 139: // are slightly dependent on the hardware implementation; they'll ! 140: // work as long as bits per pixel <= 32. ! 141: // ! 142: ! 143: unsigned int background; // bits for background pixel ! 144: unsigned int light_grey; // bits for light grey ! 145: unsigned int dark_grey; // bits for dark grey ! 146: unsigned int foreground; // bits for foreground pixel ! 147: unsigned int baseground; // bits for base color ! 148: unsigned int grayTable[4]; // bits for drawing bitmaps ! 149: ! 150: boolean_t has_title; ! 151: boolean_t prettyPanelUp; ! 152: unsigned int bolding; // bold text pixel count ! 153: ! 154: // ! 155: // Storage for saved region under an alert panel. ! 156: // ! 157: unsigned char *saveBits; ! 158: int saveHeight; ! 159: int saveRowBytes; ! 160: int saveBytes; ! 161: unsigned char *saveLocation; ! 162: ansi_state_t ansi_state; /* track ansi escape sequence state */ ! 163: u_char ansi_stack[ANSI_STACK_SIZE]; ! 164: u_char *ansi_stack_p; ! 165: ! 166: } ConsoleRep, *ConsolePtr; ! 167: ! 168: // ! 169: // BEGIN: Private utility routines ! 170: // ! 171: ! 172: static void videoMemMove( char * dst, char * src, unsigned int len ) ! 173: { ! 174: #if 1 ! 175: bcopy_nc( src, dst, len ); ! 176: #else ! 177: memmove( dst, src, len ); ! 178: #endif ! 179: } ! 180: ! 181: static unsigned int BPPToPPW(int bpp) ! 182: { ! 183: if (bpp == IO_2BitsPerPixel) return(16); ! 184: if (bpp == IO_8BitsPerPixel) return(4); ! 185: if (bpp == IO_12BitsPerPixel) return(2); ! 186: if (bpp == IO_15BitsPerPixel) return(2); ! 187: if (bpp == IO_24BitsPerPixel) return(1); ! 188: else return(-1); ! 189: } ! 190: ! 191: static unsigned char *PixelAddress(ConsolePtr console, int xPix, int yPix) ! 192: { ! 193: switch (console->display.bitsPerPixel) { ! 194: case IO_8BitsPerPixel: ! 195: return ((unsigned char *)console->display.frameBuffer) + ! 196: yPix * console->display.rowBytes + xPix; ! 197: case IO_12BitsPerPixel: ! 198: case IO_15BitsPerPixel: ! 199: return ((unsigned char *)console->display.frameBuffer) + ! 200: yPix * console->display.rowBytes + xPix * 2; ! 201: case IO_24BitsPerPixel: ! 202: return ((unsigned char *)console->display.frameBuffer) + ! 203: yPix * console->display.rowBytes + xPix * 4; ! 204: default: ! 205: panic("FBConsole/PixelAddress: bogus bitsPerPixel"); ! 206: } ! 207: } ! 208: ! 209: static void Fill(ConsolePtr console, ! 210: unsigned char *dst, // Where to start filling ! 211: unsigned pixel, // pattern to fill ! 212: unsigned len) // in pixels ! 213: // Descritpion: Fill the framebuffer with 'pixel' starting at dst ! 214: // and for 'len' pixels. ! 215: { ! 216: switch (console->display.bitsPerPixel) { ! 217: case IO_8BitsPerPixel: ! 218: { ! 219: unsigned char *dst8 = (unsigned char *)dst; ! 220: for (; len--; dst8++) ! 221: *dst8 = pixel; ! 222: break; ! 223: } ! 224: case IO_12BitsPerPixel: ! 225: case IO_15BitsPerPixel: ! 226: { ! 227: unsigned short *dst16 = (unsigned short *)dst; ! 228: for (; len--; dst16++) ! 229: *dst16 = pixel; ! 230: break; ! 231: } ! 232: case IO_24BitsPerPixel: ! 233: { ! 234: unsigned int *dst32 = (unsigned int *)dst; ! 235: for (; len--; dst32++) ! 236: *dst32 = pixel; ! 237: break; ! 238: } ! 239: default: ! 240: panic("FBConsole/Fill: bogus bitsPerPixel"); ! 241: } ! 242: } ! 243: ! 244: static void FlipCursor(ConsolePtr console) ! 245: // Description: Turn cursor on/off. This just inverts every pixel at the ! 246: // character at (curr_rown, curr_column). ! 247: { ! 248: int y; ! 249: unsigned char *dst8; ! 250: unsigned short *dst16; ! 251: unsigned int *dst32; ! 252: unsigned pixel_num; ! 253: ! 254: // Screen-relative pixel coordinates of bounds of current character. ! 255: int start_y = console->window_origin_y + ! 256: console->curr_row * CHAR_H; ! 257: int end_y = start_y + CHAR_H; ! 258: int start_x = console->window_origin_x + ! 259: console->curr_column * CHAR_W; ! 260: ! 261: for (y=start_y; y < end_y; y++) { ! 262: switch (console->display.bitsPerPixel) { ! 263: case IO_8BitsPerPixel: ! 264: dst8 = (unsigned char *)PixelAddress(console, start_x, y); ! 265: for (pixel_num = 0; pixel_num < CHAR_W; pixel_num++) { ! 266: if ((*dst8 & PIXEL_MASK_16) == ! 267: (console->background & PIXEL_MASK_16)) { ! 268: *dst8 = console->foreground; ! 269: } ! 270: else { ! 271: *dst8 = console->background; ! 272: } ! 273: dst8++; ! 274: } ! 275: break; ! 276: case IO_12BitsPerPixel: ! 277: case IO_15BitsPerPixel: ! 278: dst16 = (unsigned short *)PixelAddress(console, start_x, y); ! 279: for (pixel_num = 0; pixel_num < CHAR_W; pixel_num++) { ! 280: if ((*dst16 & PIXEL_MASK_16) == ! 281: (console->background & PIXEL_MASK_16)) { ! 282: *dst16 = console->foreground; ! 283: } ! 284: else { ! 285: *dst16 = console->background; ! 286: } ! 287: dst16++; ! 288: } ! 289: break; ! 290: case IO_24BitsPerPixel: ! 291: dst32 = (unsigned int *)PixelAddress(console, start_x, y); ! 292: for (pixel_num = 0; pixel_num < CHAR_W; pixel_num++) { ! 293: if ((*dst32 & PIXEL_MASK_32) == ! 294: (console->background & PIXEL_MASK_32)) { ! 295: *dst32 = console->foreground; ! 296: } ! 297: else { ! 298: *dst32 = console->background; ! 299: } ! 300: dst32++; ! 301: } ! 302: break; ! 303: ! 304: default: ! 305: panic("FBConsole/FlipCursor: bogus bits per pixel"); ! 306: } ! 307: } ! 308: } ! 309: ! 310: static void SwapForegroundAndBackground(ConsolePtr console) ! 311: { ! 312: int temp_color; ! 313: ! 314: temp_color = console->foreground; ! 315: console->foreground = console->background; ! 316: console->background = temp_color; ! 317: } ! 318: ! 319: static void Rect( ! 320: ConsolePtr console, ! 321: int origin_x, int origin_y, ! 322: int width, int height, ! 323: unsigned pixel) ! 324: // Description: Draws a single pixel wide horizontal line ! 325: { ! 326: while (height--) ! 327: Fill(console, ! 328: PixelAddress(console, origin_x, origin_y++), ! 329: pixel, width); ! 330: } ! 331: ! 332: #ifdef notdef ! 333: static void HorizLine( ! 334: ConsolePtr console, ! 335: int origin_x, int origin_y, int length, ! 336: unsigned pixel) ! 337: // Description: Draws a single pixel wide horizontal line ! 338: { ! 339: Fill(console, PixelAddress(console, origin_x, origin_y), pixel, length); ! 340: } ! 341: ! 342: static void VertLine( ! 343: ConsolePtr console, ! 344: int origin_x, int origin_y, int length, ! 345: unsigned pixel) ! 346: // Description: Draws a single pixel wide vertical line ! 347: { ! 348: unsigned char *dstPixel = PixelAddress(console, origin_x, origin_y); ! 349: ! 350: switch(console->display.bitsPerPixel) { ! 351: case IO_8BitsPerPixel: ! 352: { ! 353: unsigned char *dst = (unsigned char *)dstPixel; ! 354: while (length--) { ! 355: *dst = pixel; ! 356: dst += console->display.totalWidth; ! 357: } ! 358: } ! 359: break; ! 360: case IO_12BitsPerPixel: ! 361: case IO_15BitsPerPixel: ! 362: { ! 363: unsigned short *dst = (unsigned short *)dstPixel; ! 364: while (length--) { ! 365: *dst = pixel; ! 366: dst += console->display.totalWidth; ! 367: } ! 368: } ! 369: break; ! 370: case IO_24BitsPerPixel: ! 371: { ! 372: unsigned long *dst = (unsigned long *)dstPixel; ! 373: while (length--) { ! 374: *dst = pixel; ! 375: dst += console->display.totalWidth; ! 376: } ! 377: } ! 378: break; ! 379: ! 380: default: ! 381: panic("FBConsole/VertLine: bogus bits per pixel"); ! 382: } ! 383: } ! 384: #endif ! 385: ! 386: static void ClearWindow(ConsolePtr console) ! 387: // Description: Set contents of entire current window to background. ! 388: // Preconditions: ! 389: // * Cursor is off on entry and will remain so on exit. ! 390: { ! 391: int line; ! 392: unsigned char *dstPixel = PixelAddress( ! 393: console, console->window_origin_x, console->window_origin_y); ! 394: ! 395: for (line=0; line < console->pixels_per_column; line++) { ! 396: // One loop per scan line in the window. ! 397: Fill(console, dstPixel, console->background, ! 398: console->pixels_per_row); ! 399: dstPixel += console->display.rowBytes; ! 400: } ! 401: } ! 402: ! 403: static void WipeScreen(ConsolePtr console, const unsigned pixel) ! 404: // Description: Fill the screen with specific pixel value. ! 405: { ! 406: static int horstArray[5] = { 5,3,2,1,1 }; ! 407: int i,horst; ! 408: ! 409: Rect( console, 0, 0, console->display.width, console->display.height, pixel ); ! 410: ! 411: // Round rect ! 412: for( i=0; i < 5; i++) { ! 413: horst = horstArray[i]; ! 414: // top left ! 415: Fill(console, PixelAddress(console, 0, i), console->foreground, horst); ! 416: // bottom left ! 417: Fill(console, PixelAddress(console, 0, console->display.height - i - 1), console->foreground, horst); ! 418: // top right ! 419: Fill(console, PixelAddress(console, console->display.width - horst, i), console->foreground, horst); ! 420: // bottom right ! 421: Fill(console, PixelAddress(console, console->display.width - horst, console->display.height - i - 1), ! 422: console->foreground, horst); ! 423: } ! 424: } ! 425: ! 426: static void ClearToEOL(ConsolePtr console) ! 427: // Description: Clear to end of line (within window), including current pos. ! 428: // Preconditions: ! 429: // * Cursor is 'off' on entry and will remain so on exit. ! 430: { ! 431: unsigned pixel_count; ! 432: int starting_x; // window-relative 'x' coordinate ! 433: int y; ! 434: int line; ! 435: ! 436: starting_x = console->window_origin_x + ! 437: (console->curr_column * CHAR_W); ! 438: y = console->window_origin_y + (console->curr_row * CHAR_H); ! 439: ! 440: pixel_count = console->pixels_per_row - ! 441: (starting_x - console->window_origin_x); ! 442: ! 443: for (line=0; line < CHAR_H; line++) { ! 444: // One loop per scan line in the row. ! 445: Fill( ! 446: console, PixelAddress(console, starting_x, y++), ! 447: console->background, pixel_count); ! 448: } ! 449: } ! 450: ! 451: static void Erase(ConsolePtr console) ! 452: // Description: Erase current cursor location. ! 453: { ! 454: int y; ! 455: unsigned char *dst8; ! 456: unsigned short *dst16; ! 457: unsigned int *dst32; ! 458: int x; ! 459: // Screen-relative pixel coordinates of bounds of current character. ! 460: int start_y = console->window_origin_y + ! 461: console->curr_row * CHAR_H; ! 462: int end_y = start_y + CHAR_H; ! 463: int start_x = console->window_origin_x + ! 464: console->curr_column * CHAR_W; ! 465: ! 466: for (y=start_y; y<end_y; y++) { ! 467: // I think it's quicker not to use Fill() here... ! 468: switch (console->display.bitsPerPixel) { ! 469: case IO_8BitsPerPixel: ! 470: dst8 = (unsigned char *)PixelAddress(console, start_x, y); ! 471: for (x=0; x < CHAR_W; x++) { ! 472: *dst8++ = console->background; ! 473: } ! 474: break; ! 475: case IO_12BitsPerPixel: ! 476: case IO_15BitsPerPixel: ! 477: dst16 = (unsigned short *)PixelAddress(console, start_x, y); ! 478: for (x=0; x < CHAR_W; x++) { ! 479: *dst16++ = console->background; ! 480: } ! 481: break; ! 482: case IO_24BitsPerPixel: ! 483: dst32 = (unsigned int *)PixelAddress(console, start_x, y); ! 484: for (x=0; x < CHAR_W; x++) { ! 485: *dst32++ = console->background; ! 486: } ! 487: break; ! 488: ! 489: default: ! 490: panic("FBConsole/Erase: bogus bits per pixel"); ! 491: } ! 492: } ! 493: } ! 494: ! 495: extern unsigned char appleClut8[ 768 ]; ! 496: ! 497: static void Expand4ToN( ConsolePtr console, int x, int y, int width, int height, ! 498: unsigned char * dataPtr, unsigned char colors[ 16 ]) ! 499: { ! 500: unsigned char *dst; ! 501: int line, col, bit = 4; ! 502: unsigned int data, data8; ! 503: ! 504: dst = (unsigned char *) PixelAddress(console, x, y); ! 505: for( line = 0; line < height; line++) { ! 506: for( col = 0; col < width; col++, bit ^= 4) { ! 507: if( bit) ! 508: data8 = *dataPtr++; ! 509: data = colors[ (data8 >> bit) & 15]; ! 510: ! 511: switch (console->display.bitsPerPixel) { ! 512: case IO_8BitsPerPixel: ! 513: if (console->display.colorSpace != IO_OneIsWhiteColorSpace) ! 514: *(dst + col) = data; ! 515: else { ! 516: data *= 3; ! 517: *(dst + col) = ((19595 * appleClut8[data] + ! 518: 38470 * appleClut8[data + 1] + ! 519: 7471 * appleClut8[data + 2] ) / 65536); ! 520: ! 521: } ! 522: break; ! 523: case IO_24BitsPerPixel: ! 524: data *= 3; ! 525: *(((unsigned int *)dst) + col) = (appleClut8[data] << 16) ! 526: | (appleClut8[data + 1] << 8) ! 527: | appleClut8[data + 2]; ! 528: break; ! 529: case IO_15BitsPerPixel: ! 530: data *= 3; ! 531: *(((unsigned short *)dst) + col) = ( (0xf8 & (appleClut8[data])) << 7) ! 532: | ( (0xf8 & (appleClut8[data + 1])) << 2) ! 533: | ( (0xf8 & (appleClut8[data + 2])) >> 3); ! 534: break; ! 535: default: ! 536: break; ! 537: } ! 538: } ! 539: dst = (unsigned char *) ((int)dst + console->display.rowBytes); ! 540: } ! 541: } ! 542: ! 543: ! 544: ! 545: ! 546: static void DrawColorRect( ConsolePtr console, int x, int y, int width, int height, unsigned char * dataPtr) ! 547: { ! 548: unsigned char *dst8; ! 549: int line,col; ! 550: unsigned int data; ! 551: ! 552: dst8 = (unsigned char *) PixelAddress(console, x, y); ! 553: for( line = 0; line < height; line++) { ! 554: for( col = 0; col < width; col++) { ! 555: ! 556: data = *dataPtr++; ! 557: if( data != 0x01) { ! 558: switch (console->display.bitsPerPixel) { ! 559: case IO_8BitsPerPixel: ! 560: if (console->display.colorSpace == IO_OneIsWhiteColorSpace) { ! 561: data *= 3; ! 562: *(dst8 + col) = ((19595 * appleClut8[data] + ! 563: 38470 * appleClut8[data + 1] + ! 564: 7471 * appleClut8[data + 2] ) / 65536); ! 565: } else { ! 566: *(dst8 + col) = data; ! 567: } ! 568: break; ! 569: case IO_24BitsPerPixel: ! 570: data *= 3; ! 571: *(((unsigned int *)dst8) + col) = (appleClut8[data] << 16) ! 572: | (appleClut8[data + 1] << 8) ! 573: | appleClut8[data + 2]; ! 574: break; ! 575: case IO_15BitsPerPixel: ! 576: data *= 3; ! 577: *(((unsigned short *)dst8) + col) = ( (0xf8 & (appleClut8[data])) << 7) ! 578: | ( (0xf8 & (appleClut8[data + 1])) << 2) ! 579: | ( (0xf8 & (appleClut8[data + 2])) >> 3); ! 580: break; ! 581: default: ! 582: break; ! 583: } ! 584: } ! 585: } ! 586: dst8 = (unsigned char *) ((int)dst8 + console->display.rowBytes); ! 587: } ! 588: } ! 589: ! 590: static void DrawIcon( ConsolePtr console) ! 591: { ! 592: ! 593: #define ICON_WIDTH 11 ! 594: #define ICON_HEIGHT 14 ! 595: ! 596: static unsigned char iconData[ICON_WIDTH*ICON_HEIGHT] = { ! 597: 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xE3,0xE5,0x01,0x01, ! 598: 0x01,0x01,0x01,0x01,0x01,0x01,0xE3,0xE5,0xE8,0x01,0x01, ! 599: 0x01,0x01,0x01,0x01,0x01,0x01,0xE5,0xE8,0x01,0x01,0x01, ! 600: 0x01,0x01,0xE3,0xE3,0xE5,0x01,0x01,0xE3,0xE3,0xE8,0x01, ! 601: 0x01,0xE5,0x6F,0x26,0xE3,0xE3,0xE3,0xE3,0xE5,0xE6,0xE8, ! 602: 0x10,0x05,0x01,0x05,0x05,0x0A,0x11,0x10,0x17,0x5E,0x01, ! 603: 0x10,0x00,0x05,0x05,0x0B,0x0A,0x11,0x10,0x5F,0x01,0x01, ! 604: 0x3B,0x00,0x08,0x11,0x11,0x17,0x3B,0x3B,0x65,0x01,0x01, ! 605: 0x3B,0x00,0x08,0x11,0x17,0x17,0x17,0x3B,0x65,0x65,0x01, ! 606: 0xD8,0x07,0x14,0xD8,0xD8,0xD8,0xD8,0xD9,0xD9,0xDB,0x8F, ! 607: 0x14,0x3E,0x06,0x14,0x20,0x20,0x20,0x3E,0x3E,0x62,0x8D, ! 608: 0x01,0x3E,0x3E,0x14,0x20,0x20,0x3E,0x3E,0x62,0x8D,0x8D, ! 609: 0x01,0x01,0xEE,0xA3,0xA3,0xEF,0xCE,0xA3,0xCE,0xEF,0x01, ! 610: 0x01,0x01,0x01,0xEF,0xEF,0x01,0x01,0xEF,0xEF,0x01,0x01 ! 611: }; ! 612: int x,y; // location of upper left corner of glyph ! 613: ! 614: x = console->window_origin_x + console->curr_column * CHAR_W - ICON_WIDTH - 7; // left: BG_MARGIN + FG_MARGIN + 2; ! 615: y = console->window_origin_y + console->curr_row * CHAR_H - 4; ! 616: ! 617: DrawColorRect( console, x, y, ICON_WIDTH, ICON_HEIGHT, &iconData[0]); ! 618: } ! 619: ! 620: /* ! 621: * Expand a 1-bit PS bitmap, origin is lower left corner. ! 622: */ ! 623: #import "kmFontPriv.h" ! 624: ! 625: void ! 626: BltPSBitmap(IOConsoleInfo *cso, int xpos, int ypos, bitmap_t *bmp, ! 627: const unsigned char *bits, int grayValue) ! 628: { ! 629: ConsolePtr console = (ConsolePtr)cso->priv; ! 630: int x, y; ! 631: int bitoffset; ! 632: unsigned char *pixAddr; ! 633: int fg; ! 634: ! 635: pixAddr = PixelAddress(console, (console->display.width / 2) + xpos + bmp->bbx.xoff, ! 636: ((console->display.height - 480) / 2) + ypos - bmp->bbx.yoff - bmp->bbx.height + 1); ! 637: fg = console->grayTable[ grayValue & 3 ]; ! 638: ! 639: /* ! 640: * x and y are in fb coordinate system ! 641: * xoff and yoff are in ps coordinate system ! 642: */ ! 643: for (y = 0; y < bmp->bbx.height; y++) ! 644: { ! 645: for (x = 0; x < bmp->bbx.width; x++) ! 646: { ! 647: bitoffset = bmp->bitx + y * bmp->bbx.width + x; ! 648: if( bits[bitoffset >> 3] & (0x80 >> (bitoffset & 0x7))) ! 649: ! 650: switch (console->display.bitsPerPixel) ! 651: { ! 652: case IO_8BitsPerPixel: ! 653: ((unsigned char *)pixAddr)[ x ] = fg; ! 654: break; ! 655: case IO_12BitsPerPixel: ! 656: case IO_15BitsPerPixel: ! 657: ((unsigned short *)pixAddr)[ x ] = fg; ! 658: break; ! 659: ! 660: case IO_24BitsPerPixel: ! 661: ((unsigned int *)pixAddr)[ x ] = fg; ! 662: break; ! 663: } ! 664: } ! 665: pixAddr += console->display.rowBytes; ! 666: } ! 667: } ! 668: ! 669: static void BltChar(ConsolePtr console, const char c) ! 670: // Description: Paint one character at (curr_column, curr_row). ! 671: { ! 672: unsigned char *glyphbase; // the glyph we're rendering ! 673: unsigned char byte; ! 674: unsigned char *pixAddr; ! 675: int x,y; // location of upper left corner of glyph ! 676: int source_y, bold; ! 677: unsigned char *dst8, fg8; ! 678: unsigned short *dst16, fg16; ! 679: unsigned int *dst32, fg32; ! 680: ! 681: ! 682: // Erase current contents of {curr_row, curr_column}. ! 683: Erase(console); ! 684: ! 685: // Skip non-printing characters. ! 686: if (c < ENCODEBASE) { ! 687: return; ! 688: } ! 689: bold = console->bolding; ! 690: x = console->window_origin_x + console->curr_column * CHAR_W; ! 691: y = console->window_origin_y + console->curr_row * CHAR_H; ! 692: ! 693: do { ! 694: glyphbase = ohlfs12[c - ENCODEBASE]; ! 695: pixAddr = PixelAddress(console, x + bold, y); ! 696: switch (console->display.bitsPerPixel) { ! 697: case IO_8BitsPerPixel: ! 698: fg8 = (unsigned char) console->foreground; ! 699: dst8 = (unsigned char *) pixAddr; ! 700: for (source_y = CHAR_H; source_y != 0; source_y--) { ! 701: byte = *glyphbase++; ! 702: if (byte & 0x80) dst8[0] = fg8; ! 703: if (byte & 0x40) dst8[1] = fg8; ! 704: if (byte & 0x20) dst8[2] = fg8; ! 705: if (byte & 0x10) dst8[3] = fg8; ! 706: if (byte & 0x08) dst8[4] = fg8; ! 707: if (byte & 0x04) dst8[5] = fg8; ! 708: if (byte & 0x02) dst8[6] = fg8; ! 709: if (byte & 0x01) dst8[7] = fg8; ! 710: dst8 = (unsigned char *) ! 711: ((int)dst8 + console->display.rowBytes); ! 712: } ! 713: break; ! 714: case IO_12BitsPerPixel: ! 715: case IO_15BitsPerPixel: ! 716: fg16 = (unsigned short) console->foreground; ! 717: dst16 = (unsigned short *) pixAddr; ! 718: for (source_y = CHAR_H; source_y != 0; source_y--) { ! 719: byte = *glyphbase++; ! 720: if (byte & 0x80) dst16[0] = fg16; ! 721: if (byte & 0x40) dst16[1] = fg16; ! 722: if (byte & 0x20) dst16[2] = fg16; ! 723: if (byte & 0x10) dst16[3] = fg16; ! 724: if (byte & 0x08) dst16[4] = fg16; ! 725: if (byte & 0x04) dst16[5] = fg16; ! 726: if (byte & 0x02) dst16[6] = fg16; ! 727: if (byte & 0x01) dst16[7] = fg16; ! 728: dst16 = (unsigned short *) ! 729: ((int)dst16 + console->display.rowBytes); ! 730: } ! 731: break; ! 732: case IO_24BitsPerPixel: ! 733: fg32 = (unsigned int) console->foreground; ! 734: dst32 = (unsigned int *) pixAddr; ! 735: for (source_y = CHAR_H; source_y != 0; source_y--) { ! 736: byte = *glyphbase++; ! 737: if (byte & 0x80) dst32[0] = fg32; ! 738: if (byte & 0x40) dst32[1] = fg32; ! 739: if (byte & 0x20) dst32[2] = fg32; ! 740: if (byte & 0x10) dst32[3] = fg32; ! 741: if (byte & 0x08) dst32[4] = fg32; ! 742: if (byte & 0x04) dst32[5] = fg32; ! 743: if (byte & 0x02) dst32[6] = fg32; ! 744: if (byte & 0x01) dst32[7] = fg32; ! 745: dst32 = (unsigned int *) ! 746: ((int)dst32 + console->display.rowBytes); ! 747: } ! 748: break; ! 749: } ! 750: } while( bold--); ! 751: console->curr_column++; ! 752: return; ! 753: } ! 754: ! 755: extern void video_scroll_up(unsigned char * start, unsigned char * end, unsigned char * dest); ! 756: ! 757: static void FBPutC(ConsolePtr console, char c) ! 758: // Write one character to screen. Cursor is 'on' on entry and exit. ! 759: { ! 760: int repeat; ! 761: int i; ! 762: ! 763: /* ! 764: * First deal with ANSI escape sequences. ! 765: * This is a very bizarre implementation, copied from the m68k ! 766: * version. ! 767: */ ! 768: switch(console->ansi_state) { ! 769: case AS_NORMAL: ! 770: if(c == esc) { ! 771: console->ansi_state = AS_ESCAPE; ! 772: return; ! 773: } ! 774: else { ! 775: break; // continue ! 776: } ! 777: ! 778: case AS_ESCAPE: ! 779: switch(c) { ! 780: case '[': ! 781: console->ansi_state = AS_BRACKET; ! 782: return; ! 783: default: ! 784: console->ansi_state = AS_NORMAL; ! 785: break; // continue ! 786: } ! 787: ! 788: case AS_BRACKET: ! 789: if(c >= '0' && c <= '9') { ! 790: *console->ansi_stack_p = ! 791: *console->ansi_stack_p * 10 + (c - '0'); ! 792: return; ! 793: } ! 794: else if (c == ';') { ! 795: if(console->ansi_stack_p < ! 796: &console->ansi_stack[ANSI_STACK_SIZE]) { ! 797: console->ansi_stack_p++; ! 798: } ! 799: return; ! 800: } ! 801: else { ! 802: for(i=0; i<ANSI_STACK_SIZE; i++) { ! 803: if (console->ansi_stack[i] == 0) { ! 804: console->ansi_stack[i] = 1; ! 805: } ! 806: } ! 807: repeat = *console->ansi_stack_p; ! 808: FlipCursor(console); // cursor off ! 809: switch (c) { ! 810: ! 811: case 'A': ! 812: while (repeat--) { ! 813: if(console->curr_row) { ! 814: console->curr_row--; ! 815: } ! 816: } ! 817: break; ! 818: ! 819: case 'B': ! 820: while (repeat--) { ! 821: console->curr_row++; ! 822: } ! 823: break; ! 824: ! 825: case 'C': // non destructive space ! 826: while (repeat--) { ! 827: console->curr_column++; ! 828: } ! 829: break; ! 830: ! 831: case 'D': // not in termcap ! 832: while (repeat--) { ! 833: if(console->curr_column) { ! 834: console->curr_column--; ! 835: } ! 836: } ! 837: break; ! 838: ! 839: case 'E': // not in termcap ! 840: console->curr_column = 0; ! 841: while (repeat--) { ! 842: console->curr_row++; ! 843: } ! 844: break; ! 845: ! 846: case 'H': // should be home ! 847: case 'f': // not in termcap ! 848: console->curr_column = ! 849: *console->ansi_stack_p - 1; ! 850: console->ansi_stack_p--; ! 851: console->curr_row = ! 852: *console->ansi_stack_p - 1; ! 853: console->ansi_stack_p--; ! 854: break; ! 855: ! 856: case 'K': ! 857: ClearToEOL(console); ! 858: break; ! 859: ! 860: case 'm': /* FIXME */ ! 861: console->ansi_stack_p--; ! 862: console->ansi_stack_p--; ! 863: break; ! 864: } ! 865: } ! 866: console->ansi_stack_p = &console->ansi_stack[1]; ! 867: for(i=0; i<ANSI_STACK_SIZE; i++) ! 868: console->ansi_stack[i] = 0; ! 869: console->ansi_state = AS_NORMAL; ! 870: goto proceed; ! 871: } ! 872: ! 873: FlipCursor(console); // cursor off ! 874: switch(c) { ! 875: case '\r': // Carriage return ! 876: console->curr_column = 0; ! 877: break; ! 878: ! 879: case '\n': // line feed ! 880: console->curr_column = 0; ! 881: console->curr_row++; ! 882: break; ! 883: ! 884: case '\b': // backspace ! 885: if (console->curr_column == 0) ! 886: break; ! 887: console->curr_column--; ! 888: break; ! 889: ! 890: case '\t': ! 891: // tab. Erase all characters up to and including the ! 892: // next tab stop. ! 893: { ! 894: int col, num_cols; ! 895: ! 896: num_cols = TAB_SIZE - (console->curr_column % TAB_SIZE); ! 897: FlipCursor(console); // cursor on ! 898: for (col = 0; col<num_cols; col++) { ! 899: FBPutC(console, ' '); // cursor on at return ! 900: } ! 901: FlipCursor(console); // cursor off ! 902: break; ! 903: } ! 904: ! 905: case np: // aka ff, form feed ! 906: console->curr_row = console->curr_column = 0; ! 907: ClearWindow(console); ! 908: break; ! 909: ! 910: case del: ! 911: console->curr_column++; ! 912: break; ! 913: ! 914: default: ! 915: // Normal case. ! 916: BltChar(console, c); ! 917: break; ! 918: } ! 919: ! 920: // Cursor is off. ! 921: proceed: ! 922: if (console->curr_column >= console->chars_per_row) { ! 923: // End-of-line wrap. ! 924: console->curr_column = 0; ! 925: console->curr_row++; ! 926: } ! 927: ! 928: if (console->curr_row >= console->chars_per_column) { ! 929: // ! 930: // Screen scroll. Copy the whole window down in memory ! 931: // (pixels_per_row * CHAR_H) pixels, starting at ! 932: // the first character in row 1. ! 933: // ! 934: unsigned char *src; ! 935: unsigned char *dst; ! 936: int source_y; ! 937: unsigned windowRowBytes; ! 938: ! 939: console->curr_row = console->chars_per_column - 1; ! 940: switch (console->display.bitsPerPixel) { ! 941: case IO_8BitsPerPixel: ! 942: windowRowBytes = console->pixels_per_row; ! 943: break; ! 944: case IO_12BitsPerPixel: ! 945: case IO_15BitsPerPixel: ! 946: windowRowBytes = 2*console->pixels_per_row; ! 947: break; ! 948: case IO_24BitsPerPixel: ! 949: windowRowBytes = 4*console->pixels_per_row; ! 950: break; ! 951: default: ! 952: panic("FBConsole/FBPutC: bogus bitsPerPixel"); ! 953: } ! 954: ! 955: // Copy one row at a time, moving each one up ! 956: // CHAR_H rows. Within the loop, just increment ! 957: // pixel pointers by one row's worth of pixels. ! 958: // Source starts at the left top of row 1; destination ! 959: // starts at left top of row 0. ! 960: // ! 961: src = PixelAddress(console, ! 962: console->window_origin_x, ! 963: console->window_origin_y + CHAR_H); ! 964: dst = PixelAddress(console, ! 965: console->window_origin_x, ! 966: console->window_origin_y); ! 967: for (source_y = CHAR_H; // top, row 1 ! 968: source_y < console->pixels_per_column; // bottom ! 969: source_y++) { ! 970: #ifndef notDefUseFPU ! 971: video_scroll_up( src, src + windowRowBytes, dst); ! 972: #else ! 973: videoMemMove(dst, src, windowRowBytes); ! 974: #endif ! 975: src += console->display.rowBytes; ! 976: dst += console->display.rowBytes; ! 977: } ! 978: ! 979: console->curr_column = 0; ! 980: ClearToEOL(console); ! 981: } ! 982: ! 983: // Cursor back on. ! 984: FlipCursor(console); ! 985: } ! 986: ! 987: static void SetTitle(ConsolePtr console, const char *title) ! 988: // Description: Draw title bar if none exists, write specified title into it. ! 989: // Drawing a title bar involves snarfing up row 0 of the window ! 990: // and decreasing the usable size of the window by one row. ! 991: // Preconditions: ! 992: // * Cursor is 'on' on entry and will remain so on exit. ! 993: { ! 994: int saved_curr_row = console->curr_row; ! 995: int saved_curr_column = console->curr_column; ! 996: int saved_origin_y; ! 997: int title_len = strlen(title); ! 998: int pixel_num; ! 999: ! 1000: if ((title_len == 0) || (title_len > console->chars_per_row)) { ! 1001: IOLog("console: Illegal title length (%d)\n", title_len); ! 1002: return; ! 1003: } ! 1004: FlipCursor(console); // old cursor off ! 1005: if (console->has_title) { ! 1006: // First grow window by two rows - this absorbs the existing ! 1007: // title bar. ! 1008: console->window_origin_y -= CHAR_H * 2; ! 1009: console->chars_per_column += 2; ! 1010: console->pixels_per_column += CHAR_H * 2; ! 1011: saved_curr_row += 2; ! 1012: } ! 1013: ! 1014: // Clear row 0, center new title in it. ! 1015: console->curr_row = 0; ! 1016: Rect(console, ! 1017: console->window_origin_x - (BG_MARGIN - TS_MARGIN), ! 1018: console->window_origin_y - (BG_MARGIN - TS_MARGIN), ! 1019: CHAR_W * console->chars_per_row + 2 * (BG_MARGIN - TS_MARGIN), ! 1020: CHAR_H * 2 - TS_MARGIN, ! 1021: console->light_grey); ! 1022: saved_origin_y = console->window_origin_y; ! 1023: console->window_origin_y += CHAR_H / 2; ! 1024: console->curr_column = (console->chars_per_row - title_len) / 2; ! 1025: DrawIcon(console); ! 1026: // SwapForegroundAndBackground(console); ! 1027: console->bolding = 1; ! 1028: console->background = console->light_grey; ! 1029: FlipCursor(console); // new cursor on ! 1030: while (*title) { ! 1031: FBPutC(console, *title++); ! 1032: } ! 1033: FlipCursor(console); // new cursor off ! 1034: console->background = console->grayTable[0]; ! 1035: console->bolding = 0; ! 1036: // SwapForegroundAndBackground(console); ! 1037: console->window_origin_y = saved_origin_y; ! 1038: ! 1039: // Draw grey lines one pixel away from border of title bar. ! 1040: // Origin is currently at first pixel in top line of title bar. ! 1041: ! 1042: Rect(console, // inside top ! 1043: console->window_origin_x - BG_MARGIN, ! 1044: console->window_origin_y - BG_MARGIN, ! 1045: console->pixels_per_row + (BG_MARGIN * 2), ! 1046: TS_MARGIN, ! 1047: console->background); ! 1048: Rect(console, // inside bottom ! 1049: console->window_origin_x - BG_MARGIN, ! 1050: console->window_origin_y + CHAR_H * 2 - TOTAL_MARGIN - TS_MARGIN, ! 1051: console->pixels_per_row + BG_MARGIN * 2, ! 1052: TS_MARGIN, ! 1053: console->dark_grey); ! 1054: for (pixel_num = 0; pixel_num < TS_MARGIN; pixel_num++) { ! 1055: Rect(console, // left ! 1056: console->window_origin_x - BG_MARGIN + pixel_num, ! 1057: console->window_origin_y - BG_MARGIN + pixel_num, ! 1058: 1, ! 1059: CHAR_H * 2 - 1 - (pixel_num * 2), ! 1060: console->background); ! 1061: } ! 1062: for (pixel_num = 1 + BG_MARGIN - TS_MARGIN; pixel_num <= BG_MARGIN; pixel_num++) { ! 1063: Rect(console, // right ! 1064: console->window_origin_x + console->pixels_per_row + pixel_num - 1, ! 1065: console->window_origin_y - pixel_num, ! 1066: 1, ! 1067: CHAR_H * 2 - 1 - (BG_MARGIN - pixel_num) * 2, ! 1068: console->dark_grey); ! 1069: } ! 1070: Rect(console, // outside bottom ! 1071: console->window_origin_x - TOTAL_MARGIN, ! 1072: console->window_origin_y + CHAR_H * 2 - FG_MARGIN - BG_MARGIN, ! 1073: console->pixels_per_row + TOTAL_MARGIN * 2, ! 1074: FG_MARGIN, ! 1075: console->foreground); ! 1076: ! 1077: // Diminish window size by two rows. ! 1078: console->window_origin_y += CHAR_H * 2; ! 1079: console->chars_per_column -= 2; ! 1080: console->pixels_per_column -= CHAR_H * 2; ! 1081: ! 1082: ! 1083: // Restore old cursor. Careful, the y axis just changed... ! 1084: console->curr_column = saved_curr_column; ! 1085: if (saved_curr_row > 0) { ! 1086: console->curr_row = saved_curr_row - 2; ! 1087: } ! 1088: else { ! 1089: // New row 0 - clear it. ! 1090: ClearToEOL(console); ! 1091: } ! 1092: FlipCursor(console); // old cursor on ! 1093: console->has_title = TRUE; ! 1094: } ! 1095: ! 1096: ! 1097: static void UpdateWindowChars(ConsolePtr console) ! 1098: // Description: Calculate window size in characters. Used when either window ! 1099: // size or font changes. ! 1100: { ! 1101: console->chars_per_row = console->pixels_per_row / CHAR_W; ! 1102: console->chars_per_column = ! 1103: console->pixels_per_column / CHAR_H; ! 1104: } ! 1105: ! 1106: ! 1107: ! 1108: static void InitWindow(ConsolePtr console, ! 1109: int width, ! 1110: int height, ! 1111: const char *title, ! 1112: boolean_t initWindow, ! 1113: boolean_t saveUnder) ! 1114: // Description: Initialize window parameters. If initWindow is TRUE, an empty ! 1115: // window is drawn in the screen, else we assume that a window ! 1116: // already exists. Screen and font parameters must be valid on ! 1117: // entry. ! 1118: { ! 1119: // Truncate specified size to integral mutliple of character size ! 1120: // in both dimensions. ! 1121: width /= CHAR_W; // now in chars ! 1122: height /= CHAR_H; ! 1123: width *= CHAR_W; // now in pixels ! 1124: height *= CHAR_H; ! 1125: ! 1126: // Ensure there's enough room for a border. ! 1127: if (width > (console->display.width - HORIZ_BORDER - TOTAL_MARGIN * 2 - DROP_SHADOW)) ! 1128: width = console->display.width - HORIZ_BORDER - TOTAL_MARGIN * 2 - DROP_SHADOW; ! 1129: if (height > (console->display.height - VERT_BORDER - TOTAL_MARGIN * 2 - DROP_SHADOW)) ! 1130: height = console->display.height - VERT_BORDER - TOTAL_MARGIN * 2 - DROP_SHADOW; ! 1131: width &= 0xfffffffe; ! 1132: ! 1133: // ! 1134: // Init console window variables. The window is centered in the ! 1135: // ! screen, minus a pixel or two to guarantee double word alignment ! 1136: // ! for the first pixel of a row (until further developments...when ! 1137: // ! we do alert panels, we can enumerate some cases here...). ! 1138: // ! 1139: console->window_origin_x = (console->display.width - width) / 2; ! 1140: console->window_origin_y = (console->display.height - height) / 2; ! 1141: console->pixels_per_row = width; ! 1142: console->pixels_per_column = height; ! 1143: (unsigned)console->window_origin_x &= 0xfffffffe; ! 1144: ! 1145: UpdateWindowChars(console); ! 1146: ! 1147: console->curr_column = 0; ! 1148: console->has_title = FALSE; ! 1149: ! 1150: if (initWindow) { ! 1151: // Before we start drawing anything, save under if needed ! 1152: if (saveUnder) { ! 1153: int i, bytesPerPixel = 0; ! 1154: unsigned char *save, *sp; ! 1155: ! 1156: // Compute size of save under region in bytes and allocate ! 1157: switch (console->display.bitsPerPixel) { ! 1158: case IO_8BitsPerPixel: bytesPerPixel = 1; break; ! 1159: case IO_12BitsPerPixel: ! 1160: case IO_15BitsPerPixel: bytesPerPixel = 2; break; ! 1161: case IO_24BitsPerPixel: bytesPerPixel = 4; break; ! 1162: } ! 1163: console->saveHeight = height + TOTAL_MARGIN * 2 + DROP_SHADOW; ! 1164: console->saveRowBytes = (width + TOTAL_MARGIN * 2 + DROP_SHADOW)*bytesPerPixel; ! 1165: console->saveBytes = console->saveHeight*console->saveRowBytes; ! 1166: save = console->saveBits = (unsigned char *) ! 1167: kalloc_noblock(console->saveBytes); ! 1168: sp = console->saveLocation = ! 1169: PixelAddress(console, console->window_origin_x - TOTAL_MARGIN, ! 1170: console->window_origin_y - TOTAL_MARGIN); ! 1171: ! 1172: // Copy the window contents into the save under ! 1173: if( save) ! 1174: for (i = console->saveHeight; i != 0; i--) { ! 1175: videoMemMove(save, sp, console->saveRowBytes); ! 1176: sp += console->display.rowBytes; ! 1177: save += console->saveRowBytes; ! 1178: } ! 1179: } ! 1180: ! 1181: // New window - cursor at origin. ! 1182: console->curr_row = 0; ! 1183: console->has_title = FALSE; ! 1184: ! 1185: // Draw the border. The border goes outside of the specified ! 1186: // window. Outside lines are black; inside lines are ! 1187: // half-tone. ! 1188: Rect(console, // outside top ! 1189: console->window_origin_x - TOTAL_MARGIN, ! 1190: console->window_origin_y - TOTAL_MARGIN, ! 1191: width + TOTAL_MARGIN * 2, ! 1192: FG_MARGIN, ! 1193: console->foreground); ! 1194: Rect(console, // inside top ! 1195: console->window_origin_x - BG_MARGIN, ! 1196: console->window_origin_y - BG_MARGIN, ! 1197: width + BG_MARGIN * 2, ! 1198: BG_MARGIN, ! 1199: console->background); ! 1200: Rect(console, // inside bottom ! 1201: console->window_origin_x - BG_MARGIN, ! 1202: console->window_origin_y + height, ! 1203: width + BG_MARGIN * 2, ! 1204: BG_MARGIN, ! 1205: console->background); ! 1206: Rect(console, // outside bottom ! 1207: console->window_origin_x - TOTAL_MARGIN, ! 1208: console->window_origin_y + height + BG_MARGIN, ! 1209: width + TOTAL_MARGIN * 2, ! 1210: FG_MARGIN, ! 1211: console->foreground); ! 1212: if( DROP_SHADOW) Rect(console, // outside bottom shadow ! 1213: console->window_origin_x - TOTAL_MARGIN + DROP_SHADOW, ! 1214: console->window_origin_y + height + BG_MARGIN + DROP_SHADOW, ! 1215: width + TOTAL_MARGIN * 2, ! 1216: DROP_SHADOW, ! 1217: console->dark_grey); ! 1218: Rect(console, // outside left ! 1219: console->window_origin_x - TOTAL_MARGIN, ! 1220: console->window_origin_y - TOTAL_MARGIN, ! 1221: FG_MARGIN, ! 1222: height + TOTAL_MARGIN * 2, ! 1223: console->foreground); ! 1224: Rect(console, // inside left ! 1225: console->window_origin_x - BG_MARGIN, ! 1226: console->window_origin_y - BG_MARGIN, ! 1227: BG_MARGIN, ! 1228: height + BG_MARGIN * 2, ! 1229: console->background); ! 1230: Rect(console, // inside right ! 1231: console->window_origin_x + width, ! 1232: console->window_origin_y - BG_MARGIN, ! 1233: BG_MARGIN, ! 1234: height + BG_MARGIN * 2, ! 1235: console->background); ! 1236: Rect(console, // outside right ! 1237: console->window_origin_x + width + BG_MARGIN, ! 1238: console->window_origin_y - TOTAL_MARGIN, ! 1239: FG_MARGIN, ! 1240: height + TOTAL_MARGIN * 2, ! 1241: console->foreground); ! 1242: if( DROP_SHADOW) Rect(console, // outside right shadow ! 1243: console->window_origin_x + width + BG_MARGIN + DROP_SHADOW, ! 1244: console->window_origin_y - TOTAL_MARGIN + DROP_SHADOW, ! 1245: DROP_SHADOW, ! 1246: height + TOTAL_MARGIN * 2, ! 1247: console->dark_grey); ! 1248: ! 1249: // Clear the contents of the window and draw a cursor. ! 1250: ClearWindow(console); ! 1251: FlipCursor(console); // cursor on ! 1252: SetTitle(console, title); ! 1253: } ! 1254: else { ! 1255: /* Leave current window contents, just updating title. ! 1256: * We'll do a newline to make sure we have room for ! 1257: * our font and proceed.Initial cursor will be at ! 1258: * lower left corner. ! 1259: */ ! 1260: console->curr_row = console->chars_per_column - 1; ! 1261: SetTitle(console, title); ! 1262: FBPutC(console, '\n'); ! 1263: } ! 1264: return; ! 1265: } ! 1266: ! 1267: // ! 1268: // END: Private utility routines ! 1269: // ! 1270: ! 1271: // ! 1272: // BEGIN: Implementation of IOConsoleInfo functions ! 1273: // ! 1274: static void Free(IOConsoleInfo *cso) ! 1275: // Description: Free a FB Console object ! 1276: { ! 1277: IOFree(cso->priv, sizeof(ConsoleRep)); ! 1278: IOFree(cso, sizeof(IOConsoleInfo)); ! 1279: } ! 1280: ! 1281: static void Init( ! 1282: IOConsoleInfo *cso, ! 1283: ScreenMode mode, ! 1284: boolean_t initScreenOrSaveUnder, ! 1285: boolean_t initWindow, ! 1286: const char *title) ! 1287: { ! 1288: ConsolePtr console = (ConsolePtr)cso->priv; ! 1289: int i; ! 1290: ! 1291: switch (console->display.bitsPerPixel) { ! 1292: case IO_8BitsPerPixel: ! 1293: if (console->display.colorSpace == IO_OneIsWhiteColorSpace) { ! 1294: console->baseground = (TRUE || (mode == SCM_GRAPHIC)) ? 107 : 0x55; ! 1295: console->background = 0xff; ! 1296: console->foreground = 0x00; ! 1297: console->dark_grey = 85; ! 1298: console->light_grey = 187; ! 1299: } else { ! 1300: console->baseground = (TRUE || (mode == SCM_GRAPHIC)) ? 0x80 : 0x7e; ! 1301: console->background = 0x00; ! 1302: console->foreground = 0xff; ! 1303: console->dark_grey = 0xfb; ! 1304: console->light_grey = 0xf7; ! 1305: } ! 1306: break; ! 1307: case IO_15BitsPerPixel: ! 1308: console->baseground = (TRUE || (mode == SCM_GRAPHIC)) ? 0x3193 : 0x295f; ! 1309: console->background = 0x7fff; ! 1310: console->foreground = 0x0000; ! 1311: console->dark_grey = 0x294a; ! 1312: console->light_grey = 0x5ef7; ! 1313: break; ! 1314: case IO_24BitsPerPixel: ! 1315: console->baseground = (TRUE || (mode == SCM_GRAPHIC)) ? 0xff666699 : 0xff5555ff; ! 1316: console->background = 0xffffffff; ! 1317: console->foreground = 0xff000000; ! 1318: console->dark_grey = 0xff555555; ! 1319: console->light_grey = 0xffbbbbbb; ! 1320: break; ! 1321: } ! 1322: ! 1323: console->grayTable[0] = console->background; ! 1324: console->grayTable[1] = console->light_grey; ! 1325: console->grayTable[2] = console->dark_grey; ! 1326: console->grayTable[3] = console->foreground; ! 1327: ! 1328: console->ansi_state = AS_NORMAL; ! 1329: for(i=0; i<ANSI_STACK_SIZE; i++) { ! 1330: console->ansi_stack[i] = 0; ! 1331: } ! 1332: console->ansi_stack_p = &console->ansi_stack[1]; // FIXME - why not 0? ! 1333: ! 1334: // Initialize the screen, if appropriate. ! 1335: if (initScreenOrSaveUnder && (mode != SCM_ALERT)) { ! 1336: WipeScreen(console, console->baseground); ! 1337: } ! 1338: ! 1339: console->window_type = mode; ! 1340: switch(console->window_type) { ! 1341: case SCM_TEXT: ! 1342: InitWindow(console, TEXT_WIN_WIDTH, TEXT_WIN_HEIGHT, ! 1343: title, initWindow, 0 /* Don't save under */); ! 1344: break; ! 1345: case SCM_ALERT: ! 1346: InitWindow(console, ALERT_WIN_WIDTH, ALERT_WIN_HEIGHT, ! 1347: title, initWindow, initScreenOrSaveUnder ); ! 1348: break; ! 1349: case SCM_GRAPHIC: ! 1350: if( initScreenOrSaveUnder) { ! 1351: int cx, cy; ! 1352: ! 1353: cx = console->display.width / 2; ! 1354: cy = console->display.height / 2; ! 1355: Expand4ToN( console, cx + RIGHT_DX, cy + RIGHT_DY, ! 1356: RIGHT_WIDTH, RIGHT_HEIGHT, rightData, rightBotColors ); ! 1357: Expand4ToN( console, cx + CENTER_DX, cy + CENTER_DY, ! 1358: CENTER_WIDTH, CENTER_HEIGHT, centerData, centerColors ); ! 1359: Expand4ToN( console, cx + BOTTOM_DX, cy + BOTTOM_DY, ! 1360: BOTTOM_WIDTH, BOTTOM_HEIGHT, bottomData, rightBotColors ); ! 1361: } ! 1362: break; ! 1363: ! 1364: default: ! 1365: panic("FBConsole/FBInitConsole: can't init"); ! 1366: break; ! 1367: } ! 1368: return; ! 1369: } ! 1370: ! 1371: static int Restore(IOConsoleInfo *cso) ! 1372: { ! 1373: ConsolePtr console = (ConsolePtr)cso->priv; ! 1374: unsigned char *save, *dp; ! 1375: int i; ! 1376: ! 1377: if (console->window_type != SCM_ALERT) { ! 1378: IOLog("frameBuffer: bogus restore, mode %d\n", console->window_type); ! 1379: return -1; ! 1380: } ! 1381: ! 1382: // Copy save under bits back onto screen ! 1383: save = console->saveBits; ! 1384: dp = console->saveLocation; ! 1385: if( save) { ! 1386: for (i = console->saveHeight; i != 0; i--) { ! 1387: videoMemMove(dp, save, console->saveRowBytes); ! 1388: dp += console->display.rowBytes; ! 1389: save += console->saveRowBytes; ! 1390: } ! 1391: ! 1392: // Free bits ! 1393: kfree(console->saveBits, console->saveBytes); ! 1394: console->saveBits = 0; ! 1395: } ! 1396: return 0; ! 1397: } ! 1398: ! 1399: #define VIDEO_W 640 ! 1400: #define VIDEO_H 480 ! 1401: ! 1402: static int DrawRect(IOConsoleInfo *cso, const struct km_drawrect *km_rect) ! 1403: // Description: Given a 2 bit raster, convert it to the format appropriate for ! 1404: // the display. The co-ordinates passed in by these ioctls assume ! 1405: // an (VIDEO_W x VIDEO_H) screen. All screen sizes are ! 1406: // assumed to share a common center point. We scale the X and Y ! 1407: // values to maintain a constant offset from the center point, ! 1408: // so that boot animations, popup windows, and related goodies ! 1409: // don't break with screens larger or smaller than the 'default' ! 1410: // screen. ! 1411: // Preconditions: ! 1412: // * The rectangle that we are to draw must start on a 4 pixel boundary ! 1413: // and should be a multiple of 4 pixels in width. ! 1414: { ! 1415: ConsolePtr console = (ConsolePtr)cso->priv; ! 1416: int pixel; /* Starting pixel in screen */ ! 1417: int i, x, y; ! 1418: unsigned char *data; ! 1419: unsigned char value; ! 1420: unsigned int * table; ! 1421: struct km_drawrect *rect = (struct km_drawrect *) km_rect; ! 1422: int bgX, bgY, bgH; ! 1423: unsigned char * bg; ! 1424: ! 1425: table = console->grayTable; ! 1426: ! 1427: /* copyin is done in km */ ! 1428: data = rect->data.bits; ! 1429: ! 1430: x = (rect->x & 0x1ffc) + (console->display.width - VIDEO_W)/2; ! 1431: y = rect->y + (console->display.height - VIDEO_H)/2; ! 1432: ! 1433: /* Correct the x and y values for screen size */ ! 1434: if( (rect->x & 3) == 3) { ! 1435: DrawColorRect( console, x, y, rect->width, rect->height, data); ! 1436: return 0; ! 1437: } ! 1438: ! 1439: #if TEXTURE_BACKGND ! 1440: bgX = console->display.width / 2 + CENTER_DX; ! 1441: bgY = console->display.height / 2 + CENTER_DY; ! 1442: ! 1443: bgH = (y - bgY) & -2; ! 1444: if( bgH > 0) { ! 1445: bgY += bgH; ! 1446: bg = centerData + (bgH * CENTER_WIDTH) / 2; ! 1447: bgH = CENTER_HEIGHT - bgH; ! 1448: } else ! 1449: bg = (unsigned char *)0; ! 1450: #endif ! 1451: ! 1452: rect->x &= 0x1ffc; ! 1453: ! 1454: /* Sanity check */ ! 1455: if ((x + rect->width > console->display.width) ! 1456: || (y + rect->height) > console->display.height) ! 1457: return( -1 ); ! 1458: ! 1459: ! 1460: pixel = x + (y * console->display.totalWidth); ! 1461: ! 1462: switch ( console->display.bitsPerPixel ) ! 1463: { ! 1464: case IO_2BitsPerPixel: /* 2 bit pixels */ ! 1465: { ! 1466: unsigned char *dst = (unsigned char *)console->display.frameBuffer; ! 1467: unsigned char *fb; ! 1468: unsigned char final_value; ! 1469: ! 1470: dst += pixel >> 2; ! 1471: for ( y = 0; y < rect->height; ++y ) { ! 1472: fb = dst; ! 1473: for ( x = 0; x < rect->width; x += 4) { ! 1474: value = *data++; ! 1475: final_value = 0; ! 1476: for ( i = 0; i < 8; i += 2 ) { ! 1477: final_value |= ((table[(value>>i)&3] & 3) << i); ! 1478: } ! 1479: *fb++ = final_value; ! 1480: } ! 1481: dst += console->display.rowBytes; ! 1482: } ! 1483: break; ! 1484: } ! 1485: case IO_8BitsPerPixel: /* 8 bit pixels */ ! 1486: { ! 1487: unsigned char *dst = (unsigned char *)console->display.frameBuffer; ! 1488: unsigned char *fb; ! 1489: ! 1490: dst += pixel; ! 1491: for ( y = 0; y < rect->height; ++y ) { ! 1492: fb = dst; ! 1493: #if TEXTURE_BACKGND ! 1494: if( ((y & 1) == 0) && bg) { ! 1495: Expand4ToN( console, bgX, bgY, ! 1496: CENTER_WIDTH, 2, bg, centerColors ); ! 1497: bgY += 2; ! 1498: bg += CENTER_WIDTH; ! 1499: } ! 1500: #endif ! 1501: for ( x = 0; x < rect->width; x += 4) { ! 1502: value = *data++; ! 1503: if( value) { ! 1504: int pix; ! 1505: pix = (value >> 6) & 3; ! 1506: if( pix) ! 1507: fb[0] = table[pix]; ! 1508: pix = (value >> 4) & 3; ! 1509: if( pix) ! 1510: fb[1] = table[pix]; ! 1511: pix = (value >> 2) & 3; ! 1512: if( pix) ! 1513: fb[2] = table[pix]; ! 1514: pix = value & 3; ! 1515: if( pix) ! 1516: fb[3] = table[pix]; ! 1517: } ! 1518: fb += 4; ! 1519: } ! 1520: dst += console->display.rowBytes; ! 1521: } ! 1522: break; ! 1523: } ! 1524: case IO_12BitsPerPixel: /* 16 bit pixels */ ! 1525: case IO_15BitsPerPixel: /* 16 bit pixels */ ! 1526: { ! 1527: ! 1528: unsigned short *dst = (unsigned short *)console->display.frameBuffer; ! 1529: unsigned short *fb; ! 1530: dst += pixel; ! 1531: ! 1532: for ( y = 0; y < rect->height; ++y ) { ! 1533: fb = dst; ! 1534: #if TEXTURE_BACKGND ! 1535: if( ((y & 1) == 0) && bg) { ! 1536: Expand4ToN( console, bgX, bgY, ! 1537: CENTER_WIDTH, 2, bg, centerColors ); ! 1538: bgY += 2; ! 1539: bg += CENTER_WIDTH; ! 1540: } ! 1541: #endif ! 1542: for ( x = 0; x < rect->width; x += 4) { ! 1543: value = *data++; ! 1544: if( value) { ! 1545: int pix; ! 1546: pix = (value >> 6) & 3; ! 1547: if( pix) ! 1548: fb[0] = table[pix]; ! 1549: pix = (value >> 4) & 3; ! 1550: if( pix) ! 1551: fb[1] = table[pix]; ! 1552: pix = (value >> 2) & 3; ! 1553: if( pix) ! 1554: fb[2] = table[pix]; ! 1555: pix = value & 3; ! 1556: if( pix) ! 1557: fb[3] = table[pix]; ! 1558: } ! 1559: fb += 4; ! 1560: } ! 1561: dst = (unsigned short *)(((char*)dst) + ! 1562: console->display.rowBytes); ! 1563: } ! 1564: break; ! 1565: } ! 1566: case IO_24BitsPerPixel: /* 32 bit pixels */ ! 1567: { ! 1568: unsigned int *dst = (unsigned int *) console->display.frameBuffer; ! 1569: unsigned int *fb; ! 1570: ! 1571: dst += pixel; ! 1572: for ( y = 0; y < rect->height; ++y ) { ! 1573: fb = dst; ! 1574: #if TEXTURE_BACKGND ! 1575: if( ((y & 1) == 0) && bg) { ! 1576: Expand4ToN( console, bgX, bgY, ! 1577: CENTER_WIDTH, 2, bg, centerColors ); ! 1578: bgY += 2; ! 1579: bg += CENTER_WIDTH; ! 1580: } ! 1581: #endif ! 1582: for ( x = 0; x < rect->width; x += 4) { ! 1583: value = *data++; ! 1584: if( value) { ! 1585: int pix; ! 1586: pix = (value >> 6) & 3; ! 1587: if( pix) ! 1588: fb[0] = table[pix]; ! 1589: pix = (value >> 4) & 3; ! 1590: if( pix) ! 1591: fb[1] = table[pix]; ! 1592: pix = (value >> 2) & 3; ! 1593: if( pix) ! 1594: fb[2] = table[pix]; ! 1595: pix = value & 3; ! 1596: if( pix) ! 1597: fb[3] = table[pix]; ! 1598: } ! 1599: fb += 4; ! 1600: } ! 1601: dst = (unsigned int *)(((char*)dst) + ! 1602: console->display.rowBytes); ! 1603: } ! 1604: break; ! 1605: } ! 1606: } ! 1607: return 0; ! 1608: } ! 1609: ! 1610: static int EraseRect(IOConsoleInfo *cso, const struct km_drawrect *km_rect) ! 1611: // Description: Erase the specified rectangle to the color specified ! 1612: // in the km_rect structure. ! 1613: // Preconditions: ! 1614: // * The rectangle that we are to erase must start on a 4 pixel boundary ! 1615: // and should be a multiple of 4 pixels in width. ! 1616: { ! 1617: ConsolePtr console = (ConsolePtr)cso->priv; ! 1618: int pixel; // Starting pixel in screen ! 1619: int x, y, w, h; ! 1620: unsigned int value; ! 1621: struct km_drawrect *rect = (struct km_drawrect *) km_rect; ! 1622: int bgX, bgY, bgH; ! 1623: unsigned char * bg; ! 1624: ! 1625: value = console->grayTable[ rect->data.fill & 3 ]; ! 1626: ! 1627: /* Correct the x and y values for screen size */ ! 1628: x = rect->x + (console->display.width - VIDEO_W)/2; ! 1629: y = rect->y + (console->display.height - VIDEO_H)/2; ! 1630: ! 1631: x &= ~3; // Trunc to 4 pixel boundary ! 1632: w = (rect->width) & ~3; // Round dn to 4 pixel boundary ! 1633: h = rect->height; ! 1634: ! 1635: /* Sanity check */ ! 1636: /* Sanity check */ ! 1637: if (((x + w) > console->display.width) ! 1638: || ((y + h) > console->display.height) ) ! 1639: return( -1 ); ! 1640: ! 1641: ! 1642: #if TEXTURE_BACKGND ! 1643: bgX = console->display.width / 2 + CENTER_DX; ! 1644: bgY = console->display.height / 2 + CENTER_DY; ! 1645: ! 1646: bgH = (y - bgY) & -2; ! 1647: if( bgH > 0) { ! 1648: bgY += bgH; ! 1649: bg = centerData + (bgH * CENTER_WIDTH) / 2; ! 1650: bgH = CENTER_HEIGHT - bgH; ! 1651: Expand4ToN( console, bgX, bgY, ! 1652: CENTER_WIDTH, bgH, bg, centerColors ); ! 1653: } ! 1654: ! 1655: #else ! 1656: Rect( console, x, y, w, h, value); ! 1657: #endif ! 1658: ! 1659: return 0; ! 1660: } ! 1661: ! 1662: //extern void czputc( char c); ! 1663: ! 1664: static void PutC(IOConsoleInfo *cso, char c) ! 1665: // Write one character to screen. Cursor is 'on' on entry and exit. ! 1666: { ! 1667: FBPutC((ConsolePtr)cso->priv, c); ! 1668: // czputc(c); ! 1669: } ! 1670: ! 1671: static void GetSize(IOConsoleInfo *cso, struct ConsoleSize *s) ! 1672: // Return the size of the screen in pixels ! 1673: { ! 1674: ConsolePtr console = (ConsolePtr)cso->priv; ! 1675: s->cols = console->chars_per_row; ! 1676: s->rows = console->chars_per_column; ! 1677: s->pixel_width = console->display.width; ! 1678: s->pixel_height = console->display.height; ! 1679: } ! 1680: ! 1681: // ! 1682: // END: Implementation of IOConsoleInfo functions ! 1683: // ! 1684: ! 1685: static IOConsoleInfo staticConsoleInfo; ! 1686: static ConsoleRep staticConsoleRep; ! 1687: ! 1688: static void InitializeConsole( IOConsoleInfo *cso, IODisplayInfo *display ) ! 1689: { ! 1690: cso->Init = Init; ! 1691: cso->Restore = Restore; ! 1692: cso->DrawRect = DrawRect; ! 1693: cso->EraseRect = EraseRect; ! 1694: cso->PutC = PutC; ! 1695: cso->GetSize = GetSize; ! 1696: ((ConsolePtr)cso->priv)->display = *display; ! 1697: ((ConsolePtr)cso->priv)->window_type = SCM_UNINIT; ! 1698: return; ! 1699: } ! 1700: ! 1701: // ! 1702: // BEGIN: Exported routines ! 1703: // ! 1704: ! 1705: static void DoNothing(IOConsoleInfo *cso) ! 1706: { ! 1707: } ! 1708: ! 1709: IOConsoleInfo *BasicAllocateConsole(IODisplayInfo *display) ! 1710: { ! 1711: // No memory allocation. Assume non backed window. ! 1712: IOConsoleInfo *cso = &staticConsoleInfo; ! 1713: cso->priv = (void *)&staticConsoleRep; ! 1714: InitializeConsole(cso, display); ! 1715: cso->Free = DoNothing; ! 1716: #if 0 ! 1717: printf("base:%x rowBytes:%x width:%x height:%x\n",display->frameBuffer, ! 1718: display->rowBytes, display->width, display->height); ! 1719: #endif ! 1720: return cso; ! 1721: } ! 1722: ! 1723: ! 1724: IOConsoleInfo *FBAllocateConsole(IODisplayInfo *display) ! 1725: { ! 1726: IOConsoleInfo *cso = (IOConsoleInfo *)IOMalloc(sizeof(IOConsoleInfo)); ! 1727: ! 1728: if (cso == NIL) ! 1729: return NIL; ! 1730: cso->priv = (void *)IOMalloc(sizeof(ConsoleRep)); ! 1731: if (cso->priv == NIL) ! 1732: { ! 1733: IOFree(cso, sizeof(IOConsoleInfo)); ! 1734: return NIL; ! 1735: } ! 1736: InitializeConsole(cso, display); ! 1737: cso->Free = Free; ! 1738: return cso; ! 1739: } ! 1740: ! 1741: ! 1742: // ! 1743: // END: Exported routines ! 1744: //
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.