]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/preferences.cpp
fix
[xonotic/netradiant.git] / radiant / preferences.cpp
index 07b0a4799a62db0a45ec36f2bcb07344bcb40a5f..df20d71dc39be586ce0f264165b64334de8c512e 100644 (file)
@@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 #include "stdafx.h"
 #include <glib.h>
+#include <assert.h>
 #if defined (__linux__) || defined (__APPLE__)
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -745,6 +746,18 @@ CGameDescription::CGameDescription(xmlDocPtr pDoc, const Str &GameFile)
 
   mGameFile = GameFile;
 
+  prop = (char*)xmlGetProp(pNode, (xmlChar*)"quake2");
+  if (prop == NULL)
+  {
+    // default
+    quake2 = false;
+  }
+  else
+  {
+    quake2 = true;
+    xmlFree(prop);
+  }
+
   prop = (char*)xmlGetProp(pNode, (xmlChar*)"basegame");
   if (prop == NULL)
   {
@@ -953,60 +966,74 @@ void CGameDialog::SavePrefs()
   CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str;
   strGlobalPref += "global.pref";
   
-  if (!mGlobalPrefs.WriteXMLFile(strGlobalPref.GetBuffer()))
+  if ( !mGlobalPrefs.WriteXMLFile( strGlobalPref.GetBuffer() ) ) {
     Sys_FPrintf(SYS_ERR, "Error occured while saving global prefs file '%s'\n", strGlobalPref.GetBuffer());
+  }
 }
 
-void CGameDialog::DoGameDialog()
-{
-  // show the UI
-  DoModal();
+void CGameDialog::DoGameInstall() {
+       // make sure console logging is on whenever we enter the installation loop
+    g_PrefsDlg.mGamesDialog.m_bLogConsole = true;
+       Sys_LogFile();
+       mGameInstall.Run();
+}
+
+void CGameDialog::DoGameDialog() {
+       // allow looping the game selection dialog with calls to the game configure dialog in between
+       while ( m_bDoGameInstall ) {
+               
+               m_bDoGameInstall = false;
+
+               if ( DoModal() == IDCANCEL ) {
+                       Error( "game selection dialog canceled, cannot continue" );
+                       return;
+               }
+               
+               if ( m_bDoGameInstall ) {
+                       DoGameInstall();
+                       ScanForGames();
+                       // and we will loop to do another DoModal dialog
+               }
+       }
 
-  // unhook so we can use in other places
-  // we manually incref'ed it when creating, it won't be freed (destructor)
-  gtk_container_remove (GTK_CONTAINER (mTopBox), GetGlobalFrame());
+       // unhook so we can use in other places
+       // we manually incref'ed it when creating, it won't be freed (destructor)
+       gtk_container_remove( GTK_CONTAINER( mTopBox ), GetGlobalFrame() );
 
-  // we save the prefs file
-  SavePrefs();
+       // we save the prefs file
+       SavePrefs();
 }
 
 GtkWidget* CGameDialog::GetGlobalFrame()
 {
   GtkWidget *vbox, *text, *combo, *check;
 
-  if (mFrame)
-    return mFrame;
+  if ( mFrame != NULL ) {
+         return mFrame;
+  }
 
-  mFrame = gtk_frame_new(NULL);
-  gtk_container_set_border_width(GTK_CONTAINER(mFrame), 5);
-  gtk_widget_show(mFrame);
+  mFrame = gtk_frame_new( NULL );
+  gtk_container_set_border_width( GTK_CONTAINER( mFrame ), 5 );
+  gtk_widget_show( mFrame );
 
-  vbox = gtk_vbox_new (FALSE, 6);
-  gtk_widget_show (vbox);
-  gtk_container_add (GTK_CONTAINER (mFrame), vbox);
-  gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+  vbox = gtk_vbox_new( FALSE, 6 );
+  gtk_widget_show( vbox );
+  gtk_container_add( GTK_CONTAINER( mFrame ), vbox );
+  gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
 
-  text = gtk_label_new("Select the game:");
-  gtk_widget_show(text);
-  gtk_box_pack_start (GTK_BOX(vbox), text, FALSE, FALSE, 0);
-
-  combo = gtk_combo_new();
-  gtk_widget_show(combo);
-  gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
+  text = gtk_label_new( "Select the game:" );
+  gtk_widget_show( text );
+  gtk_box_pack_start( GTK_BOX( vbox ), text, FALSE, FALSE, 0 );
 
-  // fill in with the game descriptions
-  GList *combo_list = (GList*)NULL;
-  list<CGameDescription *>::iterator iGame;
-  for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++)
-  {
-    combo_list = g_list_append (combo_list, (void *)(*iGame)->mGameName.GetBuffer());
-  }
-  gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
-  g_list_free (combo_list);
+  combo = gtk_combo_box_new_text();
+  gtk_widget_show( combo );
+  gtk_box_pack_start( GTK_BOX( vbox ), combo, FALSE, FALSE, 0 );
+  AddDialogData( combo, &m_nComboSelect, DLG_COMBO_BOX_INT );
+  mGameCombo = GTK_COMBO_BOX( combo );
 
-  AddDialogData (combo, &m_nComboSelect, DLG_COMBO_INT);
+  UpdateGameCombo();
 
-  check = gtk_check_button_new_with_label("Auto load selected game on startup");
+  check = gtk_check_button_new_with_label( "Auto load selected game on startup" );
   gtk_widget_show(check);
   gtk_box_pack_start (GTK_BOX(vbox), check, FALSE, FALSE, 0);
   AddDialogData (check, &m_bAutoLoadGame, DLG_CHECK_BOOL);
@@ -1016,25 +1043,24 @@ GtkWidget* CGameDialog::GetGlobalFrame()
   gtk_box_pack_start (GTK_BOX(vbox), text, FALSE, FALSE, 0);
 
 #ifdef _WIN32
-  check = gtk_check_button_new_with_label("Networked install - per-user settings");
-  gtk_widget_show(check);
-  gtk_box_pack_start (GTK_BOX(vbox), check, FALSE, FALSE, 0);
-  AddDialogData (check, &m_bNetRun, DLG_CHECK_BOOL);
+  check = gtk_check_button_new_with_label( "Networked install - per-user settings" );
+  gtk_widget_show( check );
+  gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 );
+  AddDialogData( check, &m_bNetRun, DLG_CHECK_BOOL );
 #endif
 
