dlgloadspgame.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** 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 ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Combat *
  23. * *
  24. * $Archive:: /Commando/Code/Commando/dlgloadspgame.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 2/23/02 12:05p $*
  29. * *
  30. * $Revision:: 29 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "dlgloadspgame.h"
  36. #include "listctrl.h"
  37. #include "dialogresource.h"
  38. #include "gamedata.h"
  39. #include "gamemode.h"
  40. #include "gameinitmgr.h"
  41. #include "savegame.h"
  42. #include "devoptions.h"
  43. #include "translatedb.h"
  44. #include "string_ids.h"
  45. #include "campaign.h"
  46. #include "dialogmgr.h"
  47. #include "renegadedialogmgr.h"
  48. #include "god.h"
  49. #include "registry.h"
  50. #include "_globals.h"
  51. #include "dialogtests.h"
  52. #include "specialbuilds.h"
  53. ////////////////////////////////////////////////////////////////
  54. // Local constants
  55. ////////////////////////////////////////////////////////////////
  56. static enum
  57. {
  58. MBEVENT_DELETE_PROMPT = 1,
  59. };
  60. static enum
  61. {
  62. COL_DATE = 0,
  63. COL_TIME,
  64. COL_NAME
  65. };
  66. ////////////////////////////////////////////////////////////////
  67. // Static member initialization
  68. ////////////////////////////////////////////////////////////////
  69. LoadSPGameMenuClass * LoadSPGameMenuClass::_TheInstance = NULL;
  70. ////////////////////////////////////////////////////////////////
  71. //
  72. // On_Init_Dialog
  73. //
  74. ////////////////////////////////////////////////////////////////
  75. void
  76. LoadSPGameMenuClass::On_Init_Dialog (void)
  77. {
  78. //
  79. // Get a pointer to the list control
  80. //
  81. ListCtrlClass *list_ctrl = (ListCtrlClass *)Get_Dlg_Item (IDC_LOAD_GAME_LIST_CTRL);
  82. if (list_ctrl != NULL) {
  83. //
  84. // Configure the columns
  85. //
  86. list_ctrl->Add_Column (TRANSLATE (IDS_MENU_TIME), 0.25F, Vector3 (1, 1, 1));
  87. list_ctrl->Add_Column (TRANSLATE (IDS_MENU_DATE), 0.25F, Vector3 (1, 1, 1));
  88. list_ctrl->Add_Column (TRANSLATE (IDS_MENU_TEXT177), 0.5F, Vector3 (1, 1, 1));
  89. //
  90. // Build the lists
  91. //
  92. int start_index = 0;
  93. //start_index = Build_List ("data\\*.mix", start_index);
  94. //start_index = Build_List ("data\\m??_*.mix", start_index);
  95. StringClass file_filter;
  96. file_filter = "data\\m*.mix";
  97. #ifdef WWDEBUG
  98. if (cDevOptions::FilterLevelFiles.Is_False()) {
  99. file_filter = "data\\*.mix";
  100. }
  101. #endif // WWDEBUG
  102. start_index = Build_List (file_filter, start_index);
  103. Build_List ("data\\save\\*.sav", start_index);
  104. //
  105. // Sort the list and select the first entry
  106. //
  107. list_ctrl->Sort (LoadListSortCallback, MAKELONG (CurrSortCol, IsSortAscending));
  108. list_ctrl->Set_Curr_Sel (0);
  109. Update_Button_State ();
  110. //
  111. // Update the sort marker
  112. //
  113. ListCtrlClass::SORT_TYPE type = IsSortAscending ? ListCtrlClass::SORT_ASCENDING : ListCtrlClass::SORT_DESCENDING;
  114. list_ctrl->Set_Sort_Designator (CurrSortCol, type);
  115. }
  116. MenuDialogClass::On_Init_Dialog ();
  117. return ;
  118. }
  119. ////////////////////////////////////////////////////////////////
  120. //
  121. // Build_List
  122. //
  123. ////////////////////////////////////////////////////////////////
  124. int
  125. LoadSPGameMenuClass::Build_List (const char *search_string, int start_index)
  126. {
  127. ListCtrlClass *list_ctrl = (ListCtrlClass *)Get_Dlg_Item (IDC_LOAD_GAME_LIST_CTRL);
  128. WIN32_FIND_DATA find_info = { 0 };
  129. BOOL keep_going = TRUE;
  130. HANDLE file_find = NULL;
  131. //
  132. // Get the path to the directory we'll be searching
  133. //
  134. StringClass path_name;
  135. const char *search_dir = ::strrchr (search_string, '\\');
  136. if (search_dir != NULL) {
  137. //
  138. // Strip the search mask from the string
  139. //
  140. path_name = search_string;
  141. int len = ::strlen (search_string);
  142. int index = search_dir - search_string;
  143. path_name.Erase (index, len - index);
  144. }
  145. //
  146. // Build a list of all the saved games we know about
  147. //
  148. int index = start_index;
  149. for (file_find = ::FindFirstFile (search_string, &find_info);
  150. (file_find != INVALID_HANDLE_VALUE) && keep_going;
  151. keep_going = ::FindNextFile (file_find, &find_info))
  152. {
  153. // if (1 || Is_Game_Allowed( find_info.cFileName ) ) {
  154. if ( Is_Game_Allowed( find_info.cFileName ) ) {
  155. //
  156. // Get the user description and map name from the file
  157. //
  158. WideStringClass description;
  159. WideStringClass map_name;
  160. SaveGameManager::Smart_Peek_Description (find_info.cFileName, description, map_name);
  161. //
  162. // Default to the map name if we don't have a description
  163. //
  164. if (description.Is_Empty ()) {
  165. description = map_name;
  166. }
  167. // Get rank
  168. int rank = Get_Game_Rank( find_info.cFileName );
  169. // Modify description for games with a rank
  170. if ( rank ) {
  171. int mission = atoi( find_info.cFileName+1 );
  172. switch ( mission ) {
  173. case 0: description = TRANSLATE( IDS_LoadScreen_Tutorial_Item_00_Title ); break;
  174. case 1: description = TRANSLATE( IDS_Enc_Miss_Title_M01_01 ); break;
  175. case 2: description = TRANSLATE( IDS_Enc_Miss_Title_M02_01 ); break;
  176. case 3: description = TRANSLATE( IDS_Enc_Miss_Title_M03_01 ); break;
  177. case 4: description = TRANSLATE( IDS_Enc_Miss_Title_M04_01 ); break;
  178. case 5: description = TRANSLATE( IDS_Enc_Miss_Title_M05_01 ); break;
  179. case 6: description = TRANSLATE( IDS_Enc_Miss_Title_M06_01 ); break;
  180. case 7: description = TRANSLATE( IDS_Enc_Miss_Title_M07_01 ); break;
  181. case 8: description = TRANSLATE( IDS_Enc_Miss_Title_M08_01 ); break;
  182. case 9: description = TRANSLATE( IDS_Enc_Miss_Title_M09_01 ); break;
  183. case 10: description = TRANSLATE( IDS_Enc_Miss_Title_M10_01 ); break;
  184. case 11: description = TRANSLATE( IDS_Enc_Miss_Title_M11_01 ); break;
  185. case 13: description = TRANSLATE( IDS_LoadScreen_MX0_Title ); break;
  186. }
  187. }
  188. //
  189. // Get the time this file was last written
  190. //
  191. SYSTEMTIME system_time = { 0 };
  192. FILETIME local_time = { 0 };
  193. ::FileTimeToLocalFileTime (&find_info.ftLastWriteTime, &local_time);
  194. ::FileTimeToSystemTime (&local_time, &system_time);
  195. //
  196. // Build the time and date strings
  197. //
  198. WideStringClass time_string;
  199. WideStringClass date_string;
  200. time_string.Format (L"%d:%02d:%02d", system_time.wHour, system_time.wMinute, system_time.wSecond);
  201. date_string.Format (L"%d/%d/%d", system_time.wMonth, system_time.wDay, system_time.wYear);
  202. //
  203. // Add this entry to the list control
  204. //
  205. int item_index = list_ctrl->Insert_Entry (index ++, time_string);
  206. if (item_index >= 0) {
  207. list_ctrl->Set_Entry_Text (item_index, 1, date_string);
  208. list_ctrl->Set_Entry_Text (item_index, 2, description);
  209. for ( int i = 0; i < rank; i++ ) {
  210. list_ctrl->Add_Icon (item_index, 2, "IF_LRGSTAR.TGA");
  211. }
  212. //
  213. // Build the full path to the file
  214. //
  215. StringClass file_path = path_name;
  216. file_path += "\\";
  217. file_path += find_info.cFileName;
  218. list_ctrl->Set_Entry_Data (item_index, 0, (uint32)new FILETIME(local_time));
  219. list_ctrl->Set_Entry_Data (item_index, 1, (uint32)new StringClass(file_path));
  220. list_ctrl->Set_Entry_Data (item_index, 2, (uint32)new StringClass(find_info.cFileName));
  221. }
  222. }
  223. }
  224. if (file_find != INVALID_HANDLE_VALUE) {
  225. ::FindClose (file_find);
  226. }
  227. return index;
  228. }
  229. ////////////////////////////////////////////////////////////////
  230. //
  231. // Is_Game_Allowed
  232. //
  233. ////////////////////////////////////////////////////////////////
  234. bool
  235. LoadSPGameMenuClass::Is_Game_Allowed
  236. (
  237. const char * filename
  238. )
  239. {
  240. // Determine if this game is valid to present in the load game menu
  241. // All save games (.SAV) are allowed
  242. if ( ::strlen( filename ) > 4 && ::stricmp( filename + (::strlen( filename ) - 4), ".SAV" ) == 0 ) {
  243. return true;
  244. }
  245. // All save games not in the form Mxx.MIX are allowed
  246. if ( ( ::strlen( filename ) != 7 ) ||
  247. ( ::stricmp( filename + (::strlen( filename ) - 4), ".MIX" ) != 0 ) ||
  248. ( ::toupper( *filename ) != 'M' ) ) {
  249. return true;
  250. }
  251. // if we have a rank, allow it
  252. return ( Get_Game_Rank( filename ) > 0 );
  253. }
  254. ////////////////////////////////////////////////////////////////
  255. //
  256. // Get_Game_Rank
  257. //
  258. ////////////////////////////////////////////////////////////////
  259. int
  260. LoadSPGameMenuClass::Get_Game_Rank
  261. (
  262. const char * filename
  263. )
  264. {
  265. // Strip extention (so we can pass in .MIX, or .LSD
  266. StringClass name = filename;
  267. if ( name.Get_Length() > 4 ) {
  268. name.Erase( name.Get_Length()-4, 4 );
  269. }
  270. RegistryClass * registry = new RegistryClass( APPLICATION_SUB_KEY_NAME_MISSION_RANKS );
  271. WWASSERT( registry );
  272. int rank = 0;
  273. if ( registry->Is_Valid() ) {
  274. rank = registry->Get_Int( name, 0 );
  275. }
  276. delete registry;
  277. return rank;
  278. }
  279. ////////////////////////////////////////////////////////////////
  280. //
  281. // Set_Game_Rank
  282. //
  283. ////////////////////////////////////////////////////////////////
  284. void
  285. LoadSPGameMenuClass::Set_Game_Rank
  286. (
  287. const char * filename,
  288. int rank
  289. )
  290. {
  291. // Strip extention
  292. StringClass name = filename;
  293. if ( name.Get_Length() > 4 ) {
  294. name.Erase( name.Get_Length()-4, 4 );
  295. }
  296. RegistryClass * registry = new RegistryClass( APPLICATION_SUB_KEY_NAME_MISSION_RANKS );
  297. WWASSERT( registry );
  298. if ( registry->Is_Valid() ) {
  299. int old_rank = registry->Get_Int( name, 0 );
  300. // Set to the max of old and rank
  301. if ( old_rank > rank ) {
  302. rank = old_rank;
  303. }
  304. registry->Set_Int( name, rank );
  305. }
  306. delete registry;
  307. }
  308. ////////////////////////////////////////////////////////////////
  309. //
  310. // On_ListCtrl_Column_Click
  311. //
  312. ////////////////////////////////////////////////////////////////
  313. void
  314. LoadSPGameMenuClass::On_ListCtrl_Column_Click
  315. (
  316. ListCtrlClass *list_ctrl,
  317. int ctrl_id,
  318. int col_index
  319. )
  320. {
  321. if (ctrl_id == IDC_LOAD_GAME_LIST_CTRL) {
  322. //
  323. // Determine
  324. //
  325. if (col_index == CurrSortCol) {
  326. IsSortAscending = !IsSortAscending;
  327. } else {
  328. CurrSortCol = col_index;
  329. IsSortAscending = true;
  330. }
  331. //
  332. // Sort the list by the column that was clicked
  333. //
  334. list_ctrl->Sort (LoadListSortCallback, MAKELONG (CurrSortCol, IsSortAscending));
  335. //
  336. // Update the sort marker
  337. //
  338. ListCtrlClass::SORT_TYPE type = IsSortAscending ? ListCtrlClass::SORT_ASCENDING : ListCtrlClass::SORT_DESCENDING;
  339. list_ctrl->Set_Sort_Designator (CurrSortCol, type);
  340. }
  341. return ;
  342. }
  343. ////////////////////////////////////////////////////////////////
  344. //
  345. // On_ListCtrl_Delete_Entry
  346. //
  347. ////////////////////////////////////////////////////////////////
  348. void
  349. LoadSPGameMenuClass::On_ListCtrl_Delete_Entry
  350. (
  351. ListCtrlClass *list_ctrl,
  352. int ctrl_id,
  353. int item_index
  354. )
  355. {
  356. if (ctrl_id == IDC_LOAD_GAME_LIST_CTRL) {
  357. //
  358. // Remove the data we associated with this entry
  359. //
  360. FILETIME *file_time = (FILETIME *)list_ctrl->Get_Entry_Data (item_index, 0);
  361. StringClass *path = (StringClass *)list_ctrl->Get_Entry_Data (item_index, 1);
  362. StringClass *filename = (StringClass *)list_ctrl->Get_Entry_Data (item_index, 2);
  363. list_ctrl->Set_Entry_Data (item_index, 0, 0);
  364. list_ctrl->Set_Entry_Data (item_index, 1, 0);
  365. list_ctrl->Set_Entry_Data (item_index, 2, 0);
  366. //
  367. // Free the data
  368. //
  369. if (file_time != NULL) {
  370. delete file_time;
  371. }
  372. if (path != NULL) {
  373. delete path;
  374. }
  375. if (filename != NULL) {
  376. delete filename;
  377. }
  378. }
  379. return ;
  380. }
  381. ////////////////////////////////////////////////////////////////
  382. //
  383. // LoadListSortCallback
  384. //
  385. ////////////////////////////////////////////////////////////////
  386. int CALLBACK
  387. LoadSPGameMenuClass::LoadListSortCallback (ListCtrlClass *list_ctrl, int item_index1, int item_index2, uint32 user_param)
  388. {
  389. int retval = 0;
  390. //
  391. // Get the sorting params
  392. //
  393. int sort_col_index = LOWORD (user_param);
  394. BOOL sort_ascending = HIWORD (user_param);
  395. if (sort_col_index == 0 || sort_col_index == 1) {
  396. //
  397. // Sort by time
  398. //
  399. FILETIME *file_time1 = (FILETIME *)list_ctrl->Get_Entry_Data (item_index1, 0);
  400. FILETIME *file_time2 = (FILETIME *)list_ctrl->Get_Entry_Data (item_index2, 0);
  401. retval = ::CompareFileTime (file_time1, file_time2);
  402. } else {
  403. //
  404. // Sort by name
  405. //
  406. const WCHAR *name1 = list_ctrl->Get_Entry_Text (item_index1, 2);
  407. const WCHAR *name2 = list_ctrl->Get_Entry_Text (item_index2, 2);
  408. retval = ::wcsicmp (name1, name2);
  409. }
  410. //
  411. // Invert the return value if we are sorting descendingly
  412. //
  413. if (sort_ascending == false) {
  414. retval = -retval;
  415. }
  416. return retval;
  417. }
  418. ////////////////////////////////////////////////////////////////
  419. //
  420. // On_Command
  421. //
  422. ////////////////////////////////////////////////////////////////
  423. void
  424. LoadSPGameMenuClass::On_Command (int ctrl_id, int message_id, DWORD param)
  425. {
  426. switch (ctrl_id)
  427. {
  428. case IDC_LOAD_GAME_BUTTON:
  429. case IDOK:
  430. Load_Game ();
  431. break;
  432. case IDC_DELETE_GAME_BUTTON:
  433. Delete_Game (true);
  434. break;
  435. }
  436. MenuDialogClass::On_Command (ctrl_id, message_id, param);
  437. return ;
  438. }
  439. ////////////////////////////////////////////////////////////////
  440. //
  441. // Load_Game
  442. //
  443. ////////////////////////////////////////////////////////////////
  444. void
  445. LoadSPGameMenuClass::Load_Game (void)
  446. {
  447. #ifndef MULTIPLAYERDEMO
  448. //
  449. // Get a pointer to the list control
  450. //
  451. ListCtrlClass *list_ctrl = (ListCtrlClass *)Get_Dlg_Item (IDC_LOAD_GAME_LIST_CTRL);
  452. if (list_ctrl == NULL) {
  453. return ;
  454. }
  455. #if 0 // MOVED BELOW AND TO DIFFICULTY SELECTION
  456. //
  457. // End the current game before we load the new one
  458. //
  459. if (GameModeManager::Find ("Combat")->Is_Suspended ()) {
  460. GameInitMgrClass::End_Game();
  461. GameModeManager::Safely_Deactivate ();
  462. }
  463. #endif
  464. //
  465. // Get the currently selected entry
  466. //
  467. int item_index = list_ctrl->Get_Curr_Sel ();
  468. if (item_index != -1) {
  469. //
  470. // Get the name of the map
  471. //
  472. StringClass *filename = (StringClass *)list_ctrl->Get_Entry_Data (item_index, 2);
  473. StringClass save_name(filename->Peek_Buffer(),true);
  474. StringClass map_name(0,true);
  475. int mission = 0;
  476. if (SaveGameManager::Peek_Map_Name (save_name, map_name)) {
  477. mission = cGameData::Get_Mission_Number_From_Map_Name( map_name );
  478. } else {
  479. mission = cGameData::Get_Mission_Number_From_Map_Name( save_name );
  480. }
  481. CampaignManager::Select_Backdrop_Number( mission ); // Force default loading screen
  482. bool is_replay = Get_Game_Rank( save_name ) > 0;
  483. if ( is_replay ) {
  484. // if replay
  485. DifficultyMenuClass * dialog = new DifficultyMenuClass();
  486. dialog->Set_Replay( save_name );
  487. dialog->Start_Dialog();
  488. dialog->Release_Ref();
  489. } else {
  490. //
  491. // End the current game before we load the new one
  492. //
  493. if (GameModeManager::Find ("Combat")->Is_Suspended ()) {
  494. GameInitMgrClass::End_Game();
  495. GameModeManager::Safely_Deactivate ();
  496. }
  497. //
  498. // Load the map
  499. //
  500. GameInitMgrClass::Initialize_SP ();
  501. GameInitMgrClass::Start_Game (save_name, -1, 0);
  502. }
  503. }
  504. cGod::Reset_Inventory();
  505. return ;
  506. #endif // !MULTIPLAYERDEMO
  507. }
  508. ////////////////////////////////////////////////////////////////
  509. //
  510. // On_ListCtrl_Sel_Change
  511. //
  512. ////////////////////////////////////////////////////////////////
  513. void
  514. LoadSPGameMenuClass::On_ListCtrl_Sel_Change
  515. (
  516. ListCtrlClass *list_ctrl,
  517. int ctrl_id,
  518. int old_index,
  519. int new_index
  520. )
  521. {
  522. Update_Button_State ();
  523. return ;
  524. }
  525. ////////////////////////////////////////////////////////////////
  526. //
  527. // Update_Button_State
  528. //
  529. ////////////////////////////////////////////////////////////////
  530. void
  531. LoadSPGameMenuClass::Update_Button_State (void)
  532. {
  533. bool enable = false;
  534. //
  535. // Get a pointer to the list control
  536. //
  537. ListCtrlClass *list_ctrl = (ListCtrlClass *)Get_Dlg_Item (IDC_LOAD_GAME_LIST_CTRL);
  538. if (list_ctrl == NULL) {
  539. return ;
  540. }
  541. //
  542. // Get the currently selected entry
  543. //
  544. int item_index = list_ctrl->Get_Curr_Sel ();
  545. if (item_index != -1) {
  546. //
  547. // Get the filename associated with this entry
  548. //
  549. if (list_ctrl->Get_Entry_Data (item_index, 0) != NULL) {
  550. StringClass filename = ((StringClass *)list_ctrl->Get_Entry_Data (item_index, 1))->Peek_Buffer ();
  551. //
  552. // Check to see if this is a saved game or a level file.
  553. //
  554. int len = filename.Get_Length ();
  555. if (len >= 4 && ::lstrcmpi ((filename.Peek_Buffer () + (len - 4)), ".mix") != 0) {
  556. enable = true;
  557. }
  558. }
  559. //
  560. // Change the enable state of the button
  561. //
  562. Get_Dlg_Item (IDC_DELETE_GAME_BUTTON)->Enable (enable);
  563. }
  564. return ;
  565. }
  566. ////////////////////////////////////////////////////////////////
  567. //
  568. // On_ListCtrl_DblClk
  569. //
  570. ////////////////////////////////////////////////////////////////
  571. void
  572. LoadSPGameMenuClass::On_ListCtrl_DblClk
  573. (
  574. ListCtrlClass *list_ctrl,
  575. int ctrl_id,
  576. int item_index
  577. )
  578. {
  579. Load_Game ();
  580. return ;
  581. }
  582. ////////////////////////////////////////////////////////////////
  583. //
  584. // Delete_Game
  585. //
  586. ////////////////////////////////////////////////////////////////
  587. void
  588. LoadSPGameMenuClass::Delete_Game (bool prompt)
  589. {
  590. //
  591. // Get a pointer to the list control
  592. //
  593. ListCtrlClass *list_ctrl = (ListCtrlClass *)Get_Dlg_Item (IDC_LOAD_GAME_LIST_CTRL);
  594. if (list_ctrl == NULL) {
  595. return ;
  596. }
  597. //
  598. // Get the currently selected entry
  599. //
  600. int item_index = list_ctrl->Get_Curr_Sel ();
  601. if (item_index != -1) {
  602. //
  603. // Determine what filename this entry refers to
  604. //
  605. if (list_ctrl->Get_Entry_Data (item_index, 0) != NULL) {
  606. StringClass filename = ((StringClass *)list_ctrl->Get_Entry_Data (item_index, 1))->Peek_Buffer ();
  607. // Never delete .MIX files
  608. int len = filename.Get_Length ();
  609. if (len >= 4 && ::lstrcmpi ((filename.Peek_Buffer () + (len - 4)), ".mix") != 0) {
  610. if (prompt) {
  611. //
  612. // Build a confirmation message to display to the user
  613. //
  614. WideStringClass message;
  615. message.Format (TRANSLATE (IDS_MENU_DELETE_SAVE_MSG),
  616. list_ctrl->Get_Entry_Text (item_index, COL_NAME));
  617. //
  618. // Display a message to the user asking if they really want to do this...
  619. //
  620. DlgMsgBox::DoDialog (TRANSLATE (IDS_MENU_DELETE_SAVE_TITLE), message, DlgMsgBox::YesNo,
  621. this, MBEVENT_DELETE_PROMPT);
  622. } else {
  623. //
  624. // Delete the file and remove its entry from the list
  625. //
  626. if (::DeleteFile (filename) != 0) {
  627. list_ctrl->Delete_Entry (item_index);
  628. }
  629. }
  630. }
  631. }
  632. }
  633. Update_Button_State ();
  634. return ;
  635. }
  636. ////////////////////////////////////////////////////////////////
  637. //
  638. // HandleNotification
  639. //
  640. ////////////////////////////////////////////////////////////////
  641. void
  642. LoadSPGameMenuClass::HandleNotification (DlgMsgBoxEvent &event)
  643. {
  644. if (event.Get_User_Data () == MBEVENT_DELETE_PROMPT) {
  645. //
  646. // The user has confirmed the delete, so delete the file
  647. //
  648. if (event.Event () == DlgMsgBoxEvent::Yes) {
  649. Delete_Game (false);
  650. }
  651. }
  652. return ;
  653. }
  654. ////////////////////////////////////////////////////////////////
  655. //
  656. // Display
  657. //
  658. ////////////////////////////////////////////////////////////////
  659. void
  660. LoadSPGameMenuClass::Display (void)
  661. {
  662. #ifndef MULTIPLAYERDEMO
  663. //
  664. // Create the dialog if necessary, otherwise simply bring it to the front
  665. //
  666. if (_TheInstance == NULL) {
  667. START_DIALOG (LoadSPGameMenuClass);
  668. } else {
  669. if (_TheInstance->Is_Active_Menu () == false) {
  670. DialogMgrClass::Rollback (_TheInstance);
  671. }
  672. }
  673. return ;
  674. #endif // !MULTIPLAYERDEMO
  675. }
  676. ////////////////////////////////////////////////////////////////
  677. //
  678. // On_Last_Menu_Ending
  679. //
  680. ////////////////////////////////////////////////////////////////
  681. void
  682. LoadSPGameMenuClass::On_Last_Menu_Ending (void)
  683. {
  684. RenegadeDialogMgrClass::Goto_Location (RenegadeDialogMgrClass::LOC_MAIN_MENU);
  685. return ;
  686. }