summaryrefslogtreecommitdiff
path: root/utils/FileSystemOpenDialog
diff options
context:
space:
mode:
Diffstat (limited to 'utils/FileSystemOpenDialog')
-rw-r--r--utils/FileSystemOpenDialog/FileDialogApp.cpp73
-rw-r--r--utils/FileSystemOpenDialog/FileDialogApp.h52
-rw-r--r--utils/FileSystemOpenDialog/FileSystemOpenDialog.rc192
-rw-r--r--utils/FileSystemOpenDialog/FileSystemOpenDlg.cpp997
-rw-r--r--utils/FileSystemOpenDialog/FileSystemOpenDlg.h146
-rw-r--r--utils/FileSystemOpenDialog/StdAfx.cpp15
-rw-r--r--utils/FileSystemOpenDialog/StdAfx.h52
-rw-r--r--utils/FileSystemOpenDialog/filesystemopendialog.vpc76
-rw-r--r--utils/FileSystemOpenDialog/res/SteamFileDialog.rc213
-rw-r--r--utils/FileSystemOpenDialog/res/label_file.bmpbin0 -> 36920 bytes
-rw-r--r--utils/FileSystemOpenDialog/res/label_fo.bmpbin0 -> 36920 bytes
-rw-r--r--utils/FileSystemOpenDialog/res/label_mdl.bmpbin0 -> 36920 bytes
-rw-r--r--utils/FileSystemOpenDialog/resource.h26
13 files changed, 1642 insertions, 0 deletions
diff --git a/utils/FileSystemOpenDialog/FileDialogApp.cpp b/utils/FileSystemOpenDialog/FileDialogApp.cpp
new file mode 100644
index 0000000..7c32ab6
--- /dev/null
+++ b/utils/FileSystemOpenDialog/FileDialogApp.cpp
@@ -0,0 +1,73 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+// SteamFileDialog.cpp : Defines the initialization routines for the DLL.
+//
+
+#include "stdafx.h"
+#include "FileDialogApp.h"
+#include "interface.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//
+// Note!
+//
+// If this DLL is dynamically linked against the MFC
+// DLLs, any functions exported from this DLL which
+// call into MFC must have the AFX_MANAGE_STATE macro
+// added at the very beginning of the function.
+//
+// For example:
+//
+// extern "C" BOOL PASCAL EXPORT ExportedFunction()
+// {
+// AFX_MANAGE_STATE(AfxGetStaticModuleState());
+// // normal function body here
+// }
+//
+// It is very important that this macro appear in each
+// function, prior to any calls into MFC. This means that
+// it must appear as the first statement within the
+// function, even before any object variable declarations
+// as their constructors may generate calls into the MFC
+// DLL.
+//
+// Please see MFC Technical Notes 33 and 58 for additional
+// details.
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CSteamFileDialogApp
+
+BEGIN_MESSAGE_MAP(CSteamFileDialogApp, CWinApp)
+ //{{AFX_MSG_MAP(CSteamFileDialogApp)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CSteamFileDialogApp construction
+
+CSteamFileDialogApp::CSteamFileDialogApp()
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CSteamFileDialogApp object
+
+CSteamFileDialogApp theApp;
+
+
+
diff --git a/utils/FileSystemOpenDialog/FileDialogApp.h b/utils/FileSystemOpenDialog/FileDialogApp.h
new file mode 100644
index 0000000..6a34938
--- /dev/null
+++ b/utils/FileSystemOpenDialog/FileDialogApp.h
@@ -0,0 +1,52 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+// SteamFileDialog.h : main header file for the STEAMFILEDIALOG DLL
+//
+
+#if !defined(AFX_STEAMFILEDIALOG_H__BF4B825D_4E34_443E_84D2_6212C043388D__INCLUDED_)
+#define AFX_STEAMFILEDIALOG_H__BF4B825D_4E34_443E_84D2_6212C043388D__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // main symbols
+
+/////////////////////////////////////////////////////////////////////////////
+// CSteamFileDialogApp
+// See SteamFileDialog.cpp for the implementation of this class
+//
+
+class CSteamFileDialogApp : public CWinApp
+{
+public:
+ CSteamFileDialogApp();
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CSteamFileDialogApp)
+ //}}AFX_VIRTUAL
+
+ //{{AFX_MSG(CSteamFileDialogApp)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STEAMFILEDIALOG_H__BF4B825D_4E34_443E_84D2_6212C043388D__INCLUDED_)
diff --git a/utils/FileSystemOpenDialog/FileSystemOpenDialog.rc b/utils/FileSystemOpenDialog/FileSystemOpenDialog.rc
new file mode 100644
index 0000000..6150962
--- /dev/null
+++ b/utils/FileSystemOpenDialog/FileSystemOpenDialog.rc
@@ -0,0 +1,192 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif //_WIN32\r\n"
+ "#include ""res\\SteamFileDialog.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#endif\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "\0"
+ VALUE "FileDescription", "SteamFileDialog DLL\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "SteamFileDialog\0"
+ VALUE "LegalCopyright", "Copyright (C) 2004\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "SteamFileDialog.DLL\0"
+ VALUE "ProductName", "SteamFileDialog Dynamic Link Library\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_FILESYSTEM_OPENDIALOG DIALOG DISCARDABLE 0, 0, 573, 374
+STYLE WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+CAPTION "Open"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "List1",IDC_FILE_LIST,"SysListView32",LVS_OWNERDRAWFIXED |
+ WS_BORDER | WS_TABSTOP,7,29,559,301
+ EDITTEXT IDC_FILENAME,48,335,362,14,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "&Open",IDOK,516,335,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,516,353,50,14
+ PUSHBUTTON "&Up",IDC_UP_BUTTON,416,7,19,14
+ LTEXT "File &name:",IDC_FILENAME_LABEL,7,338,33,8
+ LTEXT "Look in:",IDC_STATIC,7,10,26,8
+ EDITTEXT IDC_LOOKIN,48,7,362,14,ES_AUTOHSCROLL | ES_READONLY |
+ NOT WS_TABSTOP
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_FILESYSTEM_OPENDIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 566
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 367
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_LABEL_MDL BITMAP DISCARDABLE "res\\label_mdl.bmp"
+IDB_LABEL_FOLDER BITMAP DISCARDABLE "res\\label_fo.bmp"
+IDB_LABEL_FILE BITMAP DISCARDABLE "res\\label_file.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_NO_RELATIVE_PATH "The selected file is not under your game's directory, so it can't be used."
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif //_WIN32
+#include "res\SteamFileDialog.rc2" // non-Microsoft Visual C++ edited resources
+#include "afxres.rc" // Standard components
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/utils/FileSystemOpenDialog/FileSystemOpenDlg.cpp b/utils/FileSystemOpenDialog/FileSystemOpenDlg.cpp
new file mode 100644
index 0000000..cb7b6a0
--- /dev/null
+++ b/utils/FileSystemOpenDialog/FileSystemOpenDlg.cpp
@@ -0,0 +1,997 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+// FileSystemOpenDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "FileSystemOpenDlg.h"
+#include "jpeglib/jpeglib.h"
+#include "utldict.h"
+#include "resource.h"
+#include "ifilesystemopendialog.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+
+CFileInfo::CFileInfo()
+{
+ m_pBitmap = NULL;
+}
+
+
+CFileInfo::~CFileInfo()
+{
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// This caches the thumbnail bitmaps we generate to speed up browsing.
+/////////////////////////////////////////////////////////////////////////////
+
+class CBitmapCache
+{
+public:
+ CBitmapCache()
+ {
+ m_CurMemoryUsage = 0;
+ m_MaxMemoryUsage = 1024 * 1024 * 6;
+ }
+
+ void AddToCache( CBitmap *pBitmap, const char *pName, int memoryUsage, bool bLock )
+ {
+ Assert( m_Bitmaps.Find( pName ) == -1 );
+ m_CurMemoryUsage += memoryUsage;
+
+ CBitmapCacheEntry newEntry;
+ newEntry.m_pBitmap = pBitmap;
+ newEntry.m_MemoryUsage = memoryUsage;
+ newEntry.m_bLocked = bLock;
+ m_Bitmaps.Insert( pName, newEntry );
+
+ EnsureMemoryUsage();
+ }
+
+ CBitmap* Find( const char *pName )
+ {
+ int i = m_Bitmaps.Find( pName );
+ if ( i == -1 )
+ return NULL;
+ else
+ return m_Bitmaps[i].m_pBitmap;
+ }
+
+ void UnlockAll()
+ {
+ for ( int i=m_Bitmaps.First(); i != m_Bitmaps.InvalidIndex(); i=m_Bitmaps.Next( i ) )
+ {
+ m_Bitmaps[i].m_bLocked = false;
+ }
+ }
+
+private:
+
+ void EnsureMemoryUsage()
+ {
+ while ( m_CurMemoryUsage > m_MaxMemoryUsage )
+ {
+ // Free something.
+ bool bFreed = false;
+ for ( int i=m_Bitmaps.First(); i != m_Bitmaps.InvalidIndex(); i=m_Bitmaps.Next( i ) )
+ {
+ if ( !m_Bitmaps[i].m_bLocked )
+ {
+ delete m_Bitmaps[i].m_pBitmap;
+ m_CurMemoryUsage -= m_Bitmaps[i].m_MemoryUsage;
+ m_Bitmaps.RemoveAt( i );
+ break;
+ }
+ }
+
+ // Nothing left to free?
+ if ( !bFreed )
+ return;
+ }
+ }
+
+private:
+
+ class CBitmapCacheEntry
+ {
+ public:
+ CBitmap *m_pBitmap;
+ int m_MemoryUsage;
+ bool m_bLocked;
+ };
+
+ CUtlDict<CBitmapCacheEntry,int> m_Bitmaps;
+ int m_CurMemoryUsage;
+ int m_MaxMemoryUsage;
+};
+
+CBitmapCache g_BitmapCache;
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CFileSystemOpenDlg dialog
+
+CFileSystemOpenDlg::CFileSystemOpenDlg(CreateInterfaceFn factory, CWnd* pParent )
+ : CDialog(CFileSystemOpenDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CFileSystemOpenDlg)
+ //}}AFX_DATA_INIT
+ m_pFileSystem = (IFileSystem*)factory( FILESYSTEM_INTERFACE_VERSION, NULL );
+ if ( !m_pFileSystem )
+ {
+ Error( "Unable to connect to %s!\n", FILESYSTEM_INTERFACE_VERSION );
+ }
+
+ m_bFilterMdlAndJpgFiles = false;
+}
+
+void CFileSystemOpenDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CFileSystemOpenDlg)
+ DDX_Control(pDX, IDC_FILENAME_LABEL, m_FilenameLabel);
+ DDX_Control(pDX, IDC_FILENAME, m_FilenameControl);
+ DDX_Control(pDX, IDC_LOOKIN, m_LookInLabel);
+ DDX_Control(pDX, IDC_FILE_LIST, m_FileList);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CFileSystemOpenDlg, CDialog)
+ //{{AFX_MSG_MAP(CFileSystemOpenDlg)
+ ON_WM_CREATE()
+ ON_WM_SIZE()
+ ON_NOTIFY(NM_DBLCLK, IDC_FILE_LIST, OnDblclkFileList)
+ ON_BN_CLICKED(IDC_UP_BUTTON, OnUpButton)
+ ON_NOTIFY(LVN_ITEMCHANGED, IDC_FILE_LIST, OnItemchangedFileList)
+ ON_WM_KEYDOWN()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CFileSystemOpenDlg message handlers
+
+void CFileSystemOpenDlg::OnOK()
+{
+ // Make sure it's a valid filename.
+ CString testFilename;
+ m_FilenameControl.GetWindowText( testFilename );
+
+ CString fullFilename = m_CurrentDir + "\\" + testFilename;
+ if ( m_pFileSystem->IsDirectory( fullFilename, GetPathID() ) )
+ {
+ m_CurrentDir = fullFilename;
+ PopulateListControl();
+ }
+ else if ( m_pFileSystem->FileExists( fullFilename, GetPathID() ) )
+ {
+ m_Filename = fullFilename;
+
+ // Translate .jpg to .mdl?
+ if ( m_bFilterMdlAndJpgFiles )
+ {
+ char tempFilename[MAX_PATH];
+ V_strcpy_safe( tempFilename, fullFilename );
+ char *pPos = strrchr( tempFilename, '.' );
+ if ( pPos )
+ {
+ if ( Q_stricmp( pPos, ".jpeg" ) == 0 || Q_stricmp( pPos, ".jpg" ) == 0 )
+ {
+ pPos[0] = 0;
+ V_strcat_safe( tempFilename, ".mdl" );
+ m_Filename = tempFilename;
+ }
+ }
+ }
+
+ EndDialog( IDOK );
+ }
+ else
+ {
+ // No file or directory here.
+ CString str;
+ str.FormatMessage( "File %1!s! doesn't exist.", (const char*)fullFilename );
+ AfxMessageBox( str, MB_OK );
+ }
+}
+
+void CFileSystemOpenDlg::SetInitialDir( const char *pDir, const char *pPathID )
+{
+ m_CurrentDir = pDir;
+ if ( pPathID )
+ m_PathIDString = pPathID;
+ else
+ m_PathIDString = "";
+}
+
+CString CFileSystemOpenDlg::GetFilename() const
+{
+ return m_Filename;
+}
+
+
+BOOL CFileSystemOpenDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ // Setup our anchor list.
+ AddAnchor( IDC_FILE_LIST, 2, 2 );
+ AddAnchor( IDC_FILE_LIST, 3, 3 );
+
+ AddAnchor( IDC_FILENAME, 1, 3 );
+ AddAnchor( IDC_FILENAME, 3, 3 );
+ AddAnchor( IDC_FILENAME, 2, 2 );
+
+ AddAnchor( IDC_FILENAME_LABEL, 0, 0 );
+ AddAnchor( IDC_FILENAME_LABEL, 2, 0 );
+ AddAnchor( IDC_FILENAME_LABEL, 1, 3 );
+ AddAnchor( IDC_FILENAME_LABEL, 3, 3 );
+
+ AddAnchor( IDOK, 0, 2 );
+ AddAnchor( IDOK, 2, 2 );
+ AddAnchor( IDOK, 1, 3 );
+ AddAnchor( IDOK, 3, 3 );
+
+ AddAnchor( IDCANCEL, 0, 2 );
+ AddAnchor( IDCANCEL, 2, 2 );
+ AddAnchor( IDCANCEL, 1, 3 );
+ AddAnchor( IDCANCEL, 3, 3 );
+
+ AddAnchor( IDC_LOOKIN, 2, 2 );
+
+ AddAnchor( IDC_UP_BUTTON, 0, 2 );
+ AddAnchor( IDC_UP_BUTTON, 2, 2 );
+
+
+ // Setup our image list.
+ m_ImageList.Create( PREVIEW_IMAGE_SIZE, PREVIEW_IMAGE_SIZE, ILC_COLOR32, 0, 512 );
+
+ m_BitmapFolder.LoadBitmap( IDB_LABEL_FOLDER );
+ m_iLabel_Folder = m_ImageList.Add( &m_BitmapFolder, (CBitmap*)NULL );
+
+ m_BitmapMdl.LoadBitmap( IDB_LABEL_MDL );
+ m_iLabel_Mdl = m_ImageList.Add( &m_BitmapMdl, (CBitmap*)NULL );
+
+ m_BitmapFile.LoadBitmap( IDB_LABEL_FILE );
+ m_iLabel_File = m_ImageList.Add( &m_BitmapFile, (CBitmap*)NULL );
+
+ m_FileList.SetImageList( &m_ImageList, LVSIL_NORMAL );
+
+ // Populate the list with the contents of our current directory.
+ PopulateListControl();
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CFileSystemOpenDlg::GetEntries( const char *pMask, CUtlVector<CString> &entries, GetEntriesMode_t mode )
+{
+ CString searchStr = m_CurrentDir + "\\" + pMask;
+
+ // Workaround Steam bug.
+ if ( searchStr == ".\\*.*" )
+ searchStr = "*.*";
+
+ FileFindHandle_t handle;
+ const char *pFile = m_pFileSystem->FindFirst( searchStr, &handle );
+ while ( pFile )
+ {
+ bool bIsDir = m_pFileSystem->FindIsDirectory( handle );
+ if ( (mode == GETENTRIES_DIRECTORIES_ONLY && bIsDir) || (mode == GETENTRIES_FILES_ONLY && !bIsDir) )
+ {
+ entries.AddToTail( pFile );
+ }
+
+ pFile = m_pFileSystem->FindNext( handle );
+ }
+ m_pFileSystem->FindClose( handle );
+}
+
+
+
+class CJpegSourceMgr : public jpeg_source_mgr
+{
+public:
+ CJpegSourceMgr()
+ {
+ this->init_source = &CJpegSourceMgr::imp_init_source;
+ this->fill_input_buffer = &CJpegSourceMgr::imp_fill_input_buffer;
+ this->skip_input_data = &CJpegSourceMgr::imp_skip_input_data;
+ this->resync_to_restart = &CJpegSourceMgr::imp_resync_to_restart;
+ this->term_source = &CJpegSourceMgr::imp_term_source;
+
+ this->next_input_byte = 0;
+ this->bytes_in_buffer = 0;
+ }
+
+ bool Init( IFileSystem *pFileSystem, FileHandle_t fp )
+ {
+ m_Data.SetSize( pFileSystem->Size( fp ) );
+ return pFileSystem->Read( m_Data.Base(), m_Data.Count(), fp ) == m_Data.Count();
+ }
+
+ static void imp_init_source(j_decompress_ptr cinfo)
+ {
+ }
+
+ static boolean imp_fill_input_buffer(j_decompress_ptr cinfo)
+ {
+ Assert( false ); // They should never need to call these functions since we give them all the data up front.
+ return 0;
+ }
+
+ static void imp_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+ {
+ AssertOnce( false ); // They should never need to call these functions since we give them all the data up front.
+ }
+
+ static boolean imp_resync_to_restart(j_decompress_ptr cinfo, int desired)
+ {
+ Assert( false ); // They should never need to call these functions since we give them all the data up front.
+ return false;
+ }
+
+ static void imp_term_source(j_decompress_ptr cinfo)
+ {
+ }
+
+ static void error_exit( j_common_ptr cptr )
+ {
+ CJpegSourceMgr *pInstance = (CJpegSourceMgr*)cptr->client_data;
+ longjmp( pInstance->m_JmpBuf, 1 );
+ }
+
+public:
+ jmp_buf m_JmpBuf;
+ CUtlVector<char> m_Data;
+};
+
+
+bool ReadJpeg( IFileSystem *pFileSystem, const char *pFilename, CUtlVector<unsigned char> &buf, int &width, int &height, const char *pPathID )
+{
+ width = height = 0;
+
+ // Read the data.
+ FileHandle_t fp = pFileSystem->Open( pFilename, "rb", pPathID );
+ if ( fp == FILESYSTEM_INVALID_HANDLE )
+ return false;
+
+ CJpegSourceMgr sourceMgr;
+ bool bRet = sourceMgr.Init( pFileSystem, fp );
+ pFileSystem->Close( fp );
+ if ( !bRet )
+ return false;
+
+ sourceMgr.bytes_in_buffer = sourceMgr.m_Data.Count();
+ sourceMgr.next_input_byte = (unsigned char*)sourceMgr.m_Data.Base();
+
+ // Load the jpeg.
+ struct jpeg_decompress_struct jpegInfo;
+ struct jpeg_error_mgr jerr;
+
+ memset( &jpegInfo, 0, sizeof( jpegInfo ) );
+ jpegInfo.client_data = &sourceMgr;
+ jpegInfo.err = jpeg_std_error(&jerr);
+ jerr.error_exit = &CJpegSourceMgr::error_exit;
+ jpeg_create_decompress(&jpegInfo);
+ jpegInfo.src = &sourceMgr;
+
+ if ( setjmp( sourceMgr.m_JmpBuf ) == 1 )
+ {
+ jpeg_destroy_decompress(&jpegInfo);
+ return false;
+ }
+
+ if (jpeg_read_header(&jpegInfo, TRUE) != JPEG_HEADER_OK)
+ {
+ return false;
+ }
+
+ // start the decompress with the jpeg engine.
+ if (jpeg_start_decompress(&jpegInfo) != TRUE || jpegInfo.output_components != 3)
+ {
+ jpeg_destroy_decompress(&jpegInfo);
+ return false;
+ }
+
+ // now that we've started the decompress with the jpeg lib, we have the attributes of the
+ // image ready to be read out of the decompress struct.
+ int row_stride = jpegInfo.output_width * jpegInfo.output_components;
+ int mem_required = jpegInfo.image_height * jpegInfo.image_width * jpegInfo.output_components;
+ JSAMPROW row_pointer[1];
+ int cur_row = 0;
+
+ width = jpegInfo.output_width;
+ height = jpegInfo.output_height;
+
+ // allocate the memory to read the image data into.
+ buf.SetSize( mem_required );
+
+ // read in all the scan lines of the image into our image data buffer.
+ bool working = true;
+ while (working && (jpegInfo.output_scanline < jpegInfo.output_height))
+ {
+ row_pointer[0] = &(buf[cur_row * row_stride]);
+ if (jpeg_read_scanlines(&jpegInfo, row_pointer, 1) != TRUE)
+ {
+ working = false;
+ }
+ ++cur_row;
+ }
+
+ if (!working)
+ {
+ jpeg_destroy_decompress(&jpegInfo);
+ return false;
+ }
+
+ jpeg_finish_decompress(&jpegInfo);
+ return true;
+}
+
+void DownsampleRGBToRGBAImage(
+ CUtlVector<unsigned char> &srcData,
+ int srcWidth,
+ int srcHeight,
+ CUtlVector<unsigned char> &destData,
+ int destWidth,
+ int destHeight )
+{
+ int srcPixelSize = 3;
+ int destPixelSize = 4;
+ destData.SetSize( destWidth * destHeight * destPixelSize );
+ memset( destData.Base(), 0xFF, destWidth * destHeight * destPixelSize );
+
+ // This preserves the aspect ratio of the image.
+ int scaledDestWidth = destWidth;
+ int scaledDestHeight = destHeight;
+ int destOffsetX = 0, destOffsetY = 0;
+ if ( srcWidth > srcHeight )
+ {
+ scaledDestHeight = (srcHeight * destHeight) / srcWidth;
+ destOffsetY = (destHeight - scaledDestHeight) / 2;
+ }
+ else if ( srcHeight > srcWidth )
+ {
+ scaledDestWidth = (srcWidth * destWidth) / srcHeight;
+ destOffsetX = (destWidth - scaledDestWidth) / 2;
+ }
+
+ for ( int destY=0; destY < scaledDestHeight; destY++ )
+ {
+ unsigned char *pDestLine = &destData[(destY + destOffsetY) * destWidth * destPixelSize + (destOffsetX * destPixelSize)];
+ unsigned char *pDestPos = pDestLine;
+
+ float destYPercent = (float)destY / (scaledDestHeight-1);
+ int srcY = (int)( destYPercent * (srcHeight-1) );
+
+ for ( int destX=0; destX < scaledDestWidth; destX++ )
+ {
+ float destXPercent = (float)destX / (scaledDestWidth-1);
+
+ int srcX = (int)( destXPercent * (srcWidth-1) );
+ unsigned char *pSrcPos = &srcData[(srcY * srcWidth + srcX) * srcPixelSize];
+ pDestPos[0] = pSrcPos[2];
+ pDestPos[1] = pSrcPos[1];
+ pDestPos[2] = pSrcPos[0];
+ pDestPos[3] = 255;
+
+ pDestPos += destPixelSize;
+ }
+ }
+}
+
+
+CBitmap* SetupJpegLabel( IFileSystem *pFileSystem, CString filename, int labelSize, const char *pPathID )
+{
+ CBitmap *pBitmap = g_BitmapCache.Find( filename );
+ if ( pBitmap )
+ return pBitmap;
+
+ CUtlVector<unsigned char> data;
+ int width, height;
+ if ( !ReadJpeg( pFileSystem, filename, data, width, height, pPathID ) )
+ return NULL;
+
+ CUtlVector<unsigned char> downsampled;
+ DownsampleRGBToRGBAImage( data, width, height, downsampled, labelSize, labelSize );
+
+ pBitmap = new CBitmap;
+ if ( pBitmap->CreateBitmap( labelSize, labelSize, 1, 32, downsampled.Base() ) )
+ {
+ g_BitmapCache.AddToCache( pBitmap, filename, downsampled.Count(), true );
+ return pBitmap;
+ }
+ else
+ {
+ delete pBitmap;
+ return NULL;
+ }
+}
+
+int CFileSystemOpenDlg::SetupLabelImage( CFileInfo *pInfo, CString name, bool bIsDir )
+{
+ if ( bIsDir )
+ return m_iLabel_Folder;
+
+ CString extension = name.Right( 4 );
+ extension.MakeLower();
+ if ( extension == ".jpg" || extension == ".jpeg" )
+ {
+ pInfo->m_pBitmap = SetupJpegLabel( m_pFileSystem, m_CurrentDir + "\\" + name, PREVIEW_IMAGE_SIZE, GetPathID() );
+ if ( pInfo->m_pBitmap )
+ return m_ImageList.Add( pInfo->m_pBitmap, (CBitmap*)NULL );
+ else
+ return m_iLabel_File;
+ }
+ else
+ {
+ return (extension == ".mdl") ? m_iLabel_Mdl : m_iLabel_File;
+ }
+}
+
+void FilterMdlAndJpgFiles( CUtlVector<CString> &files )
+{
+ // Build a dictionary with all the .jpeg files.
+ CUtlDict<int,int> jpgFiles;
+ for ( int i=0; i < files.Count(); i++ )
+ {
+ CString extension = files[i].Right( 4 );
+ extension.MakeLower();
+ if ( extension == ".jpg" || extension == ".jpeg" )
+ {
+ CString base = files[i].Left( files[i].GetLength() - 4 );
+ jpgFiles.Insert( base, 1 );
+ }
+ }
+
+ // Now look for all mdls and remove them if they have a jpg.
+ for ( int i=0; i < files.Count(); i++ )
+ {
+ CString extension = files[i].Right( 4 );
+ extension.MakeLower();
+ if ( extension == ".mdl" )
+ {
+ CString base = files[i].Left( files[i].GetLength() - 4 );
+ if ( jpgFiles.Find( base ) != -1 )
+ {
+ files.Remove( i );
+ --i;
+ }
+ }
+ }
+}
+
+
+int CALLBACK FileListSortCallback( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
+{
+ CFileSystemOpenDlg *pDlg = (CFileSystemOpenDlg*)lParamSort;
+ CFileInfo *pInfo1 = &pDlg->m_FileInfos[lParam1];
+ CFileInfo *pInfo2 = &pDlg->m_FileInfos[lParam2];
+ if ( pInfo1->m_bIsDir != pInfo2->m_bIsDir )
+ return pInfo1->m_bIsDir ? -1 : 1;
+
+ return Q_stricmp( pInfo1->m_Name, pInfo2->m_Name );
+}
+
+
+void RemoveDuplicates( CUtlVector<CString> &files )
+{
+ CUtlDict<int,int> uniqueFilenames;
+ for ( int i=0; i < files.Count(); i++ )
+ {
+ int iPreviousIndex = uniqueFilenames.Find( files[i] );
+ if ( iPreviousIndex == -1 )
+ {
+ uniqueFilenames.Insert( files[i], i );
+ }
+ else
+ {
+ files.Remove( i );
+ --i;
+ }
+ }
+}
+
+
+void CFileSystemOpenDlg::PopulateListControl()
+{
+ m_FileList.DeleteAllItems();
+ g_BitmapCache.UnlockAll();
+ m_LookInLabel.SetWindowText( CString( "[ROOT]\\" ) + m_CurrentDir );
+
+ int iItem = 0;
+
+ // First add directories at the top.
+ CUtlVector<CString> directories;
+ GetEntries( "*.*", directories, GETENTRIES_DIRECTORIES_ONLY );
+ RemoveDuplicates( directories );
+
+ for ( int i=0; i < directories.Count(); i++ )
+ {
+ if ( directories[i] == "." || directories[i] == ".." )
+ continue;
+
+ LVITEM item;
+ item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
+ item.iItem = iItem++;
+ item.iSubItem = 0;
+ item.pszText = directories[i].GetBuffer(0);
+
+ item.lParam = m_FileInfos.AddToTail();
+ m_FileInfos[item.lParam].m_bIsDir = true;
+ m_FileInfos[item.lParam].m_Name = directories[i];
+ item.iImage = SetupLabelImage( &m_FileInfos[item.lParam], directories[i], true );
+
+ m_FileList.InsertItem( &item );
+ }
+
+ CUtlVector<CString> files;
+ for ( int iMask=0; iMask < m_FileMasks.Count(); iMask++ )
+ {
+ GetEntries( m_FileMasks[iMask], files, GETENTRIES_FILES_ONLY );
+ }
+
+ RemoveDuplicates( files );
+ if ( m_bFilterMdlAndJpgFiles )
+ FilterMdlAndJpgFiles( files );
+
+ for ( int i=0; i < files.Count(); i++ )
+ {
+ LVITEM item;
+ item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
+ item.iItem = iItem++;
+ item.iSubItem = 0;
+ item.iImage = m_iLabel_Mdl;
+ item.pszText = files[i].GetBuffer(0);
+
+ item.lParam = m_FileInfos.AddToTail();
+ m_FileInfos[item.lParam].m_bIsDir = false;
+ m_FileInfos[item.lParam].m_Name = files[i];
+ item.iImage = SetupLabelImage( &m_FileInfos[item.lParam], files[i], false );
+
+ m_FileList.InsertItem( &item );
+ }
+
+ m_FileList.SortItems( FileListSortCallback, (DWORD)this );
+}
+
+void CFileSystemOpenDlg::AddFileMask( const char *pMask )
+{
+ m_FileMasks.AddToTail( pMask );
+}
+
+
+BOOL CFileSystemOpenDlg::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
+{
+ return CDialog::Create(IDD, pParentWnd);
+}
+
+int CFileSystemOpenDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CDialog::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ return 0;
+}
+
+
+LONG& GetSideCoord( RECT &rect, int iSide )
+{
+ if ( iSide == 0 )
+ return rect.left;
+ else if ( iSide == 1 )
+ return rect.top;
+ else if ( iSide == 2 )
+ return rect.right;
+ else
+ return rect.bottom;
+}
+
+
+LONG GetSideScreenCoord( CWnd *pWnd, int iSide )
+{
+ RECT rect;
+ pWnd->GetWindowRect( &rect );
+ return GetSideCoord( rect, iSide );
+}
+
+
+void CFileSystemOpenDlg::ProcessAnchor( CWindowAnchor *pAnchor )
+{
+ RECT rect, parentRect;
+ GetWindowRect( &parentRect );
+ pAnchor->m_pWnd->GetWindowRect( &rect );
+
+ GetSideCoord( rect, pAnchor->m_Side ) = GetSideCoord( parentRect, pAnchor->m_ParentSide ) + pAnchor->m_OriginalDist;
+
+ ScreenToClient( &rect );
+ pAnchor->m_pWnd->MoveWindow( &rect );
+}
+
+
+void CFileSystemOpenDlg::AddAnchor( int iDlgItem, int iSide, int iParentSide )
+{
+ CWnd *pItem = GetDlgItem( iDlgItem );
+ if ( !pItem )
+ return;
+
+ CWindowAnchor *pAnchor = &m_Anchors[m_Anchors.AddToTail()];
+ pAnchor->m_pWnd = pItem;
+ pAnchor->m_Side = iSide;
+ pAnchor->m_ParentSide = iParentSide;
+ pAnchor->m_OriginalDist = GetSideScreenCoord( pItem, iSide ) - GetSideScreenCoord( this, iParentSide );
+}
+
+
+
+void CFileSystemOpenDlg::OnSize(UINT nType, int cx, int cy)
+{
+ CDialog::OnSize(nType, cx, cy);
+
+ for ( int i=0; i < m_Anchors.Count(); i++ )
+ ProcessAnchor( &m_Anchors[i] );
+
+ if ( m_FileList.GetSafeHwnd() )
+ PopulateListControl();
+}
+
+void CFileSystemOpenDlg::OnDblclkFileList(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ /*int iSelected = m_FileList.GetNextItem( -1, LVNI_SELECTED );
+ if ( iSelected != -1 )
+ {
+ DWORD iItem = m_FileList.GetItemData( iSelected );
+ if ( iItem < (DWORD)m_FileInfos.Count() )
+ {
+ CFileInfo *pInfo = &m_FileInfos[iItem];
+ if ( pInfo->m_bIsDir )
+ {
+ m_CurrentDir += "\\" + m_FileInfos[iItem].m_Name;
+ PopulateListControl();
+ }
+ else
+ {
+ m_Filename = m_CurrentDir + "\\" + m_FileInfos[iItem].m_Name;
+ EndDialog( IDOK );
+ }
+ }
+ else
+ {
+ Assert( false );
+ }
+ }*/
+ OnOK();
+
+ *pResult = 0;
+}
+
+void CFileSystemOpenDlg::OnUpButton()
+{
+ char str[MAX_PATH];
+ V_strcpy_safe( str, m_CurrentDir );
+ Q_StripLastDir( str, sizeof( str ) );
+
+ if ( str[0] == 0 )
+ V_strcpy_safe( str, "." );
+
+ if ( str[strlen(str)-1] == '\\' || str[strlen(str)-1] == '/' )
+ str[strlen(str)-1] = 0;
+
+ m_CurrentDir = str;
+ PopulateListControl();
+}
+
+void CFileSystemOpenDlg::OnItemchangedFileList(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
+
+ DWORD iItem = m_FileList.GetItemData( pNMListView->iItem );
+ if ( iItem < (DWORD)m_FileInfos.Count() )
+ {
+ CFileInfo *pInfo = &m_FileInfos[iItem];
+ if ( (pNMListView->uChanged & LVIF_STATE) &&
+ (pNMListView->uNewState & LVIS_SELECTED) )
+ {
+ m_FilenameControl.SetWindowText( pInfo->m_Name );
+ }
+ }
+
+ *pResult = 0;
+}
+
+void CFileSystemOpenDlg::SetFilterMdlAndJpgFiles( bool bFilter )
+{
+ m_bFilterMdlAndJpgFiles = bFilter;
+}
+
+const char* CFileSystemOpenDlg::GetPathID()
+{
+ if ( m_PathIDString == "" )
+ return NULL;
+ else
+ return (const char*)m_PathIDString;
+}
+
+
+
+// ------------------------------------------------------------------------------------------------ //
+// Implementation of IFileSystemOpenDialog.
+// ------------------------------------------------------------------------------------------------ //
+
+// IFileSystemOpenDialog implementation.
+class CFileSystemOpenDialogWrapper : public IFileSystemOpenDialog
+{
+public:
+ CFileSystemOpenDialogWrapper()
+ {
+ m_pDialog = 0;
+ m_bLastModalWasWindowsDialog = false;
+ }
+
+ virtual void Release()
+ {
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ delete m_pDialog;
+ delete this;
+ }
+
+ // You must call this first to set the hwnd.
+ virtual void Init( CreateInterfaceFn factory, void *parentHwnd )
+ {
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ Assert( !m_pDialog );
+
+ m_hParentWnd = (HWND)parentHwnd;
+ m_pDialog = new CFileSystemOpenDlg( factory, CWnd::FromHandle( m_hParentWnd ) );
+ }
+
+ virtual void AddFileMask( const char *pMask )
+ {
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ Assert( m_pDialog );
+ m_pDialog->AddFileMask( pMask );
+ }
+
+ virtual void SetInitialDir( const char *pDir, const char *pPathID )
+ {
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ Assert( m_pDialog );
+ m_pDialog->SetInitialDir( pDir, pPathID );
+ }
+
+ virtual void SetFilterMdlAndJpgFiles( bool bFilter )
+ {
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ Assert( m_pDialog );
+ m_pDialog->SetFilterMdlAndJpgFiles( bFilter );
+ }
+
+ virtual void GetFilename( char *pOut, int outLen ) const
+ {
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ Assert( m_pDialog );
+
+ if ( m_bLastModalWasWindowsDialog )
+ {
+ Q_strncpy( pOut, m_RelativeFilename, outLen );
+ }
+ else
+ {
+ Q_strncpy( pOut, m_pDialog->GetFilename(), outLen );
+ }
+ }
+
+ virtual bool DoModal()
+ {
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ Assert( m_pDialog );
+
+ m_bLastModalWasWindowsDialog = false;
+ return m_pDialog->DoModal() == IDOK;
+ }
+
+ virtual bool DoModal_WindowsDialog()
+ {
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ Assert( m_pDialog );
+
+ m_bLastModalWasWindowsDialog = true;
+
+ // Get the full filename, then make sure it's a relative path.
+ char defExt[MAX_PATH] = {0};
+ if ( m_pDialog->m_FileMasks.Count() > 0 )
+ {
+ CString ext = m_pDialog->m_FileMasks[m_pDialog->m_FileMasks.Count()-1].Right( 4 );
+ const char *pStr = ext;
+ if ( pStr[0] == '.' )
+ V_strcpy_safe( defExt, pStr+1 );
+ }
+
+ char pFileNameBuf[MAX_PATH];
+ const char *pFileName = m_pDialog->m_pFileSystem->RelativePathToFullPath( m_pDialog->m_CurrentDir, m_pDialog->m_PathIDString, pFileNameBuf, MAX_PATH );
+ V_strcat_safe( pFileNameBuf, "\\" );
+
+ // Build the list of file filters.
+ char filters[1024];
+ if ( m_pDialog->m_FileMasks.Count() == 0 )
+ {
+ V_strcpy_safe( filters, "All Files (*.*)|*.*||" );
+ }
+ else
+ {
+ filters[0] = 0;
+ for ( int i=0; i < m_pDialog->m_FileMasks.Count(); i++ )
+ {
+ if ( i > 0 )
+ V_strcat_safe( filters, "|" );
+
+ V_strcat_safe( filters, m_pDialog->m_FileMasks[i] );
+ V_strcat_safe( filters, "|" );
+ V_strcat_safe( filters, m_pDialog->m_FileMasks[i] );
+ if ( pFileName )
+ {
+ V_strcat_safe( pFileNameBuf, m_pDialog->m_FileMasks[i] );
+ V_strcat_safe( pFileNameBuf, ";" );
+ }
+
+ }
+ V_strcat_safe( filters, "||" );
+ }
+
+ CFileDialog dlg(
+ true, // open dialog?
+ defExt[0]==0 ? NULL : defExt, // default file extension
+ pFileName, // initial filename
+ OFN_ENABLESIZING, // flags
+ filters,
+ CWnd::FromHandle( m_hParentWnd ) );
+
+ while ( dlg.DoModal() == IDOK )
+ {
+ // Make sure we can make this into a relative path.
+ if ( m_pDialog->m_pFileSystem->FullPathToRelativePath( dlg.GetPathName(), m_RelativeFilename, sizeof( m_RelativeFilename ) ) )
+ {
+ // Replace .jpg or .jpeg extension with .mdl?
+ char *pEnd = m_RelativeFilename;
+ while ( Q_stristr( pEnd+1, ".jpeg" ) || Q_stristr( pEnd+1, ".jpg" ) )
+ pEnd = max( Q_stristr( pEnd, ".jpeg" ), Q_stristr( pEnd, ".jpg" ) );
+
+ if ( pEnd && pEnd != m_RelativeFilename )
+ Q_strncpy( pEnd, ".mdl", sizeof( m_RelativeFilename ) - (pEnd - m_RelativeFilename) );
+
+ return true;
+ }
+ else
+ {
+ AfxMessageBox( IDS_NO_RELATIVE_PATH );
+ }
+ }
+
+ return false;
+ }
+
+private:
+ CFileSystemOpenDlg *m_pDialog;
+ HWND m_hParentWnd;
+
+ char m_RelativeFilename[MAX_PATH];
+ bool m_bLastModalWasWindowsDialog;
+};
+
+EXPOSE_INTERFACE( CFileSystemOpenDialogWrapper, IFileSystemOpenDialog, FILESYSTEMOPENDIALOG_VERSION );
+
diff --git a/utils/FileSystemOpenDialog/FileSystemOpenDlg.h b/utils/FileSystemOpenDialog/FileSystemOpenDlg.h
new file mode 100644
index 0000000..3aa053c
--- /dev/null
+++ b/utils/FileSystemOpenDialog/FileSystemOpenDlg.h
@@ -0,0 +1,146 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#if !defined(AFX_FILESYSTEMOPENDLG_H__01CFDE04_321F_4F1E_94ED_933B2B32C193__INCLUDED_)
+#define AFX_FILESYSTEMOPENDLG_H__01CFDE04_321F_4F1E_94ED_933B2B32C193__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// FileSystemOpenDlg.h : header file
+//
+
+#include "utlvector.h"
+#include "resource.h"
+#include "filesystem.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CFileSystemOpenDlg dialog
+
+class CWindowAnchor
+{
+public:
+ CWnd *m_pWnd;
+ int m_Side; //0=left, 1=top, 2=right, 3=bottom
+ int m_ParentSide; //which side to anchor to parent
+ int m_OriginalDist; //original distance from the parent side
+};
+
+class CFileInfo
+{
+public:
+ CFileInfo();
+ ~CFileInfo();
+
+ bool m_bIsDir;
+ CString m_Name;
+ CBitmap *m_pBitmap;
+};
+
+
+class CFileSystemOpenDlg : public CDialog
+{
+friend class CFileSystemOpenDialogWrapper;
+
+// Construction
+public:
+ CFileSystemOpenDlg(CreateInterfaceFn factory, CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CFileSystemOpenDlg)
+ enum { IDD = IDD_FILESYSTEM_OPENDIALOG };
+ CEdit m_FilenameLabel;
+ CEdit m_FilenameControl;
+ CEdit m_LookInLabel;
+ CListCtrl m_FileList;
+ //}}AFX_DATA
+
+ void AddFileMask( const char *pMask );
+
+ void SetInitialDir( const char *pDir, const char *pPathID = NULL );
+
+ void SetFilterMdlAndJpgFiles( bool bFilter );
+ CString GetFilename() const; // Get the filename they chose.
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CFileSystemOpenDlg)
+ public:
+ virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+
+private:
+
+ enum GetEntriesMode_t
+ {
+ GETENTRIES_FILES_ONLY,
+ GETENTRIES_DIRECTORIES_ONLY
+ };
+ void GetEntries( const char *pMask, CUtlVector<CString> &entries, GetEntriesMode_t mode );
+ void PopulateListControl();
+ int SetupLabelImage( CFileInfo *pInfo, CString name, bool bIsDir );
+
+ void AddAnchor( int iDlgItem, int iSide, int anchorSide );
+ void ProcessAnchor( CWindowAnchor *pAnchor );
+
+// Implementation
+protected:
+
+ const char* GetPathID();
+
+ friend int CALLBACK FileListSortCallback( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort );
+ friend class CFilenameShortcut;
+
+ CUtlVector<CWindowAnchor> m_Anchors;
+
+ enum
+ {
+ PREVIEW_IMAGE_SIZE=96
+ };
+
+ IFileSystem *m_pFileSystem;
+
+ // These are indexed by the lParam or userdata of each item in m_FileList.
+ CUtlVector<CFileInfo> m_FileInfos;
+
+ int m_iLabel_Folder;
+ int m_iLabel_Mdl;
+ int m_iLabel_File;
+ CBitmap m_BitmapMdl;
+ CBitmap m_BitmapFile;
+ CBitmap m_BitmapFolder;
+
+ CImageList m_ImageList;
+ CString m_CurrentDir;
+ CString m_Filename;
+ CString m_PathIDString;
+ CUtlVector<CString> m_FileMasks;
+
+ // If this is true, then we get rid of .mdl files if there is a corresponding .jpg file.
+ bool m_bFilterMdlAndJpgFiles;
+
+ // Generated message map functions
+ //{{AFX_MSG(CFileSystemOpenDlg)
+ virtual void OnOK();
+ virtual BOOL OnInitDialog();
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void OnDblclkFileList(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnUpButton();
+ afx_msg void OnItemchangedFileList(NMHDR* pNMHDR, LRESULT* pResult);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_FILESYSTEMOPENDLG_H__01CFDE04_321F_4F1E_94ED_933B2B32C193__INCLUDED_)
diff --git a/utils/FileSystemOpenDialog/StdAfx.cpp b/utils/FileSystemOpenDialog/StdAfx.cpp
new file mode 100644
index 0000000..e3b91dd
--- /dev/null
+++ b/utils/FileSystemOpenDialog/StdAfx.cpp
@@ -0,0 +1,15 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+// stdafx.cpp : source file that includes just the standard includes
+// SteamFileDialog.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
+
diff --git a/utils/FileSystemOpenDialog/StdAfx.h b/utils/FileSystemOpenDialog/StdAfx.h
new file mode 100644
index 0000000..a460b3a
--- /dev/null
+++ b/utils/FileSystemOpenDialog/StdAfx.h
@@ -0,0 +1,52 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__4F9B2A8A_E38D_4917_BA99_46DF8EC095C9__INCLUDED_)
+#define AFX_STDAFX_H__4F9B2A8A_E38D_4917_BA99_46DF8EC095C9__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "tier0/wchartypes.h"
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxole.h> // MFC OLE classes
+#include <afxodlgs.h> // MFC OLE dialog classes
+#include <afxdisp.h> // MFC Automation classes
+#endif // _AFX_NO_OLE_SUPPORT
+
+
+#ifndef _AFX_NO_DB_SUPPORT
+#include <afxdb.h> // MFC ODBC database classes
+#endif // _AFX_NO_DB_SUPPORT
+
+#ifndef _AFX_NO_DAO_SUPPORT
+#include <afxdao.h> // MFC DAO database classes
+#endif // _AFX_NO_DAO_SUPPORT
+
+#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#include <afxpriv.h>
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__4F9B2A8A_E38D_4917_BA99_46DF8EC095C9__INCLUDED_)
diff --git a/utils/FileSystemOpenDialog/filesystemopendialog.vpc b/utils/FileSystemOpenDialog/filesystemopendialog.vpc
new file mode 100644
index 0000000..fea3959
--- /dev/null
+++ b/utils/FileSystemOpenDialog/filesystemopendialog.vpc
@@ -0,0 +1,76 @@
+//-----------------------------------------------------------------------------
+// FILESYSTEMOPENDIALOG.VPC
+//
+// Project Script
+//-----------------------------------------------------------------------------
+
+$Macro SRCDIR "..\.."
+$Macro OUTBINDIR "$SRCDIR\..\game\bin"
+
+$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
+
+$Configuration
+{
+ $Compiler
+ {
+ // Deprecated MBCS MFC libraries for VS 2013 (nafxcw.lib and nafxcwd.lib) can be downloaded from http://go.microsoft.com/?linkid=9832071
+ $PreprocessorDefinitions "$BASE;NO_WARN_MBCS_MFC_DEPRECATION"
+ $AdditionalIncludeDirectories "$BASE,..\common"
+ $PreprocessorDefinitions "$BASE;;WINVER=0x502"
+ $Create/UsePrecompiledHeader "Use Precompiled Header (/Yu)"
+ $PrecompiledHeaderFile "Debug/FileSystemOpenDialog.pch"
+ $EnableC++Exceptions "Yes (/EHsc)"
+ }
+}
+
+$Project "FileSystemOpenDialog"
+{
+ $Folder "Source Files"
+ {
+ $File "$SRCDIR\public\tier0\afxmem_override.cpp"
+ $File "FileDialogApp.cpp"
+ $File "FileDialogApp.h"
+ $File "FileSystemOpenDlg.cpp"
+ $File "FileSystemOpenDlg.h"
+ $File "$SRCDIR\common\IFileSystemOpenDialog.h"
+ -$File "$SRCDIR\public\tier0\memoverride.cpp"
+ $File "$SRCDIR\public\tier0\memoverride.cpp"
+ {
+ $Configuration
+ {
+ $Compiler
+ {
+ $PreprocessorDefinitions "$BASE;NO_MEMOVERRIDE_NEW_DELETE"
+ $Create/UsePrecompiledHeader "Not Using Precompiled Headers"
+ }
+ }
+ }
+
+ $File "StdAfx.cpp"
+ {
+ $Configuration
+ {
+ $Compiler
+ {
+ $Create/UsePrecompiledHeader "Create Precompiled Header (/Yc)"
+ }
+ }
+ }
+ }
+
+ $Folder "Header Files"
+ {
+ $File "Resource.h"
+ $File "StdAfx.h"
+ }
+
+ $Folder "Resource Files"
+ {
+ $File "FileSystemOpenDialog.rc"
+ }
+
+ $Folder "Link Libraries"
+ {
+ $Lib $LIBCOMMON/libjpeg
+ }
+}
diff --git a/utils/FileSystemOpenDialog/res/SteamFileDialog.rc2 b/utils/FileSystemOpenDialog/res/SteamFileDialog.rc2
new file mode 100644
index 0000000..01fe6ec
--- /dev/null
+++ b/utils/FileSystemOpenDialog/res/SteamFileDialog.rc2
@@ -0,0 +1,13 @@
+//
+// STEAMFILEDIALOG.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/utils/FileSystemOpenDialog/res/label_file.bmp b/utils/FileSystemOpenDialog/res/label_file.bmp
new file mode 100644
index 0000000..c0b223b
--- /dev/null
+++ b/utils/FileSystemOpenDialog/res/label_file.bmp
Binary files differ
diff --git a/utils/FileSystemOpenDialog/res/label_fo.bmp b/utils/FileSystemOpenDialog/res/label_fo.bmp
new file mode 100644
index 0000000..f278de6
--- /dev/null
+++ b/utils/FileSystemOpenDialog/res/label_fo.bmp
Binary files differ
diff --git a/utils/FileSystemOpenDialog/res/label_mdl.bmp b/utils/FileSystemOpenDialog/res/label_mdl.bmp
new file mode 100644
index 0000000..50ed80f
--- /dev/null
+++ b/utils/FileSystemOpenDialog/res/label_mdl.bmp
Binary files differ
diff --git a/utils/FileSystemOpenDialog/resource.h b/utils/FileSystemOpenDialog/resource.h
new file mode 100644
index 0000000..48004e6
--- /dev/null
+++ b/utils/FileSystemOpenDialog/resource.h
@@ -0,0 +1,26 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by FileSystemOpenDialog.rc
+//
+#define IDS_NO_RELATIVE_PATH 1
+#define IDD_FILESYSTEM_OPENDIALOG 327
+#define IDB_LABEL_MDL 328
+#define IDB_LABEL_FOLDER 329
+#define IDB_LABEL_FILE 331
+#define IDC_FILENAME 1009
+#define IDC_UP_BUTTON 1010
+#define IDC_LOOKIN 1011
+#define IDC_FILE_LIST 1098
+#define IDC_FILENAME_LABEL 1644
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 1000
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 1000
+#endif
+#endif