-  check = gtk_check_button_new_with_label("Log the console to radiant.log");
-  gtk_widget_show(check);
-  gtk_box_pack_start (GTK_BOX(vbox), check, FALSE, FALSE, 0);
-  AddDialogData (check, &m_bLogConsole, DLG_CHECK_BOOL);
+  check = gtk_check_button_new_with_label( "Log the console to radiant.log" );
+  gtk_widget_show( check );
+  gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 );
+  AddDialogData( check, &m_bLogConsole, DLG_CHECK_BOOL );
 
   // incref it so we can pass it around
-  gtk_widget_ref (GTK_WIDGET(mFrame));
+  gtk_widget_ref( GTK_WIDGET( mFrame ) );
 
   return mFrame;
 }
 
-void CGameDialog::UpdateData (bool retrieve)
-{
+void CGameDialog::UpdateData( bool retrieve ) {
   if (!retrieve)
   {
     // use m_sGameFile to set m_nComboSelect
@@ -1070,25 +1096,65 @@ void CGameDialog::UpdateData (bool retrieve)
   }
 }
 
-void CGameDialog::BuildDialog()
-{
-  GtkWidget *dlg, *vbox1, *button;
+void CGameDialog::SInstallCallback( GtkWidget *widget, gpointer data ) {
+       CGameDialog *d = static_cast< CGameDialog* >( data );
+       d->m_bDoGameInstall = true;
+       d->EndModal( 0 );
+}
 
-  dlg = m_pWidget;
-  gtk_window_set_title (GTK_WINDOW (dlg), "Select Game");
+void CGameDialog::BuildDialog() {
+       GtkWidget *dlg, *vbox1, *button, *setup_button;
+       
+       dlg = m_pWidget;
+       gtk_window_set_title( GTK_WINDOW( dlg ), "Select Game" );
+
+       vbox1 = gtk_vbox_new( FALSE, 0 );
+       gtk_widget_show( vbox1 );
+       gtk_container_add( GTK_CONTAINER( dlg ), vbox1 );
+
+       gtk_container_add( GTK_CONTAINER( vbox1 ), GetGlobalFrame() );
+       mTopBox = vbox1;
+
+       setup_button = gtk_button_new_with_label( "Configure more games" );
+       gtk_widget_show( setup_button );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), setup_button, FALSE, FALSE, 0 );
+       gtk_signal_connect( GTK_OBJECT( setup_button ), "clicked",
+                                               GTK_SIGNAL_FUNC( SInstallCallback ), this );
+
+       button = gtk_button_new_with_label( "OK" );
+       gtk_widget_show( button );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 );
+       AddModalButton( button, IDOK );
+
+       button = gtk_button_new_with_label( "Cancel" );
+       gtk_widget_show( button );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 );
+       AddModalButton( button, IDCANCEL );
+       
+       gtk_widget_set_usize( button, 60, -2 );
+}
 
