From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/boot/setup/arcdisp.c | 1762 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1762 insertions(+) create mode 100644 private/ntos/boot/setup/arcdisp.c (limited to 'private/ntos/boot/setup/arcdisp.c') diff --git a/private/ntos/boot/setup/arcdisp.c b/private/ntos/boot/setup/arcdisp.c new file mode 100644 index 000000000..77f0a4c5b --- /dev/null +++ b/private/ntos/boot/setup/arcdisp.c @@ -0,0 +1,1762 @@ +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + arcdisp.c + +Abstract: + + This module provides code for managing screen output on an ARC-compliant + system. + +Author: + + John Vert (jvert) 6-Oct-1993 + +Revision History: + + John Vert (jvert) 6-Oct-1993 + Taken from old 1.0 splib sources + +--*/ +#include "setupldr.h" +#include "stdio.h" + +// +// The screen is divided into 3 areas: the header area, the status area, +// and the client area. The header area basically always says "Windows NT +// Setup". The status area is always 1 line high and displayed using a +// different attribute (black on gray). +// + + +#define HEADER_HEIGHT 3 +#define MAX_STATUS 200 // allow up to 1600 horizontal res. + +#define SCREEN_SIZE (ScreenWidth*ScreenHeight) + + +ULONG ScreenWidth=80; +ULONG ScreenHeight=25; +ULONG ScreenX=0,ScreenY=0; +UCHAR CurAttribute = DEFATT; +CHAR MessageBuffer[1024]; + +// +// private function prototypes +// +VOID +SlpDrawMenu( + IN ULONG X, + IN ULONG Y, + IN ULONG TopItem, + IN ULONG Height, + IN PSL_MENU Menu + ); + +VOID +SlpDrawMenuItem( + IN ULONG X, + IN ULONG Y, + IN ULONG TopItem, + IN ULONG Height, + IN ULONG Item, + IN PSL_MENU Menu + ); + +VOID +SlpSizeMessage( + IN PCHAR Message, + OUT PULONG Lines, + OUT PULONG MaxLength, + OUT ULONG LineLength[], + OUT PCHAR LineText[] + ); + + + +PSL_MENU +SlCreateMenu( + VOID + ) + +/*++ + +Routine Description: + + Allocates and initializes a new menu structure. + +Arguments: + + None + +Return Value: + + Pointer to the new menu structure if successful. + + NULL on failure + +--*/ +{ + PSL_MENU p; + + p=BlAllocateHeap(sizeof(SL_MENU)); + if (p==NULL) { + return(NULL); + } + p->ItemCount = 0; + p->Width = 0; + InitializeListHead(&p->ItemListHead); + return(p); +} + + +BOOLEAN +SlGetMenuItemIndex( + IN PSL_MENU Menu, + IN PCHAR Text, + OUT PULONG Index + ) + +/*++ + +Routine Description: + + Given the text of a menu item, returns the index of that item. + +Arguments: + + Menu - Supplies the menu + + Text - Supplies the text to search for. + + Index - Returns the index of the text in the menu + +Return Value: + + TRUE - Item was found. + + FALSE - Item was not found + +--*/ + +{ + ULONG i; + PSL_MENUITEM Item; + + // + // Find first item to display + // + Item = CONTAINING_RECORD(Menu->ItemListHead.Flink, + SL_MENUITEM, + ListEntry); + + i=0; + while ( Item != CONTAINING_RECORD(&Menu->ItemListHead, + SL_MENUITEM, + ListEntry)) { + if (_stricmp(Item->Text,Text)==0) { + *Index = i; + return(TRUE); + } + + Item = CONTAINING_RECORD(Item->ListEntry.Flink, + SL_MENUITEM, + ListEntry); + ++i; + + } + return(FALSE); +} + + +PVOID +SlGetMenuItem( + IN PSL_MENU Menu, + IN ULONG Item + ) + +/*++ + +Routine Description: + + Given an item index, returns the data associated with that item. + +Arguments: + + Menu - Supplies the menu structure. + + Item - Supplies the item index. + +Return Value: + + The data associated with the given item. + +--*/ + +{ + ULONG i; + PSL_MENUITEM MenuItem; + + // + // Find item to return + // + MenuItem = CONTAINING_RECORD(Menu->ItemListHead.Flink, + SL_MENUITEM, + ListEntry); + + for (i=0;iListEntry.Flink, + SL_MENUITEM, + ListEntry); + +#if DBG + if (&MenuItem->ListEntry == &Menu->ItemListHead) { + SlError(Item); + return(NULL); + } +#endif + } + return(MenuItem->Data); + +} + + +ULONG +SlAddMenuItem( + PSL_MENU Menu, + PCHAR Text, + PVOID Data, + ULONG Attributes + ) + +/*++ + +Routine Description: + + Adds an item to the menu + +Arguments: + + Menu - Supplies a pointer to the menu the item will be added to + + Text - Supplies the text to be displayed in the menu + + Data - Supplies a pointer to the data to be returned when the item + is selected. + + Attributes - Supplies any attributes for the item. + +Return Value: + + The Selection index if successful + + -1 on failure + +--*/ +{ + PSL_MENUITEM NewItem; + ULONG Length; + + NewItem = BlAllocateHeap(sizeof(SL_MENUITEM)); + if (NewItem==NULL) { + SlError(0); + return((ULONG)-1); + } + InsertTailList(&Menu->ItemListHead, &NewItem->ListEntry); + Menu->ItemCount += 1; + + NewItem->Text = Text; + NewItem->Data = Data; + NewItem->Attributes = Attributes; + Length = strlen(Text); + if (Length > Menu->Width) { + Menu->Width = Length; + } + return(Menu->ItemCount - 1); +} + + +ULONG +SlDisplayMenu( + IN ULONG HeaderId, + IN PSL_MENU Menu, + IN OUT PULONG Selection + ) + +/*++ + +Routine Description: + + Displays a menu and allows the user to pick a selection + +Arguments: + + HeaderId - Supplies the message ID of the prompt header + to be displayed above the menu. + + Menu - Supplies a pointer to the menu to be displayed + + Selection - Supplies the index of the default item. + Returns the index of the selected item. + +Return Value: + + Key that terminated the menu display. + +--*/ +{ + LONG X, Y; + ULONG Height; + ULONG Width; + ULONG TopItem; + ULONG c; + ULONG PreviousSelection; + ULONG Sel; + PCHAR Header; + ULONG HeaderLines; + ULONG MaxHeaderLength; + PCHAR HeaderText[20]; + ULONG HeaderLength[20]; + ULONG MaxMenuHeight; + ULONG i; + ULONG Count; + + Header = BlFindMessage(HeaderId); + + SlpSizeMessage(Header, + &HeaderLines, + &MaxHeaderLength, + HeaderLength, + HeaderText); + + X = (ScreenWidth-MaxHeaderLength)/2; + for (i=0;i ScreenWidth) { + MaxHeaderLength = ScreenWidth; + } + + Width = Menu->Width+4; + if (Width > ScreenWidth) { + Width=ScreenWidth; + } + + MaxMenuHeight = ScreenHeight-(HeaderLines+13); + + Height = Menu->ItemCount+2; + if (Height > MaxMenuHeight) { + Height = MaxMenuHeight; + } + + X = ((ScreenWidth - Width)/2 > 0) ? (ScreenWidth-Width)/2 : 0; + Y = (MaxMenuHeight - Height)/2 + HeaderLines + 4; + + TopItem = 0; + Sel = *Selection; + // + // Make sure default item is in view; + // + if (Sel >= Height - 2) { + TopItem = Sel - Height + 3; + } + + SlpDrawMenu(X,Y, + TopItem, + Height, + Menu); + + // + // highlight default selection + // + SlSetCurrentAttribute(INVATT); + SlpDrawMenuItem(X,Y, + TopItem, + Height, + Sel, + Menu); + SlSetCurrentAttribute(DEFATT); + SlFlushConsoleBuffer(); + do { + c = SlGetChar(); + PreviousSelection = Sel; + SlpDrawMenuItem(X, Y, + TopItem, + Height, + Sel, + Menu); + + switch (c) { + case SL_KEY_UP: + if(Sel > 0) { + Sel--; + } + break; + + case SL_KEY_DOWN: + if(Sel < Menu->ItemCount - 1) { + Sel++; + } + break; + + case SL_KEY_HOME: + Sel = 0; + break; + + case SL_KEY_END: + Sel = Menu->ItemCount - 1; + break; + + case SL_KEY_PAGEUP: + if (Menu->ItemCount > Height) { + if (Sel > Height) { + Sel -= Height; + } else { + Sel = 0; + } + } + break; + + case SL_KEY_PAGEDOWN: + if (Menu->ItemCount > Height) { + Sel += Height; + if (Sel >= Menu->ItemCount) { + Sel = Menu->ItemCount - 1; + } + } + break; + + case SL_KEY_F1: + case SL_KEY_F3: + case ASCI_CR: + case ASCI_ESC: + *Selection = Sel; + return(c); + + } + + if (Sel < TopItem) { + TopItem = Sel; + SlpDrawMenu(X, Y, + TopItem, + Height, + Menu); + } else if (Sel > TopItem+Height-3) { + TopItem = Sel - Height + 3; + SlpDrawMenu(X, Y, + TopItem, + Height, + Menu); + } + // + // highlight default selection + // + SlSetCurrentAttribute(INVATT); + SlpDrawMenuItem(X,Y, + TopItem, + Height, + Sel, + Menu); + SlSetCurrentAttribute(DEFATT); + + + } while ( TRUE ); + +} + + + +VOID +SlpDrawMenu( + IN ULONG X, + IN ULONG Y, + IN ULONG TopItem, + IN ULONG Height, + IN PSL_MENU Menu + ) + +/*++ + +Routine Description: + + Displays the menu on the screen + +Arguments: + + X - Supplies X coordinate of upper-left corner of menu + + Y - Supplies Y coordinate of upper-left corner of menu + + TopItem - Supplies index of item at the top of the menu + + Height - Supplies the height of the menu + + Menu - Supplies the menu to be displayed + +Return Value: + + None. + +--*/ + +{ + ULONG i; + PSL_MENUITEM Item; + ULONG Count; + CHAR Output[80]; + ULONG Length; + ULONG MenuWidth; + + MenuWidth = Menu->Width+4; + Output[0]=GetGraphicsChar(GraphicsCharDoubleRightDoubleDown); + for (i=1;iItemListHead.Flink, + SL_MENUITEM, + ListEntry); + + for (i=0;iListEntry.Flink, + SL_MENUITEM, + ListEntry); + } + + // + // Display items + // + Output[0]= + Output[MenuWidth-1]=GetGraphicsChar(GraphicsCharDoubleVertical); + for (i=Y+1;iListEntry != &Menu->ItemListHead) { + Length = strlen(Item->Text); + RtlCopyMemory(Output+2,Item->Text,Length); + Item = CONTAINING_RECORD(Item->ListEntry.Flink, + SL_MENUITEM, + ListEntry); + } + ArcWrite(ARC_CONSOLE_OUTPUT,Output,MenuWidth,&Count); + } + Output[0]=GetGraphicsChar(GraphicsCharDoubleRightDoubleUp); + for (i=1;iItemListHead.Flink, + SL_MENUITEM, + ListEntry); + + for (i=0;iListEntry.Flink, + SL_MENUITEM, + ListEntry); + +#if DBG + if (&MenuItem->ListEntry == &Menu->ItemListHead) { + SlError(Item); + } +#endif + } + + RtlFillMemory(Width,Menu->Width,' '); + RtlCopyMemory(Width,MenuItem->Text,strlen(MenuItem->Text)); + SlPositionCursor(X+2, Y+(Item-TopItem)+1); + ArcWrite(ARC_CONSOLE_OUTPUT,Width,Menu->Width,&Count); +} + + + +VOID +SlInitDisplay( + VOID + ) + +/*++ + +Routine Description: + + Clears the screen and does some initialization of global variables based + on the ARC display information. + +Arguments: + + None + +Return Value: + + None. + +--*/ + +{ + PARC_DISPLAY_STATUS DisplayStatus; + + // + // Check to see if this version of the ARC firmware is revision 2 or above. + // + // If not, we default to 80x25 + // + if ((SYSTEM_BLOCK->Version > 1) || + ((SYSTEM_BLOCK->Version == 1) && (SYSTEM_BLOCK->Revision >= 2))) { + + // + // Additional checks are required on 1.2 firmware, since some + // 1.2 firmware does not implement ArcGetDisplayStatus + // + if ((SYSTEM_BLOCK->FirmwareVectorLength > (ULONG)GetDisplayStatusRoutine*sizeof(PVOID)) && + (SYSTEM_BLOCK->FirmwareVector[GetDisplayStatusRoutine] != NULL)) { + DisplayStatus = ArcGetDisplayStatus(ARC_CONSOLE_OUTPUT); + + ScreenWidth = DisplayStatus->CursorMaxXPosition; + ScreenHeight = DisplayStatus->CursorMaxYPosition; + } + } + + SlSetCurrentAttribute(DEFATT); + SlClearDisplay(); +} + + +VOID +SlPrint( + IN PCHAR FormatString, + ... + ) +{ + va_list arglist; + CHAR text[MAX_STATUS+1]; + ULONG Count,Length; + ULONG MaxWidth = ScreenWidth - 2; + + if (MaxWidth > MAX_STATUS) { + MaxWidth = MAX_STATUS; + } + + va_start(arglist,FormatString); + Length = _vsnprintf(text,MaxWidth*sizeof(CHAR),FormatString,arglist); + text[MaxWidth] = 0; + + ArcWrite(ARC_CONSOLE_OUTPUT,text,Length,&Count); + va_end(arglist); +} + + +VOID +SlClearDisplay( + VOID + ) + +/*++ + +Routine Description: + + Clears the entire display, including header, client area, and status line. + +Arguments: + + None + +Return Value: + + None. + +--*/ + +{ + SlClearClientArea(); + SlWriteHeaderText(0); + SlWriteStatusText(""); + +} + +ARC_STATUS +SlClearClientArea( + VOID + ) + +/*++ + +Routine Description: + + Clears the client area of the screen. Does not disturb the header or + status areas. + +Arguments: + + None. + +Return Value: + + always ESUCCESS + +--*/ + +{ + USHORT i; + + for(i=HEADER_HEIGHT; i=ScreenWidth) { + x = ScreenWidth-1; + } + + if(y>=ScreenHeight) { + y = ScreenHeight-1; + } + + ScreenX = x; + ScreenY = y; + + SlPrint(ASCI_CSI_OUT "%d;%dH",y+1,x+1); + return(ESUCCESS); +} + + +ARC_STATUS +SlWriteString( + IN PUCHAR s + ) +{ + PUCHAR p = s,q; + BOOLEAN done = FALSE; + ULONG len,count; + + do { + q = p; + while((*q != '\0') && (*q != '\n')) { + q++; + } + if(*q == '\0') { + done = TRUE; + } else { + *q = '\0'; + } + len = q - p; + + ArcWrite(ARC_CONSOLE_OUTPUT,p,len,&count); + + ScreenX += len; + + if(!done) { + ArcWrite(ARC_CONSOLE_OUTPUT,"\r\n",2,&count); + ScreenX = 0; + ScreenY++; + if(ScreenY == ScreenHeight) { + ScreenY = ScreenHeight-1; + } + *q = '\n'; + } + p = q + 1; + } while(!done); + + return(ESUCCESS); +} + + +VOID +SlSetCurrentAttribute( + IN UCHAR Attribute + ) +{ + CurAttribute = Attribute; + + SlPrint(ASCI_CSI_OUT "0m" ASCI_CSI_OUT "3%dm" ASCI_CSI_OUT "4%dm", + Attribute & 7, // foreground color + (Attribute >> 4) & 7 // background color + ); + + if(Attribute & ATT_FG_INTENSE) { + SlPrint(ASCI_CSI_OUT "1m"); + } +} + + +VOID +SlWriteHeaderText( + IN ULONG MsgId + ) + +/*++ + +Routine Description: + + Updates the header on the screen with a given string + +Arguments: + + MsgId - Supplies the message ID of the new string to be displayed. This should + be just one line long. If it is 0, the header is cleared. + +Return Value: + + None. + +--*/ +{ + int i; + + for(i=HEADER_HEIGHT-1; i>=0; i--) { + SlPositionCursor(0,i); + SlClearToEol(); + } + + if (MsgId != 0) { + SlWriteString(BlFindMessage(MsgId)); + } +} + +// +// Stores the current status text. The size is the screen width, plus the +// terminating nul char. +// +CHAR StatusText[MAX_STATUS]; + +UCHAR StatusAttribute = DEFSTATTR; + +VOID +SlSetStatusAttribute( + IN UCHAR Attribute + ) +{ + StatusAttribute = Attribute; +} + + +VOID +SlWriteStatusText( + IN PCHAR Text + ) + +/*++ + +Routine Description: + + Updates the status area on the screen with a given string + +Arguments: + + Text - Supplies the new text for the status area. + +Return Value: + + None. + +--*/ +{ + UCHAR AttributeSave = CurAttribute; + CHAR *p; + ULONG Count; + ULONG MaxWidth = ScreenWidth - 2; + + if (MaxWidth > MAX_STATUS) { + MaxWidth = MAX_STATUS; + } + + RtlFillMemory(StatusText,sizeof(StatusText),' '); + + // + // Strip cr/lf as we copy the status text into the status text buffer. + // + p = StatusText; + Count = 0; + while((Count < MaxWidth) && *Text) { + if((*Text != '\r') && (*Text != '\n')) { + *p++ = *Text; + Count++; + } + Text++; + } + + SlSetCurrentAttribute(StatusAttribute); + SlPositionCursor(0,ScreenHeight-1); + ArcWrite(ARC_CONSOLE_OUTPUT," ",2,&Count); + SlPositionCursor(2,ScreenHeight-1); + ArcWrite(ARC_CONSOLE_OUTPUT,StatusText,MaxWidth*sizeof(CHAR),&Count); + SlSetCurrentAttribute(AttributeSave); + SlPositionCursor(0,5); +} + + +VOID +SlGetStatusText( + OUT PCHAR Text + ) +{ + RtlCopyMemory(Text,StatusText,sizeof(StatusText)); +} + + + +#if DBG +VOID +SlWriteDbgText( + IN PCHAR text + ) +{ + UCHAR SavedAttribute = CurAttribute; + + SlPositionCursor(0,0); + CurAttribute = ATT_FG_YELLOW | ATT_BG_RED | ATT_FG_INTENSE; + + SlClearToEol(); + SlWriteString(text); + + CurAttribute = SavedAttribute; +} +#endif + + +VOID +SlFlushConsoleBuffer( + VOID + ) + +/*++ + +Routine Description: + + This routine flushes the console buffer, so that we don't have any + pre-existing keypresses in the buffer when we prompt the user to + 'press any key to continue.' + +Arguments: + + NONE + +Return Value: + + NONE + +--*/ + +{ + UCHAR c; + ULONG count; + + while(ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) { + ArcRead(ARC_CONSOLE_INPUT, &c, 1, &count); + } +} + + +ULONG +SlGetChar( + VOID + ) +{ + UCHAR c; + ULONG count; + + + ArcRead(ARC_CONSOLE_INPUT,&c,1,&count); + + if(c == ASCI_CSI_IN) { + + ArcRead(ARC_CONSOLE_INPUT,&c,1,&count); + + switch(c) { + + // + // see ntos\fw\mips\fwsignal.c!TranslateScanCode() for these codes. + // Additional codes that might be useful someday: + // left=C, right=D, insert=@, delete=P + // + + case 'A': // up arrow + return(SL_KEY_UP); + + case 'B': // down arrow + return(SL_KEY_DOWN); + + case 'H': // home + return(SL_KEY_HOME); + + case 'K': // end + return(SL_KEY_END); + + case '?': // page up + return(SL_KEY_PAGEUP); + + case '/': // page down + return(SL_KEY_PAGEDOWN); + + case 'O': // function keys + + ArcRead(ARC_CONSOLE_INPUT,&c,1,&count); + + // + // F1=P, F2=Q, F3=w, F4 =x, F5 =t, F6 =u + // F7=q, F8=r, F9=p, F10=m, F11=A, F12=B + // + // Note: as of 12/15/92, f11 and f12 were commented out in the + // firmware sources so are probably never returned. + // + + switch(c) { + + case 'P': + return(SL_KEY_F1); + + case 'w': + return(SL_KEY_F3); + + case 't': + return(SL_KEY_F5); + + case 'u': + return(SL_KEY_F6); + + default: + return(0); + } + + default: + return(0); + } + + } else { + if(c == ASCI_LF) { + c = ASCI_CR; + } + return((ULONG)c); + } +} + + +BOOLEAN +SlPromptForDisk( + IN PCHAR DiskName, + IN BOOLEAN IsCancellable + ) + +/*++ + +Routine Description: + + This routine prompts a user to insert a given diskette #, or to abort the + Setup process. + + The status line will be erased. + +Arguments: + + DiskName - Supplies the name of the disk to be inserted. + + IsCancellable - Supplies flag indicating whether prompt may be cancelled. + +Return Value: + + TRUE - The user has pressed OK + + FALSE - The user has pressed CANCEL + +--*/ + +{ + ULONG msg; + ULONG y; + ULONG Key; + PCHAR StatusText; + PCHAR PleaseWait; + ULONG i; + CHAR DiskNameDisplayed[81]; + BOOLEAN Repaint=TRUE; + + SlWriteStatusText(""); + + if(IsCancellable) { + msg = SL_NEXT_DISK_PROMPT_CANCELLABLE; + } else { + msg = SL_NEXT_DISK_PROMPT; + } + StatusText = BlFindMessage(msg); + if(StatusText == NULL) { + SlError(msg); + return(FALSE); + } + + PleaseWait = BlFindMessage(SL_PLEASE_WAIT); + if(PleaseWait == NULL) { + SlError(SL_PLEASE_WAIT); + return(FALSE); + } + + // + // Get first line of DiskName and save it in DiskNameDisplayed (limit to 80 chars) + // + for(i = 0; + ((i < 80) && DiskName[i] && (DiskName[i] != '\r') && (DiskName[i] != '\n')); + i++) + { + DiskNameDisplayed[i] = DiskName[i]; + } + DiskNameDisplayed[i] = '\0'; + + do { + if (Repaint) { + SlClearClientArea(); + y = SlDisplayMessageBox(SL_MSG_INSERT_DISK); + SlPositionCursor((ScreenWidth-i)/2,y+2); + SlWriteString(DiskNameDisplayed); + SlWriteStatusText(StatusText); + } + Repaint = FALSE; + SlFlushConsoleBuffer(); + Key = SlGetChar(); + + if (Key == ASCI_CR) { + SlClearClientArea(); + SlWriteStatusText(PleaseWait); + return(TRUE); + } else if (Key == SL_KEY_F3) { + SlConfirmExit(); + Repaint=TRUE; + } else if((Key == ASCI_ESC) && IsCancellable) { + SlWriteStatusText(""); + SlClearClientArea(); + return FALSE; + } + } while ( TRUE ); +} + + +VOID +SlConfirmExit( + VOID + ) + +/*++ + +Routine Description: + + Routine to be called when user presses F3. Confirms that he really wants + to exit by popping up a dialog. DOES NOT RETURN if user chooses to exit. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + ULONG c; + CHAR OldStatus[MAX_STATUS]; + PCHAR StatusText; + + SlGetStatusText(OldStatus); + + SlClearClientArea(); + + SlSetCurrentAttribute(DEFDLGATT); + + SlDisplayMessageBox(SL_MSG_EXIT_DIALOG); + + SlSetCurrentAttribute(DEFATT); + + SlFlushConsoleBuffer(); + + while(1) { + c = SlGetChar(); + if(c == ASCI_CR) { + SlWriteStatusText(OldStatus); + return; + } + if(c == SL_KEY_F3) { + StatusText = BlFindMessage(SL_REBOOT_PROMPT); + SlClearClientArea(); +#ifdef i386 + SlDisplayMessageBox(SL_SCRN_TEXTSETUP_EXITED); +#else + SlDisplayMessageBox(SL_SCRN_TEXTSETUP_EXITED_ARC); +#endif + SlWriteStatusText(StatusText); + + SlFlushConsoleBuffer(); + while(SlGetChar() != ASCI_CR); + ArcRestart(); + } + } +} + + + +VOID +SlFriendlyError( + IN ULONG uStatus, + IN PCHAR pchBadFile, + IN ULONG uLine, + IN PCHAR pchCodeFile + ) + +/*++ + +Routine Description: + + This is called when an error occurs. It puts up a + message box, displays an informative message, and allows + the user to continue. It is intended to give friendlier + messages than the SlError macro, in the cases where SlError + gets passed ARC error codes. + + The status text line will be erased. + +Arguments: + + uStatus - ARC error code + + pchBadFile - Name of file causing error (Must be given for handled + ARC codes. Optional for unhandled codes.) + + uLine - Line # in source code file where error occurred (only + used for unhandled codes.) + + pchCodeFile - Name of souce code file where error occurred (only + used for unhandled codes.) + +Return Value: + + None. + +--*/ + +{ + ULONG uMsg; + + SlClearClientArea(); + switch(uStatus) { + case EBADF: + case EINVAL: // image corrupt + uMsg = SL_WARNING_IMG_CORRUPT; + break; + + case EIO: // i/o error + uMsg = SL_WARNING_IOERR; + break; + + case ENOENT: // file not found + uMsg = SL_WARNING_NOFILE; + break; + + case ENOMEM: // insufficient memory + uMsg = SL_WARNING_NOMEM; + break; + + case EACCES: // unrecognized file system + uMsg = SL_WARNING_BAD_FILESYS; + break; + + default: // then get SlError() behavior (with optional bad file name) + if(pchBadFile) { // include error-causing file's name + SlMessageBox( + SL_WARNING_ERROR_WFILE, + pchBadFile, + uStatus, + uLine, + pchCodeFile + ); + } else { + SlMessageBox( + SL_WARNING_ERROR, + uStatus, + uLine, + pchCodeFile + ); + } + return; + } + SlMessageBox( + uMsg, + pchBadFile + ); +} + +VOID +SlMessageBox( + IN ULONG MessageId, + ... + ) + +/*++ + +Routine Description: + + This is called when an error occurs. It puts up a + message box, displays an informative message, and allows + the user to continue. + + The status text line will be erased. + +Arguments: + + MessageId - Supplies ID of message box to be presented. + + any sprintf-compatible arguments to be inserted in the + message box. + +Return Value: + + None. + +--*/ + +{ + va_list args; + + SlClearClientArea(); + va_start(args, MessageId); + SlGenericMessageBox(MessageId, &args, NULL, NULL, NULL, NULL, TRUE); + va_end(args); + + SlFlushConsoleBuffer(); + SlGetChar(); +} + + +ULONG +SlDisplayMessageBox( + IN ULONG MessageId, + ... + ) + +/*++ + +Routine Description: + + Just puts a message box up on the screen and returns. + + The status text line will be erased. + +Arguments: + + MessageId - Supplies ID of message box to be presented. + + any sprintf-compatible arguments to be inserted in the + message box. + +Return Value: + + Y position of top line of message box + +--*/ + +{ + ULONG y; + va_list args; + + va_start(args, MessageId); + SlGenericMessageBox(MessageId, &args, NULL, NULL, &y, NULL, TRUE); + va_end(args); + + return(y); +} + + +VOID +SlFatalError( + IN ULONG MessageId, + ... + ) + +/*++ + +Routine Description: + + This is called when a fatal error occurs. It clears the client + area, puts up a message box, displays the fatal error message, and + allows the user to press a key to reboot. + + The status text line will be erased. + +Arguments: + + MessageId - Supplies ID of message box to be presented. + + any sprintf-compatible arguments to be inserted in the + message box. + +Return Value: + + Does not return. + +--*/ + +{ + va_list args; + ULONG x,y; + PUCHAR Text; + + SlClearClientArea(); + + Text = BlFindMessage(MessageId); + if(Text) { + + va_start(args, MessageId); + + _vsnprintf(MessageBuffer, sizeof(MessageBuffer), Text, args); + + // + // Add a blank line, then concatenate the 'Can't continue' text. + // + strcat(MessageBuffer, "\r\n"); + + Text = BlFindMessage(SL_CANT_CONTINUE); + if(Text) { + strcat(MessageBuffer, Text); + } + + Text = BlAllocateHeap((strlen(MessageBuffer)+1) * sizeof(CHAR)); + strcpy(Text, MessageBuffer); + + // + // Note that MessageId and args won't be used, since we're + // passing in our Text pointer. + // + SlGenericMessageBox(MessageId, &args, Text, &x, NULL, &y, TRUE); + + va_end(args); + + } else { + SlError(MessageId); + } + + SlFlushConsoleBuffer(); + SlGetChar(); + ArcRestart(); +} + + +VOID +SlGenericMessageBox( + IN ULONG MessageId, OPTIONAL + IN va_list *args, OPTIONAL + IN PCHAR Message, OPTIONAL + IN OUT PULONG xLeft, OPTIONAL + IN OUT PULONG yTop, OPTIONAL + OUT PULONG yBottom, OPTIONAL + IN BOOLEAN bCenterMsg + ) + +/*++ + +Routine Description: + + Formats and displays a message box. The longest line in the string + of characters will be centered on the screen if bCenterMsg is TRUE. + + The status text line will be erased. + +Arguments: + + NOTE: Either the MessageId/args pair or the Message string must be + specified. Message string will be used if non-NULL. + + MessageId - Supplies the MessageId that will be looked up to provide + a NULL-terminated string of characters. + Each \r\n delimited string will be displayed on its own line. + + args - Supplies the argument list that will be passed to vsprintf. + + Message - Supplies the actual text of the message to be displayed + + xLeft - If bCenterMsg is FALSE, then xLeft is used for the starting x + coordinate of the message (if specified, otherwise, x = 1). + Also, if specified, it receives the x coordinate of the left edge + of all lines that were displayed. + + yTop - If bCenterMsg is FALSE, then yTop is used for the starting y + coordinate of the message (if specified, otherwise, y = 3). + Also, if specified, receives the y coordinate of the top line where + the message box was displayed. + + yBottom - if specified, receives the y coordinate of the bottom line of + the message box. + + bCenterMsg - if TRUE, center message on the screen. + +Return Value: + + None. + +--*/ + +{ + PCHAR p; + ULONG NumLines; + ULONG MaxLength; + ULONG x; + ULONG y; + ULONG i; + PCHAR Line[20]; + ULONG LineLength[20]; + ULONG Count; + + if(!Message) { // then look up the message + p=BlFindMessage(MessageId); + if (p==NULL) { + SlError(MessageId); + x=3; + y=ScreenHeight/2; + NumLines=0; + } else { + _vsnprintf(MessageBuffer,sizeof(MessageBuffer),p,*args); + Message = MessageBuffer; + } + } else { + // + // Just make p non-NULL, so we'll know it's OK to continue. + // + p = Message; + } + + if(p) { + + SlWriteStatusText(""); // Clear status bar + + SlpSizeMessage(Message, + &NumLines, + &MaxLength, + LineLength, + Line); + + if (MaxLength > ScreenWidth) { + MaxLength = ScreenWidth; + } + + if(bCenterMsg) { + x = (ScreenWidth-MaxLength)/2; + y = (ScreenHeight-NumLines)/2; + } else { + if(xLeft) { + x = *xLeft; + } else { + x = 1; + } + + if(yTop) { + y = *yTop; + } else { + y = 3; + } + } + } + + for (i=0; i *MaxLength) { + *MaxLength = Length; + } + LineLength[NumLines] = Length; + ++NumLines; + Length = 0; + p += 2; + LineText[NumLines] = p; + + } else { + ++Length; + ++p; + + if (*p == '\0') { + + // + // End of the message. + // + + if (Length > *MaxLength) { + *MaxLength = Length; + } + LineLength[NumLines] = Length; + ++NumLines; + } + } + } + + *Lines = NumLines; + +} -- cgit v1.2.3