X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=radiant%2Fpreferences.cpp;h=d4d0bcede678898290244863d14bba94f58e9c99;hp=61d4a6ee5399dd5465974a61c21636d29cf8fc3c;hb=5f6f1176338117eb3661c19e2e75461edaff8631;hpb=12b372f89ce109a4db9d510884fbe7d05af79870 diff --git a/radiant/preferences.cpp b/radiant/preferences.cpp index 61d4a6ee..d4d0bced 100644 --- a/radiant/preferences.cpp +++ b/radiant/preferences.cpp @@ -1,5 +1,5 @@ /* -Copyright (C) 1999-2006 Id Software, Inc. and contributors. +Copyright (C) 1999-2007 id Software, Inc. and contributors. For a list of contributors, see the accompanying CONTRIBUTORS file. This file is part of GtkRadiant. @@ -25,1038 +25,3449 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Leonardo Zide (leo@lokigames.com) // -#include "preferences.h" - -#include "debugging/debugging.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "generic/callback.h" -#include "math/vector.h" -#include "string/string.h" -#include "stream/stringstream.h" -#include "os/file.h" -#include "os/path.h" -#include "os/dir.h" -#include "gtkutil/filechooser.h" -#include "gtkutil/messagebox.h" -#include "cmdlib.h" - -#include "error.h" -#include "console.h" -#include "xywindow.h" -#include "mainframe.h" -#include "qe3.h" -#include "gtkdlgs.h" - - - -void Global_constructPreferences(PreferencesPage& page) -{ - page.appendCheckBox("Console", "Enable Logging", g_Console_enableLogging); -} +#include "stdafx.h" +#include +#include +#include +#if defined (__linux__) || defined (__APPLE__) +#include +#include +#include +#include +#include +#endif +#include "missing.h" +#include "gtkmisc.h" -void Interface_constructPreferences(PreferencesPage& page) -{ -#ifdef WIN32 - page.appendCheckBox("", "Native File-Chooser", g_FileChooser_nativeGUI); - page.appendCheckBox("", "Default Text Editor", g_TextEditor_useWin32Editor); -#else - { - GtkWidget* use_custom = page.appendCheckBox("Text Editor", "Custom", g_TextEditor_useCustomEditor); - GtkWidget* custom_editor = page.appendPathEntry("Text Editor Command", g_TextEditor_editorCommand, true); - Widget_connectToggleDependency(custom_editor, use_custom); - } +#ifdef _WIN32 +#include +#define X_OK 0 +#include #endif -} -void Mouse_constructPreferences(PreferencesPage& page) -{ +#define PREF_SECTION "Prefs" +#define INTERNAL_SECTION "Internals" +#define MOUSE_KEY "MouseButtons" +#define WINDOW_KEY "QE4StyleWindows" +#define LAYOUT_KEY "WindowLayout" +#define RUNQ2_KEY "RunQuake2Run" +#define TLOCK_KEY "TextureLock" +#define RLOCK_KEY "RotateLock" +#define LOADLAST_KEY "LoadLast" +#define LOADLASTMAP_KEY "LoadLastMap" +#define LASTPROJ_KEY "LastProject" +#define LASTPROJVER_KEY "LastProjectKey" +#define LASTMAP_KEY "LastMap" +#define FACE_KEY "NewFaceGrab" +#define BSP_KEY "InternalBSP" +#define RCLICK_KEY "NewRightClick" +#define VERTEX_KEY "NewVertex" +#define AUTOSAVE_KEY "Autosave" +#define AUTOSAVETIME_KEY "AutosaveMinutes" +#define PAK_KEY "UsePAK" +#define NEWAPPLY_KEY "ApplyDismissesSurface" +#define HACK_KEY "Gatewayescapehack" +#define TEXTURE_KEY "NewTextureWindowStuff" +#define TINYBRUSH_KEY "CleanTinyBrushes" +#define TINYSIZE_KEY "CleanTinyBrusheSize" +#define SNAPSHOT_KEY "Snapshots" +#define MOVESPEED_KEY "MoveSpeed" +#define ANGLESPEED_KEY "AngleSpeed" +#define SETGAME_KEY "UseSetGame" +#define CAMXYUPDATE_KEY "CamXYUpdate" +#define CAMDRAGMULTISELECT_KEY "CamDragMultiSelect" +#define CAMFREELOOK_KEY "CamFreeLook" +#define CAMINVERSEMOUSE_KEY "CamInverseMouse" +#define CAMDISCRETE_KEY "CamDiscrete" +#define LIGHTDRAW_KEY "NewLightStyle" +#define WHATGAME_KEY "WhichGame" +#define CUBICCLIP_KEY "CubicClipping" +#define CUBICSCALE_KEY "CubicScale" +#define ALTEDGE_KEY "ALTEdgeDrag" +#define FACECOLORS_KEY "FaceColors" +#define SNAPT_KEY "SnapT" +#define XZVIS_KEY "XZVIS" +#define YZVIS_KEY "YZVIS" +#define ZVIS_KEY "ZVIS" +#define SIZEPAINT_KEY "SizePainting" +#define DLLENTITIES_KEY "DLLEntities" +#define DETACHABLEMENUS_KEY "DetachableMenus" +#define PATCHTOOLBAR_KEY "PatchToolBar" +#define WIDETOOLBAR_KEY "WideToolBar" +#define PLUGINTOOLBAR_KEY "PluginToolBar" +#define NOCLAMP_KEY "NoClamp" +#define PREFAB_KEY "PrefabPath" +#define USERINI_KEY "UserINIPath" +#define ROTATION_KEY "Rotation" +#define BUGGYICD_KEY "BuggyICD" +#define CHASEMOUSE_KEY "ChaseMouse" +#define ENTITYSHOW_KEY "EntityShow" +#define TEXTURESCALE_KEY "TextureScale" +#define TEXTURESCROLLBAR_KEY "TextureScrollbar" +#define DISPLAYLISTS_KEY "UseDisplayLists" +#define ANTIALIASEDLINES_KEY "UseAntialiasedPointsAndLines" // Fishman - Add antialiazed points and lines support. 09/03/00 +#define NORMALIZECOLORS_KEY "NormalizeColors" +#define SHADERS_KEY "UseShaders" +#define SWITCHCLIP_KEY "SwitchClipKey" +#define SELWHOLEENTS_KEY "SelectWholeEntitiesKey" +#define TEXTURESUBSET_KEY "UseTextureSubsetLoading" +#define TEXTUREQUALITY_KEY "TextureQuality" +#define SHOWSHADERS_KEY "ShowShaders" +#define SHADERTEST_KEY "ShaderTest" +#define GLLIGHTING_KEY "UseGLLighting" +#define LOADSHADERS_KEY "LoadShaders" +#define NOSTIPPLE_KEY "NoStipple" +#define UNDOLEVELS_KEY "UndoLevels" +#define VERTEXMODE_KEY "VertexSplit" +#define ENGINEPATH_KEY "EnginePath" +#define ENGINE_KEY "Engine" +#define LOGCONSOLE_KEY "LogConsole" +#define SELECTCURVES_KEY "SelectCurves" +#define SELECTMODELS_KEY "SelectModels" +#define SHADERLISTONLY_KEY "ShowShaderlistOnly" +#define WATCHBSP_KEY "WatchBSP" +#define LEAKSTOP_KEY "LeakStop" +#define DOSLEEP_KEY "SleepMode" +#define SUBDIVISIONS_KEY "Subdivisions" +#define CLIPCAULK_KEY "ClipCaulk" +#define PATCHSHOWBOUNDS_KEY "PatchShowBounds" +#define NATIVEGUI_KEY "NativeGUI" +#define STARTONPRIMMON_KEY "StartOnPrimMon" +#define NOSYSMENUPOPUPS_KEY "NoSysMenuPopups" +#define SNAPTTOGRID_KEY "SnapTToGrid" +#define FLOATINGZ_KEY "FloatingZ" +#define TARGETFIX_KEY "TargetFix" +#define GLPOINTWORKAROUND_KEY "GlPointWorkaround" // Gef: Workaround for broken Kyro * gl driver 25-aug-2001 +#define WHEELINC_KEY "WheelMouseInc" +#define PATCHBBOXSEL_KEY "PatchBBoxSel" +#define LASTLIGHTINTENSITY_KEY "LastLightIntensity" +#define CUSTOMSHADEREDITOR_KEY "UseCustomShaderEditor" +#define CUSTOMSHADEREDITORCOMMAND_KEY "CustomShaderEditorCommand" +#define TEXTURECOMPRESSIONFORMAT_KEY "TextureCompressionFormat" +#define LIGHTRADIUS_KEY "LightRadiuses" +#define Q3MAP2TEX_KEY "Q3Map2Tex" +#define ATIHACK_KEY "ATIHack" + +// window stuff +#define ENTITYSPLIT1_KEY "EntitySplit1" +#define ENTITYSPLIT2_KEY "EntitySplit2" +#define POSITIONX_KEY "PositionX" +#define POSITIONY_KEY "PositionY" +#define ENTITYWND_KEY "EntityWnd" +#define MAPINFOWND_KEY "MapInfoDlg" +#define CAMWND_KEY "CamWnd" +#define ZWND_KEY "ZWnd" +#define XYWND_KEY "XYWnd" +#define XZWND_KEY "XZWnd" +#define YZWND_KEY "YZWnd" +#define PATCHWND_KEY "PatchWnd" +#define SURFACEWND_KEY "SurfaceWnd" +#define ENTITYINFOWND_KEY "EntityInfoDlg" +#define WIDTH_KEY "Width" +#define HEIGHT_KEY "Height" +#define ZWIDTH_KEY "ZWidth" +#define XYHEIGHT_KEY "XYHeight" +#define XYWIDTH_KEY "XYWidth" +#define CAMWIDTH_KEY "CamWidth" +#define CAMHEIGHT_KEY "CamHeight" +#define ZFLOATWIDTH_KEY "ZWidthFloating" +#define STATE_KEY "State" + +// menu stuff +#define COUNT_KEY "Count" +#define FILE_KEY "File" + +//saved info +#define SI_TEXMENU_KEY "SI_TexMenu" +#define SI_GAMMA_KEY "SI_Gamma" +#define SI_COLORS_KEY "SI_Colors" +#define SI_EXCLUDE_KEY "SI_Exclude" +#define SI_INCLUDE_KEY "SI_Include" +#define SI_SURFACE_TEXDEF_KEY "SI_SurfaceTexdef" +#define SI_PATCH_TEXDEF_KEY "SI_PatchTexdef" +#define SI_AXISCOLORS_KEY "SI_AxisColors" +#define SI_SHOWNAMES_KEY "SI_ShowNames" +#define SI_SHOWCOORDS_KEY "SI_ShowCoords" +#define SI_SHOWANGLES_KEY "SI_ShowAngles" +#define SI_SHOWOUTLINES_KEY "SI_ShowOutlines" +#define SI_SHOWAXIS_KEY "SI_ShowAxis" +#define SI_NOSELOUTLINES_KEY "SI_NoSelectedOutlines" +#define SI_OUTLINESTYLE_KEY "SI_OutLineStyle" + +//for texdefs +#define TD_SCALE1_KEY "_Scale1" +#define TD_SCALE2_KEY "_Scale2" +#define TD_SHIFT1_KEY "_Shift1" +#define TD_SHIFT2_KEY "_Shift2" +#define TD_ROTATE_KEY "_Rotate" + +#define MOUSE_DEF 1 +#define WINDOW_DEF 0 +#define RUNQ2_DEF 0 +#define WATCHBSP_DEF 1 +#define TLOCK_DEF 1 +#define LOADLAST_DEF 1 +#define RUN_DEF 0 +#define SUBDIVISIONS_DEF 4 + +void WindowPosition_Parse(window_position_t& m_value, const CString& value) +{ + if(sscanf(value.GetBuffer(), "%d %d %d %d", &m_value.x, &m_value.y, &m_value.w, &m_value.h) != 4) + m_value.x = m_value.y = m_value.w = m_value.h = -1; +} + +void WindowPosition_Write(const window_position_t& m_value, CString& value) +{ + char buffer[64]; + sprintf(buffer, "%d %d %d %d", m_value.x, m_value.y, m_value.w, m_value.h); + value = buffer; +} + + +CXMLPropertyBag::CXMLPropertyBag() { + mStrFilename = ""; + mpDoc = NULL; + mbEmpty = false; +} + +// generic preference functions + +void CXMLPropertyBag::PushAssignment(const char *name, PrefTypes_t type, void *pV) +{ + list::iterator iAssign; + for(iAssign=mPrefAssignments.begin(); iAssign!=mPrefAssignments.end(); iAssign++) { - const char* buttons[] = { "2 button", "3 button", }; - page.appendRadio("Mouse Type", g_glwindow_globals.m_nMouseType, STRING_ARRAY_RANGE(buttons)); + if ((*iAssign).mName == name) + { + // we have it already, check anyway + if (pV != (*iAssign).mVal) + { + Sys_FPrintf(SYS_ERR, "PushAssignment, '%s' has different mVal\n", name); + return; + } + } } - 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_registerPreferencesPage() -{ - PreferencesDialog_addInterfacePage(FreeCaller1()); + // ok, it's not in our list yet + mPrefAssignments.push_front(CPrefAssignment(name, type, pV)); } - -/*! -========================================================= -Games selection dialog -========================================================= -*/ - -#include - -inline const char* xmlAttr_getName(xmlAttrPtr attr) +xmlNodePtr CXMLPropertyBag::EpairForName(const char *name) { - return reinterpret_cast(attr->name); -} + xmlNodePtr ret = NULL; -inline const char* xmlAttr_getValue(xmlAttrPtr attr) -{ - return reinterpret_cast(attr->children->content); + xmlNodePtr pNode = mpDocNode->children; + while (pNode != NULL) + { + if(pNode->type == XML_ELEMENT_NODE) + { + xmlAttrPtr tmp_attr_ptr = xmlHasProp(pNode, (xmlChar *)"name"); + if (tmp_attr_ptr != NULL && !strcmp(name, (char *)tmp_attr_ptr->children->content)) + { + if ( ret ) { + Sys_FPrintf( SYS_WRN, "WARNING: dupe property in CXMLPropertyBag::EpairForName '%s'\n", name ); + } else { + ret = pNode; + } + } + } + pNode = pNode->next; + } + return ret; } -CGameDescription::CGameDescription(xmlDocPtr pDoc, const CopiedString& gameFile) +void CXMLPropertyBag::GetPref(const char *name, Str *pV, const char *V) { - // read the user-friendly game name - xmlNodePtr pNode = pDoc->children; - - while (strcmp((const char*)pNode->name, "game") && pNode != 0) + xmlNodePtr pNode = EpairForName( name ); + if ( pNode ) { - pNode=pNode->next; + if ( pNode->children && pNode->children->content ) { + *pV = pNode->children->content; + } else { + // means the pref exists, and that the value is "" + *pV = ""; + } } - if (!pNode) + else { - Error("Didn't find 'game' node in the game description file '%s'\n", pDoc->URL); + pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)V); + xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name); } + // push the pref assignment if needed + PushAssignment(name, PREF_STR, pV); +} - for(xmlAttrPtr attr = pNode->properties; attr != 0; attr = attr->next) +void CXMLPropertyBag::GetPref(const char *name, int *pV, int V) +{ + xmlNodePtr pNode; + if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content) { - m_gameDescription.insert(GameDescription::value_type(xmlAttr_getName(attr), xmlAttr_getValue(attr))); + *pV = atoi((char *)pNode->children->content); } - + else { - StringOutputStream path(256); - path << AppPath_get() << gameFile.c_str() << "/"; - mGameToolsPath = path.c_str(); + char s[10]; + sprintf(s, "%d", V); + pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s); + xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name); + *pV=V; } + // push the pref assignment if needed + PushAssignment(name, PREF_INT, pV); +} - ASSERT_MESSAGE(file_exists(mGameToolsPath.c_str()), "game directory not found: " << makeQuoted(mGameToolsPath.c_str())); - - mGameFile = gameFile; - +void CXMLPropertyBag::GetPref(const char *name, bool *pV, bool V) +{ + xmlNodePtr pNode; + if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content) { - GameDescription::iterator i = m_gameDescription.find("type"); - if(i == m_gameDescription.end()) + if (!strcmp((char *)pNode->children->content, "true")) { - globalErrorStream() << "Warning, 'type' attribute not found in '" << reinterpret_cast(pDoc->URL) << "'\n"; - // default - mGameType = "q3"; + *pV = true; } else { - mGameType = (*i).second.c_str(); + *pV = false; } } + else + { + char s[10]; + V ? strcpy(s, "true") : strcpy(s, "false"); + pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s); + xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name); + *pV=V; + } + // push the pref assignment + PushAssignment(name, PREF_BOOL, pV); } -void CGameDescription::Dump() +void CXMLPropertyBag::GetPref(const char *name, float *pV, float V) { - globalOutputStream() << "game description file: " << makeQuoted(mGameFile.c_str()) << "\n"; - for(GameDescription::iterator i = m_gameDescription.begin(); i != m_gameDescription.end(); ++i) + xmlNodePtr pNode; + if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content) + { + *pV = atof((char *)pNode->children->content); + } + else { - globalOutputStream() << (*i).first.c_str() << " = " << makeQuoted((*i).second.c_str()) << "\n"; + char s[10]; + sprintf(s, "%f", V); + pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s); + xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name); + *pV=V; } + // push the pref assignment if needed + PushAssignment(name, PREF_FLOAT, pV); } -CGameDescription *g_pGameDescription; ///< shortcut to g_GamesDialog.m_pCurrentDescription - - -#include "warnings.h" -#include "stream/textfilestream.h" -#include "container/array.h" -#include "xml/ixml.h" -#include "xml/xmlparser.h" -#include "xml/xmlwriter.h" - -#include "preferencedictionary.h" -#include "stringio.h" - -const char* const PREFERENCES_VERSION = "1.0"; - -bool Preferences_Load(PreferenceDictionary& preferences, const char* filename) +void CXMLPropertyBag::GetPref(const char *name, float* pV, float* V) { - TextFileInputStream file(filename); - if(!file.failed()) + xmlNodePtr pNode; + if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content) + { + sscanf((char *)pNode->children->content, "%f %f %f", &pV[0], &pV[1], &pV[2]); + } + else { - XMLStreamParser parser(file); - XMLPreferenceDictionaryImporter importer(preferences, PREFERENCES_VERSION); - parser.exportXML(importer); - return true; + char s[128]; + sprintf(s, "%f %f %f", V[0], V[1], V[2]); + pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s); + xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name); + pV[0] = V[0]; + pV[1] = V[1]; + pV[2] = V[2]; } - return false; + // push the pref assignment if needed + PushAssignment(name, PREF_VEC3, pV); } -bool Preferences_Save(PreferenceDictionary& preferences, const char* filename) +void CXMLPropertyBag::GetPref(const char *name, window_position_t* pV, window_position_t V) { - TextFileOutputStream file(filename); - if(!file.failed()) + xmlNodePtr pNode; + if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content) { - XMLStreamWriter writer(file); - XMLPreferenceDictionaryExporter exporter(preferences, PREFERENCES_VERSION); - exporter.exportXML(writer); - return true; + WindowPosition_Parse(*pV, CString((xmlChar *)pNode->children->content)); } - return false; + else + { + CString str; + WindowPosition_Write(V, str); + pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)str.GetBuffer()); + xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name); + *pV = V; + } + // push the pref assignment if needed + PushAssignment(name, PREF_WNDPOS, pV); } -bool Preferences_Save_Safe(PreferenceDictionary& preferences, const char* filename) +void CXMLPropertyBag::UpdatePrefTree() { - Array 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); + // read the assignments and update the tree + list::iterator iPref; + for(iPref = mPrefAssignments.begin(); iPref != mPrefAssignments.end(); iPref++) + { + CPrefAssignment *pPref = &(*iPref); + // look for the node + xmlNodePtr pNode; + char s[64]; + + pNode = EpairForName(pPref->mName.GetBuffer()); + // we never expect that the node could not be found, because this is supposed to happen + // after the tree was built with GetPref calls, never on a blank tree + if (!pNode) + { + Sys_FPrintf(SYS_ERR, "Unexpected EpairForName '%s' not found in UpdatePrefTree\n", pPref->mName.GetBuffer()); + return; + } + switch ((*iPref).mType) + { + case PREF_STR: + xmlNodeSetContent(pNode, (const xmlChar *)((Str *)pPref->mVal)->GetBuffer()); + break; + case PREF_INT: + sprintf(s, "%d", *(int *)pPref->mVal); + xmlNodeSetContent(pNode, (xmlChar *)s); + break; + case PREF_FLOAT: + sprintf(s, "%f", *(float *)pPref->mVal); + xmlNodeSetContent(pNode, (xmlChar *)s); + break; + case PREF_BOOL: + *(bool *)pPref->mVal ? strcpy(s, "true") : strcpy(s, "false"); + xmlNodeSetContent(pNode, (xmlChar *)s); + break; + case PREF_VEC3: + { + float* v = (float*)pPref->mVal; + sprintf(s, "%f %f %f", v[0], v[1], v[2]); + xmlNodeSetContent(pNode, (xmlChar *)s); + } + break; + case PREF_WNDPOS: + { + CString str; + WindowPosition_Write(*(window_position_t*)pPref->mVal, str); + xmlNodeSetContent(pNode, (xmlChar*)str.GetBuffer()); + } + break; + } + } } +void CXMLPropertyBag::Clear() +{ + if(!InUse()) + return; + xmlFreeDoc(mpDoc); + mpDoc = NULL; + mpDocNode = NULL; + mbEmpty = false; +} -void LogConsole_importString(const char* string) +void CXMLPropertyBag::ReadXMLFile(const char* pFilename) { - g_Console_enableLogging = string_equal(string, "true"); - Sys_LogFile(g_Console_enableLogging); -} -typedef FreeCaller1 LogConsoleImportStringCaller; + mpDoc = xmlParseFile(pFilename); + // basic checks + if (mpDoc) + { + mpDocNode = mpDoc->children; + xmlAttrPtr tmp_attr_ptr = xmlHasProp(mpDocNode, (xmlChar *)"version"); + if (strcmp((char *)mpDocNode->name, "qpref")) + { + Sys_FPrintf(SYS_ERR, "Unrecognized node '%s' in '%s'\n", mpDocNode->name, mpDoc->URL); + xmlFreeDoc(mpDoc); + mpDoc = NULL; + } + else if (tmp_attr_ptr != NULL && strcmp((char*)tmp_attr_ptr->children->content, "1")) + { + Sys_FPrintf(SYS_ERR, "Wrong version '%s' in node for '%s'\n", (char*)tmp_attr_ptr->children->content, mpDoc->URL); + xmlFreeDoc(mpDoc); + mpDoc = NULL; + } + Sys_Printf("Opened XML property file: '%s'\n", pFilename); + } -void RegisterGlobalPreferences(PreferenceSystem& preferences) -{ - preferences.registerPreference("gamefile", CopiedStringImportStringCaller(g_GamesDialog.m_sGameFile), CopiedStringExportStringCaller(g_GamesDialog.m_sGameFile)); - preferences.registerPreference("gamePrompt", BoolImportStringCaller(g_GamesDialog.m_bGamePrompt), BoolExportStringCaller(g_GamesDialog.m_bGamePrompt)); - preferences.registerPreference("log console", LogConsoleImportStringCaller(), BoolExportStringCaller(g_Console_enableLogging)); + if (!mpDoc) + { + mbEmpty = true; + // no document, create one + mpDoc = xmlNewDoc((xmlChar *)"1.0"); + mpDocNode = xmlNewDocNode(mpDoc, NULL, (xmlChar *)"qpref", NULL); + xmlDocSetRootElement(mpDoc, mpDocNode); + xmlSetProp(mpDocNode, (xmlChar *)"version", (xmlChar *)"1"); + Sys_Printf("XML property file '%s' invalid/not found, creating blank properties tree\n", pFilename); + } } +qboolean CXMLPropertyBag::WriteXMLFile(const char* pFilename) +{ + int res = xmlSaveFormatFile(pFilename, mpDoc, 1); -PreferenceDictionary g_global_preferences; + if(res == -1) + return false; -void GlobalPreferences_Init() -{ - RegisterGlobalPreferences(g_global_preferences); + Sys_Printf("Wrote XML property file '%s'\n", pFilename); + return true; } -void CGameDialog::LoadPrefs() +// ============================================================================= +// Widget callbacks for PrefsDlg + +#if !defined(WIN32) +// browse for custom editor executable +static void OnBtnBrowseEditor (GtkWidget *widget, gpointer data) { - // load global .pref file - StringOutputStream strGlobalPref(256); - strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref"; + PrefsDlg *dlg = (PrefsDlg*)data; - globalOutputStream() << "loading global preferences from " << makeQuoted(strGlobalPref.c_str()) << "\n"; + const char *filename = file_dialog(g_PrefsDlg.GetWidget(), TRUE, _("Executable for Custom Editor")); - if(!Preferences_Load(g_global_preferences, strGlobalPref.c_str())) + if(filename != NULL) { - globalOutputStream() << "failed to load global preferences from " << strGlobalPref.c_str() << "\n"; + dlg->m_strEditorCommand = filename; + dlg->UpdateData(FALSE); } } +#endif -void CGameDialog::SavePrefs() +static void OnBtnBrowseprefab (GtkWidget *widget, gpointer data) { - StringOutputStream strGlobalPref(256); - strGlobalPref << g_Preferences.m_global_rc_path->str << "global.pref"; - - globalOutputStream() << "saving global preferences to " << strGlobalPref.c_str() << "\n"; + PrefsDlg *dlg = (PrefsDlg*)data; + char *path = dlg->m_strPrefabPath; + if (strlen (path) == 0) + path = g_strGameToolsPath; + char *dir = dir_dialog (g_PrefsDlg.GetWidget (), _("Set prefab path"), path); + dlg->UpdateData(TRUE); - if(!Preferences_Save_Safe(g_global_preferences, strGlobalPref.c_str())) + if (dir != NULL) { - globalOutputStream() << "failed to save global preferences to " << strGlobalPref.c_str() << "\n"; + CString strPath; + strPath = dir; + AddSlash(strPath); + dlg->m_strPrefabPath = strPath; + dlg->UpdateData(FALSE); + free (dir); } } -void CGameDialog::DoGameDialog() +static void OnBtnBrowseuserini (GtkWidget *widget, gpointer data) { - // show the UI - DoModal(); - - // we save the prefs file - SavePrefs(); -} + PrefsDlg *dlg = (PrefsDlg*)data; + char *path = dlg->m_strUserPath; + if (strlen (path) == 0) + path = g_strGameToolsPath; + // TODO: INI filter? + const char *filename = file_dialog (g_PrefsDlg.GetWidget(), TRUE, _("Find INI file"), path); -void CGameDialog::GameFileImport(int value) -{ - m_nComboSelect = value; - // use value to set m_sGameFile - std::list::iterator iGame = mGames.begin(); - int i; - for(i=0; iUpdateData(TRUE); + dlg->m_strUserPath = filename; + dlg->UpdateData(FALSE); } - m_sGameFile = (*iGame)->mGameFile; } -void CGameDialog::GameFileExport(const IntImportCallback& importCallback) const +static void OnButtonClean (GtkWidget *widget, gpointer data) { - // use m_sGameFile to set value - std::list::const_iterator iGame; - int i = 0; - for(iGame=mGames.begin(); iGame!=mGames.end(); ++iGame) + // make sure this is what the user wants + if (gtk_MessageBox (g_PrefsDlg.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"), MB_YESNO) == IDYES) { - if ((*iGame)->mGameFile == m_sGameFile) - { - m_nComboSelect = i; - break; - } - i++; + PrefsDlg *dlg = (PrefsDlg*)data; + dlg->EndModal (IDCANCEL); + + g_qeglobals.disable_ini = true; + remove (dlg->m_inipath->str); + char buf[PATH_MAX]; + sprintf(buf, "%sSavedInfo.bin", dlg->m_rc_path->str); + remove(buf); + HandleCommand (NULL, GINT_TO_POINTER (ID_FILE_EXIT)); + _exit (0); } - importCallback(m_nComboSelect); } -void CGameDialog_GameFileImport(CGameDialog& self, int value) -{ - self.GameFileImport(value); -} +// ============================================================================= +// PrefsDlg class -void CGameDialog_GameFileExport(CGameDialog& self, const IntImportCallback& importCallback) -{ - self.GameFileExport(importCallback); +// IMPORTANT NOTE: the values here don't matter very much +// the actual intialization if you start with an empty .ini is done when loading the prefs for the first time +// profile_load_int takes an argument to use if the value is not found +PrefsDlg::PrefsDlg () +{ + m_bWarn = TRUE; + m_nMouse = 1; + m_nView = MainFrame::eRegular; + m_bLoadLast = FALSE; + m_bInternalBSP = FALSE; + m_bRightClick = FALSE; + m_bSetGame = FALSE; + m_bAutoSave = TRUE; + m_nAutoSave = 5; + m_bLoadLastMap = FALSE; + m_bTextureWindow = FALSE; + m_bSnapShots = FALSE; + m_fTinySize = 0.5; + m_bCleanTiny = FALSE; + m_bCamXYUpdate = TRUE; + m_bCamDragMultiSelect = FALSE; + m_bCamFreeLook = TRUE; + m_bCamFreeLookStrafe = FALSE; + m_bCamInverseMouse = FALSE; + m_bCamDiscrete = TRUE; + m_bNewLightDraw = FALSE; + m_strPrefabPath = ""; + m_nWhatGame = 0; + m_bALTEdge = FALSE; + m_bFaceColors = FALSE; + m_bXZVis = FALSE; + m_bYZVis = FALSE; + m_bZVis = FALSE; + m_bSizePaint = FALSE; + m_bDLLEntities = FALSE; +#ifdef _WIN32 + m_bDetachableMenus = FALSE; // Most win32 users will find detachable menus annoying +#else + m_bDetachableMenus = TRUE; // Linux/Apple users are used to them... +#endif + m_bPatchToolbar = TRUE; + m_bWideToolbar = TRUE; + m_bPluginToolbar = TRUE; + m_bNoClamp = FALSE; + m_strUserPath = ""; + m_nRotation = 0; + m_bChaseMouse = FALSE; + m_bTextureScrollbar = TRUE; + m_bDisplayLists = TRUE; + m_bAntialiasedPointsAndLines = FALSE; // Fishman - Add antialiazed points and lines support. 09/03/00 + m_bShowShaders = FALSE; + m_nShader = -1; + m_bNoStipple = FALSE; + m_bVertexSplit = FALSE; + m_bSelectCurves = TRUE; + m_bSelectModels = TRUE; + m_nEntityShowState = ENTITY_SKINNED_BOXED; + m_nTextureScale = 2; + m_bSwitchClip = FALSE; + m_bSelectWholeEntities = TRUE; + m_nTextureQuality = 3; + m_bShowShaders = TRUE; + m_bGLLighting = FALSE; + m_nShader = 0; + m_nUndoLevels = 30; + m_bTexturesShaderlistOnly = FALSE; + // paths to ini files + m_rc_path = NULL; + m_inipath = NULL; + m_bWatchBSP = TRUE; + m_bLeakStop = TRUE; + m_iTimeout = 15; + m_bRunQuake = TRUE; + m_bDoSleep = FALSE; + m_nSubdivisions = 4; + // not prefs + m_bFloatingZ = FALSE; + m_bGlPtWorkaround = FALSE; // Gef: Kyro/GL_POINTS workaround 25-aug-2001 +#ifdef _WIN32 + m_bNativeGUI = FALSE; + m_bStartOnPrimMon = FALSE; +#endif + m_global_rc_path = NULL; +#ifdef _WIN32 + m_bUseWin32Editor = TRUE; +#else + // custom shader editor options + m_bUseCustomEditor = FALSE; + m_strEditorCommand = ""; +#endif + m_nLightRadiuses = 1; + m_bQ3Map2Texturing = TRUE; +#ifdef ATIHACK_812 + m_bGlATIHack = FALSE; +#endif } -void CGameDialog::CreateGlobalFrame(PreferencesPage& page) -{ - std::vector games; - games.reserve(mGames.size()); - for(std::list::iterator i = mGames.begin(); i != mGames.end(); ++i) - { - games.push_back((*i)->getRequiredKeyValue("name")); - } - page.appendCombo( - "Select the game", - StringArrayRange(&(*games.begin()), &(*games.end())), - ReferenceCaller1(*this), - ReferenceCaller1(*this) - ); - page.appendCheckBox("Startup", "Show Global Preferences", m_bGamePrompt); -} +/*! +========================================================= +Games selection dialog +========================================================= +*/ -GtkWindow* CGameDialog::BuildDialog() +CGameDescription::CGameDescription(xmlDocPtr pDoc, const Str &GameFile) { - GtkFrame* frame = create_dialog_frame("Game settings", GTK_SHADOW_ETCHED_IN); + char *p, *prop; + mpDoc = pDoc; + // read the user-friendly game name + xmlNodePtr pNode = mpDoc->children; - GtkVBox* vbox2 = create_dialog_vbox(0, 4); - gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(vbox2)); + while (strcmp((const char*)pNode->name, "game") && pNode != NULL) pNode=pNode->next; + if (!pNode) + { + ///< \todo add the file name (this node and gametools should all be part of CGameDescription anyway) + Error("Didn't find 'game' node in the game description file '%s'\n", pDoc->URL); + } + // on win32, game tools path can now be specified relative to the exe's cwd + prop = (char*)xmlGetProp( pNode, (xmlChar*)"gametools" ); + if ( prop == NULL ) { + Error( "Didn't find 'gametools' node in the game description file '%s'\n", pDoc->URL ); + } + { + char full[PATH_MAX]; +#ifdef _WIN32 + _fullpath( full, prop, PATH_MAX ); +#else + strncpy( full, prop, PATH_MAX ); +#endif + xmlFree( prop ); + prop = NULL; + for ( p = full; *p != '\0'; p++ ) { + if ( *p == '\\' ) { + *p = '/'; + } + mGameToolsPath = full; + if ( p != full && *(p-1) != '/' ) { + mGameToolsPath += "/"; + } + } + } + prop = (char*)xmlGetProp(pNode, (xmlChar*)"name"); + if (prop == NULL) + { + Sys_FPrintf(SYS_WRN, "Warning, 'name' attribute not found in '%s'\n", pDoc->URL); + mGameName = pDoc->URL; + } + else { - PreferencesPage preferencesPage(*this, GTK_WIDGET(vbox2)); - Global_constructPreferences(preferencesPage); - CreateGlobalFrame(preferencesPage); + mGameName = prop; + xmlFree(prop); } - return create_simple_modal_dialog_window("Global Preferences", m_modal, GTK_WIDGET(frame)); -} + mGameFile = GameFile; -class LoadGameFile -{ - std::list& mGames; - const char* mPath; -public: - LoadGameFile(std::list& games, const char* path) : mGames(games), mPath(path) + prop = (char*)xmlGetProp(pNode, (xmlChar*)"quake2"); + if (prop == NULL) { + // default + quake2 = false; } - void operator()(const char* name) const + else { - if(!extension_equal(path_get_extension(name), "game")) - { - return; - } - StringOutputStream strPath(256); - strPath << mPath << name; - globalOutputStream() << strPath.c_str() << '\n'; + quake2 = true; + xmlFree(prop); + } - 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"; - } + // if this is set, the open maps dialoge will open the engine path not the + // home dir for map loading and saving + prop = (char*)xmlGetProp(pNode, (xmlChar*)"no_maps_in_home"); + if (prop == NULL) + { + // default + noMapsInHome = false; + } + else + { + noMapsInHome = true; + xmlFree(prop); } -}; -void CGameDialog::ScanForGames() -{ - StringOutputStream strGamesPath(256); - strGamesPath << AppPath_get() << "games/"; - const char *path = strGamesPath.c_str(); + prop = (char*)xmlGetProp(pNode, (xmlChar*)"basegame"); + if (prop == NULL) + { + // default + mBaseGame = "baseq3"; + } + else + { + mBaseGame = prop; + xmlFree(prop); + } - globalOutputStream() << "Scanning for game description files: " << path << '\n'; + // on win32, engine path can now be specified relative to the exe's cwd + prop = (char*)xmlGetProp(pNode, (const xmlChar *)"enginepath"); + if ( prop != NULL ) { + char full[PATH_MAX]; +#ifdef _WIN32 + _fullpath( full, prop, PATH_MAX ); +#else + strncpy( full, prop, PATH_MAX ); +#endif + xmlFree( prop ); + prop = NULL; + // process seperators + for ( p = full; *p != '\0'; p++ ) { + if ( *p == '\\' ) { + *p = '/'; + } + } + mEnginePath = full; + if ( p != full && *(p-1) != '/' ) { + mEnginePath += "/"; + } + } + else + { + // if engine path was not specified in the .game, it implies we can guess it from the gametools path + // on win32, and for most game package, the gametools are installed with the game + char aux_path[PATH_MAX]; // aux + strcpy( aux_path, mGameToolsPath.GetBuffer() ); + if ( ( aux_path[ strlen(aux_path)-1 ] == '/' ) || ( aux_path[ strlen(aux_path)-1 ] == '\\' ) ) { + aux_path[strlen(aux_path)-1] = '\0'; // strip ending '/' if any + } + char up_path[PATH_MAX]; // up one level + ExtractFilePath( aux_path, up_path ); + mEnginePath = up_path; + } - /*! - \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//games/ scanning on top of that for developers - (if that's really needed) - */ + prop = (char*)xmlGetProp(pNode, (xmlChar*)"engine"); + if (prop == NULL) + { +#ifdef _WIN32 + mEngine = "quake3.exe"; +#elif __linux__ + mEngine = "quake3"; +#elif __APPLE__ + mEngine = "Quake3.app"; +#endif + } + else + { + mEngine = prop; + xmlFree(prop); + } - Directory_forEach(path, LoadGameFile(mGames, path)); +#if defined (__linux__) || defined (__APPLE__) + // *nix specific + prop = (char*)xmlGetProp(pNode, (const xmlChar *)"prefix"); + if(prop != NULL) + { + mUserPathPrefix = prop; + xmlFree(prop); + } +#endif + mShaderPath = xmlGetProp(pNode, (const xmlChar *)"shaderpath"); + if (!mShaderPath.GetLength()) + { + mShaderPath = "scripts/"; + mShaderlist = "scripts/shaderlist.txt"; + } + else + { + AddSlash(mShaderPath); + mShaderlist = mShaderPath; + mShaderlist += "shaderlist.txt"; + } + xmlChar* default_scale = xmlGetProp(pNode, (const xmlChar *)"default_scale"); + if (default_scale) + { + mTextureDefaultScale = atof((const char *)default_scale); + xmlFree(default_scale); + } + else + mTextureDefaultScale = 0.5f; + xmlChar* eclass_singleload = xmlGetProp(pNode, (const xmlChar*)"eclass_singleload"); + if (eclass_singleload) + { + mEClassSingleLoad = true; + xmlFree(eclass_singleload); + } + else + mEClassSingleLoad = false; + xmlChar* no_patch = xmlGetProp(pNode, (const xmlChar *)"no_patch"); + if (no_patch) + { + mNoPatch = true; + xmlFree(no_patch); + } + else + mNoPatch = false; + xmlChar* caulk_shader = xmlGetProp(pNode, (const xmlChar *)"caulk_shader"); + if (caulk_shader) + { + mCaulkShader = caulk_shader; + xmlFree(caulk_shader); + } + else + mCaulkShader = "textures/common/caulk"; } -CGameDescription* CGameDialog::GameDescriptionForComboItem() +void CGameDescription::Dump() { - std::list::iterator iGame; - int i=0; - for(iGame=mGames.begin(); iGame!=mGames.end(); ++iGame,i++) - { - if (i == m_nComboSelect) - { - return (*iGame); - } - } - return 0; // not found +#ifdef _WIN32 + if (CGameDialog::GetNetrun()) + Sys_Printf("Running in network mode, prefs path set to '%s'\n", g_strTempPath.GetBuffer()); +#endif + Sys_Printf("game name : '%s'\n", mGameName.GetBuffer()); + Sys_Printf("game file : '%s'\n", mGameFile.GetBuffer()); + Sys_Printf("game path : '%s'\n", mGameToolsPath.GetBuffer()); + Sys_Printf("base game : '%s'\n", mBaseGame.GetBuffer()); + Sys_Printf("engine path : '%s'\n", mEnginePath.GetBuffer()); + Sys_Printf("engine : '%s'\n", mEngine.GetBuffer()); + Sys_Printf("shaderlist : '%s'\n", mShaderlist.GetBuffer()); + Sys_Printf("caulk shader: '%s'\n", mCaulkShader.GetBuffer()); +#if defined (__linux__) || defined (__APPLE__) + Sys_Printf("prefix : '%s'\n", mUserPathPrefix.GetBuffer()); +#endif + Sys_Printf("default texture scale: %g\n", mTextureDefaultScale); + Sys_Printf("single eclass load : %s\n", mEClassSingleLoad ? "Yes" : "No"); + Sys_Printf("patches supported : %s\n", mNoPatch ? "No" : "Yes"); } -void CGameDialog::InitGlobalPrefPath() +CPrefAssignment& CPrefAssignment::operator = (const CPrefAssignment& ass) { - g_Preferences.m_global_rc_path = g_string_new(SettingsPath_get()); + if (&ass != this) + { + mName = ass.mName; + mType = ass.mType; + mVal = ass.mVal; + } + return *this; } -void CGameDialog::Reset() +CPrefAssignment::CPrefAssignment(const CPrefAssignment& ass) { - 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()); + *this = ass; } -void CGameDialog::Init() +void CGameDialog::LoadPrefs() { - InitGlobalPrefPath(); - LoadPrefs(); - ScanForGames(); - if (mGames.empty()) + // if we already have a document loaded, we will free and reload from file + if (mGlobalPrefs.InUse()) { - Error("Didn't find any valid game file descriptions, aborting\n"); + Sys_Printf("Reloading global prefs from file\n"); + mGlobalPrefs.Clear(); } - - CGameDescription* currentGameDescription = 0; - if (!m_bGamePrompt) - { - // search by .game name - std::list::iterator iGame; - for(iGame=mGames.begin(); iGame!=mGames.end(); ++iGame) - { - if ((*iGame)->mGameFile == m_sGameFile) - { - currentGameDescription = (*iGame); - break; - } - } - } - if (m_bGamePrompt || !currentGameDescription) + // load global .pref file + CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str; + strGlobalPref += "global.pref"; + + mGlobalPrefs.ReadXMLFile(strGlobalPref.GetBuffer()); + + mGlobalPrefs.GetPref("gamefile", &m_sGameFile, ""); // NOTE: there's no default, user HAS to select something + mGlobalPrefs.GetPref("autoload", &m_bAutoLoadGame, false); + mGlobalPrefs.GetPref("log console", &m_bLogConsole, false); + // in a very particular post-.pid startup + // we may have the console turned on and want to keep it that way + // so we use a latching system + if (m_bForceLogConsole) { - Create(); - DoGameDialog(); - // use m_nComboSelect to identify the game to run as and set the globals - currentGameDescription = GameDescriptionForComboItem(); - ASSERT_NOTNULL(currentGameDescription); + m_bLogConsole = true; + Sys_Printf("console logging has been latched on, saving prefs\n"); + SavePrefs(); + m_bForceLogConsole = false; } - g_pGameDescription = currentGameDescription; - g_pGameDescription->Dump(); -} + // console logging: call Sys_LogConsole to check console logging status + // it is important that we would log console as early as possible to make it useful + Sys_LogFile(); -CGameDialog::~CGameDialog() -{ - // free all the game descriptions - std::list::iterator iGame; - for(iGame=mGames.begin(); iGame!=mGames.end(); ++iGame) - { - delete (*iGame); - *iGame = 0; - } - if(GetWidget() != 0) + if (mGlobalPrefs.mbEmpty) { - Destroy(); + Sys_Printf("Saving global.pref with default pref values\n"); + SavePrefs(); } } -inline const char* GameDescription_getIdentifier(const CGameDescription& gameDescription) +void CGameDialog::SavePrefs() { - const char* identifier = gameDescription.getKeyValue("index"); - if(string_empty(identifier)) - { - identifier = "1"; + // update the tree and save it + mGlobalPrefs.UpdatePrefTree(); + + CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str; + strGlobalPref += "global.pref"; + + if ( !mGlobalPrefs.WriteXMLFile( strGlobalPref.GetBuffer() ) ) { + Sys_FPrintf(SYS_ERR, "Error occured while saving global prefs file '%s'\n", strGlobalPref.GetBuffer()); } - return identifier; } -void CGameDialog::AddPacksURL(StringOutputStream &URL) -{ - // add the URLs for the list of game packs installed - // FIXME: this is kinda hardcoded for now.. - std::list::iterator iGame; - for(iGame=mGames.begin(); iGame!=mGames.end(); ++iGame) - { - URL << "&Games_dlup%5B%5D=" << GameDescription_getIdentifier(*(*iGame)); - } +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(); } -CGameDialog g_GamesDialog; +void CGameDialog::DoGameDialog() { + // allow looping the game selection dialog with calls to the game configure dialog in between + while ( m_bDoGameInstall ) { + m_bDoGameInstall = false; -// ============================================================================= -// Widget callbacks for PrefsDlg + 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 + } + } -static void OnButtonClean (GtkWidget *widget, gpointer data) + // 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(); +} + +GtkWidget* CGameDialog::GetGlobalFrame() { - // make sure this is what the user wants - if (gtk_MessageBox(GTK_WIDGET(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", eMB_YESNO, eMB_ICONASTERISK) == eIDYES) - { - PrefsDlg *dlg = (PrefsDlg*)data; - dlg->EndModal (eIDCANCEL); + GtkWidget *vbox, *text, *combo, *check; - g_preferences_globals.disable_ini = true; - Preferences_Reset(); - gtk_main_quit(); + if ( mFrame != NULL ) { + return mFrame; } -} -// ============================================================================= -// PrefsDlg class + 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 ); + + 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_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 ); + + UpdateGameCombo(); + + 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); + + text = gtk_label_new(_("(this frame is available in the prefs menu if you set auto-select)")); + gtk_widget_show(text); + 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 ); +#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 ); -very first prefs init deals with selecting the game and the game tools path -then we can load .ini stuff - -using prefs / ini settings: -those are per-game - -look in ~/.radiant//gamename -======== -*/ - -#define 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 + // incref it so we can pass it around + gtk_widget_ref( GTK_WIDGET( mFrame ) ); - // 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); - - // then the ini file - m_inipath = g_string_new (m_rc_path->str); - g_string_append (m_inipath, PREFS_LOCAL_FILENAME); + return mFrame; } -void notebook_set_page(GtkWidget* notebook, GtkWidget* page) -{ - int pagenum = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), page); - if(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)) != pagenum) +void CGameDialog::UpdateData( bool retrieve ) { + if (!retrieve) { - gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), pagenum); + // use m_sGameFile to set m_nComboSelect + list::iterator iGame; + int i = 0; + for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++) + { + if ((*iGame)->mGameFile == m_sGameFile) + { + m_nComboSelect = i; + break; + } + i++; + } +#ifdef _WIN32 + UpdateNetrun(false); +#endif + } + Dialog::UpdateData(retrieve); + if (retrieve) + { + // use m_nComboSelect to set m_sGameFile + list::iterator iGame = mGames.begin(); + int i; + for(i=0; imGameFile; +#ifdef _WIN32 + UpdateNetrun(true); +#endif } } -void PrefsDlg::showPrefPage(GtkWidget* prefpage) -{ - notebook_set_page(m_notebook, prefpage); - return; +void CGameDialog::SInstallCallback( GtkWidget *widget, gpointer data ) { + CGameDialog *d = static_cast< CGameDialog* >( data ); + d->m_bDoGameInstall = true; + d->EndModal( 0 ); } -static void treeSelection(GtkTreeSelection* selection, gpointer data) -{ - PrefsDlg *dlg = (PrefsDlg*)data; +void CGameDialog::BuildDialog() { + GtkWidget *dlg, *vbox1, *button, *setup_button; - GtkTreeModel* model; - GtkTreeIter selected; - if(gtk_tree_selection_get_selected(selection, &model, &selected)) - { - GtkWidget* prefpage; - gtk_tree_model_get(model, &selected, 1, (gpointer*)&prefpage, -1); - dlg->showPrefPage(prefpage); - } + 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 ); } -typedef std::list PreferenceGroupCallbacks; +void CGameDialog::UpdateGameCombo() { + // fill in with the game descriptions + list::iterator iGame; -inline void PreferenceGroupCallbacks_constructGroup(const PreferenceGroupCallbacks& callbacks, PreferenceGroup& group) -{ - for(PreferenceGroupCallbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i) - { - (*i)(group); + if ( mGameCombo == NULL ) { + Sys_Printf( "mGameCombo == NULL\n" ); + return; } -} + // 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 ); + } -inline void PreferenceGroupCallbacks_pushBack(PreferenceGroupCallbacks& callbacks, const PreferenceGroupCallback& callback) -{ - callbacks.push_back(callback); + for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) { + gtk_combo_box_append_text( mGameCombo, (*iGame)->mGameName.GetBuffer() ); + } + gtk_combo_box_set_active( mGameCombo, 0 ); } -typedef std::list PreferencesPageCallbacks; - -inline void PreferencesPageCallbacks_constructPage(const PreferencesPageCallbacks& callbacks, PreferencesPage& page) +void CGameDialog::ScanForGames() { - for(PreferencesPageCallbacks::const_iterator i = callbacks.begin(); i != callbacks.end(); ++i) + CString strPath; + char *dirlist; + GDir *dir; + CString strGamesPath = g_strAppPath.GetBuffer(); + strGamesPath += "games"; + const char *path = strGamesPath.GetBuffer(); + + if ( !mGames.empty() ) { + Sys_Printf( "Clearing game list\n" ); + list::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: + do we put game description files below g_strAppPath, 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//games/ scanning on top of that for developers + (if that's really needed) + */ + + // FIXME need to catch the 'no game description' situation and exit with a clean error + + dir = g_dir_open(path, 0, NULL); + + if (dir != NULL) { - (*i)(page); + while (1) + { + const gchar* name = g_dir_read_name(dir); + if(name == NULL) + break; + + dirlist = g_strdup(name); +#ifdef _WIN32 + strlwr (dirlist); +#endif + char *ext = strrchr (dirlist, '.'); + if ((ext == NULL) || (strcmp (ext, ".game") != 0)) + continue; + strPath.Format("%s/%s", path, dirlist); + Sys_Printf("%s\n", strPath.GetBuffer()); + // got one, load it + xmlDocPtr pDoc = xmlParseFile(strPath.GetBuffer()); + if (pDoc) + { + mGames.push_front( new CGameDescription( pDoc, dirlist ) ); + } + else + { + Sys_FPrintf(SYS_ERR, "XML parser failed on '%s'\n", strPath.GetBuffer()); + } + + g_free( dirlist ); + } + g_dir_close( dir ); } -} -inline void PreferencesPageCallbacks_pushBack(PreferencesPageCallbacks& callbacks, const PreferencesPageCallback& callback) -{ - callbacks.push_back(callback); + // entries in the combo need to be updated + UpdateGameCombo(); } -PreferencesPageCallbacks g_interfacePreferences; -void PreferencesDialog_addInterfacePreferences(const PreferencesPageCallback& callback) +CGameDescription* CGameDialog::GameDescriptionForComboItem() { - PreferencesPageCallbacks_pushBack(g_interfacePreferences, callback); + list::iterator iGame; + int i=0; + for( iGame = mGames.begin(); iGame != mGames.end(); iGame++,i++ ) { + if ( i == m_nComboSelect ) { + return (*iGame); + } + } + return NULL; // not found } -PreferenceGroupCallbacks g_interfaceCallbacks; -void PreferencesDialog_addInterfacePage(const PreferenceGroupCallback& callback) + +void CGameDialog::InitGlobalPrefPath() { - PreferenceGroupCallbacks_pushBack(g_interfaceCallbacks, callback); + GString *global_rc_path; + // configure m_global_rc_path + // this is the g_strTempPath, and it has already been mkdir'ed + global_rc_path = g_string_new(g_strTempPath.GetBuffer()); + g_PrefsDlg.m_global_rc_path = global_rc_path; } -PreferencesPageCallbacks g_displayPreferences; -void PreferencesDialog_addDisplayPreferences(const PreferencesPageCallback& callback) +void CGameDialog::Reset() { - PreferencesPageCallbacks_pushBack(g_displayPreferences, callback); + if (!g_PrefsDlg.m_global_rc_path) + InitGlobalPrefPath(); + CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str; + strGlobalPref += "global.pref"; + remove(strGlobalPref.GetBuffer()); } -PreferenceGroupCallbacks g_displayCallbacks; -void PreferencesDialog_addDisplayPage(const PreferenceGroupCallback& callback) + +void CGameDialog::Init() { - PreferenceGroupCallbacks_pushBack(g_displayCallbacks, callback); + InitGlobalPrefPath(); + ScanForGames(); + if ( mGames.empty() ) { + DoGameInstall(); + ScanForGames(); + if ( mGames.empty() ) { + Error( "No games setup, aborting\n" ); + } + } + LoadPrefs(); + if ( m_bAutoLoadGame ) { + // search by .game name + list::iterator iGame; + for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++) + { + if ((*iGame)->mGameFile == m_sGameFile) + { + m_pCurrentGameDescription = (*iGame); + break; + } + } + } + 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"); + } + } + g_pGameDescription = m_pCurrentGameDescription; + + g_strGameToolsPath = g_pGameDescription->mGameToolsPath; + + // NOTE TTimo: this is moved from QE_LoadProject in 1.2 + // (probably broken) + // NOTE Hydra: was broken for win32, we don't use m_strHomeGame or m_strFSBasePath +#if defined (__linux__) || defined (__APPLE__) + g_qeglobals.m_strHomeGame = g_get_home_dir(); + g_qeglobals.m_strHomeGame += "/"; + g_qeglobals.m_strHomeGame += m_pCurrentGameDescription->mUserPathPrefix.GetBuffer(); + g_qeglobals.m_strHomeGame += "/"; +#else + g_qeglobals.m_strHomeGame = g_pGameDescription->mEnginePath.GetBuffer(); +#endif + + g_pGameDescription->Dump(); } -PreferencesPageCallbacks g_settingsPreferences; -void PreferencesDialog_addSettingsPreferences(const PreferencesPageCallback& callback) +CGameDialog::~CGameDialog() { - PreferencesPageCallbacks_pushBack(g_settingsPreferences, callback); + if (mFrame) + { + // NOTE I'm not too sure how reliable this is + gtk_widget_unref(GTK_WIDGET(mFrame)); + } + // free all the game descriptions + list::iterator iGame; + for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++) + { + delete (*iGame); + *iGame = NULL; + } } -PreferenceGroupCallbacks g_settingsCallbacks; -void PreferencesDialog_addSettingsPage(const PreferenceGroupCallback& callback) + +void CGameDialog::AddPacksURL(Str &URL) { - PreferenceGroupCallbacks_pushBack(g_settingsCallbacks, callback); + // add the URLs for the list of game packs installed + // FIXME: this is kinda hardcoded for now.. + list::iterator iGame; + for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++) + { + if ((*iGame)->mGameFile == "q3.game") + URL += "&Games_dlup%5B%5D=1"; + else if ((*iGame)->mGameFile == "wolf.game") + URL += "&Games_dlup%5B%5D=2"; + // FIXME: double entry + else if ((*iGame)->mGameFile == "wolf.game") + URL += "&Games_dlup%5B%5D=3"; + else if ((*iGame)->mGameFile == "jk2.game") + URL += "&Games_dlup%5B%5D=4"; + else if ((*iGame)->mGameFile == "stvef.game") + URL += "&Games_dlup%5B%5D=5"; + else if ((*iGame)->mGameFile == "sof2.game") + URL += "&Games_dlup%5B%5D=6"; + else if ((*iGame)->mGameFile == "ja.game") + URL += "&Games_dlup%5B%5D=7"; + } } -void Widget_updateDependency(GtkWidget* self, GtkWidget* toggleButton) +#ifdef _WIN32 + +#define NETRUN_FILENAME "netrun.conf" + +bool CGameDialog::m_bNetRun; + +void CGameDialog::UpdateNetrun(bool retrieve) { - gtk_widget_set_sensitive(self, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggleButton)) && GTK_WIDGET_IS_SENSITIVE(toggleButton)); + FILE *f_netrun; + CString strNetrun; + strNetrun = g_strAppPath; strNetrun += NETRUN_FILENAME; + if (!retrieve) + { + // now check if we are running from a network installation + // use a dummy file as the flag + f_netrun = fopen(strNetrun.GetBuffer(), "r"); + if (f_netrun) + { + fclose(f_netrun); + m_bNetRun = true; + } + else + m_bNetRun = false; + } + else + { + if (m_bNetRun) + { + f_netrun = fopen(strNetrun.GetBuffer(), "w"); + if (!f_netrun) + { + Sys_FPrintf(SYS_ERR, "ERROR: Failed to create netrun file '%s'\n", strNetrun.GetBuffer()); + m_bNetRun = false; + } + else + { + fclose(f_netrun); + Sys_Printf("Created/Checked '%s'\n", strNetrun.GetBuffer()); + } + } + else + { + if (remove(strNetrun.GetBuffer()) == -1) + { + if (errno != ENOENT) + Sys_FPrintf(SYS_ERR, "Failed to remove netrun file '%s'\n", strNetrun.GetBuffer()); + m_bNetRun = true; + } + else + { + Sys_Printf("Netrun mode is disabled\n"); + } + } + } } -void ToggleButton_toggled_Widget_updateDependency(GtkWidget *toggleButton, GtkWidget* self) +bool CGameDialog::GetNetrun() { - Widget_updateDependency(self, toggleButton); + return m_bNetRun; } +#endif + +/* +======== + +very first prefs init deals with selecting the game and the game tools path +then we can load .ini stuff + +using prefs / ini settings: +those are per-game + +win32: +look in g_strGameToolsPath for .ini + +linux: +look in ~/.radiant//gamename +======== +*/ + +#define PREFS_LOCAL_FILENAME "local.pref" -void ToggleButton_state_changed_Widget_updateDependency(GtkWidget* toggleButton, GtkStateType state, GtkWidget* self) +void PrefsDlg::Init() { - if(state == GTK_STATE_INSENSITIVE) + mGamesDialog.Init(); + + // m_global_rc_path has been set above, do m_rc_path with game specific stuff now + // the win32 and linux versions have been unified for network mode +#ifdef _WIN32 + if (!CGameDialog::GetNetrun()) { - Widget_updateDependency(self, toggleButton); + // legacy prefs settings, this goes where the game pack is installed + m_rc_path = g_string_new (g_strGameToolsPath.GetBuffer() ); + m_inipath = g_string_new (m_rc_path->str); + g_string_append (m_inipath, PREFS_LOCAL_FILENAME); + return; } +#endif + // 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.GetBuffer()); + g_string_append (m_rc_path, "/"); + Q_mkdir (m_rc_path->str, 0775); + + // then the ini file + m_inipath = g_string_new (m_rc_path->str); + g_string_append (m_inipath, PREFS_LOCAL_FILENAME); + } -void Widget_connectToggleDependency(GtkWidget* self, GtkWidget* toggleButton) +void PrefsDlg::UpdateData (bool retrieve) { - g_signal_connect(G_OBJECT(toggleButton), "state_changed", G_CALLBACK(ToggleButton_state_changed_Widget_updateDependency), self); - g_signal_connect(G_OBJECT(toggleButton), "toggled", G_CALLBACK(ToggleButton_toggled_Widget_updateDependency), self); - Widget_updateDependency(self, toggleButton); + // leo: the "changed" signal confuses the update function + if (m_pWidget == NULL) + return; + mGamesDialog.UpdateData (retrieve); + Dialog::UpdateData (retrieve); } +#ifdef _WIN32 +#define PREFSHSPACE 5 +#else +#define PREFSHSPACE 0 +#endif -inline GtkWidget* getVBox(GtkWidget* page) +static void UpdateSensitivity( GtkWidget *widget, gpointer data ) { - return gtk_bin_get_child(GTK_BIN(page)); + PrefsDlg *dlg = (PrefsDlg*)data; + dlg->DoSensitivity(); } -GtkTreeIter PreferenceTree_appendPage(GtkTreeStore* store, GtkTreeIter* parent, const char* name, GtkWidget* page) +static void UpdateEditorSensitivity(GtkWidget *widget, gpointer data) { - GtkTreeIter group; - gtk_tree_store_append(store, &group, parent); - gtk_tree_store_set(store, &group, 0, name, 1, page, -1); - return group; + PrefsDlg *dlg = (PrefsDlg*)data; + dlg->DoEditorSensitivity(); } -GtkWidget* PreferencePages_addPage(GtkWidget* notebook, const char* name) -{ - GtkWidget* preflabel = gtk_label_new(name); - gtk_widget_show(preflabel); - - GtkWidget* pageframe = gtk_frame_new(name); - gtk_container_set_border_width(GTK_CONTAINER(pageframe), 4); - gtk_widget_show(pageframe); - - GtkWidget* vbox = gtk_vbox_new(FALSE, 4); - gtk_widget_show(vbox); - gtk_container_set_border_width(GTK_CONTAINER(vbox), 4); - gtk_container_add(GTK_CONTAINER(pageframe), vbox); +// start new prefs dialog - // Add the page to the notebook - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); +/*! Utility function for swapping notebook pages for tree list selections */ +void PrefsDlg::showPrefPage(int prefpage) +{ + if(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)) != prefpage) + gtk_notebook_set_page(GTK_NOTEBOOK(notebook), prefpage); - return pageframe; + return; } -class PreferenceTreeGroup : public PreferenceGroup +static void treeSelection(GtkTreeSelection* selection, gpointer data) { - Dialog& m_dialog; - GtkWidget* m_notebook; - GtkTreeStore* m_store; - GtkTreeIter m_group; -public: - PreferenceTreeGroup(Dialog& dialog, GtkWidget* notebook, GtkTreeStore* store, GtkTreeIter group) : - m_dialog(dialog), - m_notebook(notebook), - m_store(store), - m_group(group) - { - } - PreferencesPage createPage(const char* treeName, const char* frameName) + PrefsDlg *dlg = (PrefsDlg*)data; + + GtkTreeModel* model; + GtkTreeIter selected; + if(gtk_tree_selection_get_selected(selection, &model, &selected)) { - GtkWidget* page = PreferencePages_addPage(m_notebook, frameName); - PreferenceTree_appendPage(m_store, &m_group, treeName, page); - return PreferencesPage(m_dialog, getVBox(page)); + int prefpage; + gtk_tree_model_get(model, &selected, 1, (gpointer*)&prefpage, -1); + dlg->showPrefPage(prefpage); } -}; +} -GtkWindow* PrefsDlg::BuildDialog() +void PrefsDlg::BuildDialog () { - PreferencesDialog_addInterfacePreferences(FreeCaller1()); - Mouse_registerPreferencesPage(); + // Main Preferences dialog + GtkWidget *dialog, *mainvbox, *hbox, *sc_win, *preflabel; + + // Widgets on notebook pages + GtkWidget *check, *label, *scale, *hbox2, *combo, + *table, *spin, *entry, *pixmap, + *radio, *button, *pageframe, *vbox; + + GList *combo_list = (GList*)NULL; + + GtkObject *adj; + + dialog = m_pWidget; + gtk_window_set_title(GTK_WINDOW(dialog), _("GtkRadiant Preferences")); + gtk_widget_realize(dialog); + + mainvbox = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(dialog), mainvbox); + gtk_container_set_border_width(GTK_CONTAINER(mainvbox), 5); + gtk_widget_show(mainvbox); + + hbox = gtk_hbox_new(FALSE, 5); + gtk_widget_show(hbox); + gtk_box_pack_end(GTK_BOX(mainvbox), hbox, FALSE, TRUE, 0); + + button = gtk_button_new_with_label(_("OK")); + gtk_widget_show(button); + gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); + gtk_widget_set_usize(button, 60, -2); + AddModalButton(button, IDOK); + + button = gtk_button_new_with_label(_("Cancel")); + 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); + + button = gtk_button_new_with_label (_("Clean")); + gtk_widget_show(button); + gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(OnButtonClean), this); + gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); + gtk_widget_set_usize (button, 60, -2); + + hbox = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 0); + gtk_widget_show(hbox); - GtkWindow* dialog = create_floating_window("GtkRadiant Preferences", m_parent); + sc_win = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sc_win), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_box_pack_start(GTK_BOX(hbox), sc_win, FALSE, FALSE, 0); + gtk_widget_show(sc_win); + + // prefs pages notebook + notebook = gtk_notebook_new(); + // hide the notebook tabs since its not supposed to look like a notebook + gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE); + gtk_box_pack_start(GTK_BOX(hbox), notebook, TRUE, TRUE, 0); + gtk_widget_show(notebook); + + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sc_win), GTK_SHADOW_IN); { - GtkWidget* mainvbox = gtk_vbox_new(FALSE, 5); - gtk_container_add(GTK_CONTAINER(dialog), mainvbox); - gtk_container_set_border_width(GTK_CONTAINER(mainvbox), 5); - gtk_widget_show(mainvbox); - + GtkTreeStore* store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); + + GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); + { - GtkWidget* hbox = gtk_hbox_new(FALSE, 5); - gtk_widget_show(hbox); - gtk_box_pack_end(GTK_BOX(mainvbox), hbox, FALSE, TRUE, 0); + GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); + GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes(_("Preferences"), renderer, "text", 0, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); + } + + { + GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); + g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(treeSelection), this); + } + gtk_widget_show(view); + + gtk_container_add(GTK_CONTAINER (sc_win), view); + + { + /********************************************************************/ + /* Add preference tree options */ + /********************************************************************/ { - GtkButton* button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &m_modal); - gtk_box_pack_end(GTK_BOX(hbox), GTK_WIDGET(button), FALSE, FALSE, 0); + GtkTreeIter group; + gtk_tree_store_append(store, &group, NULL); + gtk_tree_store_set(store, &group, 0, _("Globals"), 1, PTAB_FRONT, -1); + { + GtkTreeIter tab; + gtk_tree_store_append(store, &tab, &group); + gtk_tree_store_set(store, &tab, 0, _("Game settings"), 1, (gpointer)PTAB_GAME_SETTINGS, -1); + } } + { - GtkButton* button = create_dialog_button("Cancel", G_CALLBACK(dialog_button_cancel), &m_modal); - gtk_box_pack_end(GTK_BOX(hbox), GTK_WIDGET(button), FALSE, FALSE, 0); + GtkTreeIter group; + gtk_tree_store_append(store, &group, NULL); + gtk_tree_store_set(store, &group, 0, _("Display"), 1, PTAB_FRONT, -1); + { + GtkTreeIter tab; + gtk_tree_store_append(store, &tab, &group); + gtk_tree_store_set(store, &tab, 0, _("2D Display/Rendering"), 1, (gpointer)PTAB_2D, -1); + } + { + GtkTreeIter tab; + gtk_tree_store_append(store, &tab, &group); + gtk_tree_store_set(store, &tab, 0, _("3D View"), 1, (gpointer)PTAB_CAMERA, -1); + } + { + GtkTreeIter tab; + gtk_tree_store_append(store, &tab, &group); + gtk_tree_store_set(store, &tab, 0, _("Texture Settings"), 1, (gpointer)PTAB_TEXTURE, -1); + } } + { - GtkButton* button = create_dialog_button("Clean", G_CALLBACK(OnButtonClean), this); - gtk_box_pack_end(GTK_BOX(hbox), GTK_WIDGET(button), FALSE, FALSE, 0); + GtkTreeIter group; + gtk_tree_store_append(store, &group, NULL); + gtk_tree_store_set(store, &group, 0, _("Interface"), 1, PTAB_FRONT, -1); + { + GtkTreeIter tab; + gtk_tree_store_append(store, &tab, &group); + gtk_tree_store_set(store, &tab, 0, _("Layout"), 1, (gpointer)PTAB_LAYOUT, -1); + } + { + GtkTreeIter tab; + gtk_tree_store_append(store, &tab, &group); + gtk_tree_store_set(store, &tab, 0, _("Mouse"), 1, (gpointer)PTAB_MOUSE, -1); + } + { + GtkTreeIter tab; + gtk_tree_store_append(store, &tab, &group); + gtk_tree_store_set(store, &tab, 0, _("Editing"), 1, (gpointer)PTAB_EDITING, -1); + } } - } - - { - GtkWidget* hbox = gtk_hbox_new(FALSE, 5); - gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 0); - gtk_widget_show(hbox); - - { - GtkWidget* sc_win = gtk_scrolled_window_new(0, 0); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sc_win), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_box_pack_start(GTK_BOX(hbox), sc_win, FALSE, FALSE, 0); - gtk_widget_show(sc_win); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sc_win), GTK_SHADOW_IN); - - // prefs pages notebook - m_notebook = 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); - gtk_box_pack_start(GTK_BOX(hbox), m_notebook, TRUE, TRUE, 0); - gtk_widget_show(m_notebook); - + { + GtkTreeIter group; + gtk_tree_store_append(store, &group, NULL); + gtk_tree_store_set(store, &group, 0, _("Other"), 1, PTAB_FRONT, -1); + { + GtkTreeIter tab; + gtk_tree_store_append(store, &tab, &group); + gtk_tree_store_set(store, &tab, 0, _("Startup/Auto save"), 1, (gpointer)PTAB_STARTUP, -1); + } + { + GtkTreeIter tab; + gtk_tree_store_append(store, &tab, &group); + gtk_tree_store_set(store, &tab, 0, _("Paths"), 1, (gpointer)PTAB_PATHS, -1); + } + { + GtkTreeIter tab; + gtk_tree_store_append(store, &tab, &group); + gtk_tree_store_set(store, &tab, 0, _("Misc"), 1, (gpointer)PTAB_MISC, -1); + } + if (!g_qeglobals.bBSPFrontendPlugin) { - GtkTreeStore* store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); - - GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); - - { - GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); - GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Preferences", renderer, "text", 0, 0); - gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); - } - - { - GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); - g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(treeSelection), this); - } - - gtk_widget_show(view); - - gtk_container_add(GTK_CONTAINER (sc_win), view); - - { - /********************************************************************/ - /* Add preference tree options */ - /********************************************************************/ - // Front page... - //GtkWidget* front = - PreferencePages_addPage(m_notebook, "Front Page"); - - { - GtkWidget* global = PreferencePages_addPage(m_notebook, "Global Preferences"); - { - PreferencesPage preferencesPage(*this, getVBox(global)); - Global_constructPreferences(preferencesPage); - } - GtkTreeIter group = PreferenceTree_appendPage(store, 0, "Global", global); - { - GtkWidget* game = PreferencePages_addPage(m_notebook, "Game"); - PreferencesPage preferencesPage(*this, getVBox(game)); - g_GamesDialog.CreateGlobalFrame(preferencesPage); - - PreferenceTree_appendPage(store, &group, "Game", game); - } - } - - { - GtkWidget* interfacePage = PreferencePages_addPage(m_notebook, "Interface Preferences"); - { - PreferencesPage preferencesPage(*this, getVBox(interfacePage)); - PreferencesPageCallbacks_constructPage(g_interfacePreferences, preferencesPage); - } - - GtkTreeIter group = PreferenceTree_appendPage(store, 0, "Interface", interfacePage); - PreferenceTreeGroup preferenceGroup(*this, m_notebook, store, group); - - PreferenceGroupCallbacks_constructGroup(g_interfaceCallbacks, preferenceGroup); - } - - { - GtkWidget* display = PreferencePages_addPage(m_notebook, "Display Preferences"); - { - PreferencesPage preferencesPage(*this, getVBox(display)); - PreferencesPageCallbacks_constructPage(g_displayPreferences, preferencesPage); - } - GtkTreeIter group = PreferenceTree_appendPage(store, 0, "Display", display); - PreferenceTreeGroup preferenceGroup(*this, m_notebook, store, group); - - PreferenceGroupCallbacks_constructGroup(g_displayCallbacks, preferenceGroup); - } - - { - GtkWidget* settings = PreferencePages_addPage(m_notebook, "General Settings"); - { - PreferencesPage preferencesPage(*this, getVBox(settings)); - PreferencesPageCallbacks_constructPage(g_settingsPreferences, preferencesPage); - } - - GtkTreeIter group = PreferenceTree_appendPage(store, 0, "Settings", settings); - PreferenceTreeGroup preferenceGroup(*this, m_notebook, store, group); - - PreferenceGroupCallbacks_constructGroup(g_settingsCallbacks, preferenceGroup); - } - } - - gtk_tree_view_expand_all(GTK_TREE_VIEW(view)); - - g_object_unref(G_OBJECT(store)); + GtkTreeIter tab; + gtk_tree_store_append(store, &tab, &group); + gtk_tree_store_set(store, &tab, 0, _("BSP Monitoring"), 1, (gpointer)PTAB_BSPMONITOR, -1); } } } + + gtk_tree_view_expand_all(GTK_TREE_VIEW(view)); + + g_object_unref(G_OBJECT(store)); } - gtk_notebook_set_page(GTK_NOTEBOOK(m_notebook), 0); + /**********************************************************************/ + /* build the prefs pages */ + /**********************************************************************/ - return dialog; -} + // Front page... + // todo : add something interesting here + // NOTE TTimo: tip of the day? or a logo? + preflabel = gtk_label_new(_("Front Page")); + gtk_widget_show(preflabel); + pageframe = gtk_frame_new(NULL); + gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); + gtk_widget_show(pageframe); + vbox = gtk_vbox_new(FALSE, 5); + gtk_widget_show(vbox); + gtk_widget_set_usize(GTK_WIDGET(vbox), 350, -2); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(pageframe), vbox); -preferences_globals_t g_preferences_globals; + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); -PrefsDlg g_Preferences; // global prefs instance + /******** global preferences group ****************************/ + preflabel = gtk_label_new(_("Globals")); + gtk_widget_show(preflabel); + pageframe = mGamesDialog.GetGlobalFrame(); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); -void PreferencesDialog_constructWindow(GtkWindow* main_window) -{ - g_Preferences.m_parent = main_window; - g_Preferences.Create(); -} -void PreferencesDialog_destroyWindow() -{ - g_Preferences.Destroy(); -} + /******** 2D prefs group (xy views/rendering options) *********/ + preflabel = gtk_label_new(_("2D Display")); + gtk_widget_show(preflabel); + pageframe = gtk_frame_new(_("2D Display")); + gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); + gtk_widget_show(pageframe); + vbox = gtk_vbox_new(FALSE, 5); + gtk_widget_show(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(pageframe), vbox); + // OpenGL Display Lists + check = gtk_check_button_new_with_label(_("OpenGL Display Lists")); + gtk_widget_show(check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData(check, &m_bDisplayLists, DLG_CHECK_BOOL); + + // Antialiased points & lines + // Fishman - Add antialiazed points and lines support. 09/03/00 + check = gtk_check_button_new_with_label (_("OpenGL antialiased points and lines")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bAntialiasedPointsAndLines, DLG_CHECK_BOOL); + + // Solid selection boxes + check = gtk_check_button_new_with_label (_("Solid selection boxes")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bNoStipple, DLG_CHECK_BOOL); + + // Display size info + check = gtk_check_button_new_with_label (_("Display size info")); + gtk_widget_show (check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bSizePaint, DLG_CHECK_BOOL); + + // Alternate vertex/edge handles + // Gef: Kyro GL_POINT work around 25-aug-2001 + check = gtk_check_button_new_with_label (_("Alternate vertex/edge handles")); + gtk_widget_show(check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData(check, &m_bGlPtWorkaround, DLG_CHECK_BOOL); + + g_list_free (combo_list); + +#ifdef ATIHACK_812 + // ATI bugs + check = gtk_check_button_new_with_label (_("ATI cards with broken drivers - bug #802")); + gtk_widget_show(check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData(check, &m_bGlATIHack, DLG_CHECK_BOOL); +#endif -PreferenceDictionary g_preferences; + // Add the page to the notebook + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); -PreferenceSystem& GetPreferenceSystem() -{ - return g_preferences; -} + /******** 3D Camera view group *********/ + preflabel = gtk_label_new(_("3D View")); + gtk_widget_show(preflabel); + pageframe = gtk_frame_new(_("3D View")); + gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); + gtk_widget_show(pageframe); + vbox = gtk_vbox_new(FALSE, 5); + gtk_widget_show(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(pageframe), vbox); -class PreferenceSystemAPI -{ - PreferenceSystem* m_preferencesystem; -public: - typedef PreferenceSystem Type; - STRING_CONSTANT(Name, "*"); + // Directional velocity (Movement Velocity) + // label container + hbox2 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox2); + gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0); + + // label + label = gtk_label_new(_("Movement Velocity")); + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); + gtk_widget_show(label); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); + + // adjustment + adj = gtk_adjustment_new(100, 50, 300, 1, 10, 10); + AddDialogData(adj, &m_nMoveSpeed, DLG_ADJ_INT); + + // scale + scale = gtk_hscale_new(GTK_ADJUSTMENT(adj)); + gtk_widget_show(scale); + gtk_box_pack_start(GTK_BOX (vbox), scale, FALSE, TRUE, 2); + + gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE); + + // Angular velocity (Rotational Velocity) + // label container + hbox2 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox2); + gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0); + + // label + label = gtk_label_new (_("Rotational Velocity")); + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); + gtk_widget_show (label); + gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); + + // adjustment + adj = gtk_adjustment_new (3, 1, 180, 1, 10, 10); // value, low, high, step, page_step, page_size + AddDialogData (adj, &m_nAngleSpeed, DLG_ADJ_INT); + + // scale + scale = gtk_hscale_new (GTK_ADJUSTMENT (adj)); + gtk_widget_show (scale); + gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, TRUE, 2); + gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE); + + // Text under the velocity sliders + // container + hbox2 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox2); + gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0); + + // label + label = gtk_label_new (_("slow")); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); + + // label + label = gtk_label_new (_("fast")); + gtk_widget_show (label); + gtk_box_pack_end (GTK_BOX (hbox2), label, FALSE, FALSE, 0); + + // Allow drag to select multiple faces/brushes + // container + table = gtk_table_new(2, 1, FALSE); + gtk_widget_show(table); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); + gtk_table_set_row_spacings (GTK_TABLE (table), 5); + gtk_table_set_col_spacings (GTK_TABLE (table), 5); + + label = gtk_label_new (_("Use paint-select in camera view:")); + gtk_widget_show (label); + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + combo_list = NULL; + combo_list = g_list_append (combo_list, (void *)_("No")); + combo_list = g_list_append (combo_list, (void *)_("Yes")); + combo_list = g_list_append (combo_list, (void *)_("Yes (Classic Key Setup)")); + + combo = gtk_combo_new (); + gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list); + gtk_widget_show (combo); + gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE); + AddDialogData (combo, &m_nCamDragMultiSelect, DLG_COMBO_INT); + + // Freelook in Camera view + check = gtk_check_button_new_with_label (_("Freelook in Camera view")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT); + AddDialogData (check, &m_bCamFreeLook, DLG_CHECK_BOOL); + + // Freelook in Camera view w/ forward & back strafing instead of up and down looking + check = gtk_check_button_new_with_label (_("Freelook strafes Forward and Back")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT); + AddDialogData (check, &m_bCamFreeLookStrafe, DLG_CHECK_BOOL); + + // Invert mouse in freelook + check = gtk_check_button_new_with_label (_("Invert mouse in freelook")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT); + AddDialogData (check, &m_bCamInverseMouse, DLG_CHECK_BOOL); + + // Discrete movement + check = gtk_check_button_new_with_label (_("Discrete movement")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT); + AddDialogData (check, &m_bCamDiscrete, DLG_CHECK_BOOL); + + // Update XY views on camera move + check = gtk_check_button_new_with_label (_("Update XY views on camera move")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT); + AddDialogData (check, &m_bCamXYUpdate, DLG_CHECK_BOOL); + + // Add the page to the notebook + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - PreferenceSystemAPI() + /******** Texture group *********/ + preflabel = gtk_label_new(_("Textures")); + gtk_widget_show(preflabel); + pageframe = gtk_frame_new(_("Textures")); + gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); + gtk_widget_show(pageframe); + vbox = gtk_vbox_new(FALSE, 6); + gtk_widget_show(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(pageframe), vbox); + + // Texture quality slider + // label + label = gtk_label_new (_("Texture quality")); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); + + // adjustment + adj = gtk_adjustment_new (0, 0, 4, 1, 1, 1); + AddDialogData (adj, &m_nLatchedTextureQuality, DLG_ADJ_INT); + + // scale + scale = gtk_hscale_new (GTK_ADJUSTMENT (adj)); + gtk_widget_show (scale); + gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0); + gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE); + + // text under the texture slider + hbox2 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox2); + gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0); + label = gtk_label_new (_("low")); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); + label = gtk_label_new (_("high")); + gtk_widget_show (label); + gtk_box_pack_end (GTK_BOX (hbox2), label, FALSE, FALSE, 0); + + // texture subsets + check = gtk_check_button_new_with_label (_("Texture subsets")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bTextureWindow, DLG_CHECK_BOOL); + + // texture scrollbar + check = gtk_check_button_new_with_label (_("Texture scrollbar")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bTextureScrollbar, DLG_CHECK_BOOL); + + // texture increment matches grid + check = gtk_check_button_new_with_label (_("Tex increment matches grid")); + gtk_widget_show (check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bSnapTToGrid, DLG_CHECK_BOOL); + + // RIANT + // Texture compression choice label + // container + table = gtk_table_new(2, 1, FALSE); + gtk_widget_show(table); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); + gtk_table_set_row_spacings (GTK_TABLE (table), 5); + gtk_table_set_col_spacings (GTK_TABLE (table), 5); + + label = gtk_label_new (_("Texture Compression (if available):")); + gtk_widget_show (label); + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + + // Texture compression choice label + combo_list = NULL; + // NONE will always be in pos 0 + combo_list = g_list_append (combo_list, (void *)_("None")); + + // if OpenGL compression is enabled it will always be + // in pos 1 + if (g_qeglobals.m_bOpenGLCompressionSupported) { - m_preferencesystem = &GetPreferenceSystem(); + combo_list = g_list_append (combo_list, (void *)_("OpenGL ARB")); } - PreferenceSystem* getTable() + + // If S3 is enabled offer all 3 valid compression schemes in RGBA + if (g_qeglobals.m_bS3CompressionSupported) { - return m_preferencesystem; + combo_list = g_list_append (combo_list, (void *)_("S3TC DXT1")); + combo_list = g_list_append (combo_list, (void *)_("S3TC DXT3")); + combo_list = g_list_append (combo_list, (void *)_("S3TC DXT5")); } -}; -#include "modulesystem/singletonmodule.h" -#include "modulesystem/moduleregistry.h" + combo = gtk_combo_new (); + gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list); + gtk_widget_show (combo); + gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE); + AddDialogData (combo, &m_nTextureCompressionFormat, DLG_COMBO_INT); + g_list_free (combo_list); + + // container + table = gtk_table_new(2, 1, FALSE); + gtk_widget_show(table); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); + gtk_table_set_row_spacings (GTK_TABLE (table), 5); + gtk_table_set_col_spacings (GTK_TABLE (table), 5); + + // Startup shaders + // label + label = gtk_label_new (_("Startup Shaders:")); + gtk_widget_show (label); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + + // combo list + combo_list = NULL; + combo_list = g_list_append (combo_list, (void *)_("None")); + if (g_pGameDescription->mGameFile == "jk2.game" || g_pGameDescription->mGameFile == "ja.game") + combo_list = g_list_append (combo_list, (void *)_("System")); + else if (g_pGameDescription->mGameFile == "sof2.game") + combo_list = g_list_append (combo_list, (void *)("Tools")); + else + combo_list = g_list_append (combo_list, (void *)_("Common")); + combo_list = g_list_append (combo_list, (void *)_("All")); + combo = gtk_combo_new (); + gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list); + gtk_widget_show (combo); + gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE); + AddDialogData (combo, &m_nLatchedShader, DLG_COMBO_INT); + g_list_free (combo_list); -typedef SingletonModule PreferenceSystemModule; -typedef Static StaticPreferenceSystemModule; -StaticRegisterModule staticRegisterPreferenceSystem(StaticPreferenceSystemModule::instance()); - -void Preferences_Load() -{ - g_GamesDialog.LoadPrefs(); + // Add the page to the notebook + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - globalOutputStream() << "loading local preferences from " << g_Preferences.m_inipath->str << "\n"; + /******** Layout group *********/ + preflabel = gtk_label_new(_("Layout")); + gtk_widget_show(preflabel); + pageframe = gtk_frame_new(_("Layout")); + gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); + gtk_widget_show(pageframe); + vbox = gtk_vbox_new(FALSE, 5); + gtk_widget_show(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(pageframe), vbox); - if(!Preferences_Load(g_preferences, g_Preferences.m_inipath->str)) + // View types + // table + table = gtk_table_new (2, 4, FALSE); + gtk_widget_show (table); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); + gtk_table_set_row_spacings (GTK_TABLE (table), 5); + gtk_table_set_col_spacings (GTK_TABLE (table), 5); + + // view type 1 + pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window1.bmp"); + gtk_widget_show (pixmap); + gtk_table_attach (GTK_TABLE (table), pixmap, 0, 1, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + // view type 2 + pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window2.bmp"); + gtk_widget_show (pixmap); + gtk_table_attach (GTK_TABLE (table), pixmap, 1, 2, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + // view type 3 + pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window3.bmp"); + gtk_widget_show (pixmap); + gtk_table_attach (GTK_TABLE (table), pixmap, 2, 3, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + // view type 4 + pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window4.bmp"); + gtk_widget_show (pixmap); + gtk_table_attach (GTK_TABLE (table), pixmap, 3, 4, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + // view type 1 selector + radio = gtk_radio_button_new (NULL); + gtk_widget_show (radio); + gtk_table_attach (GTK_TABLE (table), radio, 0, 1, 1, 2, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + // view type 2 selector + radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio)); + gtk_widget_show (radio); + gtk_table_attach (GTK_TABLE (table), radio, 1, 2, 1, 2, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + // view type 3 selector + radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio)); + gtk_widget_show (radio); + gtk_table_attach (GTK_TABLE (table), radio, 2, 3, 1, 2, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + // view type 4 selector + radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio)); + gtk_widget_show (radio); + gtk_table_attach (GTK_TABLE (table), radio, 3, 4, 1, 2, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + AddDialogData (radio, &m_nLatchedView, DLG_RADIO_INT); + + // Floating Z window + check = gtk_check_button_new_with_label (_("Floating Z Window")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bLatchedFloatingZ, DLG_CHECK_BOOL); + + // show menu tear-off seperators + check = gtk_check_button_new_with_label (_("Detachable Menus")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bLatchedDetachableMenus, DLG_CHECK_BOOL); + + if (!g_pGameDescription->mNoPatch) { - globalOutputStream() << "failed to load local preferences from " << g_Preferences.m_inipath->str << "\n"; + // show patch toolbar + check = gtk_check_button_new_with_label (_("Patch Toolbar")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + g_object_set_data (G_OBJECT (dialog), "check_patchtoolbar", check); // Allow to be disabled for Q1/Q2 + AddDialogData (check, &m_bLatchedPatchToolbar, DLG_CHECK_BOOL); } -} -void Preferences_Save() -{ - if (g_preferences_globals.disable_ini) - return; + // use wide toolbar + check = gtk_check_button_new_with_label (_("Wide Toolbar")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bLatchedWideToolbar, DLG_CHECK_BOOL); + + // use plugin toolbar + check = gtk_check_button_new_with_label (_("Plugin Toolbar")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bLatchedPluginToolbar, DLG_CHECK_BOOL); + +#ifdef _WIN32 + // win32 file dialog + check = gtk_check_button_new_with_label (_("Use win32 file load dialog")); + gtk_widget_show (check); + // gtk_container_add (GTK_CONTAINER (vbox), check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bNativeGUI, DLG_CHECK_BOOL); + + // position on primary monitor + check = gtk_check_button_new_with_label (_("Start on Primary Monitor")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + g_object_set_data (G_OBJECT (dialog), "check_startonprimary", check); + gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateSensitivity), this ); + AddDialogData (check, &m_bStartOnPrimMon, DLG_CHECK_BOOL); +#endif + + // Add the page to the notebook + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); + + /******** Mouse group *********/ + preflabel = gtk_label_new(_("Mouse")); + gtk_widget_show(preflabel); + pageframe = gtk_frame_new(_("Mouse")); + gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); + gtk_widget_show(pageframe); + vbox = gtk_vbox_new(FALSE, 5); + gtk_widget_show(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(pageframe), vbox); - g_GamesDialog.SavePrefs(); + // Buttons + // container + hbox2 = gtk_hbox_new (FALSE, 5); + gtk_widget_show (hbox2); + gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); + + // 2 button radio + radio = gtk_radio_button_new_with_label (NULL, _("2 button")); + gtk_widget_show (radio); + gtk_box_pack_start (GTK_BOX (hbox2), radio, FALSE, FALSE, 0); + + // 3 button radio + radio = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), _("3 button")); + gtk_widget_show (radio); + gtk_box_pack_start (GTK_BOX (hbox2), radio, FALSE, FALSE, 0); + AddDialogData (radio, &m_nMouse, DLG_RADIO_INT); + + // right click to drop entity + check = gtk_check_button_new_with_label (_("Right click to drop entities")); + gtk_widget_show (check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bRightClick, DLG_CHECK_BOOL); + + // Mouse chaser (and this does what?) + check = gtk_check_button_new_with_label (_("Mouse chaser")); + gtk_widget_show (check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bChaseMouse, DLG_CHECK_BOOL); + + // Alt + multi-drag + check = gtk_check_button_new_with_label (_("ALT + multi-drag")); + gtk_widget_show (check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bALTEdge, DLG_CHECK_BOOL); + + // Mouse wheel increments + // container + hbox2 = gtk_hbox_new (FALSE, 5); + gtk_widget_show (hbox2); + gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); + + // label + label = gtk_label_new (_("Wheel Mouse inc:")); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); + + // entry + entry = gtk_entry_new (); + gtk_widget_show (entry); + gtk_widget_set_usize (entry, 40, -2); + gtk_box_pack_start (GTK_BOX (hbox2), entry, FALSE, FALSE, 0); + AddDialogData (entry, &m_nWheelInc, DLG_ENTRY_INT); - globalOutputStream() << "saving local preferences to " << g_Preferences.m_inipath->str << "\n"; + // Add the page to the notebook + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); - if(!Preferences_Save_Safe(g_preferences, g_Preferences.m_inipath->str)) - { - globalOutputStream() << "failed to save local preferences to " << g_Preferences.m_inipath->str << "\n"; - } -} + /******** Editing group *********/ + preflabel = gtk_label_new(_("Editing")); + gtk_widget_show(preflabel); + pageframe = gtk_frame_new(_("Editing")); + gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); + gtk_widget_show(pageframe); + vbox = gtk_vbox_new(FALSE, 5); + gtk_widget_show(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(pageframe), vbox); -void Preferences_Reset() -{ - file_remove(g_Preferences.m_inipath->str); -} + // Vertex editing splits faces + check = gtk_check_button_new_with_label (_("Vertex editing splits face")); + gtk_widget_show (check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bVertexSplit, DLG_CHECK_BOOL); + + // Fix target/targetname collisions + check = gtk_check_button_new_with_label (_("Fix target/targetname collisions")); + gtk_widget_show (check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bDoTargetFix, DLG_CHECK_BOOL); + + // Clipper tool uses caulk + check = gtk_check_button_new_with_label (_("Clipper tool uses caulk")); + gtk_widget_show (check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bClipCaulk, DLG_CHECK_BOOL); + + // Don't clamp plane points + check = gtk_check_button_new_with_label (_("Don't clamp plane points")); + gtk_widget_show (check); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bNoClamp, DLG_CHECK_BOOL); + + // Select patch by bounding box + check = gtk_check_button_new_with_label (_("Select patches by bounding box")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bPatchBBoxSelect, DLG_CHECK_BOOL); + + // Rotation increment + // container + table = gtk_table_new (2, 3, FALSE); + gtk_widget_show (table); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); + gtk_table_set_row_spacings (GTK_TABLE (table), 5); + gtk_table_set_col_spacings (GTK_TABLE (table), 5); + + // label + label = gtk_label_new (_("Rotation increment:")); + gtk_widget_show (label); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + // entry + entry = gtk_entry_new (); + gtk_widget_show (entry); + gtk_widget_set_usize (entry, 60, -2); + gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + AddDialogData (entry, &m_nRotation, DLG_ENTRY_INT); + + // Undo levels + // label + label = gtk_label_new (_("Undo Levels:")); + gtk_widget_show (label); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + // spinner (allows undo levels to be set to zero) + spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (1, 0, 64, 1, 10, 10)), 1, 0); + gtk_widget_show (spin); + gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_widget_set_usize (spin, 60, -2); + AddDialogData (spin, &m_nUndoLevels, DLG_SPIN_INT); + + // Patch subdivisions + // label + label = gtk_label_new (_("Patch subdivisions:")); + gtk_widget_show (label); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + // entry (spinner perhaps? [2-16]) + entry = gtk_entry_new (); + gtk_widget_show (entry); + gtk_widget_set_usize (entry, 60, -2); + gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + AddDialogData (entry, &m_nSubdivisions, DLG_ENTRY_INT); + // Add the page to the notebook + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); -void PrefsDlg::PostModal (EMessageBoxReturn code) -{ - if (code == eIDOK) - { - Preferences_Save(); - UpdateAllWindows(); - } + /******** Save/Load group *********/ + preflabel = gtk_label_new(_("Startup/Auto save")); + gtk_widget_show(preflabel); + pageframe = gtk_frame_new(_("Startup/Auto save")); + gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); + gtk_widget_show(pageframe); + vbox = gtk_vbox_new(FALSE, 5); + gtk_widget_show(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(pageframe), vbox); + + // Snapshots + check = gtk_check_button_new_with_label (_("Snapshots")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bSnapShots, DLG_CHECK_BOOL); + + // load last project on open + check = gtk_check_button_new_with_label (_("Load last project on open")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bLoadLast, DLG_CHECK_BOOL); + + // load last map on open + check = gtk_check_button_new_with_label (_("Load last map on open")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bLoadLastMap, DLG_CHECK_BOOL); + + // Auto save.. + // container + hbox2 = gtk_hbox_new (FALSE, 5); + gtk_widget_show (hbox2); + gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox2), 0); + + // label + check = gtk_check_button_new_with_label (_("Auto save every")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (hbox2), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bAutoSave, DLG_CHECK_BOOL); + + // spinner + spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 60, 1, 10, 10)), 1, 0); + gtk_widget_show (spin); + gtk_box_pack_start (GTK_BOX (hbox2), spin, FALSE, FALSE, 0); + gtk_widget_set_usize (spin, 60, -2); + AddDialogData (spin, &m_nAutoSave, DLG_SPIN_INT); + + // label + label = gtk_label_new (_("minutes")); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); + + // Add the page to the notebook + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); + + /******** Paths group *********/ + preflabel = gtk_label_new(_("Paths")); + gtk_widget_show(preflabel); + pageframe = gtk_frame_new(_("Paths")); + gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); + gtk_widget_show(pageframe); + vbox = gtk_vbox_new(FALSE, 5); + gtk_widget_show(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(pageframe), vbox); + + // prefab path + // table + table = gtk_table_new (3, 3, FALSE); + gtk_widget_show (table); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); + gtk_table_set_row_spacings (GTK_TABLE (table), 5); + gtk_table_set_col_spacings (GTK_TABLE (table), 5); + + // label + label = gtk_label_new (_("Prefab path:")); + gtk_widget_show (label); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); + + // path entry + entry = gtk_entry_new (); + gtk_widget_show (entry); + gtk_widget_set_usize(GTK_WIDGET(entry), 240, -2); + gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 1, 0); + AddDialogData (entry, &m_strPrefabPath, DLG_ENTRY_TEXT); + +#if 0 + // browse button + button = gtk_button_new_with_label ("..."); + gtk_widget_show (button); + gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnBrowseprefab), this); + gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); +#endif + + // User ini path + // label + label = gtk_label_new (_("User INI path:")); + gtk_widget_show (label); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); + + // user ini path entry + entry = gtk_entry_new (); + gtk_widget_show (entry); + gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 1, 0); + AddDialogData (entry, &m_strUserPath, DLG_ENTRY_TEXT); + + // user ini browse button + button = gtk_button_new_with_label ("..."); + gtk_widget_show (button); + gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnBrowseuserini), this); + gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + // Add the page to the notebook + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); + + /******** Misc group *********/ + preflabel = gtk_label_new(_("Misc")); + gtk_widget_show(preflabel); + pageframe = gtk_frame_new(_("Misc")); + gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); + gtk_widget_show(pageframe); + vbox = gtk_vbox_new(FALSE, 5); + gtk_widget_show(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(pageframe), vbox); + + // Light drawing + check = gtk_check_button_new_with_label (_("Light drawing")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &m_bNewLightDraw, DLG_CHECK_BOOL); + + // Light radiuses + // container + table = gtk_table_new(2, 1, FALSE); + gtk_widget_show(table); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); + gtk_table_set_row_spacings (GTK_TABLE (table), 5); + gtk_table_set_col_spacings (GTK_TABLE (table), 5); + + label = gtk_label_new (_("Light radiuses:")); + gtk_widget_show (label); + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + + combo_list = NULL; + combo_list = g_list_append (combo_list, (void *)_("Disabled")); + combo_list = g_list_append (combo_list, (void *)_("True Q3Map2 Style")); + combo_list = g_list_append (combo_list, (void *)_("Classic Style")); + + combo = gtk_combo_new (); + gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list); + gtk_widget_show (combo); + gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE); + AddDialogData (combo, &m_nLightRadiuses, DLG_COMBO_INT); + +#ifdef _WIN32 + check = gtk_check_button_new_with_label (_("Use win32 file associations to open text files instead of builtin editor")); + gtk_widget_show(check); + gtk_box_pack_start(GTK_BOX (vbox), check, FALSE, FALSE, 0); + AddDialogData (check, &g_PrefsDlg.m_bUseWin32Editor, DLG_CHECK_BOOL); +#else + // use custom shader editor + check = gtk_check_button_new_with_label (_("Use Custom Shader Editor")); + gtk_widget_show(check); + gtk_box_pack_start(GTK_BOX (vbox), check, FALSE, FALSE, 0); + gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateEditorSensitivity), this); + g_object_set_data (G_OBJECT(dialog), "check_customeditor", check); + AddDialogData (check, &g_PrefsDlg.m_bUseCustomEditor, DLG_CHECK_BOOL); + + // custom shader editor executable + // table + table = gtk_table_new (3, 1, FALSE); + gtk_widget_show (table); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0); + gtk_table_set_row_spacings (GTK_TABLE (table), 5); + gtk_table_set_col_spacings (GTK_TABLE (table), 5); + + // label + label = gtk_label_new(_("Custom Editor Command")); + gtk_widget_show(label); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); + g_object_set_data (G_OBJECT(dialog), "label_customeditor", label); + gtk_widget_set_sensitive (label, g_PrefsDlg.m_bUseCustomEditor); + + // custom editor command entry + entry = gtk_entry_new (); + gtk_widget_show (entry); + gtk_widget_set_usize(GTK_WIDGET(entry), 240, -2); + gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 1, 0); + AddDialogData (entry, &m_strEditorCommand, DLG_ENTRY_TEXT); + gtk_widget_set_sensitive (entry, g_PrefsDlg.m_bUseCustomEditor); + g_object_set_data (G_OBJECT(dialog), "entry_customeditor", entry); + + // browse button + button = gtk_button_new_with_label (_("...")); + gtk_widget_show (button); + gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnBrowseEditor), this); + gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + g_object_set_data (G_OBJECT(dialog), "button_customeditor", button); + gtk_widget_set_sensitive (button, g_PrefsDlg.m_bUseCustomEditor); +#endif + + // Add the page to the notebook + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); + + /******** BSP Monitoring group *********/ + // this is never displayed if the plugin isn't available + preflabel = gtk_label_new(_("BSP Monitoring")); + gtk_widget_show(preflabel); + pageframe = gtk_frame_new(_("BSP Monitoring")); + gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5); + gtk_widget_show(pageframe); + vbox = gtk_vbox_new(FALSE, 5); + gtk_widget_show(vbox); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); + gtk_container_add(GTK_CONTAINER(pageframe), vbox); + + // Enable BSP process monitoring + check = gtk_check_button_new_with_label (_("Enable BSP process monitoring")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + g_object_set_data (G_OBJECT (dialog), "check_monitorbsp", check); + gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateSensitivity), this ); + AddDialogData (check, &g_PrefsDlg.m_bWatchBSP, DLG_CHECK_BOOL); + + // Stop on leak + check = gtk_check_button_new_with_label (_("Stop compilation on leak")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + g_object_set_data (G_OBJECT (dialog), "check_leakstop", check); + AddDialogData (check, &g_PrefsDlg.m_bLeakStop, DLG_CHECK_BOOL); + + // engine after compile + check = gtk_check_button_new_with_label (_("Run engine after compile")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + g_object_set_data (G_OBJECT (dialog), "check_runengine", check); + gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateSensitivity), this ); + AddDialogData( check, &g_PrefsDlg.m_bRunQuake, DLG_CHECK_BOOL ); + + // sleep mode when running engine + check = gtk_check_button_new_with_label (_("Activate sleep mode when running the engine")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + g_object_set_data (G_OBJECT (dialog), "check_sleep", check); + AddDialogData( check, &g_PrefsDlg.m_bDoSleep, DLG_CHECK_BOOL ); + + // use q3map2's texture projection + check = gtk_check_button_new_with_label (_("Texturing compatible with q3map2")); + gtk_widget_show (check); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + g_object_set_data (G_OBJECT (dialog), "check_q3map2", check); + AddDialogData( check, &g_PrefsDlg.m_bQ3Map2Texturing, DLG_CHECK_BOOL ); + + // Add the page to the notebook + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel); + + gtk_notebook_set_page(GTK_NOTEBOOK(notebook), PTAB_FRONT); + + return; } -std::vector g_restart_required; +// end new prefs dialog -void PreferencesDialog_restartRequired(const char* staticName) +void PrefsDlg::LoadTexdefPref(texdef_t* pTexdef, char* pName) { - g_restart_required.push_back(staticName); + char buffer[256]; + + memset(pTexdef, 0, sizeof(texdef_t)); + + sprintf(buffer, "%s%s", pName, TD_SCALE1_KEY); + mLocalPrefs.GetPref(buffer, &pTexdef->scale[0], 0.5f); + + sprintf(buffer, "%s%s", pName, TD_SCALE2_KEY); + mLocalPrefs.GetPref(buffer, &pTexdef->scale[1], 0.5f); + + sprintf(buffer, "%s%s", pName, TD_SHIFT1_KEY); + mLocalPrefs.GetPref(buffer, &pTexdef->shift[0], 8.f); + + sprintf(buffer, "%s%s", pName, TD_SHIFT2_KEY); + mLocalPrefs.GetPref(buffer, &pTexdef->shift[1], 8.f); + + sprintf(buffer, "%s%s", pName, TD_ROTATE_KEY); + mLocalPrefs.GetPref(buffer, &pTexdef->rotate, 45); } -void PreferencesDialog_showDialog() +void PrefsDlg::UpdateTextureCompression() { - if(ConfirmModified("Edit Preferences") && g_Preferences.DoModal() == eIDOK) + // if OpenGL is not ready yet, don't do anything + if (!g_qeglobals.m_bOpenGLReady) { + Sys_Printf("OpenGL not ready - postpone texture compression capability check\n"); + return; + } + + if (g_qeglobals.bTextureCompressionSupported) { - if(!g_restart_required.empty()) + if (m_nTextureCompressionFormat >= 2 && !g_qeglobals.m_bS3CompressionSupported) { - StringOutputStream message(256); - message << "Preference changes require a restart:\n"; - for(std::vector::iterator i = g_restart_required.begin(); i != g_restart_required.end(); ++i) + Sys_Printf("Inconsistant pref setting for texture compression (%d), rolling back\n", m_nTextureCompressionFormat); + m_nTextureCompressionFormat = 1; // if this is not supported either, see below + } + if (m_nTextureCompressionFormat == 1 && !g_qeglobals.m_bOpenGLCompressionSupported) + { + Sys_Printf("Inconsistant pref setting for texture compression (GL_COMPRESSED_RGBA), rolling back\n"); + m_nTextureCompressionFormat = 0; + } + switch (m_nTextureCompressionFormat) + { + case (0): { - message << (*i) << '\n'; + g_qeglobals.texture_components = GL_RGBA; + Sys_Printf("texture compression disabled by preferences settings\n"); + break; + } + case (1): + { + g_qeglobals.texture_components = GL_COMPRESSED_RGBA; + Sys_Printf("OpenGL texture compression enabled\n"); + break; + } + case (2): + { + g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + Sys_Printf("S3TC DXT1 texture compression enabled\n"); + break; + } + case (3): + { + g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + Sys_Printf("S3TC DXT3 texture compression enabled\n"); + break; + } + case (4): + { + g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + Sys_Printf("S3TC DXT5 texture compression enabled\n"); + break; } - gtk_MessageBox(GTK_WIDGET(MainFrame_getWindow()), message.c_str()); - g_restart_required.clear(); } } + else + { + Sys_Printf("texture compression is not supported by your current graphic card/drivers\n"); + g_qeglobals.texture_components = GL_RGBA; + m_nTextureCompressionFormat = 0; + } +} + +#ifdef ATIHACK_812 +void PrefsDlg::UpdateATIHack() { + // if OpenGL is not ready yet, don't do anything + if (!g_qeglobals.m_bOpenGLReady) { + Sys_Printf("OpenGL not ready - postpone ATI bug workaround setup\n"); + return; + } + + if (m_bGlATIHack) { + qglCullFace = &qglCullFace_ATIHack; + qglDisable = &qglDisable_ATIHack; + qglEnable = &qglEnable_ATIHack; + qglPolygonMode = &qglPolygonMode_ATIHack; + Sys_Printf("ATI bug workaround enabled\n"); + } else { + qglCullFace = qglCullFace_real; + qglDisable = qglDisable_real; + qglEnable = qglEnable_real; + qglPolygonMode = qglPolygonMode_real; + Sys_Printf("ATI bug workaround disabled\n"); + } } +#endif + +// TTimo: m_strEnginePath has a special status, if not found in registry we need to +// initiliaze it for sure. It is not totally failsafe but we can use the same +// code than in q3map, expecting to find some "quake" above us. If not, we prompt +// for the engine executable path +void PrefsDlg::LoadPrefs () +{ + int i; + + // first things first, load prefs from global prefs + mGamesDialog.LoadPrefs(); + + // if we already have a document loaded, we will free and reload from file + if (mLocalPrefs.InUse()) { + mLocalPrefs.Clear(); + } + + // load local.pref file + mLocalPrefs.ReadXMLFile(m_inipath->str); + + mLocalPrefs.GetPref(PATCHSHOWBOUNDS_KEY, &g_bPatchShowBounds, FALSE); + mLocalPrefs.GetPref(MOUSE_KEY, &m_nMouse, MOUSE_DEF); + m_nMouseButtons = m_nMouse ? 3 : 2; + + // project file + // if it's not found here, mainframe.cpp will take care of finding one + mLocalPrefs.GetPref(LASTPROJ_KEY, &m_strLastProject, ""); + mLocalPrefs.GetPref(LASTPROJVER_KEY, &m_nLastProjectVer, -1); + + // prefab path + // NOTE TTimo: I'm not sure why this is in prefs + // should probably be a project setting + // and I'm not sure that we really have a way to set this reliably either + CString strPrefab; + strPrefab = g_qeglobals.m_strHomeGame.GetBuffer(); + strPrefab += g_pGameDescription->mBaseGame.GetBuffer(); + strPrefab += "/prefabs/"; + mLocalPrefs.GetPref(PREFAB_KEY, &m_strPrefabPath, strPrefab); + + mLocalPrefs.GetPref(LASTLIGHTINTENSITY_KEY, &m_iLastLightIntensity, 300); + mLocalPrefs.GetPref(TLOCK_KEY, &m_bTextureLock, TLOCK_DEF); + mLocalPrefs.GetPref(RLOCK_KEY, &m_bRotateLock, TLOCK_DEF); + mLocalPrefs.GetPref(LASTMAP_KEY, &m_strLastMap, ""); + mLocalPrefs.GetPref(LOADLAST_KEY, &m_bLoadLast, LOADLAST_DEF); + mLocalPrefs.GetPref(BSP_KEY, &m_bInternalBSP, FALSE); + mLocalPrefs.GetPref(RCLICK_KEY, &m_bRightClick, TRUE); + mLocalPrefs.GetPref(AUTOSAVE_KEY, &m_bAutoSave, TRUE); + mLocalPrefs.GetPref(LOADLASTMAP_KEY, &m_bLoadLastMap, FALSE); + mLocalPrefs.GetPref(TINYBRUSH_KEY, &m_bCleanTiny, FALSE); + mLocalPrefs.GetPref(TINYSIZE_KEY, &m_fTinySize, 0.5f); + mLocalPrefs.GetPref(AUTOSAVETIME_KEY, &m_nAutoSave, 5); + mLocalPrefs.GetPref(SNAPSHOT_KEY, &m_bSnapShots, FALSE); + mLocalPrefs.GetPref(MOVESPEED_KEY, &m_nMoveSpeed, 100); + mLocalPrefs.GetPref(ANGLESPEED_KEY, &m_nAngleSpeed, 3); + mLocalPrefs.GetPref(SETGAME_KEY, &m_bSetGame, FALSE); + mLocalPrefs.GetPref(CAMXYUPDATE_KEY, &m_bCamXYUpdate, TRUE); + mLocalPrefs.GetPref(CAMDRAGMULTISELECT_KEY, &m_nCamDragMultiSelect, TRUE); + mLocalPrefs.GetPref(CAMFREELOOK_KEY, &m_bCamFreeLook, TRUE); + mLocalPrefs.GetPref(CAMINVERSEMOUSE_KEY, &m_bCamInverseMouse, FALSE); + mLocalPrefs.GetPref(CAMDISCRETE_KEY, &m_bCamDiscrete, TRUE); + mLocalPrefs.GetPref(LIGHTDRAW_KEY, &m_bNewLightDraw, TRUE); + mLocalPrefs.GetPref(CUBICCLIP_KEY, &m_bCubicClipping, TRUE); + mLocalPrefs.GetPref(CUBICSCALE_KEY, &m_nCubicScale, 13); + mLocalPrefs.GetPref(ALTEDGE_KEY, &m_bALTEdge, FALSE); + mLocalPrefs.GetPref(FACECOLORS_KEY, &m_bFaceColors, FALSE); + mLocalPrefs.GetPref(XZVIS_KEY, &m_bXZVis, FALSE); + mLocalPrefs.GetPref(YZVIS_KEY, &m_bYZVis, FALSE); + mLocalPrefs.GetPref(ZVIS_KEY, &m_bZVis, FALSE); + mLocalPrefs.GetPref(SIZEPAINT_KEY, &m_bSizePaint, FALSE); + mLocalPrefs.GetPref(DLLENTITIES_KEY, &m_bDLLEntities, FALSE); + + mLocalPrefs.GetPref(DETACHABLEMENUS_KEY, &m_bLatchedDetachableMenus, TRUE); + m_bDetachableMenus = m_bLatchedDetachableMenus; + + if (g_pGameDescription->mNoPatch) + { + m_bPatchToolbar = false; + } + else + { + mLocalPrefs.GetPref(PATCHTOOLBAR_KEY, &m_bLatchedPatchToolbar, TRUE); + m_bPatchToolbar = m_bLatchedPatchToolbar; + } + mLocalPrefs.GetPref(WIDETOOLBAR_KEY, &m_bLatchedWideToolbar, TRUE); + m_bWideToolbar = m_bLatchedWideToolbar; + mLocalPrefs.GetPref(PLUGINTOOLBAR_KEY, &m_bLatchedPluginToolbar, TRUE); + m_bPluginToolbar = m_bLatchedPluginToolbar; + mLocalPrefs.GetPref(WINDOW_KEY, (int*)&m_nLatchedView, WINDOW_DEF); + m_nView = m_nLatchedView; + mLocalPrefs.GetPref(FLOATINGZ_KEY, &m_bLatchedFloatingZ, FALSE); + m_bFloatingZ = m_bLatchedFloatingZ; -void GameName_importString(const char* value) -{ - gamename_set(value); + mLocalPrefs.GetPref(TEXTUREQUALITY_KEY, &m_nLatchedTextureQuality, 3); + m_nTextureQuality = m_nLatchedTextureQuality; + + mLocalPrefs.GetPref(LOADSHADERS_KEY, &m_nLatchedShader, 0); + m_nShader = m_nLatchedShader; + + mLocalPrefs.GetPref(NOCLAMP_KEY, &m_bNoClamp, FALSE); + mLocalPrefs.GetPref(USERINI_KEY, &m_strUserPath, ""); + mLocalPrefs.GetPref(ROTATION_KEY, &m_nRotation, 45); + mLocalPrefs.GetPref(CHASEMOUSE_KEY, &m_bChaseMouse, TRUE); + mLocalPrefs.GetPref(ENTITYSHOW_KEY, &m_nEntityShowState, ENTITY_SKINNED_BOXED); + + // this will probably need to be 75 or 100 for Q1. + mLocalPrefs.GetPref(TEXTURESCALE_KEY, &m_nTextureScale, 50); + + // FIXME: Hydra - actually, this stuff is Q1,Q2 and HL specific. + if ( (g_pGameDescription->mGameFile == "hl.game") ) + { + // No BSP monitoring in the default compiler tools for Half-life (yet) + mLocalPrefs.GetPref(WATCHBSP_KEY, &m_bWatchBSP, FALSE); + + // Texture subset on by default (HL specific really, because of halflife.wad's size) + mLocalPrefs.GetPref(TEXTURE_KEY, &m_bTextureWindow, TRUE); + } + else if (g_pGameDescription->quake2 || ( g_pGameDescription->mGameFile == "q2.game" ) || ( g_pGameDescription->mGameFile == "heretic2.game" )) + { + // BSP monitoring is implemented in Quake2 and Heretic2 tools + mLocalPrefs.GetPref(WATCHBSP_KEY, &m_bWatchBSP, TRUE); + + // Texture subset on by default (HL specific really, because of halflife.wad's size) + mLocalPrefs.GetPref(TEXTURE_KEY, &m_bTextureWindow, TRUE); + } + else + { + mLocalPrefs.GetPref(WATCHBSP_KEY, &m_bWatchBSP, WATCHBSP_DEF); + mLocalPrefs.GetPref(TEXTURE_KEY, &m_bTextureWindow, FALSE); + } + + + mLocalPrefs.GetPref(TEXTURESCROLLBAR_KEY, &m_bTextureScrollbar, TRUE); + mLocalPrefs.GetPref(DISPLAYLISTS_KEY, &m_bDisplayLists, TRUE); + mLocalPrefs.GetPref(ANTIALIASEDLINES_KEY, &m_bAntialiasedPointsAndLines, FALSE); + mLocalPrefs.GetPref(SWITCHCLIP_KEY, &m_bSwitchClip, TRUE); + mLocalPrefs.GetPref(SELWHOLEENTS_KEY, &m_bSelectWholeEntities, TRUE); + mLocalPrefs.GetPref(SHOWSHADERS_KEY, &m_bShowShaders, TRUE); + mLocalPrefs.GetPref(GLLIGHTING_KEY, &m_bGLLighting, FALSE); + mLocalPrefs.GetPref(NOSTIPPLE_KEY, &m_bNoStipple, FALSE); + mLocalPrefs.GetPref(UNDOLEVELS_KEY, &m_nUndoLevels, 30); + mLocalPrefs.GetPref(VERTEXMODE_KEY, &m_bVertexSplit, TRUE); + mLocalPrefs.GetPref(RUNQ2_KEY, &m_bRunQuake, RUNQ2_DEF); + mLocalPrefs.GetPref(LEAKSTOP_KEY, &m_bLeakStop, TRUE); + mLocalPrefs.GetPref(DOSLEEP_KEY, &m_bDoSleep, FALSE); + mLocalPrefs.GetPref(SELECTCURVES_KEY, &m_bSelectCurves, TRUE); + mLocalPrefs.GetPref(SELECTMODELS_KEY, &m_bSelectModels, TRUE); + mLocalPrefs.GetPref(SHADERLISTONLY_KEY, &m_bTexturesShaderlistOnly, FALSE); + mLocalPrefs.GetPref(SUBDIVISIONS_KEY, &m_nSubdivisions, SUBDIVISIONS_DEF); + mLocalPrefs.GetPref(CLIPCAULK_KEY, &m_bClipCaulk, FALSE); + mLocalPrefs.GetPref(SNAPTTOGRID_KEY, &m_bSnapTToGrid, FALSE); + mLocalPrefs.GetPref(TARGETFIX_KEY, &m_bDoTargetFix, TRUE); + mLocalPrefs.GetPref(WHEELINC_KEY, &m_nWheelInc, 64); + mLocalPrefs.GetPref(PATCHBBOXSEL_KEY, &m_bPatchBBoxSelect, FALSE); + + // Gef: Kyro GL_POINT workaround + mLocalPrefs.GetPref(GLPOINTWORKAROUND_KEY, &m_bGlPtWorkaround, FALSE); + + // window positioning + mLocalPrefs.GetPref(ENTITYSPLIT1_KEY, &mWindowInfo.nEntitySplit1, -1); + mLocalPrefs.GetPref(ENTITYSPLIT2_KEY, &mWindowInfo.nEntitySplit2, -1); + + mLocalPrefs.GetPref(POSITIONX_KEY, &mWindowInfo.position.x, -1); + mLocalPrefs.GetPref(POSITIONY_KEY, &mWindowInfo.position.y, -1); + mLocalPrefs.GetPref(WIDTH_KEY, &mWindowInfo.position.w, -1); + mLocalPrefs.GetPref(HEIGHT_KEY, &mWindowInfo.position.h, 450); + + const window_position_t default_window_pos = { 0, 0, 200, 200, }; + + mLocalPrefs.GetPref(ENTITYWND_KEY, &mWindowInfo.posEntityWnd, default_window_pos); + mLocalPrefs.GetPref(MAPINFOWND_KEY, &mWindowInfo.posMapInfoWnd, default_window_pos); + mLocalPrefs.GetPref(CAMWND_KEY, &mWindowInfo.posCamWnd, default_window_pos); + mLocalPrefs.GetPref(ZWND_KEY, &mWindowInfo.posZWnd, default_window_pos); + mLocalPrefs.GetPref(XYWND_KEY, &mWindowInfo.posXYWnd, default_window_pos); + mLocalPrefs.GetPref(YZWND_KEY, &mWindowInfo.posYZWnd, default_window_pos); + mLocalPrefs.GetPref(XZWND_KEY, &mWindowInfo.posXZWnd, default_window_pos); + mLocalPrefs.GetPref(PATCHWND_KEY, &mWindowInfo.posPatchWnd, default_window_pos); + mLocalPrefs.GetPref(SURFACEWND_KEY, &mWindowInfo.posSurfaceWnd, default_window_pos); + mLocalPrefs.GetPref(ENTITYINFOWND_KEY, &mWindowInfo.posEntityInfoWnd, default_window_pos); + + mLocalPrefs.GetPref(ZWIDTH_KEY, &mWindowInfo.nZWidth, 30); + mLocalPrefs.GetPref(XYHEIGHT_KEY, &mWindowInfo.nXYHeight, 300); + mLocalPrefs.GetPref(XYWIDTH_KEY, &mWindowInfo.nXYWidth, 300); + mLocalPrefs.GetPref(CAMWIDTH_KEY, &mWindowInfo.nCamWidth, 200); + mLocalPrefs.GetPref(CAMHEIGHT_KEY, &mWindowInfo.nCamHeight, 200); + mLocalPrefs.GetPref(ZFLOATWIDTH_KEY, &mWindowInfo.nZFloatWidth, 300); +#ifdef _WIN32 + mLocalPrefs.GetPref(STATE_KEY, &mWindowInfo.nState, SW_SHOW); +#endif + + // menu stuff + mLocalPrefs.GetPref(COUNT_KEY, &m_nMRUCount, 0); + for(i = 0; i < 4; i++) + { + char buf[64]; + sprintf (buf, "%s%d", FILE_KEY, i); + mLocalPrefs.GetPref(buf, &m_strMRUFiles[i], ""); + } + + // some platform specific prefs +#ifdef _WIN32 + mLocalPrefs.GetPref(NATIVEGUI_KEY, &m_bNativeGUI, TRUE); + mLocalPrefs.GetPref(STARTONPRIMMON_KEY, &m_bStartOnPrimMon, FALSE); +#endif + + mLocalPrefs.GetPref(SI_TEXMENU_KEY, &g_qeglobals.d_savedinfo.iTexMenu, ID_VIEW_BILINEARMIPMAP); + mLocalPrefs.GetPref(SI_GAMMA_KEY, &g_qeglobals.d_savedinfo.fGamma, 1.0f); + mLocalPrefs.GetPref(SI_EXCLUDE_KEY, &g_qeglobals.d_savedinfo.exclude, 0); // nothing filtered by default + mLocalPrefs.GetPref(SI_INCLUDE_KEY, &g_qeglobals.d_savedinfo.include, INCLUDE_NAMES | INCLUDE_COORDS | INCLUDE_ANGLES | INCLUDE_CAMERATINT); + mLocalPrefs.GetPref(SI_SHOWNAMES_KEY, &g_qeglobals.d_savedinfo.show_names, FALSE); + mLocalPrefs.GetPref(SI_SHOWCOORDS_KEY, &g_qeglobals.d_savedinfo.show_coordinates, TRUE); + mLocalPrefs.GetPref(SI_SHOWANGLES_KEY, &g_qeglobals.d_savedinfo.show_angles, TRUE); + mLocalPrefs.GetPref(SI_SHOWOUTLINES_KEY, &g_qeglobals.d_savedinfo.show_outline, FALSE); + mLocalPrefs.GetPref(SI_SHOWAXIS_KEY, &g_qeglobals.d_savedinfo.show_axis, TRUE); + mLocalPrefs.GetPref(SI_NOSELOUTLINES_KEY, &g_qeglobals.d_savedinfo.bNoSelectedOutlines, FALSE); + + mLocalPrefs.GetPref(SI_OUTLINESTYLE_KEY, &g_qeglobals.d_savedinfo.iSelectedOutlinesStyle, OUTLINE_ZBUF|OUTLINE_BSEL); + + LoadTexdefPref(&g_qeglobals.d_savedinfo.m_SIIncrement, SI_SURFACE_TEXDEF_KEY); + LoadTexdefPref(&g_qeglobals.d_savedinfo.m_PIIncrement, SI_PATCH_TEXDEF_KEY); + + // text editor binding +#ifdef _WIN32 + mLocalPrefs.GetPref(CUSTOMSHADEREDITOR_KEY, &m_bUseWin32Editor, TRUE); +#else + mLocalPrefs.GetPref(CUSTOMSHADEREDITOR_KEY, &m_bUseCustomEditor, FALSE); + mLocalPrefs.GetPref(CUSTOMSHADEREDITORCOMMAND_KEY, &m_strEditorCommand, ""); +#endif + + + vec3_t vDefaultAxisColours[3] = { + {0.f, 0.5f, 0.f}, + {0.f, 0.f, 1.f}, + {1.f, 0.f, 0.f}, + }; + + for(i = 0; i < 3; i++) { + char buf[64]; + sprintf(buf, "%s%d", SI_AXISCOLORS_KEY, i); + mLocalPrefs.GetPref(buf, g_qeglobals.d_savedinfo.AxisColors[i], vDefaultAxisColours[i]); + } + + vec3_t vDefaultColours[COLOR_LAST] = { + {0.25f, 0.25f, 0.25f}, + {1.f, 1.f, 1.f}, + {0.75f, 0.75f, 0.75f}, + {0.5f, 0.5f, 0.5f}, + {0.25f, 0.25f, 0.25f}, + {0.0f, 0.0f, 0.0f}, + {0.f, 0.f, 1.f}, + {0.f, 0.f, 0.f}, + {0.f, 0.f, 0.f}, + {1.f, 0.f, 0.f}, + {0.f, 0.f, 1.f}, + {0.5f, 0.f, 0.75f}, + {1.0f, 0.f, 0.f}, + {0.f, 0.f, 0.f}, + {0.f, 0.f, 0.f}, + }; + + for(i = 0; i < COLOR_LAST; i++) { + char buf[64]; + sprintf(buf, "%s%d", SI_COLORS_KEY, i); + mLocalPrefs.GetPref(buf, g_qeglobals.d_savedinfo.colors[i], vDefaultColours[i]); + } + + mLocalPrefs.GetPref(TEXTURECOMPRESSIONFORMAT_KEY, &m_nTextureCompressionFormat, 1); + + mLocalPrefs.GetPref(LIGHTRADIUS_KEY, &m_nLightRadiuses, TRUE); + + mLocalPrefs.GetPref(Q3MAP2TEX_KEY, &m_bQ3Map2Texturing, TRUE); + +#ifdef ATIHACK_812 + mLocalPrefs.GetPref(ATIHACK_KEY, &m_bGlATIHack, FALSE); +#endif + + Undo_SetMaxSize(m_nUndoLevels); // set it internally as well / FIXME: why not just have one global value? + + UpdateTextureCompression(); + +#ifdef ATIHACK_812 + UpdateATIHack(); +#endif + + if (mLocalPrefs.mbEmpty) + { + mLocalPrefs.mbEmpty = false; + Sys_Printf("Saving local.pref with default pref values\n"); + SavePrefs(); + } } -typedef FreeCaller1 GameNameImportStringCaller; -void GameName_exportString(const StringImportCallback& importer) + +void PrefsDlg::SavePrefs () { - importer(gamename_get()); + if (g_qeglobals.disable_ini) + return; + +#ifdef _DEBUG + Sys_Printf("PrefsDlg::SavePrefs\n"); +#endif + + // this will take care of copying back from the dialog to the variables + // NOTE: it may be overkill to call systematically before a SavePrefs, but it's safer + // this will also cause an UpdateData for the mGamesDialog + UpdateData(TRUE); + + mGamesDialog.SavePrefs(); + + // update the tree and save it + mLocalPrefs.UpdatePrefTree(); + 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; + } + } -typedef FreeCaller1 GameNameExportStringCaller; -void GameMode_importString(const char* value) +void PrefsDlg::PostModal (int code) { - gamemode_set(value); + if (code == IDOK) + { + SavePrefs(); + // make sure the logfile is ok + Sys_LogFile(); + #ifdef ATIHACK_812 + UpdateATIHack(); + #endif + if (g_pParentWnd) + g_pParentWnd->SetGridStatus(); + Sys_UpdateWindows(W_ALL); + if (m_nUndoLevels != 0) + Undo_SetMaxSize(m_nUndoLevels); + } } -typedef FreeCaller1 GameModeImportStringCaller; -void GameMode_exportString(const StringImportCallback& importer) + +void PrefsDlg::DoEditorSensitivity() { - importer(gamemode_get()); + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_object_get_data (G_OBJECT(m_pWidget), "check_customeditor")))) + { + gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "label_customeditor")), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "entry_customeditor")), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "button_customeditor")), TRUE); + } + else + { + gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "label_customeditor")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "entry_customeditor")), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "button_customeditor")), FALSE); + } } -typedef FreeCaller1 GameModeExportStringCaller; - -void RegisterPreferences(PreferenceSystem& preferences) +void PrefsDlg::DoSensitivity() { +#if 0 + // first, look at the project file version ... will monitoring work? + // project files now XML, guaranteed to be at least version 2 + if (0)//IntForKey( g_qeglobals.d_project_entity, "version" ) < 2) + { + if (m_bWarn) + { + Str Msg; + Msg = "The current project file ("; + Msg += g_PrefsDlg.m_strLastProject; + Msg += ") is not at least version 2.\nI need version 2 or above to setup BSP monitoring correctly."; + gtk_MessageBox(m_pWidget, Msg.GetBuffer(), MB_OK ); + + m_bWarn = false; + } -#ifdef WIN32 - preferences.registerPreference("NativeGUI", BoolImportStringCaller(g_FileChooser_nativeGUI), BoolExportStringCaller(g_FileChooser_nativeGUI)); + // go ahead, disable everybuddy + gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_leakstop" )), FALSE ); + gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_monitorbsp" )), FALSE ); + gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" )), FALSE ); + gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), FALSE ); + } + else + { #endif +// m_bWarn = true; + gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_leakstop" )), TRUE ); + gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_monitorbsp" )), TRUE ); + gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" )), TRUE ); + gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), TRUE ); -#ifdef WIN32 - preferences.registerPreference("UseCustomShaderEditor", BoolImportStringCaller(g_TextEditor_useWin32Editor), BoolExportStringCaller(g_TextEditor_useWin32Editor)); -#else - preferences.registerPreference("UseCustomShaderEditor", BoolImportStringCaller(g_TextEditor_useCustomEditor), BoolExportStringCaller(g_TextEditor_useCustomEditor)); - preferences.registerPreference("CustomShaderEditorCommand", CopiedStringImportStringCaller(g_TextEditor_editorCommand), CopiedStringExportStringCaller(g_TextEditor_editorCommand)); + if ( ! gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT(m_pWidget), "check_monitorbsp" ) ) ) ) + { + gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_leakstop" )), FALSE ); + gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" )), FALSE ); + gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), FALSE ); + } else if (! gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" ) ) ) ) + { + 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( 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( 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; + case GAME_TREMULOUS: + gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), _("Tremulous") ); + 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 - preferences.registerPreference("GameName", GameNameImportStringCaller(), GameNameExportStringCaller()); - preferences.registerPreference("GameMode", GameModeImportStringCaller(), GameModeExportStringCaller()); + 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, "\n\n" ); + fclose( fg ); } -void Preferences_Init() -{ - RegisterPreferences(GetPreferenceSystem()); +/* +=============== +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; + } + if ( stricmp( dirname, TREMULOUS_PACK ) == 0 ) { + m_availGames[ iGame++ ] = GAME_TREMULOUS; + } + } } +