-  vbox1 = gtk_vbox_new (FALSE, 0);
-  gtk_widget_show(vbox1);
-  gtk_container_add (GTK_CONTAINER (dlg), vbox1);
+void CGameDialog::UpdateGameCombo() {
+  // fill in with the game descriptions
+  list<CGameDescription *>::iterator iGame;
 
-  gtk_container_add (GTK_CONTAINER (vbox1), GetGlobalFrame());
-  mTopBox = vbox1;
+  if ( mGameCombo == NULL ) {
+         Sys_Printf( "mGameCombo == NULL\n" );
+         return;
+  }
 
-  button = gtk_button_new_with_label ("OK");
-  gtk_widget_show (button);
-  gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 0);
-  AddModalButton(button, IDOK);
-  gtk_widget_set_usize (button, 60, -2);
+  // clear whatever is in - wtf no way to know how many text entries?
+  // use set/get active to track 
+  gtk_combo_box_set_active( mGameCombo, 0 );
+  while ( gtk_combo_box_get_active( mGameCombo ) == 0 ) {
+         gtk_combo_box_remove_text( mGameCombo, 0 );
+         gtk_combo_box_set_active( mGameCombo, 0 );
+  }
+  
+  for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) {
+         gtk_combo_box_append_text( mGameCombo, (*iGame)->mGameName.GetBuffer() );
+  }
+  gtk_combo_box_set_active( mGameCombo, 0 );
 }
 
 void CGameDialog::ScanForGames()
@@ -1100,7 +1166,16 @@ void CGameDialog::ScanForGames()
   strGamesPath += "games";
   const char *path = strGamesPath.GetBuffer();
 
