MainFrm.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  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. // MainFrm.cpp : implementation of the CMainFrame class
  19. //
  20. #include "stdafx.h"
  21. #include "mixviewer.h"
  22. #include "mainfrm.h"
  23. #include "wwstring.h"
  24. #include "duplicatecombiner.h"
  25. #include "wwfile.h"
  26. #include "ffactory.h"
  27. #include "mixfile.h"
  28. #include "avassetsuck.h"
  29. #include "mixpatchmaker.h"
  30. #include "ffactory.h"
  31. #include "mixfile.h"
  32. #include "mixviewerdoc.h"
  33. #include "makemixfiledialog.h"
  34. #ifdef _DEBUG
  35. #define new DEBUG_NEW
  36. #undef THIS_FILE
  37. static char THIS_FILE[] = __FILE__;
  38. #endif
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CMainFrame
  41. IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
  42. BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  43. //{{AFX_MSG_MAP(CMainFrame)
  44. ON_WM_CREATE()
  45. ON_COMMAND(IDM_COMBINE_DUPLICATES, OnCombineDuplicates)
  46. ON_COMMAND(IDM_CREATE_MIX_FILE, OnCreateMixFile)
  47. ON_COMMAND(IDM_EXPORT_FILES, OnExportFiles)
  48. ON_COMMAND(IDM_REMOVE_AV_ASSETS, OnRemoveAVAssets)
  49. ON_COMMAND(IDM_MAKE_MIX_PATCH, OnMakeMixPatch)
  50. ON_WM_DROPFILES()
  51. //}}AFX_MSG_MAP
  52. END_MESSAGE_MAP()
  53. static UINT indicators[] =
  54. {
  55. ID_SEPARATOR, // status line indicator
  56. ID_INDICATOR_CAPS,
  57. ID_INDICATOR_NUM,
  58. ID_INDICATOR_SCRL,
  59. };
  60. /////////////////////////////////////////////////////////////////////////////
  61. // CMainFrame construction/destruction
  62. CMainFrame::CMainFrame()
  63. {
  64. // TODO: add member initialization code here
  65. }
  66. CMainFrame::~CMainFrame()
  67. {
  68. }
  69. int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
  70. {
  71. if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
  72. return -1;
  73. if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
  74. | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
  75. !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
  76. {
  77. TRACE0("Failed to create toolbar\n");
  78. return -1; // fail to create
  79. }
  80. if (!m_wndStatusBar.Create(this) ||
  81. !m_wndStatusBar.SetIndicators(indicators,
  82. sizeof(indicators)/sizeof(UINT)))
  83. {
  84. TRACE0("Failed to create status bar\n");
  85. return -1; // fail to create
  86. }
  87. // TODO: Delete these three lines if you don't want the toolbar to
  88. // be dockable
  89. m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
  90. EnableDocking(CBRS_ALIGN_ANY);
  91. DockControlBar(&m_wndToolBar);
  92. return 0;
  93. }
  94. BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
  95. {
  96. if( !CFrameWnd::PreCreateWindow(cs) )
  97. return FALSE;
  98. // TODO: Modify the Window class or styles here by modifying
  99. // the CREATESTRUCT cs
  100. return TRUE;
  101. }
  102. /////////////////////////////////////////////////////////////////////////////
  103. // CMainFrame diagnostics
  104. #ifdef _DEBUG
  105. void CMainFrame::AssertValid() const
  106. {
  107. CFrameWnd::AssertValid();
  108. }
  109. void CMainFrame::Dump(CDumpContext& dc) const
  110. {
  111. CFrameWnd::Dump(dc);
  112. }
  113. #endif //_DEBUG
  114. /////////////////////////////////////////////////////////////////////////////
  115. // CMainFrame message handlers
  116. ////////////////////////////////////////////////////////////////////////////
  117. //
  118. // Get_Filename_From_Path
  119. //
  120. ////////////////////////////////////////////////////////////////////////////
  121. CString
  122. Get_Filename_From_Path (LPCTSTR path)
  123. {
  124. // Find the last occurance of the directory deliminator
  125. LPCTSTR filename = ::strrchr (path, '\\');
  126. if (filename != NULL) {
  127. // Increment past the directory deliminator
  128. filename ++;
  129. } else {
  130. filename = path;
  131. }
  132. // Return the filename part of the path
  133. return CString (filename);
  134. }
  135. ////////////////////////////////////////////////////////////////////////////
  136. //
  137. // Strip_Filename_From_Path
  138. //
  139. ////////////////////////////////////////////////////////////////////////////
  140. CString
  141. Strip_Filename_From_Path (LPCTSTR path)
  142. {
  143. // Copy the path to a buffer we can modify
  144. TCHAR temp_path[MAX_PATH];
  145. ::lstrcpy (temp_path, path);
  146. // Find the last occurance of the directory deliminator
  147. LPTSTR filename = ::strrchr (temp_path, '\\');
  148. if (filename != NULL) {
  149. // Strip off the filename
  150. filename[0] = 0;
  151. } else if ((temp_path[1] != ':') && (temp_path[1] != '\\')) {
  152. temp_path[0] = 0;
  153. }
  154. // Return the path only
  155. return StringClass (temp_path);
  156. }
  157. /////////////////////////////////////////////////////////////////////////////
  158. //
  159. // OnCombineDuplicates
  160. //
  161. /////////////////////////////////////////////////////////////////////////////
  162. void
  163. CMainFrame::OnCombineDuplicates (void)
  164. {
  165. CFileDialog dialog ( TRUE,
  166. ".dat",
  167. "always.dat",
  168. OFN_HIDEREADONLY | OFN_EXPLORER,
  169. "Mix File (*.dat, *.mix)|*.dat;*.mix||",
  170. this);
  171. dialog.m_ofn.lpstrTitle = "Pick Shared Mix File";
  172. if (dialog.DoModal () == IDOK) {
  173. DuplicateRemoverClass combiner;
  174. //
  175. // Determine what directory to search
  176. //
  177. StringClass full_path = dialog.GetPathName ();
  178. StringClass directory = Strip_Filename_From_Path (full_path);
  179. combiner.Set_Destination_File (full_path);
  180. WIN32_FIND_DATA find_info = { 0 };
  181. BOOL keep_going = TRUE;
  182. CString search_mask = directory + "\\*.mix";
  183. //
  184. // Loop over all the mix files in the search directory
  185. //
  186. int count = 0;
  187. for (HANDLE find_handle = ::FindFirstFile (search_mask, &find_info);
  188. (find_handle != INVALID_HANDLE_VALUE) && keep_going;
  189. keep_going = ::FindNextFile (find_handle, &find_info))
  190. {
  191. //
  192. // Check to make sure this isn't a directory
  193. //
  194. if (!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  195. StringClass full_path = directory;
  196. full_path += "\\";
  197. full_path += find_info.cFileName;
  198. combiner.Add_Mix_File (full_path);
  199. count ++;
  200. }
  201. }
  202. //
  203. // Close the handle we needed for the file find routines
  204. //
  205. if (find_handle != INVALID_HANDLE_VALUE) {
  206. ::FindClose (find_handle);
  207. }
  208. //
  209. // Combine the files (if necessary)
  210. //
  211. if (count > 0) {
  212. combiner.Process ();
  213. }
  214. }
  215. return ;
  216. }
  217. /////////////////////////////////////////////////////////////////////////////
  218. //
  219. // OnCreateMixFile
  220. //
  221. /////////////////////////////////////////////////////////////////////////////
  222. void
  223. CMainFrame::OnCreateMixFile (void)
  224. {
  225. MakeMixFileDialogClass dialog( this );
  226. dialog.DoModal();
  227. return ;
  228. }
  229. /////////////////////////////////////////////////////////////////////////////
  230. //
  231. // OnExportFiles
  232. //
  233. /////////////////////////////////////////////////////////////////////////////
  234. void
  235. CMainFrame::OnExportFiles (void)
  236. {
  237. StringClass current_filename;
  238. CDocument * doc = GetActiveDocument();
  239. if ( doc != NULL ) {
  240. current_filename = doc->GetPathName();
  241. }
  242. if ( !current_filename.Is_Empty() ) {
  243. DynamicVectorClass<StringClass> filenames;
  244. MixFileFactoryClass mix_factory (current_filename, _TheFileFactory);
  245. if ( mix_factory.Build_Filename_List( filenames ) ) {
  246. // Make the destination folder
  247. StringClass export_path = current_filename;
  248. export_path += " Files";
  249. int result = (int)::CreateDirectory( export_path, NULL );
  250. int error = ::GetLastError();
  251. if ( result != 0 || error == ERROR_ALREADY_EXISTS ) {
  252. bool read_error = false;
  253. bool write_error = false;
  254. for (int index = 0; index < filenames.Count (); index ++) {
  255. StringClass source_name = filenames[index];
  256. StringClass dest_name;
  257. dest_name = export_path;
  258. dest_name += "\\";
  259. dest_name += filenames[index];
  260. // If the filename contains a /, create the directory
  261. if ( ::strchr( filenames[index], '\\' ) != NULL ) {
  262. StringClass dest_folder = dest_name;
  263. int length = ::strrchr( dest_folder, '\\' ) - dest_folder;
  264. dest_folder.Erase( length, dest_folder.Get_Length() - length );
  265. int result = (int)::CreateDirectory( dest_folder, NULL );
  266. int error = ::GetLastError();
  267. if ( result == 0 && error != ERROR_ALREADY_EXISTS ) {
  268. StringClass message;
  269. message.Format ("Failed to create folder %s.", dest_folder );
  270. MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
  271. return;
  272. }
  273. }
  274. FileClass * source_file = mix_factory.Get_File( source_name );
  275. FileClass * dest_file = _TheFileFactory->Get_File( dest_name );
  276. if ( dest_file ) {
  277. if ( dest_file->Open( FileClass::WRITE ) == 0 ) {
  278. StringClass message;
  279. message.Format ("Failed to open %s for writing.", dest_name );
  280. MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
  281. return;
  282. }
  283. }
  284. if ( source_file ) {
  285. if ( source_file->Open() == 0 ) {
  286. StringClass message;
  287. message.Format ("Failed to open %s for reading.", source_name );
  288. MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
  289. return;
  290. }
  291. }
  292. if ( source_file && source_file->Is_Available() &&
  293. dest_file && dest_file->Is_Available() ) {
  294. int length = source_file->Size();
  295. unsigned char file_buffer[4096];
  296. while ( length > 0 ) {
  297. int amount = min ( (int)length, (int)sizeof( file_buffer ) );
  298. if ( source_file->Read( &(file_buffer[0]), amount ) != amount ) {
  299. read_error = true;
  300. length = 0;
  301. }
  302. if ( dest_file->Write( &file_buffer[0], amount ) != amount ) {
  303. write_error = true;
  304. length = 0;
  305. }
  306. length -= amount;
  307. }
  308. }
  309. if ( source_file != NULL ) {
  310. mix_factory.Return_File( source_file );
  311. }
  312. if ( dest_file != NULL ) {
  313. _TheFileFactory->Return_File( dest_file );
  314. }
  315. if ( read_error ) {
  316. StringClass message;
  317. message.Format ("Read Error on %s.", source_name );
  318. MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
  319. return;
  320. }
  321. if ( write_error ) {
  322. StringClass message;
  323. message.Format ("Write Error on %s.", dest_name );
  324. MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
  325. return;
  326. }
  327. // filenames[index];
  328. }
  329. } else {
  330. StringClass message;
  331. message.Format ("Failed to create folder %s.", export_path);
  332. MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
  333. }
  334. } else {
  335. StringClass message;
  336. message.Format ("Error reading the filename list from %s.", current_filename);
  337. MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
  338. }
  339. } else {
  340. StringClass message;
  341. message.Format ("No Current Mix File.");
  342. MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
  343. }
  344. return ;
  345. }
  346. /////////////////////////////////////////////////////////////////////////////
  347. //
  348. // OnRemoveAVAssets
  349. //
  350. /////////////////////////////////////////////////////////////////////////////
  351. void
  352. CMainFrame::OnRemoveAVAssets (void)
  353. {
  354. CFileDialog dialog(true, ".mix", NULL, OFN_ALLOWMULTISELECT | OFN_HIDEREADONLY | OFN_EXPLORER, "Mix File (*.dat, *.mix)|*.dat;*.mix||", this);
  355. dialog.m_ofn.lpstrTitle = "Pick Mix Files";
  356. char *file_name_buffer = new char [65536];
  357. *file_name_buffer = 0;
  358. dialog.m_ofn.lpstrFile = file_name_buffer;
  359. dialog.m_ofn.nMaxFile = 65535;
  360. if (dialog.DoModal () == IDOK) {
  361. //
  362. // Process each mix file and put the stripped mix file into a 'temp' subdirectory under the current one.
  363. //
  364. POSITION pos = dialog.GetStartPosition();
  365. while (pos != NULL) {
  366. StringClass file_name = dialog.GetNextPathName(pos);
  367. //
  368. // Get just the path portion.
  369. //
  370. char drive[_MAX_DRIVE];
  371. char dir[_MAX_DIR];
  372. char path[_MAX_PATH];
  373. char name[_MAX_PATH];
  374. char ext[_MAX_PATH];
  375. _splitpath(file_name, drive, dir, name, ext);
  376. //
  377. // Make sure the temp directory exists.
  378. //
  379. strcat(dir, "temp\\");
  380. _makepath(path, drive, dir, NULL, NULL);
  381. CreateDirectory(path, NULL);
  382. //
  383. // Make the output file name.
  384. //
  385. char output_file[_MAX_PATH];
  386. _makepath(output_file, drive, dir, name, ext);
  387. AVAssetSuckerClass sucker;
  388. sucker.Suck(file_name.Peek_Buffer(), output_file);
  389. }
  390. }
  391. delete [] file_name_buffer;
  392. }
  393. /////////////////////////////////////////////////////////////////////////////
  394. //
  395. // OnMakeMixPatch
  396. //
  397. /////////////////////////////////////////////////////////////////////////////
  398. void
  399. CMainFrame::OnMakeMixPatch(void)
  400. {
  401. //
  402. // Ask for the name of the old source mix file.
  403. //
  404. CFileDialog dialog(true, ".mix", NULL, OFN_HIDEREADONLY | OFN_EXPLORER, "Mix File (*.dat, *.mix)|*.dat;*.mix||", this);
  405. dialog.m_ofn.lpstrTitle = "Pick Old Source Mix File";
  406. char file_name_buffer[1024];
  407. file_name_buffer[0] = 0;
  408. dialog.m_ofn.lpstrFile = file_name_buffer;
  409. dialog.m_ofn.nMaxFile = 1024;
  410. if (dialog.DoModal () == IDOK) {
  411. //
  412. // Pull the name of the old source mix file.
  413. //
  414. POSITION pos = dialog.GetStartPosition();
  415. StringClass old_file_name = dialog.GetNextPathName(pos);
  416. //
  417. // Ask for the name of the new source mix file.
  418. //
  419. CFileDialog dialog2(true, ".mix", NULL, OFN_HIDEREADONLY | OFN_EXPLORER, "Mix File (*.dat, *.mix)|*.dat;*.mix||", this);
  420. dialog2.m_ofn.lpstrTitle = "Pick New Source Mix File";
  421. file_name_buffer[0] = 0;
  422. dialog2.m_ofn.lpstrFile = file_name_buffer;
  423. dialog2.m_ofn.nMaxFile = 1024;
  424. if (dialog2.DoModal () == IDOK) {
  425. //
  426. // Pull the name of the new source mix file.
  427. //
  428. pos = dialog2.GetStartPosition();
  429. StringClass new_file_name = dialog2.GetNextPathName(pos);
  430. //
  431. // Ask for the name of the output mix file.
  432. //
  433. CFileDialog dialog3(true, ".mix", NULL, OFN_HIDEREADONLY | OFN_EXPLORER, "Mix File (*.dat, *.mix)|*.dat;*.mix||", this);
  434. dialog3.m_ofn.lpstrTitle = "Pick Output Patch Mix File";
  435. file_name_buffer[0] = 0;
  436. dialog3.m_ofn.lpstrFile = file_name_buffer;
  437. dialog3.m_ofn.nMaxFile = 1024;
  438. if (dialog3.DoModal () == IDOK) {
  439. //
  440. // Pull the name of the new source mix file.
  441. //
  442. pos = dialog3.GetStartPosition();
  443. StringClass out_file_name = dialog3.GetNextPathName(pos);
  444. //
  445. // Ask for the directory containing the old source art.
  446. //
  447. char path[_MAX_PATH + 256];
  448. BROWSEINFO binfo;
  449. binfo.hwndOwner = NULL;
  450. binfo.pidlRoot = NULL;
  451. binfo.pszDisplayName = path;
  452. binfo.lpszTitle = "Select Old Source Art Directory";
  453. binfo.ulFlags = 0;
  454. binfo.lpfn = NULL;
  455. binfo.lParam = 0;
  456. binfo.iImage = 0;
  457. LPITEMIDLIST itemptr = SHBrowseForFolder(&binfo);
  458. if (itemptr) {
  459. char old_art_dir[_MAX_PATH + 256];
  460. if (SHGetPathFromIDList(itemptr, old_art_dir)) {
  461. //
  462. // Ask for the directory containing the new source art.
  463. //
  464. char path[_MAX_PATH + 256];
  465. BROWSEINFO binfo;
  466. binfo.hwndOwner = NULL;
  467. binfo.pidlRoot = NULL;
  468. binfo.pszDisplayName = path;
  469. binfo.lpszTitle = "Select New Source Art Directory";
  470. binfo.ulFlags = 0;
  471. binfo.lpfn = NULL;
  472. binfo.lParam = 0;
  473. binfo.iImage = 0;
  474. itemptr = SHBrowseForFolder(&binfo);
  475. if (itemptr) {
  476. char new_art_dir[_MAX_PATH + 256];
  477. if (SHGetPathFromIDList(itemptr, new_art_dir)) {
  478. MixPatchMakerClass patcher;
  479. patcher.Make_Patch(old_file_name.Peek_Buffer(), new_file_name.Peek_Buffer(), out_file_name.Peek_Buffer(), old_art_dir, new_art_dir);
  480. }
  481. }
  482. }
  483. }
  484. }
  485. }
  486. }
  487. }
  488. /////////////////////////////////////////////////////////////////////////////
  489. //
  490. // WindowProc
  491. //
  492. /////////////////////////////////////////////////////////////////////////////
  493. LRESULT
  494. CMainFrame::WindowProc
  495. (
  496. UINT message,
  497. WPARAM wParam,
  498. LPARAM lParam
  499. )
  500. {
  501. return CFrameWnd::WindowProc(message, wParam, lParam);
  502. }
  503. /////////////////////////////////////////////////////////////////////////////
  504. //
  505. // OnDropFiles
  506. //
  507. /////////////////////////////////////////////////////////////////////////////
  508. void
  509. CMainFrame::OnDropFiles (HDROP hDropInfo)
  510. {
  511. SetActiveWindow ();
  512. CWinApp *win_app = AfxGetApp ();
  513. ASSERT (win_app != NULL);
  514. //
  515. // Get the count of files from the drop query
  516. //
  517. int file_count = (int)::DragQueryFile (hDropInfo, (UINT)-1, NULL, 0);
  518. if (file_count > 0) {
  519. CMixViewerDoc *doc = (CMixViewerDoc *)GetActiveDocument ();
  520. if (file_count == 1) {
  521. //
  522. // Get the filename...
  523. //
  524. TCHAR filename[_MAX_PATH];
  525. ::DragQueryFile (hDropInfo, 0, filename, _MAX_PATH);
  526. //
  527. // Get the extension from the filename
  528. //
  529. char extension[_MAX_EXT] = { 0 };
  530. ::_splitpath (filename, NULL, NULL, NULL, extension);
  531. //
  532. // Is this a mix file, or should we be adding this file to the mix?
  533. //
  534. if ( ::lstrcmpi (extension, ".mix") == 0 ||
  535. ::lstrcmpi (extension, ".dat") == 0 ||
  536. ::lstrcmpi (extension, ".dbs") == 0)
  537. {
  538. win_app->OpenDocumentFile (filename);
  539. } else {
  540. Add_To_Mix_File (doc->GetPathName (), filename);
  541. doc->Reload_Views ();
  542. }
  543. } else {
  544. DynamicVectorClass<StringClass> file_list;
  545. //
  546. // Loop over each of the dropped files and add them to the current mix file
  547. //
  548. for (int index = 0; index < file_count; index ++) {
  549. //
  550. // Add this file to a list so we can batch add all the files...
  551. //
  552. TCHAR filename[_MAX_PATH];
  553. ::DragQueryFile (hDropInfo, index, filename, _MAX_PATH);
  554. file_list.Add (filename);
  555. }
  556. ::DragFinish(hDropInfo);
  557. //
  558. // Add the mix files to the list
  559. //
  560. Add_To_Mix_File (doc->GetPathName (), file_list);
  561. doc->Reload_Views ();
  562. }
  563. }
  564. return ;
  565. }
  566. /////////////////////////////////////////////////////////////////////////////
  567. //
  568. // Add_To_Mix_File
  569. //
  570. /////////////////////////////////////////////////////////////////////////////
  571. void
  572. CMainFrame::Add_To_Mix_File (const char *mix_filename, const char *filename)
  573. {
  574. DynamicVectorClass<StringClass> file_list;
  575. file_list.Add (filename);
  576. Add_To_Mix_File (mix_filename, file_list);
  577. return ;
  578. }
  579. /////////////////////////////////////////////////////////////////////////////
  580. //
  581. // Add_To_Mix_File
  582. //
  583. /////////////////////////////////////////////////////////////////////////////
  584. void
  585. CMainFrame::Add_To_Mix_File (const char *mix_filename, DynamicVectorClass<StringClass> &new_file_list)
  586. {
  587. //
  588. // Set the current directory...
  589. //
  590. CString path = Strip_Filename_From_Path (mix_filename);
  591. if (path.GetLength () > 0) {
  592. ::SetCurrentDirectory (path);
  593. }
  594. //
  595. // Get access to the mix file in qestion
  596. //
  597. MixFileFactoryClass *mix_factory = new MixFileFactoryClass (mix_filename, _TheFileFactory);
  598. if (mix_factory->Is_Valid () && mix_factory->Build_Internal_Filename_List ()) {
  599. //
  600. // Now add the new files into the mix file...
  601. //
  602. for (int index = 0; index < new_file_list.Count (); index ++) {
  603. CString filename = ::Get_Filename_From_Path (new_file_list[index]);
  604. mix_factory->Delete_File (filename);
  605. mix_factory->Add_File (new_file_list[index], filename);
  606. }
  607. //
  608. // Do it!
  609. //
  610. mix_factory->Flush_Changes ();
  611. }
  612. //
  613. // Free the mix factory
  614. //
  615. delete mix_factory;
  616. mix_factory = NULL;
  617. return ;
  618. }