//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //===========================================================================// #include "cbase.h" #include "StatusWindow.h" #include "cmdlib.h" #include #include "workspace.h" #include "workspacemanager.h" #include "workspacebrowser.h" #include "tier2/riff.h" #include "sentence.h" #include "utlbuffer.h" #include "SoundEmitterSystem/isoundemittersystembase.h" #include #include "MultipleRequest.h" bool SceneManager_HasWindowStyle( mxWindow *w, int bits ) { HWND wnd = (HWND)w->getHandle(); DWORD style = GetWindowLong( wnd, GWL_STYLE ); return ( style & bits ) ? true : false; } bool SceneManager_HasWindowExStyle( mxWindow *w, int bits ) { HWND wnd = (HWND)w->getHandle(); DWORD style = GetWindowLong( wnd, GWL_EXSTYLE ); return ( style & bits ) ? true : false; } void SceneManager_AddWindowStyle( mxWindow *w, int addbits ) { HWND wnd = (HWND)w->getHandle(); DWORD style = GetWindowLong( wnd, GWL_STYLE ); style |= addbits; SetWindowLong( wnd, GWL_STYLE, style ); } void SceneManager_AddWindowExStyle( mxWindow *w, int addbits ) { HWND wnd = (HWND)w->getHandle(); DWORD style = GetWindowLong( wnd, GWL_EXSTYLE ); style |= addbits; SetWindowLong( wnd, GWL_EXSTYLE, style ); } void SceneManager_RemoveWindowStyle( mxWindow *w, int removebits ) { HWND wnd = (HWND)w->getHandle(); DWORD style = GetWindowLong( wnd, GWL_STYLE ); style &= ~removebits; SetWindowLong( wnd, GWL_STYLE, style ); } void SceneManager_RemoveWindowExStyle( mxWindow *w, int removebits ) { HWND wnd = (HWND)w->getHandle(); DWORD style = GetWindowLong( wnd, GWL_EXSTYLE ); style &= ~removebits; SetWindowLong( wnd, GWL_EXSTYLE, style ); } //----------------------------------------------------------------------------- // Purpose: // Input : *w - //----------------------------------------------------------------------------- void SceneManager_MakeToolWindow( mxWindow *w, bool smallcaption ) { SceneManager_AddWindowStyle( w, WS_VISIBLE | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS ); if ( smallcaption ) { SceneManager_AddWindowExStyle( w, WS_EX_OVERLAPPEDWINDOW ); SceneManager_AddWindowExStyle( w, WS_EX_TOOLWINDOW ); } else { SceneManager_RemoveWindowStyle( w, WS_SYSMENU ); } } char *va( const char *fmt, ... ) { va_list args; static char output[4][1024]; static int outbuffer = 0; outbuffer++; va_start( args, fmt ); vprintf( fmt, args ); vsprintf( output[ outbuffer & 3 ], fmt, args ); return output[ outbuffer & 3 ]; } void Con_Overprintf( const char *fmt, ... ) { va_list args; static char output[1024]; va_start( args, fmt ); vprintf( fmt, args ); vsprintf( output, fmt, args ); if ( !g_pStatusWindow ) { return; } g_pStatusWindow->StatusPrint( CONSOLE_R, CONSOLE_G, CONSOLE_B, true, output ); } void Con_Printf( const char *fmt, ... ) { va_list args; static char output[1024]; va_start( args, fmt ); // vprintf( fmt, args ); vsprintf( output, fmt, args ); va_end( args ); if ( !g_pStatusWindow ) { return; } g_pStatusWindow->StatusPrint( CONSOLE_R, CONSOLE_G, CONSOLE_B, false, output ); } void Con_ColorPrintf( int r, int g, int b, const char *fmt, ... ) { va_list args; static char output[1024]; va_start( args, fmt ); vprintf( fmt, args ); vsprintf( output, fmt, args ); if ( !g_pStatusWindow ) { return; } g_pStatusWindow->StatusPrint( r, g, b, false, output ); } //----------------------------------------------------------------------------- // Purpose: // Input : *pname - // Output : char //----------------------------------------------------------------------------- char *SceneManager_MakeWindowsSlashes( char *pname ) { static char returnString[ 4096 ]; strcpy( returnString, pname ); pname = returnString; while ( *pname ) { if ( *pname == '/' ) *pname = '\\'; pname++; } return returnString; } //----------------------------------------------------------------------------- // Purpose: // Output : const char //----------------------------------------------------------------------------- const char *SceneManager_GetGameDirectory( void ) { // Todo: Make SceneManager only use the filesystem read/write paths. return gamedir; } //----------------------------------------------------------------------------- // Purpose: Takes a full path and determines if the file exists on the disk // Input : *filename - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool SceneManager_FullpathFileExists( const char *filename ) { // Should be a full path Assert( strchr( filename, ':' ) ); struct _stat buf; int result = _stat( filename, &buf ); if ( result != -1 ) return true; return false; } //----------------------------------------------------------------------------- // Purpose: converts an english string to unicode //----------------------------------------------------------------------------- int ConvertANSIToUnicode(const char *ansi, wchar_t *unicode, int unicodeBufferSize) { return ::MultiByteToWideChar(CP_ACP, 0, ansi, -1, unicode, unicodeBufferSize); } //----------------------------------------------------------------------------- // Purpose: converts an unicode string to an english string //----------------------------------------------------------------------------- int ConvertUnicodeToANSI(const wchar_t *unicode, char *ansi, int ansiBufferSize) { return ::WideCharToMultiByte(CP_ACP, 0, unicode, -1, ansi, ansiBufferSize, NULL, NULL); } int Sys_Exec( const char *pProgName, const char *pCmdLine, bool verbose ) { #if 0 int count = 0; char cmdLine[1024]; STARTUPINFO si; memset( &si, 0, sizeof(si) ); si.cb = sizeof(si); //GetStartupInfo( &si ); sprintf( cmdLine, "%s %s", pProgName, pCmdLine ); PROCESS_INFORMATION pi; memset( &pi, 0, sizeof( pi ) ); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; if ( CreateProcess( NULL, cmdLine, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi ) ) { WaitForSingleObject( pi.hProcess, INFINITE ); /* do { WaitForInputIdle( pi.hProcess, 100 ); count++; } while ( count < 100 ); */ /* DWORD exitCode = STILL_ACTIVE; do { BOOL ok = GetExitCodeProcess( pi.hProcess, &exitCode ); if ( !ok ) break; Sleep( 100 ); } while ( exitCode == STILL_ACTIVE ); */ DWORD exitCode; GetExitCodeProcess( pi.hProcess, &exitCode ); Con_Printf( "Finished\n" ); CloseHandle( pi.hProcess ); return (int)exitCode; } else { char *lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); Con_Printf( "error %s\n", lpMsgBuf ); LocalFree( (HLOCAL)lpMsgBuf ); } return false; #else char tmp[1024]; sprintf( tmp, "%s %s\n", pProgName, pCmdLine ); _strlwr( tmp ); int iret = system( tmp ); if ( iret != 0 && verbose ) { Con_Printf( "Execution failed: %s\n", tmp ); } return iret; #endif } //----------------------------------------------------------------------------- // Checks it out/ checks it in baby //----------------------------------------------------------------------------- static void SceneManager_VSSCheckout( char const *pUserName, char const *pProjectDir, char const* pRelativeDir, char const* pDestPath, char const* pFileNameWithExtension ) { char buf[1024]; // Check for the existence of the file in source safe... sprintf( buf, "filetype %s/%s%s -O- -y%s\n", pProjectDir, pRelativeDir, pFileNameWithExtension, pUserName ); int retVal = Sys_Exec( "ss.exe", buf, false ); if (retVal != 0 ) { Con_Printf( "File %s missing from VSS\n", pFileNameWithExtension ); return; } // It's there, try to check it out sprintf( buf, "checkout %s/%s%s -GL%s -GWA -O- -y%s\n", pProjectDir, pRelativeDir, pFileNameWithExtension, pDestPath, pUserName ); Sys_Exec( "ss.exe", buf, true ); } //----------------------------------------------------------------------------- // Checks it out/ checks it in baby //----------------------------------------------------------------------------- static void SceneManager_VSSCheckin( char const *pUserName, char const *pProjectDir, char const* pRelativeDir, char const* pDestPath, char const* pFileNameWithExtension ) { char buf[1024]; // Check for the existence of the file on disk. If it's not there, don't bother sprintf( buf, "%s%s", pDestPath, pFileNameWithExtension ); struct _stat statbuf; int result = _stat( buf, &statbuf ); if (result != 0) return; // Check for the existence of the file in source safe... sprintf( buf, "filetype %s/%s%s -O- -y%s\n", pProjectDir, pRelativeDir, pFileNameWithExtension, pUserName ); int retVal = Sys_Exec( "ss.exe", buf, false ); if (retVal != 0) { sprintf( buf, "Cp %s -O- -y%s\n", pProjectDir , pUserName ); Sys_Exec( "ss.exe", buf, true ); // Try to add the file to source safe... sprintf( buf, "add %s%s -GL%s -O- -I- -y%s\n", pRelativeDir, pFileNameWithExtension, pDestPath, pUserName ); Sys_Exec( "ss.exe", buf, true ); } else { // It's there, just check it in sprintf( buf, "checkin %s/%s%s -GL%s -O- -I- -y%s\n", pProjectDir, pRelativeDir, pFileNameWithExtension, pDestPath, pUserName ); Sys_Exec( "ss.exe", buf, true ); } } void SplitFileName( char const *in, char *path, int maxpath, char *filename, int maxfilename ) { char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; _splitpath( in, drive, dir, fname, ext ); if ( dir[0] ) { Q_snprintf( path, maxpath, "\\%s", dir ); } else { path[0] = 0; } Q_snprintf( filename, maxfilename, "%s%s", fname, ext ); } void VSS_Checkout( char const *name, bool updatestaticons /*= true*/ ) { CWorkspace *ws = GetWorkspaceManager()->GetBrowser()->GetWorkspace(); if ( !ws ) { return; } if ( filesystem->IsFileWritable( name ) ) { return; } char path[ 256 ]; char filename[ 256 ]; SplitFileName( name, path, sizeof( path ), filename, sizeof( filename ) ); Con_ColorPrintf( 200, 200, 100, "VSS Checkout: '%s'\n", name ); SceneManager_VSSCheckout( ws->GetVSSUserName(), ws->GetVSSProject(), path, va( "%s%s", gamedir, path ), filename ); if ( updatestaticons ) { GetWorkspaceManager()->RefreshBrowsers(); } } void VSS_Checkin( char const *name, bool updatestaticons /*= true*/ ) { CWorkspace *ws = GetWorkspaceManager()->GetBrowser()->GetWorkspace(); if ( !ws ) { return; } if ( !filesystem->IsFileWritable( name ) ) { return; } char path[ 256 ]; char filename[ 256 ]; SplitFileName( name, path, sizeof( path ), filename, sizeof( filename ) ); Con_ColorPrintf( 200, 200, 100, "VSS Checkin: '%s'\n", name ); SceneManager_VSSCheckin( ws->GetVSSUserName(), ws->GetVSSProject(), path, va( "%s%s", gamedir, path ), filename ); if ( updatestaticons ) { GetWorkspaceManager()->RefreshBrowsers(); } } //----------------------------------------------------------------------------- // Purpose: Implements the RIFF i/o interface on stdio //----------------------------------------------------------------------------- class StdIOReadBinary : public IFileReadBinary { public: int open( const char *pFileName ) { return (int)filesystem->Open( pFileName, "rb" ); } int read( void *pOutput, int size, int file ) { if ( !file ) return 0; return filesystem->Read( pOutput, size, (FileHandle_t)file ); } void seek( int file, int pos ) { if ( !file ) return; filesystem->Seek( (FileHandle_t)file, pos, FILESYSTEM_SEEK_HEAD ); } unsigned int tell( int file ) { if ( !file ) return 0; return filesystem->Tell( (FileHandle_t)file ); } unsigned int size( int file ) { if ( !file ) return 0; return filesystem->Size( (FileHandle_t)file ); } void close( int file ) { if ( !file ) return; filesystem->Close( (FileHandle_t)file ); } }; class StdIOWriteBinary : public IFileWriteBinary { public: int create( const char *pFileName ) { return (int)filesystem->Open( pFileName, "wb" ); } int write( void *pData, int size, int file ) { return filesystem->Write( pData, size, (FileHandle_t)file ); } void close( int file ) { filesystem->Close( (FileHandle_t)file ); } void seek( int file, int pos ) { filesystem->Seek( (FileHandle_t)file, pos, FILESYSTEM_SEEK_HEAD ); } unsigned int tell( int file ) { return filesystem->Tell( (FileHandle_t)file ); } }; static StdIOReadBinary io_in; static StdIOWriteBinary io_out; #define RIFF_WAVE MAKEID('W','A','V','E') #define WAVE_FMT MAKEID('f','m','t',' ') #define WAVE_DATA MAKEID('d','a','t','a') #define WAVE_FACT MAKEID('f','a','c','t') #define WAVE_CUE MAKEID('c','u','e',' ') //----------------------------------------------------------------------------- // Purpose: // Input : &walk - //----------------------------------------------------------------------------- static void SceneManager_ParseSentence( CSentence& sentence, IterateRIFF &walk ) { CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); buf.EnsureCapacity( walk.ChunkSize() ); walk.ChunkRead( buf.Base() ); buf.SeekPut( CUtlBuffer::SEEK_HEAD, walk.ChunkSize() ); sentence.InitFromDataChunk( buf.Base(), buf.TellPut() ); } bool SceneManager_LoadSentenceFromWavFileUsingIO( char const *wavfile, CSentence& sentence, IFileReadBinary& io ) { sentence.Reset(); InFileRIFF riff( wavfile, io ); // UNDONE: Don't use printf to handle errors if ( riff.RIFFName() != RIFF_WAVE ) { return false; } // set up the iterator for the whole file (root RIFF is a chunk) IterateRIFF walk( riff, riff.RIFFSize() ); // This chunk must be first as it contains the wave's format // break out when we've parsed it bool found = false; while ( walk.ChunkAvailable() && !found ) { switch( walk.ChunkName() ) { case WAVE_VALVEDATA: { found = true; SceneManager_ParseSentence( sentence, walk ); } break; } walk.ChunkNext(); } return true; } bool SceneManager_LoadSentenceFromWavFile( char const *wavfile, CSentence& sentence ) { return SceneManager_LoadSentenceFromWavFileUsingIO( wavfile, sentence, io_in ); } //----------------------------------------------------------------------------- // Purpose: // Input : store - //----------------------------------------------------------------------------- static void SceneManager_StoreValveDataChunk( CSentence& sentence, IterateOutputRIFF& store ) { // Buffer and dump data CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); sentence.SaveToBuffer( buf ); // Copy into store store.ChunkWriteData( buf.Base(), buf.TellPut() ); } bool SceneManager_SaveSentenceToWavFile( char const *wavfile, CSentence& sentence ) { char tempfile[ 512 ]; Q_StripExtension( wavfile, tempfile, sizeof( tempfile ) ); Q_DefaultExtension( tempfile, ".tmp", sizeof( tempfile ) ); if ( filesystem->FileExists( tempfile, "GAME" ) ) { filesystem->RemoveFile( tempfile, "GAME" ); } if ( !filesystem->IsFileWritable( wavfile ) ) { int retval = MultipleRequest( va( "Check out '%s'?", wavfile ) ); if ( retval != 0 ) return false; VSS_Checkout( wavfile ); } if ( !filesystem->IsFileWritable( wavfile ) ) { Con_Printf( "%s is not writable, can't save sentence data to file\n", wavfile ); return false; } // Rename original wavfile to temp filesystem->RenameFile( wavfile, tempfile, "GAME" ); // NOTE: Put this in it's own scope so that the destructor for outfileRFF actually closes the file!!!! { // Read from Temp InFileRIFF riff( tempfile, io_in ); Assert( riff.RIFFName() == RIFF_WAVE ); // set up the iterator for the whole file (root RIFF is a chunk) IterateRIFF walk( riff, riff.RIFFSize() ); // And put data back into original wavfile by name OutFileRIFF riffout( wavfile, io_out ); IterateOutputRIFF store( riffout ); bool wordtrackwritten = false; // Walk input chunks and copy to output while ( walk.ChunkAvailable() ) { store.ChunkStart( walk.ChunkName() ); switch ( walk.ChunkName() ) { case WAVE_VALVEDATA: { // Overwrite data SceneManager_StoreValveDataChunk( sentence, store ); wordtrackwritten = true; } break; default: store.CopyChunkData( walk ); break; } store.ChunkFinish(); walk.ChunkNext(); } // If we didn't write it above, write it now if ( !wordtrackwritten ) { store.ChunkStart( WAVE_VALVEDATA ); SceneManager_StoreValveDataChunk( sentence, store ); store.ChunkFinish(); } } // Remove temp file filesystem->RemoveFile( tempfile, NULL ); return true; } void SceneManager_LoadWindowPositions( KeyValues *kv, mxWindow *wnd ) { bool zoomed = kv->GetInt( "zoomed", 0 ) ? true : false; int x = kv->GetInt( "x", 0 ); int y = kv->GetInt( "y", 0 ); int w = kv->GetInt( "w", 400 ); int h = kv->GetInt( "h", 300 ); wnd->setBounds( x, y, w, h ); if ( zoomed ) { ShowWindow( (HWND)wnd->getHandle(), SW_SHOWMAXIMIZED ); } } static void Indent( CUtlBuffer& buf, int numtabs ) { for ( int i = 0 ; i < numtabs; i++ ) { buf.Printf( "\t" ); } } void SceneManager_SaveWindowPositions( CUtlBuffer& buf, int indent, mxWindow *wnd ) { int x, y, w, h; x = wnd->x(); y = wnd->y(); w = wnd->w(); h = wnd->h(); // xpos and ypos are screen space POINT pt; pt.x = x; pt.y = y; // Convert from screen space to relative to client area of parent window so // the setBounds == MoveWindow call will offset to the same location if ( wnd->getParent() ) { ScreenToClient( (HWND)wnd->getParent()->getHandle(), &pt ); x = (short)pt.x; y = (short)pt.y; } Indent( buf, indent ); buf.Printf( "\"x\"\t\"%i\"\n", x ); Indent( buf, indent ); buf.Printf( "\"y\"\t\"%i\"\n", y ); Indent( buf, indent ); buf.Printf( "\"w\"\t\"%i\"\n", w ); Indent( buf, indent ); buf.Printf( "\"h\"\t\"%i\"\n", h ); bool zoomed = IsZoomed( (HWND)wnd->getHandle() ) ? true : false; Indent( buf, indent ); buf.Printf( "\"zoomed\"\t\"%i\"\n", zoomed ? 1 : 0 ); } #if defined( _WIN32 ) || defined( WIN32 ) #define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/') #else //_WIN32 #define PATHSEPARATOR(c) ((c) == '/') #endif //_WIN32 static bool charsmatch( char c1, char c2 ) { if ( tolower( c1 ) == tolower( c2 ) ) return true; if ( PATHSEPARATOR( c1 ) && PATHSEPARATOR( c2 ) ) return true; return false; } char *Q_stristr_slash( char const *pStr, char const *pSearch ) { AssertValidStringPtr(pStr); AssertValidStringPtr(pSearch); if (!pStr || !pSearch) return 0; char const* pLetter = pStr; // Check the entire string while (*pLetter != 0) { // Skip over non-matches if ( charsmatch( *pLetter, *pSearch ) ) { // Check for match char const* pMatch = pLetter + 1; char const* pTest = pSearch + 1; while (*pTest != 0) { // We've run off the end; don't bother. if (*pMatch == 0) return 0; if ( !charsmatch( *pMatch, *pTest ) ) break; ++pMatch; ++pTest; } // Found a match! if (*pTest == 0) return (char *)pLetter; } ++pLetter; } return 0; } //----------------------------------------------------------------------------- // Purpose: // Input : *filename - //----------------------------------------------------------------------------- void MakeFileWriteable( const char *filename ) { Assert( filesystem ); char fullpath[ 512 ]; if (filesystem->GetLocalPath( filename, fullpath, sizeof(fullpath) )) { Q_FixSlashes( fullpath ); SetFileAttributes( fullpath, FILE_ATTRIBUTE_NORMAL ); } }