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