]> 4ch.mooo.com Git - 16.git/blob - 16/cawat/ID_US.C
082b2315e3156eca8896e1d32dc34d289d822d11
[16.git] / 16 / cawat / ID_US.C
1 /* Catacomb Armageddon Source Code\r
2  * Copyright (C) 1993-2014 Flat Rock Software\r
3  *\r
4  * This program is free software; you can redistribute it and/or modify\r
5  * it under the terms of the GNU General Public License as published by\r
6  * the Free Software Foundation; either version 2 of the License, or\r
7  * (at your option) any later version.\r
8  *\r
9  * This program is distributed in the hope that it will be useful,\r
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
12  * GNU General Public License for more details.\r
13  *\r
14  * You should have received a copy of the GNU General Public License along\r
15  * with this program; if not, write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
17  */\r
18 \r
19 //\r
20 //      ID Engine\r
21 //      ID_US.c - User Manager\r
22 //      v1.0d1\r
23 //      By Jason Blochowiak\r
24 //\r
25 \r
26 //\r
27 //      This module handles dealing with user input & feedback\r
28 //\r
29 //      Depends on: Input Mgr, View Mgr, some variables from the Sound, Caching,\r
30 //              and Refresh Mgrs, Memory Mgr for background save/restore\r
31 //\r
32 //      Globals:\r
33 //              ingame - Flag set by game indicating if a game is in progress\r
34 //      abortgame - Flag set if the current game should be aborted (if a load\r
35 //                      game fails)\r
36 //              loadedgame - Flag set if a game was loaded\r
37 //              abortprogram - Normally nil, this points to a terminal error message\r
38 //                      if the program needs to abort\r
39 //              restartgame - Normally set to gd_Continue, this is set to one of the\r
40 //                      difficulty levels if a new game should be started\r
41 //              PrintX, PrintY - Where the User Mgr will print (global coords)\r
42 //              WindowX,WindowY,WindowW,WindowH - The dimensions of the current\r
43 //                      window\r
44 //\r
45 \r
46 // DEBUG - handle LPT3 for Sound Source\r
47 \r
48 #include "ID_HEADS.H"\r
49 \r
50 #define CTL_M_ADLIBUPPIC        CTL_S_ADLIBUPPIC\r
51 #define CTL_M_ADLIBDNPIC        CTL_S_ADLIBDNPIC\r
52 \r
53 #pragma hdrstop\r
54 \r
55 #pragma warn    -pia\r
56 \r
57 #define MaxX    320\r
58 #define MaxY    200\r
59 \r
60 #define MaxHelpLines    500\r
61 \r
62 #define MaxHighName     57\r
63 #define MaxScores       10\r
64 typedef struct\r
65                 {\r
66                         char    name[MaxHighName + 1];\r
67                         long    score;\r
68                         word    completed;\r
69                 } HighScore;\r
70 \r
71 #define MaxGameName             32\r
72 #define MaxSaveGames    7\r
73 typedef struct\r
74                 {\r
75                         char    signature[4];\r
76                         boolean present;\r
77                         char    name[MaxGameName + 1];\r
78                 } SaveGame;\r
79 \r
80 //      Hack import for TED launch support\r
81 extern  boolean         tedlevel;\r
82 extern  word            tedlevelnum;\r
83 extern  void            TEDDeath(void);\r
84 static  char            *ParmStrings[] = {"TEDLEVEL","NOWAIT",""};\r
85 \r
86 \r
87 //      Global variables\r
88                 boolean         ingame,abortgame,loadedgame;\r
89                 char            *abortprogram;\r
90                 GameDiff        restartgame = gd_Continue;\r
91                 word            PrintX,PrintY;\r
92                 word            WindowX,WindowY,WindowW,WindowH;\r
93 \r
94 //      Internal variables\r
95 static  boolean         US_Started;\r
96 static  boolean         GameIsDirty,\r
97                                         HighScoresDirty,\r
98                                         QuitToDos,\r
99                                         ResumeGame,\r
100                                         NoWait;\r
101 \r
102 static  memptr          LineOffsets;\r
103 \r
104 static  boolean         Button0,Button1,\r
105                                         CursorBad;\r
106 static  int                     CursorX,CursorY;\r
107 \r
108 static  void            (*USL_MeasureString)(char far *,word *,word *) = VW_MeasurePropString,\r
109                                         (*USL_DrawString)(char far *) = VWB_DrawPropString;\r
110 \r
111 static  boolean         (*USL_SaveGame)(int),(*USL_LoadGame)(int);\r
112 static  void            (*USL_ResetGame)(void);\r
113 static  SaveGame        Games[MaxSaveGames];\r
114 static  HighScore       Scores[MaxScores] =\r
115                                         {\r
116                                                 {"Sir Lancelot",500},\r
117                                                 {"",0},\r
118                                                 {"",0},\r
119                                                 {"",0},\r
120                                                 {"",0},\r
121                                                 {"",0},\r
122                                                 {"",0},\r
123                                                 {"",0},\r
124                                                 {"",0},\r
125                                                 {"",0}\r
126                                         };\r
127 \r
128 //      Internal routines\r
129 \r
130 //      Public routines\r
131 \r
132 ///////////////////////////////////////////////////////////////////////////\r
133 //\r
134 //      USL_HardError() - Handles the Abort/Retry/Fail sort of errors passed\r
135 //                      from DOS.\r
136 //\r
137 ///////////////////////////////////////////////////////////////////////////\r
138 #pragma warn    -par\r
139 #pragma warn    -rch\r
140 int\r
141 USL_HardError(word errval,int ax,int bp,int si)\r
142 {\r
143 #define IGNORE  0\r
144 #define RETRY   1\r
145 #define ABORT   2\r
146 extern  void    ShutdownId(void);\r
147 \r
148 static  char            buf[32];\r
149 static  WindowRec       wr;\r
150 static  boolean         oldleavedriveon;\r
151                 int                     di;\r
152                 char            c,*s,*t;\r
153 \r
154 \r
155         di = _DI;\r
156 \r
157         oldleavedriveon = LeaveDriveOn;\r
158         LeaveDriveOn = false;\r
159 \r
160         if (ax < 0)\r
161                 s = "Device Error";\r
162         else\r
163         {\r
164                 if ((di & 0x00ff) == 0)\r
165                         s = "Drive ~ is Write Protected";\r
166                 else\r
167                         s = "Error on Drive ~";\r
168                 for (t = buf;*s;s++,t++)        // Can't use sprintf()\r
169                         if ((*t = *s) == '~')\r
170                                 *t = (ax & 0x00ff) + 'A';\r
171                 *t = '\0';\r
172                 s = buf;\r
173         }\r
174 \r
175         c = peekb(0x40,0x49);   // Get the current screen mode\r
176         if ((c < 4) || (c == 7))\r
177                 goto oh_kill_me;\r
178 \r
179         // DEBUG - handle screen cleanup\r
180 \r
181         US_SaveWindow(&wr);\r
182         US_CenterWindow(30,3);\r
183         US_CPrint(s);\r
184         US_CPrint("(R)etry or (A)bort?");\r
185         VW_UpdateScreen();\r
186         IN_ClearKeysDown();\r
187 \r
188 asm     sti     // Let the keyboard interrupts come through\r
189 \r
190         while (true)\r
191         {\r
192                 switch (IN_WaitForASCII())\r
193                 {\r
194                 case key_Escape:\r
195                 case 'a':\r
196                 case 'A':\r
197                         goto oh_kill_me;\r
198                         break;\r
199                 case key_Return:\r
200                 case key_Space:\r
201                 case 'r':\r
202                 case 'R':\r
203                         US_ClearWindow();\r
204                         VW_UpdateScreen();\r
205                         US_RestoreWindow(&wr);\r
206                         LeaveDriveOn = oldleavedriveon;\r
207                         return(RETRY);\r
208                         break;\r
209                 }\r
210         }\r
211 \r
212 oh_kill_me:\r
213         abortprogram = s;\r
214         ShutdownId();\r
215         fprintf(stderr,"Terminal Error: %s\n",s);\r
216         if (tedlevel)\r
217                 fprintf(stderr,"You launched from TED. I suggest that you reboot...\n");\r
218 \r
219         return(ABORT);\r
220 #undef  IGNORE\r
221 #undef  RETRY\r
222 #undef  ABORT\r
223 }\r
224 #pragma warn    +par\r
225 #pragma warn    +rch\r
226 \r
227 ///////////////////////////////////////////////////////////////////////////\r
228 //\r
229 //      USL_GiveSaveName() - Returns a pointer to a static buffer that contains\r
230 //              the filename to use for the specified save game\r
231 //\r
232 ///////////////////////////////////////////////////////////////////////////\r
233 static char *\r
234 USL_GiveSaveName(word game)\r
235 {\r
236 static  char    filename[32];\r
237                 char    *s,*t;\r
238 \r
239         for (s = "SAVEGM",t = filename;*s;)\r
240                 *t++ = *s++;\r
241         *t++ = game + '0';\r
242         for (s = "."EXTENSION;*s;)\r
243                 *t++ = *s++;\r
244         *t = '\0';\r
245 \r
246         return(filename);\r
247 }\r
248 \r
249 ///////////////////////////////////////////////////////////////////////////\r
250 //\r
251 //      US_SetLoadSaveHooks() - Sets the routines that the User Mgr calls after\r
252 //              reading or writing the save game headers\r
253 //\r
254 ///////////////////////////////////////////////////////////////////////////\r
255 void\r
256 US_SetLoadSaveHooks(boolean (*load)(int),boolean (*save)(int),void (*reset)(void))\r
257 {\r
258         USL_LoadGame = load;\r
259         USL_SaveGame = save;\r
260         USL_ResetGame = reset;\r
261 }\r
262 \r
263 ///////////////////////////////////////////////////////////////////////////\r
264 //\r
265 //      USL_ReadConfig() - Reads the configuration file, if present, and sets\r
266 //              things up accordingly. If it's not present, uses defaults. This file\r
267 //              includes the high scores.\r
268 //\r
269 ///////////////////////////////////////////////////////////////////////////\r
270 static void\r
271 USL_ReadConfig(void)\r
272 {\r
273         boolean         gotit;\r
274         int                     file;\r
275         SDMode          sd;\r
276         SMMode          sm;\r
277         ControlType     ctl;\r
278 \r
279         if ((file = open("CONFIG."EXTENSION,O_BINARY | O_RDONLY)) != -1)\r
280         {\r
281                 read(file,Scores,sizeof(HighScore) * MaxScores);\r
282                 read(file,&sd,sizeof(sd));\r
283                 read(file,&sm,sizeof(sm));\r
284                 read(file,&ctl,sizeof(ctl));\r
285                 read(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));\r
286                 close(file);\r
287 \r
288                 HighScoresDirty = false;\r
289                 gotit = true;\r
290         }\r
291         else\r
292         {\r
293                 sd = sdm_Off;\r
294                 sm = smm_Off;\r
295                 ctl = ctrl_Keyboard;\r
296 \r
297                 gotit = false;\r
298                 HighScoresDirty = true;\r
299         }\r
300 \r
301         SD_Default(gotit,sd,sm);\r
302         IN_Default(gotit,ctl);\r
303 }\r
304 \r
305 ///////////////////////////////////////////////////////////////////////////\r
306 //\r
307 //      USL_WriteConfig() - Writes out the current configuration, including the\r
308 //              high scores.\r
309 //\r
310 ///////////////////////////////////////////////////////////////////////////\r
311 static void\r
312 USL_WriteConfig(void)\r
313 {\r
314         int     file;\r
315 \r
316         file = open("CONFIG."EXTENSION,O_CREAT | O_BINARY | O_WRONLY,\r
317                                 S_IREAD | S_IWRITE | S_IFREG);\r
318         if (file != -1)\r
319         {\r
320                 write(file,Scores,sizeof(HighScore) * MaxScores);\r
321                 write(file,&SoundMode,sizeof(SoundMode));\r
322                 write(file,&MusicMode,sizeof(MusicMode));\r
323                 write(file,&(Controls[0]),sizeof(Controls[0]));\r
324                 write(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));\r
325                 close(file);\r
326         }\r
327 }\r
328 \r
329 ///////////////////////////////////////////////////////////////////////////\r
330 //\r
331 //      USL_CheckSavedGames() - Checks to see which saved games are present\r
332 //              & valid\r
333 //\r
334 ///////////////////////////////////////////////////////////////////////////\r
335 static void\r
336 USL_CheckSavedGames(void)\r
337 {\r
338         boolean         ok;\r
339         char            *filename;\r
340         word            i;\r
341         int                     file;\r
342         SaveGame        *game;\r
343 \r
344         USL_SaveGame = 0;\r
345         USL_LoadGame = 0;\r
346 \r
347         for (i = 0,game = Games;i < MaxSaveGames;i++,game++)\r
348         {\r
349                 filename = USL_GiveSaveName(i);\r
350                 ok = false;\r
351                 if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
352                 {\r
353                         if\r
354                         (\r
355                                 (read(file,game,sizeof(*game)) == sizeof(*game))\r
356                         &&      (!strcmp(game->signature,EXTENSION))\r
357                         )\r
358                                 ok = true;\r
359 \r
360                         close(file);\r
361                 }\r
362 \r
363                 if (ok)\r
364                         game->present = true;\r
365                 else\r
366                 {\r
367                         strcpy(game->signature,EXTENSION);\r
368                         game->present = false;\r
369                         strcpy(game->name,"Empty");\r
370                 }\r
371         }\r
372 }\r
373 \r
374 ///////////////////////////////////////////////////////////////////////////\r
375 //\r
376 //      US_Startup() - Starts the User Mgr\r
377 //\r
378 ///////////////////////////////////////////////////////////////////////////\r
379 void\r
380 US_Startup(void)\r
381 {\r
382         if (US_Started)\r
383                 return;\r
384 \r
385         harderr(USL_HardError); // Install the fatal error handler\r
386 \r
387         US_InitRndT(true);              // Initialize the random number generator\r
388 \r
389         USL_ReadConfig();               // Read config file\r
390 \r
391         US_Started = true;\r
392 }\r
393 \r
394 ///////////////////////////////////////////////////////////////////////////\r
395 //\r
396 //      US_Setup() - Does the disk access part of the User Mgr's startup\r
397 //\r
398 ///////////////////////////////////////////////////////////////////////////\r
399 void\r
400 US_Setup(void)\r
401 {\r
402         USL_CheckSavedGames();  // Check which saved games are present\r
403 }\r
404 \r
405 ///////////////////////////////////////////////////////////////////////////\r
406 //\r
407 //      US_Shutdown() - Shuts down the User Mgr\r
408 //\r
409 ///////////////////////////////////////////////////////////////////////////\r
410 void\r
411 US_Shutdown(void)\r
412 {\r
413         if (!US_Started)\r
414                 return;\r
415 \r
416         if (!abortprogram)\r
417                 USL_WriteConfig();\r
418 \r
419         US_Started = false;\r
420 }\r
421 \r
422 ///////////////////////////////////////////////////////////////////////////\r
423 //\r
424 //      US_CheckParm() - checks to see if a string matches one of a set of\r
425 //              strings. The check is case insensitive. The routine returns the\r
426 //              index of the string that matched, or -1 if no matches were found\r
427 //\r
428 ///////////////////////////////////////////////////////////////////////////\r
429 int\r
430 US_CheckParm(char *parm,char **strings)\r
431 {\r
432         char    cp,cs,\r
433                         *p,*s;\r
434         int             i;\r
435 \r
436         while (!isalpha(*parm)) // Skip non-alphas\r
437                 parm++;\r
438 \r
439         for (i = 0;*strings && **strings;i++)\r
440         {\r
441                 for (s = *strings++,p = parm,cs = cp = 0;cs == cp;)\r
442                 {\r
443                         cs = *s++;\r
444                         if (!cs)\r
445                                 return(i);\r
446                         cp = *p++;\r
447 \r
448                         if (isupper(cs))\r
449                                 cs = tolower(cs);\r
450                         if (isupper(cp))\r
451                                 cp = tolower(cp);\r
452                 }\r
453         }\r
454         return(-1);\r
455 }\r
456 \r
457 ///////////////////////////////////////////////////////////////////////////\r
458 //\r
459 //      USL_ScreenDraw() - Draws a chunk of the text screen (called only by\r
460 //              US_TextScreen())\r
461 //\r
462 ///////////////////////////////////////////////////////////////////////////\r
463 static void\r
464 USL_ScreenDraw(word x,word y,char *s,byte attr)\r
465 {\r
466         byte    far *screen;\r
467 \r
468         screen = MK_FP(0xb800,(x * 2) + (y * 80 * 2));\r
469         while (*s)\r
470         {\r
471                 *screen++ = *s++;\r
472                 *screen++ = attr;\r
473         }\r
474 }\r
475 \r
476 ///////////////////////////////////////////////////////////////////////////\r
477 //\r
478 //      USL_ClearTextScreen() - Makes sure the screen is in text mode, clears it,\r
479 //              and moves the cursor to the leftmost column of the bottom line\r
480 //\r
481 ///////////////////////////////////////////////////////////////////////////\r
482 static void\r
483 USL_ClearTextScreen(void)\r
484 {\r
485         // Set to 80x25 color text mode\r
486         _AL = 3;                                // Mode 3\r
487         _AH = 0x00;\r
488         geninterrupt(0x10);\r
489 \r
490         // Use BIOS to move the cursor to the bottom of the screen\r
491         _AH = 0x0f;\r
492         geninterrupt(0x10);             // Get current video mode into _BH\r
493         _DL = 0;                                // Lefthand side of the screen\r
494         _DH = 24;                               // Bottom row\r
495         _AH = 0x02;\r
496         geninterrupt(0x10);\r
497 }\r
498 \r
499 ///////////////////////////////////////////////////////////////////////////\r
500 //\r
501 //      US_TextScreen() - Puts up the startup text screen\r
502 //      Note: These are the only User Manager functions that can be safely called\r
503 //              before the User Mgr has been started up\r
504 //\r
505 ///////////////////////////////////////////////////////////////////////////\r
506 void\r
507 US_TextScreen(void)\r
508 {\r
509                 word    i,n,\r
510                                 sx,sy;\r
511 extern  char    far introscn;\r
512 \r
513         USL_ClearTextScreen();\r
514 \r
515         _fmemcpy(MK_FP(0xb800,0),7 + &introscn,80 * 25 * 2);\r
516 \r
517         // Check for TED launching here\r
518         for (i = 1;i < _argc;i++)\r
519         {\r
520                 n = US_CheckParm(_argv[i],ParmStrings);\r
521                 if (n == 0)\r
522                 {\r
523                         tedlevelnum = atoi(_argv[i + 1]);\r
524                         if (tedlevelnum >= 0)\r
525                         {\r
526                                 tedlevel = true;\r
527                                 return;\r
528                         }\r
529                         else\r
530                                 break;\r
531                 }\r
532                 else if (n == 1)\r
533                 {\r
534                         NoWait = true;\r
535                         return;\r
536                 }\r
537         }\r
538 }\r
539 \r
540 ///////////////////////////////////////////////////////////////////////////\r
541 //\r
542 //      USL_Show() - Changes the appearance of one of the fields on the text\r
543 //              screen. Possibly adds a checkmark in front of it and highlights it\r
544 //\r
545 ///////////////////////////////////////////////////////////////////////////\r
546 static void\r
547 USL_Show(word x,word y,word w,boolean show,boolean hilight)\r
548 {\r
549         byte    far *screen;\r
550 \r
551         screen = MK_FP(0xb800,((x - 1) * 2) + (y * 80 * 2));\r
552         *screen++ = show? 251 : ' ';    // Checkmark char or space\r
553         *screen = 0x48;\r
554         if (show && hilight)\r
555         {\r
556                 for (w++;w--;screen += 2)\r
557                         *screen = 0x4f;\r
558         }\r
559 }\r
560 \r
561 ///////////////////////////////////////////////////////////////////////////\r
562 //\r
563 //      USL_ShowMem() - Right justifies a longword in one of the memory fields on\r
564 //              the text screen\r
565 //\r
566 ///////////////////////////////////////////////////////////////////////////\r
567 static void\r
568 USL_ShowMem(word x,word y,long mem)\r
569 {\r
570         char    buf[16];\r
571         word    i;\r
572 \r
573         for (i = strlen(ltoa(mem,buf,10));i < 5;i++)\r
574                 USL_ScreenDraw(x++,y," ",0x48);\r
575         USL_ScreenDraw(x,y,buf,0x48);\r
576 }\r
577 \r
578 ///////////////////////////////////////////////////////////////////////////\r
579 //\r
580 //      US_UpdateTextScreen() - Called after the ID libraries are started up.\r
581 //              Displays what hardware is present.\r
582 //\r
583 ///////////////////////////////////////////////////////////////////////////\r
584 void\r
585 US_UpdateTextScreen(void)\r
586 {\r
587         boolean         b;\r
588         byte            far *screen;\r
589         word            i;\r
590         longword        totalmem;\r
591 \r
592         // Show video card info\r
593         b = (grmode == CGAGR);\r
594         USL_Show(21,7,4,(videocard >= CGAcard) && (videocard <= VGAcard),b);\r
595         b = (grmode == EGAGR);\r
596         USL_Show(21,8,4,(videocard >= EGAcard) && (videocard <= VGAcard),b);\r
597         b = (grmode == VGAGR);\r
598         USL_Show(21,9,4,videocard == VGAcard,b);\r
599         if (compatability)\r
600                 USL_ScreenDraw(5,10,"SVGA Compatibility Mode Enabled.",0x4f);\r
601 \r
602         // Show input device info\r
603         USL_Show(60,7,8,true,true);\r
604         USL_Show(60,8,11,JoysPresent[0],true);\r
605         USL_Show(60,9,11,JoysPresent[1],true);\r
606         USL_Show(60,10,5,MousePresent,true);\r
607 \r
608         // Show sound hardware info\r
609         USL_Show(21,14,11,true,SoundMode == sdm_PC);\r
610         b = (SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib);\r
611         USL_Show(21,15,5,AdLibPresent && !SoundBlasterPresent,\r
612                                 b && !SoundBlasterPresent);\r
613         USL_Show(21,16,13,SoundBlasterPresent,\r
614                         SoundBlasterPresent && (b || (SoundMode == sdm_SoundBlaster)));\r
615         USL_Show(21,17,13,SoundSourcePresent,SoundMode == sdm_SoundSource);\r
616 \r
617         // Show memory available/used\r
618         USL_ShowMem(63,15,mminfo.mainmem / 1024);\r
619         USL_Show(53,15,23,true,true);\r
620         USL_ShowMem(63,16,mminfo.EMSmem / 1024);\r
621         USL_Show(53,16,23,mminfo.EMSmem? true : false,true);\r
622         USL_ShowMem(63,17,mminfo.XMSmem / 1024);\r
623         USL_Show(53,17,23,mminfo.XMSmem? true : false,true);\r
624         totalmem = mminfo.mainmem + mminfo.EMSmem + mminfo.XMSmem;\r
625         USL_ShowMem(63,18,totalmem / 1024);\r
626         screen = MK_FP(0xb800,1 + (((63 - 1) * 2) + (18 * 80 * 2)));\r
627         for (i = 0;i < 13;i++,screen += 2)\r
628                 *screen = 0x4f;\r
629 \r
630         // Change Initializing... to Loading...\r
631         USL_ScreenDraw(27,22,"  Loading...   ",0x9c);\r
632 }\r
633 \r
634 ///////////////////////////////////////////////////////////////////////////\r
635 //\r
636 //      US_FinishTextScreen() - After the main program has finished its initial\r
637 //              loading, this routine waits for a keypress and then clears the screen\r
638 //\r
639 ///////////////////////////////////////////////////////////////////////////\r
640 void\r
641 US_FinishTextScreen(void)\r
642 {\r
643         // Change Loading... to Press a Key\r
644         USL_ScreenDraw(29,22," Ready - Press a Key     ",0x9a);\r
645 \r
646         if (!(tedlevel || NoWait))\r
647         {\r
648                 IN_ClearKeysDown();\r
649                 IN_Ack();\r
650         }\r
651         IN_ClearKeysDown();\r
652 \r
653         USL_ClearTextScreen();\r
654 }\r
655 \r
656 //      Window/Printing routines\r
657 \r
658 ///////////////////////////////////////////////////////////////////////////\r
659 //\r
660 //      US_SetPrintRoutines() - Sets the routines used to measure and print\r
661 //              from within the User Mgr. Primarily provided to allow switching\r
662 //              between masked and non-masked fonts\r
663 //\r
664 ///////////////////////////////////////////////////////////////////////////\r
665 void\r
666 US_SetPrintRoutines(void (*measure)(char far *,word *,word *),void (*print)(char far *))\r
667 {\r
668         USL_MeasureString = measure;\r
669         USL_DrawString = print;\r
670 }\r
671 \r
672 ///////////////////////////////////////////////////////////////////////////\r
673 //\r
674 //      US_Print() - Prints a string in the current window. Newlines are\r
675 //              supported.\r
676 //\r
677 ///////////////////////////////////////////////////////////////////////////\r
678 void\r
679 US_Print(char *s)\r
680 {\r
681         char    c,*se;\r
682         word    w,h;\r
683 \r
684         while (*s)\r
685         {\r
686                 se = s;\r
687                 while ((c = *se) && (c != '\n'))\r
688                         se++;\r
689                 *se = '\0';\r
690 \r
691                 USL_MeasureString(s,&w,&h);\r
692                 px = PrintX;\r
693                 py = PrintY;\r
694                 USL_DrawString(s);\r
695 \r
696                 s = se;\r
697                 if (c)\r
698                 {\r
699                         *se = c;\r
700                         s++;\r
701 \r
702                         PrintX = WindowX;\r
703                         PrintY += h;\r
704                 }\r
705                 else\r
706                         PrintX += w;\r
707         }\r
708 }\r
709 \r
710 ///////////////////////////////////////////////////////////////////////////\r
711 //\r
712 //      US_PrintUnsigned() - Prints an unsigned long\r
713 //\r
714 ///////////////////////////////////////////////////////////////////////////\r
715 void\r
716 US_PrintUnsigned(longword n)\r
717 {\r
718         char    buffer[32];\r
719 \r
720         US_Print(ultoa(n,buffer,10));\r
721 }\r
722 \r
723 ///////////////////////////////////////////////////////////////////////////\r
724 //\r
725 //      US_PrintSigned() - Prints a signed long\r
726 //\r
727 ///////////////////////////////////////////////////////////////////////////\r
728 void\r
729 US_PrintSigned(long n)\r
730 {\r
731         char    buffer[32];\r
732 \r
733         US_Print(ltoa(n,buffer,10));\r
734 }\r
735 \r
736 ///////////////////////////////////////////////////////////////////////////\r
737 //\r
738 //      USL_PrintInCenter() - Prints a string in the center of the given rect\r
739 //\r
740 ///////////////////////////////////////////////////////////////////////////\r
741 static void\r
742 USL_PrintInCenter(char *s,Rect r)\r
743 {\r
744         word    w,h,\r
745                         rw,rh;\r
746 \r
747         USL_MeasureString(s,&w,&h);\r
748         rw = r.lr.x - r.ul.x;\r
749         rh = r.lr.y - r.ul.y;\r
750 \r
751         px = r.ul.x + ((rw - w) / 2);\r
752         py = r.ul.y + ((rh - h) / 2);\r
753         USL_DrawString(s);\r
754 }\r
755 \r
756 ///////////////////////////////////////////////////////////////////////////\r
757 //\r
758 //      US_PrintCentered() - Prints a string centered in the current window.\r
759 //\r
760 ///////////////////////////////////////////////////////////////////////////\r
761 void\r
762 US_PrintCentered(char *s)\r
763 {\r
764         Rect    r;\r
765 \r
766         r.ul.x = WindowX;\r
767         r.ul.y = WindowY;\r
768         r.lr.x = r.ul.x + WindowW;\r
769         r.lr.y = r.ul.y + WindowH;\r
770 \r
771         USL_PrintInCenter(s,r);\r
772 }\r
773 \r
774 ///////////////////////////////////////////////////////////////////////////\r
775 //\r
776 //      US_CPrintLine() - Prints a string centered on the current line and\r
777 //              advances to the next line. Newlines are not supported.\r
778 //\r
779 ///////////////////////////////////////////////////////////////////////////\r
780 void\r
781 US_CPrintLine(char *s)\r
782 {\r
783         word    w,h;\r
784 \r
785         USL_MeasureString(s,&w,&h);\r
786 \r
787         if (w > WindowW)\r
788                 Quit("US_CPrintLine() - String exceeds width");\r
789         px = WindowX + ((WindowW - w) / 2);\r
790         py = PrintY;\r
791         USL_DrawString(s);\r
792         PrintY += h;\r
793 }\r
794 \r
795 ///////////////////////////////////////////////////////////////////////////\r
796 //\r
797 //      US_CPrint() - Prints a string in the current window. Newlines are\r
798 //              supported.\r
799 //\r
800 ///////////////////////////////////////////////////////////////////////////\r
801 void\r
802 US_CPrint(char *s)\r
803 {\r
804         char    c,*se;\r
805         word    w,h;\r
806 \r
807         while (*s)\r
808         {\r
809                 se = s;\r
810                 while ((c = *se) && (c != '\n'))\r
811                         se++;\r
812                 *se = '\0';\r
813 \r
814                 US_CPrintLine(s);\r
815 \r
816                 s = se;\r
817                 if (c)\r
818                 {\r
819                         *se = c;\r
820                         s++;\r
821                 }\r
822         }\r
823 }\r
824 \r
825 ///////////////////////////////////////////////////////////////////////////\r
826 //\r
827 //      US_ClearWindow() - Clears the current window to white and homes the\r
828 //              cursor\r
829 //\r
830 ///////////////////////////////////////////////////////////////////////////\r
831 void\r
832 US_ClearWindow(void)\r
833 {\r
834         VWB_Bar(WindowX,WindowY,WindowW,WindowH,WHITE);\r
835         PrintX = WindowX;\r
836         PrintY = WindowY;\r
837 }\r
838 \r
839 ///////////////////////////////////////////////////////////////////////////\r
840 //\r
841 //      US_DrawWindow() - Draws a frame and sets the current window parms\r
842 //\r
843 ///////////////////////////////////////////////////////////////////////////\r
844 void\r
845 US_DrawWindow(word x,word y,word w,word h)\r
846 {\r
847         word    i,\r
848                         sx,sy,sw,sh;\r
849 \r
850         WindowX = x * 8;\r
851         WindowY = y * 8;\r
852         WindowW = w * 8;\r
853         WindowH = h * 8;\r
854 \r
855         PrintX = WindowX;\r
856         PrintY = WindowY;\r
857 \r
858         sx = (x - 1) * 8;\r
859         sy = (y - 1) * 8;\r
860         sw = (w + 1) * 8;\r
861         sh = (h + 1) * 8;\r
862 \r
863         US_ClearWindow();\r
864 \r
865         VWB_DrawTile8M(sx,sy,0),VWB_DrawTile8M(sx,sy + sh,6);\r
866         for (i = sx + 8;i <= sx + sw - 8;i += 8)\r
867                 VWB_DrawTile8M(i,sy,1),VWB_DrawTile8M(i,sy + sh,7);\r
868         VWB_DrawTile8M(i,sy,2),VWB_DrawTile8M(i,sy + sh,8);\r
869 \r
870         for (i = sy + 8;i <= sy + sh - 8;i += 8)\r
871                 VWB_DrawTile8M(sx,i,3),VWB_DrawTile8M(sx + sw,i,5);\r
872 }\r
873 \r
874 ///////////////////////////////////////////////////////////////////////////\r
875 //\r
876 //      US_CenterWindow() - Generates a window of a given width & height in the\r
877 //              middle of the screen\r
878 //\r
879 ///////////////////////////////////////////////////////////////////////////\r
880 void\r
881 US_CenterWindow(word w,word h)\r
882 {\r
883         US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);\r
884 }\r
885 \r
886 ///////////////////////////////////////////////////////////////////////////\r
887 //\r
888 //      US_CenterSaveWindow() - Generates a window of a given width & height in\r
889 //              the middle of the screen, saving the background\r
890 //\r
891 ///////////////////////////////////////////////////////////////////////////\r
892 void\r
893 US_CenterSaveWindow(word w,word h,memptr *save)\r
894 {\r
895         word    x,y,\r
896                         screen;\r
897 \r
898         x = ((MaxX / 8) - w) / 2;\r
899         y = ((MaxY / 8) - h) / 2;\r
900         MM_GetPtr(save,(w * h) * CHARWIDTH);\r
901         screen = bufferofs + panadjust + ylookup[y] + (x * CHARWIDTH);\r
902         VW_ScreenToMem(screen,*save,w * CHARWIDTH,h);\r
903         US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);\r
904 }\r
905 \r
906 ///////////////////////////////////////////////////////////////////////////\r
907 //\r
908 //      US_RestoreSaveWindow() - Restores the background of the size of the\r
909 //              current window from the memory specified by save\r
910 //\r
911 ///////////////////////////////////////////////////////////////////////////\r
912 void\r
913 US_RestoreSaveWindow(memptr *save)\r
914 {\r
915         word    screen;\r
916 \r
917         screen = bufferofs + panadjust + ylookup[WindowY] + (WindowX * CHARWIDTH);\r
918         VW_MemToScreen(*save,screen,WindowW * CHARWIDTH,WindowH);\r
919         MM_FreePtr(save);\r
920 }\r
921 \r
922 ///////////////////////////////////////////////////////////////////////////\r
923 //\r
924 //      US_SaveWindow() - Saves the current window parms into a record for\r
925 //              later restoration\r
926 //\r
927 ///////////////////////////////////////////////////////////////////////////\r
928 void\r
929 US_SaveWindow(WindowRec *win)\r
930 {\r
931         win->x = WindowX;\r
932         win->y = WindowY;\r
933         win->w = WindowW;\r
934         win->h = WindowH;\r
935 \r
936         win->px = PrintX;\r
937         win->py = PrintY;\r
938 }\r
939 \r
940 ///////////////////////////////////////////////////////////////////////////\r
941 //\r
942 //      US_RestoreWindow() - Sets the current window parms to those held in the\r
943 //              record\r
944 //\r
945 ///////////////////////////////////////////////////////////////////////////\r
946 void\r
947 US_RestoreWindow(WindowRec *win)\r
948 {\r
949         WindowX = win->x;\r
950         WindowY = win->y;\r
951         WindowW = win->w;\r
952         WindowH = win->h;\r
953 \r
954         PrintX = win->px;\r
955         PrintY = win->py;\r
956 }\r
957 \r
958 //      Cursor routines\r
959 \r
960 ///////////////////////////////////////////////////////////////////////////\r
961 //\r
962 //      US_StartCursor() - Sets up the cursor for User Mgr use\r
963 //\r
964 ///////////////////////////////////////////////////////////////////////////\r
965 void\r
966 US_StartCursor(void)\r
967 {\r
968         CursorInfo      info;\r
969 \r
970         VW_SetCursor(CURSORARROWSPR);\r
971         CursorX = MaxX / 2;\r
972         CursorY = MaxY / 2;\r
973         VW_MoveCursor(CursorX,CursorY);\r
974         VW_ShowCursor();\r
975 \r
976         IN_ReadCursor(&info);   // Dispose of any accumulated movement\r
977 }\r
978 \r
979 ///////////////////////////////////////////////////////////////////////////\r
980 //\r
981 //      US_ShutCursor() - Cleans up after US_StartCursor()\r
982 //\r
983 ///////////////////////////////////////////////////////////////////////////\r
984 void\r
985 US_ShutCursor(void)\r
986 {\r
987         VW_HideCursor();\r
988 }\r
989 \r
990 ///////////////////////////////////////////////////////////////////////////\r
991 //\r
992 //      US_UpdateCursor() - Gets the new cursor position & button states from\r
993 //              the Input Mgr and tells the View Mgr where the cursor is\r
994 //\r
995 ///////////////////////////////////////////////////////////////////////////\r
996 boolean\r
997 US_UpdateCursor(void)\r
998 {\r
999         CursorInfo      info;\r
1000 \r
1001         IN_ReadCursor(&info);\r
1002         if (info.x || info.y || CursorBad)\r
1003         {\r
1004                 CursorX += info.x;\r
1005                 if (CursorX >= MaxX)\r
1006                         CursorX = MaxX - 1;\r
1007                 else if (CursorX < 0)\r
1008                         CursorX = 0;\r
1009 \r
1010                 CursorY += info.y;\r
1011                 if (CursorY >= MaxY)\r
1012                         CursorY = MaxY - 1;\r
1013                 else if (CursorY < 0)\r
1014                         CursorY = 0;\r
1015 \r
1016                 VW_MoveCursor(CursorX,CursorY);\r
1017                 CursorBad = false;\r
1018         }\r
1019         Button0 = info.button0;\r
1020         Button1 = info.button1;\r
1021         return(Button0 || Button1);\r
1022 }\r
1023 \r
1024 //      Input routines\r
1025 \r
1026 ///////////////////////////////////////////////////////////////////////////\r
1027 //\r
1028 //      USL_XORICursor() - XORs the I-bar text cursor. Used by US_LineInput()\r
1029 //\r
1030 ///////////////////////////////////////////////////////////////////////////\r
1031 static void\r
1032 USL_XORICursor(int x,int y,char *s,word cursor)\r
1033 {\r
1034         char    buf[MaxString];\r
1035         word    w,h;\r
1036 \r
1037         strcpy(buf,s);\r
1038         buf[cursor] = '\0';\r
1039         USL_MeasureString(buf,&w,&h);\r
1040 \r
1041         px = x + w - 1;\r
1042         py = y;\r
1043         USL_DrawString("\x80");\r
1044 }\r
1045 \r
1046 ///////////////////////////////////////////////////////////////////////////\r
1047 //\r
1048 //      US_LineInput() - Gets a line of user input at (x,y), the string defaults\r
1049 //              to whatever is pointed at by def. Input is restricted to maxchars\r
1050 //              chars or maxwidth pixels wide. If the user hits escape (and escok is\r
1051 //              true), nothing is copied into buf, and false is returned. If the\r
1052 //              user hits return, the current string is copied into buf, and true is\r
1053 //              returned\r
1054 //\r
1055 ///////////////////////////////////////////////////////////////////////////\r
1056 boolean\r
1057 US_LineInput(int x,int y,char *buf,char *def,boolean escok,\r
1058                                 int maxchars,int maxwidth)\r
1059 {\r
1060         boolean         redraw,\r
1061                                 cursorvis,cursormoved,\r
1062                                 done,result;\r
1063         ScanCode        sc;\r
1064         char            c,\r
1065                                 s[MaxString],olds[MaxString];\r
1066         word            i,\r
1067                                 cursor,\r
1068                                 w,h,\r
1069                                 len;\r
1070         longword        lasttime;\r
1071 \r
1072         VW_HideCursor();\r
1073 \r
1074         if (def)\r
1075                 strcpy(s,def);\r
1076         else\r
1077                 *s = '\0';\r
1078         *olds = '\0';\r
1079         cursor = strlen(s);\r
1080         cursormoved = redraw = true;\r
1081 \r
1082         cursorvis = done = false;\r
1083         lasttime = TimeCount;\r
1084         LastASCII = key_None;\r
1085         LastScan = sc_None;\r
1086 \r
1087         while (!done)\r
1088         {\r
1089                 if (cursorvis)\r
1090                         USL_XORICursor(x,y,s,cursor);\r
1091 \r
1092         asm     pushf\r
1093         asm     cli\r
1094 \r
1095                 sc = LastScan;\r
1096                 LastScan = sc_None;\r
1097                 c = LastASCII;\r
1098                 LastASCII = key_None;\r
1099 \r
1100         asm     popf\r
1101 \r
1102                 switch (sc)\r
1103                 {\r
1104                 case sc_LeftArrow:\r
1105                         if (cursor)\r
1106                                 cursor--;\r
1107                         c = key_None;\r
1108                         cursormoved = true;\r
1109                         break;\r
1110                 case sc_RightArrow:\r
1111                         if (s[cursor])\r
1112                                 cursor++;\r
1113                         c = key_None;\r
1114                         cursormoved = true;\r
1115                         break;\r
1116                 case sc_Home:\r
1117                         cursor = 0;\r
1118                         c = key_None;\r
1119                         cursormoved = true;\r
1120                         break;\r
1121                 case sc_End:\r
1122                         cursor = strlen(s);\r
1123                         c = key_None;\r
1124                         cursormoved = true;\r
1125                         break;\r
1126 \r
1127                 case sc_Return:\r
1128                         strcpy(buf,s);\r
1129                         done = true;\r
1130                         result = true;\r
1131                         c = key_None;\r
1132                         break;\r
1133                 case sc_Escape:\r
1134                         if (escok)\r
1135                         {\r
1136                                 done = true;\r
1137                                 result = false;\r
1138                         }\r
1139                         c = key_None;\r
1140                         break;\r
1141 \r
1142                 case sc_BackSpace:\r
1143                         if (cursor)\r
1144                         {\r
1145                                 strcpy(s + cursor - 1,s + cursor);\r
1146                                 cursor--;\r
1147                                 redraw = true;\r
1148                         }\r
1149                         c = key_None;\r
1150                         cursormoved = true;\r
1151                         break;\r
1152                 case sc_Delete:\r
1153                         if (s[cursor])\r
1154                         {\r
1155                                 strcpy(s + cursor,s + cursor + 1);\r
1156                                 redraw = true;\r
1157                         }\r
1158                         c = key_None;\r
1159                         cursormoved = true;\r
1160                         break;\r
1161 \r
1162                 case 0x4c:      // Keypad 5\r
1163                 case sc_UpArrow:\r
1164                 case sc_DownArrow:\r
1165                 case sc_PgUp:\r
1166                 case sc_PgDn:\r
1167                 case sc_Insert:\r
1168                         c = key_None;\r
1169                         break;\r
1170                 }\r
1171 \r
1172                 if (c)\r
1173                 {\r
1174                         len = strlen(s);\r
1175                         USL_MeasureString(s,&w,&h);\r
1176 \r
1177                         if\r
1178                         (\r
1179                                 isprint(c)\r
1180                         &&      (len < MaxString - 1)\r
1181                         &&      ((!maxchars) || (len < maxchars))\r
1182                         &&      ((!maxwidth) || (w < maxwidth))\r
1183                         )\r
1184                         {\r
1185                                 for (i = len + 1;i > cursor;i--)\r
1186                                         s[i] = s[i - 1];\r
1187                                 s[cursor++] = c;\r
1188                                 redraw = true;\r
1189                         }\r
1190                 }\r
1191 \r
1192                 if (redraw)\r
1193                 {\r
1194                         px = x;\r
1195                         py = y;\r
1196                         USL_DrawString(olds);\r
1197                         strcpy(olds,s);\r
1198 \r
1199                         px = x;\r
1200                         py = y;\r
1201                         USL_DrawString(s);\r
1202 \r
1203                         redraw = false;\r
1204                 }\r
1205 \r
1206                 if (cursormoved)\r
1207                 {\r
1208                         cursorvis = false;\r
1209                         lasttime = TimeCount - TickBase;\r
1210 \r
1211                         cursormoved = false;\r
1212                 }\r
1213                 if (TimeCount - lasttime > TickBase / 2)\r
1214                 {\r
1215                         lasttime = TimeCount;\r
1216 \r
1217                         cursorvis ^= true;\r
1218                 }\r
1219                 if (cursorvis)\r
1220                         USL_XORICursor(x,y,s,cursor);\r
1221 \r
1222                 VW_UpdateScreen();\r
1223         }\r
1224 \r
1225         if (cursorvis)\r
1226                 USL_XORICursor(x,y,s,cursor);\r
1227         if (!result)\r
1228         {\r
1229                 px = x;\r
1230                 py = y;\r
1231                 USL_DrawString(olds);\r
1232         }\r
1233         VW_ShowCursor();\r
1234         VW_UpdateScreen();\r
1235 \r
1236         IN_ClearKeysDown();\r
1237         return(result);\r
1238 }\r
1239 \r
1240 //      Control panel routines\r
1241 \r
1242 static  boolean         FlushHelp;\r
1243 static  WindowRec       HelpWindow,BottomWindow;\r
1244 typedef enum\r
1245                 {\r
1246                         uic_Draw,uic_Hit\r
1247                 } UserCall;\r
1248 typedef enum\r
1249                 {\r
1250                         uii_Bad,uii_Button,uii_RadioButton,uii_CheckBox,uii_KeyCap\r
1251                 } UIType;\r
1252 #define ui_Normal       0\r
1253 #define ui_Selected     1\r
1254 #define ui_Disabled     2\r
1255 \r
1256                                         // Prototype the custom routines\r
1257 static  boolean         USL_CtlButtonCustom(UserCall,word,word),\r
1258                                         USL_CtlPButtonCustom(UserCall,word,word),\r
1259                                         USL_CtlPSButtonCustom(UserCall,word,word),\r
1260                                         USL_CtlPRButtonCustom(UserCall,word,word),\r
1261                                         USL_CtlHButtonCustom(UserCall,word,word),\r
1262                                         USL_CtlDButtonCustom(UserCall,word,word),\r
1263                                         USL_CtlDEButtonCustom(UserCall,word,word),\r
1264                                         USL_CtlDLButtonCustom(UserCall,word,word),\r
1265                                         USL_CtlDSButtonCustom(UserCall,word,word),\r
1266                                         USL_CtlSButtonCustom(UserCall,word,word),\r
1267                                         USL_CtlCButtonCustom(UserCall,word,word),\r
1268                                         USL_CtlCKbdButtonCustom(UserCall,word,word),\r
1269                                         USL_CtlCJoyButtonCustom(UserCall,word,word);\r
1270 \r
1271                                         // The structure of a user interaction item\r
1272 typedef struct  {\r
1273                                         Rect            r;                              // The enclosing rectangle\r
1274                                         UIType          type;                   // The type of item\r
1275                                         int                     picup,picdown;  // What to draw when up/down\r
1276                                         char            *help;                  // Floating help string\r
1277                                         ScanCode        key;                    // Key equiv\r
1278                                         word            sel;                    // Interaction flags (ui_XXX)\r
1279                                         boolean         (*custom)(UserCall,word,word);  // Custom routine\r
1280                                         char            *text;                  // Text for some items\r
1281                                 } UserItem;\r
1282 typedef struct  {\r
1283                                         ScanCode        key;\r
1284                                         word            i,n,            // Hit CtlPanels2[i][n]\r
1285                                                                 toi,ton;        // Move to CtlPanels2[toi][ton]\r
1286                                 } HotKey;       // MARK\r
1287 \r
1288 static  ScanCode        *KeyMaps[] =\r
1289                                         {\r
1290                                                 &KbdDefs[0].button0,&KbdDefs[0].button1,\r
1291                                                 &KbdDefs[0].upleft,&KbdDefs[0].up,&KbdDefs[0].upright,\r
1292                                                 &KbdDefs[0].left, &KbdDefs[0].right,\r
1293                                                 &KbdDefs[0].downleft,&KbdDefs[0].down,&KbdDefs[0].downright,\r
1294                                         };\r
1295 \r
1296 // Some macros to make rectangle definition quite a bit less unpleasant\r
1297 #define CtlPanelX       8\r
1298 #define CtlPanelY       4\r
1299 #define CtlPanel2X      (8*8)\r
1300 #define CtlPanel2Y      (2*8)\r
1301 #define CtlPanel3X      (8*8)\r
1302 #define CtlPanel3Y      (7*8)\r
1303 \r
1304 #define CtlPanelR(n)    {       CtlPanelX,CtlPanelY+(32 * (n)),\\r
1305                                                         CtlPanelX+40,CtlPanelY+(32 * (n)) + 32}\r
1306 #define CtlPanel2R(x,y) {       CtlPanel2X+(x)*8,CtlPanel2Y+(y)*8,\\r
1307                                                         CtlPanel2X+32+(x)*8,CtlPanel2Y+24+(y)*8}\r
1308 #define CtlPanel3R(x,y) {       CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\\r
1309                                                         CtlPanel3X+32+(x)*8,CtlPanel3Y+24+(y)*8}\r
1310 static  UserItem        CtlPanels[] =\r
1311                                         {\r
1312 {CtlPanelR(0),uii_RadioButton,CTL_STARTUPPIC,CTL_STARTDNPIC,"Start or Resume a Game",sc_None,ui_Normal,USL_CtlButtonCustom},\r
1313 {CtlPanelR(1),uii_RadioButton,CTL_HELPUPPIC,CTL_HELPDNPIC,"Get Help With Commander Keen",sc_None,ui_Normal,USL_CtlButtonCustom},\r
1314 {CtlPanelR(2),uii_RadioButton,CTL_DISKUPPIC,CTL_DISKDNPIC,"Load / Save / Quit",sc_None,ui_Normal,USL_CtlButtonCustom},\r
1315 {CtlPanelR(3),uii_RadioButton,CTL_CONTROLSUPPIC,CTL_CONTROLSDNPIC,"Choose Controls",sc_C,ui_Normal,USL_CtlButtonCustom},\r
1316 {CtlPanelR(4),uii_RadioButton,CTL_SOUNDUPPIC,CTL_SOUNDDNPIC,"Select Sound Device",sc_F2,ui_Normal,USL_CtlButtonCustom},\r
1317 {CtlPanelR(5),uii_RadioButton,CTL_MUSICUPPIC,CTL_MUSICDNPIC,"Turn Music On / Off",sc_F7,ui_Normal,USL_CtlButtonCustom},\r
1318 {-1,-1,-1,-1,uii_Bad}\r
1319                                         },\r
1320                                         CtlPPanels[] =\r
1321                                         {\r
1322 {CtlPanel2R(10,0),uii_RadioButton,CTL_P_NEWGAMEUPPIC,CTL_P_NEWGAMEDNPIC,"Choose Difficulty for the New Game",sc_F5,ui_Normal,USL_CtlPButtonCustom},\r
1323 {CtlPanel2R(15,0),uii_RadioButton,CTL_P_RESUMEUPPIC,CTL_P_RESUMEDNPIC,"Go Back to Current Game",sc_None,ui_Normal,USL_CtlPButtonCustom},\r
1324 {-1,-1,-1,-1,uii_Bad}\r
1325                                         },\r
1326                                         CtlPSPanels[] =\r
1327                                         {\r
1328 {CtlPanel3R(13,5),uii_Button,CTL_P_MEDUPPIC,CTL_P_MEDDNPIC,"Start New Game in Normal Mode",sc_None,ui_Normal,USL_CtlPSButtonCustom},\r
1329 {CtlPanel3R(8,5),uii_Button,CTL_P_EASYUPPIC,CTL_P_EASYDNPIC,"Start New Game in Easy Mode",sc_None,ui_Normal,USL_CtlPSButtonCustom},\r
1330 {CtlPanel3R(18,5),uii_Button,CTL_P_HARDUPPIC,CTL_P_HARDDNPIC,"Start New Game in Hard Mode",sc_None,ui_Normal,USL_CtlPSButtonCustom},\r
1331 {-1,-1,-1,-1,uii_Bad}\r
1332                                         },\r
1333                                         CtlPRPanels[] =\r
1334                                         {\r
1335 {CtlPanel3R(13,5),uii_Button,CTL_P_GORESUMEUPPIC,CTL_P_GORESUMEDNPIC,"Resume Current Game",sc_None,ui_Normal,USL_CtlPRButtonCustom},\r
1336 {-1,-1,-1,-1,uii_Bad}\r
1337                                         },\r
1338                                         CtlHPanels[] =\r
1339                                         {\r
1340 {CtlPanel2R(8,0),uii_Button,CTL_H_LOSTUPPIC,CTL_H_LOSTDNPIC,"Help Me, I'm Lost!",sc_F1,ui_Normal,USL_CtlHButtonCustom},\r
1341 {CtlPanel2R(13,0),uii_Button,CTL_H_CTRLUPPIC,CTL_H_CTRLDNPIC,"Get Help with Controls",sc_None,ui_Normal,USL_CtlHButtonCustom},\r
1342 {CtlPanel2R(18,0),uii_Button,CTL_H_STORYUPPIC,CTL_H_STORYDNPIC,"Read Story & Game Tips",sc_None,ui_Normal,USL_CtlHButtonCustom},\r
1343 {-1,-1,-1,-1,uii_Bad}\r
1344                                         },\r
1345                                         CtlDPanels[] =\r
1346                                         {\r
1347 {CtlPanel2R(9,0),uii_RadioButton,CTL_D_LSGAMEUPPIC,CTL_D_LSGAMEDNPIC,"Load or Save a Game",sc_F6,ui_Normal,USL_CtlDButtonCustom},\r
1348 {CtlPanel2R(15,0),uii_RadioButton,CTL_D_DOSUPPIC,CTL_D_DOSDNPIC,"Exit to DOS",sc_Q,ui_Normal,USL_CtlDButtonCustom},\r
1349 {-1,-1,-1,-1,uii_Bad}\r
1350                                         },\r
1351                                         CtlDLSPanels[] =\r
1352                                         {\r
1353 #define CtlPanel3LSR(x,y)       {       CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\\r
1354                                                                 CtlPanel3X+32+(x)*8,CtlPanel3Y+16+(y)*8}\r
1355 {CtlPanel3LSR(1,0),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
1356 {CtlPanel3LSR(6,0),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
1357 {CtlPanel3LSR(1,2),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
1358 {CtlPanel3LSR(6,2),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
1359 {CtlPanel3LSR(1,4),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
1360 {CtlPanel3LSR(6,4),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
1361 {CtlPanel3LSR(1,6),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
1362 {CtlPanel3LSR(6,6),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
1363 {CtlPanel3LSR(1,8),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
1364 {CtlPanel3LSR(6,8),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
1365 {CtlPanel3LSR(1,10),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
1366 {CtlPanel3LSR(6,10),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
1367 {CtlPanel3LSR(1,12),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
1368 {CtlPanel3LSR(6,12),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
1369 {-1,-1,-1,-1,uii_Bad}\r
1370                                         },\r
1371                                         CtlDEPanels[] =\r
1372                                         {\r
1373 #define CtlPanel3ER(x,y)        {       CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\\r
1374                                                                 CtlPanel3X+40+(x)*8,CtlPanel3Y+24+(y)*8}\r
1375 {CtlPanel3ER(12,5),uii_Button,CTL_D_EXITUPPIC,CTL_D_EXITDNPIC,"Really Exit to DOS",sc_None,ui_Normal,USL_CtlDEButtonCustom},\r
1376 {-1,-1,-1,-1,uii_Bad}\r
1377                                         },\r
1378                                         CtlCPanels[] =\r
1379                                         {\r
1380 {CtlPanel2R(8,0),uii_RadioButton,CTL_C_KBDUPPIC,CTL_C_KBDDNPIC,"Use / Configure Keyboard",sc_F3,ui_Normal,USL_CtlCButtonCustom},\r
1381 {CtlPanel2R(13,0),uii_RadioButton,CTL_C_JOY1UPPIC,CTL_C_JOY1DNPIC,"Use / Configure Joystick 1",sc_None,ui_Normal,USL_CtlCButtonCustom},\r
1382 {CtlPanel2R(18,0),uii_RadioButton,CTL_C_JOY2UPPIC,CTL_C_JOY2DNPIC,"Use / Configure Joystick 2",sc_None,ui_Normal,USL_CtlCButtonCustom},\r
1383 {-1,-1,-1,-1,uii_Bad}\r
1384                                         },\r
1385 #define CtlPanelKC3R(x,y)       {       CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\\r
1386                                                                 CtlPanel3X+56+(x)*8,CtlPanel3Y+32+(y)*8}\r
1387                                         CtlCKbdPanels[] =\r
1388                                         {\r
1389 {CtlPanelKC3R(1,2),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key for Jumping",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
1390 {CtlPanelKC3R(1,6),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key for Throwing",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
1391 {CtlPanelKC3R(8,0),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Up & Left",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
1392 {CtlPanelKC3R(15,0),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Up",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
1393 {CtlPanelKC3R(22,0),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Up & Right",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
1394 {CtlPanelKC3R(8,4),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Left",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
1395 {CtlPanelKC3R(22,4),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Right",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
1396 {CtlPanelKC3R(8,8),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Down & Left",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
1397 {CtlPanelKC3R(15,8),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Down",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
1398 {CtlPanelKC3R(22,8),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Down & Right",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
1399 {-1,-1,-1,-1,uii_Bad}\r
1400                                         },\r
1401                                         CtlCJoyPanels[] =\r
1402                                         {\r
1403 {CtlPanel3R(13,5),uii_Button,CTL_C_CALIBRATEUPPIC,CTL_C_CALIBRATEDNPIC,"Configure Joystick",sc_None,ui_Normal,USL_CtlCJoyButtonCustom},\r
1404 {-1,-1,-1,-1,uii_Bad}\r
1405                                         },\r
1406                                         CtlSPanels[] =\r
1407                                         {\r
1408 {CtlPanel2R(3,0),uii_RadioButton,CTL_S_NOSNDUPPIC,CTL_S_NOSNDDNPIC,"Turn Sound Off",sc_None,ui_Normal,USL_CtlSButtonCustom},\r
1409 {CtlPanel2R(8,0),uii_RadioButton,CTL_S_PCSNDUPPIC,CTL_S_PCSNDDNPIC,"Use PC Speaker",sc_None,ui_Normal,USL_CtlSButtonCustom},\r
1410 {CtlPanel2R(13,0),uii_RadioButton,CTL_S_ADLIBUPPIC,CTL_S_ADLIBDNPIC,"Use AdLib Sound Effects",sc_None,ui_Normal,USL_CtlSButtonCustom},\r
1411 {CtlPanel2R(18,0),uii_RadioButton,CTL_S_SNDBLUPPIC,CTL_S_SNDBLDNPIC,"Use SoundBlaster Sound Effects",sc_None,ui_Normal,USL_CtlSButtonCustom},\r
1412 {CtlPanel2R(23,0),uii_RadioButton,CTL_S_SNDSRCUPPIC,CTL_S_SNDSRCDNPIC,"Use Sound Source Sound Effects",sc_None,ui_Normal,USL_CtlSButtonCustom},\r
1413 {-1,-1,-1,-1,uii_Bad}\r
1414                                         },\r
1415                                         CtlSSSPanels[] =\r
1416                                         {\r
1417 {CtlPanel3R(7,2),uii_CheckBox,CTL_CHECKUPPIC,CTL_CHECKDNPIC,"Turn Tandy Mode On / Off",sc_None,ui_Normal,0,"Tandy Mode"},\r
1418 {CtlPanel3R(7,6),uii_CheckBox,CTL_CHECKUPPIC,CTL_CHECKDNPIC,"Switch between LPT1 & LPT2",sc_None,ui_Normal,0,"Use LPT2"},\r
1419 {-1,-1,-1,-1,uii_Bad}\r
1420                                         },\r
1421                                         CtlMPanels[] =\r
1422                                         {\r
1423 {CtlPanel2R(9,0),uii_RadioButton,CTL_M_NOMUSUPPIC,CTL_M_NOMUSDNPIC,"Background Music Off"},\r
1424 {CtlPanel2R(15,0),uii_RadioButton,CTL_M_ADLIBUPPIC,CTL_M_ADLIBDNPIC,"Use AdLib/SoundBlaster Music"},\r
1425 {-1,-1,-1,-1,uii_Bad}\r
1426                                         },\r
1427                                         *CtlPanels2[] =\r
1428                                         {\r
1429                                                 CtlPPanels,     // Start\r
1430                                                 CtlHPanels,     // Help\r
1431                                                 CtlDPanels,     // Disk\r
1432                                                 CtlCPanels,     // Controls\r
1433                                                 CtlSPanels,     // Sound\r
1434                                                 CtlMPanels      // Music\r
1435                                         },\r
1436                                         *TheItems[4] = {CtlPanels};\r
1437 static  int                     CtlPanelButton;\r
1438 \r
1439 ///////////////////////////////////////////////////////////////////////////\r
1440 //\r
1441 //      USL_TurnOff() - Goes through a list of UserItems and sets them all to\r
1442 //              the normal state\r
1443 //\r
1444 ///////////////////////////////////////////////////////////////////////////\r
1445 static void\r
1446 USL_TurnOff(UserItem *ip)\r
1447 {\r
1448         while (ip->type != uii_Bad)\r
1449         {\r
1450                 ip->sel = ui_Normal;\r
1451                 ip++;\r
1452         }\r
1453 }\r
1454 \r
1455 ///////////////////////////////////////////////////////////////////////////\r
1456 //\r
1457 //      USL_FindDown() - Finds which UserItem, if any, is selected in the given\r
1458 //              list\r
1459 //\r
1460 ///////////////////////////////////////////////////////////////////////////\r
1461 static int\r
1462 USL_FindDown(UserItem *ip)\r
1463 {\r
1464         int     i;\r
1465 \r
1466         for (i = 0;ip->type != uii_Bad;i++,ip++)\r
1467                 if (ip->sel & ui_Selected)\r
1468                         return(i);\r
1469         return(-1);\r
1470 }\r
1471 \r
1472 ///////////////////////////////////////////////////////////////////////////\r
1473 //\r
1474 //      USL_ShowHelp() - Shows the specified string in the help window\r
1475 //\r
1476 ///////////////////////////////////////////////////////////////////////////\r
1477 static void\r
1478 USL_ShowHelp(char *s)\r
1479 {\r
1480         WindowRec       wr;\r
1481 \r
1482         if (!s)\r
1483                 return;\r
1484 \r
1485         US_SaveWindow(&wr);\r
1486         US_RestoreWindow(&HelpWindow);\r
1487 \r
1488         US_ClearWindow();\r
1489         US_PrintCentered(s);\r
1490 \r
1491         US_RestoreWindow(&wr);\r
1492 }\r
1493 \r
1494 ///////////////////////////////////////////////////////////////////////////\r
1495 //\r
1496 //      USL_HandleError() - Handles telling the user that there's been an error\r
1497 //\r
1498 ///////////////////////////////////////////////////////////////////////////\r
1499 static void\r
1500 USL_HandleError(int num)\r
1501 {\r
1502         char    buf[64];\r
1503 \r
1504         strcpy(buf,"Error: ");\r
1505         if (num < 0)\r
1506                 strcat(buf,"Unknown");\r
1507         else if (num == ENOMEM)\r
1508                 strcat(buf,"Disk is Full");\r
1509         else if (num == EINVFMT)\r
1510                 strcat(buf,"File is Incomplete");\r
1511         else\r
1512                 strcat(buf,sys_errlist[num]);\r
1513 \r
1514         VW_HideCursor();\r
1515 \r
1516         fontcolor = F_SECONDCOLOR;\r
1517         USL_ShowHelp(buf);\r
1518         fontcolor = F_BLACK;\r
1519         VW_UpdateScreen();\r
1520 \r
1521         IN_ClearKeysDown();\r
1522         IN_Ack();\r
1523 \r
1524         VW_ShowCursor();\r
1525         VW_UpdateScreen();\r
1526 }\r
1527 \r
1528 ///////////////////////////////////////////////////////////////////////////\r
1529 //\r
1530 //      USL_DrawItem() - Draws a UserItem. If there's a custom routine, this will\r
1531 //              call it with a uic_Draw command. If the custom routine returns true,\r
1532 //              then the routine handled all of the drawing. If it returns false,\r
1533 //              then this routine does the default drawing.\r
1534 //\r
1535 ///////////////////////////////////////////////////////////////////////////\r
1536 static void\r
1537 USL_DrawItem(word hiti,word hitn)\r
1538 {\r
1539         boolean         handled,centered;\r
1540         char            *text;\r
1541         word            w,h;\r
1542         int                     picup,picdown;\r
1543         Rect            r;\r
1544         UserItem        *ip;\r
1545 \r
1546         ip = &TheItems[hiti][hitn];\r
1547         if (ip->custom)\r
1548                 handled = ip->custom(uic_Draw,hiti,hitn);\r
1549         else\r
1550                 handled = false;\r
1551 \r
1552         if (!handled)\r
1553         {\r
1554                 picup = ip->picup;\r
1555                 picdown = ip->picdown;\r
1556                 switch (ip->type)\r
1557                 {\r
1558                 case uii_CheckBox:\r
1559                         px = ip->r.lr.x + 8;\r
1560                         py = ip->r.ul.y + 8;\r
1561                         text = ip->text;\r
1562                         centered = false;\r
1563                         break;\r
1564                 case uii_KeyCap:\r
1565                         if (!(ip->sel & ui_Selected))\r
1566                         {\r
1567                                 text = ip->text;\r
1568                                 if (text)\r
1569                                 {\r
1570                                         r = ip->r;\r
1571                                         centered = true;\r
1572                                 }\r
1573                         }\r
1574                         else\r
1575                                 text = nil;\r
1576                         break;\r
1577                 default:\r
1578                         text = nil;\r
1579                         break;\r
1580                 }\r
1581 \r
1582                 VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,\r
1583                                                 (ip->sel & ui_Selected)? picdown : picup);\r
1584                 if (text)\r
1585                 {\r
1586                         if (centered)\r
1587                                 USL_PrintInCenter(text,r);\r
1588                         else\r
1589                         {\r
1590                                 USL_MeasureString(text,&w,&h);\r
1591                                 VWB_Bar(px,py,w + 7,h,WHITE);\r
1592                                 USL_DrawString(text);\r
1593                         }\r
1594                 }\r
1595                 if (ip->sel & ui_Disabled)\r
1596                 {\r
1597                         if ((picup == CTL_D_LOADUPPIC) || (picup == CTL_D_SAVEUPPIC))\r
1598                                 VWB_DrawMPic(ip->r.ul.x,ip->r.ul.y,CTL_LSMASKPICM);\r
1599                         else\r
1600                                 VWB_DrawMPic(ip->r.ul.x,ip->r.ul.y,CTL_LITTLEMASKPICM);\r
1601                 }\r
1602         }\r
1603 }\r
1604 \r
1605 ///////////////////////////////////////////////////////////////////////////\r
1606 //\r
1607 //      USL_DoHit() - Handles a hit on a UserItem. If there's a custom routine,\r
1608 //                      it will be called. If it returns true, then don't do anything\r
1609 //                      more. If it returns false, then use the standard behaviour\r
1610 //\r
1611 ///////////////////////////////////////////////////////////////////////////\r
1612 static void\r
1613 USL_DoHit(word hiti,word hitn)\r
1614 {\r
1615         boolean         handled;\r
1616         word            i;\r
1617         UserItem        *ip;\r
1618 \r
1619         ip = &TheItems[hiti][hitn];\r
1620         if (ip->custom)\r
1621                 handled = ip->custom(uic_Hit,hiti,hitn);\r
1622         else\r
1623                 handled = false;\r
1624 \r
1625         if (!handled)\r
1626         {\r
1627                 if (TheItems[hiti][hitn].sel & ui_Disabled)\r
1628                 {\r
1629                         fontcolor = F_SECONDCOLOR;\r
1630                         USL_ShowHelp("This Item is Disabled");\r
1631                         fontcolor = F_BLACK;\r
1632                         return;\r
1633                 }\r
1634 \r
1635                 FlushHelp = true;\r
1636 \r
1637                 switch (ip->type)\r
1638                 {\r
1639                 case uii_Button:\r
1640                         // Must have a custom routine to handle hits - this just redraws\r
1641                         ip->sel ^= ui_Selected;\r
1642                         USL_DrawItem(hiti,hitn);\r
1643                 case uii_CheckBox:\r
1644                         ip->sel ^= ui_Selected;\r
1645                         USL_DrawItem(hiti,hitn);\r
1646                         break;\r
1647                 case uii_RadioButton:\r
1648                         for (i = 0,ip = TheItems[hiti];ip->type != uii_Bad;i++,ip++)\r
1649                         {\r
1650                                 if\r
1651                                 (\r
1652                                         (i != hitn)\r
1653                                 &&      (ip->type == uii_RadioButton)\r
1654                                 &&      (ip->sel & ui_Selected)\r
1655                                 )\r
1656                                 {\r
1657                                         ip->sel &= ~ui_Selected;\r
1658                                         USL_DrawItem(hiti,i);\r
1659                                 }\r
1660                         }\r
1661                         TheItems[hiti][hitn].sel |= ui_Selected;\r
1662                         USL_DrawItem(hiti,hitn);\r
1663                         break;\r
1664                 case uii_KeyCap:\r
1665                         break;\r
1666                 }\r
1667         }\r
1668 }\r
1669 \r
1670 ///////////////////////////////////////////////////////////////////////////\r
1671 //\r
1672 //      USL_IsInRect() - Checks to see if the coordinates given are within any\r
1673 //              of the Rects in the UserItem list. If so, returns true & sets the\r
1674 //              index & number for lookup. If not, returns false.\r
1675 //\r
1676 ///////////////////////////////////////////////////////////////////////////\r
1677 static boolean\r
1678 USL_IsInRect(word x,word y,word *index,word *number)\r
1679 {\r
1680         UserItem        *item,**items;\r
1681 \r
1682         items = TheItems;\r
1683         *index = 0;\r
1684         while (*items)\r
1685         {\r
1686                 item = *items;\r
1687                 *number = 0;\r
1688                 while (item->type != uii_Bad)\r
1689                 {\r
1690                         if\r
1691                         (\r
1692                                 (x >= item->r.ul.x)\r
1693                         &&      (x <  item->r.lr.x)\r
1694                         &&      (y >= item->r.ul.y)\r
1695                         &&      (y <  item->r.lr.y)\r
1696                         )\r
1697                                 return(true);\r
1698                         (*number)++;\r
1699                         item++;\r
1700                 }\r
1701 \r
1702                 (*index)++;\r
1703                 items++;\r
1704         }\r
1705         return(false);\r
1706 }\r
1707 \r
1708 ///////////////////////////////////////////////////////////////////////////\r
1709 //\r
1710 //      USL_TrackItem() - Tracks the given item. If the cursor is inside of the\r
1711 //              item, it's redrawn as down. If the cursor is outside, the item is\r
1712 //              drawn in its original state. Returns true if the button was released\r
1713 //              while the cursor was inside the item, or false if it wasn't.\r
1714 //\r
1715 ///////////////////////////////////////////////////////////////////////////\r
1716 static boolean\r
1717 USL_TrackItem(word hiti,word hitn)\r
1718 {\r
1719         boolean         inside,last;\r
1720         word            ini,inn,\r
1721                                 on,\r
1722                                 sel,othersel;\r
1723         UserItem        *ip,*op;\r
1724 \r
1725         ip = &TheItems[hiti][hitn];\r
1726         sel = ip->sel;\r
1727         if (ip->type == uii_RadioButton)\r
1728         {\r
1729                 inside = false;\r
1730                 for (op = TheItems[hiti],on = 0;op->type != uii_Bad;op++,on++)\r
1731                 {\r
1732                         if (op->sel & ui_Selected)\r
1733                         {\r
1734                                 inside = true;\r
1735                                 break;\r
1736                         }\r
1737                 }\r
1738                 if (!inside)\r
1739                         op = ip;\r
1740                 othersel = op->sel;\r
1741         }\r
1742         else\r
1743                 op = nil;\r
1744 \r
1745         if (ip->sel & ui_Disabled)\r
1746         {\r
1747                 fontcolor = F_SECONDCOLOR;\r
1748                 USL_ShowHelp("This item is disabled");\r
1749                 fontcolor = F_BLACK;\r
1750 \r
1751                 while (US_UpdateCursor())\r
1752                         VW_UpdateScreen();\r
1753 \r
1754                 FlushHelp = true;\r
1755                 return(false);\r
1756         }\r
1757 \r
1758         last = false;\r
1759         do\r
1760         {\r
1761                 USL_IsInRect(CursorX,CursorY,&ini,&inn);\r
1762                 inside = (ini == hiti) && (inn == hitn);\r
1763                 if (inside != last)\r
1764                 {\r
1765                         if (inside)\r
1766                         {\r
1767                                 if (op)\r
1768                                 {\r
1769                                         op->sel &= ~ui_Selected;\r
1770                                         ip->sel |= ui_Selected;\r
1771                                 }\r
1772                                 else\r
1773                                         ip->sel = sel ^ ui_Selected;\r
1774                         }\r
1775                         else\r
1776                         {\r
1777                                 if (op && (op != ip))\r
1778                                 {\r
1779                                         op->sel |= ui_Selected;\r
1780                                         ip->sel &= ~ui_Selected;\r
1781                                 }\r
1782                                 else\r
1783                                         ip->sel = sel;\r
1784                         }\r
1785 \r
1786                         USL_DrawItem(hiti,hitn);\r
1787                         if (op && (op != ip))\r
1788                                 USL_DrawItem(hiti,on);\r
1789 \r
1790                         last = inside;\r
1791                 }\r
1792                 VW_UpdateScreen();\r
1793         } while (US_UpdateCursor());\r
1794 \r
1795         if (op)\r
1796                 op->sel = othersel;\r
1797         ip->sel = sel;\r
1798         if (!inside)\r
1799         {\r
1800                 if (op && (op != ip))\r
1801                         USL_DrawItem(hiti,on);\r
1802                 USL_DrawItem(hiti,hitn);\r
1803                 VW_UpdateScreen();\r
1804         }\r
1805 \r
1806         return(inside);\r
1807 }\r
1808 \r
1809 ///////////////////////////////////////////////////////////////////////////\r
1810 //\r
1811 //      USL_GlideCursor() - Smoothly moves the cursor to the given location\r
1812 //\r
1813 ///////////////////////////////////////////////////////////////////////////\r
1814 static void\r
1815 USL_GlideCursor(long newx,long newy)\r
1816 {\r
1817         word    steps;\r
1818         long    x,y,\r
1819                         dx,dy;\r
1820 \r
1821         if (grmode == CGAGR)\r
1822                 steps = 1;\r
1823         else\r
1824                 steps = 8;\r
1825 \r
1826         x = (long)CursorX << 16;\r
1827         dx = ((newx << 16) - x) / steps;\r
1828         y = (long)CursorY << 16;\r
1829         dy = ((newy << 16) - y) / steps;\r
1830 \r
1831         while ((CursorX != newx) || (CursorY != newy))\r
1832         {\r
1833                 x += dx;\r
1834                 y += dy;\r
1835 \r
1836                 CursorX = x >> 16;\r
1837                 CursorY = y >> 16;\r
1838                 VW_MoveCursor(CursorX,CursorY);\r
1839                 VW_UpdateScreen();\r
1840         }\r
1841         CursorBad = true;\r
1842 }\r
1843 \r
1844 ///////////////////////////////////////////////////////////////////////////\r
1845 //\r
1846 //      USL_FindRect() - Code so ugly you'll puke! Given a Rect and direction,\r
1847 //      this routine will try to find a UserItem to move the cursor to\r
1848 //\r
1849 ///////////////////////////////////////////////////////////////////////////\r
1850 static void\r
1851 USL_FindRect(Rect r,Motion xd,Motion yd)\r
1852 {\r
1853         word            i,i1,i2,i3;\r
1854         Motion          m1,m2;\r
1855         Point           diffs[9],diff,*dp;\r
1856         Rect            *rp,*good,*goods[9];\r
1857         UserItem        *ip,**items;\r
1858 \r
1859         for (m1 = motion_Up,dp = diffs;m1 <= motion_Down;m1++)\r
1860         {\r
1861                 for (m2 = motion_Left;m2 <= motion_Right;m2++,dp++)\r
1862                 {\r
1863                         dp->x = m2 * 1024;\r
1864                         dp->y = m1 * 1024;\r
1865                 }\r
1866         }\r
1867         for (i = 0;i < 9;i++)\r
1868                 goods[i] = nil;\r
1869 \r
1870         // Find out which octants all of the rects (except r) are in\r
1871         for (items = TheItems;*items;items++)\r
1872         {\r
1873                 for (ip = *items;ip->type != uii_Bad;ip++)\r
1874                 {\r
1875                         rp = &ip->r;\r
1876                         diff.x = rp->ul.x - r.ul.x;\r
1877                         diff.y = rp->ul.y - r.ul.y;\r
1878                         if (!(diff.x || diff.y))\r
1879                                 continue;\r
1880 \r
1881                         if      // 1,4,7\r
1882                         (\r
1883                                 ((rp->ul.x >= r.ul.x) && (rp->ul.x < r.lr.x))\r
1884                         ||      ((rp->lr.x > r.ul.x) && (rp->lr.x <= r.lr.x))\r
1885                         )\r
1886                         {\r
1887                                 if (rp->lr.y <= r.ul.y)\r
1888                                 {\r
1889                                         if (!(goods[1] && (diff.y < diffs[1].y)))\r
1890                                         {\r
1891                                                 goods[1] = rp;\r
1892                                                 diffs[1] = diff;\r
1893                                         }\r
1894                                 }\r
1895                                 else if (rp->ul.y >= r.lr.y)\r
1896                                 {\r
1897                                         if (!(goods[7] && (diff.y > diffs[7].y)))\r
1898                                         {\r
1899                                                 goods[7] = rp;\r
1900                                                 diffs[7] = diff;\r
1901                                         }\r
1902                                 }\r
1903                         }\r
1904 \r
1905                         if      // 3,4,5\r
1906                         (\r
1907                                 ((rp->ul.y >= r.ul.y) && (rp->ul.y < r.lr.y))\r
1908                         ||      ((rp->lr.y > r.ul.y) && (rp->lr.y <= r.lr.y))\r
1909                         )\r
1910                         {\r
1911                                 if (rp->lr.x <= r.ul.x)\r
1912                                 {\r
1913                                         if (!(goods[3] && (diff.x < diffs[3].x)))\r
1914                                         {\r
1915                                                 goods[3] = rp;\r
1916                                                 diffs[3] = diff;\r
1917                                         }\r
1918                                 }\r
1919                                 else if (rp->ul.x >= r.lr.x)\r
1920                                 {\r
1921                                         if (!(goods[5] && (diff.x > diffs[5].x)))\r
1922                                         {\r
1923                                                 goods[5] = rp;\r
1924                                                 diffs[5] = diff;\r
1925                                         }\r
1926                                 }\r
1927                         }\r
1928 \r
1929                         if (rp->ul.x < r.ul.x)  // 0,6\r
1930                         {\r
1931                                 if (rp->lr.y <= r.ul.y)\r
1932                                 {\r
1933                                         if\r
1934                                         (\r
1935                                                 (!goods[0])\r
1936                                         ||      (diff.y > diffs[0].y)\r
1937                                         ||      (diff.x > diffs[6].x)\r
1938                                         )\r
1939                                         {\r
1940                                                 goods[0] = rp;\r
1941                                                 diffs[0] = diff;\r
1942                                         }\r
1943                                 }\r
1944                                 else if (rp->ul.y >= r.lr.y)\r
1945                                 {\r
1946                                         if\r
1947                                         (\r
1948                                                 (!goods[6])\r
1949                                         ||      (diff.y < diffs[6].y)\r
1950                                         ||      (diff.x > diffs[6].x)\r
1951                                         )\r
1952                                         {\r
1953                                                 goods[6] = rp;\r
1954                                                 diffs[6] = diff;\r
1955                                         }\r
1956                                 }\r
1957                         }\r
1958 \r
1959                         if (rp->lr.x > r.lr.x)  // 2,8\r
1960                         {\r
1961                                 if (rp->lr.y <= r.ul.y)\r
1962                                 {\r
1963                                         if\r
1964                                         (\r
1965                                                 (!goods[2])\r
1966                                         ||      (diff.y > diffs[2].y)\r
1967                                         ||      (diff.x < diffs[2].x)\r
1968                                         )\r
1969                                         {\r
1970                                                 goods[2] = rp;\r
1971                                                 diffs[2] = diff;\r
1972                                         }\r
1973                                 }\r
1974                                 else if (rp->ul.y >= r.lr.y)\r
1975                                 {\r
1976                                         if\r
1977                                         (\r
1978                                                 (!goods[8])\r
1979                                         ||      (diff.y < diffs[8].y)\r
1980                                         ||      (diff.x < diffs[8].x)\r
1981                                         )\r
1982                                         {\r
1983                                                 goods[8] = rp;\r
1984                                                 diffs[8] = diff;\r
1985                                         }\r
1986                                 }\r
1987                         }\r
1988                 }\r
1989         }\r
1990 \r
1991         switch (yd)\r
1992         {\r
1993         case motion_Up:\r
1994                 i1 = 1,i2 = 0,i3 = 2;\r
1995                 break;\r
1996         case motion_None:\r
1997                 switch (xd)\r
1998                 {\r
1999                 case motion_Left:\r
2000                         i1 = 3,i2 = 0,i3 = 6;\r
2001                         break;\r
2002                 case motion_Right:\r
2003                         i1 = 5,i2 = 8,i3 = 2;\r
2004                         break;\r
2005                 }\r
2006                 break;\r
2007         case motion_Down:\r
2008                 i1 = 7,i2 = 8,i3 = 6;\r
2009                 break;\r
2010         }\r
2011 \r
2012         (\r
2013                 (good = goods[i1])\r
2014         ||      (good = goods[i2])\r
2015         ||      (good = goods[i3])\r
2016         ||      (good = &r)\r
2017         );\r
2018 #if 0\r
2019         CursorX = good->lr.x - 8;\r
2020         CursorY = good->lr.y - 8;\r
2021         CursorBad = true;\r
2022         US_UpdateCursor();\r
2023 #endif\r
2024         USL_GlideCursor(good->lr.x - 8,good->lr.y - 8);\r
2025 }\r
2026 \r
2027 ///////////////////////////////////////////////////////////////////////////\r
2028 //\r
2029 //      USL_CtlButtonCustom() - The custom routine for all of the Control Panel\r
2030 //              (leftmost) buttons. Clears all of the other item lists, clears the\r
2031 //              large area, and draws the line dividing the top and bottom areas.\r
2032 //              Then it sets up and draws the appropriate top row of icons.\r
2033 //\r
2034 ///////////////////////////////////////////////////////////////////////////\r
2035 static boolean\r
2036 USL_CtlButtonCustom(UserCall call,word i,word n)\r
2037 {\r
2038         word            j;\r
2039         UserItem        *ip;\r
2040 \r
2041         if (call != uic_Hit)\r
2042                 return(false);\r
2043 \r
2044         if (n == CtlPanelButton)\r
2045                 return(true);\r
2046 \r
2047         US_ClearWindow();\r
2048         for (j = 8;j < 38;j++)\r
2049         {\r
2050                 VWB_DrawTile8M(j * 8,6 * 8,10);\r
2051                 VWB_DrawTile8M(j * 8,21 * 8,10);\r
2052         }\r
2053         VWB_DrawTile8M(7 * 8,6 * 8,9);\r
2054         VWB_DrawTile8M(38 * 8,6 * 8,11);\r
2055         VWB_DrawTile8M(7 * 8,21 * 8,9);\r
2056         VWB_DrawTile8M(38 * 8,21 * 8,11);\r
2057 \r
2058         for (j = 1;j < 4;j++)\r
2059                 TheItems[j] = nil;\r
2060 \r
2061         // Set to new button\r
2062         CtlPanelButton = n;\r
2063 \r
2064         // Draw new items\r
2065         TheItems[1] = ip = CtlPanels2[CtlPanelButton];\r
2066         j = 0;\r
2067         while (ip && (ip->type != uii_Bad))\r
2068         {\r
2069                 USL_DrawItem(i + 1,j);\r
2070                 if (ip->sel & ui_Selected)\r
2071                         USL_DoHit(i + 1,j);\r
2072                 j++;\r
2073                 ip++;\r
2074         }\r
2075 \r
2076         return(false);\r
2077 }\r
2078 \r
2079 ///////////////////////////////////////////////////////////////////////////\r
2080 //\r
2081 //      USL_CtlCKbdButtonCustom() - The custom routine for the keyboard keycaps.\r
2082 //              This routine gets a scancode and puts it in the appropriate\r
2083 //              KbdDefs[0] member.\r
2084 //\r
2085 ///////////////////////////////////////////////////////////////////////////\r
2086 static boolean\r
2087 USL_CtlCKbdButtonCustom(UserCall call,word i,word n)\r
2088 {\r
2089         boolean         state;\r
2090         word            j;\r
2091         ScanCode        scan;\r
2092         longword        time;\r
2093         UserItem        *ip;\r
2094 \r
2095         if (call != uic_Hit)\r
2096                 return(false);\r
2097 \r
2098         ip = &TheItems[i][n];\r
2099 \r
2100         fontcolor = F_SECONDCOLOR;\r
2101         USL_ShowHelp(ip->help);\r
2102         fontcolor = F_BLACK;\r
2103         VW_HideCursor();\r
2104         VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,ip->picdown);\r
2105         VW_UpdateScreen();\r
2106 \r
2107         LastScan = sc_None;\r
2108         time = TimeCount;\r
2109         state = true;\r
2110         do\r
2111         {\r
2112                 if (TimeCount - time > 35)      // Half-second delays\r
2113                 {\r
2114                         state ^= true;\r
2115                         VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,state? ip->picdown : ip->picup);\r
2116                         VW_UpdateScreen();\r
2117                         time = TimeCount;\r
2118                 }\r
2119                 if (US_UpdateCursor())\r
2120                 {\r
2121                         while (US_UpdateCursor())\r
2122                                 ;\r
2123                         scan = sc_Escape;\r
2124                         break;\r
2125                 }\r
2126 \r
2127                 asm     pushf\r
2128                 asm     cli\r
2129                 if (LastScan == sc_LShift)\r
2130                         LastScan = sc_None;\r
2131                 asm     popf\r
2132         } while (!(scan = LastScan));\r
2133         IN_ClearKey(scan);\r
2134         if (scan != sc_Escape)\r
2135         {\r
2136                 for (j = 0,state = false;j < 10;j++)\r
2137                 {\r
2138                         if (j == n)\r
2139                                 continue;\r
2140                         if (*(KeyMaps[j]) == scan)\r
2141                         {\r
2142                                 state = true;\r
2143                                 break;\r
2144                         }\r
2145                 }\r
2146                 if (state)\r
2147                 {\r
2148                         fontcolor = F_SECONDCOLOR;\r
2149                         USL_ShowHelp("That Key is Already Used!");\r
2150                         fontcolor = F_BLACK;\r
2151                 }\r
2152                 else\r
2153                 {\r
2154                         ip->text = IN_GetScanName(scan);\r
2155                         *(KeyMaps[n]) = scan;\r
2156                         FlushHelp = true;\r
2157                 }\r
2158         }\r
2159 \r
2160         USL_DrawItem(i,n);\r
2161         VW_ShowCursor();\r
2162         VW_UpdateScreen();\r
2163 \r
2164         return(true);\r
2165 }\r
2166 \r
2167 ///////////////////////////////////////////////////////////////////////////\r
2168 //\r
2169 //      USL_CtlCJoyButtonCustom() - The custom button routine for joystick\r
2170 //              calibration\r
2171 //\r
2172 ///////////////////////////////////////////////////////////////////////////\r
2173 static boolean\r
2174 USL_CtlCJoyButtonCustom(UserCall call,word i,word n)\r
2175 {\r
2176         word    joy,\r
2177                         minx,maxx,\r
2178                         miny,maxy;\r
2179 \r
2180         i++,n++;        // Shut the compiler up\r
2181 \r
2182         if (call != uic_Hit)\r
2183                 return(false);\r
2184 \r
2185         IN_ClearKeysDown();\r
2186         joy = USL_FindDown(CtlCPanels) - 1;\r
2187 \r
2188         VW_HideCursor();\r
2189         FlushHelp = true;\r
2190         fontcolor = F_SECONDCOLOR;\r
2191 \r
2192         USL_ShowHelp("Move Joystick to the Upper-Left");\r
2193         VW_UpdateScreen();\r
2194         while ((LastScan != sc_Escape) && !IN_GetJoyButtonsDB(joy))\r
2195                 ;\r
2196         if (LastScan != sc_Escape)\r
2197         {\r
2198                 IN_GetJoyAbs(joy,&minx,&miny);\r
2199                 while (IN_GetJoyButtonsDB(joy))\r
2200                         ;\r
2201 \r
2202                 USL_ShowHelp("Move Joystick to the Lower-Right");\r
2203                 VW_UpdateScreen();\r
2204                 while ((LastScan != sc_Escape) && !IN_GetJoyButtonsDB(joy))\r
2205                         ;\r
2206                 if (LastScan != sc_Escape)\r
2207                 {\r
2208                         IN_GetJoyAbs(0,&maxx,&maxy);\r
2209                         IN_SetupJoy(joy,minx,maxx,miny,maxy);\r
2210                 }\r
2211         }\r
2212 \r
2213         if (LastScan != sc_Escape)\r
2214                 while (IN_GetJoyButtonsDB(joy))\r
2215                         ;\r
2216 \r
2217         if (LastScan)\r
2218                 IN_ClearKeysDown();\r
2219 \r
2220         fontcolor = F_BLACK;\r
2221         VW_ShowCursor();\r
2222 \r
2223         return(false);\r
2224 }\r
2225 \r
2226 ///////////////////////////////////////////////////////////////////////////\r
2227 //\r
2228 //      USL_ClearBottom() - Clears the bottom part of the window\r
2229 //\r
2230 ///////////////////////////////////////////////////////////////////////////\r
2231 static void\r
2232 USL_ClearBottom(void)\r
2233 {\r
2234         WindowRec       wr;\r
2235 \r
2236         US_SaveWindow(&wr);\r
2237         US_RestoreWindow(&BottomWindow);\r
2238 \r
2239         US_ClearWindow();\r
2240 \r
2241         US_RestoreWindow(&wr);\r
2242 }\r
2243 \r
2244 ///////////////////////////////////////////////////////////////////////////\r
2245 //\r
2246 //      USL_FormatHelp() - Formats helptext. Runs through and calculates the\r
2247 //              number of lines, and the offset for the start of each line. Stops\r
2248 //              after len bytes or when it hits a tilde ('~'). Munges the text.\r
2249 //\r
2250 ///////////////////////////////////////////////////////////////////////////\r
2251 static word\r
2252 USL_FormatHelp(char far *text,long len)\r
2253 {\r
2254         word    line,\r
2255                         w,h,\r
2256                         far *off;\r
2257         char    c,\r
2258                         far *s,far *l,far *le;\r
2259 \r
2260         WindowX += 4;\r
2261         WindowW -= 4;\r
2262 \r
2263         MM_GetPtr(&LineOffsets,MaxHelpLines * sizeof(word));\r
2264         off = (word far *)LineOffsets;\r
2265         for (line = 0,le = l = s = text;(s - text < len) && (*s != '~');s++)\r
2266         {\r
2267                 if ((c = *s) == '\n')\r
2268                 {\r
2269                         *s = '\0';\r
2270                         *off++ = l - text;      // Save offset of start of line\r
2271                         line++;                         // Bump line number\r
2272                         le = l = s + 1;         // Set start of line ptr\r
2273                 }\r
2274 \r
2275                 if (c == '\r')\r
2276                         c = *s = ' ';\r
2277                 if                                              // Strip orphaned spaces\r
2278                 (\r
2279                         (c == ' ')\r
2280                 &&      (s == l)\r
2281                 &&      (*(s - 1) == '\0')\r
2282                 &&      (*(s + 1) != ' ')\r
2283                 &&      (s > text)\r
2284                 )\r
2285                         le = l = s + 1;\r
2286                 else if (c == ' ')\r
2287                 {\r
2288                         *s = '\0';\r
2289                         USL_MeasureString(l,&w,&h);\r
2290                         if (w >= WindowW)       // If string width exceeds window,\r
2291                         {\r
2292                                 *s = c;                 // Replace null char with proper char\r
2293                                 *le = '\0';             // Go back to last line end\r
2294                                 *off++ = l - text;      // Save offset of start of line\r
2295                                 line++;                 // Bump line number\r
2296                                 l = s = le + 1; // Start next time through after last line end\r
2297                         }\r
2298                         else\r
2299                         {\r
2300                                 *s = c;                 // Width still ok - put char back\r
2301                                 le = s;                 // And save ptr to last ok end of word\r
2302                         }\r
2303                 }\r
2304         }\r
2305 \r
2306         WindowX -= 4;\r
2307         WindowW += 4;\r
2308 \r
2309         return(line);\r
2310 }\r
2311 \r
2312 ///////////////////////////////////////////////////////////////////////////\r
2313 //\r
2314 //      USL_DrawHelp() - Draws helptext in the current window\r
2315 //\r
2316 ///////////////////////////////////////////////////////////////////////////\r
2317 static void\r
2318 USL_DrawHelp(char far *text,word start,word end,word line,word h,word far *lp)\r
2319 {\r
2320         px = WindowX + 4;\r
2321         py = WindowY + (line * h);\r
2322         for (lp += start;start < end;start++,px = WindowX + 4,py += h)\r
2323                 USL_DrawString(text + *lp++);\r
2324 }\r
2325 \r
2326 ///////////////////////////////////////////////////////////////////////////\r
2327 //\r
2328 //      USL_DoHelp() - Formats and displays the specified help\r
2329 //\r
2330 ///////////////////////////////////////////////////////////////////////////\r
2331 static void\r
2332 USL_DoHelp(memptr text,long len)\r
2333 {\r
2334         boolean         done,\r
2335                                 moved;\r
2336         int                     scroll;\r
2337         word            i,\r
2338                                 pixdiv,\r
2339                                 w,h,\r
2340                                 lines,cur,page,\r
2341                                 top,num,loc,\r
2342                                 far *lp,\r
2343                                 base,srcbase,destbase;\r
2344         ScanCode        waitkey;\r
2345         longword        lasttime;\r
2346         WindowRec       wr;\r
2347         CursorInfo      info;\r
2348 \r
2349         USL_ShowHelp("Arrow Keys Move / Escape Exits");\r
2350         fontcolor = F_BLACK;\r
2351 \r
2352         US_SaveWindow(&wr);\r
2353         US_RestoreWindow(&BottomWindow);\r
2354         US_ClearWindow();\r
2355 \r
2356         VW_HideCursor();\r
2357         VW_UpdateScreen();\r
2358 \r
2359         lines = USL_FormatHelp((char far *)text,len);\r
2360         USL_MeasureString("",&w,&h);\r
2361         page = WindowH / h;\r
2362         cur = 0;\r
2363         lp = LineOffsets;\r
2364 \r
2365         IN_ClearKeysDown();\r
2366         moved = true;\r
2367         lasttime = 0;\r
2368         scroll = 0;\r
2369         done = false;\r
2370         waitkey = sc_None;\r
2371         while (!done)\r
2372         {\r
2373                 if (moved)\r
2374                 {\r
2375                         while (TimeCount - lasttime < 5)\r
2376                                 ;\r
2377                         lasttime = TimeCount;\r
2378 \r
2379                         if (scroll == -1)\r
2380                         {\r
2381                                 top = cur;\r
2382                                 num = 1;\r
2383                                 loc = 0;\r
2384                         }\r
2385                         else if (scroll == +1)\r
2386                         {\r
2387                                 num = 1;\r
2388                                 loc = page - 1;\r
2389                                 top = cur + loc;\r
2390                         }\r
2391                         else\r
2392                         {\r
2393                                 top = cur;\r
2394                                 num = (page < lines)? page : lines;\r
2395                                 loc = 0;\r
2396                         }\r
2397                         if (scroll)\r
2398                         {\r
2399                                 if (grmode == CGAGR)\r
2400                                 {\r
2401                                         pixdiv = 4;\r
2402                                         base = bufferofs + panadjust + (WindowX / pixdiv);\r
2403                                 }\r
2404                                 else if (grmode == EGAGR)\r
2405                                 {\r
2406                                         VWB_Bar(WindowX,WindowY + (loc * h),WindowW,num * h,WHITE);\r
2407                                         USL_DrawHelp((char far *)text,top,top + num,loc,h,lp);\r
2408 \r
2409                                         pixdiv = 8;\r
2410                                         base = displayofs + panadjust + (WindowX / pixdiv);\r
2411                                 }\r
2412                                 else if (grmode == VGAGR)\r
2413                                         pixdiv = 1;\r
2414 \r
2415                                 if (scroll == 1)\r
2416                                 {\r
2417                                         srcbase = base + ylookup[WindowY + h];\r
2418                                         destbase = base + ylookup[WindowY];\r
2419                                         if (grmode == EGAGR)\r
2420                                         {\r
2421                                                 EGAWRITEMODE(1);\r
2422                                                 VW_WaitVBL(1);\r
2423                                         }\r
2424                                         VW_ScreenToScreen(srcbase,destbase,WindowW / pixdiv,\r
2425                                                                                 WindowH - h);\r
2426                                 }\r
2427                                 else\r
2428                                 {\r
2429                                         i = WindowY + (h * (page - 1));\r
2430                                         srcbase = base + ylookup[i - h];\r
2431                                         destbase = base + ylookup[i];\r
2432                                         base = ylookup[h];\r
2433                                         for (i = page - 1;i;i--,srcbase -= base,destbase -= base)\r
2434                                                 VW_ScreenToScreen(srcbase,destbase,WindowW / pixdiv,h);\r
2435                                 }\r
2436                                 if (grmode == CGAGR)\r
2437                                 {\r
2438                                         VWB_Bar(WindowX,WindowY + (loc * h),WindowW,num * h,WHITE);\r
2439                                         USL_DrawHelp((char far *)text,top,top + num,loc,h,lp);\r
2440                                         VW_UpdateScreen();\r
2441                                 }\r
2442                                 else if (grmode == EGAGR)\r
2443                                 {\r
2444                                         base = panadjust + (WindowX / pixdiv) +\r
2445                                                         ylookup[WindowY + (loc * h)];\r
2446                                         VW_ScreenToScreen(base + bufferofs,base + displayofs,\r
2447                                                                                 WindowW / pixdiv,h);\r
2448                                 }\r
2449                         }\r
2450                         else\r
2451                         {\r
2452                                 US_ClearWindow();\r
2453                                 USL_DrawHelp((char far *)text,top,top + num,loc,h,lp);\r
2454                                 VW_UpdateScreen();\r
2455                         }\r
2456 \r
2457                         moved = false;\r
2458                         scroll = 0;\r
2459                 }\r
2460 \r
2461                 if (waitkey)\r
2462                         while (IN_KeyDown(waitkey))\r
2463                                 ;\r
2464                 waitkey = sc_None;\r
2465 \r
2466                 IN_ReadCursor(&info);\r
2467                 if (info.y < 0)\r
2468                 {\r
2469                         if (cur > 0)\r
2470                         {\r
2471                                 scroll = -1;\r
2472                                 cur--;\r
2473                                 moved = true;\r
2474                         }\r
2475                 }\r
2476                 else if (info.y > 0)\r
2477                 {\r
2478                         if (cur + page < lines)\r
2479                         {\r
2480                                 scroll = +1;\r
2481                                 cur++;\r
2482                                 moved = true;\r
2483                         }\r
2484                 }\r
2485                 else if (info.button0 || info.button1)\r
2486                         done = true;\r
2487                 else if (IN_KeyDown(LastScan))\r
2488                 {\r
2489                         switch (LastScan)\r
2490                         {\r
2491                         case sc_Escape:\r
2492                                 done = true;\r
2493                                 break;\r
2494                         case sc_UpArrow:\r
2495                                 if (cur > 0)\r
2496                                 {\r
2497                                         scroll = -1;\r
2498                                         cur--;\r
2499                                         moved = true;\r
2500                                 }\r
2501                                 break;\r
2502                         case sc_DownArrow:\r
2503                                 if (cur + page < lines)\r
2504                                 {\r
2505                                         scroll = +1;\r
2506                                         cur++;\r
2507                                         moved = true;\r
2508                                 }\r
2509                                 break;\r
2510                         case sc_PgUp:\r
2511                                 if (cur > page)\r
2512                                         cur -= page;\r
2513                                 else\r
2514                                         cur = 0;\r
2515                                 moved = true;\r
2516                                 waitkey = sc_PgUp;\r
2517                                 break;\r
2518                         case sc_PgDn:\r
2519                                 if (cur + page < lines)\r
2520                                 {\r
2521                                         cur += page;\r
2522                                         if (cur + page >= lines)\r
2523                                                 cur = lines - page;\r
2524                                         moved = true;\r
2525                                 }\r
2526                                 waitkey = sc_PgDn;\r
2527                                 break;\r
2528                         }\r
2529                 }\r
2530         }\r
2531         IN_ClearKeysDown();\r
2532         do\r
2533         {\r
2534                 IN_ReadCursor(&info);\r
2535         } while (info.button0 || info.button1);\r
2536 \r
2537         VW_ShowCursor();\r
2538         US_ClearWindow();\r
2539         VW_UpdateScreen();\r
2540         US_RestoreWindow(&wr);\r
2541 }\r
2542 \r
2543 ///////////////////////////////////////////////////////////////////////////\r
2544 //\r
2545 //      USL_CtlHButtonCustom() - The custom routine for all of the help buttons\r
2546 //\r
2547 ///////////////////////////////////////////////////////////////////////////\r
2548 static boolean\r
2549 USL_CtlHButtonCustom(UserCall call,word i,word n)\r
2550 {\r
2551         word            j;\r
2552         UserItem        *ip;\r
2553 \r
2554         if (call != uic_Hit)\r
2555                 return(false);\r
2556 \r
2557         ip = &TheItems[i][n];\r
2558         if (ip->sel & ui_Disabled)\r
2559                 return(false);\r
2560 \r
2561         ip->sel |= ui_Selected;\r
2562         USL_DrawItem(i,n);\r
2563 \r
2564         USL_ClearBottom();\r
2565 \r
2566         fontcolor = F_SECONDCOLOR;\r
2567         USL_ShowHelp("Loading & Formatting Text...");\r
2568         VW_UpdateScreen();\r
2569 \r
2570 #ifdef  HELPTEXTLINKED  // Ugly hack because of lack of disk space...\r
2571         {\r
2572 extern  char    far gametext,far context,far story;\r
2573                 char    far *buf;\r
2574                 memptr  dupe;\r
2575 \r
2576                 switch (n)\r
2577                 {\r
2578                 case 0:\r
2579                         buf = &gametext;\r
2580                         break;\r
2581                 case 1:\r
2582                         buf = &context;\r
2583                         break;\r
2584                 case 2:\r
2585                         buf = &story;\r
2586                         break;\r
2587                 }\r
2588 \r
2589                 MM_GetPtr(&dupe,5000);\r
2590                 _fmemcpy((char far *)dupe,buf,5000);\r
2591 \r
2592                 USL_DoHelp(dupe,5000);\r
2593 \r
2594                 MM_FreePtr(&dupe);\r
2595                 if (LineOffsets)\r
2596                         MM_FreePtr(&LineOffsets);\r
2597         }\r
2598 #else\r
2599         {\r
2600                 char    *name;\r
2601                 int             file;\r
2602                 long    len;\r
2603                 memptr  buf;\r
2604 \r
2605                 switch (n)\r
2606                 {\r
2607                 case 0:\r
2608                         name = "GAMETEXT."EXTENSION;\r
2609                         break;\r
2610                 case 1:\r
2611                         name = "CONTEXT."EXTENSION;\r
2612                         break;\r
2613                 case 2:\r
2614                         name = "STORY."EXTENSION;\r
2615                         break;\r
2616                 default:\r
2617                         Quit("Bad help button number");\r
2618                 }\r
2619 \r
2620                 if ((file = open(name,O_RDONLY | O_TEXT)) == -1)\r
2621                         USL_HandleError(errno);\r
2622                 else\r
2623                 {\r
2624                         len = filelength(file);\r
2625                         MM_GetPtr(&buf,len);\r
2626 \r
2627                         if (CA_FarRead(file,(byte far *)buf,len))\r
2628                                 USL_DoHelp(buf,len);\r
2629                         else\r
2630                                 USL_HandleError(errno);\r
2631 \r
2632                         close(file);\r
2633                         MM_FreePtr(&buf);\r
2634                 }\r
2635 \r
2636                 if (LineOffsets)\r
2637                         MM_FreePtr(&LineOffsets);\r
2638         }\r
2639 #endif\r
2640 \r
2641         fontcolor = F_BLACK;\r
2642 \r
2643         ip->sel &= ~ui_Selected;\r
2644         USL_DrawItem(i,n);\r
2645 \r
2646         return(false);\r
2647 }\r
2648 \r
2649 ///////////////////////////////////////////////////////////////////////////\r
2650 //\r
2651 //      USL_CtlDButtonCustom() - The custom routine for all of the disk buttons.\r
2652 //              Sets up the bottom area of the window with the appropriate buttons\r
2653 //\r
2654 ///////////////////////////////////////////////////////////////////////////\r
2655 static boolean\r
2656 USL_CtlDButtonCustom(UserCall call,word i,word n)\r
2657 {\r
2658         word            j;\r
2659         UserItem        *ip;\r
2660 \r
2661         if (call != uic_Hit)\r
2662                 return(false);\r
2663 \r
2664         ip = &TheItems[i][n];\r
2665         if (ip->sel & ui_Disabled)\r
2666                 return(false);\r
2667 \r
2668         USL_ClearBottom();\r
2669 \r
2670         j = 0;\r
2671         TheItems[i + 1] = ip = n? CtlDEPanels : CtlDLSPanels;\r
2672         while (ip && (ip->type != uii_Bad))\r
2673         {\r
2674                 USL_DrawItem(i + 1,j++);\r
2675                 ip++;\r
2676         }\r
2677 \r
2678         return(false);\r
2679 }\r
2680 \r
2681 ///////////////////////////////////////////////////////////////////////////\r
2682 //\r
2683 //      USL_DLSRect() - Draw the rectangle for the save game names\r
2684 //\r
2685 ///////////////////////////////////////////////////////////////////////////\r
2686 static Rect\r
2687 USL_DLSRect(UserItem *ip)\r
2688 {\r
2689         Rect    r;\r
2690 \r
2691         r.ul.x = ip->r.lr.x + 40 + 2;\r
2692         r.ul.y = ip->r.ul.y + 2;\r
2693         r.lr.x = WindowX + WindowW - 8 - 2;\r
2694         r.lr.y = ip->r.lr.y - 2;\r
2695 \r
2696         VWB_Bar(r.ul.x,r.ul.y,r.lr.x - r.ul.x,r.lr.y - r.ul.y,WHITE);\r
2697 \r
2698         VWB_Hlin(r.ul.x,r.lr.x,r.ul.y,BLACK);\r
2699         VWB_Hlin(r.ul.x,r.lr.x,r.lr.y,BLACK);\r
2700         VWB_Vlin(r.ul.y,r.lr.y,r.ul.x,BLACK);\r
2701         VWB_Vlin(r.ul.y,r.lr.y,r.lr.x,BLACK);\r
2702 \r
2703         px = r.ul.x + 2;\r
2704         py = r.ul.y + 2;\r
2705 \r
2706         return(r);\r
2707 }\r
2708 \r
2709 ///////////////////////////////////////////////////////////////////////////\r
2710 //\r
2711 //      USL_CtlDLButtonCustom() - The load game custom routine\r
2712 //\r
2713 ///////////////////////////////////////////////////////////////////////////\r
2714 static boolean\r
2715 USL_CtlDLButtonCustom(UserCall call,word i,word n)\r
2716 {\r
2717         char            *filename,\r
2718                                 msg[MaxGameName + 12];\r
2719         word            err;\r
2720         int                     file;\r
2721         UserItem        *ip;\r
2722         SaveGame        *game;\r
2723         WindowRec       wr;\r
2724 \r
2725         // DEBUG - deal with warning user about loading a game causing abort\r
2726 \r
2727         game = &Games[n / 2];\r
2728         ip = &TheItems[i][n];\r
2729 \r
2730         switch (call)\r
2731         {\r
2732         case uic_Draw:\r
2733                 if (!loadedgame)\r
2734                 {\r
2735                         USL_DLSRect(ip);\r
2736                         fontcolor = game->present? F_BLACK : F_FIRSTCOLOR;\r
2737                         USL_DrawString(game->present? game->name : "Empty");\r
2738                         fontcolor = F_BLACK;\r
2739                 }\r
2740                 break;\r
2741         case uic_Hit:\r
2742                 if (ip->sel & ui_Disabled)\r
2743                         return(false);\r
2744 \r
2745                 LeaveDriveOn++;\r
2746                 filename = USL_GiveSaveName(n / 2);\r
2747 \r
2748                 US_SaveWindow(&wr);\r
2749                 US_CenterWindow(30,3);\r
2750                 strcpy(msg,"Loading `");\r
2751                 strcat(msg,game->name);\r
2752                 strcat(msg,"\'");\r
2753                 US_PrintCentered(msg);\r
2754                 VW_HideCursor();\r
2755                 VW_UpdateScreen();\r
2756 \r
2757                 err = 0;\r
2758                 if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
2759                 {\r
2760                         if (read(file,game,sizeof(*game)) == sizeof(*game))\r
2761                         {\r
2762                                 if (USL_LoadGame)\r
2763                                         if (!USL_LoadGame(file))\r
2764                                                 USL_HandleError(err = errno);\r
2765                         }\r
2766                         else\r
2767                                 USL_HandleError(err = errno);\r
2768                         close(file);\r
2769                 }\r
2770                 else\r
2771                         USL_HandleError(err = errno);\r
2772                 if (err)\r
2773                         abortgame = true;\r
2774                 else\r
2775                         loadedgame = true;\r
2776                 game->present = true;\r
2777 \r
2778                 if (loadedgame)\r
2779                         Paused = true;\r
2780 \r
2781                 VW_ShowCursor();\r
2782                 US_RestoreWindow(&wr);\r
2783 \r
2784                 LeaveDriveOn--;\r
2785                 break;\r
2786         }\r
2787         return(false);\r
2788 }\r
2789 \r
2790 ///////////////////////////////////////////////////////////////////////////\r
2791 //\r
2792 //      USL_CtlDSButtonCustom() - The save game custom routine\r
2793 //\r
2794 ///////////////////////////////////////////////////////////////////////////\r
2795 static boolean\r
2796 USL_CtlDSButtonCustom(UserCall call,word i,word n)\r
2797 {\r
2798         boolean         ok;\r
2799         char            *filename;\r
2800         word            err;\r
2801         int                     file;\r
2802         Rect            r;\r
2803         UserItem        *ip;\r
2804         SaveGame        *game;\r
2805         WindowRec       wr;\r
2806 \r
2807         if (call != uic_Hit)\r
2808                 return(false);\r
2809 \r
2810         game = &Games[n / 2];\r
2811         ip = &TheItems[i][n];\r
2812         if (ip->sel & ui_Disabled)\r
2813                 return(false);\r
2814 \r
2815         FlushHelp = true;\r
2816         fontcolor = F_SECONDCOLOR;\r
2817         USL_ShowHelp("Enter Game Name / Escape Aborts");\r
2818         fontcolor = F_BLACK;\r
2819 \r
2820         r = USL_DLSRect(ip - 1);\r
2821         ok = US_LineInput(px,py,game->name,game->present? game->name : nil,true,\r
2822                                                 MaxGameName,r.lr.x - r.ul.x - 8);\r
2823         if (!strlen(game->name))\r
2824                 strcpy(game->name,"Untitled");\r
2825         if (ok)\r
2826         {\r
2827                 US_SaveWindow(&wr);\r
2828                 US_CenterWindow(10,3);\r
2829                 US_PrintCentered("Saving");\r
2830                 VW_HideCursor();\r
2831                 VW_UpdateScreen();\r
2832 \r
2833                 LeaveDriveOn++;\r
2834                 filename = USL_GiveSaveName(n / 2);\r
2835                 err = 0;\r
2836                 file = open(filename,O_CREAT | O_BINARY | O_WRONLY,\r
2837                                         S_IREAD | S_IWRITE | S_IFREG);\r
2838                 if (file != -1)\r
2839                 {\r
2840                         if (write(file,game,sizeof(*game)) == sizeof(*game))\r
2841                         {\r
2842                                 if (USL_SaveGame)\r
2843                                         ok = USL_SaveGame(file);\r
2844                                 if (!ok)\r
2845                                         USL_HandleError(err = errno);\r
2846                         }\r
2847                         else\r
2848                                 USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
2849                         close(file);\r
2850                 }\r
2851                 else\r
2852                         USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
2853                 if (err)\r
2854                 {\r
2855                         remove(filename);\r
2856                         ok = false;\r
2857                 }\r
2858                 LeaveDriveOn--;\r
2859 \r
2860                 VW_ShowCursor();\r
2861                 US_RestoreWindow(&wr);\r
2862                 USL_DoHit(i - 1,0);\r
2863                 VW_UpdateScreen();\r
2864         }\r
2865 \r
2866         if (!game->present)\r
2867                 game->present = ok;\r
2868 \r
2869         if (ok)\r
2870         {\r
2871                 GameIsDirty = false;\r
2872                 (ip - 1)->sel &= ~ui_Disabled;\r
2873         }\r
2874 \r
2875         USL_DrawItem(i,n - 1);\r
2876 //      USL_CtlDLButtonCustom(uic_Draw,i,n - 1);\r
2877 \r
2878         return(true);\r
2879 }\r
2880 \r
2881 ///////////////////////////////////////////////////////////////////////////\r
2882 //\r
2883 //      USL_CtlSButtonCustom() - The custom routine for all of the sound buttons\r
2884 //\r
2885 ///////////////////////////////////////////////////////////////////////////\r
2886 static boolean\r
2887 USL_CtlSButtonCustom(UserCall call,word i,word n)\r
2888 {\r
2889         word            j;\r
2890         UserItem        *ip;\r
2891 \r
2892         if (call != uic_Hit)\r
2893                 return(false);\r
2894 \r
2895         ip = &TheItems[i][n];\r
2896         if (ip->sel & ui_Disabled)\r
2897                 return(false);\r
2898 \r
2899         USL_ClearBottom();\r
2900 \r
2901         if (n == sdm_SoundSource)\r
2902         {\r
2903                 j = 0;\r
2904                 TheItems[i + 1] = ip = CtlSSSPanels;\r
2905                 while (ip && (ip->type != uii_Bad))\r
2906                 {\r
2907                         USL_DrawItem(i + 1,j++);\r
2908                         ip++;\r
2909                 }\r
2910         }\r
2911         else\r
2912                 TheItems[i + 1] = nil;\r
2913 \r
2914         return(false);\r
2915 }\r
2916 \r
2917 ///////////////////////////////////////////////////////////////////////////\r
2918 //\r
2919 //      USL_CtlPButtonCustom() - The custom routine for all of the start game btns\r
2920 //\r
2921 ///////////////////////////////////////////////////////////////////////////\r
2922 static boolean\r
2923 USL_CtlPButtonCustom(UserCall call,word i,word n)\r
2924 {\r
2925         word            j;\r
2926         UserItem        *ip;\r
2927 \r
2928         if (call != uic_Hit)\r
2929                 return(false);\r
2930 \r
2931         ip = &TheItems[i][n];\r
2932         if (ip->sel & ui_Disabled)\r
2933                 return(false);\r
2934 \r
2935         USL_ClearBottom();\r
2936 \r
2937         j = 0;\r
2938         TheItems[i + 1] = ip = n? CtlPRPanels : CtlPSPanels;\r
2939         while (ip && (ip->type != uii_Bad))\r
2940         {\r
2941                 USL_DrawItem(i + 1,j++);\r
2942                 ip++;\r
2943         }\r
2944 \r
2945         return(false);\r
2946 }\r
2947 \r
2948 ///////////////////////////////////////////////////////////////////////////\r
2949 //\r
2950 //      USL_GiveAbortWarning() - Draws a string that warns the user that an\r
2951 //              action they're about to take will abort the game in progress\r
2952 //\r
2953 ///////////////////////////////////////////////////////////////////////////\r
2954 static void\r
2955 USL_GiveAbortWarning(void)\r
2956 {\r
2957         WindowRec       wr;\r
2958 \r
2959         if (!GameIsDirty)\r
2960                 return;\r
2961 \r
2962         US_SaveWindow(&wr);\r
2963         US_RestoreWindow(&BottomWindow);\r
2964         US_HomeWindow();\r
2965         PrintY += 5;\r
2966 \r
2967         VWB_Bar(WindowX,WindowY,WindowW,30,WHITE);\r
2968         fontcolor = F_SECONDCOLOR;\r
2969         US_CPrint("Warning! If you do this, you'll");\r
2970         US_CPrint("abort the current game.");\r
2971         fontcolor = F_BLACK;\r
2972 \r
2973         US_RestoreWindow(&wr);\r
2974 }\r
2975 \r
2976 ///////////////////////////////////////////////////////////////////////////\r
2977 //\r
2978 //      USL_CtlPSButtonCustom() - The custom routine for the start game button\r
2979 //\r
2980 ///////////////////////////////////////////////////////////////////////////\r
2981 static boolean\r
2982 USL_CtlPSButtonCustom(UserCall call,word i,word n)\r
2983 {\r
2984         boolean         result;\r
2985         UserItem        *ip;\r
2986 \r
2987         i++;    // Shut the compiler up\r
2988 \r
2989         switch (call)\r
2990         {\r
2991         case uic_Hit:\r
2992                 switch (n)\r
2993                 {\r
2994                 case 0:\r
2995                         restartgame = gd_Normal;\r
2996                         break;\r
2997                 case 1:\r
2998                         restartgame = gd_Easy;\r
2999                         break;\r
3000                 case 2:\r
3001                         restartgame = gd_Hard;\r
3002                         break;\r
3003                 }\r
3004                 if (restartgame && ingame && USL_ResetGame)\r
3005                         USL_ResetGame();\r
3006                 result = false;\r
3007                 break;\r
3008         case uic_Draw:\r
3009                 USL_GiveAbortWarning();\r
3010                 result = false;\r
3011                 break;\r
3012         default:\r
3013                 result = false;\r
3014                 break;\r
3015         }\r
3016         return(result);\r
3017 }\r
3018 \r
3019 ///////////////////////////////////////////////////////////////////////////\r
3020 //\r
3021 //      USL_CtlPRButtonCustom() - The custom routine for the resume game button\r
3022 //\r
3023 ///////////////////////////////////////////////////////////////////////////\r
3024 static boolean\r
3025 USL_CtlPRButtonCustom(UserCall call,word i,word n)\r
3026 {\r
3027         if (call != uic_Hit)\r
3028                 return(false);\r
3029 \r
3030         i++,n++;        // Shut the compiler up\r
3031         ResumeGame = true;\r
3032         return(false);\r
3033 }\r
3034 \r
3035 ///////////////////////////////////////////////////////////////////////////\r
3036 //\r
3037 //      USL_CtlDEButtonCustom() - The custom routine for the exit to DOS button\r
3038 //\r
3039 ///////////////////////////////////////////////////////////////////////////\r
3040 static boolean\r
3041 USL_CtlDEButtonCustom(UserCall call,word i,word n)\r
3042 {\r
3043         boolean         result;\r
3044         UserItem        *ip;\r
3045 \r
3046         i++,n++;        // Shut the compiler up\r
3047 \r
3048         switch (call)\r
3049         {\r
3050         case uic_Hit:\r
3051                 QuitToDos = true;\r
3052                 break;\r
3053         case uic_Draw:\r
3054                 USL_GiveAbortWarning();\r
3055         default:\r
3056                 result = false;\r
3057                 break;\r
3058         }\r
3059         return(result);\r
3060 }\r
3061 \r
3062 ///////////////////////////////////////////////////////////////////////////\r
3063 //\r
3064 //      USL_CtlCButtonCustom() - The custom routine for all of the control\r
3065 //              buttons\r
3066 //\r
3067 ///////////////////////////////////////////////////////////////////////////\r
3068 static boolean\r
3069 USL_CtlCButtonCustom(UserCall call,word i,word n)\r
3070 {\r
3071         word            j;\r
3072         Point           p;\r
3073         UserItem        *ip;\r
3074 \r
3075         if (call != uic_Hit)\r
3076                 return(false);\r
3077 \r
3078         ip = &TheItems[i][n];\r
3079         if (ip->sel & ui_Disabled)\r
3080                 return(false);\r
3081 \r
3082         USL_ClearBottom();\r
3083         if (n == 0)     // Keyboard\r
3084         {\r
3085                 TheItems[i + 1] = ip = CtlCKbdPanels;\r
3086                 p = CtlCKbdPanels[2].r.lr;\r
3087                 VWB_DrawPic(p.x,p.y,CTL_DIRSPIC);\r
3088         }\r
3089         else\r
3090                 TheItems[i + 1] = ip = CtlCJoyPanels;\r
3091 \r
3092         j = 0;\r
3093         while (ip && (ip->type != uii_Bad))\r
3094         {\r
3095                 USL_DrawItem(i + 1,j++);\r
3096                 ip++;\r
3097         }\r
3098 \r
3099         return(false);\r
3100 }\r
3101 \r
3102 ///////////////////////////////////////////////////////////////////////////\r
3103 //\r
3104 //      USL_HitHotKey() - After a hotkey was hit, move the cursor to the first\r
3105 //              selected item in the group after the group containing the item\r
3106 //              holding the hotkey\r
3107 //\r
3108 ///////////////////////////////////////////////////////////////////////////\r
3109 static void\r
3110 USL_HitHotKey(int i,int n)\r
3111 {\r
3112         UserItem        *ip;\r
3113 \r
3114         if (ip = TheItems[++i])\r
3115         {\r
3116                 if ((n = USL_FindDown(TheItems[i])) == -1)\r
3117                         n = 0;\r
3118                 ip += n;\r
3119                 CursorX = ip->r.lr.x - 8;\r
3120                 CursorY = ip->r.lr.y - 8;\r
3121                 CursorBad = true;\r
3122         }\r
3123 }\r
3124 \r
3125 ///////////////////////////////////////////////////////////////////////////\r
3126 //\r
3127 //      USL_CheckScan() - Checks to see if the scancode in LastScan corresponds\r
3128 //              to anything in the list of useritems. If so, selects the item.\r
3129 //\r
3130 ///////////////////////////////////////////////////////////////////////////\r
3131 static boolean\r
3132 USL_CheckScan(word *ci,word *cn)\r
3133 {\r
3134         word            i,n;\r
3135         UserItem        *ip;\r
3136 \r
3137         if (!LastScan)\r
3138                 return(false);\r
3139 \r
3140 #if 1   // DEBUG - probably kill this code\r
3141         // Use 1..? for the items across the top row\r
3142         if (TheItems[1] && !IN_KeyDown(sc_RShift))\r
3143         {\r
3144                 for (i = 0,ip = TheItems[1];(ip->type != uii_Bad) && (i < 9);i++,ip++)\r
3145                         ;\r
3146                 for (n = 0;n < i;n++)\r
3147                 {\r
3148                         if (LastScan == 2 + n)  // Numbers from 1..9\r
3149                         {\r
3150                                 if (!(TheItems[1][n].sel & ui_Disabled))\r
3151                                 {\r
3152                                         LastScan = sc_None;\r
3153                                         USL_DoHit(1,n);\r
3154                                         return(true);\r
3155                                 }\r
3156                         }\r
3157                 }\r
3158         }\r
3159 \r
3160         // Use Alt-1..6 for the items in the leftmost column\r
3161         if (IN_KeyDown(sc_RShift))\r
3162         {\r
3163                 n = LastScan - 2;\r
3164                 if (n < 6)      // Numbers from 1..6\r
3165                 {\r
3166                         USL_DoHit(0,n);\r
3167                         LastScan = sc_None;\r
3168                         return(true);\r
3169                 }\r
3170         }\r
3171 #endif\r
3172 \r
3173         // Check normal hotkeys for the leftmost column\r
3174         for (i = 0;CtlPanels[i].type != uii_Bad;i++)\r
3175         {\r
3176                 if (CtlPanels[i].key == LastScan)\r
3177                 {\r
3178                         LastScan = sc_None;\r
3179                         USL_DoHit(0,i);\r
3180                         *ci = 0;\r
3181                         *cn = i;\r
3182                         USL_HitHotKey(0,i);\r
3183                         return(true);\r
3184                 }\r
3185         }\r
3186 \r
3187         // Check normal hotkeys for the top row\r
3188         for (i = 0;i < 6;i++)\r
3189         {\r
3190                 for (n = 0,ip = CtlPanels2[i];ip && ip->type != uii_Bad;n++,ip++)\r
3191                 {\r
3192                         if ((ip->key == LastScan) && !(ip->sel & ui_Disabled))\r
3193                         {\r
3194                                 LastScan = sc_None;\r
3195                                 USL_DoHit(0,i);\r
3196                                 USL_DoHit(1,n);\r
3197                                 *ci = 1;\r
3198                                 *cn = n;\r
3199                                 USL_HitHotKey(1,n);\r
3200                                 return(true);\r
3201                         }\r
3202                 }\r
3203         }\r
3204         return(false);\r
3205 }\r
3206 \r
3207 ///////////////////////////////////////////////////////////////////////////\r
3208 //\r
3209 //      USL_SetUpCtlPanel() - Sets the states of the UserItems to reflect the\r
3210 //              values of all the appropriate variables\r
3211 //\r
3212 ///////////////////////////////////////////////////////////////////////////\r
3213 static void\r
3214 USL_SetUpCtlPanel(void)\r
3215 {\r
3216         word    i,j;\r
3217 \r
3218         GameIsDirty = ingame;\r
3219 \r
3220         // Set up restart game\r
3221         USL_TurnOff(CtlPPanels);\r
3222         CtlPPanels[0].sel = ingame? ui_Normal : ui_Selected;\r
3223         CtlPPanels[1].sel = ingame? ui_Selected : ui_Disabled;\r
3224 \r
3225         // Set up disk stuff - default to load/save game\r
3226         USL_TurnOff(CtlDPanels);\r
3227         CtlDPanels[0].sel = ui_Selected;\r
3228 \r
3229         // Set up load/save buttons\r
3230         USL_TurnOff(CtlDLSPanels);\r
3231         for (i = 0;i < MaxSaveGames;i++)\r
3232         {\r
3233                 if (!Games[i].present)\r
3234                         CtlDLSPanels[i * 2].sel = ui_Disabled;\r
3235                 if (!ingame)\r
3236                         CtlDLSPanels[(i * 2) + 1].sel = ui_Disabled;\r
3237         }\r
3238 \r
3239         // Set up Controls\r
3240         USL_TurnOff(CtlCPanels);\r
3241         CtlCPanels[1].sel = JoysPresent[0]? ui_Normal : ui_Disabled;\r
3242         CtlCPanels[2].sel = JoysPresent[1]? ui_Normal : ui_Disabled;\r
3243         if (Controls[0] == ctrl_Keyboard)\r
3244                 i = 0;\r
3245         else\r
3246                 i = (Controls[0] == ctrl_Joystick1)? 1 : 2;\r
3247         CtlCPanels[i].sel |= ui_Selected;\r
3248         if (JoysPresent[1] && !JoysPresent[0])\r
3249                 CtlCPanels[2].key = sc_F4;\r
3250         else\r
3251                 CtlCPanels[1].key = sc_F4;\r
3252 \r
3253         // Set up Keyboard\r
3254         for (i = 0;i < 10;i++)\r
3255                 CtlCKbdPanels[i].text = IN_GetScanName(*(KeyMaps[i]));\r
3256 \r
3257         // Set up Sounds\r
3258         USL_TurnOff(CtlSPanels);\r
3259         CtlSPanels[sdm_AdLib].sel = AdLibPresent? ui_Normal : ui_Disabled;\r
3260 #if 0   // DEBUG - hack because no space for digitized sounds on Keen Dreams\r
3261         CtlSPanels[sdm_SoundBlaster].sel =\r
3262                 SoundBlasterPresent? ui_Normal : ui_Disabled;\r
3263         CtlSPanels[sdm_SoundSource].sel =\r
3264                 SoundSourcePresent? ui_Normal : ui_Disabled;\r
3265 #else\r
3266         CtlSPanels[sdm_SoundBlaster].sel = ui_Disabled;\r
3267         CtlSPanels[sdm_SoundSource].sel = ui_Disabled;\r
3268 #endif\r
3269         CtlSPanels[SoundMode].sel |= ui_Selected;\r
3270 \r
3271         // Set up SoundSource\r
3272         USL_TurnOff(CtlSSSPanels);\r
3273         CtlSSSPanels[0].sel = ssIsTandy? ui_Selected : ui_Normal;\r
3274         CtlSSSPanels[1].sel = (ssPort == 2)? ui_Selected : ui_Normal;\r
3275 \r
3276         // Set up Music\r
3277         USL_TurnOff(CtlMPanels);\r
3278         CtlMPanels[smm_AdLib].sel = AdLibPresent? ui_Normal : ui_Disabled;\r
3279         CtlMPanels[MusicMode].sel |= ui_Selected;\r
3280 }\r
3281 \r
3282 ///////////////////////////////////////////////////////////////////////////\r
3283 //\r
3284 //      USL_TearDownCtlPanel() - Given the state of the control panel, sets the\r
3285 //              modes and values as appropriate\r
3286 //\r
3287 ///////////////////////////////////////////////////////////////////////////\r
3288 static void\r
3289 USL_TearDownCtlPanel(void)\r
3290 {\r
3291         int     i;\r
3292 \r
3293         i = USL_FindDown(CtlCPanels);\r
3294         if (i != -1)\r
3295         {\r
3296                 i = i? (i == 1? ctrl_Joystick1 : ctrl_Joystick2) : ctrl_Keyboard;\r
3297                 IN_SetControlType(0,i);\r
3298         }\r
3299 \r
3300         CtlCPanels[1].key = CtlCPanels[2].key = sc_None;\r
3301 \r
3302         i = USL_FindDown(CtlSPanels);\r
3303         if (i != -1)\r
3304                 SD_SetSoundMode(i);\r
3305 \r
3306         ssIsTandy = CtlSSSPanels[0].sel & ui_Selected;\r
3307         ssPort = (CtlSSSPanels[1].sel & ui_Selected)? 2 : 1;\r
3308 \r
3309         i = USL_FindDown(CtlMPanels);\r
3310         if (i != -1)\r
3311         {\r
3312                 SD_SetMusicMode(i);\r
3313 \r
3314                 if (!QuitToDos)\r
3315                 {\r
3316                         US_CenterWindow(20,8);\r
3317                         US_CPrint("Loading");\r
3318 #if 0\r
3319                         fontcolor = F_SECONDCOLOR;\r
3320                         US_CPrint("Sounds");\r
3321                         fontcolor = F_BLACK;\r
3322 #endif\r
3323                         VW_UpdateScreen();\r
3324 \r
3325                         CA_LoadAllSounds();\r
3326                 }\r
3327         }\r
3328 }\r
3329 \r
3330 ///////////////////////////////////////////////////////////////////////////\r
3331 //\r
3332 //      US_ControlPanel() - This is the main routine for the control panel\r
3333 //\r
3334 ///////////////////////////////////////////////////////////////////////////\r
3335 void\r
3336 US_ControlPanel(void)\r
3337 {\r
3338         char            gamename[MaxGameName + 10 + 1];\r
3339         ScanCode        c;\r
3340         boolean         done,\r
3341                                 buttondown,inrect;\r
3342         word            hiti,hitn,\r
3343                                 i,n,\r
3344                                 lasti,lastn,\r
3345                                 lastx,lasty;\r
3346         longword        lasttime;\r
3347         Point           p;\r
3348         Rect            userect;\r
3349         UserItem        *ip;\r
3350 \r
3351         c = LastScan;\r
3352         if (c == sc_Escape)     // Map escape from game to Exit to DOS\r
3353                 c = sc_Q;\r
3354 \r
3355         CA_UpLevel();\r
3356         for (i = CONTROLS_LUMP_START;i <= CONTROLS_LUMP_END;i++)\r
3357                 CA_MarkGrChunk(i);\r
3358         CA_MarkGrChunk(CTL_LITTLEMASKPICM);\r
3359         CA_MarkGrChunk(CTL_LSMASKPICM);\r
3360         CA_CacheMarks("Options Screen");\r
3361 \r
3362         USL_SetUpCtlPanel();\r
3363 \r
3364         US_SetPrintRoutines(VW_MeasurePropString,VWB_DrawPropString);\r
3365         fontcolor = F_BLACK;\r
3366 \r
3367         VW_InitDoubleBuffer();\r
3368 \r
3369         VWB_Bar(0,0,MaxX,MaxY,FIRSTCOLOR);\r
3370         US_DrawWindow(8,22,30,2);\r
3371         US_SaveWindow(&HelpWindow);\r
3372         US_DrawWindow(8,7,30,14);\r
3373         US_SaveWindow(&BottomWindow);\r
3374         US_DrawWindow(8,1,30,20);\r
3375 \r
3376         for (ip = CtlPanels;ip->type != uii_Bad;ip++)\r
3377                 VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,ip->picup);\r
3378 \r
3379         US_StartCursor();\r
3380         CursorX = (8 * 8) + ((MaxX - (8 * 8)) / 2);\r
3381         CursorBad = true;\r
3382 \r
3383         CtlPanelButton = -1;\r
3384         LastScan = c;\r
3385         USL_CheckScan(&i,&n);\r
3386         if (CtlPanelButton == -1)\r
3387                 USL_DoHit(0,0);\r
3388 \r
3389         ResumeGame = false;\r
3390         done = false;\r
3391         FlushHelp = true;\r
3392         lastx = lasty = -1;\r
3393         while\r
3394         (\r
3395                 (restartgame == gd_Continue)\r
3396         &&      !(done || loadedgame || ResumeGame)\r
3397         )\r
3398         {\r
3399                 VW_UpdateScreen();\r
3400 \r
3401                 buttondown = US_UpdateCursor();\r
3402                 inrect = USL_IsInRect(CursorX,CursorY,&i,&n);\r
3403 \r
3404                 if (FlushHelp)\r
3405                 {\r
3406                         lasti = -2;\r
3407                         lasttime = TimeCount;\r
3408                         FlushHelp = false;\r
3409                 }\r
3410                 if (inrect)\r
3411                 {\r
3412                         if ((lasti != i) || (lastn != n))\r
3413                         {\r
3414                                 // If over a Load button\r
3415                                 if\r
3416                                 (\r
3417                                         (CtlPanelButton == 2)\r
3418                                 &&      (i == 2)\r
3419                                 &&      (TheItems[1][0].sel & ui_Selected)\r
3420                                 &&      (Games[n / 2].present)\r
3421                                 &&      !(n & 1)\r
3422                                 )\r
3423                                 {\r
3424                                         strcpy(gamename,"Load `");\r
3425                                         strcat(gamename,Games[n / 2].name);\r
3426                                         strcat(gamename,"'");\r
3427                                         USL_ShowHelp(gamename);\r
3428                                 }\r
3429                                 else\r
3430                                         USL_ShowHelp(TheItems[i][n].help);\r
3431                                 lasti = i;\r
3432                                 lastn = n;\r
3433                         }\r
3434                 }\r
3435                 else if (lasti != (word)-1)\r
3436                 {\r
3437                         USL_ShowHelp("Select a Button");\r
3438                         lasti = -1;\r
3439                 }\r
3440 \r
3441                 hiti = i;\r
3442                 hitn = n;\r
3443 \r
3444                 if (inrect)\r
3445                         userect = TheItems[i][n].r;\r
3446                 else\r
3447                 {\r
3448                         userect.ul.x = CursorX;\r
3449                         userect.ul.y = CursorY;\r
3450                         userect.lr = userect.ul;\r
3451                 }\r
3452 \r
3453                 if (IN_KeyDown(sc_UpArrow))\r
3454                 {\r
3455                         USL_FindRect(userect,motion_None,motion_Up);\r
3456                         buttondown = false;\r
3457                         IN_ClearKey(sc_UpArrow);\r
3458                 }\r
3459                 else if (IN_KeyDown(sc_DownArrow))\r
3460                 {\r
3461                         USL_FindRect(userect,motion_None,motion_Down);\r
3462                         buttondown = false;\r
3463                         IN_ClearKey(sc_DownArrow);\r
3464                 }\r
3465                 else if (IN_KeyDown(sc_LeftArrow))\r
3466                 {\r
3467                         USL_FindRect(userect,motion_Left,motion_None);\r
3468                         buttondown = false;\r
3469                         IN_ClearKey(sc_LeftArrow);\r
3470                 }\r
3471                 else if (IN_KeyDown(sc_RightArrow))\r
3472                 {\r
3473                         USL_FindRect(userect,motion_Right,motion_None);\r
3474                         buttondown = false;\r
3475                         IN_ClearKey(sc_RightArrow);\r
3476                 }\r
3477                 else if\r
3478                 (\r
3479                         IN_KeyDown(c = sc_Return)\r
3480                 ||      IN_KeyDown(c = KbdDefs[0].button0)\r
3481                 ||      IN_KeyDown(c = KbdDefs[0].button1)\r
3482                 )\r
3483                 {\r
3484                         IN_ClearKey(c);\r
3485                         if (inrect)\r
3486                         {\r
3487                                 ip = &TheItems[hiti][hitn];\r
3488 \r
3489                                 if ((ip->type == uii_Button) && !(ip->sel & ui_Disabled))\r
3490                                 {\r
3491                                         lasttime = TimeCount;\r
3492 \r
3493                                         ip->sel |= ui_Selected;\r
3494                                         USL_DrawItem(hiti,hitn);\r
3495                                         VW_UpdateScreen();\r
3496 \r
3497                                         while (TimeCount - lasttime < TickBase / 4)\r
3498                                                 ;\r
3499                                         lasttime = TimeCount;\r
3500 \r
3501                                         ip->sel &= ~ui_Selected;\r
3502                                         USL_DrawItem(hiti,hitn);\r
3503                                         VW_UpdateScreen();\r
3504 \r
3505                                         while (TimeCount - lasttime < TickBase / 4)\r
3506                                                 ;\r
3507                                 }\r
3508 \r
3509                                 USL_DoHit(hiti,hitn);\r
3510                         }\r
3511                 }\r
3512                 else if (USL_CheckScan(&i,&n))\r
3513                         ;\r
3514                 else if (buttondown && inrect && USL_TrackItem(hiti,hitn))\r
3515                         USL_DoHit(hiti,hitn);\r
3516 \r
3517                 if (LastScan == sc_Escape)\r
3518                 {\r
3519                         IN_ClearKey(sc_Escape);\r
3520                         done = true;\r
3521                 }\r
3522 \r
3523                 if (QuitToDos)\r
3524                         done = true;\r
3525 \r
3526                 if ((lastx != CursorX) || (lasty != CursorY))\r
3527                 {\r
3528                         lastx = CursorX;\r
3529                         lasty = CursorY;\r
3530                         lasttime = TimeCount;\r
3531                 }\r
3532                 if (TimeCount - lasttime > TickBase * 10)\r
3533                 {\r
3534                         if (((TimeCount - lasttime) / TickBase) & 2)\r
3535                                 fontcolor = F_SECONDCOLOR;\r
3536                         USL_ShowHelp("Press F1 for Help");\r
3537                         fontcolor = F_BLACK;\r
3538                 }\r
3539         }\r
3540 \r
3541         US_ShutCursor();\r
3542 \r
3543         USL_TearDownCtlPanel();\r
3544 \r
3545         if (restartgame && USL_ResetGame)\r
3546                 USL_ResetGame();\r
3547 \r
3548         if (QuitToDos)\r
3549         {\r
3550                 if (tedlevel)\r
3551                         TEDDeath();\r
3552                 else\r
3553                 {\r
3554                         US_CenterWindow(20,3);\r
3555                         fontcolor = F_SECONDCOLOR;\r
3556                         US_PrintCentered("Now Exiting to DOS...");\r
3557                         fontcolor = F_BLACK;\r
3558                         VW_UpdateScreen();\r
3559                         Quit(nil);\r
3560                 }\r
3561         }\r
3562 \r
3563         CA_DownLevel();\r
3564 }\r
3565 \r
3566 //      High score routines\r
3567 \r
3568 ///////////////////////////////////////////////////////////////////////////\r
3569 //\r
3570 //      US_DisplayHighScores() - Assumes that double buffering has been started.\r
3571 //              If passed a -1 will just display the high scores, but if passed\r
3572 //              a non-negative number will display that entry in red and let the\r
3573 //              user type in a name\r
3574 //\r
3575 ///////////////////////////////////////////////////////////////////////////\r
3576 void\r
3577 US_DisplayHighScores(int which)\r
3578 {\r
3579         char            buffer[16],*str;\r
3580         word            i,\r
3581                                 w,h,\r
3582                                 x,y;\r
3583         HighScore       *s;\r
3584 \r
3585         US_CenterWindow(30,MaxScores + (MaxScores / 2));\r
3586 \r
3587         x = WindowX + (WindowW / 2);\r
3588         US_Print(" Name");\r
3589         PrintX = x + 20;\r
3590         US_Print("Score");\r
3591         PrintX = x + 60;\r
3592         US_Print("Done\n\n");\r
3593         PrintY -= 3;\r
3594 \r
3595         for (i = WindowX;i < WindowX + WindowW;i += 8)\r
3596                 VWB_DrawTile8M(i,WindowY + 8,10);\r
3597         VWB_DrawTile8M(WindowX - 8,WindowY + 8,9);\r
3598         VWB_DrawTile8M(WindowX + WindowW,WindowY + 8,11);\r
3599 \r
3600         for (i = 0,s = Scores;i < MaxScores;i++,s++)\r
3601         {\r
3602                 fontcolor = (i == which)? F_SECONDCOLOR : F_BLACK;\r
3603 \r
3604                 if (i != which)\r
3605                 {\r
3606                         US_Print(" ");\r
3607                         if (strlen(s->name))\r
3608                                 US_Print(s->name);\r
3609                         else\r
3610                                 US_Print("-");\r
3611                 }\r
3612                 else\r
3613                         y = PrintY;\r
3614 \r
3615                 PrintX = x + (7 * 8);\r
3616                 ultoa(s->score,buffer,10);\r
3617                 for (str = buffer;*str;str++)\r
3618                         *str = *str + (129 - '0');      // Used fixed-width numbers (129...)\r
3619                 USL_MeasureString(buffer,&w,&h);\r
3620                 PrintX -= w;\r
3621                 US_Print(buffer);\r
3622 \r
3623                 PrintX = x + 60;\r
3624                 if (s->completed)\r
3625                         US_PrintUnsigned(s->completed);\r
3626                 else\r
3627                         US_Print("-");\r
3628 \r
3629                 US_Print("\n");\r
3630         }\r
3631 \r
3632         if (which != -1)\r
3633         {\r
3634                 fontcolor = F_SECONDCOLOR;\r
3635                 PrintY = y;\r
3636                 PrintX = WindowX;\r
3637                 US_Print(" ");\r
3638                 strcpy(Scores[which].name,"");\r
3639                 US_LineInput(PrintX,PrintY,Scores[which].name,nil,true,MaxHighName,\r
3640                                                 (WindowW / 2) - 8);\r
3641         }\r
3642         fontcolor = F_BLACK;\r
3643 \r
3644         VW_UpdateScreen();\r
3645 }\r
3646 \r
3647 ///////////////////////////////////////////////////////////////////////////\r
3648 //\r
3649 //      US_CheckHighScore() - Checks gamestate to see if the just-ended game\r
3650 //              should be entered in the high score list. If so, lets the user\r
3651 //              enter their name\r
3652 //\r
3653 ///////////////////////////////////////////////////////////////////////////\r
3654 void\r
3655 US_CheckHighScore(long score,word other)\r
3656 {\r
3657         word            i,j,\r
3658                                 n;\r
3659         HighScore       myscore;\r
3660 \r
3661         strcpy(myscore.name,"");\r
3662         myscore.score = score;\r
3663         myscore.completed = other;\r
3664 \r
3665         for (i = 0,n = -1;i < MaxScores;i++)\r
3666         {\r
3667                 if\r
3668                 (\r
3669                         (myscore.score > Scores[i].score)\r
3670                 ||      (\r
3671                                 (myscore.score == Scores[i].score)\r
3672                         &&      (myscore.completed > Scores[i].completed)\r
3673                         )\r
3674                 )\r
3675                 {\r
3676                         for (j = MaxScores;--j > i;)\r
3677                                 Scores[j] = Scores[j - 1];\r
3678                         Scores[i] = myscore;\r
3679 \r
3680                         n = i;\r
3681                         HighScoresDirty = true;\r
3682                         break;\r
3683                 }\r
3684         }\r
3685 \r
3686         VW_InitDoubleBuffer();\r
3687         VWB_Bar(0,0,MaxX,MaxY,FIRSTCOLOR);\r
3688 \r
3689         US_DisplayHighScores(n);\r
3690         IN_UserInput(5 * TickBase,false);\r
3691 }\r