Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1451 lines
32 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. disp_gr.c
  5. Abstract:
  6. This file was created from \private\windows\setup\textmode\splib\ixdispj.c.
  7. This file contains routines to display MBCS characters to the Graphics
  8. VRAM.
  9. Author:
  10. v-junm (Compaq Japan)
  11. hideyukn
  12. tedm
  13. Environment:
  14. Kernel mode only.
  15. Revision History:
  16. --*/
  17. #include "bootx86.h"
  18. #include "displayp.h"
  19. #include "bootfont.h"
  20. #include "vmode.h"
  21. //
  22. // Physical video attributes.
  23. //
  24. #define VIDEO_BUFFER_VA 0xa0000
  25. #define VIDEO_BYTES_PER_SCAN_LINE 80
  26. #define VIDEO_WIDTH_PIXELS 640
  27. #define VIDEO_HEIGHT_SCAN_LINES 480
  28. #define VIDEO_SIZE_BYTES (VIDEO_BYTES_PER_SCAN_LINE*VIDEO_HEIGHT_SCAN_LINES)
  29. PUCHAR GrVp = (PUCHAR)VIDEO_BUFFER_VA;
  30. //
  31. // Screen width and height in half-character cells
  32. // and macro to determine total number of characters
  33. // displayed on the screen at once.
  34. //
  35. unsigned ScreenWidthCells,ScreenHeightCells;
  36. #define SCREEN_SIZE_CELLS (ScreenWidthCells*ScreenHeightCells)
  37. //
  38. // Globals:
  39. //
  40. // CharacterCellHeight is the number of scan lines total in a character.
  41. // It includes any top or bottom fill lines.
  42. //
  43. // CharacterImageHeight is the number of scan lines in the image of a character.
  44. // This is dependent on the font. Characters may be padded top and bottom.
  45. //
  46. // NOTE: All of this code assumes the font's single-byte characters are 8 bits wide
  47. // and the font's double-byte characters are 16 bits wide!
  48. //
  49. unsigned CharacterCellHeight;
  50. unsigned CharacterImageHeight;
  51. unsigned CharacterTopPad;
  52. unsigned CharacterBottomPad;
  53. #define VIDEO_BYTES_PER_TEXT_ROW (VIDEO_BYTES_PER_SCAN_LINE*CharacterCellHeight)
  54. //
  55. // Values describing the number of each type of character in the font,
  56. // and pointers to the base of the glyphs.
  57. //
  58. unsigned SbcsCharCount;
  59. unsigned DbcsCharCount;
  60. PUCHAR SbcsImages;
  61. PUCHAR DbcsImages;
  62. //
  63. // Values to be passed to GrDisplayMBCSChar
  64. //
  65. #define SBCSWIDTH 8
  66. #define DBCSWIDTH 16
  67. //
  68. // Lead byte table. Read from bootfont.bin.
  69. //
  70. UCHAR LeadByteTable[2*(MAX_DBCS_RANGE+1)];
  71. //
  72. // keeps track as to whether to reset the
  73. // display in TextGrTerminate().
  74. //
  75. BOOLEAN AllowGraphicsReset = TRUE;
  76. VOID
  77. GrDisplayMBCSChar(
  78. IN PUCHAR image,
  79. IN unsigned width,
  80. IN UCHAR top,
  81. IN UCHAR bottom
  82. );
  83. PUCHAR
  84. GrGetDBCSFontImage(
  85. USHORT Code
  86. );
  87. PUCHAR
  88. GrGetSBCSFontImage(
  89. UCHAR Code
  90. );
  91. VOID
  92. GrWriteSBCSChar(
  93. IN UCHAR c
  94. )
  95. /*++
  96. Routine Description:
  97. Displays a character at the current cursor position. ONLY SBCS
  98. characters can be displayed using this routine.
  99. Arguments:
  100. c - character to display.
  101. Return Value:
  102. None.
  103. --*/
  104. {
  105. unsigned u;
  106. PUCHAR pImage;
  107. UCHAR temp;
  108. switch(c) {
  109. case '\n':
  110. if(TextRow == (ScreenHeightCells-1)) {
  111. TextGrScrollDisplay();
  112. TextSetCursorPosition(0,TextRow);
  113. } else {
  114. TextSetCursorPosition(0,TextRow+1);
  115. }
  116. break;
  117. case '\r':
  118. break; // ignore
  119. case '\t':
  120. temp = ' ';
  121. u = 8 - (TextColumn % 8);
  122. while(u--) {
  123. TextGrCharOut(&temp);
  124. }
  125. TextSetCursorPosition(TextColumn+u,TextRow);
  126. break;
  127. default:
  128. //
  129. // Assume it's a valid SBCS character.
  130. // Get font image for SBCS char.
  131. //
  132. pImage = GrGetSBCSFontImage(c);
  133. //
  134. // Display the SBCS char. Check for special graphics characters.
  135. // Add top and bottom extra pixels accordingly (otherwise the grids
  136. // don't connect properly, because of top and bottom spacing).
  137. //
  138. if ( c == 0x2 || c == 0x1 || c == 0x16 )
  139. GrDisplayMBCSChar( pImage, SBCSWIDTH, 0x00, 0x66 );
  140. else if ( c == 0x4 || c == 0x3 || c == 0x15 )
  141. GrDisplayMBCSChar( pImage, SBCSWIDTH, 0x66, 0x00 );
  142. else if ( c == 0x5 || c == 10 || c == 0x17 || c == 0x19 )
  143. GrDisplayMBCSChar( pImage, SBCSWIDTH, 0x66, 0x66 );
  144. else
  145. GrDisplayMBCSChar( pImage, SBCSWIDTH, 0x00, 0x00 );
  146. }
  147. }
  148. VOID
  149. GrDisplayMBCSChar(
  150. IN PUCHAR image,
  151. IN unsigned width,
  152. IN UCHAR top,
  153. IN UCHAR bottom
  154. )
  155. /*++
  156. Routine Description:
  157. Displays a DBCS or a SBCS character at the current cursor
  158. position.
  159. Arguments:
  160. image - SBCS or DBCS font image.
  161. width - Width in bits of character image (must be SBCSWIDTH pr DBCSWIDTH).
  162. top - Character to fill the top extra character line(s).
  163. bottom- Character to fill the bottom extra character line(s).
  164. Return Value:
  165. FALSE if image points to NULL,
  166. else TRUE.
  167. --*/
  168. {
  169. unsigned i;
  170. //
  171. // Validate parameter
  172. //
  173. if(image == NULL) {
  174. return;
  175. }
  176. //
  177. // There are TOP_EXTRA lines at the top that we need to skip (background color).
  178. //
  179. for(i=0; i<CharacterTopPad; i++) {
  180. //
  181. // If DBCS char, we need to clear 2 bytes.
  182. //
  183. if(width == DBCSWIDTH) {
  184. *GrVp++ = top;
  185. }
  186. *GrVp++ = top;
  187. //
  188. // Position pointer at next scan line
  189. // for the font image.
  190. //
  191. GrVp += VIDEO_BYTES_PER_SCAN_LINE - (width/SBCSWIDTH);
  192. }
  193. //
  194. // Display full height of DBCS or SBCS char.
  195. //
  196. for(i=0; i<CharacterImageHeight; i++) {
  197. //
  198. // If DBCS char, need to display 2 bytes,
  199. // so display first byte here.
  200. //
  201. if(width == DBCSWIDTH) {
  202. *GrVp++ = *image++;
  203. }
  204. //
  205. // Display 2nd byte of DBCS char or the
  206. // first and only byte of SBCS char.
  207. //
  208. *GrVp++ = *image++;
  209. //
  210. // Increment GrVP to display location of
  211. // next row of font image.
  212. //
  213. GrVp += VIDEO_BYTES_PER_SCAN_LINE - (width/SBCSWIDTH);
  214. }
  215. //
  216. // There are BOT_EXTRA lines at the bottom that we need to fill with the
  217. // background color.
  218. //
  219. for(i=0; i<CharacterBottomPad; i++) {
  220. //
  221. // If DBCS char, need to clear 2 bytes
  222. //
  223. if(width == DBCSWIDTH) {
  224. *GrVp++ = bottom;
  225. }
  226. *GrVp++ = bottom;
  227. //
  228. // Position pointer at next scan line
  229. // for the font image.
  230. //
  231. GrVp += VIDEO_BYTES_PER_SCAN_LINE - (width/SBCSWIDTH);
  232. }
  233. //
  234. // Increment cursor and video pointer
  235. //
  236. if(width == DBCSWIDTH) {
  237. TextSetCursorPosition(TextColumn+2,TextRow);
  238. } else {
  239. TextSetCursorPosition(TextColumn+1,TextRow);
  240. }
  241. }
  242. unsigned
  243. GrWriteMBCSString(
  244. IN PUCHAR String,
  245. IN unsigned MaxChars
  246. )
  247. /*++
  248. Routine Description:
  249. Displays a mixed byte string at the current cursor
  250. position.
  251. Arguments:
  252. String - supplies pointer to asciz string.
  253. MaxBytes - supplies the maximum number of characters to be written.
  254. Return Value:
  255. Number of bytes written.
  256. --*/
  257. {
  258. PUCHAR pImage;
  259. USHORT DBCSChar;
  260. unsigned BytesWritten;
  261. BytesWritten = 0;
  262. //
  263. // While string is not NULL,
  264. // get font image and display it.
  265. //
  266. while(*String && MaxChars--) {
  267. //
  268. // Determine if char is SBCS or DBCS, get the correct font image,
  269. // and display it.
  270. //
  271. if(GrIsDBCSLeadByte(*String)) {
  272. DBCSChar = *String++ << 8;
  273. DBCSChar = DBCSChar | *String++;
  274. pImage = GrGetDBCSFontImage(DBCSChar);
  275. GrDisplayMBCSChar(pImage,DBCSWIDTH,0x00,0x00);
  276. BytesWritten++;
  277. } else {
  278. GrWriteSBCSChar(*String++);
  279. }
  280. BytesWritten++;
  281. }
  282. return(BytesWritten);
  283. }
  284. BOOLEAN
  285. GrIsDBCSLeadByte(
  286. IN UCHAR c
  287. )
  288. /*++
  289. Routine Description:
  290. Checks to see if a char is a DBCS leadbyte.
  291. Arguments:
  292. c - char to check if leadbyte or not.
  293. Return Value:
  294. TRUE - Leadbyte.
  295. FALSE - Non-Leadbyte.
  296. --*/
  297. {
  298. int i;
  299. //
  300. // Check to see if char is in leadbyte range.
  301. // Note if (CHAR)(0) is a valid leadbyte,
  302. // this routine will fail.
  303. //
  304. for(i=0; LeadByteTable[i]; i+=2) {
  305. if((LeadByteTable[i] <= c) && (LeadByteTable[i+1] >= c)) {
  306. return(TRUE);
  307. }
  308. }
  309. return(FALSE);
  310. }
  311. PUCHAR
  312. GrGetDBCSFontImage(
  313. USHORT Code
  314. )
  315. /*++
  316. Routine Description:
  317. Gets the font image for DBCS char.
  318. Arguments:
  319. Code - DBCS char code.
  320. Return Value:
  321. Pointer to font image, or else NULL.
  322. --*/
  323. {
  324. int Min,Max,Mid;
  325. int Multiplier;
  326. int Index;
  327. USHORT code;
  328. Min = 0;
  329. Max = DbcsCharCount;
  330. // multiplier = 2 (for index) +
  331. // 2 * height +
  332. // 2 (for unicode encoding)
  333. //
  334. Multiplier = 2 + (2*CharacterImageHeight) + 2;
  335. //
  336. // Do a binary search for the image.
  337. // Format of table:
  338. // First 2 bytes contain the DBCS char code.
  339. // Next (2 * CharacterImageHeight) bytes are the char image.
  340. // Next 2 bytes are for unicode version.
  341. //
  342. while(Max >= Min) {
  343. Mid = (Max + Min) / 2;
  344. Index = Mid*Multiplier;
  345. code = (DbcsImages[Index] << 8) | DbcsImages[Index+1];
  346. if(Code == code) {
  347. return(DbcsImages+Index+2);
  348. }
  349. if(Code < code) {
  350. Max = Mid - 1;
  351. } else {
  352. Min = Mid + 1;
  353. }
  354. }
  355. //
  356. // ERROR: No image found.
  357. //
  358. return(NULL);
  359. }
  360. //
  361. // This array is used to override a glyph returned by GrGetSBCSFontImage.
  362. // Basically, if the user is asking for one of the first 6 glyphs from
  363. // the SBCS map, we'll intercept the call and return the value from this
  364. // array.
  365. //
  366. // This is because there was a previous assumption that the first 6 glyphs
  367. // in an SBCS image were drawing characters. The same 6 drawing characters.
  368. // That means we just introduced an external reliance on every bootfont.bin.
  369. // Better to keep the dependence right here.
  370. //
  371. UCHAR SbcsRemapper[6][18] = {
  372. // SBCS codes (16 bytes worth) Unicode value
  373. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x60, 0x60, 0x67, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x25, 0x54},
  374. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0xe6, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x25, 0x57},
  375. {0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x67, 0x60, 0x60, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x5A},
  376. {0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x5D},
  377. {0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x25, 0x51},
  378. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x50}
  379. };
  380. PUCHAR
  381. GrGetSBCSFontImage(
  382. UCHAR Code
  383. )
  384. /*++
  385. Routine Description:
  386. Gets the font image for SBCS char.
  387. Arguments:
  388. Code - SBCS char code.
  389. Return Value:
  390. Pointer to font image, or else NULL.
  391. --*/
  392. {
  393. int Max,Min,Mid;
  394. int Multiplier;
  395. int Index;
  396. //
  397. // WARNING: Nauseating hack!!
  398. // We're going to special case some drawing characters here because
  399. // these graphics characters may not exist in every locale. This is
  400. // where we'll supercede some of the bootfont.bin lookups with the
  401. // glyphs we really want.
  402. //
  403. // We're going to remap some low SBCS values to some specific drawing
  404. // glyphs.
  405. //
  406. // 1: "top left corner" double-line. Corresponds to ANSI code 0xC9 and unicode 0x2554
  407. // ----
  408. // | --
  409. // | |
  410. // | |
  411. //
  412. //
  413. // 2. "top right corner" double-line. Corresponds to ANSI code 0xBB and unicode 0x2557
  414. // ----
  415. // -- |
  416. // | |
  417. // | |
  418. //
  419. // 3. "bottom left corner". Corresponds to ANSI code 0xC8 and unicode 0x255A
  420. // 4. "bottom right corner". Corresponds to ANSI code 0xBC and unicode 0x255D
  421. // 5. "double verticl line". Corresponds to ANSI code 0xBA and unicode 0x2551
  422. // 6. "double horizontal line". Corresponds to ANSI code 0xCD and unicode 0x2550
  423. //
  424. if( (Code >= 0x1) && (Code <= 0x6) ) {
  425. return SbcsRemapper[Code-1];
  426. }
  427. Min = 0;
  428. Max = SbcsCharCount;
  429. // multiplier = 1 (for index) +
  430. // height +
  431. // 2 (for unicode encoding)
  432. //
  433. Multiplier = 1 + (CharacterImageHeight) + 2;
  434. //
  435. // Do a binary search for the image.
  436. // Format of table:
  437. // First byte contains the SBCS char code.
  438. // Next (CharacterImageHeight) bytes are the char image.
  439. // Next 2 bytes are for unicode version.
  440. //
  441. while(Max >= Min) {
  442. Mid = (Max + Min) / 2;
  443. Index = Mid*Multiplier;
  444. if(Code == SbcsImages[Index]) {
  445. return(SbcsImages+Index+1);
  446. }
  447. if(Code < SbcsImages[Index]) {
  448. Max = Mid - 1;
  449. } else {
  450. Min = Mid + 1;
  451. }
  452. }
  453. //
  454. // ERROR: No image found.
  455. //
  456. return(NULL);
  457. }
  458. //
  459. // Need to turn off optimization for this
  460. // routine. Since the write and read to
  461. // GVRAM seem useless to the compiler.
  462. //
  463. #pragma optimize( "", off )
  464. VOID
  465. TextGrSetCurrentAttribute(
  466. IN UCHAR Attribute
  467. )
  468. /*++
  469. Routine Description:
  470. Sets the attribute by setting up various VGA registers.
  471. The comments only say what registers are set to what, so
  472. to understand the logic, follow the code while looking at
  473. Figure 5-5 of PC&PS/2 Video Systems by Richard Wilton.
  474. The book is published by Microsoft Press.
  475. Arguments:
  476. Attribute - New attribute to set to.
  477. Attribute:
  478. High nibble - background attribute.
  479. Low nibble - foreground attribute.
  480. Return Value:
  481. Nothing.
  482. --*/
  483. {
  484. UCHAR temp = 0;
  485. //
  486. // Address of GVRAM off the screen.
  487. //
  488. PUCHAR OffTheScreen = (PUCHAR)(0xa9600);
  489. union WordOrByte {
  490. struct Word { unsigned short ax; } x;
  491. struct Byte { unsigned char al, ah; } h;
  492. } regs;
  493. //
  494. // Reset Data Rotate/Function Select
  495. // regisger.
  496. //
  497. outpw( 0x3ce, 0x3 ); // Need to reset Data Rotate/Function Select.
  498. //
  499. // Set Enable Set/Reset to
  500. // all (0f).
  501. //
  502. outpw( 0x3ce, 0xf01 );
  503. //
  504. // Put background color into Set/Reset register.
  505. // This is done to put the background color into
  506. // the latches later.
  507. //
  508. regs.x.ax = (unsigned short)(Attribute & 0x0f0) << 4;
  509. outpw( 0x3ce, regs.x.ax ); // Put BLUE color in Set/Reset register.
  510. //
  511. // Put Set/Reset register value into GVRAM
  512. // off the screen.
  513. //
  514. *OffTheScreen = temp;
  515. //
  516. // Read from screen, so the latches will be
  517. // updated with the background color.
  518. //
  519. temp = *OffTheScreen;
  520. //
  521. // Set Data Rotate/Function Select register
  522. // to be XOR.
  523. //
  524. outpw( 0x3ce, 0x1803 );
  525. //
  526. // XOR the foreground and background color and
  527. // put it in Set/Reset register.
  528. //
  529. regs.h.ah = (Attribute >> 4) ^ (Attribute & 0x0f);
  530. regs.h.al = 0;
  531. outpw( 0x3ce, regs.x.ax );
  532. //
  533. // Put Inverse(~) of the XOR of foreground and
  534. // ground attribute into Enable Set/Reset register.
  535. //
  536. regs.x.ax = ~regs.x.ax & 0x0f01;
  537. outpw( 0x3ce, regs.x.ax );
  538. }
  539. //
  540. // Turn optimization on again.
  541. //
  542. #pragma optimize( "", on )
  543. VOID
  544. TextGrPositionCursor(
  545. USHORT Row,
  546. USHORT Column
  547. )
  548. /*++
  549. Routine Description:
  550. Sets the position of the soft cursor. That is, it doesn't move the
  551. hardware cursor but sets the location of the next write to the
  552. screen.
  553. Arguments:
  554. Row - Row coordinate of where character is to be written.
  555. Column - Column coordinate of where character is to be written.
  556. Returns:
  557. Nothing.
  558. --*/
  559. {
  560. if(Row >= ScreenHeightCells) {
  561. Row = (USHORT)ScreenHeightCells-1;
  562. }
  563. if(Column >= ScreenWidthCells) {
  564. Column = (USHORT)ScreenWidthCells-1;
  565. }
  566. GrVp = (PUCHAR)VIDEO_BUFFER_VA + (Row * VIDEO_BYTES_PER_TEXT_ROW) + Column;
  567. }
  568. VOID
  569. TextGrStringOut(
  570. IN PUCHAR String
  571. )
  572. {
  573. GrWriteMBCSString(String,(unsigned)(-1));
  574. }
  575. PUCHAR
  576. TextGrCharOut(
  577. PUCHAR pc
  578. )
  579. /*++
  580. Routine Description:
  581. Writes a character on the display at the current position.
  582. Newlines and tabs are interpreted and acted upon.
  583. Arguments:
  584. pc - pointer to mbcs character to write.
  585. Returns:
  586. pointer to next character
  587. --*/
  588. {
  589. return(pc + GrWriteMBCSString(pc,1));
  590. }
  591. VOID
  592. TextGrFillAttribute(
  593. IN UCHAR Attribute,
  594. IN ULONG Length
  595. )
  596. /*++
  597. Routine Description:
  598. Changes the screen attribute starting at the current cursor position.
  599. The cursor is not moved.
  600. Arguments:
  601. Attribute - Supplies the new attribute
  602. Length - Supplies the length of the area to change (in bytes)
  603. Return Value:
  604. None.
  605. --*/
  606. {
  607. UCHAR OldAttribute;
  608. unsigned i;
  609. ULONG x,y;
  610. PUCHAR pImage;
  611. //
  612. // Save the current attribute and set the attribute to the
  613. // character desired by the caller.
  614. //
  615. TextGetCursorPosition(&x,&y);
  616. OldAttribute = TextCurrentAttribute;
  617. TextSetCurrentAttribute(Attribute);
  618. //
  619. // Dirty hack: just write spaces into the area requested by the caller.
  620. //
  621. pImage = GrGetSBCSFontImage(' ');
  622. for(i=0; i<Length; i++) {
  623. GrDisplayMBCSChar(pImage,SBCSWIDTH,0x00,0x00);
  624. }
  625. //
  626. // Restore the current attribute.
  627. //
  628. TextSetCurrentAttribute(OldAttribute);
  629. TextSetCursorPosition(x,y);
  630. }
  631. VOID
  632. TextGrClearToEndOfLine(
  633. VOID
  634. )
  635. /*++
  636. Routine Description:
  637. Clears from the current cursor position to the end of the line
  638. by writing blanks with the current video attribute.
  639. The cursor position is not changed.
  640. Arguments:
  641. None
  642. Returns:
  643. Nothing
  644. --*/
  645. {
  646. unsigned u;
  647. ULONG OldX,OldY;
  648. UCHAR temp;
  649. //
  650. // Fill with blanks up to char before cursor position.
  651. //
  652. temp = ' ';
  653. TextGetCursorPosition(&OldX,&OldY);
  654. for(u=TextColumn; u<ScreenWidthCells; u++) {
  655. TextGrCharOut(&temp);
  656. }
  657. TextSetCursorPosition(OldX,OldY);
  658. }
  659. VOID
  660. TextGrClearFromStartOfLine(
  661. VOID
  662. )
  663. /*++
  664. Routine Description:
  665. Clears from the start of the line to the current cursor position
  666. by writing blanks with the current video attribute.
  667. The cursor position is not changed.
  668. Arguments:
  669. None
  670. Returns:
  671. Nothing
  672. --*/
  673. {
  674. unsigned u;
  675. ULONG OldX,OldY;
  676. UCHAR temp = ' ';
  677. //
  678. // Fill with blanks up to char before cursor position.
  679. //
  680. TextGetCursorPosition(&OldX,&OldY);
  681. TextSetCursorPosition(0,OldY);
  682. for(u=0; u<TextColumn; u++) {
  683. TextGrCharOut(&temp);
  684. }
  685. TextSetCursorPosition(OldX,OldY);
  686. }
  687. VOID
  688. TextGrClearToEndOfDisplay(
  689. VOID
  690. )
  691. /*++
  692. Routine Description:
  693. Clears from the current cursor position to the end of the video
  694. display by writing blanks with the current video attribute.
  695. The cursor position is not changed.
  696. Arguments:
  697. None
  698. Returns:
  699. Nothing
  700. --*/
  701. {
  702. unsigned i;
  703. //
  704. // Clear current line
  705. //
  706. TextGrClearToEndOfLine();
  707. //
  708. // Clear the remaining lines
  709. //
  710. for(i=(TextRow+1)*VIDEO_BYTES_PER_TEXT_ROW; i<VIDEO_SIZE_BYTES; i++) {
  711. ((PUCHAR)VIDEO_BUFFER_VA)[i] = 0x00;
  712. }
  713. }
  714. VOID
  715. TextGrClearDisplay(
  716. VOID
  717. )
  718. /*++
  719. Routine Description:
  720. Clears the text-mode video display by writing blanks with
  721. the current video attribute over the entire display.
  722. Arguments:
  723. None
  724. Returns:
  725. Nothing
  726. --*/
  727. {
  728. unsigned i;
  729. //
  730. // Clear screen.
  731. //
  732. for(i=0; i<VIDEO_SIZE_BYTES; i++) {
  733. ((PUCHAR)VIDEO_BUFFER_VA)[i] = 0x00;
  734. }
  735. }
  736. VOID
  737. TextGrScrollDisplay(
  738. VOID
  739. )
  740. /*++
  741. Routine Description:
  742. Scrolls the display up one line. The cursor position is not changed.
  743. Arguments:
  744. None
  745. Returns:
  746. Nothing
  747. --*/
  748. {
  749. PUCHAR Source,Dest;
  750. unsigned n,i;
  751. ULONG OldX,OldY;
  752. UCHAR temp = ' ';
  753. Source = (PUCHAR)(VIDEO_BUFFER_VA) + VIDEO_BYTES_PER_TEXT_ROW;
  754. Dest = (PUCHAR)VIDEO_BUFFER_VA;
  755. n = VIDEO_BYTES_PER_TEXT_ROW * (ScreenHeightCells-1);
  756. for(i=0; i<n; i++) {
  757. *Dest++ = *Source++;
  758. }
  759. //
  760. // Write blanks in the bottom line, using the current attribute.
  761. //
  762. TextGetCursorPosition(&OldX,&OldY);
  763. TextSetCursorPosition(0,ScreenHeightCells-1);
  764. for(i=0; i<ScreenWidthCells; i++) {
  765. TextGrCharOut(&temp);
  766. }
  767. TextSetCursorPosition(OldX,OldY);
  768. }
  769. UCHAR GrGraphicsChars[GraphicsCharMax] = { 1, 2, 3, 4, 5, 6 };
  770. // UCHAR GrGraphicsChars[GraphicsCharMax] = { '�','�','�','�','�','�' };
  771. UCHAR
  772. TextGrGetGraphicsChar(
  773. IN GraphicsChar WhichOne
  774. )
  775. {
  776. return(GrGraphicsChars[WhichOne]);
  777. }
  778. VOID
  779. TextGrInitialize(
  780. IN ULONG DiskId,
  781. OUT PULONG ImageLength
  782. )
  783. {
  784. ULONG FileId;
  785. ARC_STATUS Status;
  786. PUCHAR FontImage;
  787. ULONG BytesRead;
  788. BOOTFONTBIN_HEADER FileHeader;
  789. LARGE_INTEGER SeekOffset;
  790. ULONG SbcsSize,DbcsSize;
  791. if (ImageLength) {
  792. *ImageLength = 0;
  793. }
  794. //
  795. // Attempt to open bootfont.bin. If this fails, then boot in single-byte charset mode.
  796. //
  797. if (BlBootingFromNet
  798. #if defined(REMOTE_BOOT)
  799. && NetworkBootRom
  800. #endif // defined(REMOTE_BOOT)
  801. ) {
  802. CHAR Buffer[129];
  803. strcpy(Buffer, NetBootPath);
  804. strcat(Buffer, "BOOTFONT.BIN");
  805. Status = BlOpen(DiskId,Buffer,ArcOpenReadOnly,&FileId);
  806. } else {
  807. Status = BlOpen(DiskId,"\\BOOTFONT.BIN",ArcOpenReadOnly,&FileId);
  808. }
  809. if(Status != ESUCCESS) {
  810. goto clean0;
  811. }
  812. //
  813. // Read in the file header and check some values.
  814. // We enforce the width of 8/16 here. If this is changed code all over the
  815. // rest of this module must also be changed.
  816. //
  817. Status = BlRead(FileId,&FileHeader,sizeof(BOOTFONTBIN_HEADER),&BytesRead);
  818. if((Status != ESUCCESS)
  819. || (BytesRead != sizeof(BOOTFONTBIN_HEADER))
  820. || (FileHeader.Signature != BOOTFONTBIN_SIGNATURE)
  821. || (FileHeader.CharacterImageSbcsWidth != 8)
  822. || (FileHeader.CharacterImageDbcsWidth != 16)
  823. ) {
  824. goto clean1;
  825. }
  826. //
  827. // Calculate the amount of memory needed to hold the sbcs and dbcs
  828. // character entries. Each sbcs entry is 1 byte for the ascii value
  829. // followed by n bytes for the image itself. We assume a width of 8 pixels.
  830. // For dbcs chars each entry is 2 bytes for the codepoint and n bytes
  831. // for the image itself. We assume a width of 16 pixels.
  832. //
  833. // Add in an extra 2 bytes per entry for the ending unicode value of the SBCS/DBCS
  834. // character.
  835. //
  836. // Also perform further validation on the file by comparing the sizes
  837. // given in the header against a size we calculate.
  838. //
  839. SbcsSize = FileHeader.NumSbcsChars * (FileHeader.CharacterImageHeight + 1 + 2);
  840. DbcsSize = FileHeader.NumDbcsChars * ((2 * FileHeader.CharacterImageHeight) + 2 + 2);
  841. if((SbcsSize != FileHeader.SbcsEntriesTotalSize)
  842. || (DbcsSize != FileHeader.DbcsEntriesTotalSize)) {
  843. goto clean1;
  844. }
  845. //
  846. // save off the image length argument if requested
  847. //
  848. if (ImageLength) {
  849. (*ImageLength) = sizeof(BOOTFONTBIN_HEADER) + SbcsSize + DbcsSize;
  850. }
  851. //
  852. // Allocate memory to hold the font. We use FwAllocatePool() because
  853. // that routine uses a separate heap that was inititialized before the
  854. // high-level Bl memory system was initialized, and thus is safe.
  855. //
  856. FontImage = FwAllocatePool(SbcsSize+DbcsSize);
  857. if(!FontImage) {
  858. goto clean1;
  859. }
  860. //
  861. // The entries get read into the base of the region we carved out.
  862. // The dbcs images get read in immediately after that.
  863. //
  864. SbcsImages = FontImage;
  865. DbcsImages = SbcsImages + FileHeader.SbcsEntriesTotalSize;
  866. //
  867. // Read in the sbcs entries.
  868. //
  869. SeekOffset.HighPart = 0;
  870. SeekOffset.LowPart = FileHeader.SbcsOffset;
  871. if((BlSeek(FileId,&SeekOffset,SeekAbsolute) != ESUCCESS)
  872. || (BlRead(FileId,SbcsImages,FileHeader.SbcsEntriesTotalSize,&BytesRead) != ESUCCESS)
  873. || (BytesRead != FileHeader.SbcsEntriesTotalSize)) {
  874. goto clean2;
  875. }
  876. //
  877. // Read in the dbcs entries.
  878. //
  879. SeekOffset.HighPart = 0;
  880. SeekOffset.LowPart = FileHeader.DbcsOffset;
  881. if((BlSeek(FileId,&SeekOffset,SeekAbsolute) != ESUCCESS)
  882. || (BlRead(FileId,DbcsImages,FileHeader.DbcsEntriesTotalSize,&BytesRead) != ESUCCESS)
  883. || (BytesRead != FileHeader.DbcsEntriesTotalSize)) {
  884. goto clean2;
  885. }
  886. //
  887. // We're done with the file now.
  888. //
  889. BlClose(FileId);
  890. //
  891. // Set up various values used for displaying the font.
  892. //
  893. DbcsLangId = FileHeader.LanguageId;
  894. CharacterImageHeight = FileHeader.CharacterImageHeight;
  895. CharacterTopPad = FileHeader.CharacterTopPad;
  896. CharacterBottomPad = FileHeader.CharacterBottomPad;
  897. CharacterCellHeight = CharacterImageHeight + CharacterTopPad + CharacterBottomPad;
  898. SbcsCharCount = FileHeader.NumSbcsChars;
  899. DbcsCharCount = FileHeader.NumDbcsChars;
  900. //
  901. // throughout the file, row/columns are passed around as ushorts,
  902. // and compared to ScreenHeight/Width.
  903. // ensure ScreenWidth/Height are bounded by the size of a USHORT
  904. //
  905. ScreenWidthCells = TRUNCATE_SIZE_AT_USHORT_MAX(VIDEO_WIDTH_PIXELS / FileHeader.CharacterImageSbcsWidth);
  906. ScreenHeightCells = TRUNCATE_SIZE_AT_USHORT_MAX(VIDEO_HEIGHT_SCAN_LINES / CharacterCellHeight);
  907. RtlMoveMemory(LeadByteTable,FileHeader.DbcsLeadTable,(MAX_DBCS_RANGE+1)*2);
  908. //
  909. // Switch the display into 640x480 graphics mode and clear it.
  910. // We're done.
  911. //
  912. HW_CURSOR(0x80000000,0x12);
  913. TextClearDisplay();
  914. return;
  915. clean2:
  916. //
  917. // Want to free the memory we allocated but there's no routine to do it
  918. //
  919. //FwFreePool();
  920. clean1:
  921. //
  922. // Close the font file.
  923. //
  924. BlClose(FileId);
  925. clean0:
  926. return;
  927. }
  928. VOID
  929. TextGrTerminate(
  930. VOID
  931. )
  932. {
  933. if(DbcsLangId) {
  934. DbcsLangId = 0;
  935. //
  936. // This command switches the display into 80x25 text mode
  937. // if there is no bitmap logo displayed. The logo is common
  938. // to the loader and bootvid, and in this case we don't want
  939. // to switch to text mode and then back to graphics.
  940. //
  941. if(!GraphicsMode && AllowGraphicsReset)
  942. HW_CURSOR(0x80000000,0x3);
  943. }
  944. }
  945. VOID
  946. UTF8Encode(
  947. USHORT InputValue,
  948. PUCHAR UTF8Encoding
  949. )
  950. /*++
  951. Routine Description:
  952. Generates the UTF8 translation for a 16-bit value.
  953. Arguments:
  954. InputValue - 16-bit value to be encoded.
  955. UTF8Encoding - receives the UTF8-encoding of the 16-bit value
  956. Return Value:
  957. NONE.
  958. --*/
  959. {
  960. //
  961. // convert into UTF8 for actual transmission
  962. //
  963. // UTF-8 encodes 2-byte Unicode characters as follows:
  964. // If the first nine bits are zero (00000000 0xxxxxxx), encode it as one byte 0xxxxxxx
  965. // If the first five bits are zero (00000yyy yyxxxxxx), encode it as two bytes 110yyyyy 10xxxxxx
  966. // Otherwise (zzzzyyyy yyxxxxxx), encode it as three bytes 1110zzzz 10yyyyyy 10xxxxxx
  967. //
  968. if( (InputValue & 0xFF80) == 0 ) {
  969. //
  970. // if the top 9 bits are zero, then just
  971. // encode as 1 byte. (ASCII passes through unchanged).
  972. //
  973. UTF8Encoding[2] = (UCHAR)(InputValue & 0xFF);
  974. } else if( (InputValue & 0xF800) == 0 ) {
  975. //
  976. // if the top 5 bits are zero, then encode as 2 bytes
  977. //
  978. UTF8Encoding[2] = (UCHAR)(InputValue & 0x3F) | 0x80;
  979. UTF8Encoding[1] = (UCHAR)((InputValue >> 6) & 0x1F) | 0xC0;
  980. } else {
  981. //
  982. // encode as 3 bytes
  983. //
  984. UTF8Encoding[2] = (UCHAR)(InputValue & 0x3F) | 0x80;
  985. UTF8Encoding[1] = (UCHAR)((InputValue >> 6) & 0x3F) | 0x80;
  986. UTF8Encoding[0] = (UCHAR)((InputValue >> 12) & 0xF) | 0xE0;
  987. }
  988. }
  989. VOID
  990. GetDBCSUtf8Translation(
  991. PUCHAR InputChar,
  992. PUCHAR UTF8Encoding
  993. )
  994. /*++
  995. Routine Description:
  996. Gets the UTF8 translation for a DBCS char.
  997. Arguments:
  998. InputChar - pointer to DBCS character code.
  999. UTF8Encoding - receives the UTF8-encoding of the DBCS character code
  1000. Return Value:
  1001. NONE.
  1002. --*/
  1003. {
  1004. int Min,Max,Mid;
  1005. int Multiplier;
  1006. int Index;
  1007. USHORT code;
  1008. USHORT Code;
  1009. Code = *InputChar++ << 8;
  1010. Code = Code | *InputChar++;
  1011. // initialize our output.
  1012. for( Index = 0; Index < 3; Index++ ) {
  1013. UTF8Encoding[Index] = 0;
  1014. }
  1015. Min = 0;
  1016. Max = DbcsCharCount;
  1017. //
  1018. // multiplier = 2 (for index) +
  1019. // 2* height +
  1020. // 2 (for unicode encoding)
  1021. //
  1022. Multiplier = 2 + (2*CharacterImageHeight) + 2;
  1023. //
  1024. // Do a binary search for the image.
  1025. // Format of table:
  1026. // First 2 bytes contain the DBCS char code.
  1027. // Next (2 * CharacterImageHeight) bytes are the char image.
  1028. // Next 2 bytes are for unicode version.
  1029. //
  1030. while(Max >= Min) {
  1031. Mid = (Max + Min) / 2;
  1032. Index = Mid*Multiplier;
  1033. code = (DbcsImages[Index] << 8) | (DbcsImages[Index+1]);
  1034. if(Code == code) {
  1035. WCHAR UnicodeValue = L'\0';
  1036. PUCHAR Image = (PUCHAR)DbcsImages+Index+2;
  1037. //
  1038. // image is pointing to an array of uchars, which are
  1039. // a bitmap of the character we want to display. Right
  1040. // behind this array is the unicode encoding of the
  1041. // character. Here's what the structure looks like:
  1042. //
  1043. // index bitmap unicode encoding of 'index'
  1044. // ^ ^ ^
  1045. // | | |
  1046. // | | - we previously converted 'index' into
  1047. // | | its unicode equivilent.
  1048. // | |
  1049. // | - This is where 'image' is pointing. It's an array of characters
  1050. // | (2 * width in length), which represents the bitmap to be displayed
  1051. // | on the screen which will represent the value in 'index'
  1052. // |
  1053. // - This is either an 8-bit value (if we're messing with SBCS), or a 16-bit value
  1054. // (if we're dealing with DBCS), in which case 'width' will be DBCSWIDTH.
  1055. //
  1056. // We're going to jump over the bitmap and retrieve the unicode encoding. Then we'll
  1057. // encode it into UTF8, then spew it over the headless port.
  1058. //
  1059. UnicodeValue = (WCHAR)( (Image[DBCSWIDTH*2]) | (Image[(DBCSWIDTH*2) + 1] << 8) );
  1060. UTF8Encode( UnicodeValue,
  1061. UTF8Encoding );
  1062. return;
  1063. }
  1064. if(Code < code) {
  1065. Max = Mid - 1;
  1066. } else {
  1067. Min = Mid + 1;
  1068. }
  1069. }
  1070. //
  1071. // ERROR: No image found.
  1072. //
  1073. return;
  1074. }
  1075. VOID
  1076. GetSBCSUtf8Translation(
  1077. PUCHAR InputChar,
  1078. PUCHAR UTF8Encoding
  1079. )
  1080. /*++
  1081. Routine Description:
  1082. Gets the font image for SBCS char.
  1083. Arguments:
  1084. InputChar - pointer to SBCS character code.
  1085. UTF8Encoding - receives the UTF8-encoding of the SBCS character code
  1086. Return Value:
  1087. NONE.
  1088. --*/
  1089. {
  1090. int Index;
  1091. UCHAR Code = *InputChar;
  1092. PUCHAR SBCSImage = NULL;
  1093. WCHAR UnicodeValue;
  1094. // initialize our output.
  1095. for( Index = 0; Index < 3; Index++ ) {
  1096. UTF8Encoding[Index] = 0;
  1097. }
  1098. SBCSImage = GrGetSBCSFontImage( Code );
  1099. if( SBCSImage ) {
  1100. UnicodeValue = (WCHAR)( (SBCSImage[SBCSWIDTH*2]) | (SBCSImage[(SBCSWIDTH*2) + 1] << 8) );
  1101. UTF8Encode( UnicodeValue,
  1102. UTF8Encoding );
  1103. }
  1104. return;
  1105. }