/*++ Copyright (c) 1992 Microsoft Corporation Module Name: dndisp.c Abstract: DOS-based NT setup program video display routines. Author: Ted Miller (tedm) 30-March-1992 Revision History: --*/ #include "winnt.h" #include #define SCREEN_WIDTH 80 #define SCREEN_HEIGHT 25 #define STATUS_HEIGHT 1 #define STATUS_LEFT_MARGIN 2 #define HEADER_HEIGHT 3 // // Display attributes // #define ATT_FG_BLACK 0 #define ATT_FG_BLUE 1 #define ATT_FG_GREEN 2 #define ATT_FG_CYAN 3 #define ATT_FG_RED 4 #define ATT_FG_MAGENTA 5 #define ATT_FG_YELLOW 6 #define ATT_FG_WHITE 7 #define ATT_BG_BLACK (ATT_FG_BLACK << 4) #define ATT_BG_BLUE (ATT_FG_BLUE << 4) #define ATT_BG_GREEN (ATT_FG_GREEN << 4) #define ATT_BG_CYAN (ATT_FG_CYAN << 4) #define ATT_BG_RED (ATT_FG_RED << 4) #define ATT_BG_MAGENTA (ATT_FG_MAGENTA << 4) #define ATT_BG_YELLOW (ATT_FG_YELLOW << 4) #define ATT_BG_WHITE (ATT_FG_WHITE << 4) #define ATT_FG_INTENSE 8 #define ATT_BG_INTENSE (ATT_FG_INTENSE << 4) #define DEFAULT_ATTRIBUTE (ATT_FG_WHITE | ATT_BG_BLUE) #define STATUS_ATTRIBUTE (ATT_FG_BLACK | ATT_BG_WHITE) #define EDIT_ATTRIBUTE (ATT_FG_BLACK | ATT_BG_WHITE) #define EXITDLG_ATTRIBUTE (ATT_FG_RED | ATT_BG_WHITE) #define GAUGE_ATTRIBUTE (ATT_BG_BLUE | ATT_FG_YELLOW | ATT_FG_INTENSE) // #define USE_INT10 #ifndef USE_INT10 // // Far address of the screen buffer. // #define SCREEN_BUFFER ((UCHAR _far *)0xb8000000) #define SCREEN_BUFFER_CHR(x,y) *(SCREEN_BUFFER + (2*((x)+(SCREEN_WIDTH*(y))))) #define SCREEN_BUFFER_ATT(x,y) *(SCREEN_BUFFER + (2*((x)+(SCREEN_WIDTH*(y))))+1) BOOLEAN CursorIsActuallyOn; #endif // // Make these near because they are used in _asm blocks // UCHAR _near CurrentAttribute; UCHAR _near ScreenX; UCHAR _near ScreenY; BOOLEAN CursorOn; VOID DnpBlankScreenArea( IN UCHAR Attribute, IN UCHAR Left, IN UCHAR Right, IN UCHAR Top, IN UCHAR Bottom ); VOID DnInitializeDisplay( VOID ) /*++ Routine Description: Put the display in a known state (80x25 standard text mode) and initialize the display package. Arguments: None. Return Value: None. --*/ { CurrentAttribute = DEFAULT_ATTRIBUTE; CursorOn = FALSE; // // Set the display to standard 80x25 mode // _asm { mov ax,3 // set video mode to 3 int 10h } // // Clear the entire screen // DnpBlankScreenArea(CurrentAttribute,0,SCREEN_WIDTH-1,0,SCREEN_HEIGHT-1); DnPositionCursor(0,0); #ifndef USE_INT10 // // Shut the cursor off. // _asm { mov ah,2 // function -- position cursor mov bh,0 // display page mov dh,SCREEN_HEIGHT mov dl,0 int 10h } CursorIsActuallyOn = FALSE; #endif } VOID DnClearClientArea( VOID ) /*++ Routine Description: Clear the client area of the screen, ie, the area between the header and status line. Arguments: None. Return Value: None. --*/ { DnpBlankScreenArea( CurrentAttribute, 0, SCREEN_WIDTH-1, HEADER_HEIGHT, SCREEN_HEIGHT - STATUS_HEIGHT - 1 ); DnPositionCursor(0,HEADER_HEIGHT); } VOID DnSetGaugeAttribute( IN BOOLEAN Set ) /*++ Routine Description: Prepare for drawing the thermometer portion of a gas gauge. Arguments: Set - if TRUE, prepare for drawing the thermometer. If FALSE, restore the state for normal drawing. Return Value: None. --*/ { static UCHAR SavedAttribute = 0; if(Set) { if(!SavedAttribute) { SavedAttribute = CurrentAttribute; CurrentAttribute = GAUGE_ATTRIBUTE; } } else { if(SavedAttribute) { CurrentAttribute = SavedAttribute; SavedAttribute = 0; } } } VOID DnPositionCursor( IN UCHAR X, IN UCHAR Y ) /*++ Routine Description: Position the cursor. Arguments: X,Y - cursor coords Return Value: None. --*/ { if(X >= SCREEN_WIDTH) { X = 0; Y++; } if(Y >= SCREEN_HEIGHT) { Y = HEADER_HEIGHT; } ScreenX = X; ScreenY = Y; // // Invoke BIOS // _asm { mov ah,2 // function -- position cursor mov bh,0 // display page mov dh,ScreenY mov dl,ScreenX int 10h } #ifndef USE_INT10 CursorIsActuallyOn = TRUE; #endif } VOID DnWriteChar( IN CHAR chr ) /*++ Routine Description: Write a character in the current attribute at the current position. Arguments: chr - Character to write Return Value: None. --*/ { if(chr == '\n') { ScreenX = 0; ScreenY++; return; } #ifdef USE_INT10 // // Position the cursor (turns it on) // DnPositionCursor(ScreenX,ScreenY); // // Output the character // _asm { mov ah,9 // function -- write char/attribute pair mov al,chr mov bh,0 // display page mov bl,CurrentAttribute mov cx,1 // replication factor int 10h } // // If the cursor is supposed to be off, shut it off // if(!CursorOn) { _asm { mov ah,2 // function -- position cursor mov bh,0 // display page mov dh,SCREEN_HEIGHT mov dl,0 int 10h } } #else // // Don't draw outside the actual screen boundaries // if ( ( ScreenX < SCREEN_WIDTH ) && ( ScreenY < SCREEN_HEIGHT ) ) { SCREEN_BUFFER_CHR(ScreenX,ScreenY) = chr; SCREEN_BUFFER_ATT(ScreenX,ScreenY) = CurrentAttribute; } // // shut cursor off if necessary // if(!CursorOn && CursorIsActuallyOn) { CursorIsActuallyOn = FALSE; _asm { mov ah,2 // function -- position cursor mov bh,0 // display page mov dh,SCREEN_HEIGHT mov dl,0 int 10h } } #endif } VOID DnWriteString( IN PCHAR String ) /*++ Routine Description: Write a string on the client area in the current position and adjust the current position. The string is written in the current attribute. Arguments: String - null terminated string to write. Return Value: None. --*/ { PCHAR p; for(p=String; *p; p++) { DnWriteChar(*p); if(*p != '\n') { ScreenX++; } } } VOID DnWriteStatusText( IN PCHAR FormatString OPTIONAL, ... ) /*++ Routine Description: Update the status area Arguments: FormatString - if present, supplies a printf format string for the rest of the arguments. Otherwise the status area is cleared out. Return Value: None. --*/ { va_list arglist; int StringLength; static CHAR String[SCREEN_WIDTH+1]; UCHAR SavedAttribute; // // First, clear out the status area. // DnpBlankScreenArea( STATUS_ATTRIBUTE, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-STATUS_HEIGHT, SCREEN_HEIGHT-1 ); if(FormatString) { va_start(arglist,FormatString); StringLength = vsnprintf(String,SCREEN_WIDTH+1,FormatString,arglist); String[SCREEN_WIDTH] = '\0'; SavedAttribute = CurrentAttribute; CurrentAttribute = STATUS_ATTRIBUTE; DnPositionCursor(STATUS_LEFT_MARGIN,SCREEN_HEIGHT - STATUS_HEIGHT); DnWriteString(String); CurrentAttribute = SavedAttribute; } } VOID DnSetCopyStatusText( IN PCHAR Caption, IN PCHAR Filename ) /*++ Routine Description: Write or erase a copying message in the lower right part of the screen. Arguments: Filename - name of file currently being copied. If NULL, erases the copy status area. Return Value: None. --*/ { unsigned CopyStatusAreaLen; CHAR StatusText[100]; // // The 13 is for 8.3 and a space // CopyStatusAreaLen = strlen(Caption) + 13; // // First erase the status area. // DnpBlankScreenArea( STATUS_ATTRIBUTE, (UCHAR)(SCREEN_WIDTH - CopyStatusAreaLen), SCREEN_WIDTH - 1, SCREEN_HEIGHT - STATUS_HEIGHT, SCREEN_HEIGHT - 1 ); if(Filename) { UCHAR SavedAttribute; UCHAR SavedX,SavedY; SavedAttribute = CurrentAttribute; SavedX = ScreenX; SavedY = ScreenY; CurrentAttribute = STATUS_ATTRIBUTE; DnPositionCursor((UCHAR)(SCREEN_WIDTH-CopyStatusAreaLen),SCREEN_HEIGHT-1); memset(StatusText,0,sizeof(StatusText)); strcpy(StatusText,Caption); strncpy(StatusText + strlen(StatusText),Filename,12); DnWriteString(StatusText); CurrentAttribute = SavedAttribute; ScreenX = SavedX; ScreenY = SavedY; } } VOID DnStartEditField( IN BOOLEAN CreateField, IN UCHAR X, IN UCHAR Y, IN UCHAR W ) /*++ Routine Description: Sets up the display package to start handling an edit field. Arguments: CreateField - if TRUE, caller is starting an edit field interaction. If FALSE, he is ending one. X,Y,W - supply coords and width in chars of the edit field. Return Value: None. --*/ { static UCHAR SavedAttribute = 255; CursorOn = CreateField; if(CreateField) { if(SavedAttribute == 255) { SavedAttribute = CurrentAttribute; CurrentAttribute = EDIT_ATTRIBUTE; } DnpBlankScreenArea(EDIT_ATTRIBUTE,X,(UCHAR)(X+W-1),Y,Y); } else { if(SavedAttribute != 255) { CurrentAttribute = SavedAttribute; SavedAttribute = 255; } } } VOID DnExitDialog( VOID ) { unsigned W,H,X,Y,i; PUCHAR CharSave; PUCHAR AttSave; ULONG Key,ValidKeys[3] = { ASCI_CR,DN_KEY_F3,0 }; UCHAR SavedX,SavedY,SavedAttribute; #ifndef USE_INT10 BOOLEAN SavedCursorState = CursorOn; #endif SavedAttribute = CurrentAttribute; CurrentAttribute = EXITDLG_ATTRIBUTE; SavedX = ScreenX; SavedY = ScreenY; #ifndef USE_INT10 // // Shut the cursor off. // CursorIsActuallyOn = FALSE; CursorOn = FALSE; _asm { mov ah,2 // function -- position cursor mov bh,0 // display page mov dh,SCREEN_HEIGHT mov dl,0 int 10h } #endif // // Count lines in the dialog and determine its width. // for(H=0; DnsExitDialog.Strings[H]; H++); W = strlen(DnsExitDialog.Strings[0]); // // allocate two buffers for character save and attribute save // CharSave = MALLOC(W*H,TRUE); AttSave = MALLOC(W*H,TRUE); // // save the screen patch // for(Y=0; Y