|
|
/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
disp_gr.c
Abstract:
This file was created from \private\windows\setup\textmode\splib\ixdispj.c. This file contains routines to display MBCS characters to the Graphics VRAM.
Author:
v-junm (Compaq Japan) hideyukn tedm
Environment:
Kernel mode only.
Revision History:
--*/
#include "bootx86.h"
#include "displayp.h"
#include "bootfont.h"
#include "vmode.h"
//
// Physical video attributes.
//
#define VIDEO_BUFFER_VA 0xa0000
#define VIDEO_BYTES_PER_SCAN_LINE 80
#define VIDEO_WIDTH_PIXELS 640
#define VIDEO_HEIGHT_SCAN_LINES 480
#define VIDEO_SIZE_BYTES (VIDEO_BYTES_PER_SCAN_LINE*VIDEO_HEIGHT_SCAN_LINES)
PUCHAR GrVp = (PUCHAR)VIDEO_BUFFER_VA;
//
// Screen width and height in half-character cells
// and macro to determine total number of characters
// displayed on the screen at once.
//
unsigned ScreenWidthCells,ScreenHeightCells; #define SCREEN_SIZE_CELLS (ScreenWidthCells*ScreenHeightCells)
//
// Globals:
//
// CharacterCellHeight is the number of scan lines total in a character.
// It includes any top or bottom fill lines.
//
// CharacterImageHeight is the number of scan lines in the image of a character.
// This is dependent on the font. Characters may be padded top and bottom.
//
// NOTE: All of this code assumes the font's single-byte characters are 8 bits wide
// and the font's double-byte characters are 16 bits wide!
//
unsigned CharacterCellHeight; unsigned CharacterImageHeight; unsigned CharacterTopPad; unsigned CharacterBottomPad;
#define VIDEO_BYTES_PER_TEXT_ROW (VIDEO_BYTES_PER_SCAN_LINE*CharacterCellHeight)
//
// Values describing the number of each type of character in the font,
// and pointers to the base of the glyphs.
//
unsigned SbcsCharCount; unsigned DbcsCharCount; PUCHAR SbcsImages; PUCHAR DbcsImages;
//
// Values to be passed to GrDisplayMBCSChar
//
#define SBCSWIDTH 8
#define DBCSWIDTH 16
//
// Lead byte table. Read from bootfont.bin.
//
UCHAR LeadByteTable[2*(MAX_DBCS_RANGE+1)];
//
// keeps track as to whether to reset the
// display in TextGrTerminate().
//
BOOLEAN AllowGraphicsReset = TRUE;
VOID GrDisplayMBCSChar( IN PUCHAR image, IN unsigned width, IN UCHAR top, IN UCHAR bottom );
PUCHAR GrGetDBCSFontImage( USHORT Code );
PUCHAR GrGetSBCSFontImage( UCHAR Code );
VOID GrWriteSBCSChar( IN UCHAR c )
/*++
Routine Description:
Displays a character at the current cursor position. ONLY SBCS characters can be displayed using this routine.
Arguments:
c - character to display.
Return Value:
None.
--*/
{ unsigned u; PUCHAR pImage; UCHAR temp;
switch(c) {
case '\n': if(TextRow == (ScreenHeightCells-1)) { TextGrScrollDisplay(); TextSetCursorPosition(0,TextRow); } else { TextSetCursorPosition(0,TextRow+1); } break;
case '\r': break; // ignore
case '\t': temp = ' '; u = 8 - (TextColumn % 8); while(u--) { TextGrCharOut(&temp); } TextSetCursorPosition(TextColumn+u,TextRow); break;
default: //
// Assume it's a valid SBCS character.
// Get font image for SBCS char.
//
pImage = GrGetSBCSFontImage(c);
//
// Display the SBCS char. Check for special graphics characters.
// Add top and bottom extra pixels accordingly (otherwise the grids
// don't connect properly, because of top and bottom spacing).
//
if ( c == 0x2 || c == 0x1 || c == 0x16 ) GrDisplayMBCSChar( pImage, SBCSWIDTH, 0x00, 0x66 ); else if ( c == 0x4 || c == 0x3 || c == 0x15 ) GrDisplayMBCSChar( pImage, SBCSWIDTH, 0x66, 0x00 ); else if ( c == 0x5 || c == 10 || c == 0x17 || c == 0x19 ) GrDisplayMBCSChar( pImage, SBCSWIDTH, 0x66, 0x66 ); else GrDisplayMBCSChar( pImage, SBCSWIDTH, 0x00, 0x00 );
} }
VOID GrDisplayMBCSChar( IN PUCHAR image, IN unsigned width, IN UCHAR top, IN UCHAR bottom )
/*++
Routine Description:
Displays a DBCS or a SBCS character at the current cursor position.
Arguments:
image - SBCS or DBCS font image. width - Width in bits of character image (must be SBCSWIDTH pr DBCSWIDTH). top - Character to fill the top extra character line(s). bottom- Character to fill the bottom extra character line(s).
Return Value:
FALSE if image points to NULL, else TRUE.
--*/
{ unsigned i;
//
// Validate parameter
//
if(image == NULL) { return; }
//
// There are TOP_EXTRA lines at the top that we need to skip (background color).
//
for(i=0; i<CharacterTopPad; i++) {
//
// If DBCS char, we need to clear 2 bytes.
//
if(width == DBCSWIDTH) { *GrVp++ = top; } *GrVp++ = top;
//
// Position pointer at next scan line
// for the font image.
//
GrVp += VIDEO_BYTES_PER_SCAN_LINE - (width/SBCSWIDTH); }
//
// Display full height of DBCS or SBCS char.
//
for(i=0; i<CharacterImageHeight; i++) {
//
// If DBCS char, need to display 2 bytes,
// so display first byte here.
//
if(width == DBCSWIDTH) { *GrVp++ = *image++; }
//
// Display 2nd byte of DBCS char or the
// first and only byte of SBCS char.
//
*GrVp++ = *image++;
//
// Increment GrVP to display location of
// next row of font image.
//
GrVp += VIDEO_BYTES_PER_SCAN_LINE - (width/SBCSWIDTH); }
//
// There are BOT_EXTRA lines at the bottom that we need to fill with the
// background color.
//
for(i=0; i<CharacterBottomPad; i++) {
//
// If DBCS char, need to clear 2 bytes
//
if(width == DBCSWIDTH) { *GrVp++ = bottom; } *GrVp++ = bottom;
//
// Position pointer at next scan line
// for the font image.
//
GrVp += VIDEO_BYTES_PER_SCAN_LINE - (width/SBCSWIDTH); }
//
// Increment cursor and video pointer
//
if(width == DBCSWIDTH) { TextSetCursorPosition(TextColumn+2,TextRow); } else { TextSetCursorPosition(TextColumn+1,TextRow); } }
unsigned GrWriteMBCSString( IN PUCHAR String, IN unsigned MaxChars )
/*++
Routine Description:
Displays a mixed byte string at the current cursor position.
Arguments:
String - supplies pointer to asciz string.
MaxBytes - supplies the maximum number of characters to be written.
Return Value:
Number of bytes written.
--*/
{ PUCHAR pImage; USHORT DBCSChar; unsigned BytesWritten;
BytesWritten = 0;
//
// While string is not NULL,
// get font image and display it.
//
while(*String && MaxChars--) {
//
// Determine if char is SBCS or DBCS, get the correct font image,
// and display it.
//
if(GrIsDBCSLeadByte(*String)) { DBCSChar = *String++ << 8; DBCSChar = DBCSChar | *String++; pImage = GrGetDBCSFontImage(DBCSChar); GrDisplayMBCSChar(pImage,DBCSWIDTH,0x00,0x00); BytesWritten++; } else { GrWriteSBCSChar(*String++); } BytesWritten++; }
return(BytesWritten); }
BOOLEAN GrIsDBCSLeadByte( IN UCHAR c )
/*++
Routine Description:
Checks to see if a char is a DBCS leadbyte.
Arguments:
c - char to check if leadbyte or not.
Return Value:
TRUE - Leadbyte. FALSE - Non-Leadbyte.
--*/
{ int i;
//
// Check to see if char is in leadbyte range.
// Note if (CHAR)(0) is a valid leadbyte,
// this routine will fail.
//
for(i=0; LeadByteTable[i]; i+=2) { if((LeadByteTable[i] <= c) && (LeadByteTable[i+1] >= c)) { return(TRUE); } }
return(FALSE); }
PUCHAR GrGetDBCSFontImage( USHORT Code )
/*++
Routine Description:
Gets the font image for DBCS char.
Arguments:
Code - DBCS char code.
Return Value:
Pointer to font image, or else NULL.
--*/
{ int Min,Max,Mid; int Multiplier; int Index; USHORT code;
Min = 0; Max = DbcsCharCount; // multiplier = 2 (for index) +
// 2 * height +
// 2 (for unicode encoding)
//
Multiplier = 2 + (2*CharacterImageHeight) + 2;
//
// Do a binary search for the image.
// Format of table:
// First 2 bytes contain the DBCS char code.
// Next (2 * CharacterImageHeight) bytes are the char image.
// Next 2 bytes are for unicode version.
//
while(Max >= Min) { Mid = (Max + Min) / 2; Index = Mid*Multiplier; code = (DbcsImages[Index] << 8) | DbcsImages[Index+1];
if(Code == code) { return(DbcsImages+Index+2); }
if(Code < code) { Max = Mid - 1; } else { Min = Mid + 1; } }
//
// ERROR: No image found.
//
return(NULL); }
//
// This array is used to override a glyph returned by GrGetSBCSFontImage.
// Basically, if the user is asking for one of the first 6 glyphs from
// the SBCS map, we'll intercept the call and return the value from this
// array.
//
// This is because there was a previous assumption that the first 6 glyphs
// in an SBCS image were drawing characters. The same 6 drawing characters.
// That means we just introduced an external reliance on every bootfont.bin.
// Better to keep the dependence right here.
//
UCHAR SbcsRemapper[6][18] = { // SBCS codes (16 bytes worth) Unicode value
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x60, 0x60, 0x67, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x25, 0x54}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0xe6, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x25, 0x57}, {0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x67, 0x60, 0x60, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x5A}, {0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x06, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x5D}, {0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x25, 0x51}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x50} };
PUCHAR GrGetSBCSFontImage( UCHAR Code )
/*++
Routine Description:
Gets the font image for SBCS char.
Arguments:
Code - SBCS char code.
Return Value:
Pointer to font image, or else NULL.
--*/
{ int Max,Min,Mid; int Multiplier; int Index;
//
// WARNING: Nauseating hack!!
// We're going to special case some drawing characters here because
// these graphics characters may not exist in every locale. This is
// where we'll supercede some of the bootfont.bin lookups with the
// glyphs we really want.
//
// We're going to remap some low SBCS values to some specific drawing
// glyphs.
//
// 1: "top left corner" double-line. Corresponds to ANSI code 0xC9 and unicode 0x2554
// ----
// | --
// | |
// | |
//
//
// 2. "top right corner" double-line. Corresponds to ANSI code 0xBB and unicode 0x2557
// ----
// -- |
// | |
// | |
//
// 3. "bottom left corner". Corresponds to ANSI code 0xC8 and unicode 0x255A
// 4. "bottom right corner". Corresponds to ANSI code 0xBC and unicode 0x255D
// 5. "double verticl line". Corresponds to ANSI code 0xBA and unicode 0x2551
// 6. "double horizontal line". Corresponds to ANSI code 0xCD and unicode 0x2550
//
if( (Code >= 0x1) && (Code <= 0x6) ) { return SbcsRemapper[Code-1]; }
Min = 0; Max = SbcsCharCount; // multiplier = 1 (for index) +
// height +
// 2 (for unicode encoding)
//
Multiplier = 1 + (CharacterImageHeight) + 2;
//
// Do a binary search for the image.
// Format of table:
// First byte contains the SBCS char code.
// Next (CharacterImageHeight) bytes are the char image.
// Next 2 bytes are for unicode version.
//
while(Max >= Min) { Mid = (Max + Min) / 2; Index = Mid*Multiplier;
if(Code == SbcsImages[Index]) { return(SbcsImages+Index+1); }
if(Code < SbcsImages[Index]) { Max = Mid - 1; } else { Min = Mid + 1; } }
//
// ERROR: No image found.
//
return(NULL); }
//
// Need to turn off optimization for this
// routine. Since the write and read to
// GVRAM seem useless to the compiler.
//
#pragma optimize( "", off )
VOID TextGrSetCurrentAttribute( IN UCHAR Attribute )
/*++
Routine Description:
Sets the attribute by setting up various VGA registers. The comments only say what registers are set to what, so to understand the logic, follow the code while looking at Figure 5-5 of PC&PS/2 Video Systems by Richard Wilton. The book is published by Microsoft Press.
Arguments:
Attribute - New attribute to set to. Attribute: High nibble - background attribute. Low nibble - foreground attribute.
Return Value:
Nothing.
--*/
{ UCHAR temp = 0;
//
// Address of GVRAM off the screen.
//
PUCHAR OffTheScreen = (PUCHAR)(0xa9600);
union WordOrByte { struct Word { unsigned short ax; } x; struct Byte { unsigned char al, ah; } h; } regs;
//
// Reset Data Rotate/Function Select
// regisger.
//
outpw( 0x3ce, 0x3 ); // Need to reset Data Rotate/Function Select.
//
// Set Enable Set/Reset to
// all (0f).
//
outpw( 0x3ce, 0xf01 );
//
// Put background color into Set/Reset register.
// This is done to put the background color into
// the latches later.
//
regs.x.ax = (unsigned short)(Attribute & 0x0f0) << 4; outpw( 0x3ce, regs.x.ax ); // Put BLUE color in Set/Reset register.
//
// Put Set/Reset register value into GVRAM
// off the screen.
//
*OffTheScreen = temp;
//
// Read from screen, so the latches will be
// updated with the background color.
//
temp = *OffTheScreen;
//
// Set Data Rotate/Function Select register
// to be XOR.
//
outpw( 0x3ce, 0x1803 );
//
// XOR the foreground and background color and
// put it in Set/Reset register.
//
regs.h.ah = (Attribute >> 4) ^ (Attribute & 0x0f); regs.h.al = 0; outpw( 0x3ce, regs.x.ax );
//
// Put Inverse(~) of the XOR of foreground and
// ground attribute into Enable Set/Reset register.
//
regs.x.ax = ~regs.x.ax & 0x0f01; outpw( 0x3ce, regs.x.ax ); }
//
// Turn optimization on again.
//
#pragma optimize( "", on )
VOID TextGrPositionCursor( USHORT Row, USHORT Column )
/*++
Routine Description:
Sets the position of the soft cursor. That is, it doesn't move the hardware cursor but sets the location of the next write to the screen.
Arguments:
Row - Row coordinate of where character is to be written.
Column - Column coordinate of where character is to be written.
Returns:
Nothing.
--*/
{ if(Row >= ScreenHeightCells) { Row = (USHORT)ScreenHeightCells-1; }
if(Column >= ScreenWidthCells) { Column = (USHORT)ScreenWidthCells-1; }
GrVp = (PUCHAR)VIDEO_BUFFER_VA + (Row * VIDEO_BYTES_PER_TEXT_ROW) + Column; }
VOID TextGrStringOut( IN PUCHAR String ) { GrWriteMBCSString(String,(unsigned)(-1)); }
PUCHAR TextGrCharOut( PUCHAR pc )
/*++
Routine Description:
Writes a character on the display at the current position. Newlines and tabs are interpreted and acted upon.
Arguments:
pc - pointer to mbcs character to write.
Returns:
pointer to next character
--*/
{ return(pc + GrWriteMBCSString(pc,1)); }
VOID TextGrFillAttribute( IN UCHAR Attribute, IN ULONG Length )
/*++
Routine Description:
Changes the screen attribute starting at the current cursor position. The cursor is not moved.
Arguments:
Attribute - Supplies the new attribute
Length - Supplies the length of the area to change (in bytes)
Return Value:
None.
--*/
{ UCHAR OldAttribute; unsigned i; ULONG x,y; PUCHAR pImage;
//
// Save the current attribute and set the attribute to the
// character desired by the caller.
//
TextGetCursorPosition(&x,&y); OldAttribute = TextCurrentAttribute; TextSetCurrentAttribute(Attribute);
//
// Dirty hack: just write spaces into the area requested by the caller.
//
pImage = GrGetSBCSFontImage(' '); for(i=0; i<Length; i++) { GrDisplayMBCSChar(pImage,SBCSWIDTH,0x00,0x00); }
//
// Restore the current attribute.
//
TextSetCurrentAttribute(OldAttribute); TextSetCursorPosition(x,y); }
VOID TextGrClearToEndOfLine( VOID )
/*++
Routine Description:
Clears from the current cursor position to the end of the line by writing blanks with the current video attribute. The cursor position is not changed.
Arguments:
None
Returns:
Nothing
--*/
{ unsigned u; ULONG OldX,OldY; UCHAR temp;
//
// Fill with blanks up to char before cursor position.
//
temp = ' '; TextGetCursorPosition(&OldX,&OldY); for(u=TextColumn; u<ScreenWidthCells; u++) { TextGrCharOut(&temp); } TextSetCursorPosition(OldX,OldY); }
VOID TextGrClearFromStartOfLine( VOID )
/*++
Routine Description:
Clears from the start of the line to the current cursor position by writing blanks with the current video attribute. The cursor position is not changed.
Arguments:
None
Returns:
Nothing
--*/
{ unsigned u; ULONG OldX,OldY; UCHAR temp = ' ';
//
// Fill with blanks up to char before cursor position.
//
TextGetCursorPosition(&OldX,&OldY); TextSetCursorPosition(0,OldY); for(u=0; u<TextColumn; u++) { TextGrCharOut(&temp); } TextSetCursorPosition(OldX,OldY); }
VOID TextGrClearToEndOfDisplay( VOID )
/*++
Routine Description:
Clears from the current cursor position to the end of the video display by writing blanks with the current video attribute. The cursor position is not changed.
Arguments:
None
Returns:
Nothing
--*/ { unsigned i; //
// Clear current line
//
TextGrClearToEndOfLine();
//
// Clear the remaining lines
//
for(i=(TextRow+1)*VIDEO_BYTES_PER_TEXT_ROW; i<VIDEO_SIZE_BYTES; i++) { ((PUCHAR)VIDEO_BUFFER_VA)[i] = 0x00; } }
VOID TextGrClearDisplay( VOID )
/*++
Routine Description:
Clears the text-mode video display by writing blanks with the current video attribute over the entire display.
Arguments:
None
Returns:
Nothing
--*/
{ unsigned i;
//
// Clear screen.
//
for(i=0; i<VIDEO_SIZE_BYTES; i++) { ((PUCHAR)VIDEO_BUFFER_VA)[i] = 0x00; } }
VOID TextGrScrollDisplay( VOID )
/*++
Routine Description:
Scrolls the display up one line. The cursor position is not changed.
Arguments:
None
Returns:
Nothing
--*/
{ PUCHAR Source,Dest; unsigned n,i; ULONG OldX,OldY; UCHAR temp = ' ';
Source = (PUCHAR)(VIDEO_BUFFER_VA) + VIDEO_BYTES_PER_TEXT_ROW; Dest = (PUCHAR)VIDEO_BUFFER_VA;
n = VIDEO_BYTES_PER_TEXT_ROW * (ScreenHeightCells-1);
for(i=0; i<n; i++) { *Dest++ = *Source++; }
//
// Write blanks in the bottom line, using the current attribute.
//
TextGetCursorPosition(&OldX,&OldY);
TextSetCursorPosition(0,ScreenHeightCells-1); for(i=0; i<ScreenWidthCells; i++) { TextGrCharOut(&temp); }
TextSetCursorPosition(OldX,OldY); }
UCHAR GrGraphicsChars[GraphicsCharMax] = { 1, 2, 3, 4, 5, 6 }; // UCHAR GrGraphicsChars[GraphicsCharMax] = { '�','�','�','�','�','�' };
UCHAR TextGrGetGraphicsChar( IN GraphicsChar WhichOne ) { return(GrGraphicsChars[WhichOne]); }
VOID TextGrInitialize( IN ULONG DiskId, OUT PULONG ImageLength ) { ULONG FileId; ARC_STATUS Status; PUCHAR FontImage; ULONG BytesRead; BOOTFONTBIN_HEADER FileHeader; LARGE_INTEGER SeekOffset; ULONG SbcsSize,DbcsSize;
if (ImageLength) { *ImageLength = 0; } //
// Attempt to open bootfont.bin. If this fails, then boot in single-byte charset mode.
//
if (BlBootingFromNet #if defined(REMOTE_BOOT)
&& NetworkBootRom #endif // defined(REMOTE_BOOT)
) { CHAR Buffer[129]; strcpy(Buffer, NetBootPath); strcat(Buffer, "BOOTFONT.BIN"); Status = BlOpen(DiskId,Buffer,ArcOpenReadOnly,&FileId); } else { Status = BlOpen(DiskId,"\\BOOTFONT.BIN",ArcOpenReadOnly,&FileId); } if(Status != ESUCCESS) { goto clean0; }
//
// Read in the file header and check some values.
// We enforce the width of 8/16 here. If this is changed code all over the
// rest of this module must also be changed.
//
Status = BlRead(FileId,&FileHeader,sizeof(BOOTFONTBIN_HEADER),&BytesRead); if((Status != ESUCCESS) || (BytesRead != sizeof(BOOTFONTBIN_HEADER)) || (FileHeader.Signature != BOOTFONTBIN_SIGNATURE) || (FileHeader.CharacterImageSbcsWidth != 8) || (FileHeader.CharacterImageDbcsWidth != 16) ) { goto clean1; }
//
// Calculate the amount of memory needed to hold the sbcs and dbcs
// character entries. Each sbcs entry is 1 byte for the ascii value
// followed by n bytes for the image itself. We assume a width of 8 pixels.
// For dbcs chars each entry is 2 bytes for the codepoint and n bytes
// for the image itself. We assume a width of 16 pixels.
//
// Add in an extra 2 bytes per entry for the ending unicode value of the SBCS/DBCS
// character.
//
// Also perform further validation on the file by comparing the sizes
// given in the header against a size we calculate.
//
SbcsSize = FileHeader.NumSbcsChars * (FileHeader.CharacterImageHeight + 1 + 2); DbcsSize = FileHeader.NumDbcsChars * ((2 * FileHeader.CharacterImageHeight) + 2 + 2);
if((SbcsSize != FileHeader.SbcsEntriesTotalSize) || (DbcsSize != FileHeader.DbcsEntriesTotalSize)) { goto clean1; }
//
// save off the image length argument if requested
//
if (ImageLength) { (*ImageLength) = sizeof(BOOTFONTBIN_HEADER) + SbcsSize + DbcsSize; }
//
// Allocate memory to hold the font. We use FwAllocatePool() because
// that routine uses a separate heap that was inititialized before the
// high-level Bl memory system was initialized, and thus is safe.
//
FontImage = FwAllocatePool(SbcsSize+DbcsSize); if(!FontImage) { goto clean1; }
//
// The entries get read into the base of the region we carved out.
// The dbcs images get read in immediately after that.
//
SbcsImages = FontImage; DbcsImages = SbcsImages + FileHeader.SbcsEntriesTotalSize;
//
// Read in the sbcs entries.
//
SeekOffset.HighPart = 0; SeekOffset.LowPart = FileHeader.SbcsOffset; if((BlSeek(FileId,&SeekOffset,SeekAbsolute) != ESUCCESS) || (BlRead(FileId,SbcsImages,FileHeader.SbcsEntriesTotalSize,&BytesRead) != ESUCCESS) || (BytesRead != FileHeader.SbcsEntriesTotalSize)) { goto clean2; }
//
// Read in the dbcs entries.
//
SeekOffset.HighPart = 0; SeekOffset.LowPart = FileHeader.DbcsOffset; if((BlSeek(FileId,&SeekOffset,SeekAbsolute) != ESUCCESS) || (BlRead(FileId,DbcsImages,FileHeader.DbcsEntriesTotalSize,&BytesRead) != ESUCCESS) || (BytesRead != FileHeader.DbcsEntriesTotalSize)) { goto clean2; }
//
// We're done with the file now.
//
BlClose(FileId);
//
// Set up various values used for displaying the font.
//
DbcsLangId = FileHeader.LanguageId; CharacterImageHeight = FileHeader.CharacterImageHeight; CharacterTopPad = FileHeader.CharacterTopPad; CharacterBottomPad = FileHeader.CharacterBottomPad; CharacterCellHeight = CharacterImageHeight + CharacterTopPad + CharacterBottomPad; SbcsCharCount = FileHeader.NumSbcsChars; DbcsCharCount = FileHeader.NumDbcsChars; //
// throughout the file, row/columns are passed around as ushorts,
// and compared to ScreenHeight/Width.
// ensure ScreenWidth/Height are bounded by the size of a USHORT
//
ScreenWidthCells = TRUNCATE_SIZE_AT_USHORT_MAX(VIDEO_WIDTH_PIXELS / FileHeader.CharacterImageSbcsWidth); ScreenHeightCells = TRUNCATE_SIZE_AT_USHORT_MAX(VIDEO_HEIGHT_SCAN_LINES / CharacterCellHeight);
RtlMoveMemory(LeadByteTable,FileHeader.DbcsLeadTable,(MAX_DBCS_RANGE+1)*2);
//
// Switch the display into 640x480 graphics mode and clear it.
// We're done.
//
HW_CURSOR(0x80000000,0x12); TextClearDisplay(); return;
clean2: //
// Want to free the memory we allocated but there's no routine to do it
//
//FwFreePool();
clean1: //
// Close the font file.
//
BlClose(FileId); clean0: return; }
VOID TextGrTerminate( VOID ) { if(DbcsLangId) { DbcsLangId = 0; //
// This command switches the display into 80x25 text mode
// if there is no bitmap logo displayed. The logo is common
// to the loader and bootvid, and in this case we don't want
// to switch to text mode and then back to graphics.
//
if(!GraphicsMode && AllowGraphicsReset) HW_CURSOR(0x80000000,0x3); } }
VOID UTF8Encode( USHORT InputValue, PUCHAR UTF8Encoding ) /*++
Routine Description:
Generates the UTF8 translation for a 16-bit value.
Arguments:
InputValue - 16-bit value to be encoded. UTF8Encoding - receives the UTF8-encoding of the 16-bit value
Return Value:
NONE. --*/ {
//
// convert into UTF8 for actual transmission
//
// UTF-8 encodes 2-byte Unicode characters as follows:
// If the first nine bits are zero (00000000 0xxxxxxx), encode it as one byte 0xxxxxxx
// If the first five bits are zero (00000yyy yyxxxxxx), encode it as two bytes 110yyyyy 10xxxxxx
// Otherwise (zzzzyyyy yyxxxxxx), encode it as three bytes 1110zzzz 10yyyyyy 10xxxxxx
//
if( (InputValue & 0xFF80) == 0 ) { //
// if the top 9 bits are zero, then just
// encode as 1 byte. (ASCII passes through unchanged).
//
UTF8Encoding[2] = (UCHAR)(InputValue & 0xFF); } else if( (InputValue & 0xF800) == 0 ) { //
// if the top 5 bits are zero, then encode as 2 bytes
//
UTF8Encoding[2] = (UCHAR)(InputValue & 0x3F) | 0x80; UTF8Encoding[1] = (UCHAR)((InputValue >> 6) & 0x1F) | 0xC0; } else { //
// encode as 3 bytes
//
UTF8Encoding[2] = (UCHAR)(InputValue & 0x3F) | 0x80; UTF8Encoding[1] = (UCHAR)((InputValue >> 6) & 0x3F) | 0x80; UTF8Encoding[0] = (UCHAR)((InputValue >> 12) & 0xF) | 0xE0; } }
VOID GetDBCSUtf8Translation( PUCHAR InputChar, PUCHAR UTF8Encoding ) /*++
Routine Description:
Gets the UTF8 translation for a DBCS char.
Arguments:
InputChar - pointer to DBCS character code. UTF8Encoding - receives the UTF8-encoding of the DBCS character code
Return Value:
NONE.
--*/
{ int Min,Max,Mid; int Multiplier; int Index; USHORT code; USHORT Code;
Code = *InputChar++ << 8; Code = Code | *InputChar++;
// initialize our output.
for( Index = 0; Index < 3; Index++ ) { UTF8Encoding[Index] = 0; }
Min = 0; Max = DbcsCharCount; //
// multiplier = 2 (for index) +
// 2* height +
// 2 (for unicode encoding)
//
Multiplier = 2 + (2*CharacterImageHeight) + 2;
//
// Do a binary search for the image.
// Format of table:
// First 2 bytes contain the DBCS char code.
// Next (2 * CharacterImageHeight) bytes are the char image.
// Next 2 bytes are for unicode version.
//
while(Max >= Min) { Mid = (Max + Min) / 2; Index = Mid*Multiplier; code = (DbcsImages[Index] << 8) | (DbcsImages[Index+1]); if(Code == code) {
WCHAR UnicodeValue = L'\0'; PUCHAR Image = (PUCHAR)DbcsImages+Index+2;
//
// image is pointing to an array of uchars, which are
// a bitmap of the character we want to display. Right
// behind this array is the unicode encoding of the
// character. Here's what the structure looks like:
//
// index bitmap unicode encoding of 'index'
// ^ ^ ^
// | | |
// | | - we previously converted 'index' into
// | | its unicode equivilent.
// | |
// | - This is where 'image' is pointing. It's an array of characters
// | (2 * width in length), which represents the bitmap to be displayed
// | on the screen which will represent the value in 'index'
// |
// - This is either an 8-bit value (if we're messing with SBCS), or a 16-bit value
// (if we're dealing with DBCS), in which case 'width' will be DBCSWIDTH.
//
// We're going to jump over the bitmap and retrieve the unicode encoding. Then we'll
// encode it into UTF8, then spew it over the headless port.
//
UnicodeValue = (WCHAR)( (Image[DBCSWIDTH*2]) | (Image[(DBCSWIDTH*2) + 1] << 8) );
UTF8Encode( UnicodeValue, UTF8Encoding ); return; }
if(Code < code) { Max = Mid - 1; } else { Min = Mid + 1; } }
//
// ERROR: No image found.
//
return; }
VOID GetSBCSUtf8Translation( PUCHAR InputChar, PUCHAR UTF8Encoding )
/*++
Routine Description:
Gets the font image for SBCS char.
Arguments:
InputChar - pointer to SBCS character code. UTF8Encoding - receives the UTF8-encoding of the SBCS character code
Return Value:
NONE.
--*/
{ int Index; UCHAR Code = *InputChar; PUCHAR SBCSImage = NULL; WCHAR UnicodeValue;
// initialize our output.
for( Index = 0; Index < 3; Index++ ) { UTF8Encoding[Index] = 0; } SBCSImage = GrGetSBCSFontImage( Code );
if( SBCSImage ) { UnicodeValue = (WCHAR)( (SBCSImage[SBCSWIDTH*2]) | (SBCSImage[(SBCSWIDTH*2) + 1] << 8) ); UTF8Encode( UnicodeValue, UTF8Encoding ); } return; }
|