-  Sys_Printf("Scanning for game description files: %s\n", path);
+  if ( !mGames.empty() ) {
+         Sys_Printf( "Clearing game list\n" );
+         list<CGameDescription*>::iterator iGame;
+         for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) {
+                 delete (*iGame);
+         }
+         mGames.clear();
+  }
+
+  Sys_Printf( "Scanning for game description files: %s\n", path );
 
   /*!
   \todo FIXME LINUX:
@@ -1136,56 +1211,34 @@ void CGameDialog::ScanForGames()
       xmlDocPtr pDoc = xmlParseFile(strPath.GetBuffer());
       if (pDoc)
       {
-        mGames.push_front(new CGameDescription(pDoc, dirlist));
+        mGames.push_front( new CGameDescription( pDoc, dirlist ) );
       }
       else
       {
         Sys_FPrintf(SYS_ERR, "XML parser failed on '%s'\n", strPath.GetBuffer());
       }
 
-      g_free(dirlist);
+      g_free( dirlist );
     }
-    g_dir_close (dir);
+    g_dir_close( dir );
   }
+
+  // entries in the combo need to be updated
+  UpdateGameCombo();
 }
 
 CGameDescription* CGameDialog::GameDescriptionForComboItem()
 {
   list<CGameDescription *>::iterator iGame;
   int i=0;
-  for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++,i++)
-  {
-    if (i == m_nComboSelect)
-    {
+  for( iGame = mGames.begin(); iGame != mGames.end(); iGame++,i++ ) {
+    if ( i == m_nComboSelect ) {
       return (*iGame);
     }
   }
   return NULL; // not found
 }
 
-/*GString* CGameDialog::InitGlobalPrefPath()
-{
-  GString* global_rc_path;
-  // configure m_global_rc_path
-#if defined (__linux__) || defined (__APPLE__)
-  global_rc_path = g_string_new (g_get_home_dir ());
-
-  if (global_rc_path->str[global_rc_path->len-1] != '/')
-    g_string_append (global_rc_path, "/");
-
-  g_string_append (global_rc_path, ".radiant/");
-  mkdir (global_rc_path->str, 0775);
-  g_string_append (global_rc_path, RADIANT_VERSION);
-  g_string_append (global_rc_path, "/");
-  mkdir (global_rc_path->str, 0775);
-#elif WIN32
-  global_rc_path = g_string_new (g_strAppPath.GetBuffer() );
-#else
-#error "WTF are you compiling under"
-#endif
-  return global_rc_path;
-}*/
-
 void CGameDialog::InitGlobalPrefPath()
 {
   GString *global_rc_path;
@@ -1208,13 +1261,15 @@ void CGameDialog::Init()
 {
   InitGlobalPrefPath();
   ScanForGames();
-  if (mGames.empty())
-  {
-    Error("Didn't find any valid game file descriptions, aborting\n");
+  if ( mGames.empty() ) {
+         DoGameInstall();
+         ScanForGames();
+         if ( mGames.empty() ) {
+                 Error( "No games setup, aborting\n" );
+         }
   }
   LoadPrefs();
-  if (m_bAutoLoadGame)
-  {
+  if ( m_bAutoLoadGame ) {
     // search by .game name
     list<CGameDescription *>::iterator iGame;
     for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++)
@@ -1226,13 +1281,13 @@ void CGameDialog::Init()
       }
     }
   }
-  if (!m_bAutoLoadGame || !m_pCurrentGameDescription)
-  {
+  if ( !m_bAutoLoadGame || !m_pCurrentGameDescription ) {
     DoGameDialog();
     // use m_nComboSelect to identify the game to run as and set the globals
     m_pCurrentGameDescription = GameDescriptionForComboItem();
-    if (!m_pCurrentGameDescription)
-      Error("Lookup of game description object failed, can't continue\n");
+    if ( !m_pCurrentGameDescription ) {
+               Error("Lookup of game description object failed, can't continue\n");
+       }
   }
   g_pGameDescription = m_pCurrentGameDescription;
 
@@ -1494,7 +1549,7 @@ void PrefsDlg::BuildDialog ()
   gtk_widget_show(button);
   gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
   gtk_widget_set_usize(button, 60, -2);
-  AddModalButton (button, IDCANCEL);
+  AddModalButton(button, IDCANCEL);
 
   button = gtk_button_new_with_label ("Clean");
   gtk_widget_show(button);
@@ -3015,10 +3070,11 @@ void PrefsDlg::SavePrefs ()
   if (!mLocalPrefs.WriteXMLFile(m_inipath->str))
     Sys_FPrintf(SYS_ERR, "Error occured while saving local prefs file '%s'\n", m_inipath->str);
 
-  if (m_nMouse == 0)
-    m_nMouseButtons = 2;
-  else
-    m_nMouseButtons = 3;
+  if ( m_nMouse == 0 ) {
+         m_nMouseButtons = 2;
+  } else {
+         m_nMouseButtons = 3;
+  }
 
 }
 
@@ -3100,3 +3156,290 @@ void PrefsDlg::DoSensitivity()
       gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), FALSE );
     }
 }
