summaryrefslogtreecommitdiff
path: root/utils/vproject/vproject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/vproject/vproject.cpp')
-rw-r--r--utils/vproject/vproject.cpp648
1 files changed, 648 insertions, 0 deletions
diff --git a/utils/vproject/vproject.cpp b/utils/vproject/vproject.cpp
new file mode 100644
index 0000000..36be00c
--- /dev/null
+++ b/utils/vproject/vproject.cpp
@@ -0,0 +1,648 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// VPROJECT.CPP
+//
+//=====================================================================================//
+#include "vproject.h"
+
+#define MAX_PROJECTS 50
+
+#define ID_PROJECTS_LISTVIEW 100
+
+// column id
+#define ID_PROJECT_NAME 0
+#define ID_PROJECT_DIRECTORY 1
+
+#define WM_TRAY (WM_APP + 1)
+#define ID_TRAY 5000
+#define ID_TRAY_ADDVPROJECT 6000
+#define ID_TRAY_MODIFYVPROJECT 6001
+#define ID_TRAY_MOVEUP 6002
+#define ID_TRAY_MOVEDOWN 6003
+#define ID_TRAY_EXIT 6004
+
+typedef struct
+{
+ char *pName;
+ char *pGamedir;
+} project_t;
+
+HWND g_hWnd;
+char g_project_name[256];
+char g_project_gamedir[256];
+HINSTANCE g_hInstance;
+project_t g_projects[MAX_PROJECTS];
+int g_numProjects;
+NOTIFYICONDATA g_iconData;
+HMENU g_hMenu;
+int g_nActiveVProject;
+POINT g_cursorPoint;
+
+void TrayMessageHandler( HWND hWnd, UINT uMessageID );
+
+//-----------------------------------------------------------------------------
+// SetVProject
+//
+//-----------------------------------------------------------------------------
+void SetVProject( const char *pProjectName )
+{
+ char *pGamedir;
+ char project[256];
+ int i;
+
+ if ( pProjectName )
+ {
+ strcpy( project, pProjectName );
+ Sys_StripQuotesFromToken( project );
+
+ for ( i=0; i<g_numProjects; i++ )
+ {
+ if ( !stricmp( g_projects[i].pName, project ) )
+ {
+ // found
+ break;
+ }
+ }
+
+ if ( i >= g_numProjects )
+ {
+ // not found
+ return;
+ }
+
+ pGamedir = g_projects[i].pGamedir;
+ }
+ else
+ {
+ pGamedir = "";
+ }
+
+ // Changed to CURRENT_USER to solve security issues in vista!
+ Sys_SetRegistryString(
+ //"HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment\\VProject",
+ "HKEY_CURRENT_USER\\Environment\\VProject"
+ pGamedir );
+
+ DWORD result;
+ SendMessageTimeout(
+ HWND_BROADCAST,
+ WM_SETTINGCHANGE,
+ 0,
+ (LPARAM)"Environment",
+ SMTO_ABORTIFHUNG,
+ 0,
+ &result );
+}
+
+//-----------------------------------------------------------------------------
+// ModifyVProject
+//
+//-----------------------------------------------------------------------------
+void ModifyVProject( int index, const char *pName, const char *pGamedir )
+{
+ free( g_projects[index].pName );
+ free( g_projects[index].pGamedir );
+
+ if ( !pName || !pName[0] )
+ {
+ // delete
+ if ( g_numProjects-index-1 > 0 )
+ {
+ // shift remaining elements
+ memcpy( &g_projects[index], &g_projects[index+1], (g_numProjects-index-1)*sizeof( project_t ) );
+ }
+
+ g_projects[g_numProjects-1].pName = NULL;
+ g_projects[g_numProjects-1].pGamedir = NULL;
+
+ g_numProjects--;
+
+ if ( g_nActiveVProject == index+1 )
+ {
+ // deleted current vproject
+ if ( !g_numProjects )
+ {
+ // no more projects
+ g_nActiveVProject = 0;
+ SetVProject( NULL );
+ }
+ else
+ {
+ // set to top
+ g_nActiveVProject = 1;
+ SetVProject( g_projects[0].pName );
+ }
+ }
+ }
+ else
+ {
+ g_projects[index].pName = strdup( pName );
+ g_projects[index].pGamedir = strdup( pGamedir );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// AddVProject
+//
+//-----------------------------------------------------------------------------
+void AddVProject( const char *pName, const char *pGamedir )
+{
+ if ( !pName || !pName[0] )
+ {
+ // do not add empty projects
+ return;
+ }
+
+ ModifyVProject( g_numProjects, pName, pGamedir );
+ g_numProjects++;
+}
+
+//-----------------------------------------------------------------------------
+// LoadRegistryValues
+//
+//-----------------------------------------------------------------------------
+void LoadRegistryValues()
+{
+ char keyBuff[32];
+ char valueBuff[256];
+ char projectName[256];
+ char gamedirString[256];
+ char *ptr;
+ char *token;
+ int i;
+
+ for ( i=0; i<MAX_PROJECTS; i++ )
+ {
+ projectName[0] = '\0';
+ gamedirString[0] = '\0';
+
+ sprintf( keyBuff, "project%d", i );
+ Sys_GetRegistryString( keyBuff, valueBuff, "", sizeof( valueBuff ) );
+
+ // parse and populate valid values
+ ptr = valueBuff;
+ token = Sys_GetToken( &ptr, false, NULL );
+ if ( token[0] )
+ {
+ strcpy( projectName, token );
+ }
+ else
+ {
+ continue;
+ }
+
+ token = Sys_GetToken( &ptr, false, NULL );
+ if ( token[0] )
+ {
+ strcpy( gamedirString, token );
+ }
+
+ AddVProject( projectName, gamedirString );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// SaveRegistryValues
+//
+//-----------------------------------------------------------------------------
+void SaveRegistryValues()
+{
+ char valueBuff[256];
+ char keyBuff[32];
+ char *pProjectName;
+ char *pGamedir;
+ int len;
+ int i;
+
+ for ( i=0; i<MAX_PROJECTS; i++ )
+ {
+ sprintf( keyBuff, "project%d", i );
+
+ pProjectName = g_projects[i].pName;
+ if ( !pProjectName )
+ {
+ pProjectName = "";
+ }
+
+ pGamedir = g_projects[i].pGamedir;
+ if ( !pGamedir )
+ {
+ pGamedir = "";
+ }
+
+ len = _snprintf( valueBuff, sizeof( valueBuff ), "\"%s\" \"%s\"", pProjectName, pGamedir );
+ if ( len == -1 )
+ {
+ // kill it
+ valueBuff[0] = '\0';
+ }
+
+ Sys_SetRegistryString( keyBuff, valueBuff );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ShiftActiveProjectUp
+//
+//-----------------------------------------------------------------------------
+void ShiftActiveProjectUp()
+{
+ if ( g_numProjects <= 1 || !g_nActiveVProject )
+ {
+ // nothing to do
+ return;
+ }
+
+ int active = g_nActiveVProject-1;
+ int previous = (active + g_numProjects - 1) % g_numProjects;
+
+ project_t tempProject;
+ tempProject = g_projects[previous];
+ g_projects[previous] = g_projects[active];
+ g_projects[active] = tempProject;
+
+ g_nActiveVProject = previous + 1;
+}
+
+//-----------------------------------------------------------------------------
+// ShiftActiveProjectDown
+//
+//-----------------------------------------------------------------------------
+void ShiftActiveProjectDown()
+{
+ if ( g_numProjects <= 1 || !g_nActiveVProject )
+ {
+ // nothing to do
+ return;
+ }
+
+ int active = g_nActiveVProject-1;
+ int next = (active + g_numProjects + 1) % g_numProjects;
+
+ project_t tempProject;
+ tempProject = g_projects[next];
+ g_projects[next] = g_projects[active];
+ g_projects[active] = tempProject;
+
+ g_nActiveVProject = next + 1;
+}
+
+//-----------------------------------------------------------------------------
+// ModifyDlg_Proc
+//
+//-----------------------------------------------------------------------------
+BOOL CALLBACK ModifyDlg_Proc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ size_t len;
+ int width;
+ int height;
+ RECT rect;
+
+ switch ( message )
+ {
+ case WM_INITDIALOG:
+ SetDlgItemText( hWnd, IDC_MODIFY_PROJECT, g_project_name );
+ SetDlgItemText( hWnd, IDC_MODIFY_GAMEDIR, g_project_gamedir );
+
+ // center dialog
+ GetWindowRect( hWnd, &rect );
+ width = GetSystemMetrics( SM_CXSCREEN );
+ height = GetSystemMetrics( SM_CYSCREEN );
+ SetWindowPos( hWnd, NULL, ( width - ( rect.right - rect.left ) )/2, ( height - ( rect.bottom - rect.top ) )/2, 0, 0, SWP_NOSIZE | SWP_NOZORDER );
+ return ( TRUE );
+
+ case WM_COMMAND:
+ switch ( LOWORD( wParam ) )
+ {
+ case IDC_OK:
+ GetDlgItemText( hWnd, IDC_MODIFY_PROJECT, g_project_name, sizeof( g_project_name ) );
+ GetDlgItemText( hWnd, IDC_MODIFY_GAMEDIR, g_project_gamedir, sizeof( g_project_gamedir ) );
+
+ // remove trailing seperator
+ Sys_NormalizePath( g_project_gamedir, false );
+ len = strlen( g_project_gamedir );
+ if ( len > 2 && g_project_gamedir[len-1] == '\\' )
+ {
+ g_project_gamedir[len-1] = '\0';
+ }
+ // fall through
+
+ case IDCANCEL:
+ case IDC_CANCEL:
+ EndDialog( hWnd, wParam );
+ return ( TRUE );
+ }
+ break;
+ }
+ return ( FALSE );
+}
+
+//-----------------------------------------------------------------------------
+// ModifyDlg_Open
+//
+//-----------------------------------------------------------------------------
+BOOL ModifyDlg_Open()
+{
+ int result;
+
+ result = DialogBox( g_hInstance, MAKEINTRESOURCE( IDD_VPROJECT ), g_hWnd, ( DLGPROC )ModifyDlg_Proc );
+ if ( LOWORD( result ) != IDC_OK )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// ShowPopupMenu
+//
+//-----------------------------------------------------------------------------
+void ShowPopupMenu( HWND hWnd, bool bUseCachedMenuPos )
+{
+ BOOL bDelete = true;
+
+ // delete existing entries
+ for ( int nIndex = 1; nIndex < ID_TRAY_ADDVPROJECT && bDelete; nIndex++ )
+ {
+ bDelete = DeleteMenu( g_hMenu, nIndex, MF_BYCOMMAND );
+ }
+
+ // Insert projects
+ char szMenuItem[MAX_PATH];
+ for ( int nIndex = 0; nIndex < g_numProjects; nIndex++ )
+ {
+ strcpy( szMenuItem, g_projects[nIndex].pName );
+ strcat( szMenuItem, "\t" );
+ strcat( szMenuItem, g_projects[nIndex].pGamedir );
+ strcat( szMenuItem, " " );
+
+ InsertMenu( g_hMenu, nIndex, MF_BYPOSITION | MF_STRING, nIndex + 1, szMenuItem );
+ }
+
+ if ( g_nActiveVProject )
+ {
+ CheckMenuItem( g_hMenu, g_nActiveVProject, MF_BYCOMMAND|MF_CHECKED );
+ SetMenuDefaultItem( g_hMenu, g_nActiveVProject, FALSE );
+ }
+
+ // Display the popup menu at the current cursor location
+ // Use the cached cursor position if set
+ if ( !bUseCachedMenuPos || ( !g_cursorPoint.x && !g_cursorPoint.y ) )
+ {
+ GetCursorPos( &g_cursorPoint );
+ }
+ SetForegroundWindow( hWnd );
+ TrackPopupMenu( g_hMenu, 0, g_cursorPoint.x, g_cursorPoint.y, 0, hWnd, 0 );
+ PostMessage( hWnd, WM_NULL, 0, 0 );
+}
+
+//-----------------------------------------------------------------------------
+// TrayMessageHandler
+//
+//-----------------------------------------------------------------------------
+void TrayMessageHandler( HWND hWnd, UINT uMessageID )
+{
+ switch ( uMessageID )
+ {
+ case 0:
+ break;
+
+ case ID_TRAY_EXIT:
+ DestroyWindow( hWnd );
+ break;
+
+ case ID_TRAY_ADDVPROJECT:
+ SetForegroundWindow( hWnd );
+ g_project_name[0] = '\0';
+ g_project_gamedir[0] = '\0';
+ if ( ModifyDlg_Open() )
+ {
+ AddVProject( g_project_name, g_project_gamedir );
+ SaveRegistryValues();
+ }
+ ShowPopupMenu( hWnd, true );
+ break;
+
+ case ID_TRAY_MODIFYVPROJECT:
+ SetForegroundWindow( hWnd );
+ if ( g_nActiveVProject )
+ {
+ strcpy( g_project_name, g_projects[g_nActiveVProject-1].pName );
+ strcpy( g_project_gamedir, g_projects[g_nActiveVProject-1].pGamedir );
+ if ( ModifyDlg_Open() )
+ {
+ ModifyVProject( g_nActiveVProject-1, g_project_name, g_project_gamedir );
+ SaveRegistryValues();
+ }
+ ShowPopupMenu( hWnd, true );
+ }
+ break;
+
+ case ID_TRAY_MOVEUP:
+ SetForegroundWindow( hWnd );
+ if ( g_nActiveVProject )
+ {
+ ShiftActiveProjectUp();
+ SaveRegistryValues();
+ ShowPopupMenu( hWnd, true );
+ }
+ break;
+
+ case ID_TRAY_MOVEDOWN:
+ SetForegroundWindow( hWnd );
+ if ( g_nActiveVProject )
+ {
+ ShiftActiveProjectDown();
+ SaveRegistryValues();
+ ShowPopupMenu( hWnd, true );
+ }
+ break;
+
+ default:
+ if ( uMessageID >= 1 && uMessageID <= MAX_PROJECTS )
+ {
+ // set current vproject
+ g_nActiveVProject = uMessageID;
+ SetVProject( g_projects[uMessageID-1].pName );
+ }
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Main_WndProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK Main_WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ switch ( message )
+ {
+ case WM_DESTROY:
+ PostQuitMessage( 0 );
+ return 0L;
+
+ case WM_TRAY:
+ if ( lParam == WM_LBUTTONDOWN || lParam == WM_RBUTTONDOWN )
+ {
+ ShowPopupMenu( hWnd, false );
+ return 0L;
+ }
+ break;
+
+ case WM_COMMAND:
+ TrayMessageHandler( hWnd, LOWORD( wParam ) );
+ break;
+ }
+
+ return ( DefWindowProc( hWnd, message, wParam, lParam ) );
+}
+
+//-----------------------------------------------------------------------------
+// Startup
+//
+//-----------------------------------------------------------------------------
+bool Startup()
+{
+ int i;
+
+ // set up our window class
+ WNDCLASS wndclass;
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = Main_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = LoadIcon( g_hInstance, (LPCTSTR)IDI_VPROJECT );
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = NULL;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = VPROJECT_CLASSNAME;
+ if ( !RegisterClass( &wndclass ) )
+ {
+ return false;
+ }
+
+ // create the hidden window
+ g_hWnd = CreateWindow(
+ VPROJECT_CLASSNAME,
+ 0,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ 0,
+ CW_USEDEFAULT,
+ 0,
+ NULL,
+ NULL,
+ g_hInstance,
+ NULL );
+
+ // Create tray icon
+ g_iconData.cbSize = sizeof( NOTIFYICONDATA );
+ g_iconData.hIcon = LoadIcon( g_hInstance, (LPCTSTR)IDI_VPROJECT );
+ g_iconData.hWnd = g_hWnd;
+ g_iconData.uCallbackMessage = WM_TRAY;
+ g_iconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+ g_iconData.uID = ID_TRAY;
+ strcpy(g_iconData.szTip, "VPROJECT");
+ Shell_NotifyIcon( NIM_ADD, &g_iconData );
+
+ // Create popup menu and add initial items
+ g_hMenu = CreatePopupMenu();
+ AppendMenu( g_hMenu, MF_SEPARATOR, 0, 0);
+ AppendMenu( g_hMenu, MF_STRING, ID_TRAY_ADDVPROJECT, "Add VProject" );
+ AppendMenu( g_hMenu, MF_STRING, ID_TRAY_MODIFYVPROJECT, "Modify VProject" );
+ AppendMenu( g_hMenu, MF_STRING, ID_TRAY_MOVEUP, "Move Up" );
+ AppendMenu( g_hMenu, MF_STRING, ID_TRAY_MOVEDOWN, "Move Down" );
+ AppendMenu( g_hMenu, MF_SEPARATOR, 0, 0);
+ AppendMenu( g_hMenu, MF_STRING, ID_TRAY_EXIT, "Remove From Tray" );
+
+ // find the current vproject
+ char* vproject = getenv( "vproject" );
+ if ( vproject && vproject[0] )
+ {
+ char temp[MAX_PATH];
+ strcpy( temp, vproject );
+ Sys_NormalizePath( temp, false );
+ for ( i=0; i<g_numProjects; i++ )
+ {
+ if ( !stricmp( g_projects[i].pGamedir, temp ) )
+ {
+ // found
+ g_nActiveVProject = i+1;
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Shutdown
+//
+// Free all resources
+//-----------------------------------------------------------------------------
+void Shutdown()
+{
+}
+
+//-----------------------------------------------------------------------------
+// WinMain
+//
+// Entry point for program
+//-----------------------------------------------------------------------------
+int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow )
+{
+ bool error = true;
+ MSG msg = {0};
+
+ g_hInstance = hInstance;
+
+ // get the project list
+ LoadRegistryValues();
+
+ if ( pCmdLine && pCmdLine[0] )
+ {
+ // set directly
+ SetVProject( pCmdLine );
+ return 0;
+ }
+
+ HWND hwnd = FindWindow( VPROJECT_CLASSNAME, NULL );
+ if ( hwnd )
+ {
+ // single instance only
+ return ( FALSE );
+ }
+
+ if ( !Startup() )
+ {
+ goto cleanUp;
+ }
+
+ // message pump
+ while ( GetMessage( &msg, NULL, 0, 0 ) )
+ {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+
+ // no-error, end of app
+ error = false;
+
+cleanUp:
+ if ( error )
+ {
+ char str[255];
+ FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0, str, 255, NULL );
+ MessageBox( NULL, str, NULL, MB_OK );
+ }
+
+ Shutdown();
+
+ return ( (int)msg.wParam );
+}
+
+