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