+
+/*
+============================================================
+CGameInstall
+============================================================
+*/
+
+CGameInstall::CGameInstall() {
+       memset( m_availGames, 0, sizeof( m_availGames ) );
+}
+
+void CGameInstall::OnBtnBrowseEngine( GtkWidget *widget, gpointer data ) {
+       Sys_Printf( "OnBtnBrowseEngine\n" );
+
+       CGameInstall* i = static_cast<CGameInstall*>( data );
+       char *dir = dir_dialog( widget, "Select game directory", NULL );
+
+       i->UpdateData( TRUE );
+
+       if ( dir != NULL ) {
+               i->m_strEngine = dir;
+               i->UpdateData( FALSE );
+               free( dir );
+       }
+}
+
+void CGameInstall::OnGameSelectChanged( GtkWidget *widget, gpointer data ) {
+       Sys_Printf( "OnGameSelectChanged\n" );
+
+       CGameInstall* i = static_cast<CGameInstall*>( data );
+       i->UpdateData( TRUE );  
+       i->m_strName = gtk_combo_box_get_active_text( GTK_COMBO_BOX( widget ) );
+       i->UpdateData( FALSE );
+}
+
+void CGameInstall::BuildDialog() {
+       GtkWidget *dlg, *vbox1, *button, *text, *combo, *entry, *hbox;
+       
+       dlg = m_pWidget;
+       gtk_window_set_title( GTK_WINDOW( dlg ), "Configure games" );
+
+       vbox1 = gtk_vbox_new( FALSE, 0 );
+       gtk_widget_show( vbox1 );
+       gtk_container_add( GTK_CONTAINER( dlg ), vbox1 );
+
+       text = gtk_label_new( "Select the game to configure" );
+       gtk_widget_show( text );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 );
+
+       combo = gtk_combo_box_new_text();
+       gtk_widget_show( combo );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), combo, FALSE, FALSE, 0 );
+
+       //      GList *combo_list = NULL;
+       int iGame = 0;
+       while ( m_availGames[ iGame ] != GAME_NONE ) {
+               switch ( m_availGames[ iGame ] ) {
+               case GAME_Q2:
+                       gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Quake II" );
+                       break;
+               case GAME_Q3:
+                       gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Quake III Arena and mods" );
+                       break;
+               case GAME_URT:
+                       gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Urban Terror (standalone)" );
+                       break;
+               case GAME_UFOAI:
+                       gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "UFO: Alien Invasion" );
+                       break;
+               case GAME_Q2W:
+                       gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Quake2World" );
+                       break;
+               case GAME_WARSOW:
+                       gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Warsow" );
+                       break;
+               case GAME_NEXUIZ:
+                       gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Nexuiz" );
+                       break;
+               }
+               iGame++;
+       }
+       AddDialogData( combo, &m_nComboSelect, DLG_COMBO_BOX_INT );
+       gtk_signal_connect( GTK_OBJECT( combo ), "changed", G_CALLBACK( OnGameSelectChanged ), this );
+       gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 );  // NOTE: will trigger signal
+
+       text = gtk_label_new( "Name:" );
+       gtk_widget_show( text );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 );
+       
+       entry = gtk_entry_new();
+       gtk_widget_show( entry );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), entry, FALSE, FALSE, 0 );
+       AddDialogData( entry, &m_strName, DLG_ENTRY_TEXT );
+
+       text = gtk_label_new( "Engine directory:" );
+       gtk_widget_show( text );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 );
+
+       hbox = gtk_hbox_new( FALSE, 0 );
+       gtk_widget_show( hbox );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), hbox, FALSE, FALSE, 0 );
+       
+       entry = gtk_entry_new();
+       gtk_widget_show( entry );
+       gtk_box_pack_start( GTK_BOX( hbox ), entry, FALSE, FALSE, 0 );
+       AddDialogData( entry, &m_strEngine, DLG_ENTRY_TEXT );
+
+       button = gtk_button_new_with_label ("...");
+       gtk_widget_show( button );
+       gtk_signal_connect( GTK_OBJECT( button ), "clicked", GTK_SIGNAL_FUNC( OnBtnBrowseEngine ), this );
+       gtk_box_pack_start( GTK_BOX( hbox ), button, FALSE, FALSE, 0 );
+
+       // this gets done in the project stuff atm
+#if 0
+       text = gtk_label_new( "Mod subdirectory:" );
+       gtk_widget_show( text );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 );
+
+       entry = gtk_entry_new();
+       gtk_widget_show( entry );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), entry, FALSE, FALSE, 0 );
+       AddDialogData( entry, &m_strMod, DLG_ENTRY_TEXT );
+#endif
+
+       button = gtk_button_new_with_label( "OK" );
+       gtk_widget_show( button );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 );
+       AddModalButton( button, IDOK );
+
+       button = gtk_button_new_with_label( "Cancel" );
+       gtk_widget_show( button );
+       gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 );
+       AddModalButton( button, IDCANCEL );
+
+       gtk_widget_set_usize( button, 60, -2 );
+}
+
+void CGameInstall::Run() {
+       ScanGames();
+       if ( DoModal() == IDCANCEL ) {
+               Sys_Printf( "game dialog cancelled\n" );
+               return;
+       }
+       Sys_Printf( "combo: %d name: %s engine: %s mod: %s\n", m_nComboSelect, m_strName.GetBuffer(), m_strEngine.GetBuffer(), m_strMod.GetBuffer() );
+
+       // write out the game file
+       Str gameFilePath = g_strAppPath.GetBuffer();
+       gameFilePath += "games/";
+       gameFilePath += m_strName.GetBuffer();
+       gameFilePath += ".game";
+       Sys_Printf( "game file: %s\n", gameFilePath.GetBuffer() );
+
+       FILE *fg = fopen( gameFilePath.GetBuffer(), "w" );
+       if ( fg == NULL ) {
+               Error( "Failed to open %s for writing\n", gameFilePath.GetBuffer() );
+       }
+       fprintf( fg, "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>\n<game\n" );
+       fprintf( fg, "  name=\"%s\"\n", m_strName.GetBuffer() );
+       fprintf( fg, "  enginepath=\"%s\"\n", m_strEngine.GetBuffer() );
+       switch ( m_availGames[ m_nComboSelect ] ) {
+       case GAME_Q2: {
+               fprintf( fg, "  gametools=\"%sinstalls/Quake2Pack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  prefix=\".quake2\"\n" );
+               Str source = g_strAppPath.GetBuffer();
+               source += "installs/";
+               source += Q2_PACK;
+               source += "/install/";
+               Str dest = m_strEngine.GetBuffer();
+               CopyTree( source.GetBuffer(), dest.GetBuffer() );
+               fprintf( fg, "  basegame=\"baseq2\"\n" );
+               break;
+       }
+       case GAME_Q3: {
+               fprintf( fg, "  gametools=\"%sinstalls/Q3Pack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  prefix=\".q3a\"\n" );
+               Str source = g_strAppPath.GetBuffer();
+               source += "installs/";
+               source += Q3_PACK;
+               source += "/install/";
+               Str dest = m_strEngine.GetBuffer();
+               CopyTree( source.GetBuffer(), dest.GetBuffer() );
+               fprintf( fg, "  basegame=\"baseq3\"\n" );
+               break;
+       }
+       case GAME_URT: {
+               fprintf( fg, "  gametools=\"%sinstalls/UrTPack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  prefix=\".q3a\"\n" );
+               Str source = g_strAppPath.GetBuffer();
+               source += "installs/";
+               source += URT_PACK;
+               source += "/install/";
+               Str dest = m_strEngine.GetBuffer();
+               CopyTree( source.GetBuffer(), dest.GetBuffer() );
+               fprintf( fg, "  basegame=\"q3ut4\"\n" );
+               break;
+       }
+       case GAME_UFOAI: {
+               fprintf( fg, "  gametools=\"%sinstalls/UFOAIPack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  prefix=\".ufoai\"\n" );
+               Str source = g_strAppPath.GetBuffer();
+               source += "installs/";
+               source += UFOAI_PACK;
+               source += "/install/";
+               Str dest = m_strEngine.GetBuffer();
+               CopyTree( source.GetBuffer(), dest.GetBuffer() );
+               fprintf( fg, "  basegame=\"base\"\n" );
+               break;
+       }
+       case GAME_Q2W: {
+               fprintf( fg, "  gametools=\"%sinstalls/Q2WPack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  prefix=\".quake2world\"\n" );
+               Str source = g_strAppPath.GetBuffer();
+               source += "installs/";
+               source += Q2W_PACK;
+               source += "/install/";
+               Str dest = m_strEngine.GetBuffer();
+               CopyTree( source.GetBuffer(), dest.GetBuffer() );
+               fprintf( fg, "  basegame=\"default\"\n" );
+               break;
+       }
+       case GAME_WARSOW: {
+               fprintf( fg, "  gametools=\"%sinstalls/WarsowPack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  prefix=\".warsow\"\n" );
+               Str source = g_strAppPath.GetBuffer();
+               source += "installs/";
+               source += WARSOW_PACK;
+               source += "/install/";
+               Str dest = m_strEngine.GetBuffer();
+               CopyTree( source.GetBuffer(), dest.GetBuffer() );
+               fprintf( fg, "  basegame=\"basewsw\"\n" );
+               break;
+       }
+       case GAME_NEXUIZ: {
+               fprintf( fg, "  gametools=\"%sinstalls/NexuizPack/game\"\n", g_strAppPath.GetBuffer() );
+               fprintf( fg, "  prefix=\".nexuiz\"\n" );
+               Str source = g_strAppPath.GetBuffer();
+               source += "installs/";
+               source += NEXUIZ_PACK;
+               source += "/install/";
+               Str dest = m_strEngine.GetBuffer();
+               CopyTree( source.GetBuffer(), dest.GetBuffer() );
+               fprintf( fg, "  basegame=\"data\"\n" );
+               break;
+       }
+       }
+       fprintf( fg, "/>\n" );
+       fclose( fg );
+}
+
+/*
+===============
+CGameInstall::ScanGames
+scan for active games that can be installed, based on the presence 
+===============
+*/
+void CGameInstall::ScanGames() {
+       Str                             pakPaths = g_strAppPath.GetBuffer();
+       int                             iGame = 0;
+       const char              *dirname;
+
+       pakPaths +=     "installs/";
+       FindFiles fileScan( pakPaths.GetBuffer() );
+       while ( ( dirname = fileScan.NextFile() ) != NULL ) {
+               if ( stricmp( dirname, Q3_PACK ) == 0 ) {
+                       m_availGames[ iGame++ ] = GAME_Q3;
+               }
+               if ( stricmp( dirname, URT_PACK ) == 0 ) {
+                       m_availGames[ iGame++ ] = GAME_URT;
+               }
+               if ( stricmp( dirname, UFOAI_PACK ) == 0 ) {
+                       m_availGames[ iGame++ ] = GAME_UFOAI;
+               }
+               if ( stricmp( dirname, Q2W_PACK ) == 0 ) {
+                       m_availGames[ iGame++ ] = GAME_Q2W;
+               }
+               if ( stricmp( dirname, WARSOW_PACK ) == 0 ) {
+                       m_availGames[ iGame++ ] = GAME_WARSOW;
+               }
+               if ( stricmp( dirname, NEXUIZ_PACK ) == 0 ) {
+                       m_availGames[ iGame++ ] = GAME_NEXUIZ;
+               }
+               if ( stricmp( dirname, Q2_PACK ) == 0 ) {
+                       m_availGames[ iGame++ ] = GAME_Q2;
+               }
+       }
+}
+