]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/gtkdlgs.cpp
misc fixes
[xonotic/netradiant.git] / radiant / gtkdlgs.cpp
1 /*
2 Copyright (c) 2001, Loki software, inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, 
6 are permitted provided that the following conditions are met:
7
8 Redistributions of source code must retain the above copyright notice, this list 
9 of conditions and the following disclaimer.
10
11 Redistributions in binary form must reproduce the above copyright notice, this
12 list of conditions and the following disclaimer in the documentation and/or
13 other materials provided with the distribution.
14
15 Neither the name of Loki software nor the names of its contributors may be used 
16 to endorse or promote products derived from this software without specific prior 
17 written permission. 
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
22 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
23 DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
29 */
30
31 //
32 // Some small dialogs that don't need much
33 //
34 // Leonardo Zide (leo@lokigames.com)
35 //
36
37 #include "stdafx.h"
38 #include <gdk/gdkkeysyms.h>
39 #include <gtk/gtk.h>
40
41 #ifdef _WIN32
42 #include <gdk/gdkwin32.h>
43 #endif
44
45 #ifdef _WIN32
46 #include <shellapi.h>
47 #endif
48
49 // =============================================================================
50 // Color selection dialog
51
52 qboolean DoColor (int iIndex)
53 {
54   static bool bColorOpen = false;
55    
56   if(bColorOpen)
57   {
58     Sys_FPrintf(SYS_WRN, "DoColor dialog is already open\n");
59     return false;
60   }
61
62   bColorOpen = true;  
63    
64   if (color_dialog (g_pParentWnd->m_pWidget, g_qeglobals.d_savedinfo.colors[iIndex]))
65   {
66     /* 
67     ** scale colors so that at least one component is at 1.0F 
68     ** if this is meant to select an entity color
69     */
70     if (iIndex == COLOR_ENTITY)
71     {
72       float largest = 0.0F;
73
74       if ( g_qeglobals.d_savedinfo.colors[iIndex][0] > largest )
75         largest = g_qeglobals.d_savedinfo.colors[iIndex][0];
76       if ( g_qeglobals.d_savedinfo.colors[iIndex][1] > largest )
77         largest = g_qeglobals.d_savedinfo.colors[iIndex][1];
78       if ( g_qeglobals.d_savedinfo.colors[iIndex][2] > largest )
79         largest = g_qeglobals.d_savedinfo.colors[iIndex][2];
80
81       if ( largest == 0.0F )
82       {
83         g_qeglobals.d_savedinfo.colors[iIndex][0] = 1.0F;
84         g_qeglobals.d_savedinfo.colors[iIndex][1] = 1.0F;
85         g_qeglobals.d_savedinfo.colors[iIndex][2] = 1.0F;
86       }
87       else
88       {
89         float scaler = 1.0F / largest;
90
91         g_qeglobals.d_savedinfo.colors[iIndex][0] *= scaler;
92         g_qeglobals.d_savedinfo.colors[iIndex][1] *= scaler;
93         g_qeglobals.d_savedinfo.colors[iIndex][2] *= scaler;
94       }
95     }
96
97     Sys_UpdateWindows (W_ALL);
98     bColorOpen = false;
99     return true;
100   }
101   else {
102     bColorOpen = false;
103     return false;
104   }
105 }
106
107 // =============================================================================
108 // Project settings dialog
109
110 static void UpdateBSPCommandList (GtkWidget *dialog);
111
112 static void DoProjectAddEdit (bool edit, GtkWidget *parent)
113 {
114   GtkWidget *dlg, *vbox, *hbox, *label, *table, *button;
115   GtkWidget *cmd, *text;
116   int loop = 1, ret = IDCANCEL;
117
118   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
119   if (edit)
120     gtk_window_set_title (GTK_WINDOW (dlg), "Edit Command");
121   else
122     gtk_window_set_title (GTK_WINDOW (dlg), "Add Command");
123   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
124                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
125   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
126                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
127   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
128   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
129
130   vbox = gtk_vbox_new (FALSE, 5);
131   gtk_widget_show (vbox);
132   gtk_container_add (GTK_CONTAINER (dlg), vbox);
133   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
134
135   table = gtk_table_new (2, 2, FALSE);
136   gtk_widget_show (table);
137   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
138   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
139   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
140
141   label = gtk_label_new ("Menu text");
142   gtk_widget_show (label);
143   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
144                     (GtkAttachOptions) (GTK_FILL),
145                     (GtkAttachOptions) (0), 0, 0);
146   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
147
148   label = gtk_label_new ("Command");
149   gtk_widget_show (label);
150   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
151                     (GtkAttachOptions) (GTK_FILL),
152                     (GtkAttachOptions) (0), 0, 0);
153   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
154
155   text = gtk_entry_new ();
156   g_object_set_data (G_OBJECT (dlg), "text", text);
157   gtk_widget_show (text);
158   gtk_table_attach (GTK_TABLE (table), text, 1, 2, 0, 1,
159                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
160                     (GtkAttachOptions) (0), 0, 0);
161   gtk_widget_set_usize (text, 300, -2);
162
163   cmd = gtk_entry_new ();
164   g_object_set_data (G_OBJECT (dlg), "cmd", cmd);
165   gtk_widget_show (cmd);
166   gtk_table_attach (GTK_TABLE (table), cmd, 1, 2, 1, 2,
167                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
168                     (GtkAttachOptions) (0), 0, 0);
169   gtk_widget_set_usize (cmd, 300, -2);
170
171   hbox = gtk_hbox_new (FALSE, 5);
172   gtk_widget_show (hbox);
173   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
174
175   button = gtk_button_new_with_label ("OK");
176   gtk_widget_show (button);
177   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
178   gtk_signal_connect (GTK_OBJECT (button), "clicked",
179                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
180   gtk_widget_set_usize (button, 60, -2);
181
182   button = gtk_button_new_with_label ("Cancel");
183   gtk_widget_show (button);
184   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
185   gtk_signal_connect (GTK_OBJECT (button), "clicked",
186                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
187   gtk_widget_set_usize (button, 60, -2);
188
189   if (edit)
190   {
191     GtkTreeView* view = GTK_TREE_VIEW (g_object_get_data (G_OBJECT(parent), "view"));
192     GtkTreeSelection* selection = gtk_tree_view_get_selection(view);
193     GtkTreeIter iter;
194     GtkTreeModel* model;
195     if(gtk_tree_selection_get_selected(selection, &model, &iter))
196     {
197       char* key;
198       gtk_tree_model_get(model, &iter, 0, &key, -1);
199       const char* value = ValueForKey (g_qeglobals.d_project_entity, key);
200       gtk_entry_set_text (GTK_ENTRY (text), key);
201       gtk_entry_set_text (GTK_ENTRY (cmd), value);
202       g_free(key);
203     }
204   }
205
206   gtk_grab_add (dlg);
207   gtk_widget_show (dlg);
208
209   while (loop)
210     gtk_main_iteration ();
211
212   if (ret == IDOK)
213   {
214     const char* key = gtk_entry_get_text (GTK_ENTRY (text));
215     const char* value = gtk_entry_get_text (GTK_ENTRY (cmd));
216
217     if (strlen (key) <= 0 || strlen (value) <= 0)
218     {
219       Sys_Printf ("Command not added\n");
220     }
221     else
222     {
223       if (edit)
224       {
225         SetKeyValue (g_qeglobals.d_project_entity, key, value);
226         FillBSPMenu ();
227       }
228       else
229       {
230               if (key[0] == 'b' && key[1] == 's' && key[2] == 'p')
231               {
232                 SetKeyValue (g_qeglobals.d_project_entity, key, value);
233                 FillBSPMenu ();
234               }
235               else
236                 Sys_Printf ("BSP commands must be preceded by \"bsp\"");
237       }
238
239       UpdateBSPCommandList (parent);
240     }
241   }
242
243   gtk_grab_remove (dlg);
244   gtk_widget_destroy (dlg);
245 }
246
247 static void UpdateBSPCommandList (GtkWidget *dialog)
248 {
249   GtkListStore* store = GTK_LIST_STORE (g_object_get_data (G_OBJECT(dialog), "bsp_commands"));
250
251   gtk_list_store_clear(store);
252
253   for(epair_t* ep = g_qeglobals.d_project_entity->epairs; ep != NULL; ep = ep->next)
254   {
255     if(ep->key[0] == 'b' && ep->key[1] == 's' && ep->key[2] == 'p')
256     {
257       GtkTreeIter iter;
258       gtk_list_store_append(store, &iter);
259       gtk_list_store_set(store, &iter, 0, ep->key, -1);
260     }
261   }
262 }
263
264 static void project_add (GtkWidget *widget, gpointer data)
265 {
266   GtkWidget *dlg = GTK_WIDGET (data);
267   DoProjectAddEdit (false, dlg);
268   UpdateBSPCommandList (dlg);
269 }
270
271 static void project_change (GtkWidget *widget, gpointer data)
272 {
273   GtkWidget *dlg = GTK_WIDGET (data);
274   DoProjectAddEdit (true, dlg);
275   UpdateBSPCommandList (dlg);
276 }
277
278 static void project_remove (GtkWidget *widget, gpointer data)
279 {
280   GtkWidget* project = GTK_WIDGET(data);
281
282   GtkTreeView* view = GTK_TREE_VIEW (g_object_get_data (G_OBJECT(project), "view"));
283   GtkTreeSelection* selection = gtk_tree_view_get_selection(view);
284   GtkTreeIter iter;
285   GtkTreeModel* model;
286   if(gtk_tree_selection_get_selected(selection, &model, &iter))
287   {
288     char* key;
289     gtk_tree_model_get(model, &iter, 0, &key, -1);
290     DeleteKey (g_qeglobals.d_project_entity, key);
291     g_free(key);
292
293     char* index = gtk_tree_model_get_string_from_iter(model, &iter);
294     Sys_Printf ("Selected %s\n", index);
295     g_free(index);
296
297     UpdateBSPCommandList(project);
298     FillBSPMenu();
299   }
300 }
301
302 static const char* sQ3ComboItem = "Quake III Arena";
303 static const char* sTAComboItem = "Quake III: Team Arena";
304 static const char* sModComboItem = "Custom Quake III modification";
305 static const char* sWolfComboItem = "Return To Castle Wolfenstein";
306 static const char* sWolfModComboItem = "Custom RTCW modification";
307 static const char* sHLComboItem = "Half-life";
308 static const char* sHLModComboItem = "Custom Half-life modification";
309
310 static const char* sWolfSPCombo = "Single Player mapping mode";
311 static const char* sWolfMPCombo = "Multiplayer mapping mode";
312
313 // Arnout
314 // HARD-CODED ET HACK
315 static const char* sETComboItem = "Wolfenstein: Enemy Territory";
316 static const char* sETModComboItem = "Custom ET modification";
317
318 // RIANT
319 // HARD-CODED JK2 HACK
320 static const char* sJK2ComboItem = "Jedi Knight II Outcast";
321 static const char* sJK2ModComboItem = "Custom JK2 modification";
322 static const char* sJK2SPCombo = "Single Player mapping mode";
323 static const char* sJK2MPCombo = "Multiplayer mapping mode";
324
325 // TTimo
326 // HARD-CODED JA HACK
327 static const char* sJAComboItem = "Jedi Knight Jedi Academy";
328 static const char* sJAModComboItem = "Custom JA modification";
329 static const char* sJASPCombo = "Single Player mapping mode";
330 static const char* sJAMPCombo = "Multiplayer mapping mode";
331
332 // RIANT
333 // HARD-CODED STVEF2 HACK
334 static const char* sSTVEFComboItem = "Star Trek Voyager : Elite Force";
335 static const char* sSTVEFModComboItem = "Custom Elite Force modification";
336 static const char* sSTVEFSPCombo = "Single Player mapping mode";
337 static const char* sSTVEFMPCombo = "Holo Match mapping mode";
338
339 // RIANT
340 // HARD-CODED SOF2 HACK
341 static const char* sSOF2ComboItem = "Soldier of Fortune II - Double Helix";
342 static const char* sSOF2ModComboItem = "Custom Sof2 modification";
343 static const char* sSOF2SPCombo = "Single Player mapping mode";
344 static const char* sSOF2MPCombo = "Multiplayer mapping mode";
345
346 static GtkWidget* game_select; // GTK_COMBO
347 static GtkEntry* fsgame_entry;
348
349 gint OnSelchangeComboWhatgame (GtkWidget *widget, GdkEvent* event, gpointer data)
350 {
351   const char *dir = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(game_select)->entry));
352   // HACK: Wolf
353   if (g_pGameDescription->mGameFile == "wolf.game")
354   {
355     if (!strcmp(dir,sWolfComboItem))
356     {
357       // disable the fs_game text entry
358       gtk_entry_set_text (fsgame_entry, "");
359       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), false);
360     }
361     else
362     {
363       gtk_entry_set_text (fsgame_entry, "");
364       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), true);
365     }
366
367   }
368   // HACK: ET
369   else if (g_pGameDescription->mGameFile == "et.game")
370   {
371     if (!strcmp(dir,sETComboItem))
372     {
373       // disable the fs_game text entry
374       gtk_entry_set_text (fsgame_entry, "");
375       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), false);
376     }
377     else
378     {
379       gtk_entry_set_text (fsgame_entry, "");
380       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), true);
381     }
382
383   }
384   else if (g_pGameDescription->mGameFile == "hl.game")
385   {
386     if (!strcmp(dir,sHLComboItem))
387     {
388       // disable the fs_game text entry
389       gtk_entry_set_text (fsgame_entry, "");
390       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), false);
391     }
392     else
393     {
394       gtk_entry_set_text (fsgame_entry, "");
395       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), true);
396     }
397
398   }
399   // RIANT
400   // HACK: JK2
401   else if (g_pGameDescription->mGameFile == "jk2.game")
402   {
403     if (!strcmp(dir,sJK2ComboItem))
404     {
405       // disable the fs_game text entry
406       gtk_entry_set_text (fsgame_entry, "");
407       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), false);
408     }
409     else
410     {
411       gtk_entry_set_text (fsgame_entry, "");
412       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), true);
413     }
414   }
415   // TTimo
416   // HACK: JA
417   else if (g_pGameDescription->mGameFile == "ja.game")
418   {
419     if (!strcmp(dir,sJAComboItem))
420     {
421       // disable the fs_game text entry
422       gtk_entry_set_text (fsgame_entry, "");
423       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), false);
424     }
425     else
426     {
427       gtk_entry_set_text (fsgame_entry, "");
428       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), true);
429     }
430   }
431   // RIANT
432   // HACK: STVEF
433   else if (g_pGameDescription->mGameFile == "stvef.game")
434   {
435     if (!strcmp(dir,sSTVEFComboItem))
436     {
437       // disable the fs_game text entry
438       gtk_entry_set_text (fsgame_entry, "");
439       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), false);
440     }
441     else
442     {
443       gtk_entry_set_text (fsgame_entry, "");
444       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), true);
445     }
446   }
447   // RIANT
448   // HACK: SOF2
449   else if (g_pGameDescription->mGameFile == "sof2.game")
450   {
451     if (!strcmp(dir,sSOF2ComboItem))
452     {
453       // disable the fs_game text entry
454       gtk_entry_set_text (fsgame_entry, "");
455       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), false);
456     }
457     else
458     {
459       gtk_entry_set_text (fsgame_entry, "");
460       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), true);
461     }
462   }
463   // QUAKE 3
464   else
465   {
466     if (!strcmp(dir,sQ3ComboItem))
467     {
468       // disable the fs_game text entry
469       gtk_entry_set_text (fsgame_entry, "");
470       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), false);
471     }
472     else if (!strcmp(dir,sTAComboItem))
473     {
474       gtk_entry_set_text (fsgame_entry, "missionpack");
475       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), false);
476     }
477     else
478     {
479       gtk_entry_set_text (fsgame_entry, "");
480       gtk_widget_set_sensitive(GTK_WIDGET(fsgame_entry), true);
481     }
482   }
483
484   return TRUE;
485 }
486
487 void DoProjectSettings ()
488 {
489   GtkWidget *project;
490   GtkWidget *frame, *label, *vbox, *table1, *table2, *button;
491   GtkWidget *brush;
492   GtkWidget *scr;
493   GtkWidget *base, *game;
494   GtkWidget *gamemode_combo;
495   GList *combo_list = (GList*)NULL;
496
497   int loop = 1, ret = IDCANCEL;
498
499   project = gtk_window_new (GTK_WINDOW_TOPLEVEL);
500   gtk_window_set_title (GTK_WINDOW (project), "Project Settings");
501   gtk_signal_connect (GTK_OBJECT (project), "delete_event",
502                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
503   gtk_signal_connect (GTK_OBJECT (project), "destroy",
504                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
505   g_object_set_data (G_OBJECT (project), "loop", &loop);
506   g_object_set_data (G_OBJECT (project), "ret", &ret);
507   gtk_window_set_default_size (GTK_WINDOW (project), 550, 400);
508
509   table1 = gtk_table_new (3, 2, FALSE);
510   gtk_widget_show (table1);
511   gtk_container_add (GTK_CONTAINER (project), table1);
512   gtk_container_set_border_width (GTK_CONTAINER (table1), 5);
513   gtk_table_set_row_spacings (GTK_TABLE (table1), 5);
514   gtk_table_set_col_spacings (GTK_TABLE (table1), 5);
515
516   vbox = gtk_vbox_new (FALSE, 5);
517   gtk_widget_show (vbox);
518   gtk_table_attach (GTK_TABLE (table1), vbox, 1, 2, 0, 1,
519                     (GtkAttachOptions) (GTK_FILL),
520                     (GtkAttachOptions) (GTK_FILL), 0, 0);
521
522   button = gtk_button_new_with_label ("OK");
523   gtk_widget_show (button);
524   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
525   gtk_signal_connect (GTK_OBJECT (button), "clicked",
526                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
527   gtk_widget_set_usize (button, 60, -2);
528
529   button = gtk_button_new_with_label ("Cancel");
530   gtk_widget_show (button);
531   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
532   gtk_signal_connect (GTK_OBJECT (button), "clicked",
533                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
534   gtk_widget_set_usize (button, 60, -2);
535
536   vbox = gtk_vbox_new (FALSE, 5);
537   gtk_widget_show (vbox);
538   gtk_table_attach (GTK_TABLE (table1), vbox, 1, 2, 1, 2,
539                     (GtkAttachOptions) (GTK_FILL),
540                     (GtkAttachOptions) (GTK_FILL), 0, 0);
541
542   button = gtk_button_new_with_label ("Add...");
543   gtk_widget_show (button);
544   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
545   gtk_signal_connect (GTK_OBJECT (button), "clicked",
546                       GTK_SIGNAL_FUNC (project_add), project);
547   gtk_widget_set_usize (button, 60, -2);
548
549   button = gtk_button_new_with_label ("Change...");
550   gtk_widget_show (button);
551   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
552   gtk_signal_connect (GTK_OBJECT (button), "clicked",
553                       GTK_SIGNAL_FUNC (project_change), project);
554   gtk_widget_set_usize (button, 60, -2);
555
556   button = gtk_button_new_with_label ("Remove");
557   gtk_widget_show (button);
558   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
559   gtk_signal_connect (GTK_OBJECT (button), "clicked",
560                       GTK_SIGNAL_FUNC (project_remove), project);
561   gtk_widget_set_usize (button, 60, -2);
562
563   frame = gtk_frame_new ("Misc settings");
564   gtk_widget_show (frame);
565   gtk_table_attach (GTK_TABLE (table1), frame, 0, 1, 2, 3,
566                     (GtkAttachOptions) (GTK_FILL),
567                     (GtkAttachOptions) (GTK_FILL), 0, 0);
568
569   brush = gtk_check_button_new_with_label ("Use brush primitives in MAP files (NOTE: experimental feature,\n"
570                                            "required by the texture tools plugin)");
571   gtk_widget_show (brush);
572   gtk_container_add (GTK_CONTAINER (frame), brush);
573   gtk_container_set_border_width (GTK_CONTAINER (brush), 5);
574
575   frame = gtk_frame_new ("Menu commands");
576   gtk_widget_show (frame);
577   gtk_table_attach (GTK_TABLE (table1), frame, 0, 1, 1, 2,
578                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
579                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
580
581   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
582   gtk_widget_show (scr);
583   gtk_container_add (GTK_CONTAINER (frame), scr);
584   gtk_container_set_border_width (GTK_CONTAINER (scr), 5);
585   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
586   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
587
588
589   {
590     GtkListStore* store = gtk_list_store_new(1, G_TYPE_STRING);
591
592     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
593     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
594
595     GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
596     GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);
597     gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
598
599     GtkTreeSelection* selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
600     gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
601
602     gtk_widget_show(view);
603
604     g_object_set_data(G_OBJECT (project), "view", view);
605     g_object_set_data(G_OBJECT (project), "bsp_commands", store);
606     gtk_container_add(GTK_CONTAINER (scr), view);
607     
608     g_object_unref(G_OBJECT(store));
609   }
610
611   frame = gtk_frame_new ("Project settings");
612   gtk_widget_show (frame);
613   gtk_table_attach (GTK_TABLE (table1), frame, 0, 1, 0, 1,
614                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
615                     (GtkAttachOptions) (GTK_FILL), 0, 0);
616
617   // HACK: hardcoded game stuff
618   if (g_pGameDescription->mGameFile == "wolf.game" ||
619     g_pGameDescription->mGameFile == "et.game" ||
620     g_pGameDescription->mGameFile == "jk2.game" || 
621     g_pGameDescription->mGameFile == "stvef.game" ||
622     g_pGameDescription->mGameFile == "sof2.game" ||
623     g_pGameDescription->mGameFile == "ja.game" )
624   {
625     table2 = gtk_table_new (9, 2, FALSE);
626   }
627   else
628   {
629     table2 = gtk_table_new (8, 2, FALSE);
630   }
631   gtk_widget_show (table2);
632   gtk_container_add (GTK_CONTAINER (frame), table2);
633   gtk_container_set_border_width (GTK_CONTAINER (table2), 5);
634   gtk_table_set_row_spacings (GTK_TABLE (table2), 5);
635   gtk_table_set_col_spacings (GTK_TABLE (table2), 5);
636
637   /*
638   fill in the game selection combo
639   HACK: hardcoded Q3/Wolf/HL switch
640   \todo that stuff would be faster to write with implementation of property bags and associated code to edit
641   */
642   if (g_pGameDescription->mGameFile == "wolf.game")
643   {
644     combo_list = g_list_append (combo_list, (void *)sWolfComboItem);
645     combo_list = g_list_append (combo_list, (void *)sWolfModComboItem);
646   }
647   else if (g_pGameDescription->mGameFile == "et.game")
648   {
649     combo_list = g_list_append (combo_list, (void *)sETComboItem);
650     combo_list = g_list_append (combo_list, (void *)sETModComboItem);
651   }
652   else if (g_pGameDescription->mGameFile == "hl.game")
653   {
654     combo_list = g_list_append (combo_list, (void *)sHLComboItem);
655     combo_list = g_list_append (combo_list, (void *)sHLModComboItem);
656   }
657   // RIANT
658   // JK2 HACK
659   else if (g_pGameDescription->mGameFile == "jk2.game")
660   {
661     combo_list = g_list_append (combo_list, (void *)sJK2ComboItem);
662     combo_list = g_list_append (combo_list, (void *)sJK2ModComboItem);
663   }
664   // TTimo
665   // JA HACK
666   else if (g_pGameDescription->mGameFile == "ja.game")
667   {
668     combo_list = g_list_append (combo_list, (void *)sJAComboItem);
669     combo_list = g_list_append (combo_list, (void *)sJAModComboItem);
670   }
671   // RIANT
672   // STVEF HACK
673   else if (g_pGameDescription->mGameFile == "stvef.game")
674   {
675     combo_list = g_list_append (combo_list, (void *)sSTVEFComboItem);
676     combo_list = g_list_append (combo_list, (void *)sSTVEFModComboItem);
677   }
678   // RIANT
679   // SOF2 HACK A LA JK2 A LA WOLF
680   else if (g_pGameDescription->mGameFile == "sof2.game")
681   {
682     combo_list = g_list_append (combo_list, (void *)sSOF2ComboItem);
683     combo_list = g_list_append (combo_list, (void *)sSOF2ModComboItem);
684   }
685   else
686   {
687     // Q3 or default
688     combo_list = g_list_append (combo_list, (void *)sQ3ComboItem);
689     combo_list = g_list_append (combo_list, (void *)sTAComboItem);
690     combo_list = g_list_append (combo_list, (void *)sModComboItem);
691   }
692
693   game_select = gtk_combo_new ();
694   gtk_combo_set_popdown_strings (GTK_COMBO (game_select), combo_list);
695   gtk_widget_show (game_select);
696   gtk_table_attach (GTK_TABLE (table2), game_select, 1, 2, 6, 7,
697                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
698                     (GtkAttachOptions) (0), 0, 0);
699
700   gtk_signal_connect (GTK_OBJECT(GTK_COMBO (game_select)->entry), "changed",
701     GTK_SIGNAL_FUNC (OnSelchangeComboWhatgame), NULL);
702
703   g_list_free (combo_list);
704   gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (game_select)->entry), FALSE);
705
706   game = gtk_entry_new();
707   fsgame_entry = GTK_ENTRY(game);
708   gtk_widget_show(game);
709   gtk_table_attach(GTK_TABLE(table2), game, 1, 2, 7, 8,
710                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
711                     (GtkAttachOptions) (0), 0, 0);
712   
713   /*
714   wolf specific: select MP or SP mode
715   */
716   if (g_pGameDescription->mGameFile == "wolf.game")
717   {
718     combo_list = NULL;
719     combo_list = g_list_append (combo_list, (void *)sWolfSPCombo);
720     combo_list = g_list_append (combo_list, (void *)sWolfMPCombo);
721     
722     gamemode_combo = gtk_combo_new ();
723     gtk_combo_set_popdown_strings (GTK_COMBO (gamemode_combo), combo_list);
724     gtk_widget_show(gamemode_combo);
725     gtk_table_attach (GTK_TABLE (table2), gamemode_combo, 1, 2, 8, 9,
726       (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
727       (GtkAttachOptions) (0), 0, 0);
728
729     g_list_free (combo_list);
730     combo_list = NULL;
731
732     label = gtk_label_new ("Mapping mode");
733     gtk_widget_show (label);
734     gtk_table_attach (GTK_TABLE (table2), label, 0, 1, 8, 9,
735       (GtkAttachOptions) (GTK_FILL),
736       (GtkAttachOptions) (0), 0, 0);
737     gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
738   }
739
740   // RIANT
741   // JK2 HACK
742   if (g_pGameDescription->mGameFile == "jk2.game")
743   {
744     combo_list = NULL;
745     combo_list = g_list_append (combo_list, (void *)sJK2SPCombo);
746     combo_list = g_list_append (combo_list, (void *)sJK2MPCombo);
747     
748     gamemode_combo = gtk_combo_new ();
749     gtk_combo_set_popdown_strings (GTK_COMBO (gamemode_combo), combo_list);
750     gtk_widget_show(gamemode_combo);
751     gtk_table_attach (GTK_TABLE (table2), gamemode_combo, 1, 2, 8, 9,
752       (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
753       (GtkAttachOptions) (0), 0, 0);
754
755     g_list_free (combo_list);
756     combo_list = NULL;
757
758     label = gtk_label_new ("Mapping mode");
759     gtk_widget_show (label);
760     gtk_table_attach (GTK_TABLE (table2), label, 0, 1, 8, 9,
761       (GtkAttachOptions) (GTK_FILL),
762       (GtkAttachOptions) (0), 0, 0);
763     gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
764   }
765   // TTimo
766   // JA HACK
767   if (g_pGameDescription->mGameFile == "ja.game")
768   {
769     combo_list = NULL;
770     combo_list = g_list_append (combo_list, (void *)sJASPCombo);
771     combo_list = g_list_append (combo_list, (void *)sJAMPCombo);
772     
773     gamemode_combo = gtk_combo_new ();
774     gtk_combo_set_popdown_strings (GTK_COMBO (gamemode_combo), combo_list);
775     gtk_widget_show(gamemode_combo);
776     gtk_table_attach (GTK_TABLE (table2), gamemode_combo, 1, 2, 8, 9,
777       (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
778       (GtkAttachOptions) (0), 0, 0);
779
780     g_list_free (combo_list);
781     combo_list = NULL;
782
783     label = gtk_label_new ("Mapping mode");
784     gtk_widget_show (label);
785     gtk_table_attach (GTK_TABLE (table2), label, 0, 1, 8, 9,
786       (GtkAttachOptions) (GTK_FILL),
787       (GtkAttachOptions) (0), 0, 0);
788     gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
789   }
790   // RIANT
791   // STVEF HACK
792   if (g_pGameDescription->mGameFile == "stvef.game")
793   {
794     combo_list = NULL;
795     combo_list = g_list_append (combo_list, (void *)sSTVEFSPCombo);
796     combo_list = g_list_append (combo_list, (void *)sSTVEFMPCombo);
797     
798     gamemode_combo = gtk_combo_new ();
799     gtk_combo_set_popdown_strings (GTK_COMBO (gamemode_combo), combo_list);
800     gtk_widget_show(gamemode_combo);
801     gtk_table_attach (GTK_TABLE (table2), gamemode_combo, 1, 2, 8, 9,
802       (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
803       (GtkAttachOptions) (0), 0, 0);
804
805     g_list_free (combo_list);
806     combo_list = NULL;
807
808     label = gtk_label_new ("Mapping mode");
809     gtk_widget_show (label);
810     gtk_table_attach (GTK_TABLE (table2), label, 0, 1, 8, 9,
811       (GtkAttachOptions) (GTK_FILL),
812       (GtkAttachOptions) (0), 0, 0);
813     gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
814   }
815   // RIANT
816   // SOF2 HACK
817   if (g_pGameDescription->mGameFile == "sof2.game")
818   {
819     combo_list = NULL;
820     combo_list = g_list_append (combo_list, (void *)sSOF2SPCombo);
821     combo_list = g_list_append (combo_list, (void *)sSOF2MPCombo);
822     
823     gamemode_combo = gtk_combo_new ();
824     gtk_combo_set_popdown_strings (GTK_COMBO (gamemode_combo), combo_list);
825     gtk_widget_show(gamemode_combo);
826     gtk_table_attach (GTK_TABLE (table2), gamemode_combo, 1, 2, 8, 9,
827       (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
828       (GtkAttachOptions) (0), 0, 0);
829
830     g_list_free (combo_list);
831     combo_list = NULL;
832
833     label = gtk_label_new ("Mapping mode");
834     gtk_widget_show (label);
835     gtk_table_attach (GTK_TABLE (table2), label, 0, 1, 8, 9,
836       (GtkAttachOptions) (GTK_FILL),
837       (GtkAttachOptions) (0), 0, 0);
838     gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
839   }
840
841   /*
842   the usual stuff
843   */
844
845   base = gtk_entry_new ();
846   g_object_set_data (G_OBJECT (project), "base", base);
847   gtk_widget_show (base);
848   gtk_table_attach (GTK_TABLE (table2), base, 1, 2, 0, 1,
849                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
850                     (GtkAttachOptions) (0), 0, 0);
851
852
853   label = gtk_label_new ("basepath");
854   gtk_widget_show (label);
855   gtk_table_attach (GTK_TABLE (table2), label, 0, 1, 0, 1,
856                     (GtkAttachOptions) (GTK_FILL),
857                     (GtkAttachOptions) (0), 0, 0);
858   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
859
860
861   label = gtk_label_new ("Select mod");
862   gtk_widget_show (label);
863   gtk_table_attach (GTK_TABLE (table2), label, 0, 1, 6, 7,
864                     (GtkAttachOptions) (GTK_FILL),
865                     (GtkAttachOptions) (0), 0, 0);
866   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
867
868   label = gtk_label_new ("fs_game");
869   gtk_widget_show (label);
870   gtk_table_attach (GTK_TABLE (table2), label, 0, 1, 7, 8,
871                     (GtkAttachOptions) (GTK_FILL),
872                     (GtkAttachOptions) (0), 0, 0);
873   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
874
875   // Initialize fields
876   gtk_entry_set_text (GTK_ENTRY (base), ValueForKey (g_qeglobals.d_project_entity, "basepath"));
877   UpdateBSPCommandList (project);
878   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (brush), (g_qeglobals.m_bBrushPrimitMode) ? TRUE : FALSE);
879
880   // initialise the fs_game selection from the project settings into the dialog
881   const char *dir = ValueForKey (g_qeglobals.d_project_entity, "gamename");
882   // HACK: hardcoded wolf stuff
883   if (g_pGameDescription->mGameFile == "wolf.game")
884   {
885     if ((strlen(dir) == 0) || !stricmp(dir,"main"))
886     {
887       // no fs_game set, we are running stock Quake III Arena editing
888       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sWolfComboItem);
889       gtk_entry_set_text (GTK_ENTRY (game), "");
890       gtk_widget_set_sensitive(game, false);
891     }
892     else
893     {
894       // this is a custom mod
895       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sWolfModComboItem);
896       gtk_entry_set_text (GTK_ENTRY (game), dir);
897       gtk_widget_set_sensitive(game, true);
898     }
899   }
900   // HACK: hardcoded et stuff
901   if (g_pGameDescription->mGameFile == "et.game")
902   {
903     if ((strlen(dir) == 0) || !stricmp(dir,"etmain"))
904     {
905       // no fs_game set, we are running stock Quake III Arena editing
906       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sETComboItem);
907       gtk_entry_set_text (GTK_ENTRY (game), "");
908       gtk_widget_set_sensitive(game, false);
909     }
910     else
911     {
912       // this is a custom mod
913       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sETModComboItem);
914       gtk_entry_set_text (GTK_ENTRY (game), dir);
915       gtk_widget_set_sensitive(game, true);
916     }
917   }
918   // HACK: hardcoded half-life stuff
919   else if (g_pGameDescription->mGameFile == "hl.game")
920   {
921     if ((strlen(dir) == 0) || !stricmp(dir,"valve"))
922     {
923       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sHLComboItem);
924       gtk_entry_set_text (GTK_ENTRY (game), "");
925       gtk_widget_set_sensitive(game, false);
926     }
927     else
928     {
929       // this is a custom mod
930       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sHLModComboItem);
931       gtk_entry_set_text (GTK_ENTRY (game), dir);
932       gtk_widget_set_sensitive(game, true);
933     }
934   }
935   // RIANT
936   // JK2 HACK
937   else if (g_pGameDescription->mGameFile == "jk2.game")
938   {
939     if ((strlen(dir) == 0) || !stricmp(dir,"base"))
940     {
941       // no fs_game set, we are running stock Quake III Arena editing
942       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sJK2ComboItem);
943       gtk_entry_set_text (GTK_ENTRY (game), "");
944       gtk_widget_set_sensitive(game, false);
945     }
946     else
947     {
948       // this is a custom mod
949       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sJK2ModComboItem);
950       gtk_entry_set_text (GTK_ENTRY (game), dir);
951       gtk_widget_set_sensitive(game, true);
952     }
953   }
954   // TTimo
955   // JA HACK
956   else if (g_pGameDescription->mGameFile == "ja.game")
957   {
958     if ((strlen(dir) == 0) || !stricmp(dir,"base"))
959     {
960       // no fs_game set, we are running stock editing
961       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sJAComboItem);
962       gtk_entry_set_text (GTK_ENTRY (game), "");
963       gtk_widget_set_sensitive(game, false);
964     }
965     else
966     {
967       // this is a custom mod
968       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sJAModComboItem);
969       gtk_entry_set_text (GTK_ENTRY (game), dir);
970       gtk_widget_set_sensitive(game, true);
971     }
972   }
973   // RIANT
974   // STVEF2 HACK
975   else if (g_pGameDescription->mGameFile == "stvef.game")
976   {
977     if ((strlen(dir) == 0) || !stricmp(dir,"baseEf"))
978     {
979       // no fs_game set, we are running stock Quake III Arena editing
980       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sSTVEFComboItem);
981       gtk_entry_set_text (GTK_ENTRY (game), "");
982       gtk_widget_set_sensitive(game, false);
983     }
984     else
985     {
986       // this is a custom mod
987       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sSTVEFModComboItem);
988       gtk_entry_set_text (GTK_ENTRY (game), dir);
989       gtk_widget_set_sensitive(game, true);
990     }
991   }
992   // RIANT
993   // SOF2 HACK
994   else if (g_pGameDescription->mGameFile == "sof2.game")
995   {
996     if ((strlen(dir) == 0) || !stricmp(dir,"base"))
997     {
998       // no fs_game set, we are running stock Quake III Arena editing
999       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sSOF2ComboItem);
1000       gtk_entry_set_text (GTK_ENTRY (game), "");
1001       gtk_widget_set_sensitive(game, false);
1002     }
1003     else
1004     {
1005       // this is a custom mod
1006       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sSOF2ModComboItem);
1007       gtk_entry_set_text (GTK_ENTRY (game), dir);
1008       gtk_widget_set_sensitive(game, true);
1009     }
1010   }
1011   else
1012   {
1013     if ((strlen(dir) == 0) || !strcmp(dir,"baseq3"))
1014     {
1015       // no fs_game set, we are running stock Quake III Arena editing
1016       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sQ3ComboItem);
1017       gtk_entry_set_text (GTK_ENTRY (game), "");
1018       gtk_widget_set_sensitive(game, false);
1019     }
1020     else if (!strcmp(dir,"missionpack"))
1021     {
1022       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sTAComboItem);
1023       gtk_entry_set_text (GTK_ENTRY (game), "missionpack");
1024       gtk_widget_set_sensitive(game, false);
1025     }
1026     else
1027     {
1028       // this is a custom mod
1029       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (game_select)->entry), sModComboItem);
1030       gtk_entry_set_text (GTK_ENTRY (game), dir);
1031       gtk_widget_set_sensitive(game, true);
1032     }
1033   }
1034
1035   // HACK: hardcoded wolf stuff
1036   if (g_pGameDescription->mGameFile == "wolf.game")
1037   {
1038     const char *gamemode = ValueForKey (g_qeglobals.d_project_entity, "gamemode");
1039     if ((strlen(gamemode) == 0) || !strcmp(gamemode,"sp"))
1040     {
1041       // nothing set yet, or single player
1042       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (gamemode_combo)->entry), sWolfSPCombo);
1043     }
1044     else
1045     {
1046       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (gamemode_combo)->entry), sWolfMPCombo);
1047     }
1048   }
1049
1050   // JK2 HACK
1051   else if (g_pGameDescription->mGameFile == "jk2.game")
1052   {
1053     const char *gamemode = ValueForKey (g_qeglobals.d_project_entity, "gamemode");
1054     if ((strlen(gamemode) == 0) || !strcmp(gamemode,"sp"))
1055     {
1056       // nothing set yet, or single player
1057       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (gamemode_combo)->entry), sJK2SPCombo);
1058     }
1059     else
1060     {
1061       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (gamemode_combo)->entry), sJK2MPCombo);
1062     }
1063   }
1064   // JA HACK
1065   else if (g_pGameDescription->mGameFile == "ja.game")
1066   {
1067     const char *gamemode = ValueForKey (g_qeglobals.d_project_entity, "gamemode");
1068     if ((strlen(gamemode) == 0) || !strcmp(gamemode,"sp"))
1069     {
1070       // nothing set yet, or single player
1071       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (gamemode_combo)->entry), sJASPCombo);
1072     }
1073     else
1074     {
1075       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (gamemode_combo)->entry), sJAMPCombo);
1076     }
1077   }
1078   // STVEF HACK
1079   else if (g_pGameDescription->mGameFile == "stvef.game")
1080   {
1081     const char *gamemode = ValueForKey (g_qeglobals.d_project_entity, "gamemode");
1082     if ((strlen(gamemode) == 0) || !strcmp(gamemode,"sp"))
1083     {
1084       // nothing set yet, or single player
1085       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (gamemode_combo)->entry), sSTVEFSPCombo);
1086     }
1087     else
1088     {
1089       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (gamemode_combo)->entry), sSTVEFMPCombo);
1090     }
1091   }
1092   // SOF2 HACK
1093   else if (g_pGameDescription->mGameFile == "sof2.game")
1094   {
1095     const char *gamemode = ValueForKey (g_qeglobals.d_project_entity, "gamemode");
1096     if ((strlen(gamemode) == 0) || !strcmp(gamemode,"sp"))
1097     {
1098       // nothing set yet, or single player
1099       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (gamemode_combo)->entry), sSOF2SPCombo);
1100     }
1101     else
1102     {
1103       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (gamemode_combo)->entry), sSOF2MPCombo);
1104     }
1105   }
1106
1107   gtk_grab_add (project);
1108   gtk_widget_show (project);
1109
1110   g_pGameDescription->Dump();
1111
1112   while (loop)
1113     gtk_main_iteration ();
1114
1115   if (ret == IDOK)
1116   {
1117     char buf[1024];
1118     const char *r;
1119     char *w;
1120                 
1121     // convert path to unix format
1122     for(r = gtk_entry_get_text (GTK_ENTRY (base)), w=buf; *r != '\0'; r++, w++)
1123       *w = (*r == '\\') ? '/' : *r;
1124     // add last slash
1125     if(w != buf && *(w-1) != '/') *(w++) = '/';
1126     // terminate string
1127     *w = '\0';
1128     SetKeyValue (g_qeglobals.d_project_entity, "basepath", buf);
1129
1130     dir = gtk_entry_get_text (GTK_ENTRY (game));
1131     // Hack: hard coded wolf stuff
1132     if (g_pGameDescription->mGameFile == "wolf.game")
1133     {
1134       if (!strlen(dir) || !stricmp(dir,"main"))
1135       {
1136         DeleteKey (g_qeglobals.d_project_entity, "gamename");
1137       }
1138       else
1139       {
1140         SetKeyValue (g_qeglobals.d_project_entity, "gamename", dir);
1141       }
1142     }
1143     // Hack: hard coded ET stuff
1144     else if (g_pGameDescription->mGameFile == "et.game")
1145     {
1146       if (!strlen(dir) || !stricmp(dir,"etmain"))
1147       {
1148         DeleteKey (g_qeglobals.d_project_entity, "gamename");
1149       }
1150       else
1151       {
1152         SetKeyValue (g_qeglobals.d_project_entity, "gamename", dir);
1153       }
1154     }
1155     // Hack: hard coded Half-life stuff
1156     else if (g_pGameDescription->mGameFile == "hl.game")
1157     {
1158       if (!strlen(dir) || !stricmp(dir,"valve"))
1159       {
1160         DeleteKey (g_qeglobals.d_project_entity, "gamename");
1161       }
1162       else
1163       {
1164         SetKeyValue (g_qeglobals.d_project_entity, "gamename", dir);
1165       }
1166     }
1167     else if (g_pGameDescription->mGameFile == "jk2.game" || g_pGameDescription->mGameFile == "ja.game")
1168     {
1169       if (!strlen(dir) || !stricmp(dir,"base"))
1170       {
1171         DeleteKey (g_qeglobals.d_project_entity, "gamename");
1172       }
1173       else
1174       {
1175         SetKeyValue (g_qeglobals.d_project_entity, "gamename", dir);
1176       }
1177     }
1178     // RIANT
1179     // STVEF HACK
1180     else if (g_pGameDescription->mGameFile == "stvef.game")
1181     {
1182       if (!strlen(dir) || !stricmp(dir,"baseEf"))
1183       {
1184         DeleteKey (g_qeglobals.d_project_entity, "gamename");
1185       }
1186       else
1187       {
1188         SetKeyValue (g_qeglobals.d_project_entity, "gamename", dir);
1189       }
1190     }
1191     else
1192     {
1193       if (!strlen(dir) || !strcmp(dir,"baseq3"))
1194       {
1195         DeleteKey (g_qeglobals.d_project_entity, "gamename");
1196       }
1197       else
1198       {
1199         SetKeyValue (g_qeglobals.d_project_entity, "gamename", dir);
1200       }
1201     }
1202     
1203     // HACK: hardcoded wolf stuff
1204     if (g_pGameDescription->mGameFile == "wolf.game")
1205     {
1206       // read from gamemode_combo
1207       const char *gamemode = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(gamemode_combo)->entry));
1208       if (!strlen(gamemode) || !strcmp(gamemode, sWolfSPCombo))
1209       {
1210         SetKeyValue (g_qeglobals.d_project_entity, "gamemode", "sp");
1211       }
1212       else
1213       {
1214         SetKeyValue (g_qeglobals.d_project_entity, "gamemode", "mp");
1215       }
1216     }
1217
1218     // RIANT
1219     // JK2 HACK
1220     if (g_pGameDescription->mGameFile == "jk2.game")
1221     {
1222       // read from gamemode_combo
1223       const char *gamemode = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(gamemode_combo)->entry));
1224       if (!strlen(gamemode) || !strcmp(gamemode, sJK2SPCombo))
1225       {
1226         SetKeyValue (g_qeglobals.d_project_entity, "gamemode", "sp");
1227       }
1228       else
1229       {
1230         SetKeyValue (g_qeglobals.d_project_entity, "gamemode", "mp");
1231       }
1232     }
1233     // TTimo
1234     // JA HACK
1235     if (g_pGameDescription->mGameFile == "ja.game")
1236     {
1237       // read from gamemode_combo
1238       const char *gamemode = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(gamemode_combo)->entry));
1239       if (!strlen(gamemode) || !strcmp(gamemode, sJASPCombo))
1240       {
1241         SetKeyValue (g_qeglobals.d_project_entity, "gamemode", "sp");
1242       }
1243       else
1244       {
1245         SetKeyValue (g_qeglobals.d_project_entity, "gamemode", "mp");
1246       }
1247     }
1248     
1249     // RIANT
1250     // STVEF HACK
1251     if (g_pGameDescription->mGameFile == "stvef.game")
1252     {
1253       // read from gamemode_combo
1254       const char *gamemode = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(gamemode_combo)->entry));
1255       if (!strlen(gamemode) || !strcmp(gamemode, sSTVEFSPCombo))
1256       {
1257         SetKeyValue (g_qeglobals.d_project_entity, "gamemode", "sp");
1258       }
1259       else
1260       {
1261         SetKeyValue (g_qeglobals.d_project_entity, "gamemode", "mp");
1262       }
1263     }
1264
1265     g_qeglobals.m_strHomeMaps = g_qeglobals.m_strHomeGame;
1266     const char* str = ValueForKey(g_qeglobals.d_project_entity, "gamename");
1267     if(str[0] == '\0') str = g_pGameDescription->mBaseGame.GetBuffer();
1268     g_qeglobals.m_strHomeMaps += str;
1269     g_qeglobals.m_strHomeMaps += '/';
1270
1271     // RIANT
1272     // SOF2 HACK
1273     if (g_pGameDescription->mGameFile == "sof2.game")
1274     {
1275       // read from gamemode_combo
1276       const char *gamemode = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(gamemode_combo)->entry));
1277       if (!strlen(gamemode) || !strcmp(gamemode, sSOF2SPCombo))
1278       {
1279         SetKeyValue (g_qeglobals.d_project_entity, "gamemode", "sp");
1280       }
1281       else
1282       {
1283         SetKeyValue (g_qeglobals.d_project_entity, "gamemode", "mp");
1284       }
1285     }
1286
1287     if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (brush)))
1288       g_qeglobals.m_bBrushPrimitMode = TRUE;
1289     else
1290       g_qeglobals.m_bBrushPrimitMode = FALSE;
1291
1292     SetKeyValue(g_qeglobals.d_project_entity, "brush_primit", (g_qeglobals.m_bBrushPrimitMode ? "1" : "0" ));
1293
1294     QE_SaveProject( g_PrefsDlg.m_strLastProject.GetBuffer() );
1295   }
1296
1297   gtk_grab_remove (project);
1298   gtk_widget_destroy (project);
1299 }
1300
1301 // =============================================================================
1302 // MapInfo dialog
1303
1304 void DoMapInfo ()
1305 {
1306   static GtkWidget *dlg;
1307   GtkWidget *vbox, *vbox2, *hbox, *table, *button, *label, *scr;
1308   GtkWidget *brushes_entry, *entities_entry, *net_entry;
1309   int loop = 1, ret = IDCANCEL;
1310
1311   if (dlg != NULL)
1312     return;
1313
1314   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1315
1316   load_window_pos(dlg, g_PrefsDlg.mWindowInfo.posMapInfoWnd);
1317
1318   gtk_window_set_title (GTK_WINDOW (dlg), "Map Info");
1319   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
1320                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
1321   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
1322                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
1323   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
1324   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
1325
1326   vbox = gtk_vbox_new (FALSE, 5);
1327   gtk_widget_show (vbox);
1328   gtk_container_add (GTK_CONTAINER (dlg), vbox);
1329   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
1330
1331   hbox = gtk_hbox_new (FALSE, 5);
1332   gtk_widget_show (hbox);
1333   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
1334
1335   table = gtk_table_new (3, 2, FALSE);
1336   gtk_widget_show (table);
1337   gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
1338   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
1339   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
1340
1341   brushes_entry = gtk_entry_new ();
1342   gtk_widget_show (brushes_entry);
1343   gtk_table_attach (GTK_TABLE (table), brushes_entry, 1, 2, 0, 1,
1344                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1345                     (GtkAttachOptions) (0), 0, 0);
1346   gtk_entry_set_editable (GTK_ENTRY (brushes_entry), FALSE);
1347
1348   entities_entry = gtk_entry_new ();
1349   gtk_widget_show (entities_entry);
1350   gtk_table_attach (GTK_TABLE (table), entities_entry, 1, 2, 1, 2,
1351                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1352                     (GtkAttachOptions) (0), 0, 0);
1353   gtk_entry_set_editable (GTK_ENTRY (entities_entry), FALSE);
1354
1355   net_entry = gtk_entry_new ();
1356   gtk_widget_show (net_entry);
1357   gtk_table_attach (GTK_TABLE (table), net_entry, 1, 2, 2, 3,
1358                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1359                     (GtkAttachOptions) (0), 0, 0);
1360   gtk_entry_set_editable (GTK_ENTRY (net_entry), FALSE);
1361
1362   label = gtk_label_new ("Total Brushes");
1363   gtk_widget_show (label);
1364   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
1365                     (GtkAttachOptions) (GTK_FILL),
1366                     (GtkAttachOptions) (0), 0, 0);
1367   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1368
1369   label = gtk_label_new ("Total Entities");
1370   gtk_widget_show (label);
1371   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
1372                     (GtkAttachOptions) (GTK_FILL),
1373                     (GtkAttachOptions) (0), 0, 0);
1374   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1375
1376   label = gtk_label_new ("Net brush count\n(non entity)");
1377   gtk_widget_show (label);
1378   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
1379                     (GtkAttachOptions) (GTK_FILL),
1380                     (GtkAttachOptions) (0), 0, 0);
1381   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1382
1383   vbox2 = gtk_vbox_new (FALSE, 5);
1384   gtk_widget_show (vbox2);
1385   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
1386
1387   button = gtk_button_new_with_label ("Close");
1388   gtk_widget_show (button);
1389   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
1390   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1391                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
1392   gtk_widget_set_usize (button, 60, -2);
1393
1394   label = gtk_label_new ("Entity breakdown");
1395   gtk_widget_show (label);
1396   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
1397   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1398
1399   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
1400   gtk_widget_show (scr);
1401   gtk_box_pack_start (GTK_BOX (vbox), scr, TRUE, TRUE, 0);
1402   gtk_container_set_border_width (GTK_CONTAINER (scr), 5);
1403   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1404
1405   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scr), GTK_SHADOW_IN);
1406
1407   GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
1408
1409   {
1410     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1411     gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(view), TRUE);
1412
1413     {
1414       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1415       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Entity", renderer, "text", 0, NULL);
1416       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1417       gtk_tree_view_column_set_sort_column_id(column, 0);
1418     }
1419
1420     {
1421       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1422       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Count", renderer, "text", 1, NULL);
1423       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1424       gtk_tree_view_column_set_sort_column_id(column, 1);
1425     }
1426
1427     gtk_widget_show(view);
1428
1429     gtk_container_add(GTK_CONTAINER (scr), view);
1430   }
1431
1432   // Initialize fields
1433   int TotalBrushes = 0, TotalEntities = 0, Net = 0;
1434
1435   for (brush_t* pBrush = active_brushes.next; pBrush != &active_brushes; pBrush = pBrush->next)
1436   {
1437     TotalBrushes++;
1438     if (pBrush->owner == world_entity)
1439       Net++;
1440   }
1441
1442   typedef struct
1443   {
1444     const char *name;
1445     int count;
1446   } map_t;
1447
1448   GSList *l, *entitymap = NULL;
1449   map_t *entry;
1450
1451   for (entity_t* pEntity = entities.next; pEntity != &entities; pEntity=pEntity->next)
1452   {
1453     TotalEntities++;
1454     bool add = true;
1455
1456     for (l = entitymap; l; l = g_slist_next (l))
1457     {
1458       entry = (map_t*)l->data;
1459
1460       if (strcmp (entry->name, pEntity->eclass->name) == 0)
1461       {
1462               entry->count++;
1463               add = false;
1464               break;
1465       }
1466     }
1467
1468     if (add)
1469     {
1470       entry = (map_t*)qmalloc (sizeof (map_t));
1471       entry->name = pEntity->eclass->name;
1472       entry->count = 1;
1473       entitymap = g_slist_append (entitymap, entry);
1474     }
1475   }
1476
1477   while (entitymap)
1478   {
1479     entry = (map_t*)entitymap->data;
1480     char tmp[16];
1481     sprintf (tmp, "%d", entry->count);
1482     GtkTreeIter iter;
1483     gtk_list_store_append(GTK_LIST_STORE(store), &iter);
1484     gtk_list_store_set(GTK_LIST_STORE(store), &iter, 0, entry->name, 1, tmp, -1);
1485     free (entry);
1486     entitymap = g_slist_remove (entitymap, entry);
1487   }
1488
1489   g_object_unref(G_OBJECT(store));
1490
1491   char tmp[16];
1492   sprintf (tmp, "%d", TotalBrushes);
1493   gtk_entry_set_text (GTK_ENTRY (brushes_entry), tmp);
1494   sprintf (tmp, "%d", TotalEntities);
1495   gtk_entry_set_text (GTK_ENTRY (entities_entry), tmp);
1496   sprintf (tmp, "%d", Net);
1497   gtk_entry_set_text (GTK_ENTRY (net_entry), tmp);
1498
1499   gtk_grab_add (dlg);
1500   gtk_widget_show (dlg);
1501
1502   while (loop)
1503     gtk_main_iteration ();
1504
1505   // save before exit
1506   save_window_pos(dlg, g_PrefsDlg.mWindowInfo.posMapInfoWnd);
1507
1508   gtk_grab_remove (dlg);
1509   gtk_widget_destroy (dlg);
1510   dlg = NULL;
1511 }
1512
1513 // =============================================================================
1514 // Entity List dialog
1515
1516 static void entitylist_select (GtkWidget *widget, gpointer data)
1517 {
1518   GtkTreeView* view = GTK_TREE_VIEW(g_object_get_data (G_OBJECT (data), "entities"));
1519
1520   GtkTreeSelection* selection = gtk_tree_view_get_selection(view);
1521
1522   GtkTreeModel* model;
1523   GtkTreeIter selected;
1524   if(gtk_tree_selection_get_selected(selection, &model, &selected))
1525   {
1526     entity_t* pEntity;
1527     gtk_tree_model_get(model, &selected, 1, &pEntity, -1);
1528
1529     if (pEntity)
1530     {
1531       for (epair_t* pEpair = pEntity->epairs; pEpair; pEpair = pEpair->next)
1532       {
1533               Select_Deselect ();
1534               Select_Brush (pEntity->brushes.onext);
1535               Sys_UpdateWindows(W_ALL);
1536       }
1537     }
1538   }
1539 }
1540
1541 static gint entitylist_click (GtkWidget *widget, GdkEventButton *event, gpointer data)
1542 {
1543   if (event->type == GDK_2BUTTON_PRESS)
1544   {
1545     entitylist_select (NULL, data);
1546     return TRUE;
1547   }
1548   return FALSE;
1549 }
1550
1551 static void entitylist_selection_changed(GtkTreeSelection* selection, gpointer data)
1552 {
1553   GtkListStore* store = GTK_LIST_STORE (g_object_get_data (G_OBJECT (data), "keyvalues"));
1554
1555   gtk_list_store_clear(store);
1556
1557   GtkTreeModel* model;
1558   GtkTreeIter selected;
1559   if(gtk_tree_selection_get_selected(selection, &model, &selected))
1560   {
1561     entity_t* pEntity;
1562     gtk_tree_model_get(model, &selected, 1, &pEntity, -1);
1563
1564     if (pEntity)
1565     {
1566       for (epair_t* pEpair = pEntity->epairs; pEpair; pEpair = pEpair->next)
1567       {
1568         GtkTreeIter appended;
1569         gtk_list_store_append(store, &appended);
1570         gtk_list_store_set(store, &appended, 0, pEpair->key, 1, pEpair->value, -1);
1571       }
1572     }
1573   }
1574 }
1575
1576 void DoEntityList ()
1577 {
1578   static GtkWidget *dlg;
1579   GtkWidget *vbox, *hbox, *hbox2, *button, *scr;
1580   int loop = 1, ret = IDCANCEL;
1581
1582   if (dlg != NULL)
1583     return;
1584
1585   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1586
1587   load_window_pos (dlg, g_PrefsDlg.mWindowInfo.posEntityInfoWnd);
1588
1589   gtk_window_set_title (GTK_WINDOW (dlg), "Entities");
1590   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
1591                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
1592   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
1593                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
1594   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
1595   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
1596
1597   hbox = gtk_hbox_new (TRUE, 5);
1598   gtk_widget_show (hbox);
1599   gtk_container_add (GTK_CONTAINER (dlg), hbox);
1600   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
1601
1602   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
1603   gtk_widget_show (scr);
1604   gtk_box_pack_start (GTK_BOX (hbox), scr, TRUE, TRUE, 0);
1605   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1606   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
1607
1608   {
1609     GtkTreeStore* store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
1610
1611     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1612     g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(entitylist_click), dlg);
1613     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
1614
1615     {
1616       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1617       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);
1618       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1619     }
1620
1621     {
1622       GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
1623       g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(entitylist_selection_changed), dlg);
1624     }
1625
1626     gtk_widget_show(view);
1627
1628     gtk_container_add(GTK_CONTAINER (scr), view);
1629     g_object_set_data (G_OBJECT (dlg), "entities", view);
1630
1631     {
1632       {
1633         GtkTreeIter child;
1634         gtk_tree_store_append(store, &child, NULL);
1635         gtk_tree_store_set(store, &child, 0, world_entity->eclass->name, 1, world_entity, -1);
1636       }
1637
1638       GSList *l, *entitymap = NULL;
1639       typedef struct
1640       {
1641         GtkTreeIter node;
1642         const char *name;
1643       } map_t;
1644       map_t *entry;
1645
1646       for (entity_t* pEntity=entities.next; pEntity != &entities; pEntity=pEntity->next)
1647       {
1648         GtkTreeIter parent;
1649         bool found = false;
1650
1651         for (l = entitymap; l; l = g_slist_next (l))
1652         {
1653           entry = (map_t*)l->data;
1654
1655           if (strcmp (entry->name, pEntity->eclass->name) == 0)
1656           {
1657                   parent = entry->node;
1658                   found = true;
1659                   break;
1660           }
1661         }
1662
1663         if (!found)
1664         {
1665           gtk_tree_store_append(store, &parent, NULL);
1666           gtk_tree_store_set(store, &parent, 0, pEntity->eclass->name, 1, NULL, -1);
1667
1668           entry = (map_t*)malloc (sizeof(map_t));
1669           entitymap = g_slist_append (entitymap, entry);
1670           entry->name = pEntity->eclass->name;
1671           entry->node = parent;
1672         }
1673
1674         GtkTreeIter child;
1675         gtk_tree_store_append(store, &child, &parent);
1676         gtk_tree_store_set(store, &child, 0, pEntity->eclass->name, 1, pEntity, -1);
1677       }
1678
1679       while (entitymap)
1680       {
1681         free (entitymap->data);
1682         entitymap = g_slist_remove (entitymap, entitymap->data);
1683       }
1684     }
1685     
1686     g_object_unref(G_OBJECT(store));
1687   }
1688
1689   vbox = gtk_vbox_new (FALSE, 5);
1690   gtk_widget_show (vbox);
1691   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1692
1693   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
1694   gtk_widget_show (scr);
1695   gtk_box_pack_start (GTK_BOX (vbox), scr, TRUE, TRUE, 0);
1696   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1697   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
1698
1699   {
1700     GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
1701
1702     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1703
1704     {
1705       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1706       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", 0, NULL);
1707       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1708     }
1709
1710     {
1711       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1712       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Value", renderer, "text", 1, NULL);
1713       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1714     }
1715
1716     gtk_widget_show(view);
1717
1718     g_object_set_data(G_OBJECT(dlg), "keyvalues", store);
1719     gtk_container_add(GTK_CONTAINER (scr), view);
1720     
1721     g_object_unref(G_OBJECT(store));
1722   }
1723
1724   hbox2 = gtk_hbox_new (FALSE, 5);
1725   gtk_widget_show (hbox2);
1726   gtk_box_pack_start (GTK_BOX (vbox), hbox2, TRUE, TRUE, 0);
1727   
1728   button = gtk_button_new_with_label ("Select");
1729   gtk_widget_show (button);
1730   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
1731   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1732                       GTK_SIGNAL_FUNC (entitylist_select), dlg);
1733   gtk_widget_set_usize (button, 60, -2);
1734
1735   button = gtk_button_new_with_label ("Close");
1736   gtk_widget_show (button);
1737   gtk_box_pack_end (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
1738   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1739                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
1740   gtk_widget_set_usize (button, 60, -2);
1741
1742   gtk_grab_add (dlg);
1743   gtk_widget_show (dlg);
1744
1745   while (loop)
1746     gtk_main_iteration ();
1747
1748   save_window_pos (dlg, g_PrefsDlg.mWindowInfo.posMapInfoWnd);
1749
1750   gtk_grab_remove (dlg);
1751   gtk_widget_destroy (dlg);
1752
1753   dlg = NULL;
1754 }
1755
1756 // =============================================================================
1757 // Rotate dialog
1758
1759 static void rotatedlg_apply (GtkWidget *widget, gpointer data)
1760 {
1761   GtkSpinButton *spin;
1762   float f;
1763
1764   spin = GTK_SPIN_BUTTON (g_object_get_data (G_OBJECT (data), "x"));
1765   f = gtk_spin_button_get_value_as_float (spin);
1766   if (f != 0.0)
1767     Select_RotateAxis(0,f);
1768   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), 0.0f); // reset to 0 on Apply
1769   
1770   spin = GTK_SPIN_BUTTON (g_object_get_data (G_OBJECT (data), "y"));
1771   f = gtk_spin_button_get_value_as_float (spin);
1772   if (f != 0.0)
1773     Select_RotateAxis(1,f);
1774   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), 0.0f);
1775   
1776   spin = GTK_SPIN_BUTTON (g_object_get_data (G_OBJECT (data), "z"));
1777   f = gtk_spin_button_get_value_as_float (spin);
1778   if (f != 0.0)
1779     Select_RotateAxis(2,f);
1780   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), 0.0f);
1781 }
1782
1783 void DoRotateDlg ()
1784 {
1785   GtkWidget *dlg, *hbox, *vbox, *table, *label, *button;
1786   GtkWidget *x, *y, *z;
1787   GtkObject *adj;
1788   int loop = 1, ret = IDCANCEL;
1789
1790   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1791   gtk_window_set_title (GTK_WINDOW (dlg), "Arbitrary rotation");
1792   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
1793                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
1794   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
1795                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
1796   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
1797   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
1798
1799   hbox = gtk_hbox_new (FALSE, 5);
1800   gtk_widget_show (hbox);
1801   gtk_container_add (GTK_CONTAINER (dlg), hbox);
1802   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
1803  
1804   table = gtk_table_new (3, 2, FALSE);
1805   gtk_widget_show (table);
1806   gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
1807   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
1808   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
1809  
1810   label = gtk_label_new ("  X  ");
1811   gtk_widget_show (label);
1812   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
1813                     (GtkAttachOptions) (0),
1814                     (GtkAttachOptions) (0), 0, 0);
1815
1816   label = gtk_label_new ("  Y  ");
1817   gtk_widget_show (label);
1818   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
1819                     (GtkAttachOptions) (0),
1820                     (GtkAttachOptions) (0), 0, 0);
1821  
1822   label = gtk_label_new ("  Z  ");
1823
1824   gtk_widget_show (label);
1825   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
1826                     (GtkAttachOptions) (0),
1827                     (GtkAttachOptions) (0), 0, 0);
1828  
1829   adj = gtk_adjustment_new (0, -359, 359, 1, 10, 10);
1830   x = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);
1831   g_object_set_data (G_OBJECT (dlg), "x", x);
1832   gtk_widget_show (x);
1833   gtk_table_attach (GTK_TABLE (table), x, 1, 2, 0, 1,
1834                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1835                     (GtkAttachOptions) (0), 0, 0);
1836   gtk_widget_set_usize (x, 60, -2);
1837   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (x), TRUE);
1838  
1839   adj = gtk_adjustment_new (0, -359, 359, 1, 10, 10);
1840   y = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);
1841   g_object_set_data (G_OBJECT (dlg), "y", y);
1842   gtk_widget_show (y);
1843   gtk_table_attach (GTK_TABLE (table), y, 1, 2, 1, 2,
1844                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1845                     (GtkAttachOptions) (0), 0, 0);
1846   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (y), TRUE);
1847  
1848   adj = gtk_adjustment_new (0, -359, 359, 1, 10, 10);
1849   z = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);
1850   g_object_set_data (G_OBJECT (dlg), "z", z);
1851   gtk_widget_show (z);
1852   gtk_table_attach (GTK_TABLE (table), z, 1, 2, 2, 3,
1853                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1854                     (GtkAttachOptions) (0), 0, 0);
1855   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (z), TRUE);
1856  
1857   vbox = gtk_vbox_new (FALSE, 5);
1858   gtk_widget_show (vbox);
1859   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1860  
1861   button = gtk_button_new_with_label ("OK");
1862   gtk_widget_show (button);
1863   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1864   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1865                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
1866   gtk_widget_set_usize (button, 60, -2);
1867  
1868   button = gtk_button_new_with_label ("Cancel");
1869   gtk_widget_show (button);
1870   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1871   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1872                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
1873  
1874   button = gtk_button_new_with_label ("Apply");
1875   gtk_widget_show (button);
1876   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1877   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1878                       GTK_SIGNAL_FUNC (rotatedlg_apply), dlg);
1879
1880   gtk_grab_add (dlg);
1881   gtk_widget_show (dlg);
1882
1883   while (loop)
1884     gtk_main_iteration ();
1885
1886   if (ret == IDOK)
1887     rotatedlg_apply (button, dlg);
1888
1889   gtk_grab_remove (dlg);
1890   gtk_widget_destroy (dlg);
1891 }
1892
1893 // =============================================================================
1894 // Gamma dialog
1895
1896 void DoGamma ()
1897 {
1898   GtkWidget *dlg, *vbox, *hbox, *label, *button, *entry;
1899   int loop = 1, ret = IDCANCEL;
1900
1901   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1902   gtk_window_set_title (GTK_WINDOW (dlg), "Gamma");
1903   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
1904                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
1905   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
1906                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
1907   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
1908   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
1909
1910   hbox = gtk_hbox_new (FALSE, 5);
1911   gtk_widget_show (hbox);
1912   gtk_container_add (GTK_CONTAINER (dlg), hbox);
1913   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
1914
1915   vbox = gtk_vbox_new (FALSE, 5);
1916   gtk_widget_show (vbox);
1917   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1918
1919   entry = gtk_entry_new ();
1920   gtk_widget_show (entry);
1921   gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
1922
1923   label = gtk_label_new ("0.0 is brightest\n1.0 is darkest");
1924   gtk_widget_show (label);
1925   gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
1926
1927   label = gtk_label_new ("You must restart for the\nsettings to take effect");
1928   gtk_widget_show (label);
1929   gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
1930
1931   vbox = gtk_vbox_new (FALSE, 5);
1932   gtk_widget_show (vbox);
1933   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1934
1935   button = gtk_button_new_with_label ("OK");
1936   gtk_widget_show (button);
1937   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1938   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1939                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
1940   gtk_widget_set_usize (button, 60, -2);
1941  
1942   button = gtk_button_new_with_label ("Cancel");
1943   gtk_widget_show (button);
1944   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1945   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1946                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
1947
1948   // Initialize dialog
1949   char buf[16];
1950   sprintf (buf, "%1.1f", g_qeglobals.d_savedinfo.fGamma);
1951   gtk_entry_set_text (GTK_ENTRY (entry), buf);
1952
1953   gtk_grab_add (dlg);
1954   gtk_widget_show (dlg);
1955
1956   while (loop)
1957     gtk_main_iteration ();
1958
1959   if (ret == IDOK)
1960     g_qeglobals.d_savedinfo.fGamma = g_strtod (gtk_entry_get_text (GTK_ENTRY (entry)), NULL);
1961
1962   gtk_grab_remove (dlg);
1963   gtk_widget_destroy (dlg);
1964 }
1965
1966 // =============================================================================
1967 // Find Brush Dialog
1968
1969 // helper function to walk through the active brushes only and drop the regioned out ones
1970 bool WalkRegionBrush (brush_t **b, entity_t *e)
1971 {
1972   brush_t *b2;
1973   do
1974   {
1975     for(b2=active_brushes.next ; b2 != &active_brushes ; b2=b2->next)
1976     {
1977       if (b2==*b)
1978         break; // this is an active brush
1979     }
1980     if (b2==&active_brushes)
1981     {
1982       // this is a regioned out brush
1983       *b = (*b)->onext;
1984       if (*b == &e->brushes)
1985       {
1986         Sys_Status ("No such brush", 0);
1987         return false;
1988       }
1989     }
1990   } while (b2==&active_brushes);
1991   return true;
1992 }
1993
1994 void SelectBrush (int entitynum, int brushnum)
1995 {
1996   entity_t *e;
1997   brush_t *b;
1998   int i;
1999
2000   // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503
2001   // making this work when regioning is on too
2002
2003   if (entitynum == 0)
2004     e = world_entity;
2005   else
2006   {
2007     e = entities.next;
2008     while (--entitynum)
2009     {
2010       e = e->next;
2011       if (e == &entities)
2012       {
2013         Sys_Status ("No such entity", 0);
2014         return;
2015       }
2016       if (region_active)
2017       {
2018         // we need to make sure we walk to the next 'active' entity to have a valid --entitynum
2019         // that is, find a brush that belongs to this entity in the active brushes
2020         do
2021         {
2022           for (b = active_brushes.next ; b != &active_brushes ; b=b->next)
2023           {
2024             if (b->owner == e)
2025               break; // this is an active entity
2026           }
2027           if (b==&active_brushes)
2028           {
2029             // this is a regioned out entity
2030             e = e->next;        
2031             // don't walk past the end either
2032             if (e == &entities)
2033             {
2034               Sys_Status ("No such entity", 0);
2035               return;
2036             }
2037           }
2038         } while(b==&active_brushes);
2039       }
2040     }
2041   }
2042
2043   b = e->brushes.onext;
2044   if (b == &e->brushes)
2045   {
2046     Sys_Status ("No such brush", 0);
2047     return;
2048   }
2049   if (region_active)
2050   {
2051     if (!WalkRegionBrush(&b, e))
2052       return;
2053   }
2054
2055   while (brushnum--)
2056   {
2057     b = b->onext;
2058     if (b == &e->brushes)
2059     {
2060       Sys_Status ("No such brush", 0);
2061       return;
2062     }
2063     if (region_active)
2064     {
2065       if (!WalkRegionBrush(&b, e))
2066         return;
2067     }
2068   }
2069
2070   Brush_RemoveFromList (b);
2071   Brush_AddToList (b, &selected_brushes);
2072
2073   Sys_UpdateWindows (W_ALL);
2074   for (i = 0; i < 3; i++)
2075   {
2076     if (g_pParentWnd->GetXYWnd())
2077       g_pParentWnd->GetXYWnd()->GetOrigin()[i] = (b->mins[i] + b->maxs[i])/2;
2078
2079     if (g_pParentWnd->GetXZWnd())
2080       g_pParentWnd->GetXZWnd()->GetOrigin()[i] = (b->mins[i] + b->maxs[i])/2;
2081     
2082     if (g_pParentWnd->GetYZWnd())
2083       g_pParentWnd->GetYZWnd()->GetOrigin()[i] = (b->mins[i] + b->maxs[i])/2;
2084   }
2085
2086   Sys_Status ("Selected", 0);
2087 }
2088
2089 static void GetSelectionIndex (int *ent, int *brush)
2090 {
2091   brush_t *b, *b2;
2092   entity_t *entity;
2093
2094   *ent = *brush = 0;
2095
2096   b = selected_brushes.next;
2097   if (b == &selected_brushes)
2098     return;
2099
2100   // find entity
2101   if (b->owner != world_entity)
2102   {
2103     (*ent)++;
2104     for (entity = entities.next; entity != &entities; entity=entity->next, (*ent)++)
2105       ;
2106   }
2107
2108   // find brush
2109   for (b2=b->owner->brushes.onext; b2 != b && b2 != &b->owner->brushes; b2=b2->onext, (*brush)++)
2110     ;
2111 }
2112
2113 void DoFind ()
2114 {
2115   GtkWidget *dlg, *vbox, *hbox, *table, *label, *button, *entity, *brush;
2116   int loop = 1, ret = IDCANCEL;
2117
2118   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2119   gtk_window_set_title (GTK_WINDOW (dlg), "Find Brush");
2120   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2121                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2122   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2123                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2124   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2125   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2126
2127   vbox = gtk_vbox_new (FALSE, 5);
2128   gtk_widget_show (vbox);
2129   gtk_container_add (GTK_CONTAINER (dlg), vbox);
2130   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
2131
2132   table = gtk_table_new (2, 2, FALSE);
2133   gtk_widget_show (table);
2134   gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
2135   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2136   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2137  
2138   label = gtk_label_new ("Entity number");
2139   gtk_widget_show (label);
2140   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2141                     (GtkAttachOptions) (0),
2142                     (GtkAttachOptions) (0), 0, 0);
2143
2144   label = gtk_label_new ("Brush number");
2145   gtk_widget_show (label);
2146   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
2147                     (GtkAttachOptions) (0),
2148                     (GtkAttachOptions) (0), 0, 0);
2149
2150   entity = gtk_entry_new ();
2151   gtk_widget_show (entity);
2152   gtk_table_attach (GTK_TABLE (table), entity, 1, 2, 0, 1,
2153                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2154                     (GtkAttachOptions) (0), 0, 0);
2155
2156   brush = gtk_entry_new ();
2157   gtk_widget_show (brush);
2158   gtk_table_attach (GTK_TABLE (table), brush, 1, 2, 1, 2,
2159                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2160                     (GtkAttachOptions) (0), 0, 0);
2161
2162   hbox = gtk_hbox_new (FALSE, 5);
2163   gtk_widget_show (hbox);
2164   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
2165
2166   button = gtk_button_new_with_label ("OK");
2167   gtk_widget_show (button);
2168   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
2169   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2170                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2171   gtk_widget_set_usize (button, 60, -2);
2172  
2173   button = gtk_button_new_with_label ("Cancel");
2174   gtk_widget_show (button);
2175   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
2176   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2177                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
2178
2179   // Initialize dialog
2180   char buf[16];
2181   int ent, br;
2182
2183   GetSelectionIndex (&ent, &br);
2184   sprintf (buf, "%i", ent);
2185   gtk_entry_set_text (GTK_ENTRY (entity), buf);
2186   sprintf (buf, "%i", br);
2187   gtk_entry_set_text (GTK_ENTRY (brush), buf);
2188
2189   gtk_grab_add (dlg);
2190   gtk_widget_show (dlg);
2191
2192   while (loop)
2193     gtk_main_iteration ();
2194
2195   if (ret == IDOK)
2196   {
2197     const char *entstr = gtk_entry_get_text (GTK_ENTRY (entity));
2198     const char *brushstr = gtk_entry_get_text (GTK_ENTRY (brush));
2199     SelectBrush (atoi(entstr), atoi(brushstr));
2200   }
2201
2202   gtk_grab_remove (dlg);
2203   gtk_widget_destroy (dlg);
2204 }
2205
2206 // =============================================================================
2207 // Arbitrary Sides dialog
2208
2209 void DoSides (bool bCone, bool bSphere, bool bTorus)
2210 {
2211   GtkWidget *dlg, *vbox, *hbox, *button, *label, *entry;
2212   int loop = 1, ret = IDCANCEL;
2213
2214   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2215   gtk_window_set_title (GTK_WINDOW (dlg), "Arbitrary sides");
2216   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2217                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2218   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2219                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2220   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2221   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2222
2223   hbox = gtk_hbox_new (FALSE, 5);
2224   gtk_widget_show (hbox);
2225   gtk_container_add (GTK_CONTAINER (dlg), hbox);
2226   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2227
2228   label = gtk_label_new ("Sides:");
2229   gtk_widget_show (label);
2230   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
2231
2232   entry = gtk_entry_new ();
2233   gtk_widget_show (entry);
2234   gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
2235
2236   vbox = gtk_vbox_new (FALSE, 5);
2237   gtk_widget_show (vbox);
2238   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, TRUE, 0);
2239
2240   button = gtk_button_new_with_label ("OK");
2241   gtk_widget_show (button);
2242   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2243   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2244                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2245   gtk_widget_set_usize (button, 60, -2);
2246  
2247   button = gtk_button_new_with_label ("Cancel");
2248   gtk_widget_show (button);
2249   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2250   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2251                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
2252
2253   gtk_grab_add (dlg);
2254   gtk_widget_show (dlg);
2255
2256   while (loop)
2257     gtk_main_iteration ();
2258
2259   if (ret == IDOK)
2260   {
2261     const char *str = gtk_entry_get_text (GTK_ENTRY (entry));
2262
2263     if (bCone)
2264       Brush_MakeSidedCone(atoi(str));
2265     else if (bSphere)
2266       Brush_MakeSidedSphere(atoi(str));
2267     else
2268       Brush_MakeSided (atoi(str));
2269   }
2270
2271   gtk_grab_remove (dlg);
2272   gtk_widget_destroy (dlg);
2273 }
2274
2275 // =============================================================================
2276 // New Patch dialog
2277
2278 void DoNewPatchDlg ()
2279 {
2280   GtkWidget *dlg, *hbox, *table, *vbox, *label, *button, *combo;
2281   GtkWidget *width, *height;
2282   GList *combo_list = (GList*)NULL;
2283   int loop = 1, ret = IDCANCEL;
2284
2285   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2286   gtk_window_set_title (GTK_WINDOW (dlg), "Patch density");
2287   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2288                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2289   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2290                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2291   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2292   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2293
2294   hbox = gtk_hbox_new (FALSE, 5);
2295   gtk_widget_show (hbox);
2296   gtk_container_add (GTK_CONTAINER (dlg), hbox);
2297   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2298
2299   table = gtk_table_new (2, 2, FALSE);
2300   gtk_widget_show (table);
2301   gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
2302   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2303   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2304  
2305   label = gtk_label_new ("Width:");
2306   gtk_widget_show (label);
2307   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2308                     (GtkAttachOptions) (GTK_FILL),
2309                     (GtkAttachOptions) (0), 0, 0);
2310   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2311
2312   label = gtk_label_new ("Height:");
2313   gtk_widget_show (label);
2314   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
2315                     (GtkAttachOptions) (GTK_FILL),
2316                     (GtkAttachOptions) (0), 0, 0);
2317   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2318
2319   combo_list = g_list_append (combo_list, (void *)"3");
2320   combo_list = g_list_append (combo_list, (void *)"5");
2321   combo_list = g_list_append (combo_list, (void *)"7");
2322   combo_list = g_list_append (combo_list, (void *)"9");
2323   combo_list = g_list_append (combo_list, (void *)"11");
2324   combo_list = g_list_append (combo_list, (void *)"13");
2325   combo_list = g_list_append (combo_list, (void *)"15");
2326
2327   combo = gtk_combo_new ();
2328   width = GTK_COMBO (combo)->entry;
2329   gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
2330   gtk_widget_show (combo);
2331   gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 0, 1,
2332                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2333                     (GtkAttachOptions) (0), 0, 0);
2334
2335   combo = gtk_combo_new ();
2336   height = GTK_COMBO (combo)->entry;
2337   gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
2338   gtk_widget_show (combo);
2339   gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 1, 2,
2340                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2341                     (GtkAttachOptions) (0), 0, 0);
2342
2343   vbox = gtk_vbox_new (FALSE, 5);
2344   gtk_widget_show (vbox);
2345   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
2346
2347   button = gtk_button_new_with_label ("OK");
2348   gtk_widget_show (button);
2349   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2350   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2351                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2352   gtk_widget_set_usize (button, 60, -2);
2353  
2354   button = gtk_button_new_with_label ("Cancel");
2355   gtk_widget_show (button);
2356   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2357   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2358                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
2359
2360   // Initialize dialog
2361   g_list_free (combo_list);
2362   gtk_entry_set_text (GTK_ENTRY (width), "3");
2363   gtk_entry_set_editable (GTK_ENTRY (width), FALSE);
2364   gtk_entry_set_text (GTK_ENTRY (height), "3");
2365   gtk_entry_set_editable (GTK_ENTRY (height), FALSE);
2366
2367   gtk_grab_add (dlg);
2368   gtk_widget_show (dlg);
2369
2370   while (loop)
2371     gtk_main_iteration ();
2372
2373   if (ret == IDOK)
2374   {
2375     const char* w = gtk_entry_get_text (GTK_ENTRY (width));
2376     const char* h = gtk_entry_get_text (GTK_ENTRY (height));
2377
2378     Patch_GenericMesh(atoi (w), atoi (h), g_pParentWnd->ActiveXY ()->GetViewType ());
2379     Sys_UpdateWindows (W_ALL);
2380   }
2381
2382   gtk_grab_remove (dlg);
2383   gtk_widget_destroy (dlg);
2384 }
2385
2386 // =============================================================================
2387 // New Patch dialog
2388
2389 void DoScaleDlg ()
2390 {
2391   GtkWidget *dlg, *hbox, *table, *vbox, *label, *button;
2392   GtkWidget *x, *y, *z;
2393   int loop = 1, ret = IDCANCEL;
2394
2395   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2396   gtk_window_set_title (GTK_WINDOW (dlg), "Scale");
2397   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2398                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2399   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2400                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2401   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2402   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2403
2404   hbox = gtk_hbox_new (FALSE, 5);
2405   gtk_widget_show (hbox);
2406   gtk_container_add (GTK_CONTAINER (dlg), hbox);
2407   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2408
2409   table = gtk_table_new (3, 2, FALSE);
2410   gtk_widget_show (table);
2411   gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
2412   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2413   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2414  
2415   label = gtk_label_new ("X:");
2416   gtk_widget_show (label);
2417   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2418                     (GtkAttachOptions) (GTK_FILL),
2419                     (GtkAttachOptions) (0), 0, 0);
2420   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2421
2422   label = gtk_label_new ("Y:");
2423   gtk_widget_show (label);
2424   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
2425                     (GtkAttachOptions) (GTK_FILL),
2426                     (GtkAttachOptions) (0), 0, 0);
2427   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2428
2429   label = gtk_label_new ("Z:");
2430   gtk_widget_show (label);
2431   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
2432                     (GtkAttachOptions) (GTK_FILL),
2433                     (GtkAttachOptions) (0), 0, 0);
2434   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2435
2436   x = gtk_entry_new ();
2437   gtk_widget_show (x);
2438   gtk_table_attach (GTK_TABLE (table), x, 1, 2, 0, 1,
2439                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2440                     (GtkAttachOptions) (0), 0, 0);
2441
2442   y = gtk_entry_new ();
2443   gtk_widget_show (y);
2444   gtk_table_attach (GTK_TABLE (table), y, 1, 2, 1, 2,
2445                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2446                     (GtkAttachOptions) (0), 0, 0);
2447
2448   z = gtk_entry_new ();
2449   gtk_widget_show (z);
2450   gtk_table_attach (GTK_TABLE (table), z, 1, 2, 2, 3,
2451                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2452                     (GtkAttachOptions) (0), 0, 0);
2453
2454   vbox = gtk_vbox_new (FALSE, 5);
2455   gtk_widget_show (vbox);
2456   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
2457
2458   button = gtk_button_new_with_label ("OK");
2459   gtk_widget_show (button);
2460   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2461   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2462                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2463   gtk_widget_set_usize (button, 60, -2);
2464  
2465   button = gtk_button_new_with_label ("Cancel");
2466   gtk_widget_show (button);
2467   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2468   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2469                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
2470
2471   // Initialize dialog
2472   gtk_entry_set_text (GTK_ENTRY (x), "1.0");
2473   gtk_entry_set_text (GTK_ENTRY (y), "1.0");
2474   gtk_entry_set_text (GTK_ENTRY (z), "1.0");
2475
2476   gtk_grab_add (dlg);
2477   gtk_widget_show (dlg);
2478
2479   while (loop)
2480     gtk_main_iteration ();
2481
2482   if (ret == IDOK)
2483   {
2484     float sx, sy, sz;
2485     sx = atof (gtk_entry_get_text (GTK_ENTRY (x)));
2486     sy = atof (gtk_entry_get_text (GTK_ENTRY (y)));
2487     sz = atof (gtk_entry_get_text (GTK_ENTRY (z)));
2488
2489     if (sx > 0 && sy > 0 && sz > 0)
2490     {
2491       Select_Scale(sx, sy, sz);
2492       Sys_UpdateWindows (W_ALL);
2493     }
2494     else
2495       Sys_Printf("Warning.. Tried to scale by a zero value.");
2496   }
2497
2498   gtk_grab_remove (dlg);
2499   gtk_widget_destroy (dlg);
2500 }
2501
2502 // =============================================================================
2503 // Thicken Patch dialog
2504
2505 void DoThickenDlg ()
2506 {
2507   GtkWidget *dlg, *vbox, *hbox, *vbox2, *button, *label;
2508   GtkWidget *amount, *seams, *group;
2509   int loop = 1, ret = IDCANCEL;
2510   static qboolean bGroupResult = true;
2511
2512   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2513   gtk_window_set_title (GTK_WINDOW (dlg), "Thicken Patch");
2514   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2515                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2516   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2517                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2518   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2519   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2520
2521   vbox = gtk_vbox_new (FALSE, 5);
2522   gtk_widget_show (vbox);
2523   gtk_container_add (GTK_CONTAINER (dlg), vbox);
2524   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
2525
2526   hbox = gtk_hbox_new (FALSE, 5);
2527   gtk_widget_show (hbox);
2528   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
2529
2530   label = gtk_label_new ("This produces a set of patches\n"
2531                          "that contains the original patch along with the\n"
2532                          "'thick' patch and an optimal set of seam patches.");
2533   gtk_widget_show (label);
2534   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
2535
2536   vbox2 = gtk_vbox_new (FALSE, 5);
2537   gtk_widget_show (vbox2);
2538   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, TRUE, 0);
2539
2540   button = gtk_button_new_with_label ("OK");
2541   gtk_widget_show (button);
2542   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
2543   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2544                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2545   gtk_widget_set_usize (button, 60, -2);
2546  
2547   button = gtk_button_new_with_label ("Cancel");
2548   gtk_widget_show (button);
2549   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
2550   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2551                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
2552
2553   hbox = gtk_hbox_new (FALSE, 5);
2554   gtk_widget_show (hbox);
2555   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
2556
2557   label = gtk_label_new ("Amount:");
2558   gtk_widget_show (label);
2559   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
2560
2561   amount = gtk_entry_new ();
2562   gtk_widget_show (amount);
2563   gtk_box_pack_start (GTK_BOX (hbox), amount, FALSE, FALSE, 0);
2564
2565   seams = gtk_check_button_new_with_label ("Seams");
2566   gtk_widget_show (seams);
2567   gtk_box_pack_start (GTK_BOX (hbox), seams, FALSE, FALSE, 0);
2568   
2569   // bGroupResult
2570   group = gtk_check_button_new_with_label("Result to func_group");
2571   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(group), bGroupResult);
2572   gtk_box_pack_start(GTK_BOX(vbox), group, FALSE, FALSE, 0);
2573   gtk_widget_show(group);
2574   
2575
2576   // Initialize dialog
2577   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (seams), TRUE);
2578   gtk_entry_set_text (GTK_ENTRY (amount), "8");
2579
2580   gtk_grab_add (dlg);
2581   gtk_widget_show (dlg);
2582
2583   while (loop)
2584     gtk_main_iteration ();
2585
2586   if (ret == IDOK)
2587   {
2588     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(group)))
2589       bGroupResult = true;
2590     else
2591       bGroupResult = false;
2592     Patch_Thicken (atoi (gtk_entry_get_text (GTK_ENTRY (amount))),
2593                    gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (seams)), bGroupResult);
2594     Sys_UpdateWindows (W_ALL);
2595   }
2596
2597   gtk_grab_remove (dlg);
2598   gtk_widget_destroy (dlg);
2599 }
2600
2601 // =============================================================================
2602 // About dialog (no program is complete without one)
2603
2604 void about_button_changelog (GtkWidget *widget, gpointer data)
2605 {
2606   Str log;
2607   log = g_strAppPath;
2608   log += "changelog.txt";
2609   OpenURL(log.GetBuffer());
2610 }
2611
2612 void about_button_credits (GtkWidget *widget, gpointer data)
2613 {
2614   Str cred;
2615   cred = g_strAppPath;
2616   cred += "credits.html";
2617   OpenURL(cred.GetBuffer());
2618 }
2619
2620 void DoAbout ()
2621 {
2622   GtkWidget *dlg, *vbox, *vbox2, *hbox, *frame, *table, *label, *pixmap, *button, *sc_extensions, *text_extensions;
2623   int loop = 1, ret = IDCANCEL;
2624
2625   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2626   gtk_window_set_title (GTK_WINDOW (dlg), "About GtkRadiant");
2627   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2628                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2629   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2630                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2631   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2632   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2633
2634   vbox = gtk_vbox_new (FALSE, 10);
2635   gtk_widget_show (vbox);
2636   gtk_container_add (GTK_CONTAINER (dlg), vbox);
2637   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
2638
2639   hbox = gtk_hbox_new (FALSE, 5);
2640   gtk_widget_show (hbox);
2641   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
2642
2643   vbox2 = gtk_vbox_new (FALSE, 5);
2644   gtk_widget_show (vbox2);
2645   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, FALSE, 0);
2646
2647   frame = gtk_frame_new ((char*)NULL);
2648   gtk_widget_show (frame);
2649   gtk_box_pack_start (GTK_BOX (vbox2), frame, FALSE, FALSE, 0);
2650   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
2651
2652   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "logo.bmp");
2653   gtk_widget_show (pixmap);
2654   gtk_container_add (GTK_CONTAINER (frame), pixmap);
2655
2656   label = gtk_label_new ("GtkRadiant " RADIANT_VERSION "\n"
2657     __DATE__ "\n\n"
2658     RADIANT_ABOUTMSG "\n\n"
2659     "By qeradiant.com\n\n"
2660     "This product contains software technology\n"
2661     "from id Software, Inc. ('id Technology').\n"
2662     "id Technology 2000 id Software,Inc.\n\n"
2663     "GtkRadiant is unsupported, however\n"
2664     "you may report your problems at\n"
2665     "http://zerowing.idsoftware.com/bugzilla"
2666   );
2667                          
2668   gtk_widget_show (label);
2669   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
2670   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
2671   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
2672
2673   vbox2 = gtk_vbox_new (FALSE, 5);
2674   gtk_widget_show (vbox2);
2675   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, TRUE, 0);
2676
2677   button = gtk_button_new_with_label ("OK");
2678   gtk_widget_show (button);
2679   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
2680   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2681                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2682
2683   button = gtk_button_new_with_label ("Credits");
2684   gtk_widget_show (button);
2685   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
2686   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2687                       GTK_SIGNAL_FUNC (about_button_credits), NULL);
2688
2689   button = gtk_button_new_with_label ("Changelog");
2690   gtk_widget_show (button);
2691   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
2692   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2693                       GTK_SIGNAL_FUNC (about_button_changelog), NULL);
2694
2695   frame = gtk_frame_new ("OpenGL Properties");
2696   gtk_widget_show (frame);
2697   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2698
2699   table = gtk_table_new (3, 2, FALSE);
2700   gtk_widget_show (table);
2701   gtk_container_add (GTK_CONTAINER (frame), table);
2702   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2703   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2704   gtk_container_set_border_width (GTK_CONTAINER (table), 5);
2705  
2706   label = gtk_label_new ("Vendor:");
2707   gtk_widget_show (label);
2708   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2709                     (GtkAttachOptions) (GTK_FILL),
2710                     (GtkAttachOptions) (0), 0, 0);
2711   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2712
2713   label = gtk_label_new ("Version:");
2714   gtk_widget_show (label);
2715   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
2716                     (GtkAttachOptions) (GTK_FILL),
2717                     (GtkAttachOptions) (0), 0, 0);
2718   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2719
2720   label = gtk_label_new ("Renderer:");
2721   gtk_widget_show (label);
2722   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
2723                     (GtkAttachOptions) (GTK_FILL),
2724                     (GtkAttachOptions) (0), 0, 0);
2725   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2726
2727   label = gtk_label_new ((char*)qglGetString (GL_VENDOR));
2728   gtk_widget_show (label);
2729   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
2730                     (GtkAttachOptions) (GTK_FILL),
2731                     (GtkAttachOptions) (0), 0, 0);
2732   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2733
2734   label = gtk_label_new ((char*)qglGetString (GL_VERSION));
2735   gtk_widget_show (label);
2736   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 1, 2,
2737                     (GtkAttachOptions) (GTK_FILL),
2738                     (GtkAttachOptions) (0), 0, 0);
2739   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2740
2741   label = gtk_label_new ((char*)qglGetString (GL_RENDERER));
2742   gtk_widget_show (label);
2743   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 2, 3,
2744                     (GtkAttachOptions) (GTK_FILL),
2745                     (GtkAttachOptions) (0), 0, 0);
2746   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2747
2748   frame = gtk_frame_new ("OpenGL Extensions");
2749   gtk_widget_show (frame);
2750   gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
2751
2752   hbox = gtk_hbox_new (FALSE, 5);
2753   gtk_widget_show (hbox);
2754   gtk_container_add (GTK_CONTAINER (frame), hbox);
2755   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2756
2757   sc_extensions = gtk_scrolled_window_new(NULL, NULL);
2758   gtk_box_pack_start(GTK_BOX(hbox), sc_extensions, TRUE, TRUE, 0);
2759   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sc_extensions), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2760   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sc_extensions), GTK_SHADOW_IN);
2761   gtk_widget_show(sc_extensions);
2762         
2763   text_extensions = gtk_text_view_new();
2764   gtk_text_view_set_editable(GTK_TEXT_VIEW(text_extensions), FALSE);
2765   gtk_container_add (GTK_CONTAINER (sc_extensions), text_extensions);
2766   GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_extensions));
2767   gtk_text_buffer_set_text(buffer, (char *)qglGetString(GL_EXTENSIONS), -1);
2768   gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_extensions), GTK_WRAP_WORD);;
2769   gtk_widget_show(text_extensions);     
2770         
2771   gtk_grab_add (dlg);
2772   gtk_widget_show (dlg);
2773
2774   while (loop)
2775     gtk_main_iteration ();
2776
2777   gtk_grab_remove (dlg);
2778   gtk_widget_destroy (dlg);
2779 }
2780
2781 // =============================================================================
2782 // Command List dialog 
2783
2784 void DoCommandListDlg ()
2785 {
2786   GtkWidget *dlg, *vbox, *hbox, *scr, *button;
2787   int loop = 1, ret = IDCANCEL;
2788
2789   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2790   gtk_window_set_title (GTK_WINDOW (dlg), "Mapped Commands");
2791   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2792                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2793   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2794                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2795   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2796   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2797   gtk_window_set_default_size (GTK_WINDOW (dlg), 400, 400);
2798
2799   hbox = gtk_hbox_new (FALSE, 5);
2800   gtk_widget_show (hbox);
2801   gtk_container_add (GTK_CONTAINER (dlg), hbox);
2802   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2803
2804   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
2805   gtk_widget_show (scr);
2806   gtk_box_pack_start (GTK_BOX (hbox), scr, TRUE, TRUE, 0);
2807   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
2808   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scr), GTK_SHADOW_IN);
2809
2810   {
2811     GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
2812
2813     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
2814
2815     {
2816       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
2817       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Command", renderer, "text", 0, NULL);
2818       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
2819     }
2820
2821     {
2822       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
2823       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", 1, NULL);
2824       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
2825     }
2826
2827     gtk_widget_show(view);
2828     gtk_container_add(GTK_CONTAINER (scr), view);
2829
2830     {
2831       // Initialize dialog
2832       CString path;
2833       path = g_strTempPath;
2834       path += "commandlist.txt";
2835
2836       GSList *cmds = NULL;
2837       int n;
2838
2839       for (n = 0; n < g_nCommandCount; n++)
2840         cmds = g_slist_append (cmds, g_Commands[n].m_strCommand);
2841       cmds = g_slist_sort (cmds, (gint (*)(const void *, const void *))strcmp);
2842
2843       Sys_Printf("Writing the command list to %s", path.GetBuffer() );
2844       FILE* fileout = fopen (path.GetBuffer (), "wt");
2845
2846       while (cmds)
2847       {
2848         for (n = 0; n < g_nCommandCount; n++)
2849           if (cmds->data == g_Commands[n].m_strCommand)
2850             break;
2851
2852         char c = g_Commands[n].m_nKey;
2853         CString strLine, strMod(""), strKeys (c);
2854
2855         for (int k = 0; k < g_nKeyCount; k++)
2856         {
2857           if (g_Keys[k].m_nVKKey == g_Commands[n].m_nKey)
2858           {
2859             strKeys = g_Keys[k].m_strName;
2860             break;
2861           }
2862         }
2863
2864         if (g_Commands[n].m_nModifiers & RAD_SHIFT)
2865           strMod = "Shift";
2866         if (g_Commands[n].m_nModifiers & RAD_ALT)
2867           strMod += (strMod.GetLength() > 0) ? " + Alt" : "Alt";
2868         if (g_Commands[n].m_nModifiers & RAD_CONTROL)
2869           strMod += (strMod.GetLength() > 0) ? " + Control" : "Control";
2870         if (strMod.GetLength() > 0)
2871           strMod += " + ";
2872         strMod += strKeys;
2873
2874         {
2875           GtkTreeIter iter;
2876           gtk_list_store_append(store, &iter);
2877           gtk_list_store_set(store, &iter, 0, g_Commands[n].m_strCommand, 1, strMod.GetBuffer (), -1);
2878         }
2879  
2880         if (fileout != NULL)
2881         {
2882           strLine.Format("%-25s %s\r\n", g_Commands[n].m_strCommand, strMod.GetBuffer ());
2883           fputs (strLine.GetBuffer (), fileout);
2884         }
2885
2886         cmds = g_slist_remove (cmds, cmds->data);
2887       }
2888
2889       if (fileout != NULL)
2890         fclose (fileout);
2891     }
2892     
2893     g_object_unref(G_OBJECT(store));
2894   }
2895
2896   vbox = gtk_vbox_new (FALSE, 5);
2897   gtk_widget_show (vbox);
2898   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
2899
2900   button = gtk_button_new_with_label ("Close");
2901   gtk_widget_show (button);
2902   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2903   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2904                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2905   gtk_widget_set_usize (button, 60, -2);
2906
2907   gtk_grab_add (dlg);
2908   gtk_widget_show (dlg);
2909
2910   while (loop)
2911     gtk_main_iteration ();
2912
2913   gtk_grab_remove (dlg);
2914   gtk_widget_destroy (dlg);
2915 }
2916
2917 // =============================================================================
2918 // Texture List dialog 
2919
2920 void DoTextureListDlg ()
2921 {
2922   GtkWidget *dlg, *vbox, *hbox, *scr, *button;
2923   int loop = 1, ret = IDCANCEL;
2924
2925   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2926   gtk_window_set_title (GTK_WINDOW (dlg), "Textures");
2927   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2928                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2929   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2930                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2931   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2932   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2933   gtk_window_set_default_size (GTK_WINDOW (dlg), 400, 400);
2934
2935   hbox = gtk_hbox_new (FALSE, 5);
2936   gtk_widget_show (hbox);
2937   gtk_container_add (GTK_CONTAINER (dlg), hbox);
2938   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2939
2940   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
2941   gtk_widget_show (scr);
2942   gtk_box_pack_start (GTK_BOX (hbox), scr, TRUE, TRUE, 0);
2943   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
2944   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scr), GTK_SHADOW_IN);
2945
2946   GtkWidget* texture_list;
2947
2948   {
2949     GtkListStore* store = gtk_list_store_new(1, G_TYPE_STRING);
2950
2951     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
2952     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); 
2953
2954     {
2955       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
2956       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);
2957       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
2958     }
2959
2960     gtk_widget_show(view);
2961     gtk_container_add(GTK_CONTAINER (scr), view);
2962
2963     {
2964       // Initialize dialog
2965       GSList *textures = (GSList*)NULL;
2966       FillTextureMenu(&textures);
2967       while (textures != NULL)
2968       {
2969         {
2970           GtkTreeIter iter;
2971           gtk_list_store_append(store, &iter);
2972           gtk_list_store_set(store, &iter, 0, (gchar*)textures->data, -1);
2973         }
2974         free (textures->data);
2975         textures = g_slist_remove (textures, textures->data);
2976       }
2977     }
2978     
2979     g_object_unref(G_OBJECT(store));
2980
2981     texture_list = view;
2982   }
2983
2984   vbox = gtk_vbox_new (FALSE, 5);
2985   gtk_widget_show (vbox);
2986   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
2987
2988   button = gtk_button_new_with_label ("Load");
2989   gtk_widget_show (button);
2990   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2991   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2992                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2993   gtk_widget_set_usize (button, 60, -2);
2994
2995   button = gtk_button_new_with_label ("Close");
2996   gtk_widget_show (button);
2997   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2998   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2999                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3000   gtk_widget_set_usize (button, 60, -2);
3001
3002   gtk_grab_add (dlg);
3003   gtk_widget_show (dlg);
3004
3005   while (loop)
3006     gtk_main_iteration ();
3007
3008   if (ret == IDOK)
3009   {
3010     GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(texture_list));
3011
3012     GtkTreeModel* model;
3013     GtkTreeIter iter;
3014     if(gtk_tree_selection_get_selected(selection, &model, &iter))
3015     {
3016       GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
3017       if(gtk_tree_path_get_depth(path) == 1)
3018         Texture_ShowDirectory(gtk_tree_path_get_indices(path)[0] + CMD_TEXTUREWAD);
3019       gtk_tree_path_free(path);
3020     }
3021   }
3022
3023   gtk_grab_remove (dlg);
3024   gtk_widget_destroy (dlg);
3025 }
3026
3027 // =============================================================================
3028 // Cap dialog 
3029
3030 int DoCapDlg (int *type, bool *b_GroupResult)
3031 {
3032   GtkWidget *dlg, *vbox, *hbox, *table, *pixmap, *button, *group_toggle, *radio_vbox;
3033   GtkWidget *bevel, *endcap, *ibevel, *iendcap;
3034   GSList *group = (GSList*)NULL;
3035         int loop = 1, ret = IDCANCEL;
3036         
3037   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3038   gtk_window_set_title (GTK_WINDOW (dlg), "Cap");
3039   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3040                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3041   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3042                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3043   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3044   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3045
3046         hbox = gtk_hbox_new (FALSE, 5);
3047   gtk_widget_show (hbox);
3048   gtk_container_add (GTK_CONTAINER (dlg), hbox);
3049   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3050
3051   // Gef: Added a vbox to contain the toggle buttons
3052   radio_vbox = gtk_vbox_new(FALSE, 4);
3053   gtk_container_add(GTK_CONTAINER(hbox), radio_vbox);
3054   gtk_widget_show(radio_vbox);
3055                 
3056   table = gtk_table_new (4, 2, FALSE);
3057   gtk_widget_show (table);
3058   gtk_box_pack_start (GTK_BOX (radio_vbox), table, TRUE, TRUE, 0);
3059   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
3060   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
3061  
3062   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "cap_bevel.bmp");
3063   gtk_widget_show (pixmap);
3064   gtk_table_attach (GTK_TABLE (table), pixmap, 0, 1, 0, 1,
3065                     (GtkAttachOptions) (GTK_FILL),
3066                     (GtkAttachOptions) (0), 0, 0);
3067
3068   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "cap_endcap.bmp");
3069   gtk_widget_show (pixmap);
3070   gtk_table_attach (GTK_TABLE (table), pixmap, 0, 1, 1, 2,
3071                     (GtkAttachOptions) (GTK_FILL),
3072                     (GtkAttachOptions) (0), 0, 0);
3073
3074   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "cap_ibevel.bmp");
3075   gtk_widget_show (pixmap);
3076   gtk_table_attach (GTK_TABLE (table), pixmap, 0, 1, 2, 3,
3077                     (GtkAttachOptions) (GTK_FILL),
3078                     (GtkAttachOptions) (0), 0, 0);
3079
3080   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "cap_iendcap.bmp");
3081   gtk_widget_show (pixmap);
3082   gtk_table_attach (GTK_TABLE (table), pixmap, 0, 1, 3, 4,
3083                     (GtkAttachOptions) (GTK_FILL),
3084                     (GtkAttachOptions) (0), 0, 0);
3085
3086   bevel = gtk_radio_button_new_with_label (group, "Bevel");
3087   gtk_widget_show (bevel);
3088   gtk_table_attach (GTK_TABLE (table), bevel, 1, 2, 0, 1,
3089                     (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
3090                     (GtkAttachOptions) (0), 0, 0);
3091   group = gtk_radio_button_group (GTK_RADIO_BUTTON (bevel));
3092
3093   endcap = gtk_radio_button_new_with_label (group, "Endcap");
3094   gtk_widget_show (endcap);
3095   gtk_table_attach (GTK_TABLE (table), endcap, 1, 2, 1, 2,
3096                     (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
3097                     (GtkAttachOptions) (0), 0, 0);
3098   group = gtk_radio_button_group (GTK_RADIO_BUTTON (endcap));
3099
3100   ibevel = gtk_radio_button_new_with_label (group, "Inverted Bevel");
3101   gtk_widget_show (ibevel);
3102   gtk_table_attach (GTK_TABLE (table), ibevel, 1, 2, 2, 3,
3103                     (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
3104                     (GtkAttachOptions) (0), 0, 0);
3105   group = gtk_radio_button_group (GTK_RADIO_BUTTON (ibevel));
3106
3107   iendcap = gtk_radio_button_new_with_label (group, "Inverted Endcap");
3108   gtk_widget_show (iendcap);
3109   gtk_table_attach (GTK_TABLE (table), iendcap, 1, 2, 3, 4,
3110                     (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
3111                     (GtkAttachOptions) (0), 0, 0);
3112   group = gtk_radio_button_group (GTK_RADIO_BUTTON (iendcap));
3113
3114   // Gef: added radio toggle for func_grouping capped patches
3115   group_toggle = gtk_check_button_new_with_label("Result to func_group");
3116   gtk_container_add(GTK_CONTAINER(radio_vbox), group_toggle);
3117   gtk_widget_show(group_toggle);
3118         
3119   vbox = gtk_vbox_new (FALSE, 5);
3120   gtk_widget_show (vbox);
3121   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3122
3123   button = gtk_button_new_with_label ("OK");
3124   gtk_widget_show (button);
3125   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3126   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3127                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
3128   gtk_widget_set_usize (button, 60, -2);
3129
3130   button = gtk_button_new_with_label ("Cancel");
3131   gtk_widget_show (button);
3132   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3133   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3134                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3135   gtk_widget_set_usize (button, 60, -2);
3136
3137   // Gef: Set the state of the func_group toggle
3138   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (group_toggle), *b_GroupResult);
3139         
3140   // Initialize dialog
3141   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bevel), TRUE);
3142
3143   gtk_grab_add (dlg);
3144   gtk_widget_show (dlg);
3145
3146   while (loop)
3147     gtk_main_iteration ();
3148
3149   if (ret == IDOK)
3150   {
3151     if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (bevel)))
3152       *type = BEVEL; //*type = CapDialog::BEVEL;
3153     else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (endcap)))
3154       *type = ENDCAP; //*type = CapDialog::ENDCAP;
3155     else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ibevel)))
3156       *type = IBEVEL; // *type = CapDialog::IBEVEL;
3157     else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (iendcap)))
3158       *type = IENDCAP; // *type = CapDialog::IENDCAP;
3159
3160     // Gef: Added toggle for optional cap func_grouping
3161     *b_GroupResult = (bool *)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(group_toggle));
3162   }
3163
3164   gtk_grab_remove (dlg);
3165   gtk_widget_destroy (dlg);
3166
3167   return ret;
3168 }
3169
3170 // =============================================================================
3171 // Scripts dialog 
3172
3173 void DoScriptsDlg ()
3174 {
3175   GtkWidget *dlg, *vbox, *vbox2, *hbox, *label, *button, *scr;
3176   int loop = 1, ret = IDCANCEL;
3177
3178   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3179   gtk_window_set_title (GTK_WINDOW (dlg), "Available Scripts - Not Implemented Yet");
3180   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3181                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3182   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3183                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3184   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3185   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3186
3187   vbox = gtk_vbox_new (FALSE, 5);
3188   gtk_widget_show (vbox);
3189   gtk_container_add (GTK_CONTAINER (dlg), vbox);
3190   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
3191
3192   label = gtk_label_new ("WARNING: BrushScripting is in a highly experimental state and is\n"
3193                          "far from complete. If you attempt to use them it is VERY LIKELY\n"
3194                          "that Radiant will crash. Save your work before attempting to\n"
3195                          "make use of any scripting features.");
3196   gtk_widget_show (label);
3197   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
3198   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
3199   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3200
3201   hbox = gtk_hbox_new (FALSE, 5);
3202   gtk_widget_show (hbox);
3203   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3204
3205   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
3206   gtk_widget_show (scr);
3207   gtk_box_pack_start (GTK_BOX (hbox), scr, TRUE, TRUE, 0);
3208   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
3209   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scr), GTK_SHADOW_IN);
3210
3211   GtkWidget* scripts_list;
3212
3213   {
3214     GtkListStore* store = gtk_list_store_new(1, G_TYPE_STRING);
3215
3216     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
3217     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); 
3218
3219     {
3220       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
3221       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);
3222       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
3223     }
3224
3225     gtk_widget_show(view);
3226     gtk_container_add(GTK_CONTAINER (scr), view);
3227
3228     {
3229       // Initialize dialog
3230       CString strINI;
3231       strINI = g_strGameToolsPath;
3232       strINI += "/scripts.ini";
3233       FILE *f;
3234
3235       f = fopen (strINI.GetBuffer(), "rt");
3236       if (f != NULL)
3237       {
3238         char line[1024], *ptr;
3239
3240         // read section names
3241         while (fgets (line, 1024, f) != 0)
3242         {
3243           if (line[0] != '[')
3244             continue;
3245
3246           ptr = strchr (line, ']');
3247           *ptr = '\0';
3248
3249           {
3250             GtkTreeIter iter;
3251             gtk_list_store_append(store, &iter);
3252             gtk_list_store_set(store, &iter, 0, line, -1);
3253           }
3254         }
3255         fclose (f);
3256       }
3257     }
3258     
3259     g_object_unref(G_OBJECT(store));
3260
3261     scripts_list = view;
3262   }
3263
3264   vbox2 = gtk_vbox_new (FALSE, 5);
3265   gtk_widget_show (vbox2);
3266   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
3267
3268   button = gtk_button_new_with_label ("Run");
3269   gtk_widget_show (button);
3270   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
3271   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3272                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
3273   gtk_widget_set_usize (button, 60, -2);
3274
3275   button = gtk_button_new_with_label ("New...");
3276   gtk_widget_show (button);
3277   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
3278   gtk_widget_set_sensitive (button, FALSE);
3279   gtk_widget_set_usize (button, 60, -2);
3280
3281   button = gtk_button_new_with_label ("Edit...");
3282   gtk_widget_show (button);
3283   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
3284   gtk_widget_set_sensitive (button, FALSE);
3285   gtk_widget_set_usize (button, 60, -2);
3286
3287   button = gtk_button_new_with_label ("Close");
3288   gtk_widget_show (button);
3289   gtk_box_pack_end (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
3290   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3291                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3292   gtk_widget_set_usize (button, 60, -2);
3293
3294   gtk_grab_add (dlg);
3295   gtk_widget_show (dlg);
3296
3297   while (loop)
3298     gtk_main_iteration ();
3299
3300   if (ret == IDOK)
3301   {
3302     GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(scripts_list));
3303
3304     GtkTreeModel* model;
3305     GtkTreeIter iter;
3306     if(gtk_tree_selection_get_selected(selection, &model, &iter))
3307     {
3308       char* script;
3309       gtk_tree_model_get(model, &iter, 0, &script, -1);
3310       RunScriptByName(script, true);
3311       g_free(script);
3312     }
3313   }
3314
3315   gtk_grab_remove (dlg);
3316   gtk_widget_destroy (dlg);
3317 }
3318
3319 // =============================================================================
3320 //  dialog 
3321
3322 int DoBSInputDlg (const char *fields[5], float values[5])
3323 {
3324   GtkWidget *dlg, *vbox, *hbox, *label, *button;
3325   GtkWidget *entries[5];
3326   int i, loop = 1, ret = IDCANCEL;
3327
3328   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3329   gtk_window_set_title (GTK_WINDOW (dlg), "BrushScript Input");
3330   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3331                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3332   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3333                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3334   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3335   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3336
3337   hbox = gtk_hbox_new (FALSE, 5);
3338   gtk_widget_show (hbox);
3339   gtk_container_add (GTK_CONTAINER (dlg), hbox);
3340   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3341
3342   vbox = gtk_vbox_new (FALSE, 5);
3343   gtk_widget_show (vbox);
3344   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
3345
3346   // Create entries and initialize them
3347   for (i = 0; i < 5; i++)
3348   {
3349     if (strlen (fields[i]) == 0)
3350       continue;
3351
3352     label = gtk_label_new (fields[i]);
3353     gtk_widget_show (label);
3354     gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
3355     gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
3356     gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3357
3358     entries[i] = gtk_entry_new ();
3359     gtk_widget_show (entries[i]);
3360     gtk_box_pack_start (GTK_BOX (vbox), entries[i], TRUE, TRUE, 0);
3361
3362     char buf[32];
3363     sprintf (buf, "%f", values[i]);
3364     gtk_entry_set_text (GTK_ENTRY (entries[i]), buf);
3365   }
3366
3367   vbox = gtk_vbox_new (FALSE, 5);
3368   gtk_widget_show (vbox);
3369   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3370
3371   button = gtk_button_new_with_label ("OK");
3372   gtk_widget_show (button);
3373   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3374   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3375                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
3376   gtk_widget_set_usize (button, 60, -2);
3377
3378   button = gtk_button_new_with_label ("Cancel");
3379   gtk_widget_show (button);
3380   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3381   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3382                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3383   gtk_widget_set_usize (button, 60, -2);
3384
3385   gtk_grab_add (dlg);
3386   gtk_widget_show (dlg);
3387
3388   while (loop)
3389     gtk_main_iteration ();
3390
3391   for (i = 0; i < 5; i++)
3392   {
3393     if (strlen (fields[i]) == 0)
3394       continue;
3395
3396     values[i] = atof (gtk_entry_get_text (GTK_ENTRY (entries[i])));
3397   }
3398
3399   gtk_grab_remove (dlg);
3400   gtk_widget_destroy (dlg);
3401
3402   return ret;
3403 }
3404
3405 // =============================================================================
3406 // TextureLayout dialog 
3407
3408 int DoTextureLayout (float *fx, float *fy)
3409 {
3410   GtkWidget *dlg, *vbox, *hbox, *table, *label, *button;
3411   GtkWidget *x, *y;
3412   int loop = 1, ret = IDCANCEL;
3413
3414   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3415   gtk_window_set_title (GTK_WINDOW (dlg), "Patch texture layout");
3416   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3417                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3418   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3419                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3420   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3421   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3422
3423   hbox = gtk_hbox_new (FALSE, 5);
3424   gtk_widget_show (hbox);
3425   gtk_container_add (GTK_CONTAINER (dlg), hbox);
3426   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3427
3428   vbox = gtk_vbox_new (FALSE, 5);
3429   gtk_widget_show (vbox);
3430   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
3431
3432   label = gtk_label_new ("Texture will be fit across the patch based\n"
3433                          "on the x and y values given. Values of 1x1\n"
3434                          "will \"fit\" the texture. 2x2 will repeat\n"
3435                          "it twice, etc.");
3436   gtk_widget_show (label);
3437   gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
3438   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3439
3440   table = gtk_table_new (2, 2, FALSE);
3441   gtk_widget_show (table);
3442   gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
3443   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
3444   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
3445  
3446   label = gtk_label_new ("Texture x:");
3447   gtk_widget_show (label);
3448   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
3449                     (GtkAttachOptions) (GTK_FILL),
3450                     (GtkAttachOptions) (0), 0, 0);
3451   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3452
3453   label = gtk_label_new ("Texture y:");
3454   gtk_widget_show (label);
3455   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
3456                     (GtkAttachOptions) (GTK_FILL),
3457                     (GtkAttachOptions) (0), 0, 0);
3458   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3459
3460   x = gtk_entry_new ();
3461   gtk_widget_show (x);
3462   gtk_table_attach (GTK_TABLE (table), x, 1, 2, 0, 1,
3463                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
3464                     (GtkAttachOptions) (0), 0, 0);
3465
3466   y = gtk_entry_new ();
3467   gtk_widget_show (y);
3468   gtk_table_attach (GTK_TABLE (table), y, 1, 2, 1, 2,
3469                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
3470                     (GtkAttachOptions) (0), 0, 0);
3471
3472   vbox = gtk_vbox_new (FALSE, 5);
3473   gtk_widget_show (vbox);
3474   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3475
3476   button = gtk_button_new_with_label ("OK");
3477   gtk_widget_show (button);
3478   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3479   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3480                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
3481   gtk_widget_set_usize (button, 60, -2);
3482
3483   button = gtk_button_new_with_label ("Cancel");
3484   gtk_widget_show (button);
3485   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3486   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3487                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3488   gtk_widget_set_usize (button, 60, -2);
3489
3490   // Initialize
3491   gtk_entry_set_text (GTK_ENTRY (x), "4.0");
3492   gtk_entry_set_text (GTK_ENTRY (y), "4.0");
3493
3494   gtk_grab_add (dlg);
3495   gtk_widget_show (dlg);
3496
3497   while (loop)
3498     gtk_main_iteration ();
3499
3500   if (ret == IDOK)
3501   {
3502     *fx = atof (gtk_entry_get_text (GTK_ENTRY (x)));
3503     *fy = atof (gtk_entry_get_text (GTK_ENTRY (y)));
3504   }
3505
3506   gtk_grab_remove (dlg);
3507   gtk_widget_destroy (dlg);
3508
3509   return ret;
3510 }
3511
3512 // =============================================================================
3513 // Name dialog 
3514
3515 char* DoNameDlg (const char* title)
3516 {
3517   GtkWidget *dlg, *vbox, *hbox, *label, *button, *entry;
3518   int loop = 1, ret = IDCANCEL;
3519   char *str;
3520
3521   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3522   gtk_window_set_title (GTK_WINDOW (dlg), title);
3523   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3524                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3525   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3526                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3527   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3528   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3529
3530   hbox = gtk_hbox_new (FALSE, 5);
3531   gtk_widget_show (hbox);
3532   gtk_container_add (GTK_CONTAINER (dlg), hbox);
3533   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3534
3535   label = gtk_label_new ("Name:");
3536   gtk_widget_show (label);
3537   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
3538
3539   entry = gtk_entry_new ();
3540   gtk_widget_show (entry);
3541   gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
3542
3543   vbox = gtk_vbox_new (FALSE, 5);
3544   gtk_widget_show (vbox);
3545   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3546
3547   button = gtk_button_new_with_label ("OK");
3548   gtk_widget_show (button);
3549   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3550   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3551                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
3552   gtk_widget_set_usize (button, 60, -2);
3553
3554   button = gtk_button_new_with_label ("Cancel");
3555   gtk_widget_show (button);
3556   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3557   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3558                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3559   gtk_widget_set_usize (button, 60, -2);
3560
3561   gtk_grab_add (dlg);
3562   gtk_widget_show (dlg);
3563
3564   while (loop)
3565     gtk_main_iteration ();
3566
3567   if (ret == IDOK)
3568     str = strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
3569   else
3570     str = NULL;
3571
3572   gtk_grab_remove (dlg);
3573   gtk_widget_destroy (dlg);
3574
3575   return str;
3576 }
3577
3578 // =============================================================================
3579 // NewProject dialog 
3580
3581 char* DoNewProjectDlg ()
3582 {
3583   GtkWidget *dlg, *vbox, *hbox, *label, *button, *entry, *check;
3584   int loop = 1, ret = IDCANCEL;
3585   char *str;
3586
3587   // start by a warning message
3588   // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=459
3589   CString msg;
3590   msg = "Are you sure you want a new project?\n";
3591   msg += "Please note that creating a new project is not the prefered way to setup GtkRadiant for mod editing.\n";
3592   msg += "Check http://www.qeradiant.com/faq/index.cgi?file=220 for more information";
3593   if (gtk_MessageBox(NULL, msg.GetBuffer(), "Confirm", MB_YESNO, "http://www.qeradiant.com/faq/index.cgi?file=220" ) == IDNO)
3594   {
3595     return NULL;
3596   }
3597
3598   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3599   gtk_window_set_title (GTK_WINDOW (dlg), "New Project");
3600   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3601                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3602   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3603                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3604   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3605   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3606
3607   hbox = gtk_hbox_new (FALSE, 10);
3608   gtk_widget_show (hbox);
3609   gtk_container_add (GTK_CONTAINER (dlg), hbox);
3610   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3611
3612   vbox = gtk_vbox_new (FALSE, 5);
3613   gtk_widget_show (vbox);
3614   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3615
3616   label = gtk_label_new ("This will create a new directory beneath your\n"
3617                          "game path based on the project name you give.");
3618   gtk_widget_show (label);
3619   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
3620   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3621
3622   label = gtk_label_new ("Project name:");
3623   gtk_widget_show (label);
3624   gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
3625   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3626   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3627
3628   entry = gtk_entry_new ();
3629   gtk_widget_show (entry);
3630   gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
3631
3632   check = gtk_check_button_new_with_label ("Include game dll files");
3633   gtk_widget_show (check);
3634   gtk_box_pack_start (GTK_BOX (vbox), check, TRUE, TRUE, 0);
3635   gtk_widget_set_sensitive (check, FALSE);
3636
3637   vbox = gtk_vbox_new (FALSE, 5);
3638   gtk_widget_show (vbox);
3639   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3640
3641   button = gtk_button_new_with_label ("OK");
3642   gtk_widget_show (button);
3643   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3644   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3645                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
3646   gtk_widget_set_usize (button, 60, -2);
3647
3648   button = gtk_button_new_with_label ("Cancel");
3649   gtk_widget_show (button);
3650   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3651   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3652                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3653   gtk_widget_set_usize (button, 60, -2);
3654
3655   gtk_grab_add (dlg);
3656   gtk_widget_show (dlg);
3657
3658   while (loop)
3659     gtk_main_iteration ();
3660
3661   if (ret == IDOK)
3662     str = strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
3663   else
3664     str = NULL;
3665
3666   gtk_grab_remove (dlg);
3667   gtk_widget_destroy (dlg);
3668
3669   return str;
3670 }
3671
3672 // =============================================================================
3673 // Text Editor dialog 
3674
3675 // master window widget
3676 static GtkWidget *text_editor = NULL;
3677 static GtkWidget *text_widget; // slave, text widget from the gtk editor
3678
3679 static gint editor_delete (GtkWidget *widget, gpointer data)
3680 {
3681   if (gtk_MessageBox (widget, "Close the shader editor ?", "Radiant", MB_YESNO) == IDNO)
3682     return TRUE;
3683
3684   gtk_widget_hide (text_editor);
3685
3686   return TRUE;
3687 }
3688
3689 static void editor_save (GtkWidget *widget, gpointer data)
3690 {
3691   FILE *f = fopen ((char*)g_object_get_data (G_OBJECT (data), "filename"), "w");
3692   gpointer text = g_object_get_data (G_OBJECT (data), "text");
3693
3694   if (f == NULL)
3695   {
3696     gtk_MessageBox (GTK_WIDGET(data), "Error saving file !");
3697     return;
3698   }
3699
3700   char *str = gtk_editable_get_chars (GTK_EDITABLE (text), 0, -1);
3701   fwrite (str, 1, strlen (str), f);
3702   fclose (f);
3703 }
3704
3705 static void editor_close (GtkWidget *widget, gpointer data)
3706 {
3707   if (gtk_MessageBox (text_editor, "Close the shader editor ?", "Radiant", MB_YESNO) == IDNO)
3708     return;
3709
3710   gtk_widget_hide (text_editor);
3711 }
3712
3713 // several attempts
3714 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=355
3715 #if 0
3716 #ifdef _WIN32
3717
3718 HWND FindEditWindow()
3719 {
3720   return FindWindow("TFormEditPadLite", NULL);
3721 }
3722
3723 HWND FindEditWindow()
3724 {
3725   HWND hwnd = FindWindow("TFormEditPadLite", NULL);
3726   if (hwnd)
3727   {
3728     hwnd = FindWindowEx(hwnd, NULL, "TPanel", NULL);
3729     if (hwnd)
3730     {
3731       hwnd = FindWindowEx(hwnd, NULL, "TPanel", NULL);
3732       if (hwnd)
3733       {
3734         hwnd = FindWindowEx(hwnd, NULL, "TEditPadEditor", NULL);
3735         if (hwnd)
3736         {
3737           hwnd = FindWindowEx(hwnd, NULL, "TWinControlProxy", NULL);
3738           return hwnd;
3739         }
3740       }
3741     }
3742   }
3743   return NULL;
3744 }
3745
3746 HWND FindEditWindow()
3747 {
3748   HWND hwnd = FindWindow("TFormEditPadLite", NULL);
3749   if (hwnd)
3750   {
3751     hwnd = FindWindowEx(hwnd, NULL, "TPanel", NULL);
3752     if (hwnd)
3753     {
3754       hwnd = FindWindowEx(hwnd, NULL, "TPanel", NULL);
3755       if (hwnd)
3756       {
3757         hwnd = FindWindowEx(hwnd, NULL, "TPanel", NULL);
3758         if (hwnd)
3759         {
3760           hwnd = FindWindowEx(hwnd, NULL, "TFrameSearchReplace", NULL);
3761           if (hwnd)
3762           {
3763             hwnd = FindWindowEx(hwnd, NULL, "TJGStringEditorControl", NULL);
3764             return hwnd;
3765           }
3766         }
3767       }
3768     }
3769   }
3770   return NULL;
3771 }
3772
3773 HWND FindEditWindow()
3774 {
3775   HWND hwnd = FindWindow("TEditPadForm", NULL);
3776   HWND hwndEdit = NULL;
3777   if (hwnd != NULL)
3778   {
3779     HWND hwndTab = FindWindowEx(hwnd, NULL, "TTabControl", NULL);
3780     if (hwndTab != NULL)
3781     {
3782       hwndEdit = FindWindowEx(hwndTab, NULL, "TRicherEdit", NULL);
3783     }
3784   }
3785   return hwndEdit;
3786 }
3787 #endif
3788 #endif // #if 0
3789
3790 static void CreateGtkTextEditor ()
3791 {
3792   GtkWidget *dlg;
3793   GtkWidget *vbox, *hbox, *button, *scr, *text;
3794
3795   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3796
3797   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3798                       GTK_SIGNAL_FUNC (editor_delete), NULL);
3799   gtk_window_set_default_size (GTK_WINDOW (dlg), 600, 300);
3800
3801   vbox = gtk_vbox_new (FALSE, 5);
3802   gtk_widget_show (vbox);
3803   gtk_container_add (GTK_CONTAINER (dlg), vbox);
3804   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
3805
3806   scr = gtk_scrolled_window_new (NULL, NULL);
3807   gtk_widget_show (scr);
3808   gtk_box_pack_start (GTK_BOX (vbox), scr, TRUE, TRUE, 0);
3809   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3810   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
3811
3812   text = gtk_text_view_new();
3813   gtk_container_add (GTK_CONTAINER (scr), text);
3814   gtk_widget_show (text);
3815   g_object_set_data (G_OBJECT (dlg), "text", text);
3816   gtk_text_view_set_editable (GTK_TEXT_VIEW(text), TRUE);
3817
3818   hbox = gtk_hbox_new (FALSE, 5);
3819   gtk_widget_show (hbox);
3820   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
3821
3822   button = gtk_button_new_with_label ("Close");
3823   gtk_widget_show (button);
3824   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
3825   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3826                       GTK_SIGNAL_FUNC (editor_close), dlg);
3827   gtk_widget_set_usize (button, 60, -2);
3828
3829   button = gtk_button_new_with_label ("Save");
3830   gtk_widget_show (button);
3831   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
3832   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3833                       GTK_SIGNAL_FUNC (editor_save), dlg);
3834   gtk_widget_set_usize (button, 60, -2);
3835
3836   text_editor = dlg;
3837   text_widget = text;
3838 }
3839
3840 static void DoGtkTextEditor (const char* filename, guint cursorpos)
3841 {
3842   if (!text_editor)
3843     CreateGtkTextEditor(); // build it the first time we need it
3844
3845   // Load file
3846   FILE *f = fopen (filename, "r");
3847
3848   if (f == NULL)
3849   {
3850     Sys_Printf("Unable to load file %s in shader editor.\n", filename);
3851     gtk_widget_hide (text_editor);
3852   }
3853   else
3854   {
3855     fseek (f, 0, SEEK_END);
3856     int len = ftell (f);
3857     void *buf = qmalloc (len);
3858     void *old_filename;
3859
3860     rewind (f);
3861     fread (buf, 1, len, f);
3862
3863     gtk_window_set_title (GTK_WINDOW (text_editor), filename);
3864
3865     GtkTextBuffer* text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_widget));
3866     gtk_text_buffer_set_text(text_buffer, (char*)buf, len);
3867
3868     old_filename = g_object_get_data (G_OBJECT (text_editor), "filename");
3869     if (old_filename)
3870       free(old_filename);
3871     g_object_set_data (G_OBJECT (text_editor), "filename", strdup (filename));
3872
3873     // trying to show later
3874     gtk_widget_show (text_editor);
3875
3876 #ifdef _WIN32
3877     while (gtk_events_pending ())
3878       gtk_main_iteration ();
3879 #endif
3880
3881     // only move the cursor if it's not exceeding the size..
3882     // NOTE: this is erroneous, cursorpos is the offset in bytes, not in characters
3883     // len is the max size in bytes, not in characters either, but the character count is below that limit..
3884     // thinking .. the difference between character count and byte count would be only because of CR/LF?
3885     {
3886       GtkTextIter text_iter;
3887       // character offset, not byte offset
3888       gtk_text_buffer_get_iter_at_offset(text_buffer, &text_iter, cursorpos);
3889       gtk_text_buffer_place_cursor(text_buffer, &text_iter);
3890     }
3891
3892 #ifdef _WIN32
3893     gtk_widget_queue_draw(text_widget);
3894 #endif
3895
3896     free (buf);
3897     fclose (f);
3898   }
3899 }
3900
3901 void DoTextEditor (const char* filename, int cursorpos)
3902 {
3903   CString strEditCommand;
3904 #ifdef _WIN32
3905   if (g_PrefsDlg.m_bUseWin32Editor)
3906   {
3907     Sys_Printf("opening file '%s' (line %d info ignored)\n", filename);
3908     ShellExecute((HWND)GDK_WINDOW_HWND (g_pParentWnd->m_pWidget->window), "open", filename, NULL, NULL, SW_SHOW );
3909     return;
3910   }
3911 #else
3912   // check if a custom editor is set
3913   if((g_PrefsDlg.m_bUseCustomEditor) && (g_PrefsDlg.m_strEditorCommand.GetLength() > 0))
3914   {
3915     strEditCommand = g_PrefsDlg.m_strEditorCommand;
3916     strEditCommand += " \"";
3917     strEditCommand += filename;
3918     strEditCommand += "\"";
3919     
3920     Sys_Printf("Launching: %s\n", strEditCommand.GetBuffer());
3921     // note: linux does not return false if the command failed so it will assume success
3922     if (Q_Exec(NULL, (char *)strEditCommand.GetBuffer(), NULL, true) == false)
3923     {
3924       Sys_FPrintf(SYS_WRN, "Warning: Failed to execute %s, using default\n", strEditCommand.GetBuffer());
3925     }
3926     else
3927     {
3928       // the command (appeared) to run successfully, no need to do anything more
3929       return;
3930     }
3931   }
3932 #endif
3933   
3934   DoGtkTextEditor (filename, cursorpos);
3935
3936   // old win32 code with EditPad bindings, broken
3937   // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=355
3938 #if 0
3939   strEditCommand = g_strAppPath.GetBuffer();
3940   strEditCommand += "editpad.exe";
3941   strEditCommand += " \"";
3942   strEditCommand += filename;
3943   strEditCommand += "\"";
3944   if (Q_Exec(NULL, (char *)strEditCommand.GetBuffer(), NULL, true) == false)
3945   {
3946     Sys_FPrintf(SYS_WRN, "WARNING: Gtk shader editor is not fully functional on windows in general and unstable on win98 in particular.\n");
3947     Sys_FPrintf(SYS_WRN, "  you can use EditPad instead (install it in Radiant's directory): http://www.qeradiant.com/?data=files&files_dir=18\n");
3948     DoGtkTextEditor (filename, cursorpos);
3949   }
3950   else
3951   {
3952     // TTimo: we used to call Delay here, to continue processing messages. But it seems to induce a lot of instabilities.
3953     // so now the user will simply have to wait.
3954     Sleep( 1500 );
3955
3956         // now grab the edit window and scroll to the shader we want to edit
3957     HWND hwndEdit = FindEditWindow();
3958
3959     if (hwndEdit != NULL)
3960       PostMessage(hwndEdit, EM_SETSEL, cursorpos, cursorpos);
3961     else
3962       Sys_Printf("Unable to load shader editor.\n");
3963   }
3964 #endif
3965 }
3966
3967 // =============================================================================
3968 // Light Intensity dialog 
3969
3970 int DoLightIntensityDlg (int *intensity)
3971 {
3972   GtkWidget *dlg, *vbox, *hbox, *label, *button, *entry;
3973   int loop = 1, ret = IDCANCEL;
3974
3975   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3976   gtk_window_set_title (GTK_WINDOW (dlg), "Light intensity");
3977   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3978                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3979   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3980                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3981   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3982   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3983
3984   GtkAccelGroup *accel_group = gtk_accel_group_new ();
3985   gtk_window_add_accel_group (GTK_WINDOW (dlg), accel_group);
3986
3987   hbox = gtk_hbox_new (FALSE, 5);
3988   gtk_widget_show (hbox);
3989   gtk_container_add (GTK_CONTAINER (dlg), hbox);
3990   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3991
3992   vbox = gtk_vbox_new (FALSE, 5);
3993   gtk_widget_show (vbox);
3994   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
3995
3996   label = gtk_label_new ("ESC for default, ENTER to validate");
3997   gtk_widget_show (label);
3998   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
3999
4000   entry = gtk_entry_new ();
4001   gtk_widget_show (entry);
4002   gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4003
4004   vbox = gtk_vbox_new (FALSE, 5);
4005   gtk_widget_show (vbox);
4006   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
4007
4008   button = gtk_button_new_with_label ("OK");
4009   gtk_widget_show (button);
4010   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
4011   gtk_signal_connect (GTK_OBJECT (button), "clicked",
4012                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
4013   gtk_widget_add_accelerator (button, "clicked", accel_group,
4014                               GDK_Return, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
4015   gtk_widget_set_usize (button, 60, -2);
4016
4017   button = gtk_button_new_with_label ("Cancel");
4018   gtk_widget_show (button);
4019   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
4020   gtk_signal_connect (GTK_OBJECT (button), "clicked",
4021                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
4022   gtk_widget_add_accelerator (button, "clicked", accel_group,
4023                               GDK_Escape, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
4024   gtk_widget_set_usize (button, 60, -2);
4025
4026   char buf[16];
4027   sprintf (buf, "%d", *intensity);
4028   gtk_entry_set_text (GTK_ENTRY (entry), buf);
4029
4030   gtk_grab_add (dlg);
4031   gtk_widget_show (dlg);
4032
4033   while (loop)
4034     gtk_main_iteration ();
4035
4036   if (ret == IDOK)
4037     *intensity = atoi (gtk_entry_get_text (GTK_ENTRY (entry)));
4038
4039   gtk_grab_remove (dlg);
4040   gtk_widget_destroy (dlg);
4041
4042   return ret;
4043 }