]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/preferences.cpp
reformat code! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / radiant / preferences.cpp
index 091a88f36324bb884e4c203bebe28b374995a009..fbd9815169fb935bc5bcea1b316638e47eab80ed 100644 (file)
 #include "gtkdlgs.h"
 
 
-
-void Global_constructPreferences( PreferencesPage& page ){
-       page.appendCheckBox( "Console", "Enable Logging", g_Console_enableLogging );
+void Global_constructPreferences(PreferencesPage &page)
+{
+    page.appendCheckBox("Console", "Enable Logging", g_Console_enableLogging);
 }
 
-void Interface_constructPreferences( PreferencesPage& page ){
+void Interface_constructPreferences(PreferencesPage &page)
+{
 #if GDEF_OS_WINDOWS
-       page.appendCheckBox( "", "Default Text Editor", g_TextEditor_useWin32Editor );
+    page.appendCheckBox( "", "Default Text Editor", g_TextEditor_useWin32Editor );
 #else
-       {
-               ui::CheckButton use_custom = page.appendCheckBox( "Text Editor", "Custom", g_TextEditor_useCustomEditor );
-               ui::Widget custom_editor = page.appendPathEntry( "Text Editor Command", g_TextEditor_editorCommand, true );
-               Widget_connectToggleDependency( custom_editor, use_custom );
-       }
+    {
+        ui::CheckButton use_custom = page.appendCheckBox("Text Editor", "Custom", g_TextEditor_useCustomEditor);
+        ui::Widget custom_editor = page.appendPathEntry("Text Editor Command", g_TextEditor_editorCommand, true);
+        Widget_connectToggleDependency(custom_editor, use_custom);
+    }
 #endif
 }
 
-void Mouse_constructPreferences( PreferencesPage& page ){
-       {
-               const char* buttons[] = { "2 button", "3 button", };
-               page.appendRadio( "Mouse Type",  g_glwindow_globals.m_nMouseType, STRING_ARRAY_RANGE( buttons ) );
-       }
-       page.appendCheckBox( "Right Button", "Activates Context Menu", g_xywindow_globals.m_bRightClick );
+void Mouse_constructPreferences(PreferencesPage &page)
+{
+    {
+        const char *buttons[] = {"2 button", "3 button",};
+        page.appendRadio("Mouse Type", g_glwindow_globals.m_nMouseType, STRING_ARRAY_RANGE(buttons));
+    }
+    page.appendCheckBox("Right Button", "Activates Context Menu", g_xywindow_globals.m_bRightClick);
 }
-void Mouse_constructPage( PreferenceGroup& group ){
-       PreferencesPage page( group.createPage( "Mouse", "Mouse Preferences" ) );
-       Mouse_constructPreferences( page );
+
+void Mouse_constructPage(PreferenceGroup &group)
+{
+    PreferencesPage page(group.createPage("Mouse", "Mouse Preferences"));
+    Mouse_constructPreferences(page);
 }
-void Mouse_registerPreferencesPage(){
-       PreferencesDialog_addInterfacePage( makeCallbackF(Mouse_constructPage) );
+
+void Mouse_registerPreferencesPage()
+{
+    PreferencesDialog_addInterfacePage(makeCallbackF(Mouse_constructPage));
 }
 
 
@@ -94,61 +100,62 @@ void Mouse_registerPreferencesPage(){
 #include <map>
 #include <uilib/uilib.h>
 
-inline const char* xmlAttr_getName( xmlAttrPtr attr ){
-       return reinterpret_cast<const char*>( attr->name );
-}
-
-inline const char* xmlAttr_getValue( xmlAttrPtr attr ){
-       return reinterpret_cast<const char*>( attr->children->content );
+inline const char *xmlAttr_getName(xmlAttrPtr attr)
+{
+    return reinterpret_cast<const char *>( attr->name );
 }
 
-CGameDescription::CGameDescription( xmlDocPtr pDoc, const CopiedString& gameFile ){
-       // read the user-friendly game name
-       xmlNodePtr pNode = pDoc->children;
-
-       while ( strcmp( (const char*)pNode->name, "game" ) && pNode != 0 )
-       {
-               pNode = pNode->next;
-       }
-       if ( !pNode ) {
-               Error( "Didn't find 'game' node in the game description file '%s'\n", pDoc->URL );
-       }
-
-       for ( xmlAttrPtr attr = pNode->properties; attr != 0; attr = attr->next )
-       {
-               m_gameDescription.insert( GameDescription::value_type( xmlAttr_getName( attr ), xmlAttr_getValue( attr ) ) );
-       }
-
-       {
-               StringOutputStream path( 256 );
-               path << AppPath_get() << gameFile.c_str() << "/";
-               mGameToolsPath = path.c_str();
-       }
-
-       ASSERT_MESSAGE( file_exists( mGameToolsPath.c_str() ), "game directory not found: " << makeQuoted( mGameToolsPath.c_str() ) );
-
-       mGameFile = gameFile;
-
-       {
-               GameDescription::iterator i = m_gameDescription.find( "type" );
-               if ( i == m_gameDescription.end() ) {
-                       globalErrorStream() << "Warning, 'type' attribute not found in '" << reinterpret_cast<const char*>( pDoc->URL ) << "'\n";
-                       // default
-                       mGameType = "q3";
-               }
-               else
-               {
-                       mGameType = ( *i ).second.c_str();
-               }
-       }
+inline const char *xmlAttr_getValue(xmlAttrPtr attr)
+{
+    return reinterpret_cast<const char *>( attr->children->content );
 }
 
-void CGameDescription::Dump(){
-       globalOutputStream() << "game description file: " << makeQuoted( mGameFile.c_str() ) << "\n";
-       for ( GameDescription::iterator i = m_gameDescription.begin(); i != m_gameDescription.end(); ++i )
-       {
-               globalOutputStream() << ( *i ).first.c_str() << " = " << makeQuoted( ( *i ).second.c_str() ) << "\n";
-       }
+CGameDescription::CGameDescription(xmlDocPtr pDoc, const CopiedString &gameFile)
+{
+    // read the user-friendly game name
+    xmlNodePtr pNode = pDoc->children;
+
+    while (strcmp((const char *) pNode->name, "game") && pNode != 0) {
+        pNode = pNode->next;
+    }
+    if (!pNode) {
+        Error("Didn't find 'game' node in the game description file '%s'\n", pDoc->URL);
+    }
+
+    for (xmlAttrPtr attr = pNode->properties; attr != 0; attr = attr->next) {
+        m_gameDescription.insert(GameDescription::value_type(xmlAttr_getName(attr), xmlAttr_getValue(attr)));
+    }
+
+    {
+        StringOutputStream path(256);
+        path << AppPath_get() << gameFile.c_str() << "/";
+        mGameToolsPath = path.c_str();
+    }
+
+    ASSERT_MESSAGE(file_exists(mGameToolsPath.c_str()),
+                   "game directory not found: " << makeQuoted(mGameToolsPath.c_str()));
+
+    mGameFile = gameFile;
+
+    {
+        GameDescription::iterator i = m_gameDescription.find("type");
+        if (i == m_gameDescription.end()) {
+            globalErrorStream() << "Warning, 'type' attribute not found in '"
+                                << reinterpret_cast<const char *>( pDoc->URL ) << "'\n";
+            // default
+            mGameType = "q3";
+        } else {
+            mGameType = (*i).second.c_str();
+        }
+    }
+}
+
+void CGameDescription::Dump()
+{
+    globalOutputStream() << "game description file: " << makeQuoted(mGameFile.c_str()) << "\n";
+    for (GameDescription::iterator i = m_gameDescription.begin(); i != m_gameDescription.end(); ++i) {
+        globalOutputStream() << (*i).first.c_str() << " = " << makeQuoted((*i).second.c_str()) << "\n";
+    }
 }
 
 CGameDescription *g_pGameDescription; ///< shortcut to g_GamesDialog.m_pCurrentDescription
@@ -164,306 +171,319 @@ CGameDescription *g_pGameDescription; ///< shortcut to g_GamesDialog.m_pCurrentD
 #include "preferencedictionary.h"
 #include "stringio.h"
 
-const char* const PREFERENCES_VERSION = "1.0";
-
-bool Preferences_Load( PreferenceDictionary& preferences, const char* filename, const char *cmdline_prefix ){
-       bool ret = false;
-       TextFileInputStream file( filename );
-       if ( !file.failed() ) {
-               XMLStreamParser parser( file );
-               XMLPreferenceDictionaryImporter importer( preferences, PREFERENCES_VERSION );
-               parser.exportXML( importer );
-               ret = true;
-       }
-
-       int l = strlen( cmdline_prefix );
-       for ( int i = 1; i < g_argc - 1; ++i )
-       {
-               if ( g_argv[i][0] == '-' ) {
-                       if ( !strncmp( g_argv[i] + 1, cmdline_prefix, l ) ) {
-                               if ( g_argv[i][l + 1] == '-' ) {
-                                       preferences.importPref( g_argv[i] + l + 2, g_argv[i + 1] );
-                               }
-                       }
-                       ++i;
-               }
-       }
-
-       return ret;
-}
-
-bool Preferences_Save( PreferenceDictionary& preferences, const char* filename ){
-       TextFileOutputStream file( filename );
-       if ( !file.failed() ) {
-               XMLStreamWriter writer( file );
-               XMLPreferenceDictionaryExporter exporter( preferences, PREFERENCES_VERSION );
-               exporter.exportXML( writer );
-               return true;
-       }
-       return false;
-}
-
-bool Preferences_Save_Safe( PreferenceDictionary& preferences, const char* filename ){
-       Array<char> tmpName( filename, filename + strlen( filename ) + 1 + 3 );
-       *( tmpName.end() - 4 ) = 'T';
-       *( tmpName.end() - 3 ) = 'M';
-       *( tmpName.end() - 2 ) = 'P';
-       *( tmpName.end() - 1 ) = '\0';
-
-       return Preferences_Save( preferences, tmpName.data() )
-                  && ( !file_exists( filename ) || file_remove( filename ) )
-                  && file_move( tmpName.data(), filename );
+const char *const PREFERENCES_VERSION = "1.0";
+
+bool Preferences_Load(PreferenceDictionary &preferences, const char *filename, const char *cmdline_prefix)
+{
+    bool ret = false;
+    TextFileInputStream file(filename);
+    if (!file.failed()) {
+        XMLStreamParser parser(file);
+        XMLPreferenceDictionaryImporter importer(preferences, PREFERENCES_VERSION);
+        parser.exportXML(importer);
+        ret = true;
+    }
+
+    int l = strlen(cmdline_prefix);
+    for (int i = 1; i < g_argc - 1; ++i) {
+        if (g_argv[i][0] == '-') {
+            if (!strncmp(g_argv[i] + 1, cmdline_prefix, l)) {
+                if (g_argv[i][l + 1] == '-') {
+                    preferences.importPref(g_argv[i] + l + 2, g_argv[i + 1]);
+                }
+            }
+            ++i;
+        }
+    }
+
+    return ret;
+}
+
+bool Preferences_Save(PreferenceDictionary &preferences, const char *filename)
+{
+    TextFileOutputStream file(filename);
+    if (!file.failed()) {
+        XMLStreamWriter writer(file);
+        XMLPreferenceDictionaryExporter exporter(preferences, PREFERENCES_VERSION);
+        exporter.exportXML(writer);
+        return true;
+    }
+    return false;
+}
+
+bool Preferences_Save_Safe(PreferenceDictionary &preferences, const char *filename)
+{
+    Array<char> tmpName(filename, filename + strlen(filename) + 1 + 3);
+    *(tmpName.end() - 4) = 'T';
+    *(tmpName.end() - 3) = 'M';
+    *(tmpName.end() - 2) = 'P';
+    *(tmpName.end() - 1) = '\0';
+
+    return Preferences_Save(preferences, tmpName.data())
+           && (!file_exists(filename) || file_remove(filename))
+           && file_move(tmpName.data(), filename);
 }
 
 
 struct LogConsole {
-       static void Export(const Callback<void(bool)> &returnz) {
-               returnz(g_Console_enableLogging);
-       }
-
-       static void Import(bool value) {
-               g_Console_enableLogging = value;
-               Sys_LogFile(g_Console_enableLogging);
-       }
+    static void Export(const Callback<void(bool)> &returnz)
+    {
+        returnz(g_Console_enableLogging);
+    }
+
+    static void Import(bool value)
+    {
+        g_Console_enableLogging = value;
+        Sys_LogFile(g_Console_enableLogging);
+    }
 };
 
 
-void RegisterGlobalPreferences( PreferenceSystem& preferences ){
-       preferences.registerPreference( "gamefile", make_property_string( g_GamesDialog.m_sGameFile ) );
-       preferences.registerPreference( "gamePrompt", make_property_string( g_GamesDialog.m_bGamePrompt ) );
-       preferences.registerPreference( "log console", make_property_string<LogConsole>() );
+void RegisterGlobalPreferences(PreferenceSystem &preferences)
+{
+    preferences.registerPreference("gamefile", make_property_string(g_GamesDialog.m_sGameFile));
+    preferences.registerPreference("gamePrompt", make_property_string(g_GamesDialog.m_bGamePrompt));
+    preferences.registerPreference("log console", make_property_string<LogConsole>());
 }
 
 
 PreferenceDictionary g_global_preferences;
 
-void GlobalPreferences_Init(){
-       RegisterGlobalPreferences( g_global_preferences );
+void GlobalPreferences_Init()
+{
+    RegisterGlobalPreferences(g_global_preferences);
 }
 
-void CGameDialog::LoadPrefs(){
-       // load global .pref file
-       StringOutputStream strGlobalPref( 256 );
-       strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref";
+void CGameDialog::LoadPrefs()
+{
+    // load global .pref file
+    StringOutputStream strGlobalPref(256);
+    strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref";
 
-       globalOutputStream() << "loading global preferences from " << makeQuoted( strGlobalPref.c_str() ) << "\n";
+    globalOutputStream() << "loading global preferences from " << makeQuoted(strGlobalPref.c_str()) << "\n";
 
-       if ( !Preferences_Load( g_global_preferences, strGlobalPref.c_str(), "global" ) ) {
-               globalOutputStream() << "failed to load global preferences from " << strGlobalPref.c_str() << "\n";
-       }
+    if (!Preferences_Load(g_global_preferences, strGlobalPref.c_str(), "global")) {
+        globalOutputStream() << "failed to load global preferences from " << strGlobalPref.c_str() << "\n";
+    }
 }
 
-void CGameDialog::SavePrefs(){
-       StringOutputStream strGlobalPref( 256 );
-       strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref";
+void CGameDialog::SavePrefs()
+{
+    StringOutputStream strGlobalPref(256);
+    strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref";
 
-       globalOutputStream() << "saving global preferences to " << strGlobalPref.c_str() << "\n";
+    globalOutputStream() << "saving global preferences to " << strGlobalPref.c_str() << "\n";
 
-       if ( !Preferences_Save_Safe( g_global_preferences, strGlobalPref.c_str() ) ) {
-               globalOutputStream() << "failed to save global preferences to " << strGlobalPref.c_str() << "\n";
-       }
+    if (!Preferences_Save_Safe(g_global_preferences, strGlobalPref.c_str())) {
+        globalOutputStream() << "failed to save global preferences to " << strGlobalPref.c_str() << "\n";
+    }
 }
 
-void CGameDialog::DoGameDialog(){
-       // show the UI
-       DoModal();
+void CGameDialog::DoGameDialog()
+{
+    // show the UI
+    DoModal();
 
-       // we save the prefs file
-       SavePrefs();
+    // we save the prefs file
+    SavePrefs();
 }
 
-void CGameDialog::GameFileImport( int value ){
-       m_nComboSelect = value;
-       // use value to set m_sGameFile
-       std::list<CGameDescription *>::iterator iGame = mGames.begin();
-       int i;
-       for ( i = 0; i < value; i++ )
-       {
-               ++iGame;
-       }
-       m_sGameFile = ( *iGame )->mGameFile;
+void CGameDialog::GameFileImport(int value)
+{
+    m_nComboSelect = value;
+    // use value to set m_sGameFile
+    std::list<CGameDescription *>::iterator iGame = mGames.begin();
+    int i;
+    for (i = 0; i < value; i++) {
+        ++iGame;
+    }
+    m_sGameFile = (*iGame)->mGameFile;
 }
 
-void CGameDialog::GameFileExport( const Callback<void(int)> & importCallback ) const {
-       // use m_sGameFile to set value
-       std::list<CGameDescription *>::const_iterator iGame;
-       int i = 0;
-       for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame )
-       {
-               if ( ( *iGame )->mGameFile == m_sGameFile ) {
-                       m_nComboSelect = i;
-                       break;
-               }
-               i++;
-       }
-       importCallback( m_nComboSelect );
+void CGameDialog::GameFileExport(const Callback<void(int)> &importCallback) const
+{
+    // use m_sGameFile to set value
+    std::list<CGameDescription *>::const_iterator iGame;
+    int i = 0;
+    for (iGame = mGames.begin(); iGame != mGames.end(); ++iGame) {
+        if ((*iGame)->mGameFile == m_sGameFile) {
+            m_nComboSelect = i;
+            break;
+        }
+        i++;
+    }
+    importCallback(m_nComboSelect);
 }
 
 struct CGameDialog_GameFile {
-       static void Export(const CGameDialog &self, const Callback<void(int)> &returnz) {
-               self.GameFileExport(returnz);
-       }
-
-       static void Import(CGameDialog &self, int value) {
-               self.GameFileImport(value);
-       }
+    static void Export(const CGameDialog &self, const Callback<void(int)> &returnz)
+    {
+        self.GameFileExport(returnz);
+    }
+
+    static void Import(CGameDialog &self, int value)
+    {
+        self.GameFileImport(value);
+    }
 };
 
-void CGameDialog::CreateGlobalFrame( PreferencesPage& page ){
-       std::vector<const char*> games;
-       games.reserve( mGames.size() );
-       for ( std::list<CGameDescription *>::iterator i = mGames.begin(); i != mGames.end(); ++i )
-       {
-               games.push_back( ( *i )->getRequiredKeyValue( "name" ) );
-       }
-       page.appendCombo(
-               "Select the game",
-               StringArrayRange( &( *games.begin() ), &( *games.end() ) ),
-               make_property<CGameDialog_GameFile>(*this)
-               );
-       page.appendCheckBox( "Startup", "Show Global Preferences", m_bGamePrompt );
-}
-
-ui::Window CGameDialog::BuildDialog(){
-       auto frame = create_dialog_frame( "Game settings", ui::Shadow::ETCHED_IN );
-
-       auto vbox2 = create_dialog_vbox( 0, 4 );
-       frame.add(vbox2);
-
-       {
-               PreferencesPage preferencesPage( *this, vbox2 );
-               Global_constructPreferences( preferencesPage );
-               CreateGlobalFrame( preferencesPage );
-       }
-
-       return create_simple_modal_dialog_window( "Global Preferences", m_modal, frame );
-}
-
-void CGameDialog::ScanForGames(){
-       StringOutputStream strGamesPath( 256 );
-       strGamesPath << AppPath_get() << "games/";
-       const char *path = strGamesPath.c_str();
-
-       globalOutputStream() << "Scanning for game description files: " << path << '\n';
-
-       /*!
-          \todo FIXME LINUX:
-          do we put game description files below AppPath, or in ~/.radiant
-          i.e. read only or read/write?
-          my guess .. readonly cause it's an install
-          we will probably want to add ~/.radiant/<version>/games/ scanning on top of that for developers
-          (if that's really needed)
-        */
-
-       Directory_forEach(path, [&](const char *name) {
-               if (!extension_equal(path_get_extension(name), "game")) {
-                       return;
-               }
-               StringOutputStream strPath(256);
-               strPath << path << name;
-               globalOutputStream() << strPath.c_str() << '\n';
-
-               xmlDocPtr pDoc = xmlParseFile(strPath.c_str());
-               if (pDoc) {
-                       mGames.push_front(new CGameDescription(pDoc, name));
-                       xmlFreeDoc(pDoc);
-               } else {
-                       globalErrorStream() << "XML parser failed on '" << strPath.c_str() << "'\n";
-               }
-       });
-}
-
-CGameDescription* CGameDialog::GameDescriptionForComboItem(){
-       std::list<CGameDescription *>::iterator iGame;
-       int i = 0;
-       for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame,i++ )
-       {
-               if ( i == m_nComboSelect ) {
-                       return ( *iGame );
-               }
-       }
-       return 0; // not found
-}
-
-void CGameDialog::InitGlobalPrefPath(){
-       g_Preferences.m_global_rc_path = g_string_new( SettingsPath_get() );
-}
-
-void CGameDialog::Reset(){
-       if ( !g_Preferences.m_global_rc_path ) {
-               InitGlobalPrefPath();
-       }
-       StringOutputStream strGlobalPref( 256 );
-       strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref";
-       file_remove( strGlobalPref.c_str() );
-}
-
-void CGameDialog::Init(){
-       InitGlobalPrefPath();
-       LoadPrefs();
-       ScanForGames();
-       if ( mGames.empty() ) {
-               Error( "Didn't find any valid game file descriptions, aborting\n" );
-       }
-       else
-       {
-               std::list<CGameDescription *>::iterator iGame, iPrevGame;
-               for ( iGame = mGames.begin(), iPrevGame = mGames.end(); iGame != mGames.end(); iPrevGame = iGame, ++iGame )
-               {
-                       if ( iPrevGame != mGames.end() ) {
-                               if ( strcmp( ( *iGame )->getRequiredKeyValue( "name" ), ( *iPrevGame )->getRequiredKeyValue( "name" ) ) < 0 ) {
-                                       CGameDescription *h = *iGame;
-                                       *iGame = *iPrevGame;
-                                       *iPrevGame = h;
-                               }
-                       }
-               }
-       }
-
-       CGameDescription* currentGameDescription = 0;
-
-       if ( !m_bGamePrompt ) {
-               // search by .game name
-               std::list<CGameDescription *>::iterator iGame;
-               for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame )
-               {
-                       if ( ( *iGame )->mGameFile == m_sGameFile ) {
-                               currentGameDescription = ( *iGame );
-                               break;
-                       }
-               }
-       }
-       if ( m_bGamePrompt || !currentGameDescription ) {
-               Create();
-               DoGameDialog();
-               // use m_nComboSelect to identify the game to run as and set the globals
-               currentGameDescription = GameDescriptionForComboItem();
-               ASSERT_NOTNULL( currentGameDescription );
-       }
-       g_pGameDescription = currentGameDescription;
-
-       g_pGameDescription->Dump();
-}
-
-CGameDialog::~CGameDialog(){
-       // free all the game descriptions
-       std::list<CGameDescription *>::iterator iGame;
-       for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame )
-       {
-               delete ( *iGame );
-               *iGame = 0;
-       }
-       if ( GetWidget() ) {
-               Destroy();
-       }
-}
-
-inline const char* GameDescription_getIdentifier( const CGameDescription& gameDescription ){
-       const char* identifier = gameDescription.getKeyValue( "index" );
-       if ( string_empty( identifier ) ) {
-               identifier = "1";
-       }
-       return identifier;
+void CGameDialog::CreateGlobalFrame(PreferencesPage &page)
+{
+    std::vector<const char *> games;
+    games.reserve(mGames.size());
+    for (std::list<CGameDescription *>::iterator i = mGames.begin(); i != mGames.end(); ++i) {
+        games.push_back((*i)->getRequiredKeyValue("name"));
+    }
+    page.appendCombo(
+            "Select the game",
+            StringArrayRange(&(*games.begin()), &(*games.end())),
+            make_property<CGameDialog_GameFile>(*this)
+    );
+    page.appendCheckBox("Startup", "Show Global Preferences", m_bGamePrompt);
+}
+
+ui::Window CGameDialog::BuildDialog()
+{
+    auto frame = create_dialog_frame("Game settings", ui::Shadow::ETCHED_IN);
+
+    auto vbox2 = create_dialog_vbox(0, 4);
+    frame.add(vbox2);
+
+    {
+        PreferencesPage preferencesPage(*this, vbox2);
+        Global_constructPreferences(preferencesPage);
+        CreateGlobalFrame(preferencesPage);
+    }
+
+    return create_simple_modal_dialog_window("Global Preferences", m_modal, frame);
+}
+
+void CGameDialog::ScanForGames()
+{
+    StringOutputStream strGamesPath(256);
+    strGamesPath << AppPath_get() << "games/";
+    const char *path = strGamesPath.c_str();
+
+    globalOutputStream() << "Scanning for game description files: " << path << '\n';
+
+    /*!
+       \todo FIXME LINUX:
+       do we put game description files below AppPath, or in ~/.radiant
+       i.e. read only or read/write?
+       my guess .. readonly cause it's an install
+       we will probably want to add ~/.radiant/<version>/games/ scanning on top of that for developers
+       (if that's really needed)
+     */
+
+    Directory_forEach(path, [&](const char *name) {
+        if (!extension_equal(path_get_extension(name), "game")) {
+            return;
+        }
+        StringOutputStream strPath(256);
+        strPath << path << name;
+        globalOutputStream() << strPath.c_str() << '\n';
+
+        xmlDocPtr pDoc = xmlParseFile(strPath.c_str());
+        if (pDoc) {
+            mGames.push_front(new CGameDescription(pDoc, name));
+            xmlFreeDoc(pDoc);
+        } else {
+            globalErrorStream() << "XML parser failed on '" << strPath.c_str() << "'\n";
+        }
+    });
+}
+
+CGameDescription *CGameDialog::GameDescriptionForComboItem()
+{
+    std::list<CGameDescription *>::iterator iGame;
+    int i = 0;
+    for (iGame = mGames.begin(); iGame != mGames.end(); ++iGame, i++) {
+        if (i == m_nComboSelect) {
+            return (*iGame);
+        }
+    }
+    return 0; // not found
+}
+
+void CGameDialog::InitGlobalPrefPath()
+{
+    g_Preferences.m_global_rc_path = g_string_new(SettingsPath_get());
+}
+
+void CGameDialog::Reset()
+{
+    if (!g_Preferences.m_global_rc_path) {
+        InitGlobalPrefPath();
+    }
+    StringOutputStream strGlobalPref(256);
+    strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref";
+    file_remove(strGlobalPref.c_str());
+}
+
+void CGameDialog::Init()
+{
+    InitGlobalPrefPath();
+    LoadPrefs();
+    ScanForGames();
+    if (mGames.empty()) {
+        Error("Didn't find any valid game file descriptions, aborting\n");
+    } else {
+        std::list<CGameDescription *>::iterator iGame, iPrevGame;
+        for (iGame = mGames.begin(), iPrevGame = mGames.end(); iGame != mGames.end(); iPrevGame = iGame, ++iGame) {
+            if (iPrevGame != mGames.end()) {
+                if (strcmp((*iGame)->getRequiredKeyValue("name"), (*iPrevGame)->getRequiredKeyValue("name")) < 0) {
+                    CGameDescription *h = *iGame;
+                    *iGame = *iPrevGame;
+                    *iPrevGame = h;
+                }
+            }
+        }
+    }
+
+    CGameDescription *currentGameDescription = 0;
+
+    if (!m_bGamePrompt) {
+        // search by .game name
+        std::list<CGameDescription *>::iterator iGame;
+        for (iGame = mGames.begin(); iGame != mGames.end(); ++iGame) {
+            if ((*iGame)->mGameFile == m_sGameFile) {
+                currentGameDescription = (*iGame);
+                break;
+            }
+        }
+    }
+    if (m_bGamePrompt || !currentGameDescription) {
+        Create();
+        DoGameDialog();
+        // use m_nComboSelect to identify the game to run as and set the globals
+        currentGameDescription = GameDescriptionForComboItem();
+        ASSERT_NOTNULL(currentGameDescription);
+    }
+    g_pGameDescription = currentGameDescription;
+
+    g_pGameDescription->Dump();
+}
+
+CGameDialog::~CGameDialog()
+{
+    // free all the game descriptions
+    std::list<CGameDescription *>::iterator iGame;
+    for (iGame = mGames.begin(); iGame != mGames.end(); ++iGame) {
+        delete (*iGame);
+        *iGame = 0;
+    }
+    if (GetWidget()) {
+        Destroy();
+    }
+}
+
+inline const char *GameDescription_getIdentifier(const CGameDescription &gameDescription)
+{
+    const char *identifier = gameDescription.getKeyValue("index");
+    if (string_empty(identifier)) {
+        identifier = "1";
+    }
+    return identifier;
 }
 
 
@@ -473,18 +493,19 @@ CGameDialog g_GamesDialog;
 // =============================================================================
 // Widget callbacks for PrefsDlg
 
-static void OnButtonClean( ui::Widget widget, gpointer data ){
-       // make sure this is what the user wants
-       if ( ui::alert( g_Preferences.GetWidget(), "This will close Radiant and clean the corresponding registry entries.\n"
-                                                                                                                                 "Next time you start Radiant it will be good as new. Do you wish to continue?",
-                                                "Reset Registry", ui::alert_type::YESNO, ui::alert_icon::Asterisk ) == ui::alert_response::YES ) {
-               PrefsDlg *dlg = (PrefsDlg*)data;
-               dlg->EndModal( eIDCANCEL );
+static void OnButtonClean(ui::Widget widget, gpointer data)
+{
+    // make sure this is what the user wants
+    if (ui::alert(g_Preferences.GetWidget(), "This will close Radiant and clean the corresponding registry entries.\n"
+                          "Next time you start Radiant it will be good as new. Do you wish to continue?",
+                  "Reset Registry", ui::alert_type::YESNO, ui::alert_icon::Asterisk) == ui::alert_response::YES) {
+        PrefsDlg *dlg = (PrefsDlg *) data;
+        dlg->EndModal(eIDCANCEL);
 
-               g_preferences_globals.disable_ini = true;
-               Preferences_Reset();
-               gtk_main_quit();
-       }
+        g_preferences_globals.disable_ini = true;
+        Preferences_Reset();
+        gtk_main_quit();
+    }
 }
 
 // =============================================================================
@@ -505,319 +526,353 @@ static void OnButtonClean( ui::Widget widget, gpointer data ){
 
 const char *PREFS_LOCAL_FILENAME = "local.pref";
 
-void PrefsDlg::Init(){
-       // m_global_rc_path has been set above
-       // m_rc_path is for game specific preferences
-       // takes the form: global-pref-path/gamename/prefs-file
+void PrefsDlg::Init()
+{
+    // m_global_rc_path has been set above
+    // m_rc_path is for game specific preferences
+    // takes the form: global-pref-path/gamename/prefs-file
 
-       // this is common to win32 and Linux init now
-       m_rc_path = g_string_new( m_global_rc_path->str );
+    // this is common to win32 and Linux init now
+    m_rc_path = g_string_new(m_global_rc_path->str);
 
-       // game sub-dir
-       g_string_append( m_rc_path, g_pGameDescription->mGameFile.c_str() );
-       g_string_append( m_rc_path, "/" );
-       Q_mkdir( m_rc_path->str );
+    // game sub-dir
+    g_string_append(m_rc_path, g_pGameDescription->mGameFile.c_str());
+    g_string_append(m_rc_path, "/");
+    Q_mkdir(m_rc_path->str);
 
-       // then the ini file
-       m_inipath = g_string_new( m_rc_path->str );
-       g_string_append( m_inipath, PREFS_LOCAL_FILENAME );
+    // then the ini file
+    m_inipath = g_string_new(m_rc_path->str);
+    g_string_append(m_inipath, PREFS_LOCAL_FILENAME);
 }
 
-void notebook_set_page( ui::Widget notebook, ui::Widget page ){
-       int pagenum = gtk_notebook_page_num( GTK_NOTEBOOK( notebook ), page );
-       if ( gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) != pagenum ) {
-               gtk_notebook_set_current_page( GTK_NOTEBOOK( notebook ), pagenum );
-       }
+void notebook_set_page(ui::Widget notebook, ui::Widget page)
+{
+    int pagenum = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), page);
+    if (gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)) != pagenum) {
+        gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), pagenum);
+    }
 }
 
-void PrefsDlg::showPrefPage( ui::Widget prefpage ){
-       notebook_set_page( m_notebook, prefpage );
-       return;
+void PrefsDlg::showPrefPage(ui::Widget prefpage)
+{
+    notebook_set_page(m_notebook, prefpage);
+    return;
 }
 
-static void treeSelection( ui::TreeSelection selection, gpointer data ){
-       PrefsDlg *dlg = (PrefsDlg*)data;
+static void treeSelection(ui::TreeSelection selection, gpointer data)
+{
+    PrefsDlg *dlg = (PrefsDlg *) data;
 
-       GtkTreeModel* model;
-       GtkTreeIter selected;
-       if ( gtk_tree_selection_get_selected( selection, &model, &selected ) ) {
-               ui::Widget prefpage{ui::null};
-               gtk_tree_model_get( model, &selected, 1, (gpointer*)&prefpage, -1 );
-               dlg->showPrefPage( prefpage );
-       }
+    GtkTreeModel *model;
+    GtkTreeIter selected;
+    if (gtk_tree_selection_get_selected(selection, &model, &selected)) {
+        ui::Widget prefpage{ui::null};
+        gtk_tree_model_get(model, &selected, 1, (gpointer *) &prefpage, -1);
+        dlg->showPrefPage(prefpage);
+    }
 }
 
 typedef std::list<PreferenceGroupCallback> PreferenceGroupCallbacks;
 
-inline void PreferenceGroupCallbacks_constructGroup( const PreferenceGroupCallbacks& callbacks, PreferenceGroup& group ){
-       for ( PreferenceGroupCallbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i )
-       {
-               ( *i )( group );
-       }
+inline void PreferenceGroupCallbacks_constructGroup(const PreferenceGroupCallbacks &callbacks, PreferenceGroup &group)
+{
+    for (PreferenceGroupCallbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i) {
+        (*i)(group);
+    }
 }
 
 
-inline void PreferenceGroupCallbacks_pushBack( PreferenceGroupCallbacks& callbacks, const PreferenceGroupCallback& callback ){
-       callbacks.push_back( callback );
+inline void
+PreferenceGroupCallbacks_pushBack(PreferenceGroupCallbacks &callbacks, const PreferenceGroupCallback &callback)
+{
+    callbacks.push_back(callback);
 }
 
 typedef std::list<PreferencesPageCallback> PreferencesPageCallbacks;
 
-inline void PreferencesPageCallbacks_constructPage( const PreferencesPageCallbacks& callbacks, PreferencesPage& page ){
-       for ( PreferencesPageCallbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i )
-       {
-               ( *i )( page );
-       }
+inline void PreferencesPageCallbacks_constructPage(const PreferencesPageCallbacks &callbacks, PreferencesPage &page)
+{
+    for (PreferencesPageCallbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i) {
+        (*i)(page);
+    }
 }
 
-inline void PreferencesPageCallbacks_pushBack( PreferencesPageCallbacks& callbacks, const PreferencesPageCallback& callback ){
-       callbacks.push_back( callback );
+inline void
+PreferencesPageCallbacks_pushBack(PreferencesPageCallbacks &callbacks, const PreferencesPageCallback &callback)
+{
+    callbacks.push_back(callback);
 }
 
 PreferencesPageCallbacks g_interfacePreferences;
-void PreferencesDialog_addInterfacePreferences( const PreferencesPageCallback& callback ){
-       PreferencesPageCallbacks_pushBack( g_interfacePreferences, callback );
+
+void PreferencesDialog_addInterfacePreferences(const PreferencesPageCallback &callback)
+{
+    PreferencesPageCallbacks_pushBack(g_interfacePreferences, callback);
 }
+
 PreferenceGroupCallbacks g_interfaceCallbacks;
-void PreferencesDialog_addInterfacePage( const PreferenceGroupCallback& callback ){
-       PreferenceGroupCallbacks_pushBack( g_interfaceCallbacks, callback );
+
+void PreferencesDialog_addInterfacePage(const PreferenceGroupCallback &callback)
+{
+    PreferenceGroupCallbacks_pushBack(g_interfaceCallbacks, callback);
 }
 
 PreferencesPageCallbacks g_displayPreferences;
-void PreferencesDialog_addDisplayPreferences( const PreferencesPageCallback& callback ){
-       PreferencesPageCallbacks_pushBack( g_displayPreferences, callback );
+
+void PreferencesDialog_addDisplayPreferences(const PreferencesPageCallback &callback)
+{
+    PreferencesPageCallbacks_pushBack(g_displayPreferences, callback);
 }
+
 PreferenceGroupCallbacks g_displayCallbacks;
-void PreferencesDialog_addDisplayPage( const PreferenceGroupCallback& callback ){
-       PreferenceGroupCallbacks_pushBack( g_displayCallbacks, callback );
+
+void PreferencesDialog_addDisplayPage(const PreferenceGroupCallback &callback)
+{
+    PreferenceGroupCallbacks_pushBack(g_displayCallbacks, callback);
 }
 
 PreferencesPageCallbacks g_settingsPreferences;
-void PreferencesDialog_addSettingsPreferences( const PreferencesPageCallback& callback ){
-       PreferencesPageCallbacks_pushBack( g_settingsPreferences, callback );
+
+void PreferencesDialog_addSettingsPreferences(const PreferencesPageCallback &callback)
+{
+    PreferencesPageCallbacks_pushBack(g_settingsPreferences, callback);
 }
+
 PreferenceGroupCallbacks g_settingsCallbacks;
-void PreferencesDialog_addSettingsPage( const PreferenceGroupCallback& callback ){
-       PreferenceGroupCallbacks_pushBack( g_settingsCallbacks, callback );
+
+void PreferencesDialog_addSettingsPage(const PreferenceGroupCallback &callback)
+{
+    PreferenceGroupCallbacks_pushBack(g_settingsCallbacks, callback);
 }
 
-void Widget_updateDependency( ui::Widget self, ui::Widget toggleButton ){
-       gtk_widget_set_sensitive( self, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( toggleButton ) ) && gtk_widget_is_sensitive( toggleButton ) );
+void Widget_updateDependency(ui::Widget self, ui::Widget toggleButton)
+{
+    gtk_widget_set_sensitive(self, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggleButton)) &&
+                                   gtk_widget_is_sensitive(toggleButton));
 }
 
-void ToggleButton_toggled_Widget_updateDependency( ui::Widget toggleButton, ui::Widget self ){
-       Widget_updateDependency( self, toggleButton );
+void ToggleButton_toggled_Widget_updateDependency(ui::Widget toggleButton, ui::Widget self)
+{
+    Widget_updateDependency(self, toggleButton);
 }
 
-void ToggleButton_state_changed_Widget_updateDependency( ui::Widget toggleButton, GtkStateType state, ui::Widget self ){
-       if ( state == GTK_STATE_INSENSITIVE ) {
-               Widget_updateDependency( self, toggleButton );
-       }
+void ToggleButton_state_changed_Widget_updateDependency(ui::Widget toggleButton, GtkStateType state, ui::Widget self)
+{
+    if (state == GTK_STATE_INSENSITIVE) {
+        Widget_updateDependency(self, toggleButton);
+    }
 }
 
-void Widget_connectToggleDependency( ui::Widget self, ui::Widget toggleButton ){
-       toggleButton.connect( "state_changed", G_CALLBACK( ToggleButton_state_changed_Widget_updateDependency ), self );
-       toggleButton.connect( "toggled", G_CALLBACK( ToggleButton_toggled_Widget_updateDependency ), self );
-       Widget_updateDependency( self, toggleButton );
+void Widget_connectToggleDependency(ui::Widget self, ui::Widget toggleButton)
+{
+    toggleButton.connect("state_changed", G_CALLBACK(ToggleButton_state_changed_Widget_updateDependency), self);
+    toggleButton.connect("toggled", G_CALLBACK(ToggleButton_toggled_Widget_updateDependency), self);
+    Widget_updateDependency(self, toggleButton);
 }
 
 
-inline ui::VBox getVBox( ui::Bin page ){
-       return ui::VBox::from(gtk_bin_get_child(page));
+inline ui::VBox getVBox(ui::Bin page)
+{
+    return ui::VBox::from(gtk_bin_get_child(page));
 }
 
-GtkTreeIter PreferenceTree_appendPage( ui::TreeStore store, GtkTreeIter* parent, const char* name, ui::Widget page ){
-       GtkTreeIter group;
-       gtk_tree_store_append( store, &group, parent );
-       gtk_tree_store_set( store, &group, 0, name, 1, page, -1 );
-       return group;
+GtkTreeIter PreferenceTree_appendPage(ui::TreeStore store, GtkTreeIter *parent, const char *name, ui::Widget page)
+{
+    GtkTreeIter group;
+    gtk_tree_store_append(store, &group, parent);
+    gtk_tree_store_set(store, &group, 0, name, 1, page, -1);
+    return group;
 }
 
-ui::Bin PreferencePages_addPage( ui::Widget notebook, const char* name ){
-       ui::Widget preflabel = ui::Label( name );
-       preflabel.show();
+ui::Bin PreferencePages_addPage(ui::Widget notebook, const char *name)
+{
+    ui::Widget preflabel = ui::Label(name);
+    preflabel.show();
 
-       auto pageframe = ui::Frame( name );
-       gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 4 );
-       pageframe.show();
+    auto pageframe = ui::Frame(name);
+    gtk_container_set_border_width(GTK_CONTAINER(pageframe), 4);
+    pageframe.show();
 
-       ui::Widget vbox = ui::VBox( FALSE, 4 );
-       vbox.show();
-       gtk_container_set_border_width( GTK_CONTAINER( vbox ), 4 );
-       pageframe.add(vbox);
+    ui::Widget vbox = ui::VBox(FALSE, 4);
+    vbox.show();
+    gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
+    pageframe.add(vbox);
 
-       // Add the page to the notebook
-       gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel );
+    // Add the page to the notebook
+    gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
 
-       return pageframe;
+    return pageframe;
 }
 
-class PreferenceTreeGroup : public PreferenceGroup
-{
-Dialog& m_dialog;
-ui::Widget m_notebook;
-ui::TreeStore m_store;
-GtkTreeIter m_group;
+class PreferenceTreeGroup : public PreferenceGroup {
+    Dialog &m_dialog;
+    ui::Widget m_notebook;
+    ui::TreeStore m_store;
+    GtkTreeIter m_group;
 public:
-PreferenceTreeGroup( Dialog& dialog, ui::Widget notebook, ui::TreeStore store, GtkTreeIter group ) :
-       m_dialog( dialog ),
-       m_notebook( notebook ),
-       m_store( store ),
-       m_group( group ){
-}
-PreferencesPage createPage( const char* treeName, const char* frameName ){
-       auto page = PreferencePages_addPage( m_notebook, frameName );
-       PreferenceTree_appendPage( m_store, &m_group, treeName, page );
-       return PreferencesPage( m_dialog, getVBox( page ) );
-}
+    PreferenceTreeGroup(Dialog &dialog, ui::Widget notebook, ui::TreeStore store, GtkTreeIter group) :
+            m_dialog(dialog),
+            m_notebook(notebook),
+            m_store(store),
+            m_group(group)
+    {
+    }
+
+    PreferencesPage createPage(const char *treeName, const char *frameName)
+    {
+        auto page = PreferencePages_addPage(m_notebook, frameName);
+        PreferenceTree_appendPage(m_store, &m_group, treeName, page);
+        return PreferencesPage(m_dialog, getVBox(page));
+    }
 };
 
-ui::Window PrefsDlg::BuildDialog(){
-       PreferencesDialog_addInterfacePreferences( makeCallbackF(Interface_constructPreferences) );
-       Mouse_registerPreferencesPage();
-
-       ui::Window dialog = ui::Window(create_floating_window( "NetRadiant Preferences", m_parent ));
-
-       {
-               auto mainvbox = ui::VBox( FALSE, 5 );
-               dialog.add(mainvbox);
-               gtk_container_set_border_width( GTK_CONTAINER( mainvbox ), 5 );
-               mainvbox.show();
-
-               {
-                       auto hbox = ui::HBox( FALSE, 5 );
-                       hbox.show();
-                       mainvbox.pack_end(hbox, FALSE, TRUE, 0);
-
-                       {
-                               auto button = create_dialog_button( "OK", G_CALLBACK( dialog_button_ok ), &m_modal );
-                               hbox.pack_end(button, FALSE, FALSE, 0);
-                       }
-                       {
-                               auto button = create_dialog_button( "Cancel", G_CALLBACK( dialog_button_cancel ), &m_modal );
-                               hbox.pack_end(button, FALSE, FALSE, 0);
-                       }
-                       {
-                               auto button = create_dialog_button( "Clean", G_CALLBACK( OnButtonClean ), this );
-                               hbox.pack_end(button, FALSE, FALSE, 0);
-                       }
-               }
-
-               {
-                       auto hbox = ui::HBox( FALSE, 5 );
-                       mainvbox.pack_start( hbox, TRUE, TRUE, 0 );
-                       hbox.show();
-
-                       {
-                               auto sc_win = ui::ScrolledWindow(ui::New);
-                               gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( sc_win ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );
-                               hbox.pack_start( sc_win, FALSE, FALSE, 0 );
-                               sc_win.show();
-                               gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( sc_win ), GTK_SHADOW_IN );
-
-                               // prefs pages notebook
-                               m_notebook = ui::Widget::from(gtk_notebook_new());
-                               // hide the notebook tabs since its not supposed to look like a notebook
-                               gtk_notebook_set_show_tabs( GTK_NOTEBOOK( m_notebook ), FALSE );
-                               hbox.pack_start( m_notebook, TRUE, TRUE, 0 );
-                               m_notebook.show();
-
-
-                               {
-                                       auto store = ui::TreeStore::from(gtk_tree_store_new( 2, G_TYPE_STRING, G_TYPE_POINTER ));
-
-                                       auto view = ui::TreeView(ui::TreeModel::from(store._handle));
-                                       gtk_tree_view_set_headers_visible(view, FALSE );
-
-                                       {
-                                               auto renderer = ui::CellRendererText(ui::New);
-                        auto column = ui::TreeViewColumn( "Preferences", renderer, {{"text", 0}} );
-                                               gtk_tree_view_append_column(view, column );
-                                       }
-
-                                       {
-                                               auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view));
-                                               selection.connect( "changed", G_CALLBACK( treeSelection ), this );
-                                       }
-
-                                       view.show();
-
-                                       sc_win.add(view);
-
-                                       {
-                                               /********************************************************************/
-                                               /* Add preference tree options                                      */
-                                               /********************************************************************/
-                                               // Front page...
-                                               //GtkWidget* front =
-                                               PreferencePages_addPage( m_notebook, "Front Page" );
-
-                                               {
-                                                       auto global = PreferencePages_addPage( m_notebook, "Global Preferences" );
-                                                       {
-                                                               PreferencesPage preferencesPage( *this, getVBox( global ) );
-                                                               Global_constructPreferences( preferencesPage );
-                                                       }
-                            auto group = PreferenceTree_appendPage( store, 0, "Global", global );
-                                                       {
-                                                               auto game = PreferencePages_addPage( m_notebook, "Game" );
-                                                               PreferencesPage preferencesPage( *this, getVBox( game ) );
-                                                               g_GamesDialog.CreateGlobalFrame( preferencesPage );
-
-                                                               PreferenceTree_appendPage( store, &group, "Game", game );
-                                                       }
-                                               }
-
-                                               {
-                                                       auto interfacePage = PreferencePages_addPage( m_notebook, "Interface Preferences" );
-                                                       {
-                                                               PreferencesPage preferencesPage( *this, getVBox( interfacePage ) );
-                                                               PreferencesPageCallbacks_constructPage( g_interfacePreferences, preferencesPage );
-                                                       }
-
-                            auto group = PreferenceTree_appendPage( store, 0, "Interface", interfacePage );
-                                                       PreferenceTreeGroup preferenceGroup( *this, m_notebook, store, group );
-
-                                                       PreferenceGroupCallbacks_constructGroup( g_interfaceCallbacks, preferenceGroup );
-                                               }
-
-                                               {
-                                                       auto display = PreferencePages_addPage( m_notebook, "Display Preferences" );
-                                                       {
-                                                               PreferencesPage preferencesPage( *this, getVBox( display ) );
-                                                               PreferencesPageCallbacks_constructPage( g_displayPreferences, preferencesPage );
-                                                       }
-                            auto group = PreferenceTree_appendPage( store, 0, "Display", display );
-                                                       PreferenceTreeGroup preferenceGroup( *this, m_notebook, store, group );
-
-                                                       PreferenceGroupCallbacks_constructGroup( g_displayCallbacks, preferenceGroup );
-                                               }
-
-                                               {
-                                                       auto settings = PreferencePages_addPage( m_notebook, "General Settings" );
-                                                       {
-                                                               PreferencesPage preferencesPage( *this, getVBox( settings ) );
-                                                               PreferencesPageCallbacks_constructPage( g_settingsPreferences, preferencesPage );
-                                                       }
-
-                            auto group = PreferenceTree_appendPage( store, 0, "Settings", settings );
-                                                       PreferenceTreeGroup preferenceGroup( *this, m_notebook, store, group );
-
-                                                       PreferenceGroupCallbacks_constructGroup( g_settingsCallbacks, preferenceGroup );
-                                               }
-                                       }
-
-                                       gtk_tree_view_expand_all(view );
-
-                                       g_object_unref( G_OBJECT( store ) );
-                               }
-                       }
-               }
-       }
-
-       gtk_notebook_set_current_page( GTK_NOTEBOOK( m_notebook ), 0 );
-
-       return dialog;
+ui::Window PrefsDlg::BuildDialog()
+{
+    PreferencesDialog_addInterfacePreferences(makeCallbackF(Interface_constructPreferences));
+    Mouse_registerPreferencesPage();
+
+    ui::Window dialog = ui::Window(create_floating_window("NetRadiant Preferences", m_parent));
+
+    {
+        auto mainvbox = ui::VBox(FALSE, 5);
+        dialog.add(mainvbox);
+        gtk_container_set_border_width(GTK_CONTAINER(mainvbox), 5);
+        mainvbox.show();
+
+        {
+            auto hbox = ui::HBox(FALSE, 5);
+            hbox.show();
+            mainvbox.pack_end(hbox, FALSE, TRUE, 0);
+
+            {
+                auto button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &m_modal);
+                hbox.pack_end(button, FALSE, FALSE, 0);
+            }
+            {
+                auto button = create_dialog_button("Cancel", G_CALLBACK(dialog_button_cancel), &m_modal);
+                hbox.pack_end(button, FALSE, FALSE, 0);
+            }
+            {
+                auto button = create_dialog_button("Clean", G_CALLBACK(OnButtonClean), this);
+                hbox.pack_end(button, FALSE, FALSE, 0);
+            }
+        }
+
+        {
+            auto hbox = ui::HBox(FALSE, 5);
+            mainvbox.pack_start(hbox, TRUE, TRUE, 0);
+            hbox.show();
+
+            {
+                auto sc_win = ui::ScrolledWindow(ui::New);
+                gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sc_win), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+                hbox.pack_start(sc_win, FALSE, FALSE, 0);
+                sc_win.show();
+                gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sc_win), GTK_SHADOW_IN);
+
+                // prefs pages notebook
+                m_notebook = ui::Widget::from(gtk_notebook_new());
+                // hide the notebook tabs since its not supposed to look like a notebook
+                gtk_notebook_set_show_tabs(GTK_NOTEBOOK(m_notebook), FALSE);
+                hbox.pack_start(m_notebook, TRUE, TRUE, 0);
+                m_notebook.show();
+
+
+                {
+                    auto store = ui::TreeStore::from(gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER));
+
+                    auto view = ui::TreeView(ui::TreeModel::from(store._handle));
+                    gtk_tree_view_set_headers_visible(view, FALSE);
+
+                    {
+                        auto renderer = ui::CellRendererText(ui::New);
+                        auto column = ui::TreeViewColumn("Preferences", renderer, {{"text", 0}});
+                        gtk_tree_view_append_column(view, column);
+                    }
+
+                    {
+                        auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view));
+                        selection.connect("changed", G_CALLBACK(treeSelection), this);
+                    }
+
+                    view.show();
+
+                    sc_win.add(view);
+
+                    {
+                        /********************************************************************/
+                        /* Add preference tree options                                      */
+                        /********************************************************************/
+                        // Front page...
+                        //GtkWidget* front =
+                        PreferencePages_addPage(m_notebook, "Front Page");
+
+                        {
+                            auto global = PreferencePages_addPage(m_notebook, "Global Preferences");
+                            {
+                                PreferencesPage preferencesPage(*this, getVBox(global));
+                                Global_constructPreferences(preferencesPage);
+                            }
+                            auto group = PreferenceTree_appendPage(store, 0, "Global", global);
+                            {
+                                auto game = PreferencePages_addPage(m_notebook, "Game");
+                                PreferencesPage preferencesPage(*this, getVBox(game));
+                                g_GamesDialog.CreateGlobalFrame(preferencesPage);
+
+                                PreferenceTree_appendPage(store, &group, "Game", game);
+                            }
+                        }
+
+                        {
+                            auto interfacePage = PreferencePages_addPage(m_notebook, "Interface Preferences");
+                            {
+                                PreferencesPage preferencesPage(*this, getVBox(interfacePage));
+                                PreferencesPageCallbacks_constructPage(g_interfacePreferences, preferencesPage);
+                            }
+
+                            auto group = PreferenceTree_appendPage(store, 0, "Interface", interfacePage);
+                            PreferenceTreeGroup preferenceGroup(*this, m_notebook, store, group);
+
+                            PreferenceGroupCallbacks_constructGroup(g_interfaceCallbacks, preferenceGroup);
+                        }
+
+                        {
+                            auto display = PreferencePages_addPage(m_notebook, "Display Preferences");
+                            {
+                                PreferencesPage preferencesPage(*this, getVBox(display));
+                                PreferencesPageCallbacks_constructPage(g_displayPreferences, preferencesPage);
+                            }
+                            auto group = PreferenceTree_appendPage(store, 0, "Display", display);
+                            PreferenceTreeGroup preferenceGroup(*this, m_notebook, store, group);
+
+                            PreferenceGroupCallbacks_constructGroup(g_displayCallbacks, preferenceGroup);
+                        }
+
+                        {
+                            auto settings = PreferencePages_addPage(m_notebook, "General Settings");
+                            {
+                                PreferencesPage preferencesPage(*this, getVBox(settings));
+                                PreferencesPageCallbacks_constructPage(g_settingsPreferences, preferencesPage);
+                            }
+
+                            auto group = PreferenceTree_appendPage(store, 0, "Settings", settings);
+                            PreferenceTreeGroup preferenceGroup(*this, m_notebook, store, group);
+
+                            PreferenceGroupCallbacks_constructGroup(g_settingsCallbacks, preferenceGroup);
+                        }
+                    }
+
+                    gtk_tree_view_expand_all(view);
+
+                    g_object_unref(G_OBJECT(store));
+                }
+            }
+        }
+    }
+
+    gtk_notebook_set_current_page(GTK_NOTEBOOK(m_notebook), 0);
+
+    return dialog;
 }
 
 preferences_globals_t g_preferences_globals;
@@ -825,34 +880,41 @@ preferences_globals_t g_preferences_globals;
 PrefsDlg g_Preferences;               // global prefs instance
 
 
-void PreferencesDialog_constructWindow( ui::Window main_window ){
-       g_Preferences.m_parent = main_window;
-       g_Preferences.Create();
+void PreferencesDialog_constructWindow(ui::Window main_window)
+{
+    g_Preferences.m_parent = main_window;
+    g_Preferences.Create();
 }
-void PreferencesDialog_destroyWindow(){
-       g_Preferences.Destroy();
+
+void PreferencesDialog_destroyWindow()
+{
+    g_Preferences.Destroy();
 }
 
 
 PreferenceDictionary g_preferences;
 
-PreferenceSystem& GetPreferenceSystem(){
-       return g_preferences;
+PreferenceSystem &GetPreferenceSystem()
+{
+    return g_preferences;
 }
 
-class PreferenceSystemAPI
-{
-PreferenceSystem* m_preferencesystem;
+class PreferenceSystemAPI {
+    PreferenceSystem *m_preferencesystem;
 public:
-typedef PreferenceSystem Type;
-STRING_CONSTANT( Name, "*" );
+    typedef PreferenceSystem Type;
 
-PreferenceSystemAPI(){
-       m_preferencesystem = &GetPreferenceSystem();
-}
-PreferenceSystem* getTable(){
-       return m_preferencesystem;
-}
+    STRING_CONSTANT(Name, "*");
+
+    PreferenceSystemAPI()
+    {
+        m_preferencesystem = &GetPreferenceSystem();
+    }
+
+    PreferenceSystem *getTable()
+    {
+        return m_preferencesystem;
+    }
 };
 
 #include "modulesystem/singletonmodule.h"
@@ -860,97 +922,109 @@ PreferenceSystem* getTable(){
 
 typedef SingletonModule<PreferenceSystemAPI> PreferenceSystemModule;
 typedef Static<PreferenceSystemModule> StaticPreferenceSystemModule;
-StaticRegisterModule staticRegisterPreferenceSystem( StaticPreferenceSystemModule::instance() );
+StaticRegisterModule staticRegisterPreferenceSystem(StaticPreferenceSystemModule::instance());
 
-void Preferences_Load(){
-       g_GamesDialog.LoadPrefs();
+void Preferences_Load()
+{
+    g_GamesDialog.LoadPrefs();
 
-       globalOutputStream() << "loading local preferences from " << g_Preferences.m_inipath->str << "\n";
+    globalOutputStream() << "loading local preferences from " << g_Preferences.m_inipath->str << "\n";
 
-       if ( !Preferences_Load( g_preferences, g_Preferences.m_inipath->str, g_GamesDialog.m_sGameFile.c_str() ) ) {
-               globalOutputStream() << "failed to load local preferences from " << g_Preferences.m_inipath->str << "\n";
-       }
+    if (!Preferences_Load(g_preferences, g_Preferences.m_inipath->str, g_GamesDialog.m_sGameFile.c_str())) {
+        globalOutputStream() << "failed to load local preferences from " << g_Preferences.m_inipath->str << "\n";
+    }
 }
 
-void Preferences_Save(){
-       if ( g_preferences_globals.disable_ini ) {
-               return;
-       }
+void Preferences_Save()
+{
+    if (g_preferences_globals.disable_ini) {
+        return;
+    }
 
-       g_GamesDialog.SavePrefs();
+    g_GamesDialog.SavePrefs();
 
-       globalOutputStream() << "saving local preferences to " << g_Preferences.m_inipath->str << "\n";
+    globalOutputStream() << "saving local preferences to " << g_Preferences.m_inipath->str << "\n";
 
-       if ( !Preferences_Save_Safe( g_preferences, g_Preferences.m_inipath->str ) ) {
-               globalOutputStream() << "failed to save local preferences to " << g_Preferences.m_inipath->str << "\n";
-       }
+    if (!Preferences_Save_Safe(g_preferences, g_Preferences.m_inipath->str)) {
+        globalOutputStream() << "failed to save local preferences to " << g_Preferences.m_inipath->str << "\n";
+    }
 }
 
-void Preferences_Reset(){
-       file_remove( g_Preferences.m_inipath->str );
+void Preferences_Reset()
+{
+    file_remove(g_Preferences.m_inipath->str);
 }
 
 
-void PrefsDlg::PostModal( EMessageBoxReturn code ){
-       if ( code == eIDOK ) {
-               Preferences_Save();
-               UpdateAllWindows();
-       }
+void PrefsDlg::PostModal(EMessageBoxReturn code)
+{
+    if (code == eIDOK) {
+        Preferences_Save();
+        UpdateAllWindows();
+    }
 }
 
-std::vector<const char*> g_restart_required;
+std::vector<const char *> g_restart_required;
 
-void PreferencesDialog_restartRequired( const char* staticName ){
-       g_restart_required.push_back( staticName );
+void PreferencesDialog_restartRequired(const char *staticName)
+{
+    g_restart_required.push_back(staticName);
 }
 
-void PreferencesDialog_showDialog(){
-       if ( ConfirmModified( "Edit Preferences" ) && g_Preferences.DoModal() == eIDOK ) {
-               if ( !g_restart_required.empty() ) {
-                       StringOutputStream message( 256 );
-                       message << "Preference changes require a restart:\n";
-                       for ( std::vector<const char*>::iterator i = g_restart_required.begin(); i != g_restart_required.end(); ++i )
-                       {
-                               message << ( *i ) << '\n';
-                       }
-                       ui::alert( MainFrame_getWindow(), message.c_str() );
-                       g_restart_required.clear();
-               }
-       }
+void PreferencesDialog_showDialog()
+{
+    if (ConfirmModified("Edit Preferences") && g_Preferences.DoModal() == eIDOK) {
+        if (!g_restart_required.empty()) {
+            StringOutputStream message(256);
+            message << "Preference changes require a restart:\n";
+            for (std::vector<const char *>::iterator i = g_restart_required.begin();
+                 i != g_restart_required.end(); ++i) {
+                message << (*i) << '\n';
+            }
+            ui::alert(MainFrame_getWindow(), message.c_str());
+            g_restart_required.clear();
+        }
+    }
 }
 
 struct GameName {
-       static void Export(const Callback<void(const char *)> &returnz) {
-               returnz(gamename_get());
-       }
-
-       static void Import(const char *value) {
-               gamename_set(value);
-       }
+    static void Export(const Callback<void(const char *)> &returnz)
+    {
+        returnz(gamename_get());
+    }
+
+    static void Import(const char *value)
+    {
+        gamename_set(value);
+    }
 };
 
 struct GameMode {
-       static void Export(const Callback<void(const char *)> &returnz) {
-               returnz(gamemode_get());
-       }
-
-       static void Import(const char *value) {
-               gamemode_set(value);
-       }
+    static void Export(const Callback<void(const char *)> &returnz)
+    {
+        returnz(gamemode_get());
+    }
+
+    static void Import(const char *value)
+    {
+        gamemode_set(value);
+    }
 };
 
-void RegisterPreferences( PreferenceSystem& preferences ){
+void RegisterPreferences(PreferenceSystem &preferences)
+{
 #if GDEF_OS_WINDOWS
-       preferences.registerPreference( "UseCustomShaderEditor", make_property_string( g_TextEditor_useWin32Editor ) );
+    preferences.registerPreference( "UseCustomShaderEditor", make_property_string( g_TextEditor_useWin32Editor ) );
 #else
-       preferences.registerPreference( "UseCustomShaderEditor", make_property_string( g_TextEditor_useCustomEditor ) );
-       preferences.registerPreference( "CustomShaderEditorCommand", make_property_string( g_TextEditor_editorCommand ) );
+    preferences.registerPreference("UseCustomShaderEditor", make_property_string(g_TextEditor_useCustomEditor));
+    preferences.registerPreference("CustomShaderEditorCommand", make_property_string(g_TextEditor_editorCommand));
 #endif
 
-       preferences.registerPreference( "GameName", make_property<GameName>() );
-       preferences.registerPreference( "GameMode", make_property<GameMode>() );
+    preferences.registerPreference("GameName", make_property<GameName>());
+    preferences.registerPreference("GameMode", make_property<GameMode>());
 }
 
-void Preferences_Init(){
-       RegisterPreferences( GetPreferenceSystem() );
+void Preferences_Init()
+{
+    RegisterPreferences(GetPreferenceSystem());
 }