]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/preferences.cpp
* fixed a lot of compiler warnings (mostly const char * stuff and use of uninitialize...
[xonotic/netradiant.git] / radiant / preferences.cpp
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 //
23 // User preferences
24 //
25 // Leonardo Zide (leo@lokigames.com)
26 //
27
28 #include "stdafx.h"
29 #include <glib.h>
30 #include <assert.h>
31 #if defined (__linux__) || defined (__APPLE__)
32 #include <sys/stat.h>
33 #include <sys/types.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <dirent.h>
37 #endif
38 #include "missing.h"
39 #include "gtkmisc.h"
40
41 #ifdef _WIN32
42 #include <io.h>
43 #define X_OK 0
44 #include <sys/stat.h>
45 #endif
46
47 #define PREF_SECTION            "Prefs"
48 #define INTERNAL_SECTION        "Internals"
49 #define MOUSE_KEY               "MouseButtons"
50 #define WINDOW_KEY              "QE4StyleWindows"
51 #define LAYOUT_KEY              "WindowLayout"
52 #define RUNQ2_KEY               "RunQuake2Run"
53 #define TLOCK_KEY               "TextureLock"
54 #define RLOCK_KEY               "RotateLock"
55 #define LOADLAST_KEY            "LoadLast"
56 #define LOADLASTMAP_KEY         "LoadLastMap"
57 #define LASTPROJ_KEY            "LastProject"
58 #define LASTPROJVER_KEY         "LastProjectKey"
59 #define LASTMAP_KEY             "LastMap"
60 #define FACE_KEY                "NewFaceGrab"
61 #define BSP_KEY                 "InternalBSP"
62 #define RCLICK_KEY              "NewRightClick"
63 #define VERTEX_KEY              "NewVertex"
64 #define AUTOSAVE_KEY            "Autosave"
65 #define AUTOSAVETIME_KEY        "AutosaveMinutes"
66 #define PAK_KEY                 "UsePAK"
67 #define NEWAPPLY_KEY            "ApplyDismissesSurface"
68 #define HACK_KEY                "Gatewayescapehack"
69 #define TEXTURE_KEY             "NewTextureWindowStuff"
70 #define TINYBRUSH_KEY           "CleanTinyBrushes"
71 #define TINYSIZE_KEY            "CleanTinyBrusheSize"
72 #define SNAPSHOT_KEY            "Snapshots"
73 #define MOVESPEED_KEY           "MoveSpeed"
74 #define ANGLESPEED_KEY          "AngleSpeed"
75 #define SETGAME_KEY             "UseSetGame"
76 #define CAMXYUPDATE_KEY         "CamXYUpdate"
77 #define CAMDRAGMULTISELECT_KEY  "CamDragMultiSelect"
78 #define CAMFREELOOK_KEY         "CamFreeLook"
79 #define CAMINVERSEMOUSE_KEY         "CamInverseMouse"
80 #define CAMDISCRETE_KEY         "CamDiscrete"
81 #define LIGHTDRAW_KEY           "NewLightStyle"
82 #define WHATGAME_KEY            "WhichGame"
83 #define CUBICCLIP_KEY           "CubicClipping"
84 #define CUBICSCALE_KEY          "CubicScale"
85 #define ALTEDGE_KEY             "ALTEdgeDrag"
86 #define FACECOLORS_KEY          "FaceColors"
87 #define SNAPT_KEY               "SnapT"
88 #define XZVIS_KEY               "XZVIS"
89 #define YZVIS_KEY               "YZVIS"
90 #define ZVIS_KEY                "ZVIS"
91 #define SIZEPAINT_KEY           "SizePainting"
92 #define DLLENTITIES_KEY         "DLLEntities"
93 #define DETACHABLEMENUS_KEY     "DetachableMenus"
94 #define PATCHTOOLBAR_KEY        "PatchToolBar"
95 #define WIDETOOLBAR_KEY         "WideToolBar"
96 #define PLUGINTOOLBAR_KEY "PluginToolBar"
97 #define NOCLAMP_KEY             "NoClamp"
98 #define PREFAB_KEY              "PrefabPath"
99 #define USERINI_KEY             "UserINIPath"
100 #define ROTATION_KEY            "Rotation"
101 #define BUGGYICD_KEY            "BuggyICD"
102 #define CHASEMOUSE_KEY          "ChaseMouse"
103 #define ENTITYSHOW_KEY          "EntityShow"
104 #define TEXTURESCALE_KEY        "TextureScale"
105 #define TEXTURESCROLLBAR_KEY    "TextureScrollbar"
106 #define DISPLAYLISTS_KEY        "UseDisplayLists"
107 #define ANTIALIASEDLINES_KEY    "UseAntialiasedPointsAndLines" // Fishman - Add antialiazed points and lines support. 09/03/00
108 #define NORMALIZECOLORS_KEY     "NormalizeColors"
109 #define SHADERS_KEY             "UseShaders"
110 #define SWITCHCLIP_KEY          "SwitchClipKey"
111 #define SELWHOLEENTS_KEY                    "SelectWholeEntitiesKey"
112 #define TEXTURESUBSET_KEY                 "UseTextureSubsetLoading"
113 #define TEXTUREQUALITY_KEY          "TextureQuality"
114 #define SHOWSHADERS_KEY               "ShowShaders"
115 #define SHADERTEST_KEY          "ShaderTest"
116 #define GLLIGHTING_KEY          "UseGLLighting"
117 #define LOADSHADERS_KEY         "LoadShaders"
118 #define NOSTIPPLE_KEY           "NoStipple"
119 #define UNDOLEVELS_KEY          "UndoLevels"
120 #define VERTEXMODE_KEY          "VertexSplit"
121 #define ENGINEPATH_KEY          "EnginePath"
122 #define ENGINE_KEY              "Engine"
123 #define LOGCONSOLE_KEY          "LogConsole"
124 #define SELECTCURVES_KEY        "SelectCurves"
125 #define SELECTMODELS_KEY        "SelectModels"
126 #define SHADERLISTONLY_KEY      "ShowShaderlistOnly"
127 #define WATCHBSP_KEY            "WatchBSP"
128 #define LEAKSTOP_KEY            "LeakStop"
129 #define DOSLEEP_KEY             "SleepMode"
130 #define SUBDIVISIONS_KEY        "Subdivisions"
131 #define CLIPCAULK_KEY           "ClipCaulk"
132 #define PATCHSHOWBOUNDS_KEY     "PatchShowBounds"
133 #define NATIVEGUI_KEY           "NativeGUI"
134 #define STARTONPRIMMON_KEY      "StartOnPrimMon"
135 #define NOSYSMENUPOPUPS_KEY     "NoSysMenuPopups"
136 #define SNAPTTOGRID_KEY         "SnapTToGrid"
137 #define FLOATINGZ_KEY           "FloatingZ"
138 #define TARGETFIX_KEY           "TargetFix"
139 #define GLPOINTWORKAROUND_KEY   "GlPointWorkaround"             // Gef: Workaround for broken Kyro * gl driver 25-aug-2001
140 #define WHEELINC_KEY            "WheelMouseInc"
141 #define PATCHBBOXSEL_KEY        "PatchBBoxSel"
142 #define LASTLIGHTINTENSITY_KEY  "LastLightIntensity"
143 #define CUSTOMSHADEREDITOR_KEY        "UseCustomShaderEditor"
144 #define CUSTOMSHADEREDITORCOMMAND_KEY "CustomShaderEditorCommand"
145 #define TEXTURECOMPRESSIONFORMAT_KEY "TextureCompressionFormat"
146 #define LIGHTRADIUS_KEY "LightRadiuses"
147 #define Q3MAP2TEX_KEY "Q3Map2Tex"
148 #define ATIHACK_KEY "ATIHack"
149
150 // window stuff
151 #define ENTITYSPLIT1_KEY  "EntitySplit1"
152 #define ENTITYSPLIT2_KEY  "EntitySplit2"
153 #define POSITIONX_KEY     "PositionX"
154 #define POSITIONY_KEY     "PositionY"
155 #define ENTITYWND_KEY     "EntityWnd"
156 #define MAPINFOWND_KEY    "MapInfoDlg"
157 #define CAMWND_KEY        "CamWnd"
158 #define ZWND_KEY          "ZWnd"
159 #define XYWND_KEY         "XYWnd"
160 #define XZWND_KEY         "XZWnd"
161 #define YZWND_KEY         "YZWnd"
162 #define PATCHWND_KEY      "PatchWnd"
163 #define SURFACEWND_KEY    "SurfaceWnd"
164 #define ENTITYINFOWND_KEY "EntityInfoDlg"
165 #define WIDTH_KEY         "Width"
166 #define HEIGHT_KEY        "Height"
167 #define ZWIDTH_KEY        "ZWidth"
168 #define XYHEIGHT_KEY      "XYHeight"
169 #define XYWIDTH_KEY       "XYWidth"
170 #define CAMWIDTH_KEY      "CamWidth"
171 #define CAMHEIGHT_KEY     "CamHeight"
172 #define ZFLOATWIDTH_KEY   "ZWidthFloating"
173 #define STATE_KEY         "State"
174
175 // menu stuff
176 #define COUNT_KEY         "Count"
177 #define FILE_KEY          "File"
178
179 //saved info
180 #define SI_TEXMENU_KEY          "SI_TexMenu"
181 #define SI_GAMMA_KEY            "SI_Gamma"
182 #define SI_COLORS_KEY           "SI_Colors"
183 #define SI_EXCLUDE_KEY          "SI_Exclude"
184 #define SI_INCLUDE_KEY          "SI_Include"
185 #define SI_SURFACE_TEXDEF_KEY   "SI_SurfaceTexdef"
186 #define SI_PATCH_TEXDEF_KEY     "SI_PatchTexdef"
187 #define SI_AXISCOLORS_KEY       "SI_AxisColors"
188 #define SI_SHOWNAMES_KEY        "SI_ShowNames"
189 #define SI_SHOWCOORDS_KEY       "SI_ShowCoords"
190 #define SI_SHOWANGLES_KEY       "SI_ShowAngles"
191 #define SI_SHOWOUTLINES_KEY     "SI_ShowOutlines"
192 #define SI_SHOWAXIS_KEY         "SI_ShowAxis"
193 #define SI_NOSELOUTLINES_KEY    "SI_NoSelectedOutlines"
194 #define SI_OUTLINESTYLE_KEY "SI_OutLineStyle"
195
196 //for texdefs
197 #define TD_SCALE1_KEY           "_Scale1"
198 #define TD_SCALE2_KEY           "_Scale2"
199 #define TD_SHIFT1_KEY           "_Shift1"
200 #define TD_SHIFT2_KEY           "_Shift2"
201 #define TD_ROTATE_KEY           "_Rotate"
202
203 #define MOUSE_DEF 1
204 #define WINDOW_DEF 0
205 #define RUNQ2_DEF 0
206 #define WATCHBSP_DEF 1
207 #define TLOCK_DEF 1
208 #define LOADLAST_DEF 1
209 #define RUN_DEF 0
210 #define SUBDIVISIONS_DEF 4
211
212 void WindowPosition_Parse(window_position_t& m_value, const CString& value)
213 {
214   if(sscanf(value.GetBuffer(), "%d %d %d %d", &m_value.x, &m_value.y, &m_value.w, &m_value.h) != 4)
215     m_value.x = m_value.y = m_value.w = m_value.h = -1;
216 }
217
218 void WindowPosition_Write(const window_position_t& m_value, CString& value)
219 {
220   char buffer[64];
221   sprintf(buffer, "%d %d %d %d", m_value.x, m_value.y, m_value.w, m_value.h);
222   value = buffer;
223 }
224
225
226 CXMLPropertyBag::CXMLPropertyBag() {
227   mStrFilename = "";
228   mpDoc = NULL;
229   mbEmpty = false;
230 }
231
232 // generic preference functions
233
234 void CXMLPropertyBag::PushAssignment(const char *name, PrefTypes_t type, void *pV)
235 {
236   list<CPrefAssignment>::iterator iAssign;
237   for(iAssign=mPrefAssignments.begin(); iAssign!=mPrefAssignments.end(); iAssign++)
238   {
239     if ((*iAssign).mName == name)
240     {
241       // we have it already, check anyway
242       if (pV != (*iAssign).mVal)
243       {
244         Sys_FPrintf(SYS_ERR, "PushAssignment, '%s' has different mVal\n", name);
245         return;
246       }
247     }
248   }
249   // ok, it's not in our list yet
250   mPrefAssignments.push_front(CPrefAssignment(name, type, pV));
251 }
252
253 xmlNodePtr CXMLPropertyBag::EpairForName(const char *name)
254 {
255   xmlNodePtr ret = NULL;
256
257   xmlNodePtr pNode = mpDocNode->children;
258   while (pNode != NULL)
259   {
260     if(pNode->type == XML_ELEMENT_NODE)
261     {
262       xmlAttrPtr tmp_attr_ptr = xmlHasProp(pNode, (xmlChar *)"name");
263       if (tmp_attr_ptr != NULL && !strcmp(name, (char *)tmp_attr_ptr->children->content))
264       {
265         if ( ret ) {
266           Sys_FPrintf( SYS_WRN, "WARNING: dupe property in CXMLPropertyBag::EpairForName '%s'\n", name );
267         } else {
268           ret = pNode;
269         }
270       }
271     }
272     pNode = pNode->next;
273   }
274   return ret;
275 }
276
277 void CXMLPropertyBag::GetPref(const char *name, Str *pV, const char *V)
278 {
279   xmlNodePtr pNode = EpairForName( name );
280   if ( pNode )
281   {
282     if ( pNode->children && pNode->children->content ) {
283       *pV = pNode->children->content;
284     } else {
285       // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=427
286       // means the pref exists, and that the value is ""
287       *pV = "";
288     }
289   }
290   else
291   {
292     pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)V);
293     xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name);
294   }
295   // push the pref assignment if needed
296   PushAssignment(name, PREF_STR, pV);
297 }
298
299 void CXMLPropertyBag::GetPref(const char *name, int *pV, int V)
300 {
301   xmlNodePtr pNode;
302   if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content)
303   {
304     *pV = atoi((char *)pNode->children->content);
305   }
306   else
307   {
308     char s[10];
309     sprintf(s, "%d", V);
310     pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s);
311     xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name);
312     *pV=V;
313   }
314   // push the pref assignment if needed
315   PushAssignment(name, PREF_INT, pV);
316 }
317
318 void CXMLPropertyBag::GetPref(const char *name, bool *pV, bool V)
319 {
320   xmlNodePtr pNode;
321   if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content)
322   {
323     if (!strcmp((char *)pNode->children->content, "true"))
324     {
325       *pV = true;
326     }
327     else
328     {
329       *pV = false;
330     }
331   }
332   else
333   {
334     char s[10];
335     V ? strcpy(s, "true") : strcpy(s, "false");
336     pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s);
337     xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name);
338     *pV=V;
339   }
340   // push the pref assignment
341   PushAssignment(name, PREF_BOOL, pV);
342 }
343
344 void CXMLPropertyBag::GetPref(const char *name, float *pV, float V)
345 {
346   xmlNodePtr pNode;
347   if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content)
348   {
349     *pV = atof((char *)pNode->children->content);
350   }
351   else
352   {
353     char s[10];
354     sprintf(s, "%f", V);
355     pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s);
356     xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name);
357     *pV=V;
358   }
359   // push the pref assignment if needed
360   PushAssignment(name, PREF_FLOAT, pV);
361 }
362
363 void CXMLPropertyBag::GetPref(const char *name, float* pV, float* V)
364 {
365   xmlNodePtr pNode;
366   if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content)
367   {
368     sscanf((char *)pNode->children->content, "%f %f %f", &pV[0], &pV[1], &pV[2]);
369   }
370   else
371   {
372     char s[128];
373     sprintf(s, "%f %f %f", V[0], V[1], V[2]);
374     pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)s);
375     xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name);
376     pV[0] = V[0];
377     pV[1] = V[1];
378     pV[2] = V[2];
379   }
380   // push the pref assignment if needed
381   PushAssignment(name, PREF_VEC3, pV);
382 }
383
384 void CXMLPropertyBag::GetPref(const char *name, window_position_t* pV, window_position_t V)
385 {
386   xmlNodePtr pNode;
387   if ((pNode = EpairForName(name)) && pNode->children && pNode->children->content)
388   {
389     WindowPosition_Parse(*pV, CString((xmlChar *)pNode->children->content));
390   }
391   else
392   {
393     CString str;
394     WindowPosition_Write(V, str);
395     pNode = xmlNewChild(mpDocNode, NULL, (xmlChar *)"epair", (xmlChar *)str.GetBuffer());
396     xmlSetProp(pNode, (xmlChar *)"name", (xmlChar *)name);
397     *pV = V;
398   }
399   // push the pref assignment if needed
400   PushAssignment(name, PREF_WNDPOS, pV);
401 }
402
403 void CXMLPropertyBag::UpdatePrefTree()
404 {
405   // read the assignments and update the tree
406   list<CPrefAssignment>::iterator iPref;
407   for(iPref = mPrefAssignments.begin(); iPref != mPrefAssignments.end(); iPref++)
408   {
409     CPrefAssignment *pPref = &(*iPref);
410     // look for the node
411     xmlNodePtr pNode;
412     char s[64];
413
414     pNode = EpairForName(pPref->mName.GetBuffer());
415     // we never expect that the node could not be found, because this is supposed to happen
416     // after the tree was built with GetPref calls, never on a blank tree
417     if (!pNode)
418     {
419       Sys_FPrintf(SYS_ERR, "Unexpected EpairForName '%s' not found in UpdatePrefTree\n", pPref->mName.GetBuffer());
420       return;
421     }
422     switch ((*iPref).mType)
423     {
424     case PREF_STR:
425       xmlNodeSetContent(pNode, (const xmlChar *)((Str *)pPref->mVal)->GetBuffer());
426       break;
427     case PREF_INT:
428       sprintf(s, "%d", *(int *)pPref->mVal);
429       xmlNodeSetContent(pNode, (xmlChar *)s);
430       break;
431     case PREF_FLOAT:
432       sprintf(s, "%f", *(float *)pPref->mVal);
433       xmlNodeSetContent(pNode, (xmlChar *)s);
434       break;
435     case PREF_BOOL:
436       *(bool *)pPref->mVal ? strcpy(s, "true") : strcpy(s, "false");
437       xmlNodeSetContent(pNode, (xmlChar *)s);
438       break;
439     case PREF_VEC3:
440       {
441         float* v = (float*)pPref->mVal;
442         sprintf(s, "%f %f %f", v[0], v[1], v[2]);
443         xmlNodeSetContent(pNode, (xmlChar *)s);
444       }
445       break;
446     case PREF_WNDPOS:
447       {
448         CString str;
449         WindowPosition_Write(*(window_position_t*)pPref->mVal, str);
450         xmlNodeSetContent(pNode, (xmlChar*)str.GetBuffer());
451       }
452       break;
453     }
454   }
455 }
456
457 void CXMLPropertyBag::Clear()
458 {
459   if(!InUse())
460     return;
461
462   xmlFreeDoc(mpDoc);
463   mpDoc = NULL;
464   mpDocNode = NULL;
465   mbEmpty = false;
466 }
467
468 void CXMLPropertyBag::ReadXMLFile(const char* pFilename)
469 {
470   mpDoc = xmlParseFile(pFilename);
471
472   // basic checks
473   if (mpDoc)
474   {
475     mpDocNode = mpDoc->children;
476     xmlAttrPtr tmp_attr_ptr = xmlHasProp(mpDocNode, (xmlChar *)"version");
477     if (strcmp((char *)mpDocNode->name, "qpref"))
478     {
479       Sys_FPrintf(SYS_ERR, "Unrecognized node '%s' in '%s'\n", mpDocNode->name, mpDoc->URL);
480       xmlFreeDoc(mpDoc);
481       mpDoc = NULL;
482     }
483     else if (tmp_attr_ptr != NULL && strcmp((char*)tmp_attr_ptr->children->content, "1"))
484     {
485       Sys_FPrintf(SYS_ERR, "Wrong version '%s' in <qpref> node for '%s'\n", (char*)tmp_attr_ptr->children->content, mpDoc->URL);
486       xmlFreeDoc(mpDoc);
487       mpDoc = NULL;
488     }
489     Sys_Printf("Opened XML property file: '%s'\n", pFilename);
490   }
491
492   if (!mpDoc)
493   {
494     mbEmpty = true;
495     // no document, create one
496     mpDoc = xmlNewDoc((xmlChar *)"1.0");
497     mpDocNode = xmlNewDocNode(mpDoc, NULL, (xmlChar *)"qpref", NULL);
498     xmlDocSetRootElement(mpDoc, mpDocNode);
499     xmlSetProp(mpDocNode, (xmlChar *)"version", (xmlChar *)"1");
500     Sys_Printf("XML property file '%s' invalid/not found, creating blank properties tree\n", pFilename);
501   }
502 }
503
504 qboolean CXMLPropertyBag::WriteXMLFile(const char* pFilename)
505 {
506   int res = xmlSaveFormatFile(pFilename, mpDoc, 1);
507
508   if(res == -1)
509     return false;
510
511   Sys_Printf("Wrote XML property file '%s'\n", pFilename);
512   return true;
513 }
514
515 // =============================================================================
516 // Widget callbacks for PrefsDlg
517
518 #if !defined(WIN32)
519 // browse for custom editor executable
520 static void OnBtnBrowseEditor (GtkWidget *widget, gpointer data)
521 {
522   PrefsDlg *dlg = (PrefsDlg*)data;
523
524   const char *filename = file_dialog(g_PrefsDlg.GetWidget(), TRUE, "Executable for Custom Editor");
525
526   if(filename != NULL)
527   {
528     dlg->m_strEditorCommand = filename;
529     dlg->UpdateData(FALSE);
530   }
531 }
532 #endif
533
534 static void OnBtnBrowseprefab (GtkWidget *widget, gpointer data)
535 {
536   PrefsDlg *dlg = (PrefsDlg*)data;
537   char *path = dlg->m_strPrefabPath;
538   if (strlen (path) == 0)
539     path = g_strGameToolsPath;
540   char *dir = dir_dialog (g_PrefsDlg.GetWidget (), "Set prefab path", path);
541   dlg->UpdateData(TRUE);
542
543   if (dir != NULL)
544   {
545     CString strPath;
546     strPath = dir;
547     AddSlash(strPath);
548     dlg->m_strPrefabPath = strPath;
549     dlg->UpdateData(FALSE);
550     free (dir);
551   }
552 }
553
554 static void OnBtnBrowseuserini (GtkWidget *widget, gpointer data)
555 {
556   PrefsDlg *dlg = (PrefsDlg*)data;
557   char *path = dlg->m_strUserPath;
558   if (strlen (path) == 0)
559     path = g_strGameToolsPath;
560   // TODO: INI filter?
561   const char *filename = file_dialog (g_PrefsDlg.GetWidget(), TRUE, "Find INI file", path);
562
563   if (filename != NULL)
564   {
565     dlg->UpdateData(TRUE);
566     dlg->m_strUserPath = filename;
567     dlg->UpdateData(FALSE);
568   }
569 }
570
571 static void OnButtonClean (GtkWidget *widget, gpointer data)
572 {
573   // make sure this is what the user wants
574   if (gtk_MessageBox (g_PrefsDlg.GetWidget (), "This will close Radiant and clean the corresponding registry entries.\n"
575                   "Next time you start Radiant it will be good as new. Do you wish to continue?",
576                   "Reset Registry", MB_YESNO) == IDYES)
577   {
578     PrefsDlg *dlg = (PrefsDlg*)data;
579     dlg->EndModal (IDCANCEL);
580
581     g_qeglobals.disable_ini = true;
582     remove (dlg->m_inipath->str);
583     char buf[PATH_MAX];
584     sprintf(buf, "%sSavedInfo.bin", dlg->m_rc_path->str);
585     remove(buf);
586     HandleCommand (NULL, GINT_TO_POINTER (ID_FILE_EXIT));
587     _exit (0);
588   }
589 }
590
591 // =============================================================================
592 // PrefsDlg class
593
594 // IMPORTANT NOTE: the values here don't matter very much
595 // the actual intialization if you start with an empty .ini is done when loading the prefs for the first time
596 // profile_load_int takes an argument to use if the value is not found
597 PrefsDlg::PrefsDlg ()
598 {
599   m_bWarn = TRUE;
600   m_nMouse = 1;
601   m_nView = MainFrame::eRegular;
602   m_bLoadLast = FALSE;
603   m_bInternalBSP = FALSE;
604   m_bRightClick = FALSE;
605   m_bSetGame = FALSE;
606   m_bAutoSave = TRUE;
607   m_nAutoSave = 5;
608   m_bLoadLastMap = FALSE;
609   m_bTextureWindow = FALSE;
610   m_bSnapShots = FALSE;
611   m_fTinySize = 0.5;
612   m_bCleanTiny = FALSE;
613   m_bCamXYUpdate = TRUE;
614   m_bCamDragMultiSelect = FALSE;
615   m_bCamFreeLook = TRUE;
616   m_bCamFreeLookStrafe = FALSE;
617   m_bCamInverseMouse = FALSE;
618   m_bCamDiscrete = TRUE;
619   m_bNewLightDraw = FALSE;
620   m_strPrefabPath = "";
621   m_nWhatGame = 0;
622   m_bALTEdge = FALSE;
623   m_bFaceColors = FALSE;
624   m_bXZVis = FALSE;
625   m_bYZVis = FALSE;
626   m_bZVis = FALSE;
627   m_bSizePaint = FALSE;
628   m_bDLLEntities = FALSE;
629 #ifdef _WIN32
630   m_bDetachableMenus = FALSE;   // Most win32 users will find detachable menus annoying
631 #else
632   m_bDetachableMenus = TRUE;    // Linux/Apple users are used to them...
633 #endif
634   m_bPatchToolbar = TRUE;
635   m_bWideToolbar = TRUE;
636   m_bPluginToolbar = TRUE;
637   m_bNoClamp = FALSE;
638   m_strUserPath = "";
639   m_nRotation = 0;
640   m_bChaseMouse = FALSE;
641   m_bTextureScrollbar = TRUE;
642   m_bDisplayLists = TRUE;
643   m_bAntialiasedPointsAndLines = FALSE; // Fishman - Add antialiazed points and lines support. 09/03/00
644   m_bShowShaders = FALSE;
645   m_nShader = -1;
646   m_bNoStipple = FALSE;
647   m_bVertexSplit = FALSE;
648   m_bSelectCurves = TRUE;
649   m_bSelectModels = TRUE;
650   m_nEntityShowState = ENTITY_SKINNED_BOXED;
651   m_nTextureScale = 2;
652   m_bSwitchClip = FALSE;
653   m_bSelectWholeEntities = TRUE;
654   m_nTextureQuality = 3;
655   m_bShowShaders = TRUE;
656   m_bGLLighting = FALSE;
657   m_nShader = 0;
658   m_nUndoLevels = 30;
659   m_bTexturesShaderlistOnly = FALSE;
660   // paths to ini files
661   m_rc_path = NULL;
662   m_inipath = NULL;
663   m_bWatchBSP = TRUE;
664   m_bLeakStop = TRUE;
665   m_iTimeout = 15;
666   m_bRunQuake = TRUE;
667   m_bDoSleep = FALSE;
668   m_nSubdivisions = 4;
669   // not prefs
670   m_bFloatingZ = FALSE;
671   m_bGlPtWorkaround = FALSE;    // Gef: Kyro/GL_POINTS workaround 25-aug-2001
672 #ifdef _WIN32
673   m_bNativeGUI = FALSE;
674   m_bStartOnPrimMon = FALSE;
675 #endif
676   m_global_rc_path = NULL;
677 #ifdef _WIN32
678   m_bUseWin32Editor = TRUE;
679 #else
680   // custom shader editor options
681   m_bUseCustomEditor = FALSE;
682   m_strEditorCommand = "";
683 #endif
684   m_nLightRadiuses = 1;
685   m_bQ3Map2Texturing = TRUE;
686 #ifdef ATIHACK_812
687         m_bGlATIHack = FALSE;
688 #endif
689 }
690
691 /*!
692 =========================================================
693 Games selection dialog
694 =========================================================
695 */
696
697 CGameDescription::CGameDescription(xmlDocPtr pDoc, const Str &GameFile)
698 {
699   char *p, *prop;
700   mpDoc = pDoc;
701   // read the user-friendly game name
702   xmlNodePtr pNode = mpDoc->children;
703
704   while (strcmp((const char*)pNode->name, "game") && pNode != NULL) pNode=pNode->next;
705   if (!pNode)
706   {
707     ///< \todo add the file name (this node and gametools should all be part of CGameDescription anyway)
708     Error("Didn't find 'game' node in the game description file '%s'\n", pDoc->URL);
709   }
710   // on win32, game tools path can now be specified relative to the exe's cwd
711   prop = (char*)xmlGetProp( pNode, (xmlChar*)"gametools" );
712   if ( prop == NULL ) {
713           Error( "Didn't find 'gametools' node in the game description file '%s'\n", pDoc->URL );
714   }
715   {
716         char full[PATH_MAX];
717 #ifdef _WIN32
718         _fullpath( full, prop, PATH_MAX );
719 #else
720     strncpy( full, prop, PATH_MAX );
721 #endif
722     xmlFree( prop );
723     prop = NULL;
724     for ( p = full; *p != '\0'; p++ ) {
725           if ( *p == '\\' ) {
726             *p = '/';
727           }
728           mGameToolsPath = full;
729           if ( p != full && *(p-1) != '/' ) {
730             mGameToolsPath += "/";
731           }
732     }
733   }
734
735   prop = (char*)xmlGetProp(pNode, (xmlChar*)"name");
736   if (prop == NULL)
737   {
738     Sys_FPrintf(SYS_WRN, "Warning, 'name' attribute not found in '%s'\n", pDoc->URL);
739     mGameName = pDoc->URL;
740   }
741   else
742   {
743     mGameName = prop;
744     xmlFree(prop);
745   }
746
747   mGameFile = GameFile;
748
749   prop = (char*)xmlGetProp(pNode, (xmlChar*)"quake2");
750   if (prop == NULL)
751   {
752     // default
753     quake2 = false;
754   }
755   else
756   {
757     quake2 = true;
758     xmlFree(prop);
759   }
760
761   prop = (char*)xmlGetProp(pNode, (xmlChar*)"basegame");
762   if (prop == NULL)
763   {
764     // default
765     mBaseGame = "baseq3";
766   }
767   else
768   {
769     mBaseGame = prop;
770     xmlFree(prop);
771   }
772
773   // on win32, engine path can now be specified relative to the exe's cwd
774   prop = (char*)xmlGetProp(pNode, (const xmlChar *)"enginepath");
775   if ( prop != NULL ) {
776     char full[PATH_MAX];
777 #ifdef _WIN32
778         _fullpath( full, prop, PATH_MAX );
779 #else
780         strncpy( full, prop, PATH_MAX );
781 #endif
782     xmlFree( prop );
783         prop = NULL;
784     // process seperators
785     for ( p = full; *p != '\0'; p++ ) {
786           if ( *p == '\\' ) {
787             *p = '/';
788           }
789         }
790     mEnginePath = full;
791         if ( p != full && *(p-1) != '/' ) {
792           mEnginePath += "/";
793         }
794   }
795   else
796   {
797     // if engine path was not specified in the .game, it implies we can guess it from the gametools path
798     // on win32, and for most game package, the gametools are installed with the game
799     char aux_path[PATH_MAX]; // aux
800     strcpy( aux_path, mGameToolsPath.GetBuffer() );
801         if ( ( aux_path[ strlen(aux_path)-1 ] == '/' ) || ( aux_path[ strlen(aux_path)-1 ] == '\\' ) ) {
802       aux_path[strlen(aux_path)-1] = '\0'; // strip ending '/' if any
803         }
804     char up_path[PATH_MAX]; // up one level
805     ExtractFilePath( aux_path, up_path );
806     mEnginePath = up_path;
807   }
808
809   prop = (char*)xmlGetProp(pNode, (xmlChar*)"engine");
810   if (prop == NULL)
811   {
812 #ifdef _WIN32
813     mEngine = "quake3.exe";
814 #elif __linux__
815     mEngine = "quake3";
816 #elif __APPLE__
817     mEngine = "Quake3.app";
818 #endif
819   }
820   else
821   {
822     mEngine = prop;
823     xmlFree(prop);
824   }
825
826 #if defined (__linux__) || defined (__APPLE__)
827   // *nix specific
828   prop = (char*)xmlGetProp(pNode, (const xmlChar *)"prefix");
829   if(prop != NULL)
830   {
831     mUserPathPrefix = prop;
832     xmlFree(prop);
833   }
834 #endif
835   mShaderPath = xmlGetProp(pNode, (const xmlChar *)"shaderpath");
836   if (!mShaderPath.GetLength())
837   {
838     mShaderPath = "scripts/";
839     mShaderlist = "scripts/shaderlist.txt";
840   }
841   else
842   {
843     AddSlash(mShaderPath);
844     mShaderlist = mShaderPath;
845     mShaderlist += "shaderlist.txt";
846   }
847   xmlChar* default_scale = xmlGetProp(pNode, (const xmlChar *)"default_scale");
848   if (default_scale)
849   {
850     mTextureDefaultScale = atof((const char *)default_scale);
851     xmlFree(default_scale);
852   }
853   else
854     mTextureDefaultScale = 0.5f;
855   xmlChar* eclass_singleload = xmlGetProp(pNode, (const xmlChar*)"eclass_singleload");
856   if (eclass_singleload)
857   {
858     mEClassSingleLoad = true;
859     xmlFree(eclass_singleload);
860   }
861   else
862     mEClassSingleLoad = false;
863   xmlChar* no_patch = xmlGetProp(pNode, (const xmlChar *)"no_patch");
864   if (no_patch)
865   {
866     mNoPatch = true;
867     xmlFree(no_patch);
868   }
869   else
870     mNoPatch = false;
871   xmlChar* caulk_shader = xmlGetProp(pNode, (const xmlChar *)"caulk_shader");
872   if (caulk_shader)
873   {
874     mCaulkShader = caulk_shader;
875     xmlFree(caulk_shader);
876   }
877   else
878     mCaulkShader = "textures/common/caulk";
879 }
880
881 void CGameDescription::Dump()
882 {
883 #ifdef _WIN32
884   if (CGameDialog::GetNetrun())
885     Sys_Printf("Running in network mode, prefs path set to '%s'\n", g_strTempPath.GetBuffer());
886 #endif
887   Sys_Printf("game name            : '%s'\n", mGameName.GetBuffer());
888   Sys_Printf("game file            : '%s'\n", mGameFile.GetBuffer());
889   Sys_Printf("game path            : '%s'\n", mGameToolsPath.GetBuffer());
890   Sys_Printf("base game            : '%s'\n", mBaseGame.GetBuffer());
891   Sys_Printf("engine path          : '%s'\n", mEnginePath.GetBuffer());
892   Sys_Printf("engine               : '%s'\n", mEngine.GetBuffer());
893   Sys_Printf("shaderlist           : '%s'\n", mShaderlist.GetBuffer());
894   Sys_Printf("caulk shader: '%s'\n", mCaulkShader.GetBuffer());
895 #if defined (__linux__) || defined (__APPLE__)
896   Sys_Printf("prefix               : '%s'\n", mUserPathPrefix.GetBuffer());
897 #endif
898   Sys_Printf("default texture scale: %g\n", mTextureDefaultScale);
899   Sys_Printf("single eclass load   : %s\n", mEClassSingleLoad ? "Yes" : "No");
900   Sys_Printf("patches supported    : %s\n", mNoPatch ? "No" : "Yes");
901 }
902
903 CPrefAssignment& CPrefAssignment::operator = (const CPrefAssignment& ass)
904 {
905   if (&ass != this)
906   {
907     mName = ass.mName;
908     mType = ass.mType;
909     mVal = ass.mVal;
910   }
911   return *this;
912 }
913
914 CPrefAssignment::CPrefAssignment(const CPrefAssignment& ass)
915 {
916   *this = ass;
917 }
918
919 void CGameDialog::LoadPrefs()
920 {
921   // if we already have a document loaded, we will free and reload from file
922   if (mGlobalPrefs.InUse())
923   {
924     Sys_Printf("Reloading global prefs from file\n");
925     mGlobalPrefs.Clear();
926   }
927
928   // load global .pref file
929   CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str;
930   strGlobalPref += "global.pref";
931
932   mGlobalPrefs.ReadXMLFile(strGlobalPref.GetBuffer());
933
934   mGlobalPrefs.GetPref("gamefile", &m_sGameFile, ""); // NOTE: there's no default, user HAS to select something
935   mGlobalPrefs.GetPref("autoload", &m_bAutoLoadGame, false);
936   mGlobalPrefs.GetPref("log console", &m_bLogConsole, false);
937   // in a very particular post-.pid startup
938   // we may have the console turned on and want to keep it that way
939   // so we use a latching system
940   if (m_bForceLogConsole)
941   {
942     m_bLogConsole = true;
943     Sys_Printf("console logging has been latched on, saving prefs\n");
944     SavePrefs();
945     m_bForceLogConsole = false;
946   }
947
948   // console logging: call Sys_LogConsole to check console logging status
949   // it is important that we would log console as early as possible to make it useful
950   Sys_LogFile();
951
952   if (mGlobalPrefs.mbEmpty)
953   {
954     Sys_Printf("Saving global.pref with default pref values\n");
955     SavePrefs();
956   }
957 }
958
959 void CGameDialog::SavePrefs()
960 {
961   // update the tree and save it
962   mGlobalPrefs.UpdatePrefTree();
963
964   CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str;
965   strGlobalPref += "global.pref";
966
967   if ( !mGlobalPrefs.WriteXMLFile( strGlobalPref.GetBuffer() ) ) {
968     Sys_FPrintf(SYS_ERR, "Error occured while saving global prefs file '%s'\n", strGlobalPref.GetBuffer());
969   }
970 }
971
972 void CGameDialog::DoGameInstall() {
973         // make sure console logging is on whenever we enter the installation loop
974     g_PrefsDlg.mGamesDialog.m_bLogConsole = true;
975         Sys_LogFile();
976         mGameInstall.Run();
977 }
978
979 void CGameDialog::DoGameDialog() {
980         // allow looping the game selection dialog with calls to the game configure dialog in between
981         while ( m_bDoGameInstall ) {
982
983                 m_bDoGameInstall = false;
984
985                 if ( DoModal() == IDCANCEL ) {
986                         Error( "game selection dialog canceled, cannot continue" );
987                         return;
988                 }
989
990                 if ( m_bDoGameInstall ) {
991                         DoGameInstall();
992                         ScanForGames();
993                         // and we will loop to do another DoModal dialog
994                 }
995         }
996
997         // unhook so we can use in other places
998         // we manually incref'ed it when creating, it won't be freed (destructor)
999         gtk_container_remove( GTK_CONTAINER( mTopBox ), GetGlobalFrame() );
1000
1001         // we save the prefs file
1002         SavePrefs();
1003 }
1004
1005 GtkWidget* CGameDialog::GetGlobalFrame()
1006 {
1007   GtkWidget *vbox, *text, *combo, *check;
1008
1009   if ( mFrame != NULL ) {
1010           return mFrame;
1011   }
1012
1013   mFrame = gtk_frame_new( NULL );
1014   gtk_container_set_border_width( GTK_CONTAINER( mFrame ), 5 );
1015   gtk_widget_show( mFrame );
1016
1017   vbox = gtk_vbox_new( FALSE, 6 );
1018   gtk_widget_show( vbox );
1019   gtk_container_add( GTK_CONTAINER( mFrame ), vbox );
1020   gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
1021
1022   text = gtk_label_new( "Select the game:" );
1023   gtk_widget_show( text );
1024   gtk_box_pack_start( GTK_BOX( vbox ), text, FALSE, FALSE, 0 );
1025
1026   combo = gtk_combo_box_new_text();
1027   gtk_widget_show( combo );
1028   gtk_box_pack_start( GTK_BOX( vbox ), combo, FALSE, FALSE, 0 );
1029   AddDialogData( combo, &m_nComboSelect, DLG_COMBO_BOX_INT );
1030   mGameCombo = GTK_COMBO_BOX( combo );
1031
1032   UpdateGameCombo();
1033
1034   check = gtk_check_button_new_with_label( "Auto load selected game on startup" );
1035   gtk_widget_show(check);
1036   gtk_box_pack_start (GTK_BOX(vbox), check, FALSE, FALSE, 0);
1037   AddDialogData (check, &m_bAutoLoadGame, DLG_CHECK_BOOL);
1038
1039   text = gtk_label_new("(this frame is available in the prefs menu if you set auto-select)");
1040   gtk_widget_show(text);
1041   gtk_box_pack_start (GTK_BOX(vbox), text, FALSE, FALSE, 0);
1042
1043 #ifdef _WIN32
1044   check = gtk_check_button_new_with_label( "Networked install - per-user settings" );
1045   gtk_widget_show( check );
1046   gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 );
1047   AddDialogData( check, &m_bNetRun, DLG_CHECK_BOOL );
1048 #endif
1049
1050   check = gtk_check_button_new_with_label( "Log the console to radiant.log" );
1051   gtk_widget_show( check );
1052   gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 );
1053   AddDialogData( check, &m_bLogConsole, DLG_CHECK_BOOL );
1054
1055   // incref it so we can pass it around
1056   gtk_widget_ref( GTK_WIDGET( mFrame ) );
1057
1058   return mFrame;
1059 }
1060
1061 void CGameDialog::UpdateData( bool retrieve ) {
1062   if (!retrieve)
1063   {
1064     // use m_sGameFile to set m_nComboSelect
1065     list<CGameDescription *>::iterator iGame;
1066     int i = 0;
1067     for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++)
1068     {
1069       if ((*iGame)->mGameFile == m_sGameFile)
1070       {
1071         m_nComboSelect = i;
1072         break;
1073       }
1074       i++;
1075     }
1076 #ifdef _WIN32
1077     UpdateNetrun(false);
1078 #endif
1079   }
1080   Dialog::UpdateData(retrieve);
1081   if (retrieve)
1082   {
1083     // use m_nComboSelect to set m_sGameFile
1084     list<CGameDescription *>::iterator iGame = mGames.begin();
1085     int i;
1086     for(i=0; i<m_nComboSelect; i++)
1087     {
1088       iGame++;
1089     }
1090     m_sGameFile = (*iGame)->mGameFile;
1091 #ifdef _WIN32
1092     UpdateNetrun(true);
1093 #endif
1094   }
1095 }
1096
1097 void CGameDialog::SInstallCallback( GtkWidget *widget, gpointer data ) {
1098         CGameDialog *d = static_cast< CGameDialog* >( data );
1099         d->m_bDoGameInstall = true;
1100         d->EndModal( 0 );
1101 }
1102
1103 void CGameDialog::BuildDialog() {
1104         GtkWidget *dlg, *vbox1, *button, *setup_button;
1105
1106         dlg = m_pWidget;
1107         gtk_window_set_title( GTK_WINDOW( dlg ), "Select Game" );
1108
1109         vbox1 = gtk_vbox_new( FALSE, 0 );
1110         gtk_widget_show( vbox1 );
1111         gtk_container_add( GTK_CONTAINER( dlg ), vbox1 );
1112
1113         gtk_container_add( GTK_CONTAINER( vbox1 ), GetGlobalFrame() );
1114         mTopBox = vbox1;
1115
1116         setup_button = gtk_button_new_with_label( "Configure more games" );
1117         gtk_widget_show( setup_button );
1118         gtk_box_pack_start( GTK_BOX( vbox1 ), setup_button, FALSE, FALSE, 0 );
1119         gtk_signal_connect( GTK_OBJECT( setup_button ), "clicked",
1120                                                 GTK_SIGNAL_FUNC( SInstallCallback ), this );
1121
1122         button = gtk_button_new_with_label( "OK" );
1123         gtk_widget_show( button );
1124         gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 );
1125         AddModalButton( button, IDOK );
1126
1127         button = gtk_button_new_with_label( "Cancel" );
1128         gtk_widget_show( button );
1129         gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 );
1130         AddModalButton( button, IDCANCEL );
1131
1132         gtk_widget_set_usize( button, 60, -2 );
1133 }
1134
1135 void CGameDialog::UpdateGameCombo() {
1136   // fill in with the game descriptions
1137   list<CGameDescription *>::iterator iGame;
1138
1139   if ( mGameCombo == NULL ) {
1140           Sys_Printf( "mGameCombo == NULL\n" );
1141           return;
1142   }
1143
1144   // clear whatever is in - wtf no way to know how many text entries?
1145   // use set/get active to track
1146   gtk_combo_box_set_active( mGameCombo, 0 );
1147   while ( gtk_combo_box_get_active( mGameCombo ) == 0 ) {
1148           gtk_combo_box_remove_text( mGameCombo, 0 );
1149           gtk_combo_box_set_active( mGameCombo, 0 );
1150   }
1151
1152   for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) {
1153           gtk_combo_box_append_text( mGameCombo, (*iGame)->mGameName.GetBuffer() );
1154   }
1155   gtk_combo_box_set_active( mGameCombo, 0 );
1156 }
1157
1158 void CGameDialog::ScanForGames()
1159 {
1160   CString strPath;
1161   char *dirlist;
1162   GDir *dir;
1163   CString strGamesPath = g_strAppPath.GetBuffer();
1164   strGamesPath += "games";
1165   const char *path = strGamesPath.GetBuffer();
1166
1167   if ( !mGames.empty() ) {
1168           Sys_Printf( "Clearing game list\n" );
1169           list<CGameDescription*>::iterator iGame;
1170           for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) {
1171                   delete (*iGame);
1172           }
1173           mGames.clear();
1174   }
1175
1176   Sys_Printf( "Scanning for game description files: %s\n", path );
1177
1178   /*!
1179   \todo FIXME LINUX:
1180   do we put game description files below g_strAppPath, or in ~/.radiant
1181   i.e. read only or read/write?
1182   my guess .. readonly cause it's an install
1183   we will probably want to add ~/.radiant/<version>/games/ scanning on top of that for developers
1184   (if that's really needed)
1185   */
1186
1187   // FIXME need to catch the 'no game description' situation and exit with a clean error
1188
1189   dir = g_dir_open(path, 0, NULL);
1190
1191   if (dir != NULL)
1192   {
1193     while (1)
1194     {
1195       const gchar* name = g_dir_read_name(dir);
1196       if(name == NULL)
1197         break;
1198
1199       dirlist = g_strdup(name);
1200 #ifdef _WIN32
1201       strlwr (dirlist);
1202 #endif
1203       char *ext = strrchr (dirlist, '.');
1204       if ((ext == NULL) || (strcmp (ext, ".game") != 0))
1205         continue;
1206       strPath.Format("%s/%s", path, dirlist);
1207       Sys_Printf("%s\n", strPath.GetBuffer());
1208       // got one, load it
1209       xmlDocPtr pDoc = xmlParseFile(strPath.GetBuffer());
1210       if (pDoc)
1211       {
1212         mGames.push_front( new CGameDescription( pDoc, dirlist ) );
1213       }
1214       else
1215       {
1216         Sys_FPrintf(SYS_ERR, "XML parser failed on '%s'\n", strPath.GetBuffer());
1217       }
1218
1219       g_free( dirlist );
1220     }
1221     g_dir_close( dir );
1222   }
1223
1224   // entries in the combo need to be updated
1225   UpdateGameCombo();
1226 }
1227
1228 CGameDescription* CGameDialog::GameDescriptionForComboItem()
1229 {
1230   list<CGameDescription *>::iterator iGame;
1231   int i=0;
1232   for( iGame = mGames.begin(); iGame != mGames.end(); iGame++,i++ ) {
1233     if ( i == m_nComboSelect ) {
1234       return (*iGame);
1235     }
1236   }
1237   return NULL; // not found
1238 }
1239
1240 void CGameDialog::InitGlobalPrefPath()
1241 {
1242   GString *global_rc_path;
1243   // configure m_global_rc_path
1244   // this is the g_strTempPath, and it has already been mkdir'ed
1245   global_rc_path = g_string_new(g_strTempPath.GetBuffer());
1246   g_PrefsDlg.m_global_rc_path = global_rc_path;
1247 }
1248
1249 void CGameDialog::Reset()
1250 {
1251   if (!g_PrefsDlg.m_global_rc_path)
1252     InitGlobalPrefPath();
1253   CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str;
1254   strGlobalPref += "global.pref";
1255   remove(strGlobalPref.GetBuffer());
1256 }
1257
1258 void CGameDialog::Init()
1259 {
1260   InitGlobalPrefPath();
1261   ScanForGames();
1262   if ( mGames.empty() ) {
1263           DoGameInstall();
1264           ScanForGames();
1265           if ( mGames.empty() ) {
1266                   Error( "No games setup, aborting\n" );
1267           }
1268   }
1269   LoadPrefs();
1270   if ( m_bAutoLoadGame ) {
1271     // search by .game name
1272     list<CGameDescription *>::iterator iGame;
1273     for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++)
1274     {
1275       if ((*iGame)->mGameFile == m_sGameFile)
1276       {
1277         m_pCurrentGameDescription = (*iGame);
1278         break;
1279       }
1280     }
1281   }
1282   if ( !m_bAutoLoadGame || !m_pCurrentGameDescription ) {
1283     DoGameDialog();
1284     // use m_nComboSelect to identify the game to run as and set the globals
1285     m_pCurrentGameDescription = GameDescriptionForComboItem();
1286     if ( !m_pCurrentGameDescription ) {
1287                 Error("Lookup of game description object failed, can't continue\n");
1288         }
1289   }
1290   g_pGameDescription = m_pCurrentGameDescription;
1291
1292   g_strGameToolsPath = g_pGameDescription->mGameToolsPath;
1293
1294         // NOTE TTimo: this is moved from QE_LoadProject in 1.2
1295         // (probably broken)
1296   // NOTE Hydra: was broken for win32, we don't use m_strHomeGame or m_strFSBasePath
1297 #if defined (__linux__) || defined (__APPLE__)
1298   g_qeglobals.m_strHomeGame = g_get_home_dir();
1299   g_qeglobals.m_strHomeGame += "/";
1300   g_qeglobals.m_strHomeGame += m_pCurrentGameDescription->mUserPathPrefix.GetBuffer();
1301   g_qeglobals.m_strHomeGame += "/";
1302 #else
1303   g_qeglobals.m_strHomeGame = g_pGameDescription->mEnginePath.GetBuffer();
1304 #endif
1305
1306   g_pGameDescription->Dump();
1307 }
1308
1309 CGameDialog::~CGameDialog()
1310 {
1311   if (mFrame)
1312   {
1313     // NOTE I'm not too sure how reliable this is
1314     gtk_widget_unref(GTK_WIDGET(mFrame));
1315   }
1316   // free all the game descriptions
1317   list<CGameDescription *>::iterator iGame;
1318   for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++)
1319   {
1320     delete (*iGame);
1321     *iGame = NULL;
1322   }
1323 }
1324
1325 void CGameDialog::AddPacksURL(Str &URL)
1326 {
1327   // add the URLs for the list of game packs installed
1328   // FIXME: this is kinda hardcoded for now..
1329   list<CGameDescription *>::iterator iGame;
1330   for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++)
1331   {
1332     if ((*iGame)->mGameFile == "q3.game")
1333       URL += "&Games_dlup%5B%5D=1";
1334     else if ((*iGame)->mGameFile == "wolf.game")
1335       URL += "&Games_dlup%5B%5D=2";
1336     else if ((*iGame)->mGameFile == "wolf.game")
1337       URL += "&Games_dlup%5B%5D=3";
1338     else if ((*iGame)->mGameFile == "jk2.game")
1339       URL += "&Games_dlup%5B%5D=4";
1340     else if ((*iGame)->mGameFile == "stvef.game")
1341       URL += "&Games_dlup%5B%5D=5";
1342     else if ((*iGame)->mGameFile == "sof2.game")
1343       URL += "&Games_dlup%5B%5D=6";
1344     else if ((*iGame)->mGameFile == "ja.game")
1345       URL += "&Games_dlup%5B%5D=7";
1346   }
1347 }
1348
1349 #ifdef _WIN32
1350
1351 #define NETRUN_FILENAME "netrun.conf"
1352
1353 bool CGameDialog::m_bNetRun;
1354
1355 void CGameDialog::UpdateNetrun(bool retrieve)
1356 {
1357   FILE *f_netrun;
1358   CString strNetrun;
1359   strNetrun = g_strAppPath; strNetrun += NETRUN_FILENAME;
1360   if (!retrieve)
1361   {
1362     // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=639
1363     // now check if we are running from a network installation
1364     // use a dummy file as the flag
1365     f_netrun = fopen(strNetrun.GetBuffer(), "r");
1366     if (f_netrun)
1367     {
1368       fclose(f_netrun);
1369       m_bNetRun = true;
1370     }
1371     else
1372       m_bNetRun = false;
1373   }
1374   else
1375   {
1376     if (m_bNetRun)
1377     {
1378       f_netrun = fopen(strNetrun.GetBuffer(), "w");
1379       if (!f_netrun)
1380       {
1381         Sys_FPrintf(SYS_ERR, "ERROR: Failed to create netrun file '%s'\n", strNetrun.GetBuffer());
1382         m_bNetRun = false;
1383       }
1384       else
1385       {
1386         fclose(f_netrun);
1387         Sys_Printf("Created/Checked '%s'\n", strNetrun.GetBuffer());
1388       }
1389     }
1390     else
1391     {
1392       if (remove(strNetrun.GetBuffer()) == -1)
1393       {
1394         if (errno != ENOENT)
1395           Sys_FPrintf(SYS_ERR, "Failed to remove netrun file '%s'\n", strNetrun.GetBuffer());
1396         m_bNetRun = true;
1397       }
1398       else
1399       {
1400         Sys_Printf("Netrun mode is disabled\n");
1401       }
1402     }
1403   }
1404 }
1405
1406 bool CGameDialog::GetNetrun()
1407 {
1408   return m_bNetRun;
1409 }
1410 #endif
1411
1412 /*
1413 ========
1414
1415 very first prefs init deals with selecting the game and the game tools path
1416 then we can load .ini stuff
1417
1418 using prefs / ini settings:
1419 those are per-game
1420
1421 win32:
1422 look in g_strGameToolsPath for .ini
1423
1424 linux:
1425 look in ~/.radiant/<version>/gamename
1426 ========
1427 */
1428
1429 #define PREFS_LOCAL_FILENAME "local.pref"
1430
1431 void PrefsDlg::Init()
1432 {
1433   mGamesDialog.Init();
1434
1435   // m_global_rc_path has been set above, do m_rc_path with game specific stuff now
1436   // the win32 and linux versions have been unified for network mode
1437 #ifdef _WIN32
1438   if (!CGameDialog::GetNetrun())
1439   {
1440     // legacy prefs settings, this goes where the game pack is installed
1441     m_rc_path = g_string_new (g_strGameToolsPath.GetBuffer() );
1442     m_inipath = g_string_new (m_rc_path->str);
1443     g_string_append (m_inipath, PREFS_LOCAL_FILENAME);
1444     return;
1445   }
1446 #endif
1447   // this is common to win32 and Linux init now
1448   m_rc_path = g_string_new (m_global_rc_path->str);
1449
1450   // game sub-dir
1451   g_string_append (m_rc_path, g_pGameDescription->mGameFile.GetBuffer());
1452   g_string_append (m_rc_path, "/");
1453   Q_mkdir (m_rc_path->str, 0775);
1454
1455   // then the ini file
1456   m_inipath = g_string_new (m_rc_path->str);
1457   g_string_append (m_inipath, PREFS_LOCAL_FILENAME);
1458
1459 }
1460
1461 void PrefsDlg::UpdateData (bool retrieve)
1462 {
1463   // leo: the "changed" signal confuses the update function
1464   if (m_pWidget == NULL)
1465     return;
1466   mGamesDialog.UpdateData (retrieve);
1467   Dialog::UpdateData (retrieve);
1468 }
1469
1470 #ifdef _WIN32
1471 #define PREFSHSPACE 5
1472 #else
1473 #define PREFSHSPACE 0
1474 #endif
1475
1476 static void UpdateSensitivity( GtkWidget *widget, gpointer data )
1477 {
1478   PrefsDlg *dlg = (PrefsDlg*)data;
1479   dlg->DoSensitivity();
1480 }
1481
1482 static void UpdateEditorSensitivity(GtkWidget *widget, gpointer data)
1483 {
1484   PrefsDlg *dlg = (PrefsDlg*)data;
1485   dlg->DoEditorSensitivity();
1486 }
1487
1488 // start new prefs dialog
1489
1490 /*! Utility function for swapping notebook pages for tree list selections */
1491 void PrefsDlg::showPrefPage(int prefpage)
1492 {
1493   if(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)) != prefpage)
1494     gtk_notebook_set_page(GTK_NOTEBOOK(notebook), prefpage);
1495
1496   return;
1497 }
1498
1499 static void treeSelection(GtkTreeSelection* selection, gpointer data)
1500 {
1501   PrefsDlg *dlg = (PrefsDlg*)data;
1502
1503   GtkTreeModel* model;
1504   GtkTreeIter selected;
1505   if(gtk_tree_selection_get_selected(selection, &model, &selected))
1506   {
1507     int prefpage;
1508     gtk_tree_model_get(model, &selected, 1, (gpointer*)&prefpage, -1);
1509     dlg->showPrefPage(prefpage);
1510   }
1511 }
1512
1513 void PrefsDlg::BuildDialog ()
1514 {
1515   // Main Preferences dialog
1516   GtkWidget *dialog, *mainvbox, *hbox, *sc_win, *preflabel;
1517
1518   // Widgets on notebook pages
1519   GtkWidget *check, *label, *scale, *hbox2, *combo,
1520             *table, *spin,  *entry, *pixmap,
1521             *radio, *button, *pageframe, *vbox;
1522
1523   GList *combo_list = (GList*)NULL;
1524
1525   GtkObject *adj;
1526
1527   dialog = m_pWidget;
1528   gtk_window_set_title(GTK_WINDOW(dialog), "GtkRadiant Preferences");
1529   gtk_widget_realize(dialog);
1530
1531   mainvbox = gtk_vbox_new(FALSE, 5);
1532   gtk_container_add(GTK_CONTAINER(dialog), mainvbox);
1533   gtk_container_set_border_width(GTK_CONTAINER(mainvbox), 5);
1534   gtk_widget_show(mainvbox);
1535
1536   hbox = gtk_hbox_new(FALSE, 5);
1537   gtk_widget_show(hbox);
1538   gtk_box_pack_end(GTK_BOX(mainvbox), hbox, FALSE, TRUE, 0);
1539
1540   button = gtk_button_new_with_label("OK");
1541   gtk_widget_show(button);
1542   gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1543   gtk_widget_set_usize(button, 60, -2);
1544   AddModalButton(button, IDOK);
1545
1546   button = gtk_button_new_with_label("Cancel");
1547   gtk_widget_show(button);
1548   gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1549   gtk_widget_set_usize(button, 60, -2);
1550   AddModalButton(button, IDCANCEL);
1551
1552   button = gtk_button_new_with_label ("Clean");
1553   gtk_widget_show(button);
1554   gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(OnButtonClean), this);
1555   gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1556   gtk_widget_set_usize (button, 60, -2);
1557
1558   hbox = gtk_hbox_new(FALSE, 5);
1559   gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 0);
1560   gtk_widget_show(hbox);
1561
1562   sc_win = gtk_scrolled_window_new(NULL, NULL);
1563   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sc_win), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1564   gtk_box_pack_start(GTK_BOX(hbox), sc_win, FALSE, FALSE, 0);
1565   gtk_widget_show(sc_win);
1566
1567   // prefs pages notebook
1568   notebook = gtk_notebook_new();
1569   // hide the notebook tabs since its not supposed to look like a notebook
1570   gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
1571   gtk_box_pack_start(GTK_BOX(hbox), notebook, TRUE, TRUE, 0);
1572   gtk_widget_show(notebook);
1573
1574   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sc_win), GTK_SHADOW_IN);
1575
1576   {
1577     GtkTreeStore* store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
1578
1579     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1580     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
1581
1582     {
1583       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1584       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Preferences", renderer, "text", 0, NULL);
1585       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1586     }
1587
1588     {
1589       GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
1590       g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(treeSelection), this);
1591     }
1592
1593     gtk_widget_show(view);
1594
1595     gtk_container_add(GTK_CONTAINER (sc_win), view);
1596
1597     {
1598       /********************************************************************/
1599       /* Add preference tree options                                      */
1600       /********************************************************************/
1601       {
1602         GtkTreeIter group;
1603         gtk_tree_store_append(store, &group, NULL);
1604         gtk_tree_store_set(store, &group, 0, "Globals", 1, PTAB_FRONT, -1);
1605         {
1606           GtkTreeIter tab;
1607           gtk_tree_store_append(store, &tab, &group);
1608           gtk_tree_store_set(store, &tab, 0, "Game settings", 1, (gpointer)PTAB_GAME_SETTINGS, -1);
1609         }
1610       }
1611
1612       {
1613         GtkTreeIter group;
1614         gtk_tree_store_append(store, &group, NULL);
1615         gtk_tree_store_set(store, &group, 0, "Display", 1, PTAB_FRONT, -1);
1616         {
1617           GtkTreeIter tab;
1618           gtk_tree_store_append(store, &tab, &group);
1619           gtk_tree_store_set(store, &tab, 0, "2D Display/Rendering", 1, (gpointer)PTAB_2D, -1);
1620         }
1621         {
1622           GtkTreeIter tab;
1623           gtk_tree_store_append(store, &tab, &group);
1624           gtk_tree_store_set(store, &tab, 0, "3D View", 1, (gpointer)PTAB_CAMERA, -1);
1625         }
1626         {
1627           GtkTreeIter tab;
1628           gtk_tree_store_append(store, &tab, &group);
1629           gtk_tree_store_set(store, &tab, 0, "Texture Settings", 1, (gpointer)PTAB_TEXTURE, -1);
1630         }
1631       }
1632
1633       {
1634         GtkTreeIter group;
1635         gtk_tree_store_append(store, &group, NULL);
1636         gtk_tree_store_set(store, &group, 0, "Interface", 1, PTAB_FRONT, -1);
1637         {
1638           GtkTreeIter tab;
1639           gtk_tree_store_append(store, &tab, &group);
1640           gtk_tree_store_set(store, &tab, 0, "Layout", 1, (gpointer)PTAB_LAYOUT, -1);
1641         }
1642         {
1643           GtkTreeIter tab;
1644           gtk_tree_store_append(store, &tab, &group);
1645           gtk_tree_store_set(store, &tab, 0, "Mouse", 1, (gpointer)PTAB_MOUSE, -1);
1646         }
1647         {
1648           GtkTreeIter tab;
1649           gtk_tree_store_append(store, &tab, &group);
1650           gtk_tree_store_set(store, &tab, 0, "Editing", 1, (gpointer)PTAB_EDITING, -1);
1651         }
1652       }
1653
1654       {
1655         GtkTreeIter group;
1656         gtk_tree_store_append(store, &group, NULL);
1657         gtk_tree_store_set(store, &group, 0, "Other", 1, PTAB_FRONT, -1);
1658         {
1659           GtkTreeIter tab;
1660           gtk_tree_store_append(store, &tab, &group);
1661           gtk_tree_store_set(store, &tab, 0, "Startup/Auto save", 1, (gpointer)PTAB_STARTUP, -1);
1662         }
1663         {
1664           GtkTreeIter tab;
1665           gtk_tree_store_append(store, &tab, &group);
1666           gtk_tree_store_set(store, &tab, 0, "Paths", 1, (gpointer)PTAB_PATHS, -1);
1667         }
1668         {
1669           GtkTreeIter tab;
1670           gtk_tree_store_append(store, &tab, &group);
1671           gtk_tree_store_set(store, &tab, 0, "Misc", 1, (gpointer)PTAB_MISC, -1);
1672         }
1673         if (!g_qeglobals.bBSPFrontendPlugin)
1674         {
1675           GtkTreeIter tab;
1676           gtk_tree_store_append(store, &tab, &group);
1677           gtk_tree_store_set(store, &tab, 0, "BSP Monitoring", 1, (gpointer)PTAB_BSPMONITOR, -1);
1678         }
1679       }
1680     }
1681
1682     gtk_tree_view_expand_all(GTK_TREE_VIEW(view));
1683
1684     g_object_unref(G_OBJECT(store));
1685   }
1686
1687   /**********************************************************************/
1688   /* build the prefs pages                                              */
1689   /**********************************************************************/
1690
1691   // Front page...
1692   // todo : add something interesting here
1693   // NOTE TTimo: tip of the day? or a logo?
1694   preflabel = gtk_label_new("Front Page");
1695   gtk_widget_show(preflabel);
1696   pageframe = gtk_frame_new(NULL);
1697   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
1698   gtk_widget_show(pageframe);
1699   vbox = gtk_vbox_new(FALSE, 5);
1700   gtk_widget_show(vbox);
1701   gtk_widget_set_usize(GTK_WIDGET(vbox), 350, -2);
1702   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
1703   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
1704
1705   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
1706
1707   /******** global preferences group ****************************/
1708   preflabel = gtk_label_new("Globals");
1709   gtk_widget_show(preflabel);
1710
1711   pageframe = mGamesDialog.GetGlobalFrame();
1712   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
1713
1714   /******** 2D prefs group (xy views/rendering options) *********/
1715   preflabel = gtk_label_new("2D Display");
1716   gtk_widget_show(preflabel);
1717   pageframe = gtk_frame_new("2D Display");
1718   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
1719   gtk_widget_show(pageframe);
1720   vbox = gtk_vbox_new(FALSE, 5);
1721   gtk_widget_show(vbox);
1722   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
1723   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
1724
1725   // OpenGL Display Lists
1726   check = gtk_check_button_new_with_label("OpenGL Display Lists");
1727   gtk_widget_show(check);
1728   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
1729   AddDialogData(check, &m_bDisplayLists, DLG_CHECK_BOOL);
1730
1731   // Antialiased points & lines
1732   // Fishman - Add antialiazed points and lines support. 09/03/00
1733   check = gtk_check_button_new_with_label ("OpenGL antialiased points and lines");
1734   gtk_widget_show (check);
1735   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1736   AddDialogData (check, &m_bAntialiasedPointsAndLines, DLG_CHECK_BOOL);
1737
1738   // Solid selection boxes
1739   check = gtk_check_button_new_with_label ("Solid selection boxes");
1740   gtk_widget_show (check);
1741   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1742   AddDialogData (check, &m_bNoStipple, DLG_CHECK_BOOL);
1743
1744   // Display size info
1745   check = gtk_check_button_new_with_label ("Display size info");
1746   gtk_widget_show (check);
1747   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
1748   AddDialogData (check, &m_bSizePaint, DLG_CHECK_BOOL);
1749
1750   // Alternate vertex/edge handles
1751   // Gef: Kyro GL_POINT work around 25-aug-2001
1752   check = gtk_check_button_new_with_label ("Alternate vertex/edge handles");
1753   gtk_widget_show(check);
1754   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
1755   AddDialogData(check, &m_bGlPtWorkaround, DLG_CHECK_BOOL);
1756
1757   g_list_free (combo_list);
1758
1759 #ifdef ATIHACK_812
1760         // ATI bugs
1761         // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=812
1762         check = gtk_check_button_new_with_label ("ATI cards with broken drivers - bug #802");
1763         gtk_widget_show(check);
1764         gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
1765         AddDialogData(check, &m_bGlATIHack, DLG_CHECK_BOOL);
1766 #endif
1767
1768   // Add the page to the notebook
1769   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
1770
1771   /******** 3D Camera view group *********/
1772   preflabel = gtk_label_new("3D View");
1773   gtk_widget_show(preflabel);
1774   pageframe = gtk_frame_new("3D View");
1775   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
1776   gtk_widget_show(pageframe);
1777   vbox = gtk_vbox_new(FALSE, 5);
1778   gtk_widget_show(vbox);
1779   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
1780   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
1781
1782   // Directional velocity (Movement Velocity)
1783   // label container
1784   hbox2 = gtk_hbox_new (FALSE, 0);
1785   gtk_widget_show (hbox2);
1786   gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0);
1787
1788   // label
1789   label = gtk_label_new("Movement Velocity");
1790   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1791   gtk_widget_show(label);
1792   gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1793
1794   // adjustment
1795   adj = gtk_adjustment_new(100, 50, 300, 1, 10, 10);
1796   AddDialogData(adj, &m_nMoveSpeed, DLG_ADJ_INT);
1797
1798   // scale
1799   scale = gtk_hscale_new(GTK_ADJUSTMENT(adj));
1800   gtk_widget_show(scale);
1801   gtk_box_pack_start(GTK_BOX (vbox), scale, FALSE, TRUE, 2);
1802
1803   gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
1804
1805   // Angular velocity (Rotational Velocity)
1806   // label container
1807   hbox2 = gtk_hbox_new (FALSE, 0);
1808   gtk_widget_show (hbox2);
1809   gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0);
1810
1811   // label
1812   label = gtk_label_new ("Rotational Velocity");
1813   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1814   gtk_widget_show (label);
1815   gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1816
1817   // adjustment
1818   adj = gtk_adjustment_new (3, 1, 180, 1, 10, 10); // value, low, high, step, page_step, page_size
1819   AddDialogData (adj, &m_nAngleSpeed, DLG_ADJ_INT);
1820
1821   // scale
1822   scale = gtk_hscale_new (GTK_ADJUSTMENT (adj));
1823   gtk_widget_show (scale);
1824   gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, TRUE, 2);
1825   gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
1826
1827   // Text under the velocity sliders
1828   // container
1829   hbox2 = gtk_hbox_new (FALSE, 0);
1830   gtk_widget_show (hbox2);
1831   gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0);
1832
1833   // label
1834   label = gtk_label_new ("slow");
1835   gtk_widget_show (label);
1836   gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1837
1838   // label
1839   label = gtk_label_new ("fast");
1840   gtk_widget_show (label);
1841   gtk_box_pack_end (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1842
1843   // Allow drag to select multiple faces/brushes
1844   // container
1845   table = gtk_table_new(2, 1, FALSE);
1846   gtk_widget_show(table);
1847   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
1848   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
1849   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
1850
1851   label = gtk_label_new ("Use paint-select in camera view:");
1852   gtk_widget_show (label);
1853   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1854   gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
1855                   (GtkAttachOptions) (0),
1856                   (GtkAttachOptions) (0), 0, 0);
1857
1858   combo_list = NULL;
1859   combo_list = g_list_append (combo_list, (void *)"No");
1860   combo_list = g_list_append (combo_list, (void *)"Yes");
1861   combo_list = g_list_append (combo_list, (void *)"Yes (Classic Key Setup)");
1862
1863   combo = gtk_combo_new ();
1864   gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
1865   gtk_widget_show (combo);
1866   gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1,
1867                   (GtkAttachOptions) (GTK_FILL),
1868                   (GtkAttachOptions) (0), 0, 0);
1869   gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE);
1870   AddDialogData (combo, &m_nCamDragMultiSelect, DLG_COMBO_INT);
1871
1872   // Freelook in Camera view
1873   check = gtk_check_button_new_with_label ("Freelook in Camera view");
1874   gtk_widget_show (check);
1875   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1876   gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT);
1877   AddDialogData (check, &m_bCamFreeLook, DLG_CHECK_BOOL);
1878
1879   // Freelook in Camera view w/ forward & back strafing instead of up and down looking
1880   check = gtk_check_button_new_with_label ("Freelook strafes Forward and Back");
1881   gtk_widget_show (check);
1882   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1883   gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT);
1884   AddDialogData (check, &m_bCamFreeLookStrafe, DLG_CHECK_BOOL);
1885
1886   // Invert mouse in freelook
1887   check = gtk_check_button_new_with_label ("Invert mouse in freelook");
1888   gtk_widget_show (check);
1889   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1890   gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT);
1891   AddDialogData (check, &m_bCamInverseMouse, DLG_CHECK_BOOL);
1892
1893   // Discrete movement
1894   check = gtk_check_button_new_with_label ("Discrete movement");
1895   gtk_widget_show (check);
1896   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1897   gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT);
1898   AddDialogData (check, &m_bCamDiscrete, DLG_CHECK_BOOL);
1899
1900   // Update XY views on camera move
1901   check = gtk_check_button_new_with_label ("Update XY views on camera move");
1902   gtk_widget_show (check);
1903   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1904   gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT);
1905   AddDialogData (check, &m_bCamXYUpdate, DLG_CHECK_BOOL);
1906
1907   // Add the page to the notebook
1908   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
1909
1910   /******** Texture group *********/
1911   preflabel = gtk_label_new("Textures");
1912   gtk_widget_show(preflabel);
1913   pageframe = gtk_frame_new("Textures");
1914   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
1915   gtk_widget_show(pageframe);
1916   vbox = gtk_vbox_new(FALSE, 6);
1917   gtk_widget_show(vbox);
1918   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
1919   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
1920
1921   // Texture quality slider
1922   // label
1923   label = gtk_label_new ("Texture quality");
1924   gtk_widget_show (label);
1925   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
1926   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1927   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1928
1929   // adjustment
1930   adj = gtk_adjustment_new (0, 0, 4, 1, 1, 1);
1931   AddDialogData (adj, &m_nLatchedTextureQuality, DLG_ADJ_INT);
1932
1933   // scale
1934   scale = gtk_hscale_new (GTK_ADJUSTMENT (adj));
1935   gtk_widget_show (scale);
1936   gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
1937   gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
1938
1939   // text under the texture slider
1940   hbox2 = gtk_hbox_new (FALSE, 0);
1941   gtk_widget_show (hbox2);
1942   gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0);
1943   label = gtk_label_new ("low");
1944   gtk_widget_show (label);
1945   gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1946   label = gtk_label_new ("high");
1947   gtk_widget_show (label);
1948   gtk_box_pack_end (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1949
1950   // texture subsets
1951   check = gtk_check_button_new_with_label ("Texture subsets");
1952   gtk_widget_show (check);
1953   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1954   AddDialogData (check, &m_bTextureWindow, DLG_CHECK_BOOL);
1955
1956   // texture scrollbar
1957   check = gtk_check_button_new_with_label ("Texture scrollbar");
1958   gtk_widget_show (check);
1959   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1960   AddDialogData (check, &m_bTextureScrollbar, DLG_CHECK_BOOL);
1961
1962   // texture increment matches grid
1963   check = gtk_check_button_new_with_label ("Tex increment matches grid");
1964   gtk_widget_show (check);
1965   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
1966   AddDialogData (check, &m_bSnapTToGrid, DLG_CHECK_BOOL);
1967
1968   // RIANT
1969   // Texture compression choice label
1970   // container
1971   table = gtk_table_new(2, 1, FALSE);
1972   gtk_widget_show(table);
1973   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
1974   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
1975   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
1976
1977   label = gtk_label_new ("Texture Compression (if available):");
1978   gtk_widget_show (label);
1979   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1980   gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
1981                   (GtkAttachOptions) (0),
1982                   (GtkAttachOptions) (0), 0, 0);
1983   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1984
1985   // Texture compression choice label
1986   combo_list = NULL;
1987   // NONE will always be in pos 0
1988   combo_list = g_list_append (combo_list, (void *)"None");
1989
1990   // if OpenGL compression is enabled it will always be
1991   // in pos 1
1992   if (g_qeglobals.m_bOpenGLCompressionSupported)
1993   {
1994     combo_list = g_list_append (combo_list, (void *)"OpenGL ARB");
1995   }
1996
1997   // If S3 is enabled offer all 3 valid compression schemes in RGBA
1998   if (g_qeglobals.m_bS3CompressionSupported)
1999   {
2000     combo_list = g_list_append (combo_list, (void *)"S3TC DXT1");
2001     combo_list = g_list_append (combo_list, (void *)"S3TC DXT3");
2002     combo_list = g_list_append (combo_list, (void *)"S3TC DXT5");
2003   }
2004
2005   combo = gtk_combo_new ();
2006   gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
2007   gtk_widget_show (combo);
2008   gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1,
2009                   (GtkAttachOptions) (GTK_FILL),
2010                   (GtkAttachOptions) (0), 0, 0);
2011   gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE);
2012   AddDialogData (combo, &m_nTextureCompressionFormat, DLG_COMBO_INT);
2013   g_list_free (combo_list);
2014
2015   // container
2016   table = gtk_table_new(2, 1, FALSE);
2017   gtk_widget_show(table);
2018   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
2019   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2020   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2021
2022   // Startup shaders
2023   // label
2024   label = gtk_label_new ("Startup Shaders:");
2025   gtk_widget_show (label);
2026   gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
2027   gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
2028                   (GtkAttachOptions) (0),
2029                   (GtkAttachOptions) (0), 0, 0);
2030   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2031
2032   // combo list
2033   combo_list = NULL;
2034   combo_list = g_list_append (combo_list, (void *)"None");
2035   if (g_pGameDescription->mGameFile == "jk2.game" || g_pGameDescription->mGameFile == "ja.game")
2036     combo_list = g_list_append (combo_list, (void *)"System");
2037   else if (g_pGameDescription->mGameFile == "sof2.game")
2038     combo_list = g_list_append (combo_list, (void *)"Tools");
2039   else
2040     combo_list = g_list_append (combo_list, (void *)"Common");
2041   combo_list = g_list_append (combo_list, (void *)"All");
2042   combo = gtk_combo_new ();
2043   gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
2044   gtk_widget_show (combo);
2045   gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1,
2046                   (GtkAttachOptions) (GTK_FILL),
2047                   (GtkAttachOptions) (0), 0, 0);
2048   gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE);
2049   AddDialogData (combo, &m_nLatchedShader, DLG_COMBO_INT);
2050   g_list_free (combo_list);
2051
2052   // Add the page to the notebook
2053   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2054
2055   /******** Layout group *********/
2056   preflabel = gtk_label_new("Layout");
2057   gtk_widget_show(preflabel);
2058   pageframe = gtk_frame_new("Layout");
2059   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2060   gtk_widget_show(pageframe);
2061   vbox = gtk_vbox_new(FALSE, 5);
2062   gtk_widget_show(vbox);
2063   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2064   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2065
2066   // View types
2067   // table
2068   table = gtk_table_new (2, 4, FALSE);
2069   gtk_widget_show (table);
2070   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
2071   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2072   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2073
2074   // view type 1
2075   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window1.bmp");
2076   gtk_widget_show (pixmap);
2077   gtk_table_attach (GTK_TABLE (table), pixmap, 0, 1, 0, 1,
2078                     (GtkAttachOptions) (0),
2079                     (GtkAttachOptions) (0), 0, 0);
2080
2081   // view type 2
2082   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window2.bmp");
2083   gtk_widget_show (pixmap);
2084   gtk_table_attach (GTK_TABLE (table), pixmap, 1, 2, 0, 1,
2085                     (GtkAttachOptions) (0),
2086                     (GtkAttachOptions) (0), 0, 0);
2087
2088   // view type 3
2089   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window3.bmp");
2090   gtk_widget_show (pixmap);
2091   gtk_table_attach (GTK_TABLE (table), pixmap, 2, 3, 0, 1,
2092                     (GtkAttachOptions) (0),
2093                     (GtkAttachOptions) (0), 0, 0);
2094
2095   // view type 4
2096   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window4.bmp");
2097   gtk_widget_show (pixmap);
2098   gtk_table_attach (GTK_TABLE (table), pixmap, 3, 4, 0, 1,
2099                     (GtkAttachOptions) (0),
2100                     (GtkAttachOptions) (0), 0, 0);
2101
2102   // view type 1 selector
2103   radio = gtk_radio_button_new (NULL);
2104   gtk_widget_show (radio);
2105   gtk_table_attach (GTK_TABLE (table), radio, 0, 1, 1, 2,
2106                     (GtkAttachOptions) (0),
2107                     (GtkAttachOptions) (0), 0, 0);
2108
2109   // view type 2 selector
2110   radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio));
2111   gtk_widget_show (radio);
2112   gtk_table_attach (GTK_TABLE (table), radio, 1, 2, 1, 2,
2113                     (GtkAttachOptions) (0),
2114                     (GtkAttachOptions) (0), 0, 0);
2115
2116   // view type 3 selector
2117   radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio));
2118   gtk_widget_show (radio);
2119   gtk_table_attach (GTK_TABLE (table), radio, 2, 3, 1, 2,
2120                     (GtkAttachOptions) (0),
2121                     (GtkAttachOptions) (0), 0, 0);
2122
2123   // view type 4 selector
2124   radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio));
2125   gtk_widget_show (radio);
2126   gtk_table_attach (GTK_TABLE (table), radio, 3, 4, 1, 2,
2127                     (GtkAttachOptions) (0),
2128                     (GtkAttachOptions) (0), 0, 0);
2129   AddDialogData (radio, &m_nLatchedView, DLG_RADIO_INT);
2130
2131   // Floating Z window
2132   check = gtk_check_button_new_with_label ("Floating Z Window");
2133   gtk_widget_show (check);
2134   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2135   AddDialogData (check, &m_bLatchedFloatingZ, DLG_CHECK_BOOL);
2136
2137   // show menu tear-off seperators
2138   check = gtk_check_button_new_with_label ("Detachable Menus");
2139   gtk_widget_show (check);
2140   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2141   AddDialogData (check, &m_bLatchedDetachableMenus, DLG_CHECK_BOOL);
2142
2143   if (!g_pGameDescription->mNoPatch)
2144   {
2145     // show patch toolbar
2146     check = gtk_check_button_new_with_label ("Patch Toolbar");
2147     gtk_widget_show (check);
2148     gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2149     g_object_set_data (G_OBJECT (dialog), "check_patchtoolbar", check); // Allow to be disabled for Q1/Q2
2150     AddDialogData (check, &m_bLatchedPatchToolbar, DLG_CHECK_BOOL);
2151   }
2152
2153   // use wide toolbar
2154   check = gtk_check_button_new_with_label ("Wide Toolbar");
2155   gtk_widget_show (check);
2156   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2157   AddDialogData (check, &m_bLatchedWideToolbar, DLG_CHECK_BOOL);
2158
2159   // use plugin toolbar
2160   check = gtk_check_button_new_with_label ("Plugin Toolbar");
2161   gtk_widget_show (check);
2162   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2163   AddDialogData (check, &m_bLatchedPluginToolbar, DLG_CHECK_BOOL);
2164
2165 #ifdef _WIN32
2166   // win32 file dialog
2167   check = gtk_check_button_new_with_label ("Use win32 file load dialog");
2168   gtk_widget_show (check);
2169   // gtk_container_add (GTK_CONTAINER (vbox), check);
2170   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2171   AddDialogData (check, &m_bNativeGUI, DLG_CHECK_BOOL);
2172
2173   // position on primary monitor
2174   check = gtk_check_button_new_with_label ("Start on Primary Monitor");
2175   gtk_widget_show (check);
2176   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2177   g_object_set_data (G_OBJECT (dialog), "check_startonprimary", check);
2178   gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateSensitivity), this );
2179   AddDialogData (check, &m_bStartOnPrimMon, DLG_CHECK_BOOL);
2180 #endif
2181
2182   // Add the page to the notebook
2183   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2184
2185   /******** Mouse group *********/
2186   preflabel = gtk_label_new("Mouse");
2187   gtk_widget_show(preflabel);
2188   pageframe = gtk_frame_new("Mouse");
2189   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2190   gtk_widget_show(pageframe);
2191   vbox = gtk_vbox_new(FALSE, 5);
2192   gtk_widget_show(vbox);
2193   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2194   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2195
2196   // Buttons
2197   // container
2198   hbox2 = gtk_hbox_new (FALSE, 5);
2199   gtk_widget_show (hbox2);
2200   gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
2201
2202   // 2 button radio
2203   radio = gtk_radio_button_new_with_label (NULL, "2 button");
2204   gtk_widget_show (radio);
2205   gtk_box_pack_start (GTK_BOX (hbox2), radio, FALSE, FALSE, 0);
2206
2207   // 3 button radio
2208   radio = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), "3 button");
2209   gtk_widget_show (radio);
2210   gtk_box_pack_start (GTK_BOX (hbox2), radio, FALSE, FALSE, 0);
2211   AddDialogData (radio, &m_nMouse, DLG_RADIO_INT);
2212
2213   // right click to drop entity
2214   check = gtk_check_button_new_with_label ("Right click to drop entities");
2215   gtk_widget_show (check);
2216   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2217   AddDialogData (check, &m_bRightClick, DLG_CHECK_BOOL);
2218
2219   // Mouse chaser (and this does what?)
2220   check = gtk_check_button_new_with_label ("Mouse chaser");
2221   gtk_widget_show (check);
2222   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2223   AddDialogData (check, &m_bChaseMouse, DLG_CHECK_BOOL);
2224
2225   // Alt + multi-drag
2226   check = gtk_check_button_new_with_label ("ALT + multi-drag");
2227   gtk_widget_show (check);
2228   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2229   AddDialogData (check, &m_bALTEdge, DLG_CHECK_BOOL);
2230
2231   // Mouse wheel increments
2232   // container
2233   hbox2 = gtk_hbox_new (FALSE, 5);
2234   gtk_widget_show (hbox2);
2235   gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
2236
2237   // label
2238   label = gtk_label_new ("Wheel Mouse inc:");
2239   gtk_widget_show (label);
2240   gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
2241
2242   // entry
2243   entry = gtk_entry_new ();
2244   gtk_widget_show (entry);
2245   gtk_widget_set_usize (entry, 40, -2);
2246   gtk_box_pack_start (GTK_BOX (hbox2), entry, FALSE, FALSE, 0);
2247   AddDialogData (entry, &m_nWheelInc, DLG_ENTRY_INT);
2248
2249   // Add the page to the notebook
2250   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2251
2252   /******** Editing group *********/
2253   preflabel = gtk_label_new("Editing");
2254   gtk_widget_show(preflabel);
2255   pageframe = gtk_frame_new("Editing");
2256   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2257   gtk_widget_show(pageframe);
2258   vbox = gtk_vbox_new(FALSE, 5);
2259   gtk_widget_show(vbox);
2260   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2261   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2262
2263   // Vertex editing splits faces
2264   check = gtk_check_button_new_with_label ("Vertex editing splits face");
2265   gtk_widget_show (check);
2266   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2267   AddDialogData (check, &m_bVertexSplit, DLG_CHECK_BOOL);
2268
2269   // Fix target/targetname collisions
2270   check = gtk_check_button_new_with_label ("Fix target/targetname collisions");
2271   gtk_widget_show (check);
2272   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2273   AddDialogData (check, &m_bDoTargetFix, DLG_CHECK_BOOL);
2274
2275   // Clipper tool uses caulk
2276   check = gtk_check_button_new_with_label ("Clipper tool uses caulk");
2277   gtk_widget_show (check);
2278   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2279   AddDialogData (check, &m_bClipCaulk, DLG_CHECK_BOOL);
2280
2281   // Don't clamp plane points
2282   check = gtk_check_button_new_with_label ("Don't clamp plane points");
2283   gtk_widget_show (check);
2284   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2285   AddDialogData (check, &m_bNoClamp, DLG_CHECK_BOOL);
2286
2287   // Select patch by bounding box
2288   check = gtk_check_button_new_with_label ("Select patches by bounding box");
2289   gtk_widget_show (check);
2290   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2291   AddDialogData (check, &m_bPatchBBoxSelect, DLG_CHECK_BOOL);
2292
2293   // Rotation increment
2294   // container
2295   table = gtk_table_new (2, 3, FALSE);
2296   gtk_widget_show (table);
2297   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
2298   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2299   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2300
2301   // label
2302   label = gtk_label_new ("Rotation increment:");
2303   gtk_widget_show (label);
2304   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2305                    (GtkAttachOptions) (0),
2306                    (GtkAttachOptions) (0), 0, 0);
2307
2308   // entry
2309   entry = gtk_entry_new ();
2310   gtk_widget_show (entry);
2311   gtk_widget_set_usize (entry, 60, -2);
2312   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
2313                    (GtkAttachOptions) (GTK_FILL),
2314                    (GtkAttachOptions) (0), 0, 0);
2315   AddDialogData (entry, &m_nRotation, DLG_ENTRY_INT);
2316
2317   // Undo levels
2318   // label
2319   label = gtk_label_new ("Undo Levels:");
2320   gtk_widget_show (label);
2321   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
2322                    (GtkAttachOptions) (0),
2323                    (GtkAttachOptions) (0), 0, 0);
2324
2325   // spinner (allows undo levels to be set to zero)
2326   spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (1, 0, 64, 1, 10, 10)), 1, 0);
2327   gtk_widget_show (spin);
2328   gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 1, 2,
2329                    (GtkAttachOptions) (GTK_FILL),
2330                    (GtkAttachOptions) (0), 0, 0);
2331   gtk_widget_set_usize (spin, 60, -2);
2332   AddDialogData (spin, &m_nUndoLevels, DLG_SPIN_INT);
2333
2334   // Patch subdivisions
2335   // label
2336   label = gtk_label_new ("Patch subdivisions:");
2337   gtk_widget_show (label);
2338   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
2339                    (GtkAttachOptions) (0),
2340                    (GtkAttachOptions) (0), 0, 0);
2341
2342   // entry (spinner perhaps? [2-16])
2343   entry = gtk_entry_new ();
2344   gtk_widget_show (entry);
2345   gtk_widget_set_usize (entry, 60, -2);
2346   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 2, 3,
2347                    (GtkAttachOptions) (GTK_FILL),
2348                    (GtkAttachOptions) (0), 0, 0);
2349   AddDialogData (entry, &m_nSubdivisions, DLG_ENTRY_INT);
2350
2351   // Add the page to the notebook
2352   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2353
2354   /******** Save/Load group *********/
2355   preflabel = gtk_label_new("Startup/Auto save");
2356   gtk_widget_show(preflabel);
2357   pageframe = gtk_frame_new("Startup/Auto save");
2358   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2359   gtk_widget_show(pageframe);
2360   vbox = gtk_vbox_new(FALSE, 5);
2361   gtk_widget_show(vbox);
2362   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2363   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2364
2365   // Snapshots
2366   check = gtk_check_button_new_with_label ("Snapshots");
2367   gtk_widget_show (check);
2368   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2369   AddDialogData (check, &m_bSnapShots, DLG_CHECK_BOOL);
2370
2371   // load last project on open
2372   check = gtk_check_button_new_with_label ("Load last project on open");
2373   gtk_widget_show (check);
2374   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2375   AddDialogData (check, &m_bLoadLast, DLG_CHECK_BOOL);
2376
2377   // load last map on open
2378   check = gtk_check_button_new_with_label ("Load last map on open");
2379   gtk_widget_show (check);
2380   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2381   AddDialogData (check, &m_bLoadLastMap, DLG_CHECK_BOOL);
2382
2383   // Auto save..
2384   // container
2385   hbox2 = gtk_hbox_new (FALSE, 5);
2386   gtk_widget_show (hbox2);
2387   gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
2388   gtk_container_set_border_width (GTK_CONTAINER (hbox2), 0);
2389
2390   // label
2391   check = gtk_check_button_new_with_label ("Auto save every");
2392   gtk_widget_show (check);
2393   gtk_box_pack_start (GTK_BOX (hbox2), check, FALSE, FALSE, 0);
2394   AddDialogData (check, &m_bAutoSave, DLG_CHECK_BOOL);
2395
2396   // spinner
2397   spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 60, 1, 10, 10)), 1, 0);
2398   gtk_widget_show (spin);
2399   gtk_box_pack_start (GTK_BOX (hbox2), spin, FALSE, FALSE, 0);
2400   gtk_widget_set_usize (spin, 60, -2);
2401   AddDialogData (spin, &m_nAutoSave, DLG_SPIN_INT);
2402
2403   // label
2404   label = gtk_label_new ("minutes");
2405   gtk_widget_show (label);
2406   gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
2407
2408   // Add the page to the notebook
2409   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2410
2411   /******** Paths group *********/
2412   preflabel = gtk_label_new("Paths");
2413   gtk_widget_show(preflabel);
2414   pageframe = gtk_frame_new("Paths");
2415   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2416   gtk_widget_show(pageframe);
2417   vbox = gtk_vbox_new(FALSE, 5);
2418   gtk_widget_show(vbox);
2419   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2420   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2421
2422   // prefab path
2423   // table
2424   table = gtk_table_new (3, 3, FALSE);
2425   gtk_widget_show (table);
2426   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
2427   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2428   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2429
2430   // label
2431   label = gtk_label_new ("Prefab path:");
2432   gtk_widget_show (label);
2433   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2434                    (GtkAttachOptions) (0),
2435                    (GtkAttachOptions) (0), 0, 0);
2436   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
2437
2438   // path entry
2439   entry = gtk_entry_new ();
2440   gtk_widget_show (entry);
2441   gtk_widget_set_usize(GTK_WIDGET(entry), 240, -2);
2442   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
2443                    (GtkAttachOptions) (GTK_FILL),
2444                    (GtkAttachOptions) (0), 1, 0);
2445   AddDialogData (entry, &m_strPrefabPath, DLG_ENTRY_TEXT);
2446
2447   // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=805
2448 #if 0
2449   // browse button
2450   button = gtk_button_new_with_label ("...");
2451   gtk_widget_show (button);
2452   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnBrowseprefab), this);
2453   gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
2454                    (GtkAttachOptions) (0),
2455                    (GtkAttachOptions) (0), 0, 0);
2456 #endif
2457
2458   // User ini path
2459   // label
2460   label = gtk_label_new ("User INI path:");
2461   gtk_widget_show (label);
2462   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
2463                    (GtkAttachOptions) (0),
2464                    (GtkAttachOptions) (0), 0, 0);
2465   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
2466
2467   // user ini path entry
2468   entry = gtk_entry_new ();
2469   gtk_widget_show (entry);
2470   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,
2471                    (GtkAttachOptions) (GTK_FILL),
2472                    (GtkAttachOptions) (0), 1, 0);
2473   AddDialogData (entry, &m_strUserPath, DLG_ENTRY_TEXT);
2474
2475   // user ini browse button
2476   button = gtk_button_new_with_label ("...");
2477   gtk_widget_show (button);
2478   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnBrowseuserini), this);
2479   gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
2480                    (GtkAttachOptions) (0),
2481                    (GtkAttachOptions) (0), 0, 0);
2482
2483   // Add the page to the notebook
2484   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2485
2486   /******** Misc group *********/
2487   preflabel = gtk_label_new("Misc");
2488   gtk_widget_show(preflabel);
2489   pageframe = gtk_frame_new("Misc");
2490   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2491   gtk_widget_show(pageframe);
2492   vbox = gtk_vbox_new(FALSE, 5);
2493   gtk_widget_show(vbox);
2494   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2495   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2496
2497   // Light drawing
2498   check = gtk_check_button_new_with_label ("Light drawing");
2499   gtk_widget_show (check);
2500   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2501   AddDialogData (check, &m_bNewLightDraw, DLG_CHECK_BOOL);
2502
2503   // Light radiuses
2504   // container
2505   table = gtk_table_new(2, 1, FALSE);
2506   gtk_widget_show(table);
2507   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
2508   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2509   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2510
2511   label = gtk_label_new ("Light radiuses:");
2512   gtk_widget_show (label);
2513   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
2514   gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
2515                   (GtkAttachOptions) (0),
2516                   (GtkAttachOptions) (0), 0, 0);
2517
2518   combo_list = NULL;
2519   combo_list = g_list_append (combo_list, (void *)"Disabled");
2520   combo_list = g_list_append (combo_list, (void *)"True Q3Map2 Style");
2521   combo_list = g_list_append (combo_list, (void *)"Classic Style");
2522
2523   combo = gtk_combo_new ();
2524   gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
2525   gtk_widget_show (combo);
2526   gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1,
2527                   (GtkAttachOptions) (GTK_FILL),
2528                   (GtkAttachOptions) (0), 0, 0);
2529   gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE);
2530   AddDialogData (combo, &m_nLightRadiuses, DLG_COMBO_INT);
2531
2532 #ifdef _WIN32
2533   check = gtk_check_button_new_with_label ("Use win32 file associations to open text files instead of builtin editor");
2534   gtk_widget_show(check);
2535   gtk_box_pack_start(GTK_BOX (vbox), check, FALSE, FALSE, 0);
2536   AddDialogData (check, &g_PrefsDlg.m_bUseWin32Editor, DLG_CHECK_BOOL);
2537 #else
2538   // use custom shader editor
2539   check = gtk_check_button_new_with_label ("Use Custom Shader Editor");
2540   gtk_widget_show(check);
2541   gtk_box_pack_start(GTK_BOX (vbox), check, FALSE, FALSE, 0);
2542   gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateEditorSensitivity), this);
2543   g_object_set_data (G_OBJECT(dialog), "check_customeditor", check);
2544   AddDialogData (check, &g_PrefsDlg.m_bUseCustomEditor, DLG_CHECK_BOOL);
2545
2546   // custom shader editor executable
2547   // table
2548   table = gtk_table_new (3, 1, FALSE);
2549   gtk_widget_show (table);
2550   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
2551   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2552   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2553
2554   // label
2555   label = gtk_label_new("Custom Editor Command");
2556   gtk_widget_show(label);
2557   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2558                    (GtkAttachOptions) (0),
2559                    (GtkAttachOptions) (0), 0, 0);
2560   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
2561   g_object_set_data (G_OBJECT(dialog), "label_customeditor", label);
2562   gtk_widget_set_sensitive (label, g_PrefsDlg.m_bUseCustomEditor);
2563
2564   // custom editor command entry
2565   entry = gtk_entry_new ();
2566   gtk_widget_show (entry);
2567   gtk_widget_set_usize(GTK_WIDGET(entry), 240, -2);
2568   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
2569                    (GtkAttachOptions) (GTK_FILL),
2570                    (GtkAttachOptions) (0), 1, 0);
2571   AddDialogData (entry, &m_strEditorCommand, DLG_ENTRY_TEXT);
2572   gtk_widget_set_sensitive (entry, g_PrefsDlg.m_bUseCustomEditor);
2573   g_object_set_data (G_OBJECT(dialog), "entry_customeditor", entry);
2574
2575   // browse button
2576   button = gtk_button_new_with_label ("...");
2577   gtk_widget_show (button);
2578   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnBrowseEditor), this);
2579   gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
2580                    (GtkAttachOptions) (0),
2581                    (GtkAttachOptions) (0), 0, 0);
2582   g_object_set_data (G_OBJECT(dialog), "button_customeditor", button);
2583   gtk_widget_set_sensitive (button, g_PrefsDlg.m_bUseCustomEditor);
2584 #endif
2585
2586   // Add the page to the notebook
2587   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2588
2589   /******** BSP Monitoring group *********/
2590   // this is never displayed if the plugin isn't available
2591   preflabel = gtk_label_new("BSP Monitoring");
2592   gtk_widget_show(preflabel);
2593   pageframe = gtk_frame_new("BSP Monitoring");
2594   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2595   gtk_widget_show(pageframe);
2596   vbox = gtk_vbox_new(FALSE, 5);
2597   gtk_widget_show(vbox);
2598   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2599   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2600
2601   // Enable BSP process monitoring
2602   check = gtk_check_button_new_with_label ("Enable BSP process monitoring");
2603   gtk_widget_show (check);
2604   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2605   g_object_set_data (G_OBJECT (dialog), "check_monitorbsp", check);
2606   gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateSensitivity), this );
2607   AddDialogData (check, &g_PrefsDlg.m_bWatchBSP, DLG_CHECK_BOOL);
2608
2609   // Stop on leak
2610   check = gtk_check_button_new_with_label ("Stop compilation on leak");
2611   gtk_widget_show (check);
2612   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2613   g_object_set_data (G_OBJECT (dialog), "check_leakstop", check);
2614   AddDialogData (check, &g_PrefsDlg.m_bLeakStop, DLG_CHECK_BOOL);
2615
2616   // engine after compile
2617   check = gtk_check_button_new_with_label ("Run engine after compile");
2618   gtk_widget_show (check);
2619   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2620   g_object_set_data (G_OBJECT (dialog), "check_runengine", check);
2621   gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateSensitivity), this );
2622   AddDialogData( check, &g_PrefsDlg.m_bRunQuake, DLG_CHECK_BOOL );
2623
2624   // sleep mode when running engine
2625   check = gtk_check_button_new_with_label ("Activate sleep mode when running the engine");
2626   gtk_widget_show (check);
2627   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2628   g_object_set_data (G_OBJECT (dialog), "check_sleep", check);
2629   AddDialogData( check, &g_PrefsDlg.m_bDoSleep, DLG_CHECK_BOOL );
2630
2631   // use q3map2's texture projection
2632   check = gtk_check_button_new_with_label ("Texturing compatible with q3map2");
2633   gtk_widget_show (check);
2634   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2635   g_object_set_data (G_OBJECT (dialog), "check_q3map2", check);
2636   AddDialogData( check, &g_PrefsDlg.m_bQ3Map2Texturing, DLG_CHECK_BOOL );
2637
2638   // Add the page to the notebook
2639   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2640
2641   gtk_notebook_set_page(GTK_NOTEBOOK(notebook), PTAB_FRONT);
2642
2643   return;
2644 }
2645
2646 // end new prefs dialog
2647
2648 void PrefsDlg::LoadTexdefPref(texdef_t* pTexdef, char* pName)
2649 {
2650   char buffer[256];
2651
2652   memset(pTexdef, 0, sizeof(texdef_t));
2653
2654   sprintf(buffer, "%s%s", pName, TD_SCALE1_KEY);
2655   mLocalPrefs.GetPref(buffer, &pTexdef->scale[0],   0.5f);
2656
2657   sprintf(buffer, "%s%s", pName, TD_SCALE2_KEY);
2658   mLocalPrefs.GetPref(buffer, &pTexdef->scale[1],   0.5f);
2659
2660   sprintf(buffer, "%s%s", pName, TD_SHIFT1_KEY);
2661   mLocalPrefs.GetPref(buffer, &pTexdef->shift[0],   8.f);
2662
2663   sprintf(buffer, "%s%s", pName, TD_SHIFT2_KEY);
2664   mLocalPrefs.GetPref(buffer, &pTexdef->shift[1],   8.f);
2665
2666   sprintf(buffer, "%s%s", pName, TD_ROTATE_KEY);
2667   mLocalPrefs.GetPref(buffer, &pTexdef->rotate,     45);
2668 }
2669
2670 void PrefsDlg::UpdateTextureCompression()
2671 {
2672   // if OpenGL is not ready yet, don't do anything
2673   if (!g_qeglobals.m_bOpenGLReady) {
2674     Sys_Printf("OpenGL not ready - postpone texture compression capability check\n");
2675     return;
2676   }
2677
2678   if (g_qeglobals.bTextureCompressionSupported)
2679   {
2680     if (m_nTextureCompressionFormat >= 2 && !g_qeglobals.m_bS3CompressionSupported)
2681     {
2682       Sys_Printf("Inconsistant pref setting for texture compression (%d), rolling back\n", m_nTextureCompressionFormat);
2683       m_nTextureCompressionFormat = 1; // if this is not supported either, see below
2684     }
2685     if (m_nTextureCompressionFormat == 1 && !g_qeglobals.m_bOpenGLCompressionSupported)
2686     {
2687       Sys_Printf("Inconsistant pref setting for texture compression (GL_COMPRESSED_RGBA), rolling back\n");
2688       m_nTextureCompressionFormat = 0;
2689     }
2690     switch (m_nTextureCompressionFormat)
2691     {
2692     case (0):
2693       {
2694         g_qeglobals.texture_components = GL_RGBA;
2695         Sys_Printf("texture compression disabled by preferences settings\n");
2696         break;
2697       }
2698     case (1):
2699       {
2700         g_qeglobals.texture_components = GL_COMPRESSED_RGBA;
2701         Sys_Printf("OpenGL texture compression enabled\n");
2702         break;
2703       }
2704     case (2):
2705       {
2706         g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
2707         Sys_Printf("S3TC DXT1 texture compression enabled\n");
2708         break;
2709       }
2710     case (3):
2711       {
2712         g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
2713         Sys_Printf("S3TC DXT3 texture compression enabled\n");
2714         break;
2715       }
2716     case (4):
2717       {
2718         g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
2719         Sys_Printf("S3TC DXT5 texture compression enabled\n");
2720         break;
2721       }
2722     }
2723   }
2724   else
2725   {
2726     Sys_Printf("texture compression is not supported by your current graphic card/drivers\n");
2727     g_qeglobals.texture_components = GL_RGBA;
2728     m_nTextureCompressionFormat = 0;
2729   }
2730 }
2731
2732 #ifdef ATIHACK_812
2733 void PrefsDlg::UpdateATIHack() {
2734   // if OpenGL is not ready yet, don't do anything
2735   if (!g_qeglobals.m_bOpenGLReady) {
2736     Sys_Printf("OpenGL not ready - postpone ATI bug workaround setup\n");
2737     return;
2738   }
2739
2740   if (m_bGlATIHack) {
2741     qglCullFace = &qglCullFace_ATIHack;
2742     qglDisable = &qglDisable_ATIHack;
2743     qglEnable = &qglEnable_ATIHack;
2744     qglPolygonMode = &qglPolygonMode_ATIHack;
2745     Sys_Printf("ATI bug workaround enabled\n");
2746   } else {
2747     qglCullFace = qglCullFace_real;
2748     qglDisable = qglDisable_real;
2749     qglEnable = qglEnable_real;
2750     qglPolygonMode = qglPolygonMode_real;
2751     Sys_Printf("ATI bug workaround disabled\n");
2752   }
2753 }
2754 #endif
2755
2756 // TTimo: m_strEnginePath has a special status, if not found in registry we need to
2757 // initiliaze it for sure. It is not totally failsafe but we can use the same
2758 // code than in q3map, expecting to find some "quake" above us. If not, we prompt
2759 // for the engine executable path
2760 void PrefsDlg::LoadPrefs ()
2761 {
2762   int i;
2763
2764   // first things first, load prefs from global prefs
2765   mGamesDialog.LoadPrefs();
2766
2767   // if we already have a document loaded, we will free and reload from file
2768   if (mLocalPrefs.InUse()) {
2769     mLocalPrefs.Clear();
2770   }
2771
2772   // load local.pref file
2773   mLocalPrefs.ReadXMLFile(m_inipath->str);
2774
2775   mLocalPrefs.GetPref(PATCHSHOWBOUNDS_KEY,  &g_bPatchShowBounds,  FALSE);
2776   mLocalPrefs.GetPref(MOUSE_KEY,            &m_nMouse,            MOUSE_DEF);
2777   m_nMouseButtons = m_nMouse ? 3 : 2;
2778
2779         // project file
2780         // if it's not found here, mainframe.cpp will take care of finding one
2781   mLocalPrefs.GetPref(LASTPROJ_KEY, &m_strLastProject, "");
2782   mLocalPrefs.GetPref(LASTPROJVER_KEY, &m_nLastProjectVer, -1);
2783
2784         // prefab path
2785   // NOTE TTimo: I'm not sure why this is in prefs
2786   // should probably be a project setting
2787   // and I'm not sure that we really have a way to set this reliably either
2788   CString strPrefab;
2789   strPrefab = g_qeglobals.m_strHomeGame.GetBuffer();
2790   strPrefab += g_pGameDescription->mBaseGame.GetBuffer();
2791   strPrefab += "/prefabs/";
2792   mLocalPrefs.GetPref(PREFAB_KEY, &m_strPrefabPath, strPrefab);
2793
2794   mLocalPrefs.GetPref(LASTLIGHTINTENSITY_KEY, &m_iLastLightIntensity, 300);
2795   mLocalPrefs.GetPref(TLOCK_KEY,              &m_bTextureLock,        TLOCK_DEF);
2796   mLocalPrefs.GetPref(RLOCK_KEY,              &m_bRotateLock,         TLOCK_DEF);
2797   mLocalPrefs.GetPref(LASTMAP_KEY,            &m_strLastMap,          "");
2798   mLocalPrefs.GetPref(LOADLAST_KEY,           &m_bLoadLast,           LOADLAST_DEF);
2799   mLocalPrefs.GetPref(BSP_KEY,                &m_bInternalBSP,        FALSE);
2800   mLocalPrefs.GetPref(RCLICK_KEY,             &m_bRightClick,         TRUE);
2801   mLocalPrefs.GetPref(AUTOSAVE_KEY,           &m_bAutoSave,           TRUE);
2802   mLocalPrefs.GetPref(LOADLASTMAP_KEY,        &m_bLoadLastMap,        FALSE);
2803   mLocalPrefs.GetPref(TINYBRUSH_KEY,          &m_bCleanTiny,          FALSE);
2804   mLocalPrefs.GetPref(TINYSIZE_KEY,           &m_fTinySize,           0.5f);
2805   mLocalPrefs.GetPref(AUTOSAVETIME_KEY,       &m_nAutoSave,           5);
2806   mLocalPrefs.GetPref(SNAPSHOT_KEY,           &m_bSnapShots,          FALSE);
2807   mLocalPrefs.GetPref(MOVESPEED_KEY,          &m_nMoveSpeed,          100);
2808   mLocalPrefs.GetPref(ANGLESPEED_KEY,         &m_nAngleSpeed,         3);
2809   mLocalPrefs.GetPref(SETGAME_KEY,            &m_bSetGame,            FALSE);
2810   mLocalPrefs.GetPref(CAMXYUPDATE_KEY,        &m_bCamXYUpdate,        TRUE);
2811   mLocalPrefs.GetPref(CAMDRAGMULTISELECT_KEY, &m_nCamDragMultiSelect, TRUE);
2812   mLocalPrefs.GetPref(CAMFREELOOK_KEY,        &m_bCamFreeLook,        TRUE);
2813   mLocalPrefs.GetPref(CAMINVERSEMOUSE_KEY,    &m_bCamInverseMouse,    FALSE);
2814   mLocalPrefs.GetPref(CAMDISCRETE_KEY,        &m_bCamDiscrete,        TRUE);
2815   mLocalPrefs.GetPref(LIGHTDRAW_KEY,          &m_bNewLightDraw,       TRUE);
2816   mLocalPrefs.GetPref(CUBICCLIP_KEY,          &m_bCubicClipping,      TRUE);
2817   mLocalPrefs.GetPref(CUBICSCALE_KEY,         &m_nCubicScale,         13);
2818   mLocalPrefs.GetPref(ALTEDGE_KEY,            &m_bALTEdge,            FALSE);
2819   mLocalPrefs.GetPref(FACECOLORS_KEY,         &m_bFaceColors,         FALSE);
2820   mLocalPrefs.GetPref(XZVIS_KEY,              &m_bXZVis,              FALSE);
2821   mLocalPrefs.GetPref(YZVIS_KEY,              &m_bYZVis,              FALSE);
2822   mLocalPrefs.GetPref(ZVIS_KEY,               &m_bZVis,               FALSE);
2823   mLocalPrefs.GetPref(SIZEPAINT_KEY,          &m_bSizePaint,                  FALSE);
2824   mLocalPrefs.GetPref(DLLENTITIES_KEY,        &m_bDLLEntities,                FALSE);
2825
2826   mLocalPrefs.GetPref(DETACHABLEMENUS_KEY,    &m_bLatchedDetachableMenus,            TRUE);
2827   m_bDetachableMenus = m_bLatchedDetachableMenus;
2828
2829   if (g_pGameDescription->mNoPatch)
2830   {
2831     m_bPatchToolbar = false;
2832   }
2833   else
2834   {
2835     mLocalPrefs.GetPref(PATCHTOOLBAR_KEY,       &m_bLatchedPatchToolbar,               TRUE);
2836     m_bPatchToolbar = m_bLatchedPatchToolbar;
2837   }
2838
2839   mLocalPrefs.GetPref(WIDETOOLBAR_KEY,        &m_bLatchedWideToolbar,                TRUE);
2840   m_bWideToolbar = m_bLatchedWideToolbar;
2841
2842   mLocalPrefs.GetPref(PLUGINTOOLBAR_KEY, &m_bLatchedPluginToolbar, TRUE);
2843   m_bPluginToolbar = m_bLatchedPluginToolbar;
2844
2845   mLocalPrefs.GetPref(WINDOW_KEY,             (int*)&m_nLatchedView,  WINDOW_DEF);
2846   m_nView = m_nLatchedView;
2847
2848   mLocalPrefs.GetPref(FLOATINGZ_KEY,          &m_bLatchedFloatingZ,           FALSE);
2849   m_bFloatingZ = m_bLatchedFloatingZ;
2850
2851   mLocalPrefs.GetPref(TEXTUREQUALITY_KEY,     &m_nLatchedTextureQuality,             3);
2852   m_nTextureQuality = m_nLatchedTextureQuality;
2853
2854   mLocalPrefs.GetPref(LOADSHADERS_KEY,        &m_nLatchedShader,                     0);
2855   m_nShader = m_nLatchedShader;
2856
2857   mLocalPrefs.GetPref(NOCLAMP_KEY,            &m_bNoClamp,                    FALSE);
2858   mLocalPrefs.GetPref(USERINI_KEY,            &m_strUserPath,                 "");
2859   mLocalPrefs.GetPref(ROTATION_KEY,           &m_nRotation,                   45);
2860   mLocalPrefs.GetPref(CHASEMOUSE_KEY,         &m_bChaseMouse,                 TRUE);
2861   mLocalPrefs.GetPref(ENTITYSHOW_KEY,         &m_nEntityShowState,            ENTITY_SKINNED_BOXED);
2862
2863   // this will probably need to be 75 or 100 for Q1.
2864   mLocalPrefs.GetPref(TEXTURESCALE_KEY,       &m_nTextureScale,               50);
2865
2866   // FIXME: Hydra - actually, this stuff is Q1,Q2 and HL specific.
2867   if ( (g_pGameDescription->mGameFile == "hl.game") )
2868   {
2869     // No BSP monitoring in the default compiler tools for Half-life (yet)
2870     mLocalPrefs.GetPref(WATCHBSP_KEY,           &m_bWatchBSP,                   FALSE);
2871
2872     // Texture subset on by default (HL specific really, because of halflife.wad's size)
2873     mLocalPrefs.GetPref(TEXTURE_KEY,            &m_bTextureWindow,              TRUE);
2874   }
2875   else if ( ( g_pGameDescription->mGameFile == "q2.game" ) || ( g_pGameDescription->mGameFile == "heretic2.game" ) )
2876   {
2877     // BSP monitoring is implemented in Quake2 and Heretic2 tools
2878     mLocalPrefs.GetPref(WATCHBSP_KEY,           &m_bWatchBSP,                   TRUE);
2879
2880     // Texture subset on by default (HL specific really, because of halflife.wad's size)
2881     mLocalPrefs.GetPref(TEXTURE_KEY,            &m_bTextureWindow,              TRUE);
2882   }
2883   else
2884   {
2885     mLocalPrefs.GetPref(WATCHBSP_KEY,           &m_bWatchBSP,                   WATCHBSP_DEF);
2886     mLocalPrefs.GetPref(TEXTURE_KEY,            &m_bTextureWindow,              FALSE);
2887   }
2888
2889
2890   mLocalPrefs.GetPref(TEXTURESCROLLBAR_KEY,   &m_bTextureScrollbar,           TRUE);
2891   mLocalPrefs.GetPref(DISPLAYLISTS_KEY,       &m_bDisplayLists,               TRUE);
2892   mLocalPrefs.GetPref(ANTIALIASEDLINES_KEY,   &m_bAntialiasedPointsAndLines,  FALSE);
2893   mLocalPrefs.GetPref(SWITCHCLIP_KEY,         &m_bSwitchClip,                 TRUE);
2894   mLocalPrefs.GetPref(SELWHOLEENTS_KEY,       &m_bSelectWholeEntities,        TRUE);
2895   mLocalPrefs.GetPref(SHOWSHADERS_KEY,        &m_bShowShaders,                TRUE);
2896   mLocalPrefs.GetPref(GLLIGHTING_KEY,         &m_bGLLighting,                 FALSE);
2897   mLocalPrefs.GetPref(NOSTIPPLE_KEY,          &m_bNoStipple,                  FALSE);
2898   mLocalPrefs.GetPref(UNDOLEVELS_KEY,         &m_nUndoLevels,                 30);
2899   mLocalPrefs.GetPref(VERTEXMODE_KEY,         &m_bVertexSplit,                TRUE);
2900   mLocalPrefs.GetPref(RUNQ2_KEY,              &m_bRunQuake,                   RUNQ2_DEF);
2901   mLocalPrefs.GetPref(LEAKSTOP_KEY,           &m_bLeakStop,                   TRUE);
2902   mLocalPrefs.GetPref(DOSLEEP_KEY,            &m_bDoSleep,                    FALSE);
2903   mLocalPrefs.GetPref(SELECTCURVES_KEY,       &m_bSelectCurves,               TRUE);
2904   mLocalPrefs.GetPref(SELECTMODELS_KEY,       &m_bSelectModels,               TRUE);
2905   mLocalPrefs.GetPref(SHADERLISTONLY_KEY,     &m_bTexturesShaderlistOnly,     FALSE);
2906   mLocalPrefs.GetPref(SUBDIVISIONS_KEY,       &m_nSubdivisions,               SUBDIVISIONS_DEF);
2907   mLocalPrefs.GetPref(CLIPCAULK_KEY,          &m_bClipCaulk,                  FALSE);
2908   mLocalPrefs.GetPref(SNAPTTOGRID_KEY,        &m_bSnapTToGrid,                FALSE);
2909   mLocalPrefs.GetPref(TARGETFIX_KEY,          &m_bDoTargetFix,                TRUE);
2910   mLocalPrefs.GetPref(WHEELINC_KEY,           &m_nWheelInc,                   64);
2911   mLocalPrefs.GetPref(PATCHBBOXSEL_KEY,       &m_bPatchBBoxSelect,            FALSE);
2912
2913   // Gef: Kyro GL_POINT workaround
2914   mLocalPrefs.GetPref(GLPOINTWORKAROUND_KEY,  &m_bGlPtWorkaround,             FALSE);
2915
2916   // window positioning
2917   mLocalPrefs.GetPref(ENTITYSPLIT1_KEY,       &mWindowInfo.nEntitySplit1,     -1);
2918   mLocalPrefs.GetPref(ENTITYSPLIT2_KEY,       &mWindowInfo.nEntitySplit2,     -1);
2919
2920   mLocalPrefs.GetPref(POSITIONX_KEY,          &mWindowInfo.position.x,        -1);
2921   mLocalPrefs.GetPref(POSITIONY_KEY,          &mWindowInfo.position.y,        -1);
2922   mLocalPrefs.GetPref(WIDTH_KEY,              &mWindowInfo.position.w,        -1);
2923   mLocalPrefs.GetPref(HEIGHT_KEY,             &mWindowInfo.position.h,        450);
2924
2925   const window_position_t default_window_pos = { 0, 0, 200, 200, };
2926
2927   mLocalPrefs.GetPref(ENTITYWND_KEY,          &mWindowInfo.posEntityWnd,      default_window_pos);
2928   mLocalPrefs.GetPref(MAPINFOWND_KEY,         &mWindowInfo.posMapInfoWnd,     default_window_pos);
2929   mLocalPrefs.GetPref(CAMWND_KEY,             &mWindowInfo.posCamWnd,         default_window_pos);
2930   mLocalPrefs.GetPref(ZWND_KEY,               &mWindowInfo.posZWnd,           default_window_pos);
2931   mLocalPrefs.GetPref(XYWND_KEY,              &mWindowInfo.posXYWnd,          default_window_pos);
2932   mLocalPrefs.GetPref(YZWND_KEY,              &mWindowInfo.posYZWnd,          default_window_pos);
2933   mLocalPrefs.GetPref(XZWND_KEY,              &mWindowInfo.posXZWnd,          default_window_pos);
2934   mLocalPrefs.GetPref(PATCHWND_KEY,           &mWindowInfo.posPatchWnd,       default_window_pos);
2935   mLocalPrefs.GetPref(SURFACEWND_KEY,         &mWindowInfo.posSurfaceWnd,     default_window_pos);
2936   mLocalPrefs.GetPref(ENTITYINFOWND_KEY,      &mWindowInfo.posEntityInfoWnd,  default_window_pos);
2937
2938   mLocalPrefs.GetPref(ZWIDTH_KEY,             &mWindowInfo.nZWidth,           30);
2939   mLocalPrefs.GetPref(XYHEIGHT_KEY,           &mWindowInfo.nXYHeight,         300);
2940   mLocalPrefs.GetPref(XYWIDTH_KEY,            &mWindowInfo.nXYWidth,          300);
2941   mLocalPrefs.GetPref(CAMWIDTH_KEY,           &mWindowInfo.nCamWidth,         200);
2942   mLocalPrefs.GetPref(CAMHEIGHT_KEY,          &mWindowInfo.nCamHeight,        200);
2943   mLocalPrefs.GetPref(ZFLOATWIDTH_KEY,        &mWindowInfo.nZFloatWidth,      300);
2944 #ifdef _WIN32
2945   mLocalPrefs.GetPref(STATE_KEY,              &mWindowInfo.nState,            SW_SHOW);
2946 #endif
2947
2948   // menu stuff
2949   mLocalPrefs.GetPref(COUNT_KEY,              &m_nMRUCount,                   0);
2950   for(i = 0; i < 4; i++)
2951   {
2952     char buf[64];
2953     sprintf (buf, "%s%d", FILE_KEY, i);
2954     mLocalPrefs.GetPref(buf,                  &m_strMRUFiles[i],              "");
2955   }
2956
2957   // some platform specific prefs
2958 #ifdef _WIN32
2959   mLocalPrefs.GetPref(NATIVEGUI_KEY,          &m_bNativeGUI,                  TRUE);
2960   mLocalPrefs.GetPref(STARTONPRIMMON_KEY,     &m_bStartOnPrimMon,             FALSE);
2961 #endif
2962
2963   mLocalPrefs.GetPref(SI_TEXMENU_KEY,         &g_qeglobals.d_savedinfo.iTexMenu,                ID_VIEW_BILINEARMIPMAP);
2964   mLocalPrefs.GetPref(SI_GAMMA_KEY,           &g_qeglobals.d_savedinfo.fGamma,                  1.0f);
2965   mLocalPrefs.GetPref(SI_EXCLUDE_KEY,         &g_qeglobals.d_savedinfo.exclude,                 0); // nothing filtered by default
2966   mLocalPrefs.GetPref(SI_INCLUDE_KEY,         &g_qeglobals.d_savedinfo.include,                 INCLUDE_NAMES | INCLUDE_COORDS | INCLUDE_ANGLES | INCLUDE_CAMERATINT);
2967   mLocalPrefs.GetPref(SI_SHOWNAMES_KEY,       &g_qeglobals.d_savedinfo.show_names,              FALSE);
2968   mLocalPrefs.GetPref(SI_SHOWCOORDS_KEY,      &g_qeglobals.d_savedinfo.show_coordinates,        TRUE);
2969   mLocalPrefs.GetPref(SI_SHOWANGLES_KEY,      &g_qeglobals.d_savedinfo.show_angles,             TRUE);
2970   mLocalPrefs.GetPref(SI_SHOWOUTLINES_KEY,    &g_qeglobals.d_savedinfo.show_outline,            FALSE);
2971   mLocalPrefs.GetPref(SI_SHOWAXIS_KEY,        &g_qeglobals.d_savedinfo.show_axis,               TRUE);
2972   mLocalPrefs.GetPref(SI_NOSELOUTLINES_KEY,   &g_qeglobals.d_savedinfo.bNoSelectedOutlines,     FALSE);
2973
2974   mLocalPrefs.GetPref(SI_OUTLINESTYLE_KEY,   &g_qeglobals.d_savedinfo.iSelectedOutlinesStyle,  OUTLINE_ZBUF|OUTLINE_BSEL);
2975
2976   LoadTexdefPref(&g_qeglobals.d_savedinfo.m_SIIncrement, SI_SURFACE_TEXDEF_KEY);
2977   LoadTexdefPref(&g_qeglobals.d_savedinfo.m_PIIncrement, SI_PATCH_TEXDEF_KEY);
2978
2979   // text editor binding
2980 #ifdef _WIN32
2981   mLocalPrefs.GetPref(CUSTOMSHADEREDITOR_KEY, &m_bUseWin32Editor, TRUE);
2982 #else
2983   mLocalPrefs.GetPref(CUSTOMSHADEREDITOR_KEY, &m_bUseCustomEditor, FALSE);
2984   mLocalPrefs.GetPref(CUSTOMSHADEREDITORCOMMAND_KEY, &m_strEditorCommand, "");
2985 #endif
2986
2987
2988   vec3_t vDefaultAxisColours[3] = {
2989     {0.f, 0.5f, 0.f},
2990     {0.f, 0.f, 1.f},
2991     {1.f, 0.f, 0.f},
2992   };
2993
2994   for(i = 0; i < 3; i++) {
2995     char buf[64];
2996     sprintf(buf, "%s%d", SI_AXISCOLORS_KEY, i);
2997     mLocalPrefs.GetPref(buf,   g_qeglobals.d_savedinfo.AxisColors[i], vDefaultAxisColours[i]);
2998   }
2999
3000   vec3_t vDefaultColours[COLOR_LAST] = {
3001     {0.25f, 0.25f,  0.25f},
3002     {1.f,   1.f,    1.f},
3003     {0.75f, 0.75f,  0.75f},
3004     {0.5f,  0.5f,   0.5f},
3005     {0.25f, 0.25f,  0.25f},
3006     {0.0f,  0.0f,   0.0f},
3007     {0.f,   0.f,    1.f},
3008     {0.f,   0.f,    0.f},
3009     {0.f,   0.f,    0.f},
3010     {1.f,   0.f,    0.f},
3011     {0.f,   0.f,    1.f},
3012     {0.5f,  0.f,    0.75f},
3013     {1.0f,  0.f,    0.f},
3014     {0.f,   0.f,    0.f},
3015     {0.f,   0.f,    0.f},
3016   };
3017
3018   for(i = 0; i < COLOR_LAST; i++) {
3019     char buf[64];
3020     sprintf(buf, "%s%d", SI_COLORS_KEY, i);
3021     mLocalPrefs.GetPref(buf,   g_qeglobals.d_savedinfo.colors[i], vDefaultColours[i]);
3022   }
3023
3024   mLocalPrefs.GetPref(TEXTURECOMPRESSIONFORMAT_KEY, &m_nTextureCompressionFormat, 1);
3025
3026   mLocalPrefs.GetPref(LIGHTRADIUS_KEY, &m_nLightRadiuses, TRUE);
3027
3028   mLocalPrefs.GetPref(Q3MAP2TEX_KEY, &m_bQ3Map2Texturing, TRUE);
3029
3030 #ifdef ATIHACK_812
3031         mLocalPrefs.GetPref(ATIHACK_KEY, &m_bGlATIHack, FALSE);
3032 #endif
3033
3034   Undo_SetMaxSize(m_nUndoLevels); // set it internally as well / FIXME: why not just have one global value?
3035
3036   UpdateTextureCompression();
3037
3038 #ifdef ATIHACK_812
3039   UpdateATIHack();
3040 #endif
3041
3042   if (mLocalPrefs.mbEmpty)
3043   {
3044     mLocalPrefs.mbEmpty = false;
3045     Sys_Printf("Saving local.pref with default pref values\n");
3046     SavePrefs();
3047   }
3048 }
3049
3050 void PrefsDlg::SavePrefs ()
3051 {
3052   if (g_qeglobals.disable_ini)
3053     return;
3054
3055 #ifdef _DEBUG
3056   Sys_Printf("PrefsDlg::SavePrefs\n");
3057 #endif
3058
3059   // this will take care of copying back from the dialog to the variables
3060   // NOTE: it may be overkill to call systematically before a SavePrefs, but it's safer
3061   // this will also cause an UpdateData for the mGamesDialog
3062   UpdateData(TRUE);
3063
3064   mGamesDialog.SavePrefs();
3065
3066   // update the tree and save it
3067   mLocalPrefs.UpdatePrefTree();
3068   if (!mLocalPrefs.WriteXMLFile(m_inipath->str))
3069     Sys_FPrintf(SYS_ERR, "Error occured while saving local prefs file '%s'\n", m_inipath->str);
3070
3071   if ( m_nMouse == 0 ) {
3072           m_nMouseButtons = 2;
3073   } else {
3074           m_nMouseButtons = 3;
3075   }
3076
3077 }
3078
3079 void PrefsDlg::PostModal (int code)
3080 {
3081   if (code == IDOK)
3082   {
3083     SavePrefs();
3084     // make sure the logfile is ok
3085     Sys_LogFile();
3086     #ifdef ATIHACK_812
3087       UpdateATIHack();
3088     #endif
3089     if (g_pParentWnd)
3090       g_pParentWnd->SetGridStatus();
3091     Sys_UpdateWindows(W_ALL);
3092     if (m_nUndoLevels != 0)
3093                 Undo_SetMaxSize(m_nUndoLevels);
3094   }
3095 }
3096
3097 void PrefsDlg::DoEditorSensitivity()
3098 {
3099   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_object_get_data (G_OBJECT(m_pWidget), "check_customeditor"))))
3100   {
3101     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "label_customeditor")), TRUE);
3102     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "entry_customeditor")), TRUE);
3103     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "button_customeditor")), TRUE);
3104   }
3105   else
3106   {
3107     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "label_customeditor")), FALSE);
3108     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "entry_customeditor")), FALSE);
3109     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "button_customeditor")), FALSE);
3110   }
3111 }
3112
3113 void PrefsDlg::DoSensitivity()
3114 {
3115 #if 0
3116   // first, look at the project file version ... will monitoring work?
3117   // project files now XML, guaranteed to be at least version 2
3118   if (0)//IntForKey( g_qeglobals.d_project_entity, "version" ) < 2)
3119   {
3120     if (m_bWarn)
3121     {
3122       Str Msg;
3123       Msg = "The current project file (";
3124       Msg += g_PrefsDlg.m_strLastProject;
3125       Msg += ") is not at least version 2.\nI need version 2 or above to setup BSP monitoring correctly.";
3126       gtk_MessageBox(m_pWidget, Msg.GetBuffer(), MB_OK );
3127
3128       m_bWarn = false;
3129     }
3130
3131     // go ahead, disable everybuddy
3132     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_leakstop" )), FALSE );
3133     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_monitorbsp" )), FALSE );
3134     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" )), FALSE );
3135     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), FALSE );
3136   }
3137   else
3138   {
3139 #endif
3140 //    m_bWarn = true;
3141
3142     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_leakstop" )), TRUE );
3143     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_monitorbsp" )), TRUE );
3144     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" )), TRUE );
3145     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), TRUE );
3146
3147     if ( ! gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT(m_pWidget), "check_monitorbsp" ) ) ) )
3148     {
3149       gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_leakstop" )), FALSE );
3150       gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" )), FALSE );
3151       gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), FALSE );
3152     } else if (! gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" ) ) ) )
3153     {
3154       gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), FALSE );
3155     }
3156 }
3157
3158 /*
3159 ============================================================
3160 CGameInstall
3161 ============================================================
3162 */
3163
3164 CGameInstall::CGameInstall() {
3165         memset( m_availGames, 0, sizeof( m_availGames ) );
3166 }
3167
3168 void CGameInstall::OnBtnBrowseEngine( GtkWidget *widget, gpointer data ) {
3169         Sys_Printf( "OnBtnBrowseEngine\n" );
3170
3171         CGameInstall* i = static_cast<CGameInstall*>( data );
3172         char *dir = dir_dialog( widget, "Select game directory", NULL );
3173
3174         i->UpdateData( TRUE );
3175
3176         if ( dir != NULL ) {
3177                 i->m_strEngine = dir;
3178                 i->UpdateData( FALSE );
3179                 free( dir );
3180         }
3181 }
3182
3183 void CGameInstall::OnGameSelectChanged( GtkWidget *widget, gpointer data ) {
3184         Sys_Printf( "OnGameSelectChanged\n" );
3185
3186         CGameInstall* i = static_cast<CGameInstall*>( data );
3187         i->UpdateData( TRUE );
3188         i->m_strName = gtk_combo_box_get_active_text( GTK_COMBO_BOX( widget ) );
3189         i->UpdateData( FALSE );
3190 }
3191
3192 void CGameInstall::BuildDialog() {
3193         GtkWidget *dlg, *vbox1, *button, *text, *combo, *entry, *hbox;
3194
3195         dlg = m_pWidget;
3196         gtk_window_set_title( GTK_WINDOW( dlg ), "Configure games" );
3197
3198         vbox1 = gtk_vbox_new( FALSE, 0 );
3199         gtk_widget_show( vbox1 );
3200         gtk_container_add( GTK_CONTAINER( dlg ), vbox1 );
3201
3202         text = gtk_label_new( "Select the game to configure" );
3203         gtk_widget_show( text );
3204         gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 );
3205
3206         combo = gtk_combo_box_new_text();
3207         gtk_widget_show( combo );
3208         gtk_box_pack_start( GTK_BOX( vbox1 ), combo, FALSE, FALSE, 0 );
3209
3210         //      GList *combo_list = NULL;
3211         int iGame = 0;
3212         while ( m_availGames[ iGame ] != GAME_NONE ) {
3213                 switch ( m_availGames[ iGame ] ) {
3214                 case GAME_Q2:
3215                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Quake II" );
3216                         break;
3217                 case GAME_Q3:
3218                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Quake III Arena and mods" );
3219                         break;
3220                 case GAME_URT:
3221                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Urban Terror (standalone)" );
3222                         break;
3223                 case GAME_UFOAI:
3224                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "UFO: Alien Invasion" );
3225                         break;
3226                 case GAME_Q2W:
3227                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Quake2World" );
3228                         break;
3229                 case GAME_WARSOW:
3230                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Warsow" );
3231                         break;
3232                 case GAME_NEXUIZ:
3233                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Nexuiz" );
3234                         break;
3235                 }
3236                 iGame++;
3237         }
3238         AddDialogData( combo, &m_nComboSelect, DLG_COMBO_BOX_INT );
3239         gtk_signal_connect( GTK_OBJECT( combo ), "changed", G_CALLBACK( OnGameSelectChanged ), this );
3240         gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 );  // NOTE: will trigger signal
3241
3242         text = gtk_label_new( "Name:" );
3243         gtk_widget_show( text );
3244         gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 );
3245
3246         entry = gtk_entry_new();
3247         gtk_widget_show( entry );
3248         gtk_box_pack_start( GTK_BOX( vbox1 ), entry, FALSE, FALSE, 0 );
3249         AddDialogData( entry, &m_strName, DLG_ENTRY_TEXT );
3250
3251         text = gtk_label_new( "Engine directory:" );
3252         gtk_widget_show( text );
3253         gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 );
3254
3255         hbox = gtk_hbox_new( FALSE, 0 );
3256         gtk_widget_show( hbox );
3257         gtk_box_pack_start( GTK_BOX( vbox1 ), hbox, FALSE, FALSE, 0 );
3258
3259         entry = gtk_entry_new();
3260         gtk_widget_show( entry );
3261         gtk_box_pack_start( GTK_BOX( hbox ), entry, FALSE, FALSE, 0 );
3262         AddDialogData( entry, &m_strEngine, DLG_ENTRY_TEXT );
3263
3264         button = gtk_button_new_with_label ("...");
3265         gtk_widget_show( button );
3266         gtk_signal_connect( GTK_OBJECT( button ), "clicked", GTK_SIGNAL_FUNC( OnBtnBrowseEngine ), this );
3267         gtk_box_pack_start( GTK_BOX( hbox ), button, FALSE, FALSE, 0 );
3268
3269         // this gets done in the project stuff atm
3270 #if 0
3271         text = gtk_label_new( "Mod subdirectory:" );
3272         gtk_widget_show( text );
3273         gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 );
3274
3275         entry = gtk_entry_new();
3276         gtk_widget_show( entry );
3277         gtk_box_pack_start( GTK_BOX( vbox1 ), entry, FALSE, FALSE, 0 );
3278         AddDialogData( entry, &m_strMod, DLG_ENTRY_TEXT );
3279 #endif
3280
3281         button = gtk_button_new_with_label( "OK" );
3282         gtk_widget_show( button );
3283         gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 );
3284         AddModalButton( button, IDOK );
3285
3286         button = gtk_button_new_with_label( "Cancel" );
3287         gtk_widget_show( button );
3288         gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 );
3289         AddModalButton( button, IDCANCEL );
3290
3291         gtk_widget_set_usize( button, 60, -2 );
3292 }
3293
3294 void CGameInstall::Run() {
3295         ScanGames();
3296         if ( DoModal() == IDCANCEL ) {
3297                 Sys_Printf( "game dialog cancelled\n" );
3298                 return;
3299         }
3300         Sys_Printf( "combo: %d name: %s engine: %s mod: %s\n", m_nComboSelect, m_strName.GetBuffer(), m_strEngine.GetBuffer(), m_strMod.GetBuffer() );
3301
3302         // write out the game file
3303         Str gameFilePath = g_strAppPath.GetBuffer();
3304         gameFilePath += "games/";
3305         gameFilePath += m_strName.GetBuffer();
3306         gameFilePath += ".game";
3307         Sys_Printf( "game file: %s\n", gameFilePath.GetBuffer() );
3308
3309         FILE *fg = fopen( gameFilePath.GetBuffer(), "w" );
3310         if ( fg == NULL ) {
3311                 Error( "Failed to open %s for writing\n", gameFilePath.GetBuffer() );
3312         }
3313         fprintf( fg, "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>\n<game\n" );
3314         fprintf( fg, "  name=\"%s\"\n", m_strName.GetBuffer() );
3315         fprintf( fg, "  enginepath=\"%s\"\n", m_strEngine.GetBuffer() );
3316         switch ( m_availGames[ m_nComboSelect ] ) {
3317         case GAME_Q2: {
3318                 fprintf( fg, "  gametools=\"%sinstalls/Quake2Pack/game\"\n", g_strAppPath.GetBuffer() );
3319                 fprintf( fg, "  prefix=\".quake2\"\n" );
3320                 Str source = g_strAppPath.GetBuffer();
3321                 source += "installs/";
3322                 source += Q2_PACK;
3323                 source += "/install/";
3324                 Str dest = m_strEngine.GetBuffer();
3325                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3326                 fprintf( fg, "  basegame=\"baseq2\"\n" );
3327                 break;
3328         }
3329         case GAME_Q3: {
3330                 fprintf( fg, "  gametools=\"%sinstalls/Q3Pack/game\"\n", g_strAppPath.GetBuffer() );
3331                 fprintf( fg, "  prefix=\".q3a\"\n" );
3332                 Str source = g_strAppPath.GetBuffer();
3333                 source += "installs/";
3334                 source += Q3_PACK;
3335                 source += "/install/";
3336                 Str dest = m_strEngine.GetBuffer();
3337                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3338                 fprintf( fg, "  basegame=\"baseq3\"\n" );
3339                 break;
3340         }
3341         case GAME_URT: {
3342                 fprintf( fg, "  gametools=\"%sinstalls/UrTPack/game\"\n", g_strAppPath.GetBuffer() );
3343                 fprintf( fg, "  prefix=\".q3a\"\n" );
3344                 Str source = g_strAppPath.GetBuffer();
3345                 source += "installs/";
3346                 source += URT_PACK;
3347                 source += "/install/";
3348                 Str dest = m_strEngine.GetBuffer();
3349                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3350                 fprintf( fg, "  basegame=\"q3ut4\"\n" );
3351                 break;
3352         }
3353         case GAME_UFOAI: {
3354                 fprintf( fg, "  gametools=\"%sinstalls/UFOAIPack/game\"\n", g_strAppPath.GetBuffer() );
3355                 fprintf( fg, "  prefix=\".ufoai\"\n" );
3356                 Str source = g_strAppPath.GetBuffer();
3357                 source += "installs/";
3358                 source += UFOAI_PACK;
3359                 source += "/install/";
3360                 Str dest = m_strEngine.GetBuffer();
3361                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3362                 fprintf( fg, "  basegame=\"base\"\n" );
3363                 break;
3364         }
3365         case GAME_Q2W: {
3366                 fprintf( fg, "  gametools=\"%sinstalls/Q2WPack/game\"\n", g_strAppPath.GetBuffer() );
3367                 fprintf( fg, "  prefix=\".quake2world\"\n" );
3368                 Str source = g_strAppPath.GetBuffer();
3369                 source += "installs/";
3370                 source += Q2W_PACK;
3371                 source += "/install/";
3372                 Str dest = m_strEngine.GetBuffer();
3373                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3374                 fprintf( fg, "  basegame=\"default\"\n" );
3375                 break;
3376         }
3377         case GAME_WARSOW: {
3378                 fprintf( fg, "  gametools=\"%sinstalls/WarsowPack/game\"\n", g_strAppPath.GetBuffer() );
3379                 fprintf( fg, "  prefix=\".warsow\"\n" );
3380                 Str source = g_strAppPath.GetBuffer();
3381                 source += "installs/";
3382                 source += WARSOW_PACK;
3383                 source += "/install/";
3384                 Str dest = m_strEngine.GetBuffer();
3385                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3386                 fprintf( fg, "  basegame=\"basewsw\"\n" );
3387                 break;
3388         }
3389         case GAME_NEXUIZ: {
3390                 fprintf( fg, "  gametools=\"%sinstalls/NexuizPack/game\"\n", g_strAppPath.GetBuffer() );
3391                 fprintf( fg, "  prefix=\".nexuiz\"\n" );
3392                 Str source = g_strAppPath.GetBuffer();
3393                 source += "installs/";
3394                 source += NEXUIZ_PACK;
3395                 source += "/install/";
3396                 Str dest = m_strEngine.GetBuffer();
3397                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3398                 fprintf( fg, "  basegame=\"data\"\n" );
3399                 break;
3400         }
3401         }
3402         fprintf( fg, "/>\n" );
3403         fclose( fg );
3404 }
3405
3406 /*
3407 ===============
3408 CGameInstall::ScanGames
3409 scan for active games that can be installed, based on the presence
3410 ===============
3411 */
3412 void CGameInstall::ScanGames() {
3413         Str                             pakPaths = g_strAppPath.GetBuffer();
3414         int                             iGame = 0;
3415         const char              *dirname;
3416
3417         pakPaths +=     "installs/";
3418         FindFiles fileScan( pakPaths.GetBuffer() );
3419         while ( ( dirname = fileScan.NextFile() ) != NULL ) {
3420                 if ( stricmp( dirname, Q3_PACK ) == 0 ) {
3421                         m_availGames[ iGame++ ] = GAME_Q3;
3422                 }
3423                 if ( stricmp( dirname, URT_PACK ) == 0 ) {
3424                         m_availGames[ iGame++ ] = GAME_URT;
3425                 }
3426                 if ( stricmp( dirname, UFOAI_PACK ) == 0 ) {
3427                         m_availGames[ iGame++ ] = GAME_UFOAI;
3428                 }
3429                 if ( stricmp( dirname, Q2W_PACK ) == 0 ) {
3430                         m_availGames[ iGame++ ] = GAME_Q2W;
3431                 }
3432                 if ( stricmp( dirname, WARSOW_PACK ) == 0 ) {
3433                         m_availGames[ iGame++ ] = GAME_WARSOW;
3434                 }
3435                 if ( stricmp( dirname, NEXUIZ_PACK ) == 0 ) {
3436                         m_availGames[ iGame++ ] = GAME_NEXUIZ;
3437                 }
3438                 if ( stricmp( dirname, Q2_PACK ) == 0 ) {
3439                         m_availGames[ iGame++ ] = GAME_Q2;
3440                 }
3441         }
3442 }
3443