ref: 2c0d5e026f50ae4f2a069b882a598e9a8a4d553b
dir: /us1.c/
// // ID Engine // ID_US_1.c - User Manager - General routines // v1.1d1 // By Jason Blochowiak // Hacked up for Catacomb 3D // // // This module handles dealing with user input & feedback // // Depends on: Input Mgr, View Mgr, some variables from the Sound, Caching, // and Refresh Mgrs, Memory Mgr for background save/restore // // Globals: // ingame - Flag set by game indicating if a game is in progress // abortgame - Flag set if the current game should be aborted (if a load // game fails) // loadedgame - Flag set if a game was loaded // abortprogram - Normally nil, this points to a terminal error message // if the program needs to abort // restartgame - Normally set to gd_Continue, this is set to one of the // difficulty levels if a new game should be started // PrintX, PrintY - Where the User Mgr will print (global coords) // WindowX,WindowY,WindowW,WindowH - The dimensions of the current // window // #include "ID_HEADS.H" #pragma hdrstop #pragma warn -pia // Global variables char *abortprogram; int NoWait; u16int PrintX,PrintY; u16int WindowX,WindowY,WindowW,WindowH; // Internal variables #define ConfigVersion 1 static char *ParmStrings[] = {"TEDLEVEL","NOWAIT"}, *ParmStrings2[] = {"COMP","NOCOMP"}; static int US_Started; int Button0,Button1, CursorBad; s16int CursorX,CursorY; void (*USL_MeasureString)(char far *,u16int *,u16int *) = VW_MeasurePropString, (*USL_DrawString)(char far *) = VWB_DrawPropString; SaveGame Games[MaxSaveGames]; HighScore Scores[MaxScores] = { {"id software-'92",10000,1}, {"Adrian Carmack",10000,1}, {"John Carmack",10000,1}, {"Kevin Cloud",10000,1}, {"Tom Hall",10000,1}, {"John Romero",10000,1}, {"Jay Wilbur",10000,1}, }; // Internal routines // Public routines /////////////////////////////////////////////////////////////////////////// // // USL_HardError() - Handles the Abort/Retry/Fail sort of errors passed // from DOS. // /////////////////////////////////////////////////////////////////////////// #pragma warn -par #pragma warn -rch int USL_HardError(u16int errval,s16int ax,s16int bp,s16int si) { #define IGNORE 0 #define RETRY 1 #define ABORT 2 extern void ShutdownId(void); static char buf[32]; static WindowRec wr; s16int di; char c,*s,*t; di = _DI; if (ax < 0) s = "Device Error"; else { if ((di & 0x00ff) == 0) s = "Drive ~ is Write Protected"; else s = "Error on Drive ~"; for (t = buf;*s;s++,t++) // Can't use sprintf() if ((*t = *s) == '~') *t = (ax & 0x00ff) + 'A'; *t = '\0'; s = buf; } c = peekb(0x40,0x49); // Get the current screen mode if ((c < 4) || (c == 7)) goto oh_kill_me; // DEBUG - handle screen cleanup US_SaveWindow(&wr); US_CenterWindow(30,3); US_CPrint(s); US_CPrint("(R)etry or (A)bort?"); VW_UpdateScreen(); IN_ClearKeysDown(); asm sti // Let the keyboard interrupts come through while (true) { switch (IN_WaitForASCII()) { case key_Escape: case 'a': case 'A': goto oh_kill_me; break; case key_Return: case key_Space: case 'r': case 'R': US_ClearWindow(); VW_UpdateScreen(); US_RestoreWindow(&wr); return(RETRY); break; } } oh_kill_me: abortprogram = s; ShutdownId(); fprintf(stderr,"Terminal Error: %s\n",s); if (tedlevel) fprintf(stderr,"You launched from TED. I suggest that you reboot...\n"); return(ABORT); #undef IGNORE #undef RETRY #undef ABORT } #pragma warn +par #pragma warn +rch /////////////////////////////////////////////////////////////////////////// // // US_Startup() - Starts the User Mgr // /////////////////////////////////////////////////////////////////////////// void US_Startup(void) { s16int i,n; if (US_Started) return; harderr(USL_HardError); // Install the fatal error handler US_InitRndT(true); // Initialize the random number generator for (i = 1;i < _argc;i++) { switch (US_CheckParm(_argv[i],ParmStrings2)) { case 0: compatability = true; break; case 1: compatability = false; break; } } // Check for TED launching here for (i = 1;i < _argc;i++) { n = US_CheckParm(_argv[i],ParmStrings); switch(n) { case 0: tedlevelnum = atoi(_argv[i + 1]); if (tedlevelnum >= 0) tedlevel = true; break; case 1: NoWait = true; break; } } US_Started = true; } /////////////////////////////////////////////////////////////////////////// // // US_Shutdown() - Shuts down the User Mgr // /////////////////////////////////////////////////////////////////////////// void US_Shutdown(void) { if (!US_Started) return; US_Started = false; } /////////////////////////////////////////////////////////////////////////// // // US_CheckParm() - checks to see if a string matches one of a set of // strings. The check is case insensitive. The routine returns the // index of the string that matched, or -1 if no matches were found // /////////////////////////////////////////////////////////////////////////// int US_CheckParm(char *parm,char **strings) { char cp,cs, *p,*s; s16int i; while (!isalpha(*parm)) // Skip non-alphas parm++; for (i = 0;*strings && **strings;i++) { for (s = *strings++,p = parm,cs = cp = 0;cs == cp;) { cs = *s++; if (!cs) return(i); cp = *p++; if (isupper(cs)) cs = tolower(cs); if (isupper(cp)) cp = tolower(cp); } } return(-1); } // Window/Printing routines /////////////////////////////////////////////////////////////////////////// // // US_SetPrintRoutines() - Sets the routines used to measure and print // from within the User Mgr. Primarily provided to allow switching // between masked and non-masked fonts // /////////////////////////////////////////////////////////////////////////// void US_SetPrintRoutines(void (*measure)(char far *,u16int *,u16int *),void (*print)(char far *)) { USL_MeasureString = measure; USL_DrawString = print; } /////////////////////////////////////////////////////////////////////////// // // US_Print() - Prints a string in the current window. Newlines are // supported. // /////////////////////////////////////////////////////////////////////////// void US_Print(char far *s) { char c,far *se; u16int w,h; while (*s) { se = s; while ((c = *se) && (c != '\n')) se++; *se = '\0'; USL_MeasureString(s,&w,&h); px = PrintX; py = PrintY; USL_DrawString(s); s = se; if (c) { *se = c; s++; PrintX = WindowX; PrintY += h; } else PrintX += w; } } /////////////////////////////////////////////////////////////////////////// // // US_PrintUnsigned() - Prints an u32int // /////////////////////////////////////////////////////////////////////////// void US_PrintUnsigned(u32int n) { char buffer[32]; US_Print(ultoa(n,buffer,10)); } /////////////////////////////////////////////////////////////////////////// // // US_PrintSigned() - Prints a s32int // /////////////////////////////////////////////////////////////////////////// void US_PrintSigned(s32int n) { char buffer[32]; US_Print(ltoa(n,buffer,10)); } /////////////////////////////////////////////////////////////////////////// // // USL_PrintInCenter() - Prints a string in the center of the given rect // /////////////////////////////////////////////////////////////////////////// void USL_PrintInCenter(char far *s,Rectangle r) { u16int w,h; USL_MeasureString(s,&w,&h); px = r.min.x + ((Dx(r) - w) / 2); py = r.min.y + ((Dy(r) - h) / 2); USL_DrawString(s); } /////////////////////////////////////////////////////////////////////////// // // US_PrintCentered() - Prints a string centered in the current window. // /////////////////////////////////////////////////////////////////////////// void US_PrintCentered(char far *s) { USL_PrintInCenter(s,Rect(WindowX,WindowY,WindowW+WindowX,WindowH+WindowY); } /////////////////////////////////////////////////////////////////////////// // // US_CPrintLine() - Prints a string centered on the current line and // advances to the next line. Newlines are not supported. // /////////////////////////////////////////////////////////////////////////// void US_CPrintLine(char far *s) { u16int w,h; USL_MeasureString(s,&w,&h); if (w > WindowW) Quit("US_CPrintLine() - String exceeds width"); px = WindowX + ((WindowW - w) / 2); py = PrintY; USL_DrawString(s); PrintY += h; } /////////////////////////////////////////////////////////////////////////// // // US_CPrint() - Prints a string in the current window. Newlines are // supported. // /////////////////////////////////////////////////////////////////////////// void US_CPrint(char far *s) { char c,far *se; while (*s) { se = s; while ((c = *se) && (c != '\n')) se++; *se = '\0'; US_CPrintLine(s); s = se; if (c) { *se = c; s++; } } } /////////////////////////////////////////////////////////////////////////// // // US_ClearWindow() - Clears the current window to white and homes the // cursor // /////////////////////////////////////////////////////////////////////////// void US_ClearWindow(void) { VWB_Bar(WindowX,WindowY,WindowW,WindowH,WHITE); PrintX = WindowX; PrintY = WindowY; } /////////////////////////////////////////////////////////////////////////// // // US_DrawWindow() - Draws a frame and sets the current window parms // /////////////////////////////////////////////////////////////////////////// void US_DrawWindow(u16int x,u16int y,u16int w,u16int h) { u16int i, sx,sy,sw,sh; WindowX = x * 8; WindowY = y * 8; WindowW = w * 8; WindowH = h * 8; PrintX = WindowX; PrintY = WindowY; sx = (x - 1) * 8; sy = (y - 1) * 8; sw = (w + 1) * 8; sh = (h + 1) * 8; US_ClearWindow(); VWB_DrawTile8(sx,sy,0),VWB_DrawTile8(sx,sy + sh,5); for (i = sx + 8;i <= sx + sw - 8;i += 8) VWB_DrawTile8(i,sy,1),VWB_DrawTile8(i,sy + sh,6); VWB_DrawTile8(i,sy,2),VWB_DrawTile8(i,sy + sh,7); for (i = sy + 8;i <= sy + sh - 8;i += 8) VWB_DrawTile8(sx,i,3),VWB_DrawTile8(sx + sw,i,4); } /////////////////////////////////////////////////////////////////////////// // // US_CenterWindow() - Generates a window of a given width & height in the // middle of the screen // /////////////////////////////////////////////////////////////////////////// void US_CenterWindow(u16int w,u16int h) { US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h); } /////////////////////////////////////////////////////////////////////////// // // US_SaveWindow() - Saves the current window parms into a record for // later restoration // /////////////////////////////////////////////////////////////////////////// void US_SaveWindow(WindowRec *win) { win->x = WindowX; win->y = WindowY; win->w = WindowW; win->h = WindowH; win->px = PrintX; win->py = PrintY; } /////////////////////////////////////////////////////////////////////////// // // US_RestoreWindow() - Sets the current window parms to those held in the // record // /////////////////////////////////////////////////////////////////////////// void US_RestoreWindow(WindowRec *win) { WindowX = win->x; WindowY = win->y; WindowW = win->w; WindowH = win->h; PrintX = win->px; PrintY = win->py; } // Input routines /////////////////////////////////////////////////////////////////////////// // // USL_XORICursor() - XORs the I-bar text cursor. Used by US_LineInput() // /////////////////////////////////////////////////////////////////////////// static void USL_XORICursor(s16int x,s16int y,char *s,u16int cursor) { static int status; // VGA doesn't XOR... char buf[MaxString]; s16int temp; u16int w,h; strcpy(buf,s); buf[cursor] = '\0'; USL_MeasureString(buf,&w,&h); px = x + w - 1; py = y; if (status^=1) USL_DrawString("\x80"); else { temp = fontcolor; fontcolor = backcolor; USL_DrawString("\x80"); fontcolor = temp; } } /////////////////////////////////////////////////////////////////////////// // // US_LineInput() - Gets a line of user input at (x,y), the string defaults // to whatever is pointed at by def. Input is restricted to maxchars // chars or maxwidth pixels wide. If the user hits escape (and escok is // true), nothing is copied into buf, and false is returned. If the // user hits return, the current string is copied into buf, and true is // returned // /////////////////////////////////////////////////////////////////////////// int US_LineInput(s16int x,s16int y,char *buf,char *def,int escok, s16int maxchars,s16int maxwidth) { int redraw, cursorvis,cursormoved, done,result; u8int sc; char c, s[MaxString],olds[MaxString]; u16int i, cursor, w,h, len,temp; u32int lasttime; if (def) strcpy(s,def); else *s = '\0'; *olds = '\0'; cursor = strlen(s); cursormoved = redraw = true; cursorvis = done = false; lasttime = TimeCount; LastASCII = key_None; LastScan = sc_None; while (!done) { if (cursorvis) USL_XORICursor(x,y,s,cursor); asm pushf asm cli sc = LastScan; LastScan = sc_None; c = LastASCII; LastASCII = key_None; asm popf switch (sc) { case sc_LeftArrow: if (cursor) cursor--; c = key_None; cursormoved = true; break; case sc_RightArrow: if (s[cursor]) cursor++; c = key_None; cursormoved = true; break; case sc_Home: cursor = 0; c = key_None; cursormoved = true; break; case sc_End: cursor = strlen(s); c = key_None; cursormoved = true; break; case sc_Return: strcpy(buf,s); done = true; result = true; c = key_None; break; case sc_Escape: if (escok) { done = true; result = false; } c = key_None; break; case sc_BackSpace: if (cursor) { strcpy(s + cursor - 1,s + cursor); cursor--; redraw = true; } c = key_None; cursormoved = true; break; case sc_Delete: if (s[cursor]) { strcpy(s + cursor,s + cursor + 1); redraw = true; } c = key_None; cursormoved = true; break; case 0x4c: // Keypad 5 case sc_UpArrow: case sc_DownArrow: case sc_PgUp: case sc_PgDn: case sc_Insert: c = key_None; break; } if (c) { len = strlen(s); USL_MeasureString(s,&w,&h); if ( isprint(c) && (len < MaxString - 1) && ((!maxchars) || (len < maxchars)) && ((!maxwidth) || (w < maxwidth)) ) { for (i = len + 1;i > cursor;i--) s[i] = s[i - 1]; s[cursor++] = c; redraw = true; } } if (redraw) { px = x; py = y; temp = fontcolor; fontcolor = backcolor; USL_DrawString(olds); fontcolor = temp; strcpy(olds,s); px = x; py = y; USL_DrawString(s); redraw = false; } if (cursormoved) { cursorvis = false; lasttime = TimeCount - TickBase; cursormoved = false; } if (TimeCount - lasttime > TickBase / 2) { lasttime = TimeCount; cursorvis ^= true; } if (cursorvis) USL_XORICursor(x,y,s,cursor); VW_UpdateScreen(); } if (cursorvis) USL_XORICursor(x,y,s,cursor); if (!result) { px = x; py = y; USL_DrawString(olds); } VW_UpdateScreen(); IN_ClearKeysDown(); return(result); }