]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/preferences.cpp
fix
[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(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(char *name, Str *pV, 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(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(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(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(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(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   bool bEmpty = false;
922
923   // if we already have a document loaded, we will free and reload from file
924   if (mGlobalPrefs.InUse())
925   {
926     Sys_Printf("Reloading global prefs from file\n");
927     mGlobalPrefs.Clear();
928   }
929
930   // load global .pref file
931   CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str;
932   strGlobalPref += "global.pref";
933
934   mGlobalPrefs.ReadXMLFile(strGlobalPref.GetBuffer());
935
936   mGlobalPrefs.GetPref("gamefile", &m_sGameFile, ""); // NOTE: there's no default, user HAS to select something
937   mGlobalPrefs.GetPref("autoload", &m_bAutoLoadGame, false);
938   mGlobalPrefs.GetPref("log console", &m_bLogConsole, false);
939   // in a very particular post-.pid startup
940   // we may have the console turned on and want to keep it that way
941   // so we use a latching system
942   if (m_bForceLogConsole)
943   {
944     m_bLogConsole = true;
945     Sys_Printf("console logging has been latched on, saving prefs\n");
946     SavePrefs();
947     m_bForceLogConsole = false;
948   }
949
950   // console logging: call Sys_LogConsole to check console logging status
951   // it is important that we would log console as early as possible to make it useful
952   Sys_LogFile();
953
954   if (mGlobalPrefs.mbEmpty)
955   {
956     Sys_Printf("Saving global.pref with default pref values\n");
957     SavePrefs();
958   }
959 }
960
961 void CGameDialog::SavePrefs()
962 {
963   // update the tree and save it
964   mGlobalPrefs.UpdatePrefTree();
965   
966   CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str;
967   strGlobalPref += "global.pref";
968   
969   if ( !mGlobalPrefs.WriteXMLFile( strGlobalPref.GetBuffer() ) ) {
970     Sys_FPrintf(SYS_ERR, "Error occured while saving global prefs file '%s'\n", strGlobalPref.GetBuffer());
971   }
972 }
973
974 void CGameDialog::DoGameInstall() {
975         // make sure console logging is on whenever we enter the installation loop
976     g_PrefsDlg.mGamesDialog.m_bLogConsole = true;
977         Sys_LogFile();
978         mGameInstall.Run();
979 }
980
981 void CGameDialog::DoGameDialog() {
982         // allow looping the game selection dialog with calls to the game configure dialog in between
983         while ( m_bDoGameInstall ) {
984                 
985                 m_bDoGameInstall = false;
986
987                 if ( DoModal() == IDCANCEL ) {
988                         Error( "game selection dialog canceled, cannot continue" );
989                         return;
990                 }
991                 
992                 if ( m_bDoGameInstall ) {
993                         DoGameInstall();
994                         ScanForGames();
995                         // and we will loop to do another DoModal dialog
996                 }
997         }
998
999         // unhook so we can use in other places
1000         // we manually incref'ed it when creating, it won't be freed (destructor)
1001         gtk_container_remove( GTK_CONTAINER( mTopBox ), GetGlobalFrame() );
1002
1003         // we save the prefs file
1004         SavePrefs();
1005 }
1006
1007 GtkWidget* CGameDialog::GetGlobalFrame()
1008 {
1009   GtkWidget *vbox, *text, *combo, *check;
1010
1011   if ( mFrame != NULL ) {
1012           return mFrame;
1013   }
1014
1015   mFrame = gtk_frame_new( NULL );
1016   gtk_container_set_border_width( GTK_CONTAINER( mFrame ), 5 );
1017   gtk_widget_show( mFrame );
1018
1019   vbox = gtk_vbox_new( FALSE, 6 );
1020   gtk_widget_show( vbox );
1021   gtk_container_add( GTK_CONTAINER( mFrame ), vbox );
1022   gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
1023
1024   text = gtk_label_new( "Select the game:" );
1025   gtk_widget_show( text );
1026   gtk_box_pack_start( GTK_BOX( vbox ), text, FALSE, FALSE, 0 );
1027
1028   combo = gtk_combo_box_new_text();
1029   gtk_widget_show( combo );
1030   gtk_box_pack_start( GTK_BOX( vbox ), combo, FALSE, FALSE, 0 );
1031   AddDialogData( combo, &m_nComboSelect, DLG_COMBO_BOX_INT );
1032   mGameCombo = GTK_COMBO_BOX( combo );
1033
1034   UpdateGameCombo();
1035
1036   check = gtk_check_button_new_with_label( "Auto load selected game on startup" );
1037   gtk_widget_show(check);
1038   gtk_box_pack_start (GTK_BOX(vbox), check, FALSE, FALSE, 0);
1039   AddDialogData (check, &m_bAutoLoadGame, DLG_CHECK_BOOL);
1040   
1041   text = gtk_label_new("(this frame is available in the prefs menu if you set auto-select)");
1042   gtk_widget_show(text);
1043   gtk_box_pack_start (GTK_BOX(vbox), text, FALSE, FALSE, 0);
1044
1045 #ifdef _WIN32
1046   check = gtk_check_button_new_with_label( "Networked install - per-user settings" );
1047   gtk_widget_show( check );
1048   gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 );
1049   AddDialogData( check, &m_bNetRun, DLG_CHECK_BOOL );
1050 #endif
1051
1052   check = gtk_check_button_new_with_label( "Log the console to radiant.log" );
1053   gtk_widget_show( check );
1054   gtk_box_pack_start( GTK_BOX( vbox ), check, FALSE, FALSE, 0 );
1055   AddDialogData( check, &m_bLogConsole, DLG_CHECK_BOOL );
1056
1057   // incref it so we can pass it around
1058   gtk_widget_ref( GTK_WIDGET( mFrame ) );
1059
1060   return mFrame;
1061 }
1062
1063 void CGameDialog::UpdateData( bool retrieve ) {
1064   if (!retrieve)
1065   {
1066     // use m_sGameFile to set m_nComboSelect
1067     list<CGameDescription *>::iterator iGame;
1068     int i = 0;
1069     for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++)
1070     {
1071       if ((*iGame)->mGameFile == m_sGameFile)
1072       {
1073         m_nComboSelect = i;
1074         break;
1075       }
1076       i++;
1077     }
1078 #ifdef _WIN32
1079     UpdateNetrun(false);
1080 #endif
1081   }
1082   Dialog::UpdateData(retrieve);
1083   if (retrieve)
1084   {
1085     // use m_nComboSelect to set m_sGameFile
1086     list<CGameDescription *>::iterator iGame = mGames.begin();
1087     int i;
1088     for(i=0; i<m_nComboSelect; i++)
1089     {
1090       iGame++;
1091     }
1092     m_sGameFile = (*iGame)->mGameFile;
1093 #ifdef _WIN32
1094     UpdateNetrun(true);
1095 #endif
1096   }
1097 }
1098
1099 void CGameDialog::SInstallCallback( GtkWidget *widget, gpointer data ) {
1100         CGameDialog *d = static_cast< CGameDialog* >( data );
1101         d->m_bDoGameInstall = true;
1102         d->EndModal( 0 );
1103 }
1104
1105 void CGameDialog::BuildDialog() {
1106         GtkWidget *dlg, *vbox1, *button, *setup_button;
1107         
1108         dlg = m_pWidget;
1109         gtk_window_set_title( GTK_WINDOW( dlg ), "Select Game" );
1110
1111         vbox1 = gtk_vbox_new( FALSE, 0 );
1112         gtk_widget_show( vbox1 );
1113         gtk_container_add( GTK_CONTAINER( dlg ), vbox1 );
1114
1115         gtk_container_add( GTK_CONTAINER( vbox1 ), GetGlobalFrame() );
1116         mTopBox = vbox1;
1117
1118         setup_button = gtk_button_new_with_label( "Configure more games" );
1119         gtk_widget_show( setup_button );
1120         gtk_box_pack_start( GTK_BOX( vbox1 ), setup_button, FALSE, FALSE, 0 );
1121         gtk_signal_connect( GTK_OBJECT( setup_button ), "clicked",
1122                                                 GTK_SIGNAL_FUNC( SInstallCallback ), this );
1123
1124         button = gtk_button_new_with_label( "OK" );
1125         gtk_widget_show( button );
1126         gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 );
1127         AddModalButton( button, IDOK );
1128
1129         button = gtk_button_new_with_label( "Cancel" );
1130         gtk_widget_show( button );
1131         gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 );
1132         AddModalButton( button, IDCANCEL );
1133         
1134         gtk_widget_set_usize( button, 60, -2 );
1135 }
1136
1137 void CGameDialog::UpdateGameCombo() {
1138   // fill in with the game descriptions
1139   list<CGameDescription *>::iterator iGame;
1140
1141   if ( mGameCombo == NULL ) {
1142           Sys_Printf( "mGameCombo == NULL\n" );
1143           return;
1144   }
1145
1146   // clear whatever is in - wtf no way to know how many text entries?
1147   // use set/get active to track 
1148   gtk_combo_box_set_active( mGameCombo, 0 );
1149   while ( gtk_combo_box_get_active( mGameCombo ) == 0 ) {
1150           gtk_combo_box_remove_text( mGameCombo, 0 );
1151           gtk_combo_box_set_active( mGameCombo, 0 );
1152   }
1153   
1154   for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) {
1155           gtk_combo_box_append_text( mGameCombo, (*iGame)->mGameName.GetBuffer() );
1156   }
1157   gtk_combo_box_set_active( mGameCombo, 0 );
1158 }
1159
1160 void CGameDialog::ScanForGames()
1161 {
1162   CString strPath;
1163   char *dirlist;
1164   GDir *dir;
1165   CString strGamesPath = g_strAppPath.GetBuffer();
1166   strGamesPath += "games";
1167   const char *path = strGamesPath.GetBuffer();
1168
1169   if ( !mGames.empty() ) {
1170           Sys_Printf( "Clearing game list\n" );
1171           list<CGameDescription*>::iterator iGame;
1172           for ( iGame = mGames.begin(); iGame != mGames.end(); iGame++ ) {
1173                   delete (*iGame);
1174           }
1175           mGames.clear();
1176   }
1177
1178   Sys_Printf( "Scanning for game description files: %s\n", path );
1179
1180   /*!
1181   \todo FIXME LINUX:
1182   do we put game description files below g_strAppPath, or in ~/.radiant
1183   i.e. read only or read/write?
1184   my guess .. readonly cause it's an install
1185   we will probably want to add ~/.radiant/<version>/games/ scanning on top of that for developers
1186   (if that's really needed)
1187   */
1188
1189   // FIXME need to catch the 'no game description' situation and exit with a clean error
1190
1191   dir = g_dir_open(path, 0, NULL);
1192
1193   if (dir != NULL)
1194   {
1195     while (1)
1196     {
1197       const gchar* name = g_dir_read_name(dir);
1198       if(name == NULL)
1199         break;
1200
1201       dirlist = g_strdup(name);
1202 #ifdef _WIN32
1203       strlwr (dirlist);
1204 #endif
1205       char *ext = strrchr (dirlist, '.');
1206       if ((ext == NULL) || (strcmp (ext, ".game") != 0))
1207         continue;
1208       strPath.Format("%s/%s", path, dirlist);
1209       Sys_Printf("%s\n", strPath.GetBuffer());
1210       // got one, load it
1211       xmlDocPtr pDoc = xmlParseFile(strPath.GetBuffer());
1212       if (pDoc)
1213       {
1214         mGames.push_front( new CGameDescription( pDoc, dirlist ) );
1215       }
1216       else
1217       {
1218         Sys_FPrintf(SYS_ERR, "XML parser failed on '%s'\n", strPath.GetBuffer());
1219       }
1220
1221       g_free( dirlist );
1222     }
1223     g_dir_close( dir );
1224   }
1225
1226   // entries in the combo need to be updated
1227   UpdateGameCombo();
1228 }
1229
1230 CGameDescription* CGameDialog::GameDescriptionForComboItem()
1231 {
1232   list<CGameDescription *>::iterator iGame;
1233   int i=0;
1234   for( iGame = mGames.begin(); iGame != mGames.end(); iGame++,i++ ) {
1235     if ( i == m_nComboSelect ) {
1236       return (*iGame);
1237     }
1238   }
1239   return NULL; // not found
1240 }
1241
1242 void CGameDialog::InitGlobalPrefPath()
1243 {
1244   GString *global_rc_path;
1245   // configure m_global_rc_path
1246   // this is the g_strTempPath, and it has already been mkdir'ed
1247   global_rc_path = g_string_new(g_strTempPath.GetBuffer());
1248   g_PrefsDlg.m_global_rc_path = global_rc_path;
1249 }
1250
1251 void CGameDialog::Reset()
1252 {
1253   if (!g_PrefsDlg.m_global_rc_path)
1254     InitGlobalPrefPath();
1255   CString strGlobalPref = g_PrefsDlg.m_global_rc_path->str;
1256   strGlobalPref += "global.pref";
1257   remove(strGlobalPref.GetBuffer());
1258 }
1259
1260 void CGameDialog::Init()
1261 {
1262   InitGlobalPrefPath();
1263   ScanForGames();
1264   if ( mGames.empty() ) {
1265           DoGameInstall();
1266           ScanForGames();
1267           if ( mGames.empty() ) {
1268                   Error( "No games setup, aborting\n" );
1269           }
1270   }
1271   LoadPrefs();
1272   if ( m_bAutoLoadGame ) {
1273     // search by .game name
1274     list<CGameDescription *>::iterator iGame;
1275     for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++)
1276     {
1277       if ((*iGame)->mGameFile == m_sGameFile)
1278       {
1279         m_pCurrentGameDescription = (*iGame);
1280         break;
1281       }
1282     }
1283   }
1284   if ( !m_bAutoLoadGame || !m_pCurrentGameDescription ) {
1285     DoGameDialog();
1286     // use m_nComboSelect to identify the game to run as and set the globals
1287     m_pCurrentGameDescription = GameDescriptionForComboItem();
1288     if ( !m_pCurrentGameDescription ) {
1289                 Error("Lookup of game description object failed, can't continue\n");
1290         }
1291   }
1292   g_pGameDescription = m_pCurrentGameDescription;
1293
1294   g_strGameToolsPath = g_pGameDescription->mGameToolsPath;
1295
1296         // NOTE TTimo: this is moved from QE_LoadProject in 1.2
1297         // (probably broken)
1298   // NOTE Hydra: was broken for win32, we don't use m_strHomeGame or m_strFSBasePath
1299 #if defined (__linux__) || defined (__APPLE__)
1300   g_qeglobals.m_strHomeGame = g_get_home_dir();
1301   g_qeglobals.m_strHomeGame += "/";
1302   g_qeglobals.m_strHomeGame += m_pCurrentGameDescription->mUserPathPrefix.GetBuffer();
1303   g_qeglobals.m_strHomeGame += "/";
1304 #else
1305   g_qeglobals.m_strHomeGame = g_pGameDescription->mEnginePath.GetBuffer();
1306 #endif
1307   
1308   g_pGameDescription->Dump();
1309 }
1310
1311 CGameDialog::~CGameDialog()
1312 {
1313   if (mFrame)
1314   {
1315     // NOTE I'm not too sure how reliable this is
1316     gtk_widget_unref(GTK_WIDGET(mFrame));
1317   }
1318   // free all the game descriptions
1319   list<CGameDescription *>::iterator iGame;
1320   for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++)
1321   {
1322     delete (*iGame);
1323     *iGame = NULL;
1324   }
1325 }
1326
1327 void CGameDialog::AddPacksURL(Str &URL)
1328 {
1329   // add the URLs for the list of game packs installed
1330   // FIXME: this is kinda hardcoded for now..
1331   list<CGameDescription *>::iterator iGame;
1332   for(iGame=mGames.begin(); iGame!=mGames.end(); iGame++)
1333   {  
1334     if ((*iGame)->mGameFile == "q3.game")      
1335       URL += "&Games_dlup%5B%5D=1";
1336     else if ((*iGame)->mGameFile == "wolf.game")
1337       URL += "&Games_dlup%5B%5D=2";
1338     else if ((*iGame)->mGameFile == "wolf.game")
1339       URL += "&Games_dlup%5B%5D=3";
1340     else if ((*iGame)->mGameFile == "jk2.game")
1341       URL += "&Games_dlup%5B%5D=4";
1342     else if ((*iGame)->mGameFile == "stvef.game")
1343       URL += "&Games_dlup%5B%5D=5";
1344     else if ((*iGame)->mGameFile == "sof2.game")
1345       URL += "&Games_dlup%5B%5D=6";
1346     else if ((*iGame)->mGameFile == "ja.game")
1347       URL += "&Games_dlup%5B%5D=7";
1348   }
1349 }
1350
1351 #ifdef _WIN32
1352
1353 #define NETRUN_FILENAME "netrun.conf"
1354
1355 bool CGameDialog::m_bNetRun;
1356
1357 void CGameDialog::UpdateNetrun(bool retrieve)
1358 {
1359   FILE *f_netrun;
1360   CString strNetrun;
1361   strNetrun = g_strAppPath; strNetrun += NETRUN_FILENAME;
1362   if (!retrieve)
1363   {
1364     // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=639
1365     // now check if we are running from a network installation
1366     // use a dummy file as the flag
1367     f_netrun = fopen(strNetrun.GetBuffer(), "r");
1368     if (f_netrun)
1369     {
1370       fclose(f_netrun);
1371       m_bNetRun = true;
1372     }
1373     else
1374       m_bNetRun = false;
1375   }
1376   else
1377   {
1378     if (m_bNetRun)
1379     {
1380       f_netrun = fopen(strNetrun.GetBuffer(), "w");
1381       if (!f_netrun)
1382       {
1383         Sys_FPrintf(SYS_ERR, "ERROR: Failed to create netrun file '%s'\n", strNetrun.GetBuffer());
1384         m_bNetRun = false;
1385       }
1386       else
1387       {
1388         fclose(f_netrun);
1389         Sys_Printf("Created/Checked '%s'\n", strNetrun.GetBuffer());
1390       }
1391     }
1392     else
1393     {
1394       if (remove(strNetrun.GetBuffer()) == -1)
1395       {
1396         if (errno != ENOENT)
1397           Sys_FPrintf(SYS_ERR, "Failed to remove netrun file '%s'\n", strNetrun.GetBuffer());
1398         m_bNetRun = true;
1399       }
1400       else
1401       {
1402         Sys_Printf("Netrun mode is disabled\n");
1403       }
1404     }
1405   }
1406 }
1407
1408 bool CGameDialog::GetNetrun()
1409 {
1410   return m_bNetRun;
1411 }
1412 #endif
1413
1414 /*
1415 ========
1416
1417 very first prefs init deals with selecting the game and the game tools path
1418 then we can load .ini stuff
1419
1420 using prefs / ini settings:
1421 those are per-game
1422
1423 win32:
1424 look in g_strGameToolsPath for .ini
1425
1426 linux:
1427 look in ~/.radiant/<version>/gamename
1428 ========
1429 */
1430
1431 #define PREFS_LOCAL_FILENAME "local.pref"
1432
1433 void PrefsDlg::Init()
1434 {
1435   mGamesDialog.Init();
1436
1437   // m_global_rc_path has been set above, do m_rc_path with game specific stuff now
1438   // the win32 and linux versions have been unified for network mode
1439 #ifdef _WIN32
1440   if (!CGameDialog::GetNetrun())
1441   {
1442     // legacy prefs settings, this goes where the game pack is installed
1443     m_rc_path = g_string_new (g_strGameToolsPath.GetBuffer() );
1444     m_inipath = g_string_new (m_rc_path->str);
1445     g_string_append (m_inipath, PREFS_LOCAL_FILENAME);
1446     return;
1447   }
1448 #endif
1449   // this is common to win32 and Linux init now
1450   m_rc_path = g_string_new (m_global_rc_path->str);
1451   
1452   // game sub-dir
1453   g_string_append (m_rc_path, g_pGameDescription->mGameFile.GetBuffer());
1454   g_string_append (m_rc_path, "/");
1455   Q_mkdir (m_rc_path->str, 0775);
1456   
1457   // then the ini file
1458   m_inipath = g_string_new (m_rc_path->str);
1459   g_string_append (m_inipath, PREFS_LOCAL_FILENAME);
1460   
1461 }
1462
1463 void PrefsDlg::UpdateData (bool retrieve)
1464 {
1465   // leo: the "changed" signal confuses the update function
1466   if (m_pWidget == NULL)
1467     return;
1468   mGamesDialog.UpdateData (retrieve);
1469   Dialog::UpdateData (retrieve);
1470 }
1471
1472 #ifdef _WIN32
1473 #define PREFSHSPACE 5
1474 #else
1475 #define PREFSHSPACE 0
1476 #endif
1477
1478 static void UpdateSensitivity( GtkWidget *widget, gpointer data )
1479 {
1480   PrefsDlg *dlg = (PrefsDlg*)data;
1481   dlg->DoSensitivity();
1482 }
1483
1484 static void UpdateEditorSensitivity(GtkWidget *widget, gpointer data)
1485 {
1486   PrefsDlg *dlg = (PrefsDlg*)data;
1487   dlg->DoEditorSensitivity();
1488 }
1489
1490 // start new prefs dialog
1491
1492 /*! Utility function for swapping notebook pages for tree list selections */
1493 void PrefsDlg::showPrefPage(int prefpage)
1494 {
1495   if(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)) != prefpage)
1496     gtk_notebook_set_page(GTK_NOTEBOOK(notebook), prefpage);
1497   
1498   return;
1499 }
1500
1501 static void treeSelection(GtkTreeSelection* selection, gpointer data)
1502 {
1503   PrefsDlg *dlg = (PrefsDlg*)data;
1504
1505   GtkTreeModel* model;
1506   GtkTreeIter selected;
1507   if(gtk_tree_selection_get_selected(selection, &model, &selected))
1508   {
1509     int prefpage;
1510     gtk_tree_model_get(model, &selected, 1, (gpointer*)&prefpage, -1);
1511     dlg->showPrefPage(prefpage);
1512   }
1513 }
1514
1515 void PrefsDlg::BuildDialog ()
1516 {
1517   // Main Preferences dialog
1518   GtkWidget *dialog, *mainvbox, *hbox, *sc_win, *preflabel;
1519
1520   // Widgets on notebook pages
1521   GtkWidget *check, *label, *scale, *hbox2, *combo,
1522             *table, *spin,  *entry, *pixmap,
1523             *radio, *button, *pageframe, *vbox;
1524   
1525   GList *combo_list = (GList*)NULL;
1526   
1527   GtkObject *adj;
1528     
1529   dialog = m_pWidget;
1530   gtk_window_set_title(GTK_WINDOW(dialog), "GtkRadiant Preferences");
1531   gtk_widget_realize(dialog);
1532     
1533   mainvbox = gtk_vbox_new(FALSE, 5);
1534   gtk_container_add(GTK_CONTAINER(dialog), mainvbox);
1535   gtk_container_set_border_width(GTK_CONTAINER(mainvbox), 5);
1536   gtk_widget_show(mainvbox);
1537   
1538   hbox = gtk_hbox_new(FALSE, 5);
1539   gtk_widget_show(hbox);
1540   gtk_box_pack_end(GTK_BOX(mainvbox), hbox, FALSE, TRUE, 0);
1541
1542   button = gtk_button_new_with_label("OK");
1543   gtk_widget_show(button);
1544   gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1545   gtk_widget_set_usize(button, 60, -2);
1546   AddModalButton(button, IDOK);
1547
1548   button = gtk_button_new_with_label("Cancel");
1549   gtk_widget_show(button);
1550   gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1551   gtk_widget_set_usize(button, 60, -2);
1552   AddModalButton(button, IDCANCEL);
1553
1554   button = gtk_button_new_with_label ("Clean");
1555   gtk_widget_show(button);
1556   gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(OnButtonClean), this);
1557   gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1558   gtk_widget_set_usize (button, 60, -2);
1559   
1560   hbox = gtk_hbox_new(FALSE, 5);
1561   gtk_box_pack_start(GTK_BOX(mainvbox), hbox, TRUE, TRUE, 0);
1562   gtk_widget_show(hbox);
1563   
1564   sc_win = gtk_scrolled_window_new(NULL, NULL);
1565   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sc_win), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1566   gtk_box_pack_start(GTK_BOX(hbox), sc_win, FALSE, FALSE, 0);
1567   gtk_widget_show(sc_win);
1568
1569   // prefs pages notebook
1570   notebook = gtk_notebook_new();
1571   // hide the notebook tabs since its not supposed to look like a notebook
1572   gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
1573   gtk_box_pack_start(GTK_BOX(hbox), notebook, TRUE, TRUE, 0);
1574   gtk_widget_show(notebook);
1575
1576   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sc_win), GTK_SHADOW_IN);
1577
1578   {
1579     GtkTreeStore* store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
1580
1581     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1582     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
1583
1584     {
1585       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1586       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Preferences", renderer, "text", 0, NULL);
1587       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1588     }
1589
1590     {
1591       GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
1592       g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(treeSelection), this);
1593     }
1594
1595     gtk_widget_show(view);
1596
1597     gtk_container_add(GTK_CONTAINER (sc_win), view);
1598
1599     {
1600       /********************************************************************/
1601       /* Add preference tree options                                      */
1602       /********************************************************************/
1603       {
1604         GtkTreeIter group;
1605         gtk_tree_store_append(store, &group, NULL);
1606         gtk_tree_store_set(store, &group, 0, "Globals", 1, PTAB_FRONT, -1);
1607         {
1608           GtkTreeIter tab;
1609           gtk_tree_store_append(store, &tab, &group);
1610           gtk_tree_store_set(store, &tab, 0, "Game settings", 1, (gpointer)PTAB_GAME_SETTINGS, -1);
1611         }
1612       }
1613
1614       {
1615         GtkTreeIter group;
1616         gtk_tree_store_append(store, &group, NULL);
1617         gtk_tree_store_set(store, &group, 0, "Display", 1, PTAB_FRONT, -1);
1618         {
1619           GtkTreeIter tab;
1620           gtk_tree_store_append(store, &tab, &group);
1621           gtk_tree_store_set(store, &tab, 0, "2D Display/Rendering", 1, (gpointer)PTAB_2D, -1);
1622         }
1623         {
1624           GtkTreeIter tab;
1625           gtk_tree_store_append(store, &tab, &group);
1626           gtk_tree_store_set(store, &tab, 0, "3D View", 1, (gpointer)PTAB_CAMERA, -1);
1627         }
1628         {
1629           GtkTreeIter tab;
1630           gtk_tree_store_append(store, &tab, &group);
1631           gtk_tree_store_set(store, &tab, 0, "Texture Settings", 1, (gpointer)PTAB_TEXTURE, -1);
1632         }
1633       }
1634   
1635       {
1636         GtkTreeIter group;
1637         gtk_tree_store_append(store, &group, NULL);
1638         gtk_tree_store_set(store, &group, 0, "Interface", 1, PTAB_FRONT, -1);
1639         {
1640           GtkTreeIter tab;
1641           gtk_tree_store_append(store, &tab, &group);
1642           gtk_tree_store_set(store, &tab, 0, "Layout", 1, (gpointer)PTAB_LAYOUT, -1);
1643         }
1644         {
1645           GtkTreeIter tab;
1646           gtk_tree_store_append(store, &tab, &group);
1647           gtk_tree_store_set(store, &tab, 0, "Mouse", 1, (gpointer)PTAB_MOUSE, -1);
1648         }
1649         {
1650           GtkTreeIter tab;
1651           gtk_tree_store_append(store, &tab, &group);
1652           gtk_tree_store_set(store, &tab, 0, "Editing", 1, (gpointer)PTAB_EDITING, -1);
1653         }
1654       }
1655   
1656       {
1657         GtkTreeIter group;
1658         gtk_tree_store_append(store, &group, NULL);
1659         gtk_tree_store_set(store, &group, 0, "Other", 1, PTAB_FRONT, -1);
1660         {
1661           GtkTreeIter tab;
1662           gtk_tree_store_append(store, &tab, &group);
1663           gtk_tree_store_set(store, &tab, 0, "Startup/Auto save", 1, (gpointer)PTAB_STARTUP, -1);
1664         }
1665         {
1666           GtkTreeIter tab;
1667           gtk_tree_store_append(store, &tab, &group);
1668           gtk_tree_store_set(store, &tab, 0, "Paths", 1, (gpointer)PTAB_PATHS, -1);
1669         }
1670         {
1671           GtkTreeIter tab;
1672           gtk_tree_store_append(store, &tab, &group);
1673           gtk_tree_store_set(store, &tab, 0, "Misc", 1, (gpointer)PTAB_MISC, -1);
1674         }
1675         if (!g_qeglobals.bBSPFrontendPlugin)
1676         {
1677           GtkTreeIter tab;
1678           gtk_tree_store_append(store, &tab, &group);
1679           gtk_tree_store_set(store, &tab, 0, "BSP Monitoring", 1, (gpointer)PTAB_BSPMONITOR, -1);
1680         }
1681       }
1682     }
1683
1684     gtk_tree_view_expand_all(GTK_TREE_VIEW(view));
1685     
1686     g_object_unref(G_OBJECT(store));
1687   }
1688   
1689   /**********************************************************************/
1690   /* build the prefs pages                                              */
1691   /**********************************************************************/
1692   
1693   // Front page...
1694   // todo : add something interesting here
1695   // NOTE TTimo: tip of the day? or a logo?
1696   preflabel = gtk_label_new("Front Page");
1697   gtk_widget_show(preflabel);
1698   pageframe = gtk_frame_new(NULL);
1699   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
1700   gtk_widget_show(pageframe);
1701   vbox = gtk_vbox_new(FALSE, 5);
1702   gtk_widget_show(vbox);
1703   gtk_widget_set_usize(GTK_WIDGET(vbox), 350, -2);
1704   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
1705   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
1706   
1707   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
1708
1709   /******** global preferences group ****************************/
1710   preflabel = gtk_label_new("Globals");
1711   gtk_widget_show(preflabel);
1712
1713   pageframe = mGamesDialog.GetGlobalFrame();
1714   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
1715   
1716   /******** 2D prefs group (xy views/rendering options) *********/
1717   preflabel = gtk_label_new("2D Display");
1718   gtk_widget_show(preflabel);
1719   pageframe = gtk_frame_new("2D Display");
1720   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
1721   gtk_widget_show(pageframe);
1722   vbox = gtk_vbox_new(FALSE, 5);
1723   gtk_widget_show(vbox);
1724   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
1725   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
1726   
1727   // OpenGL Display Lists
1728   check = gtk_check_button_new_with_label("OpenGL Display Lists");
1729   gtk_widget_show(check);
1730   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
1731   AddDialogData(check, &m_bDisplayLists, DLG_CHECK_BOOL);
1732   
1733   // Antialiased points & lines
1734   // Fishman - Add antialiazed points and lines support. 09/03/00
1735   check = gtk_check_button_new_with_label ("OpenGL antialiased points and lines");
1736   gtk_widget_show (check);
1737   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1738   AddDialogData (check, &m_bAntialiasedPointsAndLines, DLG_CHECK_BOOL);
1739   
1740   // Solid selection boxes
1741   check = gtk_check_button_new_with_label ("Solid selection boxes");
1742   gtk_widget_show (check);
1743   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1744   AddDialogData (check, &m_bNoStipple, DLG_CHECK_BOOL);
1745   
1746   // Display size info
1747   check = gtk_check_button_new_with_label ("Display size info");
1748   gtk_widget_show (check);
1749   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
1750   AddDialogData (check, &m_bSizePaint, DLG_CHECK_BOOL);
1751
1752   // Alternate vertex/edge handles
1753   // Gef: Kyro GL_POINT work around 25-aug-2001
1754   check = gtk_check_button_new_with_label ("Alternate vertex/edge handles");
1755   gtk_widget_show(check);
1756   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
1757   AddDialogData(check, &m_bGlPtWorkaround, DLG_CHECK_BOOL);
1758
1759   g_list_free (combo_list);
1760
1761 #ifdef ATIHACK_812
1762         // ATI bugs
1763         // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=812
1764         check = gtk_check_button_new_with_label ("ATI cards with broken drivers - bug #802");
1765         gtk_widget_show(check);
1766         gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
1767         AddDialogData(check, &m_bGlATIHack, DLG_CHECK_BOOL);
1768 #endif
1769   
1770   // Add the page to the notebook
1771   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
1772   
1773   /******** 3D Camera view group *********/
1774   preflabel = gtk_label_new("3D View");
1775   gtk_widget_show(preflabel);
1776   pageframe = gtk_frame_new("3D View");
1777   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
1778   gtk_widget_show(pageframe);
1779   vbox = gtk_vbox_new(FALSE, 5);
1780   gtk_widget_show(vbox);
1781   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
1782   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
1783
1784   // Directional velocity (Movement Velocity)
1785   // label container
1786   hbox2 = gtk_hbox_new (FALSE, 0);
1787   gtk_widget_show (hbox2);
1788   gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0);
1789   
1790   // label
1791   label = gtk_label_new("Movement Velocity");
1792   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1793   gtk_widget_show(label);
1794   gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1795   
1796   // adjustment
1797   adj = gtk_adjustment_new(100, 50, 300, 1, 10, 10);
1798   AddDialogData(adj, &m_nMoveSpeed, DLG_ADJ_INT);
1799   
1800   // scale
1801   scale = gtk_hscale_new(GTK_ADJUSTMENT(adj));
1802   gtk_widget_show(scale);
1803   gtk_box_pack_start(GTK_BOX (vbox), scale, FALSE, TRUE, 2);
1804   
1805   gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
1806   
1807   // Angular velocity (Rotational Velocity)
1808   // label container
1809   hbox2 = gtk_hbox_new (FALSE, 0);
1810   gtk_widget_show (hbox2);
1811   gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0);
1812   
1813   // label
1814   label = gtk_label_new ("Rotational Velocity");
1815   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1816   gtk_widget_show (label);
1817   gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
1818   
1819   // adjustment
1820   adj = gtk_adjustment_new (3, 1, 180, 1, 10, 10); // value, low, high, step, page_step, page_size
1821   AddDialogData (adj, &m_nAngleSpeed, DLG_ADJ_INT);
1822   
1823   // scale
1824   scale = gtk_hscale_new (GTK_ADJUSTMENT (adj));
1825   gtk_widget_show (scale);
1826   gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, TRUE, 2);
1827   gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);  
1828
1829   // Text under the velocity sliders
1830   // container
1831   hbox2 = gtk_hbox_new (FALSE, 0);
1832   gtk_widget_show (hbox2);
1833   gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0);
1834   
1835   // label
1836   label = gtk_label_new ("slow");
1837   gtk_widget_show (label);
1838   gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1839   
1840   // label
1841   label = gtk_label_new ("fast");
1842   gtk_widget_show (label);
1843   gtk_box_pack_end (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1844   
1845   // Allow drag to select multiple faces/brushes
1846   // container
1847   table = gtk_table_new(2, 1, FALSE);
1848   gtk_widget_show(table);
1849   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
1850   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
1851   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
1852
1853   label = gtk_label_new ("Use paint-select in camera view:");
1854   gtk_widget_show (label);
1855   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1856   gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
1857                   (GtkAttachOptions) (0),
1858                   (GtkAttachOptions) (0), 0, 0);
1859
1860   combo_list = NULL;
1861   combo_list = g_list_append (combo_list, (void *)"No");
1862   combo_list = g_list_append (combo_list, (void *)"Yes");
1863   combo_list = g_list_append (combo_list, (void *)"Yes (Classic Key Setup)");
1864
1865   combo = gtk_combo_new ();
1866   gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
1867   gtk_widget_show (combo);
1868   gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1,
1869                   (GtkAttachOptions) (GTK_FILL),
1870                   (GtkAttachOptions) (0), 0, 0);
1871   gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE);
1872   AddDialogData (combo, &m_nCamDragMultiSelect, DLG_COMBO_INT);  
1873
1874   // Freelook in Camera view
1875   check = gtk_check_button_new_with_label ("Freelook in Camera view");
1876   gtk_widget_show (check);
1877   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1878   gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT);
1879   AddDialogData (check, &m_bCamFreeLook, DLG_CHECK_BOOL);
1880
1881   // Freelook in Camera view w/ forward & back strafing instead of up and down looking
1882   check = gtk_check_button_new_with_label ("Freelook strafes Forward and Back");
1883   gtk_widget_show (check);
1884   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1885   gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT);
1886   AddDialogData (check, &m_bCamFreeLookStrafe, DLG_CHECK_BOOL);
1887
1888   // Invert mouse in freelook
1889   check = gtk_check_button_new_with_label ("Invert mouse in freelook");
1890   gtk_widget_show (check);
1891   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1892   gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT);
1893   AddDialogData (check, &m_bCamInverseMouse, DLG_CHECK_BOOL);
1894
1895   // Discrete movement
1896   check = gtk_check_button_new_with_label ("Discrete movement");
1897   gtk_widget_show (check);
1898   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1899   gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT);
1900   AddDialogData (check, &m_bCamDiscrete, DLG_CHECK_BOOL);
1901
1902   // Update XY views on camera move
1903   check = gtk_check_button_new_with_label ("Update XY views on camera move");
1904   gtk_widget_show (check);
1905   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1906   gtk_label_set_justify (GTK_LABEL (GTK_BIN (check)->child), GTK_JUSTIFY_LEFT);
1907   AddDialogData (check, &m_bCamXYUpdate, DLG_CHECK_BOOL);
1908
1909   // Add the page to the notebook
1910   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
1911
1912   /******** Texture group *********/
1913   preflabel = gtk_label_new("Textures");
1914   gtk_widget_show(preflabel);
1915   pageframe = gtk_frame_new("Textures");
1916   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
1917   gtk_widget_show(pageframe);
1918   vbox = gtk_vbox_new(FALSE, 6);
1919   gtk_widget_show(vbox);
1920   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
1921   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
1922   
1923   // Texture quality slider
1924   // label
1925   label = gtk_label_new ("Texture quality");
1926   gtk_widget_show (label);
1927   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
1928   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1929   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1930   
1931   // adjustment
1932   adj = gtk_adjustment_new (0, 0, 4, 1, 1, 1);
1933   AddDialogData (adj, &m_nLatchedTextureQuality, DLG_ADJ_INT);
1934   
1935   // scale
1936   scale = gtk_hscale_new (GTK_ADJUSTMENT (adj));
1937   gtk_widget_show (scale);
1938   gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
1939   gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
1940
1941   // text under the texture slider
1942   hbox2 = gtk_hbox_new (FALSE, 0);
1943   gtk_widget_show (hbox2);
1944   gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 0);
1945   label = gtk_label_new ("low");
1946   gtk_widget_show (label);
1947   gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1948   label = gtk_label_new ("high");
1949   gtk_widget_show (label);
1950   gtk_box_pack_end (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1951
1952   // texture subsets
1953   check = gtk_check_button_new_with_label ("Texture subsets");
1954   gtk_widget_show (check);
1955   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1956   AddDialogData (check, &m_bTextureWindow, DLG_CHECK_BOOL);
1957   
1958   // texture scrollbar
1959   check = gtk_check_button_new_with_label ("Texture scrollbar");
1960   gtk_widget_show (check);
1961   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
1962   AddDialogData (check, &m_bTextureScrollbar, DLG_CHECK_BOOL);
1963
1964   // texture increment matches grid
1965   check = gtk_check_button_new_with_label ("Tex increment matches grid");
1966   gtk_widget_show (check);
1967   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
1968   AddDialogData (check, &m_bSnapTToGrid, DLG_CHECK_BOOL);
1969
1970   // RIANT
1971   // Texture compression choice label
1972   // container
1973   table = gtk_table_new(2, 1, FALSE);
1974   gtk_widget_show(table);
1975   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
1976   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
1977   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
1978
1979   label = gtk_label_new ("Texture Compression (if available):");
1980   gtk_widget_show (label);
1981   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1982   gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
1983                   (GtkAttachOptions) (0),
1984                   (GtkAttachOptions) (0), 0, 0);
1985   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1986
1987   // Texture compression choice label
1988   combo_list = NULL;
1989   // NONE will always be in pos 0
1990   combo_list = g_list_append (combo_list, (void *)"None");
1991
1992   // if OpenGL compression is enabled it will always be
1993   // in pos 1
1994   if (g_qeglobals.m_bOpenGLCompressionSupported)
1995   {
1996     combo_list = g_list_append (combo_list, (void *)"OpenGL ARB");
1997   }
1998
1999   // If S3 is enabled offer all 3 valid compression schemes in RGBA
2000   if (g_qeglobals.m_bS3CompressionSupported)
2001   {
2002     combo_list = g_list_append (combo_list, (void *)"S3TC DXT1");
2003     combo_list = g_list_append (combo_list, (void *)"S3TC DXT3");
2004     combo_list = g_list_append (combo_list, (void *)"S3TC DXT5");
2005   }
2006
2007   combo = gtk_combo_new ();
2008   gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
2009   gtk_widget_show (combo);
2010   gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1,
2011                   (GtkAttachOptions) (GTK_FILL),
2012                   (GtkAttachOptions) (0), 0, 0);
2013   gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE);
2014   AddDialogData (combo, &m_nTextureCompressionFormat, DLG_COMBO_INT);
2015   g_list_free (combo_list);
2016
2017   // container
2018   table = gtk_table_new(2, 1, FALSE);
2019   gtk_widget_show(table);
2020   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
2021   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2022   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2023
2024   // Startup shaders
2025   // label
2026   label = gtk_label_new ("Startup Shaders:");
2027   gtk_widget_show (label);
2028   gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
2029   gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
2030                   (GtkAttachOptions) (0),
2031                   (GtkAttachOptions) (0), 0, 0);
2032   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2033   
2034   // combo list
2035   combo_list = NULL;
2036   combo_list = g_list_append (combo_list, (void *)"None");
2037   if (g_pGameDescription->mGameFile == "jk2.game" || g_pGameDescription->mGameFile == "ja.game")
2038     combo_list = g_list_append (combo_list, (void *)"System");
2039   else if (g_pGameDescription->mGameFile == "sof2.game")
2040     combo_list = g_list_append (combo_list, (void *)"Tools");
2041   else
2042     combo_list = g_list_append (combo_list, (void *)"Common");
2043   combo_list = g_list_append (combo_list, (void *)"All");
2044   combo = gtk_combo_new ();
2045   gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
2046   gtk_widget_show (combo);
2047   gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1,
2048                   (GtkAttachOptions) (GTK_FILL),
2049                   (GtkAttachOptions) (0), 0, 0);
2050   gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE);
2051   AddDialogData (combo, &m_nLatchedShader, DLG_COMBO_INT);
2052   g_list_free (combo_list);
2053   
2054   // Add the page to the notebook
2055   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2056   
2057   /******** Layout group *********/
2058   preflabel = gtk_label_new("Layout");
2059   gtk_widget_show(preflabel);
2060   pageframe = gtk_frame_new("Layout");
2061   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2062   gtk_widget_show(pageframe);
2063   vbox = gtk_vbox_new(FALSE, 5);
2064   gtk_widget_show(vbox);
2065   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2066   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2067
2068   // View types
2069   // table
2070   table = gtk_table_new (2, 4, FALSE);
2071   gtk_widget_show (table);
2072   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
2073   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2074   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2075
2076   // view type 1
2077   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window1.bmp");
2078   gtk_widget_show (pixmap);
2079   gtk_table_attach (GTK_TABLE (table), pixmap, 0, 1, 0, 1,
2080                     (GtkAttachOptions) (0),
2081                     (GtkAttachOptions) (0), 0, 0);
2082
2083   // view type 2
2084   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window2.bmp");
2085   gtk_widget_show (pixmap);
2086   gtk_table_attach (GTK_TABLE (table), pixmap, 1, 2, 0, 1,
2087                     (GtkAttachOptions) (0),
2088                     (GtkAttachOptions) (0), 0, 0);
2089
2090   // view type 3
2091   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window3.bmp");
2092   gtk_widget_show (pixmap);
2093   gtk_table_attach (GTK_TABLE (table), pixmap, 2, 3, 0, 1,
2094                     (GtkAttachOptions) (0),
2095                     (GtkAttachOptions) (0), 0, 0);
2096
2097   // view type 4
2098   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "window4.bmp");
2099   gtk_widget_show (pixmap);
2100   gtk_table_attach (GTK_TABLE (table), pixmap, 3, 4, 0, 1,
2101                     (GtkAttachOptions) (0),
2102                     (GtkAttachOptions) (0), 0, 0);
2103
2104   // view type 1 selector
2105   radio = gtk_radio_button_new (NULL);
2106   gtk_widget_show (radio);
2107   gtk_table_attach (GTK_TABLE (table), radio, 0, 1, 1, 2,
2108                     (GtkAttachOptions) (0),
2109                     (GtkAttachOptions) (0), 0, 0);
2110
2111   // view type 2 selector
2112   radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio));
2113   gtk_widget_show (radio);
2114   gtk_table_attach (GTK_TABLE (table), radio, 1, 2, 1, 2,
2115                     (GtkAttachOptions) (0),
2116                     (GtkAttachOptions) (0), 0, 0);
2117
2118   // view type 3 selector
2119   radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio));
2120   gtk_widget_show (radio);
2121   gtk_table_attach (GTK_TABLE (table), radio, 2, 3, 1, 2,
2122                     (GtkAttachOptions) (0),
2123                     (GtkAttachOptions) (0), 0, 0);
2124
2125   // view type 4 selector
2126   radio = gtk_radio_button_new_from_widget (GTK_RADIO_BUTTON (radio));
2127   gtk_widget_show (radio);
2128   gtk_table_attach (GTK_TABLE (table), radio, 3, 4, 1, 2,
2129                     (GtkAttachOptions) (0),
2130                     (GtkAttachOptions) (0), 0, 0);
2131   AddDialogData (radio, &m_nLatchedView, DLG_RADIO_INT);
2132   
2133   // Floating Z window
2134   check = gtk_check_button_new_with_label ("Floating Z Window");
2135   gtk_widget_show (check);
2136   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2137   AddDialogData (check, &m_bLatchedFloatingZ, DLG_CHECK_BOOL);
2138   
2139   // show menu tear-off seperators
2140   check = gtk_check_button_new_with_label ("Detachable Menus");
2141   gtk_widget_show (check);
2142   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2143   AddDialogData (check, &m_bLatchedDetachableMenus, DLG_CHECK_BOOL);
2144
2145   if (!g_pGameDescription->mNoPatch)
2146   {
2147     // show patch toolbar
2148     check = gtk_check_button_new_with_label ("Patch Toolbar");
2149     gtk_widget_show (check);
2150     gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2151     g_object_set_data (G_OBJECT (dialog), "check_patchtoolbar", check); // Allow to be disabled for Q1/Q2
2152     AddDialogData (check, &m_bLatchedPatchToolbar, DLG_CHECK_BOOL);
2153   }
2154
2155   // use wide toolbar
2156   check = gtk_check_button_new_with_label ("Wide Toolbar");
2157   gtk_widget_show (check);
2158   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2159   AddDialogData (check, &m_bLatchedWideToolbar, DLG_CHECK_BOOL);
2160
2161   // use plugin toolbar
2162   check = gtk_check_button_new_with_label ("Plugin Toolbar");
2163   gtk_widget_show (check);
2164   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2165   AddDialogData (check, &m_bLatchedPluginToolbar, DLG_CHECK_BOOL);
2166
2167 #ifdef _WIN32
2168   // win32 file dialog
2169   check = gtk_check_button_new_with_label ("Use win32 file load dialog");
2170   gtk_widget_show (check);
2171   // gtk_container_add (GTK_CONTAINER (vbox), check);
2172   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2173   AddDialogData (check, &m_bNativeGUI, DLG_CHECK_BOOL);
2174
2175   // position on primary monitor
2176   check = gtk_check_button_new_with_label ("Start on Primary Monitor");
2177   gtk_widget_show (check);
2178   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2179   g_object_set_data (G_OBJECT (dialog), "check_startonprimary", check);
2180   gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateSensitivity), this );
2181   AddDialogData (check, &m_bStartOnPrimMon, DLG_CHECK_BOOL);
2182 #endif  
2183
2184   // Add the page to the notebook
2185   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2186   
2187   /******** Mouse group *********/
2188   preflabel = gtk_label_new("Mouse");
2189   gtk_widget_show(preflabel);
2190   pageframe = gtk_frame_new("Mouse");
2191   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2192   gtk_widget_show(pageframe);
2193   vbox = gtk_vbox_new(FALSE, 5);
2194   gtk_widget_show(vbox);
2195   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2196   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2197   
2198   // Buttons
2199   // container
2200   hbox2 = gtk_hbox_new (FALSE, 5);
2201   gtk_widget_show (hbox2);
2202   gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
2203
2204   // 2 button radio
2205   radio = gtk_radio_button_new_with_label (NULL, "2 button");
2206   gtk_widget_show (radio);
2207   gtk_box_pack_start (GTK_BOX (hbox2), radio, FALSE, FALSE, 0);
2208
2209   // 3 button radio
2210   radio = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), "3 button");
2211   gtk_widget_show (radio);
2212   gtk_box_pack_start (GTK_BOX (hbox2), radio, FALSE, FALSE, 0);
2213   AddDialogData (radio, &m_nMouse, DLG_RADIO_INT);
2214
2215   // right click to drop entity
2216   check = gtk_check_button_new_with_label ("Right click to drop entities");
2217   gtk_widget_show (check);
2218   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2219   AddDialogData (check, &m_bRightClick, DLG_CHECK_BOOL);
2220
2221   // Mouse chaser (and this does what?)
2222   check = gtk_check_button_new_with_label ("Mouse chaser");
2223   gtk_widget_show (check);
2224   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2225   AddDialogData (check, &m_bChaseMouse, DLG_CHECK_BOOL);
2226
2227   // Alt + multi-drag
2228   check = gtk_check_button_new_with_label ("ALT + multi-drag");
2229   gtk_widget_show (check);
2230   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2231   AddDialogData (check, &m_bALTEdge, DLG_CHECK_BOOL);
2232
2233   // Mouse wheel increments
2234   // container
2235   hbox2 = gtk_hbox_new (FALSE, 5);
2236   gtk_widget_show (hbox2);
2237   gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
2238   
2239   // label
2240   label = gtk_label_new ("Wheel Mouse inc:");
2241   gtk_widget_show (label);
2242   gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
2243   
2244   // entry
2245   entry = gtk_entry_new ();
2246   gtk_widget_show (entry);
2247   gtk_widget_set_usize (entry, 40, -2);
2248   gtk_box_pack_start (GTK_BOX (hbox2), entry, FALSE, FALSE, 0);
2249   AddDialogData (entry, &m_nWheelInc, DLG_ENTRY_INT);  
2250
2251   // Add the page to the notebook
2252   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2253   
2254   /******** Editing group *********/
2255   preflabel = gtk_label_new("Editing");
2256   gtk_widget_show(preflabel);
2257   pageframe = gtk_frame_new("Editing");
2258   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2259   gtk_widget_show(pageframe);
2260   vbox = gtk_vbox_new(FALSE, 5);
2261   gtk_widget_show(vbox);
2262   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2263   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2264   
2265   // Vertex editing splits faces
2266   check = gtk_check_button_new_with_label ("Vertex editing splits face");
2267   gtk_widget_show (check);
2268   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2269   AddDialogData (check, &m_bVertexSplit, DLG_CHECK_BOOL);
2270
2271   // Fix target/targetname collisions
2272   check = gtk_check_button_new_with_label ("Fix target/targetname collisions");
2273   gtk_widget_show (check);
2274   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2275   AddDialogData (check, &m_bDoTargetFix, DLG_CHECK_BOOL);
2276   
2277   // Clipper tool uses caulk
2278   check = gtk_check_button_new_with_label ("Clipper tool uses caulk");
2279   gtk_widget_show (check);
2280   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2281   AddDialogData (check, &m_bClipCaulk, DLG_CHECK_BOOL);
2282
2283   // Don't clamp plane points
2284   check = gtk_check_button_new_with_label ("Don't clamp plane points");
2285   gtk_widget_show (check);
2286   gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
2287   AddDialogData (check, &m_bNoClamp, DLG_CHECK_BOOL);
2288
2289   // Select patch by bounding box
2290   check = gtk_check_button_new_with_label ("Select patches by bounding box");
2291   gtk_widget_show (check);
2292   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2293   AddDialogData (check, &m_bPatchBBoxSelect, DLG_CHECK_BOOL);  
2294   
2295   // Rotation increment
2296   // container
2297   table = gtk_table_new (2, 3, FALSE);
2298   gtk_widget_show (table);
2299   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
2300   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2301   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2302   
2303   // label
2304   label = gtk_label_new ("Rotation increment:");
2305   gtk_widget_show (label);
2306   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2307                    (GtkAttachOptions) (0),
2308                    (GtkAttachOptions) (0), 0, 0);
2309                    
2310   // entry
2311   entry = gtk_entry_new ();
2312   gtk_widget_show (entry);
2313   gtk_widget_set_usize (entry, 60, -2);
2314   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
2315                    (GtkAttachOptions) (GTK_FILL),
2316                    (GtkAttachOptions) (0), 0, 0);
2317   AddDialogData (entry, &m_nRotation, DLG_ENTRY_INT);
2318   
2319   // Undo levels
2320   // label
2321   label = gtk_label_new ("Undo Levels:");
2322   gtk_widget_show (label);
2323   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
2324                    (GtkAttachOptions) (0),
2325                    (GtkAttachOptions) (0), 0, 0);
2326                    
2327   // spinner (allows undo levels to be set to zero)
2328   spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (1, 0, 64, 1, 10, 10)), 1, 0); 
2329   gtk_widget_show (spin);
2330   gtk_table_attach (GTK_TABLE (table), spin, 1, 2, 1, 2,
2331                    (GtkAttachOptions) (GTK_FILL),
2332                    (GtkAttachOptions) (0), 0, 0);
2333   gtk_widget_set_usize (spin, 60, -2);
2334   AddDialogData (spin, &m_nUndoLevels, DLG_SPIN_INT);
2335
2336   // Patch subdivisions
2337   // label
2338   label = gtk_label_new ("Patch subdivisions:");
2339   gtk_widget_show (label);
2340   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
2341                    (GtkAttachOptions) (0),
2342                    (GtkAttachOptions) (0), 0, 0);
2343                    
2344   // entry (spinner perhaps? [2-16])
2345   entry = gtk_entry_new ();
2346   gtk_widget_show (entry);
2347   gtk_widget_set_usize (entry, 60, -2);
2348   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 2, 3,
2349                    (GtkAttachOptions) (GTK_FILL),
2350                    (GtkAttachOptions) (0), 0, 0);
2351   AddDialogData (entry, &m_nSubdivisions, DLG_ENTRY_INT);
2352
2353   // Add the page to the notebook
2354   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2355   
2356   /******** Save/Load group *********/
2357   preflabel = gtk_label_new("Startup/Auto save");
2358   gtk_widget_show(preflabel);
2359   pageframe = gtk_frame_new("Startup/Auto save");
2360   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2361   gtk_widget_show(pageframe);
2362   vbox = gtk_vbox_new(FALSE, 5);
2363   gtk_widget_show(vbox);
2364   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2365   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2366
2367   // Snapshots
2368   check = gtk_check_button_new_with_label ("Snapshots");
2369   gtk_widget_show (check);
2370   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2371   AddDialogData (check, &m_bSnapShots, DLG_CHECK_BOOL);
2372   
2373   // load last project on open
2374   check = gtk_check_button_new_with_label ("Load last project on open");
2375   gtk_widget_show (check);
2376   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2377   AddDialogData (check, &m_bLoadLast, DLG_CHECK_BOOL);
2378
2379   // load last map on open
2380   check = gtk_check_button_new_with_label ("Load last map on open");
2381   gtk_widget_show (check);
2382   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2383   AddDialogData (check, &m_bLoadLastMap, DLG_CHECK_BOOL);
2384
2385   // Auto save..
2386   // container
2387   hbox2 = gtk_hbox_new (FALSE, 5);
2388   gtk_widget_show (hbox2);
2389   gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
2390   gtk_container_set_border_width (GTK_CONTAINER (hbox2), 0);
2391   
2392   // label
2393   check = gtk_check_button_new_with_label ("Auto save every");
2394   gtk_widget_show (check);
2395   gtk_box_pack_start (GTK_BOX (hbox2), check, FALSE, FALSE, 0);
2396   AddDialogData (check, &m_bAutoSave, DLG_CHECK_BOOL);
2397   
2398   // spinner
2399   spin = gtk_spin_button_new (GTK_ADJUSTMENT (gtk_adjustment_new (1, 1, 60, 1, 10, 10)), 1, 0);
2400   gtk_widget_show (spin);
2401   gtk_box_pack_start (GTK_BOX (hbox2), spin, FALSE, FALSE, 0);
2402   gtk_widget_set_usize (spin, 60, -2);
2403   AddDialogData (spin, &m_nAutoSave, DLG_SPIN_INT);
2404   
2405   // label
2406   label = gtk_label_new ("minutes");
2407   gtk_widget_show (label);
2408   gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
2409   
2410   // Add the page to the notebook
2411   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2412   
2413   /******** Paths group *********/
2414   preflabel = gtk_label_new("Paths");
2415   gtk_widget_show(preflabel);
2416   pageframe = gtk_frame_new("Paths");
2417   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2418   gtk_widget_show(pageframe);
2419   vbox = gtk_vbox_new(FALSE, 5);
2420   gtk_widget_show(vbox);
2421   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2422   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2423
2424   // prefab path
2425   // table
2426   table = gtk_table_new (3, 3, FALSE);
2427   gtk_widget_show (table);
2428   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
2429   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2430   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2431   
2432   // label
2433   label = gtk_label_new ("Prefab path:");
2434   gtk_widget_show (label);
2435   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2436                    (GtkAttachOptions) (0),
2437                    (GtkAttachOptions) (0), 0, 0);
2438   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
2439   
2440   // path entry
2441   entry = gtk_entry_new ();
2442   gtk_widget_show (entry);
2443   gtk_widget_set_usize(GTK_WIDGET(entry), 240, -2);
2444   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
2445                    (GtkAttachOptions) (GTK_FILL),
2446                    (GtkAttachOptions) (0), 1, 0);
2447   AddDialogData (entry, &m_strPrefabPath, DLG_ENTRY_TEXT);
2448
2449   // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=805
2450 #if 0  
2451   // browse button
2452   button = gtk_button_new_with_label ("...");
2453   gtk_widget_show (button);
2454   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnBrowseprefab), this);
2455   gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
2456                    (GtkAttachOptions) (0),
2457                    (GtkAttachOptions) (0), 0, 0);
2458 #endif
2459
2460   // User ini path
2461   // label
2462   label = gtk_label_new ("User INI path:");
2463   gtk_widget_show (label);
2464   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
2465                    (GtkAttachOptions) (0),
2466                    (GtkAttachOptions) (0), 0, 0);
2467   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
2468   
2469   // user ini path entry
2470   entry = gtk_entry_new ();
2471   gtk_widget_show (entry);
2472   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,
2473                    (GtkAttachOptions) (GTK_FILL),
2474                    (GtkAttachOptions) (0), 1, 0);
2475   AddDialogData (entry, &m_strUserPath, DLG_ENTRY_TEXT);
2476   
2477   // user ini browse button
2478   button = gtk_button_new_with_label ("...");
2479   gtk_widget_show (button);
2480   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnBrowseuserini), this);
2481   gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
2482                    (GtkAttachOptions) (0),
2483                    (GtkAttachOptions) (0), 0, 0);
2484
2485   // Add the page to the notebook
2486   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2487   
2488   /******** Misc group *********/
2489   preflabel = gtk_label_new("Misc");
2490   gtk_widget_show(preflabel);
2491   pageframe = gtk_frame_new("Misc");
2492   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2493   gtk_widget_show(pageframe);
2494   vbox = gtk_vbox_new(FALSE, 5);
2495   gtk_widget_show(vbox);
2496   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2497   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2498   
2499   // Light drawing
2500   check = gtk_check_button_new_with_label ("Light drawing");
2501   gtk_widget_show (check);
2502   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2503   AddDialogData (check, &m_bNewLightDraw, DLG_CHECK_BOOL);
2504
2505   // Light radiuses
2506   // container
2507   table = gtk_table_new(2, 1, FALSE);
2508   gtk_widget_show(table);
2509   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
2510   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2511   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2512
2513   label = gtk_label_new ("Light radiuses:");
2514   gtk_widget_show (label);
2515   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
2516   gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
2517                   (GtkAttachOptions) (0),
2518                   (GtkAttachOptions) (0), 0, 0);
2519
2520   combo_list = NULL;
2521   combo_list = g_list_append (combo_list, (void *)"Disabled");
2522   combo_list = g_list_append (combo_list, (void *)"True Q3Map2 Style");
2523   combo_list = g_list_append (combo_list, (void *)"Classic Style");
2524
2525   combo = gtk_combo_new ();
2526   gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
2527   gtk_widget_show (combo);
2528   gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1,
2529                   (GtkAttachOptions) (GTK_FILL),
2530                   (GtkAttachOptions) (0), 0, 0);
2531   gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (combo)->entry), FALSE);
2532   AddDialogData (combo, &m_nLightRadiuses, DLG_COMBO_INT);
2533
2534 #ifdef _WIN32
2535   check = gtk_check_button_new_with_label ("Use win32 file associations to open text files instead of builtin editor");
2536   gtk_widget_show(check);
2537   gtk_box_pack_start(GTK_BOX (vbox), check, FALSE, FALSE, 0);
2538   AddDialogData (check, &g_PrefsDlg.m_bUseWin32Editor, DLG_CHECK_BOOL);
2539 #else
2540   // use custom shader editor
2541   check = gtk_check_button_new_with_label ("Use Custom Shader Editor");
2542   gtk_widget_show(check);
2543   gtk_box_pack_start(GTK_BOX (vbox), check, FALSE, FALSE, 0);
2544   gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateEditorSensitivity), this);
2545   g_object_set_data (G_OBJECT(dialog), "check_customeditor", check);
2546   AddDialogData (check, &g_PrefsDlg.m_bUseCustomEditor, DLG_CHECK_BOOL);
2547   
2548   // custom shader editor executable
2549   // table
2550   table = gtk_table_new (3, 1, FALSE);
2551   gtk_widget_show (table);
2552   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
2553   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2554   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2555   
2556   // label
2557   label = gtk_label_new("Custom Editor Command");
2558   gtk_widget_show(label);
2559   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2560                    (GtkAttachOptions) (0),
2561                    (GtkAttachOptions) (0), 0, 0);
2562   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
2563   g_object_set_data (G_OBJECT(dialog), "label_customeditor", label);
2564   gtk_widget_set_sensitive (label, g_PrefsDlg.m_bUseCustomEditor);
2565   
2566   // custom editor command entry
2567   entry = gtk_entry_new ();
2568   gtk_widget_show (entry);
2569   gtk_widget_set_usize(GTK_WIDGET(entry), 240, -2);
2570   gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
2571                    (GtkAttachOptions) (GTK_FILL),
2572                    (GtkAttachOptions) (0), 1, 0);
2573   AddDialogData (entry, &m_strEditorCommand, DLG_ENTRY_TEXT);
2574   gtk_widget_set_sensitive (entry, g_PrefsDlg.m_bUseCustomEditor);
2575   g_object_set_data (G_OBJECT(dialog), "entry_customeditor", entry);
2576   
2577   // browse button
2578   button = gtk_button_new_with_label ("...");
2579   gtk_widget_show (button);
2580   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (OnBtnBrowseEditor), this);
2581   gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
2582                    (GtkAttachOptions) (0),
2583                    (GtkAttachOptions) (0), 0, 0);
2584   g_object_set_data (G_OBJECT(dialog), "button_customeditor", button);
2585   gtk_widget_set_sensitive (button, g_PrefsDlg.m_bUseCustomEditor);
2586 #endif
2587
2588   // Add the page to the notebook
2589   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2590
2591   /******** BSP Monitoring group *********/
2592   // this is never displayed if the plugin isn't available
2593   preflabel = gtk_label_new("BSP Monitoring");
2594   gtk_widget_show(preflabel);
2595   pageframe = gtk_frame_new("BSP Monitoring");
2596   gtk_container_set_border_width(GTK_CONTAINER(pageframe), 5);
2597   gtk_widget_show(pageframe);
2598   vbox = gtk_vbox_new(FALSE, 5);
2599   gtk_widget_show(vbox);
2600   gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
2601   gtk_container_add(GTK_CONTAINER(pageframe), vbox);
2602
2603   // Enable BSP process monitoring
2604   check = gtk_check_button_new_with_label ("Enable BSP process monitoring");
2605   gtk_widget_show (check);
2606   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2607   g_object_set_data (G_OBJECT (dialog), "check_monitorbsp", check);
2608   gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateSensitivity), this );
2609   AddDialogData (check, &g_PrefsDlg.m_bWatchBSP, DLG_CHECK_BOOL);
2610
2611   // Stop on leak
2612   check = gtk_check_button_new_with_label ("Stop compilation on leak");
2613   gtk_widget_show (check);
2614   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2615   g_object_set_data (G_OBJECT (dialog), "check_leakstop", check);
2616   AddDialogData (check, &g_PrefsDlg.m_bLeakStop, DLG_CHECK_BOOL);
2617
2618   // engine after compile
2619   check = gtk_check_button_new_with_label ("Run engine after compile");
2620   gtk_widget_show (check);
2621   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2622   g_object_set_data (G_OBJECT (dialog), "check_runengine", check);
2623   gtk_signal_connect( GTK_OBJECT (check), "clicked", GTK_SIGNAL_FUNC(UpdateSensitivity), this );
2624   AddDialogData( check, &g_PrefsDlg.m_bRunQuake, DLG_CHECK_BOOL );  
2625   
2626   // sleep mode when running engine
2627   check = gtk_check_button_new_with_label ("Activate sleep mode when running the engine");
2628   gtk_widget_show (check);
2629   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2630   g_object_set_data (G_OBJECT (dialog), "check_sleep", check);
2631   AddDialogData( check, &g_PrefsDlg.m_bDoSleep, DLG_CHECK_BOOL );
2632   
2633   // use q3map2's texture projection
2634   check = gtk_check_button_new_with_label ("Texturing compatible with q3map2");
2635   gtk_widget_show (check);
2636   gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0);
2637   g_object_set_data (G_OBJECT (dialog), "check_q3map2", check);
2638   AddDialogData( check, &g_PrefsDlg.m_bQ3Map2Texturing, DLG_CHECK_BOOL );
2639
2640   // Add the page to the notebook
2641   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pageframe, preflabel);
2642
2643   gtk_notebook_set_page(GTK_NOTEBOOK(notebook), PTAB_FRONT);
2644
2645   return;
2646 }
2647
2648 // end new prefs dialog
2649
2650 void PrefsDlg::LoadTexdefPref(texdef_t* pTexdef, char* pName)
2651 {
2652   char buffer[256];
2653
2654   memset(pTexdef, 0, sizeof(texdef_t));
2655
2656   sprintf(buffer, "%s%s", pName, TD_SCALE1_KEY);
2657   mLocalPrefs.GetPref(buffer, &pTexdef->scale[0],   0.5f);      
2658
2659   sprintf(buffer, "%s%s", pName, TD_SCALE2_KEY);
2660   mLocalPrefs.GetPref(buffer, &pTexdef->scale[1],   0.5f);
2661
2662   sprintf(buffer, "%s%s", pName, TD_SHIFT1_KEY);
2663   mLocalPrefs.GetPref(buffer, &pTexdef->shift[0],   8.f);
2664
2665   sprintf(buffer, "%s%s", pName, TD_SHIFT2_KEY);
2666   mLocalPrefs.GetPref(buffer, &pTexdef->shift[1],   8.f);
2667
2668   sprintf(buffer, "%s%s", pName, TD_ROTATE_KEY);
2669   mLocalPrefs.GetPref(buffer, &pTexdef->rotate,     45);
2670 }
2671
2672 void PrefsDlg::UpdateTextureCompression()
2673 {
2674   // if OpenGL is not ready yet, don't do anything
2675   if (!g_qeglobals.m_bOpenGLReady) {
2676     Sys_Printf("OpenGL not ready - postpone texture compression capability check\n");
2677     return;
2678   }
2679   
2680   if (g_qeglobals.bTextureCompressionSupported)
2681   {
2682     if (m_nTextureCompressionFormat >= 2 && !g_qeglobals.m_bS3CompressionSupported)
2683     {
2684       Sys_Printf("Inconsistant pref setting for texture compression (%d), rolling back\n", m_nTextureCompressionFormat);
2685       m_nTextureCompressionFormat = 1; // if this is not supported either, see below
2686     }
2687     if (m_nTextureCompressionFormat == 1 && !g_qeglobals.m_bOpenGLCompressionSupported)
2688     {
2689       Sys_Printf("Inconsistant pref setting for texture compression (GL_COMPRESSED_RGBA), rolling back\n");
2690       m_nTextureCompressionFormat = 0;
2691     }
2692     switch (m_nTextureCompressionFormat)
2693     {
2694     case (0):
2695       {
2696         g_qeglobals.texture_components = GL_RGBA;
2697         Sys_Printf("texture compression disabled by preferences settings\n");
2698         break;
2699       }
2700     case (1):
2701       {
2702         g_qeglobals.texture_components = GL_COMPRESSED_RGBA;
2703         Sys_Printf("OpenGL texture compression enabled\n");
2704         break;
2705       }
2706     case (2):
2707       {
2708         g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
2709         Sys_Printf("S3TC DXT1 texture compression enabled\n");
2710         break;
2711       }
2712     case (3):
2713       {
2714         g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
2715         Sys_Printf("S3TC DXT3 texture compression enabled\n");
2716         break;
2717       }
2718     case (4):
2719       {
2720         g_qeglobals.texture_components = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
2721         Sys_Printf("S3TC DXT5 texture compression enabled\n");
2722         break;
2723       }
2724     }
2725   }
2726   else
2727   {
2728     Sys_Printf("texture compression is not supported by your current graphic card/drivers\n");
2729     g_qeglobals.texture_components = GL_RGBA;
2730     m_nTextureCompressionFormat = 0;
2731   }
2732 }
2733
2734 #ifdef ATIHACK_812
2735 void PrefsDlg::UpdateATIHack() {
2736   // if OpenGL is not ready yet, don't do anything
2737   if (!g_qeglobals.m_bOpenGLReady) {
2738     Sys_Printf("OpenGL not ready - postpone ATI bug workaround setup\n");
2739     return;
2740   }
2741
2742   if (m_bGlATIHack) {
2743     qglCullFace = &qglCullFace_ATIHack;
2744     qglDisable = &qglDisable_ATIHack;
2745     qglEnable = &qglEnable_ATIHack;
2746     qglPolygonMode = &qglPolygonMode_ATIHack;
2747     Sys_Printf("ATI bug workaround enabled\n");
2748   } else {
2749     qglCullFace = qglCullFace_real;
2750     qglDisable = qglDisable_real;
2751     qglEnable = qglEnable_real;
2752     qglPolygonMode = qglPolygonMode_real;
2753     Sys_Printf("ATI bug workaround disabled\n");
2754   }
2755 }
2756 #endif
2757
2758 // TTimo: m_strEnginePath has a special status, if not found in registry we need to 
2759 // initiliaze it for sure. It is not totally failsafe but we can use the same
2760 // code than in q3map, expecting to find some "quake" above us. If not, we prompt
2761 // for the engine executable path
2762 void PrefsDlg::LoadPrefs ()
2763 {
2764   int i;
2765
2766   // first things first, load prefs from global prefs
2767   mGamesDialog.LoadPrefs();
2768
2769   // if we already have a document loaded, we will free and reload from file
2770   if (mLocalPrefs.InUse()) {
2771     mLocalPrefs.Clear();
2772   }
2773
2774   // load local.pref file
2775   mLocalPrefs.ReadXMLFile(m_inipath->str);
2776
2777   mLocalPrefs.GetPref(PATCHSHOWBOUNDS_KEY,  &g_bPatchShowBounds,  FALSE);
2778   mLocalPrefs.GetPref(MOUSE_KEY,            &m_nMouse,            MOUSE_DEF);
2779   m_nMouseButtons = m_nMouse ? 3 : 2;
2780   
2781         // project file
2782         // if it's not found here, mainframe.cpp will take care of finding one
2783   mLocalPrefs.GetPref(LASTPROJ_KEY, &m_strLastProject, "");
2784   mLocalPrefs.GetPref(LASTPROJVER_KEY, &m_nLastProjectVer, -1);
2785
2786         // prefab path
2787   // NOTE TTimo: I'm not sure why this is in prefs
2788   // should probably be a project setting
2789   // and I'm not sure that we really have a way to set this reliably either
2790   CString strPrefab;
2791   strPrefab = g_qeglobals.m_strHomeGame.GetBuffer();
2792   strPrefab += g_pGameDescription->mBaseGame.GetBuffer();
2793   strPrefab += "/prefabs/";
2794   mLocalPrefs.GetPref(PREFAB_KEY, &m_strPrefabPath, strPrefab);
2795
2796   mLocalPrefs.GetPref(LASTLIGHTINTENSITY_KEY, &m_iLastLightIntensity, 300);
2797   mLocalPrefs.GetPref(TLOCK_KEY,              &m_bTextureLock,        TLOCK_DEF);
2798   mLocalPrefs.GetPref(RLOCK_KEY,              &m_bRotateLock,         TLOCK_DEF);
2799   mLocalPrefs.GetPref(LASTMAP_KEY,            &m_strLastMap,          "");
2800   mLocalPrefs.GetPref(LOADLAST_KEY,           &m_bLoadLast,           LOADLAST_DEF);
2801   mLocalPrefs.GetPref(BSP_KEY,                &m_bInternalBSP,        FALSE);
2802   mLocalPrefs.GetPref(RCLICK_KEY,             &m_bRightClick,         TRUE);
2803   mLocalPrefs.GetPref(AUTOSAVE_KEY,           &m_bAutoSave,           TRUE);
2804   mLocalPrefs.GetPref(LOADLASTMAP_KEY,        &m_bLoadLastMap,        FALSE);
2805   mLocalPrefs.GetPref(TINYBRUSH_KEY,          &m_bCleanTiny,          FALSE);
2806   mLocalPrefs.GetPref(TINYSIZE_KEY,           &m_fTinySize,           0.5f);
2807   mLocalPrefs.GetPref(AUTOSAVETIME_KEY,       &m_nAutoSave,           5);
2808   mLocalPrefs.GetPref(SNAPSHOT_KEY,           &m_bSnapShots,          FALSE);
2809   mLocalPrefs.GetPref(MOVESPEED_KEY,          &m_nMoveSpeed,          100);
2810   mLocalPrefs.GetPref(ANGLESPEED_KEY,         &m_nAngleSpeed,         3);
2811   mLocalPrefs.GetPref(SETGAME_KEY,            &m_bSetGame,            FALSE);
2812   mLocalPrefs.GetPref(CAMXYUPDATE_KEY,        &m_bCamXYUpdate,        TRUE);
2813   mLocalPrefs.GetPref(CAMDRAGMULTISELECT_KEY, &m_nCamDragMultiSelect, TRUE);
2814   mLocalPrefs.GetPref(CAMFREELOOK_KEY,        &m_bCamFreeLook,        TRUE);
2815   mLocalPrefs.GetPref(CAMINVERSEMOUSE_KEY,    &m_bCamInverseMouse,    FALSE);
2816   mLocalPrefs.GetPref(CAMDISCRETE_KEY,        &m_bCamDiscrete,        TRUE);
2817   mLocalPrefs.GetPref(LIGHTDRAW_KEY,          &m_bNewLightDraw,       TRUE);
2818   mLocalPrefs.GetPref(CUBICCLIP_KEY,          &m_bCubicClipping,      TRUE);
2819   mLocalPrefs.GetPref(CUBICSCALE_KEY,         &m_nCubicScale,         13);
2820   mLocalPrefs.GetPref(ALTEDGE_KEY,            &m_bALTEdge,            FALSE);
2821   mLocalPrefs.GetPref(FACECOLORS_KEY,         &m_bFaceColors,         FALSE);
2822   mLocalPrefs.GetPref(XZVIS_KEY,              &m_bXZVis,              FALSE);
2823   mLocalPrefs.GetPref(YZVIS_KEY,              &m_bYZVis,              FALSE);
2824   mLocalPrefs.GetPref(ZVIS_KEY,               &m_bZVis,               FALSE);
2825   mLocalPrefs.GetPref(SIZEPAINT_KEY,          &m_bSizePaint,                  FALSE);
2826   mLocalPrefs.GetPref(DLLENTITIES_KEY,        &m_bDLLEntities,                FALSE);
2827
2828   mLocalPrefs.GetPref(DETACHABLEMENUS_KEY,    &m_bLatchedDetachableMenus,            TRUE);
2829   m_bDetachableMenus = m_bLatchedDetachableMenus;
2830   
2831   if (g_pGameDescription->mNoPatch)
2832   {
2833     m_bPatchToolbar = false;
2834   }
2835   else
2836   {
2837     mLocalPrefs.GetPref(PATCHTOOLBAR_KEY,       &m_bLatchedPatchToolbar,               TRUE);
2838     m_bPatchToolbar = m_bLatchedPatchToolbar;
2839   }
2840
2841   mLocalPrefs.GetPref(WIDETOOLBAR_KEY,        &m_bLatchedWideToolbar,                TRUE);
2842   m_bWideToolbar = m_bLatchedWideToolbar;
2843  
2844   mLocalPrefs.GetPref(PLUGINTOOLBAR_KEY, &m_bLatchedPluginToolbar, TRUE);
2845   m_bPluginToolbar = m_bLatchedPluginToolbar;
2846
2847   mLocalPrefs.GetPref(WINDOW_KEY,             (int*)&m_nLatchedView,  WINDOW_DEF);
2848   m_nView = m_nLatchedView;
2849
2850   mLocalPrefs.GetPref(FLOATINGZ_KEY,          &m_bLatchedFloatingZ,           FALSE);
2851   m_bFloatingZ = m_bLatchedFloatingZ;
2852
2853   mLocalPrefs.GetPref(TEXTUREQUALITY_KEY,     &m_nLatchedTextureQuality,             3);
2854   m_nTextureQuality = m_nLatchedTextureQuality;
2855
2856   mLocalPrefs.GetPref(LOADSHADERS_KEY,        &m_nLatchedShader,                     0);
2857   m_nShader = m_nLatchedShader;
2858
2859   mLocalPrefs.GetPref(NOCLAMP_KEY,            &m_bNoClamp,                    FALSE);
2860   mLocalPrefs.GetPref(USERINI_KEY,            &m_strUserPath,                 "");
2861   mLocalPrefs.GetPref(ROTATION_KEY,           &m_nRotation,                   45);
2862   mLocalPrefs.GetPref(CHASEMOUSE_KEY,         &m_bChaseMouse,                 TRUE);
2863   mLocalPrefs.GetPref(ENTITYSHOW_KEY,         &m_nEntityShowState,            ENTITY_SKINNED_BOXED);
2864
2865   // this will probably need to be 75 or 100 for Q1.
2866   mLocalPrefs.GetPref(TEXTURESCALE_KEY,       &m_nTextureScale,               50);
2867
2868   // FIXME: Hydra - actually, this stuff is Q1,Q2 and HL specific.
2869   if ( (g_pGameDescription->mGameFile == "hl.game") )
2870   {
2871     // No BSP monitoring in the default compiler tools for Half-life (yet)
2872     mLocalPrefs.GetPref(WATCHBSP_KEY,           &m_bWatchBSP,                   FALSE);
2873
2874     // Texture subset on by default (HL specific really, because of halflife.wad's size)
2875     mLocalPrefs.GetPref(TEXTURE_KEY,            &m_bTextureWindow,              TRUE);
2876   }
2877   else if ( ( g_pGameDescription->mGameFile == "q2.game" ) || ( g_pGameDescription->mGameFile == "heretic2.game" ) )
2878   {
2879     // BSP monitoring is implemented in Quake2 and Heretic2 tools
2880     mLocalPrefs.GetPref(WATCHBSP_KEY,           &m_bWatchBSP,                   TRUE);
2881
2882     // Texture subset on by default (HL specific really, because of halflife.wad's size)
2883     mLocalPrefs.GetPref(TEXTURE_KEY,            &m_bTextureWindow,              TRUE);
2884   }
2885   else
2886   {
2887     mLocalPrefs.GetPref(WATCHBSP_KEY,           &m_bWatchBSP,                   WATCHBSP_DEF);
2888     mLocalPrefs.GetPref(TEXTURE_KEY,            &m_bTextureWindow,              FALSE);
2889   }
2890
2891
2892   mLocalPrefs.GetPref(TEXTURESCROLLBAR_KEY,   &m_bTextureScrollbar,           TRUE);
2893   mLocalPrefs.GetPref(DISPLAYLISTS_KEY,       &m_bDisplayLists,               TRUE);
2894   mLocalPrefs.GetPref(ANTIALIASEDLINES_KEY,   &m_bAntialiasedPointsAndLines,  FALSE);
2895   mLocalPrefs.GetPref(SWITCHCLIP_KEY,         &m_bSwitchClip,                 TRUE);
2896   mLocalPrefs.GetPref(SELWHOLEENTS_KEY,       &m_bSelectWholeEntities,        TRUE);
2897   mLocalPrefs.GetPref(SHOWSHADERS_KEY,        &m_bShowShaders,                TRUE);
2898   mLocalPrefs.GetPref(GLLIGHTING_KEY,         &m_bGLLighting,                 FALSE);
2899   mLocalPrefs.GetPref(NOSTIPPLE_KEY,          &m_bNoStipple,                  FALSE);
2900   mLocalPrefs.GetPref(UNDOLEVELS_KEY,         &m_nUndoLevels,                 30);
2901   mLocalPrefs.GetPref(VERTEXMODE_KEY,         &m_bVertexSplit,                TRUE);
2902   mLocalPrefs.GetPref(RUNQ2_KEY,              &m_bRunQuake,                   RUNQ2_DEF);
2903   mLocalPrefs.GetPref(LEAKSTOP_KEY,           &m_bLeakStop,                   TRUE);
2904   mLocalPrefs.GetPref(DOSLEEP_KEY,            &m_bDoSleep,                    FALSE);
2905   mLocalPrefs.GetPref(SELECTCURVES_KEY,       &m_bSelectCurves,               TRUE);
2906   mLocalPrefs.GetPref(SELECTMODELS_KEY,       &m_bSelectModels,               TRUE);
2907   mLocalPrefs.GetPref(SHADERLISTONLY_KEY,     &m_bTexturesShaderlistOnly,     FALSE);
2908   mLocalPrefs.GetPref(SUBDIVISIONS_KEY,       &m_nSubdivisions,               SUBDIVISIONS_DEF);
2909   mLocalPrefs.GetPref(CLIPCAULK_KEY,          &m_bClipCaulk,                  FALSE);
2910   mLocalPrefs.GetPref(SNAPTTOGRID_KEY,        &m_bSnapTToGrid,                FALSE);
2911   mLocalPrefs.GetPref(TARGETFIX_KEY,          &m_bDoTargetFix,                TRUE);
2912   mLocalPrefs.GetPref(WHEELINC_KEY,           &m_nWheelInc,                   64);
2913   mLocalPrefs.GetPref(PATCHBBOXSEL_KEY,       &m_bPatchBBoxSelect,            FALSE);
2914   
2915   // Gef: Kyro GL_POINT workaround
2916   mLocalPrefs.GetPref(GLPOINTWORKAROUND_KEY,  &m_bGlPtWorkaround,             FALSE);
2917
2918   // window positioning
2919   mLocalPrefs.GetPref(ENTITYSPLIT1_KEY,       &mWindowInfo.nEntitySplit1,     -1);
2920   mLocalPrefs.GetPref(ENTITYSPLIT2_KEY,       &mWindowInfo.nEntitySplit2,     -1);
2921
2922   mLocalPrefs.GetPref(POSITIONX_KEY,          &mWindowInfo.position.x,        -1);
2923   mLocalPrefs.GetPref(POSITIONY_KEY,          &mWindowInfo.position.y,        -1);
2924   mLocalPrefs.GetPref(WIDTH_KEY,              &mWindowInfo.position.w,        -1);
2925   mLocalPrefs.GetPref(HEIGHT_KEY,             &mWindowInfo.position.h,        450);
2926
2927   const window_position_t default_window_pos = { 0, 0, 200, 200, };
2928
2929   mLocalPrefs.GetPref(ENTITYWND_KEY,          &mWindowInfo.posEntityWnd,      default_window_pos);
2930   mLocalPrefs.GetPref(MAPINFOWND_KEY,         &mWindowInfo.posMapInfoWnd,     default_window_pos);
2931   mLocalPrefs.GetPref(CAMWND_KEY,             &mWindowInfo.posCamWnd,         default_window_pos);
2932   mLocalPrefs.GetPref(ZWND_KEY,               &mWindowInfo.posZWnd,           default_window_pos);
2933   mLocalPrefs.GetPref(XYWND_KEY,              &mWindowInfo.posXYWnd,          default_window_pos);
2934   mLocalPrefs.GetPref(YZWND_KEY,              &mWindowInfo.posYZWnd,          default_window_pos);
2935   mLocalPrefs.GetPref(XZWND_KEY,              &mWindowInfo.posXZWnd,          default_window_pos);
2936   mLocalPrefs.GetPref(PATCHWND_KEY,           &mWindowInfo.posPatchWnd,       default_window_pos);
2937   mLocalPrefs.GetPref(SURFACEWND_KEY,         &mWindowInfo.posSurfaceWnd,     default_window_pos);
2938   mLocalPrefs.GetPref(ENTITYINFOWND_KEY,      &mWindowInfo.posEntityInfoWnd,  default_window_pos);
2939
2940   mLocalPrefs.GetPref(ZWIDTH_KEY,             &mWindowInfo.nZWidth,           30);
2941   mLocalPrefs.GetPref(XYHEIGHT_KEY,           &mWindowInfo.nXYHeight,         300);
2942   mLocalPrefs.GetPref(XYWIDTH_KEY,            &mWindowInfo.nXYWidth,          300);
2943   mLocalPrefs.GetPref(CAMWIDTH_KEY,           &mWindowInfo.nCamWidth,         200);
2944   mLocalPrefs.GetPref(CAMHEIGHT_KEY,          &mWindowInfo.nCamHeight,        200);
2945   mLocalPrefs.GetPref(ZFLOATWIDTH_KEY,        &mWindowInfo.nZFloatWidth,      300);
2946 #ifdef _WIN32
2947   mLocalPrefs.GetPref(STATE_KEY,              &mWindowInfo.nState,            SW_SHOW);
2948 #endif
2949
2950   // menu stuff
2951   mLocalPrefs.GetPref(COUNT_KEY,              &m_nMRUCount,                   0);
2952   for(i = 0; i < 4; i++) 
2953   {
2954     char buf[64];
2955     sprintf (buf, "%s%d", FILE_KEY, i);
2956     mLocalPrefs.GetPref(buf,                  &m_strMRUFiles[i],              "");    
2957   }
2958
2959   // some platform specific prefs
2960 #ifdef _WIN32
2961   mLocalPrefs.GetPref(NATIVEGUI_KEY,          &m_bNativeGUI,                  TRUE);
2962   mLocalPrefs.GetPref(STARTONPRIMMON_KEY,     &m_bStartOnPrimMon,             FALSE);
2963 #endif
2964
2965   mLocalPrefs.GetPref(SI_TEXMENU_KEY,         &g_qeglobals.d_savedinfo.iTexMenu,                ID_VIEW_BILINEARMIPMAP);
2966   mLocalPrefs.GetPref(SI_GAMMA_KEY,           &g_qeglobals.d_savedinfo.fGamma,                  1.0f);
2967   mLocalPrefs.GetPref(SI_EXCLUDE_KEY,         &g_qeglobals.d_savedinfo.exclude,                 0); // nothing filtered by default
2968   mLocalPrefs.GetPref(SI_INCLUDE_KEY,         &g_qeglobals.d_savedinfo.include,                 INCLUDE_NAMES | INCLUDE_COORDS | INCLUDE_ANGLES | INCLUDE_CAMERATINT);
2969   mLocalPrefs.GetPref(SI_SHOWNAMES_KEY,       &g_qeglobals.d_savedinfo.show_names,              FALSE);
2970   mLocalPrefs.GetPref(SI_SHOWCOORDS_KEY,      &g_qeglobals.d_savedinfo.show_coordinates,        TRUE);
2971   mLocalPrefs.GetPref(SI_SHOWANGLES_KEY,      &g_qeglobals.d_savedinfo.show_angles,             TRUE);
2972   mLocalPrefs.GetPref(SI_SHOWOUTLINES_KEY,    &g_qeglobals.d_savedinfo.show_outline,            FALSE);
2973   mLocalPrefs.GetPref(SI_SHOWAXIS_KEY,        &g_qeglobals.d_savedinfo.show_axis,               TRUE);
2974   mLocalPrefs.GetPref(SI_NOSELOUTLINES_KEY,   &g_qeglobals.d_savedinfo.bNoSelectedOutlines,     FALSE);
2975
2976   mLocalPrefs.GetPref(SI_OUTLINESTYLE_KEY,   &g_qeglobals.d_savedinfo.iSelectedOutlinesStyle,  OUTLINE_ZBUF|OUTLINE_BSEL);
2977
2978   LoadTexdefPref(&g_qeglobals.d_savedinfo.m_SIIncrement, SI_SURFACE_TEXDEF_KEY);
2979   LoadTexdefPref(&g_qeglobals.d_savedinfo.m_PIIncrement, SI_PATCH_TEXDEF_KEY);
2980
2981   // text editor binding
2982 #ifdef _WIN32
2983   mLocalPrefs.GetPref(CUSTOMSHADEREDITOR_KEY, &m_bUseWin32Editor, TRUE);
2984 #else
2985   mLocalPrefs.GetPref(CUSTOMSHADEREDITOR_KEY, &m_bUseCustomEditor, FALSE);
2986   mLocalPrefs.GetPref(CUSTOMSHADEREDITORCOMMAND_KEY, &m_strEditorCommand, "");
2987 #endif
2988
2989
2990   vec3_t vDefaultAxisColours[3] = {
2991     {0.f, 0.5f, 0.f},
2992     {0.f, 0.f, 1.f},
2993     {1.f, 0.f, 0.f},
2994   };
2995
2996   for(i = 0; i < 3; i++) {
2997     char buf[64];
2998     sprintf(buf, "%s%d", SI_AXISCOLORS_KEY, i);
2999     mLocalPrefs.GetPref(buf,   g_qeglobals.d_savedinfo.AxisColors[i], vDefaultAxisColours[i]);
3000   }
3001
3002   vec3_t vDefaultColours[COLOR_LAST] = {
3003     {0.25f, 0.25f,  0.25f},
3004     {1.f,   1.f,    1.f},
3005     {0.75f, 0.75f,  0.75f},
3006     {0.5f,  0.5f,   0.5f},
3007     {0.25f, 0.25f,  0.25f},
3008     {0.0f,  0.0f,   0.0f},
3009     {0.f,   0.f,    1.f},
3010     {0.f,   0.f,    0.f},
3011     {0.f,   0.f,    0.f},
3012     {1.f,   0.f,    0.f},
3013     {0.f,   0.f,    1.f},
3014     {0.5f,  0.f,    0.75f},
3015     {1.0f,  0.f,    0.f},
3016     {0.f,   0.f,    0.f},
3017     {0.f,   0.f,    0.f},
3018   };
3019
3020   for(i = 0; i < COLOR_LAST; i++) {
3021     char buf[64];
3022     sprintf(buf, "%s%d", SI_COLORS_KEY, i);
3023     mLocalPrefs.GetPref(buf,   g_qeglobals.d_savedinfo.colors[i], vDefaultColours[i]);
3024   }
3025
3026   mLocalPrefs.GetPref(TEXTURECOMPRESSIONFORMAT_KEY, &m_nTextureCompressionFormat, 1);
3027
3028   mLocalPrefs.GetPref(LIGHTRADIUS_KEY, &m_nLightRadiuses, TRUE);
3029
3030   mLocalPrefs.GetPref(Q3MAP2TEX_KEY, &m_bQ3Map2Texturing, TRUE);
3031
3032 #ifdef ATIHACK_812
3033         mLocalPrefs.GetPref(ATIHACK_KEY, &m_bGlATIHack, FALSE);
3034 #endif
3035
3036   Undo_SetMaxSize(m_nUndoLevels); // set it internally as well / FIXME: why not just have one global value?
3037
3038   UpdateTextureCompression();
3039
3040 #ifdef ATIHACK_812
3041   UpdateATIHack();
3042 #endif
3043
3044   if (mLocalPrefs.mbEmpty)
3045   {
3046     mLocalPrefs.mbEmpty = false;
3047     Sys_Printf("Saving local.pref with default pref values\n");
3048     SavePrefs();
3049   }
3050 }
3051
3052 void PrefsDlg::SavePrefs ()
3053 {
3054   if (g_qeglobals.disable_ini)
3055     return;
3056
3057 #ifdef _DEBUG
3058   Sys_Printf("PrefsDlg::SavePrefs\n");
3059 #endif
3060
3061   // this will take care of copying back from the dialog to the variables
3062   // NOTE: it may be overkill to call systematically before a SavePrefs, but it's safer
3063   // this will also cause an UpdateData for the mGamesDialog
3064   UpdateData(TRUE);
3065
3066   mGamesDialog.SavePrefs();
3067
3068   // update the tree and save it
3069   mLocalPrefs.UpdatePrefTree();
3070   if (!mLocalPrefs.WriteXMLFile(m_inipath->str))
3071     Sys_FPrintf(SYS_ERR, "Error occured while saving local prefs file '%s'\n", m_inipath->str);
3072
3073   if ( m_nMouse == 0 ) {
3074           m_nMouseButtons = 2;
3075   } else {
3076           m_nMouseButtons = 3;
3077   }
3078
3079 }
3080
3081 void PrefsDlg::PostModal (int code)
3082 {
3083   if (code == IDOK)
3084   {
3085     SavePrefs();
3086     // make sure the logfile is ok
3087     Sys_LogFile();
3088     #ifdef ATIHACK_812
3089       UpdateATIHack();
3090     #endif
3091     if (g_pParentWnd)
3092       g_pParentWnd->SetGridStatus();
3093     Sys_UpdateWindows(W_ALL);
3094     if (m_nUndoLevels != 0)
3095                 Undo_SetMaxSize(m_nUndoLevels);
3096   }
3097 }
3098
3099 void PrefsDlg::DoEditorSensitivity()
3100 {
3101   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_object_get_data (G_OBJECT(m_pWidget), "check_customeditor"))))
3102   {
3103     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "label_customeditor")), TRUE);
3104     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "entry_customeditor")), TRUE);
3105     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "button_customeditor")), TRUE);
3106   }
3107   else
3108   {
3109     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "label_customeditor")), FALSE);
3110     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "entry_customeditor")), FALSE);
3111     gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data (G_OBJECT(m_pWidget), "button_customeditor")), FALSE);
3112   }
3113 }
3114
3115 void PrefsDlg::DoSensitivity()
3116 {
3117 #if 0
3118   // first, look at the project file version ... will monitoring work?
3119   // project files now XML, guaranteed to be at least version 2
3120   if (0)//IntForKey( g_qeglobals.d_project_entity, "version" ) < 2)
3121   {
3122     if (m_bWarn)
3123     {
3124       Str Msg;
3125       Msg = "The current project file (";
3126       Msg += g_PrefsDlg.m_strLastProject;
3127       Msg += ") is not at least version 2.\nI need version 2 or above to setup BSP monitoring correctly.";
3128       gtk_MessageBox(m_pWidget, Msg.GetBuffer(), MB_OK );
3129       
3130       m_bWarn = false;
3131     }
3132
3133     // go ahead, disable everybuddy
3134     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_leakstop" )), FALSE );
3135     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_monitorbsp" )), FALSE );
3136     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" )), FALSE );
3137     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), FALSE );
3138   }
3139   else
3140   {
3141 #endif
3142 //    m_bWarn = true;
3143
3144     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_leakstop" )), TRUE );
3145     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_monitorbsp" )), TRUE );
3146     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" )), TRUE );
3147     gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), TRUE );
3148
3149     if ( ! gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT(m_pWidget), "check_monitorbsp" ) ) ) )
3150     {
3151       gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_leakstop" )), FALSE );
3152       gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" )), FALSE );
3153       gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), FALSE );
3154     } else if (! gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT(m_pWidget), "check_runengine" ) ) ) )
3155     {
3156       gtk_widget_set_sensitive( GTK_WIDGET(g_object_get_data( G_OBJECT(m_pWidget), "check_sleep" )), FALSE );
3157     }
3158 }
3159
3160 /*
3161 ============================================================
3162 CGameInstall
3163 ============================================================
3164 */
3165
3166 CGameInstall::CGameInstall() {
3167         memset( m_availGames, 0, sizeof( m_availGames ) );
3168 }
3169
3170 void CGameInstall::OnBtnBrowseEngine( GtkWidget *widget, gpointer data ) {
3171         Sys_Printf( "OnBtnBrowseEngine\n" );
3172
3173         CGameInstall* i = static_cast<CGameInstall*>( data );
3174         char *dir = dir_dialog( widget, "Select game directory", NULL );
3175
3176         i->UpdateData( TRUE );
3177
3178         if ( dir != NULL ) {
3179                 i->m_strEngine = dir;
3180                 i->UpdateData( FALSE );
3181                 free( dir );
3182         }
3183 }
3184
3185 void CGameInstall::OnGameSelectChanged( GtkWidget *widget, gpointer data ) {
3186         Sys_Printf( "OnGameSelectChanged\n" );
3187
3188         CGameInstall* i = static_cast<CGameInstall*>( data );
3189         i->UpdateData( TRUE );  
3190         i->m_strName = gtk_combo_box_get_active_text( GTK_COMBO_BOX( widget ) );
3191         i->UpdateData( FALSE );
3192 }
3193
3194 void CGameInstall::BuildDialog() {
3195         GtkWidget *dlg, *vbox1, *button, *text, *combo, *entry, *hbox;
3196         
3197         dlg = m_pWidget;
3198         gtk_window_set_title( GTK_WINDOW( dlg ), "Configure games" );
3199
3200         vbox1 = gtk_vbox_new( FALSE, 0 );
3201         gtk_widget_show( vbox1 );
3202         gtk_container_add( GTK_CONTAINER( dlg ), vbox1 );
3203
3204         text = gtk_label_new( "Select the game to configure" );
3205         gtk_widget_show( text );
3206         gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 );
3207
3208         combo = gtk_combo_box_new_text();
3209         gtk_widget_show( combo );
3210         gtk_box_pack_start( GTK_BOX( vbox1 ), combo, FALSE, FALSE, 0 );
3211
3212         //      GList *combo_list = NULL;
3213         int iGame = 0;
3214         while ( m_availGames[ iGame ] != GAME_NONE ) {
3215                 switch ( m_availGames[ iGame ] ) {
3216                 case GAME_Q2:
3217                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Quake II" );
3218                         break;
3219                 case GAME_Q3:
3220                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Quake III Arena and mods" );
3221                         break;
3222                 case GAME_URT:
3223                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Urban Terror (standalone)" );
3224                         break;
3225                 case GAME_UFOAI:
3226                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "UFO: Alien Invasion" );
3227                         break;
3228                 case GAME_Q2W:
3229                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Quake2World" );
3230                         break;
3231                 case GAME_WARSOW:
3232                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Warsow" );
3233                         break;
3234                 case GAME_NEXUIZ:
3235                         gtk_combo_box_append_text( GTK_COMBO_BOX( combo ), "Nexuiz" );
3236                         break;
3237                 }
3238                 iGame++;
3239         }
3240         AddDialogData( combo, &m_nComboSelect, DLG_COMBO_BOX_INT );
3241         gtk_signal_connect( GTK_OBJECT( combo ), "changed", G_CALLBACK( OnGameSelectChanged ), this );
3242         gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 );  // NOTE: will trigger signal
3243
3244         text = gtk_label_new( "Name:" );
3245         gtk_widget_show( text );
3246         gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 );
3247         
3248         entry = gtk_entry_new();
3249         gtk_widget_show( entry );
3250         gtk_box_pack_start( GTK_BOX( vbox1 ), entry, FALSE, FALSE, 0 );
3251         AddDialogData( entry, &m_strName, DLG_ENTRY_TEXT );
3252
3253         text = gtk_label_new( "Engine directory:" );
3254         gtk_widget_show( text );
3255         gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 );
3256
3257         hbox = gtk_hbox_new( FALSE, 0 );
3258         gtk_widget_show( hbox );
3259         gtk_box_pack_start( GTK_BOX( vbox1 ), hbox, FALSE, FALSE, 0 );
3260         
3261         entry = gtk_entry_new();
3262         gtk_widget_show( entry );
3263         gtk_box_pack_start( GTK_BOX( hbox ), entry, FALSE, FALSE, 0 );
3264         AddDialogData( entry, &m_strEngine, DLG_ENTRY_TEXT );
3265
3266         button = gtk_button_new_with_label ("...");
3267         gtk_widget_show( button );
3268         gtk_signal_connect( GTK_OBJECT( button ), "clicked", GTK_SIGNAL_FUNC( OnBtnBrowseEngine ), this );
3269         gtk_box_pack_start( GTK_BOX( hbox ), button, FALSE, FALSE, 0 );
3270
3271         // this gets done in the project stuff atm
3272 #if 0
3273         text = gtk_label_new( "Mod subdirectory:" );
3274         gtk_widget_show( text );
3275         gtk_box_pack_start( GTK_BOX( vbox1 ), text, FALSE, FALSE, 0 );
3276
3277         entry = gtk_entry_new();
3278         gtk_widget_show( entry );
3279         gtk_box_pack_start( GTK_BOX( vbox1 ), entry, FALSE, FALSE, 0 );
3280         AddDialogData( entry, &m_strMod, DLG_ENTRY_TEXT );
3281 #endif
3282
3283         button = gtk_button_new_with_label( "OK" );
3284         gtk_widget_show( button );
3285         gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 );
3286         AddModalButton( button, IDOK );
3287
3288         button = gtk_button_new_with_label( "Cancel" );
3289         gtk_widget_show( button );
3290         gtk_box_pack_start( GTK_BOX( vbox1 ), button, FALSE, FALSE, 0 );
3291         AddModalButton( button, IDCANCEL );
3292
3293         gtk_widget_set_usize( button, 60, -2 );
3294 }
3295
3296 void CGameInstall::Run() {
3297         ScanGames();
3298         if ( DoModal() == IDCANCEL ) {
3299                 Sys_Printf( "game dialog cancelled\n" );
3300                 return;
3301         }
3302         Sys_Printf( "combo: %d name: %s engine: %s mod: %s\n", m_nComboSelect, m_strName.GetBuffer(), m_strEngine.GetBuffer(), m_strMod.GetBuffer() );
3303
3304         // write out the game file
3305         Str gameFilePath = g_strAppPath.GetBuffer();
3306         gameFilePath += "games/";
3307         gameFilePath += m_strName.GetBuffer();
3308         gameFilePath += ".game";
3309         Sys_Printf( "game file: %s\n", gameFilePath.GetBuffer() );
3310
3311         FILE *fg = fopen( gameFilePath.GetBuffer(), "w" );
3312         if ( fg == NULL ) {
3313                 Error( "Failed to open %s for writing\n", gameFilePath.GetBuffer() );
3314         }
3315         fprintf( fg, "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>\n<game\n" );
3316         fprintf( fg, "  name=\"%s\"\n", m_strName.GetBuffer() );
3317         fprintf( fg, "  enginepath=\"%s\"\n", m_strEngine.GetBuffer() );
3318         switch ( m_availGames[ m_nComboSelect ] ) {
3319         case GAME_Q2: {
3320                 fprintf( fg, "  gametools=\"%sinstalls/Quake2Pack/game\"\n", g_strAppPath.GetBuffer() );
3321                 fprintf( fg, "  prefix=\".quake2\"\n" );
3322                 Str source = g_strAppPath.GetBuffer();
3323                 source += "installs/";
3324                 source += Q2_PACK;
3325                 source += "/install/";
3326                 Str dest = m_strEngine.GetBuffer();
3327                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3328                 fprintf( fg, "  basegame=\"baseq2\"\n" );
3329                 break;
3330         }
3331         case GAME_Q3: {
3332                 fprintf( fg, "  gametools=\"%sinstalls/Q3Pack/game\"\n", g_strAppPath.GetBuffer() );
3333                 fprintf( fg, "  prefix=\".q3a\"\n" );
3334                 Str source = g_strAppPath.GetBuffer();
3335                 source += "installs/";
3336                 source += Q3_PACK;
3337                 source += "/install/";
3338                 Str dest = m_strEngine.GetBuffer();
3339                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3340                 fprintf( fg, "  basegame=\"baseq3\"\n" );
3341                 break;
3342         }
3343         case GAME_URT: {
3344                 fprintf( fg, "  gametools=\"%sinstalls/UrTPack/game\"\n", g_strAppPath.GetBuffer() );
3345                 fprintf( fg, "  prefix=\".q3a\"\n" );
3346                 Str source = g_strAppPath.GetBuffer();
3347                 source += "installs/";
3348                 source += URT_PACK;
3349                 source += "/install/";
3350                 Str dest = m_strEngine.GetBuffer();
3351                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3352                 fprintf( fg, "  basegame=\"q3ut4\"\n" );
3353                 break;
3354         }
3355         case GAME_UFOAI: {
3356                 fprintf( fg, "  gametools=\"%sinstalls/UFOAIPack/game\"\n", g_strAppPath.GetBuffer() );
3357                 fprintf( fg, "  prefix=\".ufoai\"\n" );
3358                 Str source = g_strAppPath.GetBuffer();
3359                 source += "installs/";
3360                 source += UFOAI_PACK;
3361                 source += "/install/";
3362                 Str dest = m_strEngine.GetBuffer();
3363                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3364                 fprintf( fg, "  basegame=\"base\"\n" );
3365                 break;
3366         }
3367         case GAME_Q2W: {
3368                 fprintf( fg, "  gametools=\"%sinstalls/Q2WPack/game\"\n", g_strAppPath.GetBuffer() );
3369                 fprintf( fg, "  prefix=\".quake2world\"\n" );
3370                 Str source = g_strAppPath.GetBuffer();
3371                 source += "installs/";
3372                 source += Q2W_PACK;
3373                 source += "/install/";
3374                 Str dest = m_strEngine.GetBuffer();
3375                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3376                 fprintf( fg, "  basegame=\"default\"\n" );
3377                 break;
3378         }
3379         case GAME_WARSOW: {
3380                 fprintf( fg, "  gametools=\"%sinstalls/WarsowPack/game\"\n", g_strAppPath.GetBuffer() );
3381                 fprintf( fg, "  prefix=\".warsow\"\n" );
3382                 Str source = g_strAppPath.GetBuffer();
3383                 source += "installs/";
3384                 source += WARSOW_PACK;
3385                 source += "/install/";
3386                 Str dest = m_strEngine.GetBuffer();
3387                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3388                 fprintf( fg, "  basegame=\"basewsw\"\n" );
3389                 break;
3390         }
3391         case GAME_NEXUIZ: {
3392                 fprintf( fg, "  gametools=\"%sinstalls/NexuizPack/game\"\n", g_strAppPath.GetBuffer() );
3393                 fprintf( fg, "  prefix=\".nexuiz\"\n" );
3394                 Str source = g_strAppPath.GetBuffer();
3395                 source += "installs/";
3396                 source += NEXUIZ_PACK;
3397                 source += "/install/";
3398                 Str dest = m_strEngine.GetBuffer();
3399                 CopyTree( source.GetBuffer(), dest.GetBuffer() );
3400                 fprintf( fg, "  basegame=\"data\"\n" );
3401                 break;
3402         }
3403         }
3404         fprintf( fg, "/>\n" );
3405         fclose( fg );
3406 }
3407
3408 /*
3409 ===============
3410 CGameInstall::ScanGames
3411 scan for active games that can be installed, based on the presence 
3412 ===============
3413 */
3414 void CGameInstall::ScanGames() {
3415         Str                             pakPaths = g_strAppPath.GetBuffer();
3416         int                             iGame = 0;
3417         const char              *dirname;
3418
3419         pakPaths +=     "installs/";
3420         FindFiles fileScan( pakPaths.GetBuffer() );
3421         while ( ( dirname = fileScan.NextFile() ) != NULL ) {
3422                 if ( stricmp( dirname, Q3_PACK ) == 0 ) {
3423                         m_availGames[ iGame++ ] = GAME_Q3;
3424                 }
3425                 if ( stricmp( dirname, URT_PACK ) == 0 ) {
3426                         m_availGames[ iGame++ ] = GAME_URT;
3427                 }
3428                 if ( stricmp( dirname, UFOAI_PACK ) == 0 ) {
3429                         m_availGames[ iGame++ ] = GAME_UFOAI;
3430                 }
3431                 if ( stricmp( dirname, Q2W_PACK ) == 0 ) {
3432                         m_availGames[ iGame++ ] = GAME_Q2W;
3433                 }
3434                 if ( stricmp( dirname, WARSOW_PACK ) == 0 ) {
3435                         m_availGames[ iGame++ ] = GAME_WARSOW;
3436                 }
3437                 if ( stricmp( dirname, NEXUIZ_PACK ) == 0 ) {
3438                         m_availGames[ iGame++ ] = GAME_NEXUIZ;
3439                 }
3440                 if ( stricmp( dirname, Q2_PACK ) == 0 ) {
3441                         m_availGames[ iGame++ ] = GAME_Q2;
3442                 }
3443         }
3444 }
3445