CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

LOADDLG.CPP (27625B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c\vcs\code\loaddlg.cpv   2.18   16 Oct 1995 16:51:18   JOE_BOSTIC  $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : LOADDLG.CPP                                                  *
     24  *                                                                                             *
     25  *                   Programmer : Maria Legg, Joe Bostic, Bill Randolph                        *
     26  *                                                                                             *
     27  *                   Start Date : March 19, 1995                                               *
     28  *                                                                                             *
     29  *                  Last Update : June 25, 1995 [JLB]                                          *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   LoadOptionsClass::Clear_List -- clears the list box & Files arrays                        *
     34  *   LoadOptionsClass::Compare -- for qsort                                                    *
     35  *   LoadOptionsClass::Fill_List -- fills the list box & GameNum arrays                        *
     36  *   LoadOptionsClass::LoadOptionsClass -- class constructor                                   *
     37  *   LoadOptionsClass::Num_From_Ext -- clears the list box & GameNum arrays                    *
     38  *   LoadOptionsClass::Process -- main processing routine                                      *
     39  *   LoadOptionsClass::~LoadOptionsClass -- class destructor                                   *
     40  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     41 
     42 #include "function.h"
     43 #include <io.h>				// for unlink
     44 
     45 
     46 /***********************************************************************************************
     47  * LoadOptionsClass::LoadOptionsClass -- class constructor                                     *
     48  *                                                                                             *
     49  * INPUT:                                                                                      *
     50  *      style      style for this load/save dialog (LOAD/SAVE/DELETE)                          *
     51  *                                                                                             *
     52  * OUTPUT:                                                                                     *
     53  *      none.                                                                                  *
     54  *                                                                                             *
     55  * WARNINGS:                                                                                   *
     56  *      none.                                                                                  *
     57  *                                                                                             *
     58  * HISTORY:                                                                                    *
     59  *   02/14/1995 BR : Created.                                                                  *
     60  *=============================================================================================*/
     61 LoadOptionsClass::LoadOptionsClass(LoadStyleType style)
     62 {
     63 	Style = style;
     64 	Files.Clear();
     65 }
     66 
     67 
     68 /***********************************************************************************************
     69  * LoadOptionsClass::~LoadOptionsClass -- class destructor                                     *
     70  *                                                                                             *
     71  * INPUT:                                                                                      *
     72  *      none.                                                                                  *
     73  *                                                                                             *
     74  * OUTPUT:                                                                                     *
     75  *      none.                                                                                  *
     76  *                                                                                             *
     77  * WARNINGS:                                                                                   *
     78  *      none.                                                                                  *
     79  *                                                                                             *
     80  * HISTORY:                                                                                    *
     81  *   02/14/1995 BR : Created.                                                                  *
     82  *=============================================================================================*/
     83 LoadOptionsClass::~LoadOptionsClass()
     84 {
     85 	for (int i = 0; i < Files.Count(); i++) {
     86 		delete Files[i];
     87 	}
     88 	Files.Clear();
     89 }
     90 
     91 
     92 /***********************************************************************************************
     93  * LoadOptionsClass::Process -- main processing routine                                        *
     94  *                                                                                             *
     95  * INPUT:                                                                                      *
     96  *      none.                                                                                  *
     97  *                                                                                             *
     98  * OUTPUT:                                                                                     *
     99  *      false = User cancelled, true = operation completed                                     *
    100  *                                                                                             *
    101  * WARNINGS:                                                                                   *
    102  *      none.                                                                                  *
    103  *                                                                                             *
    104  * HISTORY:                                                                                    *
    105  *   02/14/1995 BR : Created.                                                                  *
    106  *=============================================================================================*/
    107 int LoadOptionsClass::Process(void)
    108 {
    109 	/*
    110 	**	Dialog & button dimensions
    111 	*/
    112 	int factor			= (SeenBuff.Get_Width() == 320) ? 1 : 2;
    113 	int d_dialog_w		= 250 *factor;
    114 	int d_dialog_h		= 156 * factor;
    115 	int d_dialog_x		= (SeenBuff.Get_Width() - d_dialog_w) >> 1;
    116 	int d_dialog_y		= (SeenBuff.Get_Height() - d_dialog_h) >> 1;
    117 	int d_dialog_cx	= d_dialog_x + (d_dialog_w >> 1);
    118 	int d_txt8_h		= 11 * factor;
    119 	int d_margin		= 7 * factor;
    120 
    121 	int d_list_w 		= d_dialog_w - (d_margin * 2);
    122 	int d_list_h 		= 104 * factor;
    123 	int d_list_x 		= d_dialog_x + d_margin;
    124 	int d_list_y 		= d_dialog_y + d_margin + d_txt8_h + d_margin;
    125 
    126 	int d_edit_w 		= d_dialog_w - (d_margin * 2);
    127 	int d_edit_h 		= 13 * factor;
    128 	int d_edit_x 		= d_dialog_x + d_margin;
    129 	int d_edit_y 		= d_list_y + d_list_h - (30 * factor) + d_margin + d_txt8_h;
    130 
    131 #ifdef german
    132 	int d_button_w 	= 50 * factor;
    133 #else
    134 	int d_button_w 	= 40 * factor;
    135 #endif
    136 	int d_button_h 	= 13 * factor;
    137 	int d_button_x 	= d_dialog_cx - d_button_w - d_margin;
    138 	int d_button_y 	= d_dialog_y + d_dialog_h - d_button_h - d_margin;
    139 
    140 #ifdef german
    141 	int d_cancel_w 	= 50 * factor;
    142 #else
    143 	int d_cancel_w 	= 40 * factor;
    144 #endif
    145 	int d_cancel_h 	= 13 * factor;
    146 	int d_cancel_x 	= d_dialog_cx + d_margin;
    147 	int d_cancel_y 	= d_dialog_y + d_dialog_h - d_cancel_h - d_margin;
    148 #if(0)
    149 	enum {
    150 		D_DIALOG_W = 250,											// dialog width
    151 		D_DIALOG_H = 156,											// dialog height
    152 		D_DIALOG_X = ((320 - D_DIALOG_W) / 2),				// centered x-coord
    153 		D_DIALOG_Y = ((200 - D_DIALOG_H) / 2),				// centered y-coord
    154 		D_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2),		// coord of x-center
    155 
    156 		D_TXT8_H = 11,												// ht of 8-pt text
    157 		D_MARGIN = 7,												// margin width/height
    158 
    159 		D_LIST_W = D_DIALOG_W - (D_MARGIN * 2),
    160 		D_LIST_H = 104,
    161 		D_LIST_X = D_DIALOG_X + D_MARGIN,
    162 		D_LIST_Y = D_DIALOG_Y + D_MARGIN + D_TXT8_H + D_MARGIN,
    163 
    164 		D_EDIT_W = D_DIALOG_W - (D_MARGIN * 2),
    165 		D_EDIT_H = 13,
    166 		D_EDIT_X = D_DIALOG_X + D_MARGIN,
    167 		D_EDIT_Y = D_LIST_Y + D_LIST_H - 30 + D_MARGIN + D_TXT8_H,
    168 
    169 #if (GERMAN | FRENCH)
    170 		D_BUTTON_W = 50,
    171 #else
    172 		D_BUTTON_W = 40,
    173 #endif
    174 		D_BUTTON_H = 13,
    175 		D_BUTTON_X = D_DIALOG_CX - D_BUTTON_W - D_MARGIN,
    176 		D_BUTTON_Y = D_DIALOG_Y + D_DIALOG_H - D_BUTTON_H - D_MARGIN,
    177 
    178 #if (GERMAN | FRENCH)
    179 		D_CANCEL_W = 50,//BG:40
    180 #else
    181 		D_CANCEL_W = 40,
    182 #endif
    183 		D_CANCEL_H = 13,
    184 		D_CANCEL_X = D_DIALOG_CX + D_MARGIN,
    185 		D_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - D_CANCEL_H - D_MARGIN,
    186 	};
    187 #endif
    188 	/*
    189 	**	Button enumerations
    190 	*/
    191 	enum {
    192 		BUTTON_LOAD = 100,
    193 		BUTTON_SAVE,
    194 		BUTTON_DELETE,
    195 		BUTTON_CANCEL,
    196 		BUTTON_LIST,
    197 		BUTTON_EDIT,
    198 	};
    199 
    200 	/*
    201 	**	Redraw values: in order from "top" to "bottom" layer of the dialog
    202 	*/
    203 	typedef enum {
    204 		REDRAW_NONE = 0,
    205 		REDRAW_BUTTONS,
    206 		REDRAW_BACKGROUND,
    207 		REDRAW_ALL = REDRAW_BACKGROUND
    208 	} RedrawType;
    209 
    210 	/*
    211 	**	Dialog variables
    212 	*/
    213 	bool cancel = false;						// true = user cancels
    214 	int list_ht = d_list_h;					// adjusted list box height
    215 
    216 	/*
    217 	**	Other Variables
    218 	*/
    219 	int btn_txt;								// text on the 'OK' button
    220 	int btn_id;									// ID of 'OK' button
    221 	int caption;								// dialog caption
    222 	int game_idx = 0;							// index of game to save/load/etc
    223 	int game_num = 0;							// file number of game to load/save/etc
    224 	char game_descr[40] = {0};				// save-game description
    225 	char fname[13];							// for generating filename to delete
    226 
    227 	void const *up_button;
    228 	void const *down_button;
    229 
    230 	if (InMainLoop){
    231 		up_button = Hires_Retrieve("BTN-UP.SHP");
    232 		down_button = Hires_Retrieve("BTN-DN.SHP");
    233 	}else{
    234 		up_button = Hires_Retrieve("BTN-UP2.SHP");
    235 		down_button = Hires_Retrieve("BTN-DN2.SHP");
    236 	}
    237 
    238 	/*
    239 	**	Buttons
    240 	*/
    241 	ControlClass *commands = NULL;		// the button list
    242 
    243  	if (Style == LOAD) {
    244 		btn_txt = TXT_LOAD_BUTTON;
    245 		btn_id = BUTTON_LOAD;
    246 		caption = TXT_LOAD_MISSION;
    247 	} else {
    248 		if (Style == SAVE) {
    249 			btn_txt = TXT_SAVE_BUTTON;
    250 			btn_id = BUTTON_SAVE;
    251 			caption = TXT_SAVE_MISSION;
    252 			list_ht -= 30;
    253 		} else {
    254 			btn_txt = TXT_DELETE_BUTTON;
    255 			btn_id = BUTTON_DELETE;
    256 			caption = TXT_DELETE_MISSION;
    257 		}
    258 	}
    259 
    260 	TextButtonClass button (btn_id, btn_txt, TPF_6PT_GRAD|TPF_CENTER|TPF_NOSHADOW,
    261 		d_button_x, d_button_y, d_button_w);
    262 
    263 	TextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL, TPF_6PT_GRAD|TPF_CENTER|TPF_NOSHADOW,
    264 		d_cancel_x, d_cancel_y, d_cancel_w);
    265 
    266 	ListClass listbtn (BUTTON_LIST, d_list_x, d_list_y, d_list_w, list_ht,
    267 		TPF_6PT_GRAD | TPF_NOSHADOW,
    268 		up_button,
    269 		down_button);
    270 
    271 	EditClass editbtn (BUTTON_EDIT, game_descr, 40, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW,
    272 		d_edit_x, d_edit_y, d_edit_w, -1, EditClass::ALPHANUMERIC);
    273 
    274 	/*
    275 	**	Initialize.
    276 	*/
    277 	Set_Logic_Page(SeenBuff);
    278 
    279 	Fill_List(&listbtn);
    280 
    281 	/*
    282 	**	Do nothing if list is empty.
    283 	*/
    284 	if ((Style == LOAD || Style == WWDELETE) && listbtn.Count()==0) {
    285 		Clear_List(&listbtn);
    286 		CCMessageBox().Process(TXT_NO_SAVES);
    287 		return(false);
    288 	}
    289 
    290 	/*
    291 	**	Create the button list.
    292 	*/
    293 	commands = &button;
    294 	cancelbtn.Add_Tail(*commands);
    295 	listbtn.Add_Tail(*commands);
    296 	if (Style == SAVE) {
    297 		editbtn.Add_Tail(*commands);
    298 		editbtn.Set_Focus();
    299 	}
    300 
    301 	/*
    302 	**	Main Processing Loop.
    303 	*/
    304 	bool firsttime = true;
    305 	bool display = true;
    306 	bool process = true;
    307 	while (process) {
    308 
    309 		/*
    310 		**	Invoke game callback.
    311 		*/
    312 		if (GameToPlay == GAME_NORMAL) {
    313 			Call_Back();
    314 		} else {
    315 			if (Main_Loop()) {
    316 				process = false;
    317 				cancel = true;
    318 			}
    319 		}
    320 
    321 		/*
    322 		** If we have just received input focus again after running in the background then
    323 		** we need to redraw.
    324 		*/
    325 		if (AllSurfaces.SurfacesRestored){
    326 			AllSurfaces.SurfacesRestored=FALSE;
    327 			display=TRUE;
    328 		}
    329 
    330 		/*
    331 		**	Refresh display if needed.
    332 		*/
    333 		if (display) {
    334 
    335 			Hide_Mouse();
    336 			/*
    337 			**	Redraw the map.
    338 			*/
    339 			if (InMainLoop){
    340 				HiddenPage.Clear();
    341 				Map.Flag_To_Redraw(true);
    342 				Map.Render();
    343 			}else{
    344 				HiddenPage.Clear();
    345 				Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
    346 				Blit_Hid_Page_To_Seen_Buff();
    347 			}
    348 
    349 
    350 			/*
    351 			**	Display the dialog box.
    352 			*/
    353 			if (display) {
    354 				Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
    355 				Draw_Caption(caption, d_dialog_x, d_dialog_y, d_dialog_w);
    356 
    357 				if (Style == SAVE) {
    358 					Fancy_Text_Print(TXT_MISSION_DESCRIPTION, d_dialog_cx,
    359 						d_edit_y - d_txt8_h, CC_GREEN, TBLACK, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_CENTER | TPF_NOSHADOW);
    360 				}
    361 			}
    362 
    363 			/*
    364 			**	Redraw the buttons.
    365 			*/
    366 			if (display) {
    367 				commands->Flag_List_To_Redraw();
    368 			}
    369 			Show_Mouse();
    370 			display = false;
    371 		}
    372 
    373 		/*
    374 		**	Get user input.
    375 		*/
    376 		KeyNumType input = commands->Input();
    377 
    378 		/*
    379 		**	The first time through the processing loop, set the edit
    380 		**	gadget to have the focus if this is the save dialog. The
    381 		**	focus must be set here since the gadget list has changed
    382 		**	and this change will cause any previous focus setting to be
    383 		**	cleared by the input processing routine.
    384 		*/
    385 		if (firsttime && Style == SAVE) {
    386 			firsttime = false;
    387 			editbtn.Set_Focus();
    388 			editbtn.Flag_To_Redraw();
    389 		}
    390 
    391 		/*
    392 		**	If the <RETURN> key was pressed, then default to the appropriate
    393 		**	action button according to the style of this dialog box.
    394 		*/
    395 		if (input == KN_RETURN) {
    396 			switch (Style) {
    397 				case SAVE:
    398 					input = (KeyNumType)(BUTTON_SAVE|KN_BUTTON);
    399 					break;
    400 
    401 				case LOAD:
    402 					input = (KeyNumType)(BUTTON_LOAD|KN_BUTTON);
    403 					break;
    404 
    405 				case WWDELETE:
    406 					input = (KeyNumType)(BUTTON_DELETE|KN_BUTTON);
    407 					break;
    408 			}
    409 		}
    410 
    411 		/*
    412 		**	Process input.
    413 		*/
    414 		switch (input) {
    415 			/*
    416 			** Load: if load fails, present a message, and stay in the dialog
    417 			** to allow the user to try another game
    418 			*/
    419 			case (BUTTON_LOAD | KN_BUTTON):
    420 				game_idx = listbtn.Current_Index();
    421 				game_num = Files[game_idx]->Num;
    422 				if (Files[game_idx]->Valid) {
    423 					CCMessageBox().Process(TXT_LOADING, TXT_NONE);
    424 					if (!Load_Game(game_num)) {
    425 						CCMessageBox().Process(TXT_ERROR_LOADING_GAME);
    426 					} else {
    427 						Hide_Mouse();
    428 						VisiblePage.Clear();
    429 						Set_Palette(GamePalette);
    430 						Show_Mouse();
    431 						process = false;
    432 					}
    433 				} else {
    434 					CCMessageBox().Process(TXT_OBSOLETE_SAVEGAME);
    435 				}
    436 				break;
    437 
    438 			/*
    439 			** Save: Save the game & exit the dialog
    440 			*/
    441 			case (BUTTON_SAVE | KN_BUTTON):
    442 				if (!strlen(game_descr)) {
    443 					CCMessageBox().Process(TXT_MUSTENTER_DESCRIPTION);
    444 					firsttime = true;
    445 					display = true;
    446 					break;
    447 				}
    448 				game_idx = listbtn.Current_Index();
    449 				if (Disk_Space_Available() < SAVE_GAME_DISK_SPACE && game_idx == 0) {
    450 //					CCMessageBox().Process("Insuficent disk space to save a game.  Please delete a previous save to free up some disk space and try again.");
    451 					CCMessageBox().Process(TXT_SPACE_CANT_SAVE);
    452 					firsttime = true;
    453 					display = true;
    454 					break;
    455 				}
    456 
    457 				game_num = Files[game_idx]->Num;
    458 				if (!Save_Game(game_num,game_descr)) {
    459 					CCMessageBox().Process(TXT_ERROR_SAVING_GAME);
    460 				} else {
    461 					CCMessageBox().Process(TXT_GAME_WAS_SAVED, TXT_NONE, TXT_NONE);
    462 				}
    463 				process = false;
    464 				break;
    465 
    466 			/*
    467 			** Delete: delete the file & stay in the dialog, to allow the user
    468 			** to delete multiple files.
    469 			*/
    470 			case (BUTTON_DELETE | KN_BUTTON):
    471 				game_idx = listbtn.Current_Index();
    472 				game_num = Files[game_idx]->Num;
    473 				if (CCMessageBox().Process(TXT_DELETE_FILE_QUERY,TXT_YES,TXT_NO)==0) {
    474 					sprintf(fname,"SAVEGAME.%03d",game_num);
    475 					unlink(fname);
    476 					Clear_List(&listbtn);
    477 					Fill_List(&listbtn);
    478 					if (listbtn.Count() == 0) {
    479 						process = false;
    480 					}
    481 				}
    482 				display = true;
    483 				break;
    484 
    485 			/*
    486 			** If the user clicks on the list, see if the there is a new current
    487 			** item; if so, and if we're in SAVE mode, copy the list item into
    488 			** the save-game description field.
    489 			*/
    490 			case (BUTTON_LIST | KN_BUTTON):
    491 				if (Style != SAVE) {
    492 					break;
    493 				}
    494 
    495 				if (listbtn.Count() && listbtn.Current_Index() != game_idx) {
    496 					game_idx = listbtn.Current_Index();
    497 					/*
    498 					** Copy the game's description, UNLESS it's the empty slot; if
    499 					** it is, set the edit buffer to empty.
    500 					*/
    501 					if (game_idx != 0) {
    502 						strcpy(game_descr,listbtn.Get_Item(game_idx));
    503 					} else {
    504 						game_descr[0] = 0;
    505 					}
    506 					editbtn.Set_Text(game_descr,40);
    507 				}
    508 				break;
    509 
    510 			/*
    511 			** ESC/Cancel: break
    512 			*/
    513 			case (KN_ESC):
    514 			case (BUTTON_CANCEL | KN_BUTTON):
    515 				cancel = true;
    516 				process = false;
    517 				break;
    518 
    519 			default:
    520 				break;
    521 		}
    522 	}
    523 
    524 	Clear_List(&listbtn);
    525 
    526 	if (cancel) return(false);
    527 
    528 	return(true);
    529 }
    530 
    531 
    532 /***********************************************************************************************
    533  * LoadOptionsClass::Clear_List -- clears the list box & Files arrays                          *
    534  *                                                                                             *
    535  * This step is essential, because it frees all the strings allocated for list items.          *
    536  *                                                                                             *
    537  * INPUT:                                                                                      *
    538  *      none.                                                                                  *
    539  *                                                                                             *
    540  * OUTPUT:                                                                                     *
    541  *      none.                                                                                  *
    542  *                                                                                             *
    543  * WARNINGS:                                                                                   *
    544  *      none.                                                                                  *
    545  *                                                                                             *
    546  * HISTORY:                                                                                    *
    547  *   02/14/1995 BR : Created.                                                                  *
    548  *=============================================================================================*/
    549 void LoadOptionsClass::Clear_List(ListClass *list)
    550 {
    551 	/*
    552 	** For every item in the list, free its buffer & remove it from the list.
    553 	*/
    554 	int j = list->Count();
    555 	int i;
    556 	for (i = 0; i < j; i++) {
    557 		list->Remove_Item(list->Get_Item(0));
    558 	}
    559 
    560 	/*
    561 	** Clear the array of game numbers
    562 	*/
    563 	for (i = 0; i < Files.Count(); i++) {
    564 		delete Files[i];
    565 	}
    566 	Files.Clear();
    567 }
    568 
    569 
    570 /***********************************************************************************************
    571  * LoadOptionsClass::Fill_List -- fills the list box & GameNum arrays                          *
    572  *                                                                                             *
    573  * INPUT:                                                                                      *
    574  *      none.                                                                                  *
    575  *                                                                                             *
    576  * OUTPUT:                                                                                     *
    577  *      none.                                                                                  *
    578  *                                                                                             *
    579  * WARNINGS:                                                                                   *
    580  *      none.                                                                                  *
    581  *                                                                                             *
    582  * HISTORY:                                                                                    *
    583  *   02/14/1995 BR : Created.                                                                  *
    584  *   06/25/1995 JLB : Shows which saved games are "(old)".                                     *
    585  *=============================================================================================*/
    586 void LoadOptionsClass::Fill_List(ListClass *list)
    587 {
    588 //PG_TO_FIX
    589 #if (0)
    590 	FileEntryClass *fdata;	// for adding entries to 'Files'
    591 	char descr[DESCRIP_MAX];
    592 	unsigned scenario;			// scenario #
    593 	HousesType house;				// house
    594 	struct find_t ff;		// for _dos_findfirst
    595 	int id;
    596 
    597 	/*
    598 	** Make sure the list is empty
    599 	*/
    600 	Clear_List(list);
    601 
    602 	/*
    603 	** Add the Empty Slot entry
    604 	*/
    605 	if (Style == SAVE) {
    606 		fdata = new FileEntryClass;
    607 		strcpy(fdata->Descr,Text_String(TXT_EMPTY_SLOT));
    608 		fdata->DateTime = 0xffffffff;	// will always be first
    609 		Files.Add(fdata);
    610 	}
    611 
    612 	/*
    613 	** Find all savegame files
    614 	*/
    615 	int rc = _dos_findfirst("SAVEGAME.*", _A_NORMAL, &ff);
    616 
    617 	while (!rc) {
    618 		/*
    619 		** Extract the game ID from the filename
    620 		*/
    621 		id = Num_From_Ext(ff.name);
    622 
    623 		/*
    624 		** get the game's info; if success, add it to the list
    625 		*/
    626 		bool ok = Get_Savefile_Info(id, descr, &scenario, &house);
    627 
    628 		fdata = new FileEntryClass;
    629 
    630 		fdata->Descr[0] = '\0';
    631 		if (!ok) strcpy(fdata->Descr, Text_String(TXT_OLD_GAME));
    632 		strncat(fdata->Descr, descr, (sizeof(fdata->Descr)-strlen(fdata->Descr))-1);
    633 		fdata->Valid = ok;
    634 		fdata->Scenario = scenario;
    635 		fdata->House = house;
    636 		fdata->Num = id;
    637 		fdata->DateTime = (((unsigned long)ff.wr_date) << 16) | (unsigned long)ff.wr_time;
    638 		Files.Add(fdata);
    639 
    640 		/*
    641 		** Find the next file
    642 		*/
    643 		rc = _dos_findnext(&ff);
    644 	}
    645 
    646 	/*
    647 	** If saving a game, determine a unique file ID for the empty slot
    648 	*/
    649 	if (Style == SAVE) {
    650 		/*
    651 		** Find an un-used number to associate with the Empty Slot by looking in
    652 		** GameNum for each number from 0 to 'N', where 'N' is the # of entries
    653 		** in the list; if any number isn't found, use that number; otherwise,
    654 		** use 'N + 1'.
    655 		*/
    656 		for (int i = 0; i < Files.Count(); i++) {		// i = the # we're searching for
    657 			id = -1;											// mark as 'not found'
    658 			for (int j = 0; j < Files.Count(); j++) {	// loop through all game ID's
    659 				if (Files[j]->Num==i) {					// if found, mark as found
    660 					id = j;
    661 					break;
    662 				}
    663 			}
    664 			if (id == -1)	break;							// if ID not found, use this one
    665 		}
    666 
    667 		Files[0]->Num = i;								// set the empty slot's ID
    668 	}
    669 
    670 	/*
    671 	** Now sort the list in order of Date/Time (newest first, oldest last)
    672 	*/
    673 	qsort((void *)(&Files[0]), Files.Count(), sizeof(class FileEntryClass *), LoadOptionsClass::Compare);
    674 
    675 	/*
    676 	** Now add every file's name to the list box
    677 	*/
    678 	for (int i = 0; i < Files.Count(); i++) {
    679 		list->Add_Item(Files[i]->Descr);
    680 	}
    681 #endif
    682 }
    683 
    684 
    685 /***********************************************************************************************
    686  * LoadOptionsClass::Num_From_Ext -- clears the list box & GameNum arrays                      *
    687  *                                                                                             *
    688  * INPUT:                                                                                      *
    689  *      fname      filename to parse                                                           *
    690  *                                                                                             *
    691  * OUTPUT:                                                                                     *
    692  *      File number for this name.                                                             *
    693  *                                                                                             *
    694  * WARNINGS:                                                                                   *
    695  *      none.                                                                                  *
    696  *                                                                                             *
    697  * HISTORY:                                                                                    *
    698  *   02/14/1995 BR : Created.                                                                  *
    699  *=============================================================================================*/
    700 int LoadOptionsClass::Num_From_Ext(char *fname)
    701 {
    702 	char ext[_MAX_EXT];
    703 
    704 	_splitpath(fname, NULL, NULL, NULL, ext);
    705 	int num = atoi(ext + 1);		// skip the '.'
    706 	return(num);
    707 }
    708 
    709 
    710 /***********************************************************************************************
    711  * LoadOptionsClass::Compare -- for qsort                                                      *
    712  *                                                                                             *
    713  * INPUT:                                                                                      *
    714  *      p1,p2      ptrs to elements to compare                                                 *
    715  *                                                                                             *
    716  * OUTPUT:                                                                                     *
    717  *      0 = same, -1 = (*p1) goes BEFORE (*p2), 1 = (*p1) goes AFTER (*p2)                     *
    718  *                                                                                             *
    719  * WARNINGS:                                                                                   *
    720  *      none.                                                                                  *
    721  *                                                                                             *
    722  * HISTORY:                                                                                    *
    723  *   02/14/1995 BR : Created.                                                                  *
    724  *=============================================================================================*/
    725 int LoadOptionsClass::Compare(const void *p1, const void *p2)
    726 {
    727 	class FileEntryClass *fe1,*fe2;
    728 
    729 	fe1 = *((class FileEntryClass **)p1);
    730 	fe2 = *((class FileEntryClass **)p2);
    731 
    732 	if (fe1->DateTime > fe2->DateTime) return(-1);
    733 	if (fe1->DateTime < fe2->DateTime) return(1);
    734 	return(0);
    735 }