| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- // MainFrm.cpp : implementation of the CMainFrame class
- //
- #include "stdafx.h"
- #include "mixviewer.h"
- #include "mainfrm.h"
- #include "wwstring.h"
- #include "duplicatecombiner.h"
- #include "wwfile.h"
- #include "ffactory.h"
- #include "mixfile.h"
- #include "avassetsuck.h"
- #include "mixpatchmaker.h"
- #include "ffactory.h"
- #include "mixfile.h"
- #include "mixviewerdoc.h"
- #include "makemixfiledialog.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // CMainFrame
- IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
- BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
- //{{AFX_MSG_MAP(CMainFrame)
- ON_WM_CREATE()
- ON_COMMAND(IDM_COMBINE_DUPLICATES, OnCombineDuplicates)
- ON_COMMAND(IDM_CREATE_MIX_FILE, OnCreateMixFile)
- ON_COMMAND(IDM_EXPORT_FILES, OnExportFiles)
- ON_COMMAND(IDM_REMOVE_AV_ASSETS, OnRemoveAVAssets)
- ON_COMMAND(IDM_MAKE_MIX_PATCH, OnMakeMixPatch)
- ON_WM_DROPFILES()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- static UINT indicators[] =
- {
- ID_SEPARATOR, // status line indicator
- ID_INDICATOR_CAPS,
- ID_INDICATOR_NUM,
- ID_INDICATOR_SCRL,
- };
- /////////////////////////////////////////////////////////////////////////////
- // CMainFrame construction/destruction
- CMainFrame::CMainFrame()
- {
- // TODO: add member initialization code here
- }
- CMainFrame::~CMainFrame()
- {
- }
- int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
- return -1;
- if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
- | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
- !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
- {
- TRACE0("Failed to create toolbar\n");
- return -1; // fail to create
- }
- if (!m_wndStatusBar.Create(this) ||
- !m_wndStatusBar.SetIndicators(indicators,
- sizeof(indicators)/sizeof(UINT)))
- {
- TRACE0("Failed to create status bar\n");
- return -1; // fail to create
- }
- // TODO: Delete these three lines if you don't want the toolbar to
- // be dockable
- m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
- EnableDocking(CBRS_ALIGN_ANY);
- DockControlBar(&m_wndToolBar);
- return 0;
- }
- BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
- {
- if( !CFrameWnd::PreCreateWindow(cs) )
- return FALSE;
- // TODO: Modify the Window class or styles here by modifying
- // the CREATESTRUCT cs
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CMainFrame diagnostics
- #ifdef _DEBUG
- void CMainFrame::AssertValid() const
- {
- CFrameWnd::AssertValid();
- }
- void CMainFrame::Dump(CDumpContext& dc) const
- {
- CFrameWnd::Dump(dc);
- }
- #endif //_DEBUG
- /////////////////////////////////////////////////////////////////////////////
- // CMainFrame message handlers
- ////////////////////////////////////////////////////////////////////////////
- //
- // Get_Filename_From_Path
- //
- ////////////////////////////////////////////////////////////////////////////
- CString
- Get_Filename_From_Path (LPCTSTR path)
- {
- // Find the last occurance of the directory deliminator
- LPCTSTR filename = ::strrchr (path, '\\');
- if (filename != NULL) {
- // Increment past the directory deliminator
- filename ++;
- } else {
- filename = path;
- }
- // Return the filename part of the path
- return CString (filename);
- }
- ////////////////////////////////////////////////////////////////////////////
- //
- // Strip_Filename_From_Path
- //
- ////////////////////////////////////////////////////////////////////////////
- CString
- Strip_Filename_From_Path (LPCTSTR path)
- {
- // Copy the path to a buffer we can modify
- TCHAR temp_path[MAX_PATH];
- ::lstrcpy (temp_path, path);
- // Find the last occurance of the directory deliminator
- LPTSTR filename = ::strrchr (temp_path, '\\');
- if (filename != NULL) {
- // Strip off the filename
- filename[0] = 0;
- } else if ((temp_path[1] != ':') && (temp_path[1] != '\\')) {
- temp_path[0] = 0;
- }
- // Return the path only
- return StringClass (temp_path);
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // OnCombineDuplicates
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- CMainFrame::OnCombineDuplicates (void)
- {
- CFileDialog dialog ( TRUE,
- ".dat",
- "always.dat",
- OFN_HIDEREADONLY | OFN_EXPLORER,
- "Mix File (*.dat, *.mix)|*.dat;*.mix||",
- this);
- dialog.m_ofn.lpstrTitle = "Pick Shared Mix File";
- if (dialog.DoModal () == IDOK) {
- DuplicateRemoverClass combiner;
- //
- // Determine what directory to search
- //
- StringClass full_path = dialog.GetPathName ();
- StringClass directory = Strip_Filename_From_Path (full_path);
- combiner.Set_Destination_File (full_path);
- WIN32_FIND_DATA find_info = { 0 };
- BOOL keep_going = TRUE;
- CString search_mask = directory + "\\*.mix";
- //
- // Loop over all the mix files in the search directory
- //
- int count = 0;
- for (HANDLE find_handle = ::FindFirstFile (search_mask, &find_info);
- (find_handle != INVALID_HANDLE_VALUE) && keep_going;
- keep_going = ::FindNextFile (find_handle, &find_info))
- {
- //
- // Check to make sure this isn't a directory
- //
- if (!(find_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
- StringClass full_path = directory;
- full_path += "\\";
- full_path += find_info.cFileName;
- combiner.Add_Mix_File (full_path);
- count ++;
- }
- }
- //
- // Close the handle we needed for the file find routines
- //
- if (find_handle != INVALID_HANDLE_VALUE) {
- ::FindClose (find_handle);
- }
- //
- // Combine the files (if necessary)
- //
- if (count > 0) {
- combiner.Process ();
- }
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // OnCreateMixFile
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- CMainFrame::OnCreateMixFile (void)
- {
- MakeMixFileDialogClass dialog( this );
- dialog.DoModal();
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // OnExportFiles
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- CMainFrame::OnExportFiles (void)
- {
- StringClass current_filename;
- CDocument * doc = GetActiveDocument();
- if ( doc != NULL ) {
- current_filename = doc->GetPathName();
- }
- if ( !current_filename.Is_Empty() ) {
- DynamicVectorClass<StringClass> filenames;
- MixFileFactoryClass mix_factory (current_filename, _TheFileFactory);
- if ( mix_factory.Build_Filename_List( filenames ) ) {
- // Make the destination folder
- StringClass export_path = current_filename;
- export_path += " Files";
- int result = (int)::CreateDirectory( export_path, NULL );
- int error = ::GetLastError();
- if ( result != 0 || error == ERROR_ALREADY_EXISTS ) {
- bool read_error = false;
- bool write_error = false;
- for (int index = 0; index < filenames.Count (); index ++) {
- StringClass source_name = filenames[index];
- StringClass dest_name;
- dest_name = export_path;
- dest_name += "\\";
- dest_name += filenames[index];
- // If the filename contains a /, create the directory
- if ( ::strchr( filenames[index], '\\' ) != NULL ) {
- StringClass dest_folder = dest_name;
- int length = ::strrchr( dest_folder, '\\' ) - dest_folder;
- dest_folder.Erase( length, dest_folder.Get_Length() - length );
- int result = (int)::CreateDirectory( dest_folder, NULL );
- int error = ::GetLastError();
- if ( result == 0 && error != ERROR_ALREADY_EXISTS ) {
- StringClass message;
- message.Format ("Failed to create folder %s.", dest_folder );
- MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
- return;
- }
- }
- FileClass * source_file = mix_factory.Get_File( source_name );
- FileClass * dest_file = _TheFileFactory->Get_File( dest_name );
- if ( dest_file ) {
- if ( dest_file->Open( FileClass::WRITE ) == 0 ) {
- StringClass message;
- message.Format ("Failed to open %s for writing.", dest_name );
- MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
- return;
- }
- }
- if ( source_file ) {
- if ( source_file->Open() == 0 ) {
- StringClass message;
- message.Format ("Failed to open %s for reading.", source_name );
- MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
- return;
- }
- }
- if ( source_file && source_file->Is_Available() &&
- dest_file && dest_file->Is_Available() ) {
- int length = source_file->Size();
- unsigned char file_buffer[4096];
- while ( length > 0 ) {
- int amount = min ( (int)length, (int)sizeof( file_buffer ) );
- if ( source_file->Read( &(file_buffer[0]), amount ) != amount ) {
- read_error = true;
- length = 0;
- }
- if ( dest_file->Write( &file_buffer[0], amount ) != amount ) {
- write_error = true;
- length = 0;
- }
- length -= amount;
- }
- }
- if ( source_file != NULL ) {
- mix_factory.Return_File( source_file );
- }
- if ( dest_file != NULL ) {
- _TheFileFactory->Return_File( dest_file );
- }
- if ( read_error ) {
- StringClass message;
- message.Format ("Read Error on %s.", source_name );
- MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
- return;
- }
- if ( write_error ) {
- StringClass message;
- message.Format ("Write Error on %s.", dest_name );
- MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
- return;
- }
- // filenames[index];
- }
- } else {
- StringClass message;
- message.Format ("Failed to create folder %s.", export_path);
- MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
- }
- } else {
- StringClass message;
- message.Format ("Error reading the filename list from %s.", current_filename);
- MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
- }
- } else {
- StringClass message;
- message.Format ("No Current Mix File.");
- MessageBox (message, "Mix File Error", MB_ICONERROR | MB_OK);
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // OnRemoveAVAssets
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- CMainFrame::OnRemoveAVAssets (void)
- {
- CFileDialog dialog(true, ".mix", NULL, OFN_ALLOWMULTISELECT | OFN_HIDEREADONLY | OFN_EXPLORER, "Mix File (*.dat, *.mix)|*.dat;*.mix||", this);
- dialog.m_ofn.lpstrTitle = "Pick Mix Files";
- char *file_name_buffer = new char [65536];
- *file_name_buffer = 0;
- dialog.m_ofn.lpstrFile = file_name_buffer;
- dialog.m_ofn.nMaxFile = 65535;
- if (dialog.DoModal () == IDOK) {
- //
- // Process each mix file and put the stripped mix file into a 'temp' subdirectory under the current one.
- //
- POSITION pos = dialog.GetStartPosition();
- while (pos != NULL) {
- StringClass file_name = dialog.GetNextPathName(pos);
- //
- // Get just the path portion.
- //
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
- char path[_MAX_PATH];
- char name[_MAX_PATH];
- char ext[_MAX_PATH];
- _splitpath(file_name, drive, dir, name, ext);
- //
- // Make sure the temp directory exists.
- //
- strcat(dir, "temp\\");
- _makepath(path, drive, dir, NULL, NULL);
- CreateDirectory(path, NULL);
- //
- // Make the output file name.
- //
- char output_file[_MAX_PATH];
- _makepath(output_file, drive, dir, name, ext);
- AVAssetSuckerClass sucker;
- sucker.Suck(file_name.Peek_Buffer(), output_file);
- }
- }
- delete [] file_name_buffer;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // OnMakeMixPatch
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- CMainFrame::OnMakeMixPatch(void)
- {
- //
- // Ask for the name of the old source mix file.
- //
- CFileDialog dialog(true, ".mix", NULL, OFN_HIDEREADONLY | OFN_EXPLORER, "Mix File (*.dat, *.mix)|*.dat;*.mix||", this);
- dialog.m_ofn.lpstrTitle = "Pick Old Source Mix File";
- char file_name_buffer[1024];
- file_name_buffer[0] = 0;
- dialog.m_ofn.lpstrFile = file_name_buffer;
- dialog.m_ofn.nMaxFile = 1024;
- if (dialog.DoModal () == IDOK) {
- //
- // Pull the name of the old source mix file.
- //
- POSITION pos = dialog.GetStartPosition();
- StringClass old_file_name = dialog.GetNextPathName(pos);
- //
- // Ask for the name of the new source mix file.
- //
- CFileDialog dialog2(true, ".mix", NULL, OFN_HIDEREADONLY | OFN_EXPLORER, "Mix File (*.dat, *.mix)|*.dat;*.mix||", this);
- dialog2.m_ofn.lpstrTitle = "Pick New Source Mix File";
- file_name_buffer[0] = 0;
- dialog2.m_ofn.lpstrFile = file_name_buffer;
- dialog2.m_ofn.nMaxFile = 1024;
- if (dialog2.DoModal () == IDOK) {
- //
- // Pull the name of the new source mix file.
- //
- pos = dialog2.GetStartPosition();
- StringClass new_file_name = dialog2.GetNextPathName(pos);
- //
- // Ask for the name of the output mix file.
- //
- CFileDialog dialog3(true, ".mix", NULL, OFN_HIDEREADONLY | OFN_EXPLORER, "Mix File (*.dat, *.mix)|*.dat;*.mix||", this);
- dialog3.m_ofn.lpstrTitle = "Pick Output Patch Mix File";
- file_name_buffer[0] = 0;
- dialog3.m_ofn.lpstrFile = file_name_buffer;
- dialog3.m_ofn.nMaxFile = 1024;
- if (dialog3.DoModal () == IDOK) {
- //
- // Pull the name of the new source mix file.
- //
- pos = dialog3.GetStartPosition();
- StringClass out_file_name = dialog3.GetNextPathName(pos);
- //
- // Ask for the directory containing the old source art.
- //
- char path[_MAX_PATH + 256];
- BROWSEINFO binfo;
- binfo.hwndOwner = NULL;
- binfo.pidlRoot = NULL;
- binfo.pszDisplayName = path;
- binfo.lpszTitle = "Select Old Source Art Directory";
- binfo.ulFlags = 0;
- binfo.lpfn = NULL;
- binfo.lParam = 0;
- binfo.iImage = 0;
- LPITEMIDLIST itemptr = SHBrowseForFolder(&binfo);
- if (itemptr) {
- char old_art_dir[_MAX_PATH + 256];
- if (SHGetPathFromIDList(itemptr, old_art_dir)) {
- //
- // Ask for the directory containing the new source art.
- //
- char path[_MAX_PATH + 256];
- BROWSEINFO binfo;
- binfo.hwndOwner = NULL;
- binfo.pidlRoot = NULL;
- binfo.pszDisplayName = path;
- binfo.lpszTitle = "Select New Source Art Directory";
- binfo.ulFlags = 0;
- binfo.lpfn = NULL;
- binfo.lParam = 0;
- binfo.iImage = 0;
- itemptr = SHBrowseForFolder(&binfo);
- if (itemptr) {
- char new_art_dir[_MAX_PATH + 256];
- if (SHGetPathFromIDList(itemptr, new_art_dir)) {
- MixPatchMakerClass patcher;
- patcher.Make_Patch(old_file_name.Peek_Buffer(), new_file_name.Peek_Buffer(), out_file_name.Peek_Buffer(), old_art_dir, new_art_dir);
- }
- }
- }
- }
- }
- }
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // WindowProc
- //
- /////////////////////////////////////////////////////////////////////////////
- LRESULT
- CMainFrame::WindowProc
- (
- UINT message,
- WPARAM wParam,
- LPARAM lParam
- )
- {
- return CFrameWnd::WindowProc(message, wParam, lParam);
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // OnDropFiles
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- CMainFrame::OnDropFiles (HDROP hDropInfo)
- {
- SetActiveWindow ();
- CWinApp *win_app = AfxGetApp ();
- ASSERT (win_app != NULL);
- //
- // Get the count of files from the drop query
- //
- int file_count = (int)::DragQueryFile (hDropInfo, (UINT)-1, NULL, 0);
- if (file_count > 0) {
- CMixViewerDoc *doc = (CMixViewerDoc *)GetActiveDocument ();
- if (file_count == 1) {
- //
- // Get the filename...
- //
- TCHAR filename[_MAX_PATH];
- ::DragQueryFile (hDropInfo, 0, filename, _MAX_PATH);
- //
- // Get the extension from the filename
- //
- char extension[_MAX_EXT] = { 0 };
- ::_splitpath (filename, NULL, NULL, NULL, extension);
- //
- // Is this a mix file, or should we be adding this file to the mix?
- //
- if ( ::lstrcmpi (extension, ".mix") == 0 ||
- ::lstrcmpi (extension, ".dat") == 0 ||
- ::lstrcmpi (extension, ".dbs") == 0)
- {
- win_app->OpenDocumentFile (filename);
- } else {
- Add_To_Mix_File (doc->GetPathName (), filename);
- doc->Reload_Views ();
- }
-
- } else {
- DynamicVectorClass<StringClass> file_list;
- //
- // Loop over each of the dropped files and add them to the current mix file
- //
- for (int index = 0; index < file_count; index ++) {
-
- //
- // Add this file to a list so we can batch add all the files...
- //
- TCHAR filename[_MAX_PATH];
- ::DragQueryFile (hDropInfo, index, filename, _MAX_PATH);
- file_list.Add (filename);
- }
- ::DragFinish(hDropInfo);
- //
- // Add the mix files to the list
- //
- Add_To_Mix_File (doc->GetPathName (), file_list);
- doc->Reload_Views ();
- }
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Add_To_Mix_File
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- CMainFrame::Add_To_Mix_File (const char *mix_filename, const char *filename)
- {
- DynamicVectorClass<StringClass> file_list;
- file_list.Add (filename);
- Add_To_Mix_File (mix_filename, file_list);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Add_To_Mix_File
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- CMainFrame::Add_To_Mix_File (const char *mix_filename, DynamicVectorClass<StringClass> &new_file_list)
- {
- //
- // Set the current directory...
- //
- CString path = Strip_Filename_From_Path (mix_filename);
- if (path.GetLength () > 0) {
- ::SetCurrentDirectory (path);
- }
- //
- // Get access to the mix file in qestion
- //
- MixFileFactoryClass *mix_factory = new MixFileFactoryClass (mix_filename, _TheFileFactory);
- if (mix_factory->Is_Valid () && mix_factory->Build_Internal_Filename_List ()) {
- //
- // Now add the new files into the mix file...
- //
- for (int index = 0; index < new_file_list.Count (); index ++) {
- CString filename = ::Get_Filename_From_Path (new_file_list[index]);
- mix_factory->Delete_File (filename);
- mix_factory->Add_File (new_file_list[index], filename);
- }
- //
- // Do it!
- //
- mix_factory->Flush_Changes ();
- }
- //
- // Free the mix factory
- //
- delete mix_factory;
- mix_factory = NULL;
- return ;
- }
|