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