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