]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/gtkdlgs.cpp
more eol-style
[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_CheckProjectEntity();
1295
1296     QE_SaveProject( g_PrefsDlg.m_strLastProject.GetBuffer() );
1297   }
1298
1299   gtk_grab_remove (project);
1300   gtk_widget_destroy (project);
1301 }
1302
1303 // =============================================================================
1304 // MapInfo dialog
1305
1306 void DoMapInfo ()
1307 {
1308   static GtkWidget *dlg;
1309   GtkWidget *vbox, *vbox2, *hbox, *table, *button, *label, *scr;
1310   GtkWidget *brushes_entry, *entities_entry, *net_entry;
1311   int loop = 1, ret = IDCANCEL;
1312
1313   if (dlg != NULL)
1314     return;
1315
1316   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1317
1318   load_window_pos(dlg, g_PrefsDlg.mWindowInfo.posMapInfoWnd);
1319
1320   gtk_window_set_title (GTK_WINDOW (dlg), "Map Info");
1321   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
1322                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
1323   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
1324                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
1325   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
1326   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
1327
1328   vbox = gtk_vbox_new (FALSE, 5);
1329   gtk_widget_show (vbox);
1330   gtk_container_add (GTK_CONTAINER (dlg), vbox);
1331   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
1332
1333   hbox = gtk_hbox_new (FALSE, 5);
1334   gtk_widget_show (hbox);
1335   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
1336
1337   table = gtk_table_new (3, 2, FALSE);
1338   gtk_widget_show (table);
1339   gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
1340   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
1341   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
1342
1343   brushes_entry = gtk_entry_new ();
1344   gtk_widget_show (brushes_entry);
1345   gtk_table_attach (GTK_TABLE (table), brushes_entry, 1, 2, 0, 1,
1346                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1347                     (GtkAttachOptions) (0), 0, 0);
1348   gtk_entry_set_editable (GTK_ENTRY (brushes_entry), FALSE);
1349
1350   entities_entry = gtk_entry_new ();
1351   gtk_widget_show (entities_entry);
1352   gtk_table_attach (GTK_TABLE (table), entities_entry, 1, 2, 1, 2,
1353                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1354                     (GtkAttachOptions) (0), 0, 0);
1355   gtk_entry_set_editable (GTK_ENTRY (entities_entry), FALSE);
1356
1357   net_entry = gtk_entry_new ();
1358   gtk_widget_show (net_entry);
1359   gtk_table_attach (GTK_TABLE (table), net_entry, 1, 2, 2, 3,
1360                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1361                     (GtkAttachOptions) (0), 0, 0);
1362   gtk_entry_set_editable (GTK_ENTRY (net_entry), FALSE);
1363
1364   label = gtk_label_new ("Total Brushes");
1365   gtk_widget_show (label);
1366   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
1367                     (GtkAttachOptions) (GTK_FILL),
1368                     (GtkAttachOptions) (0), 0, 0);
1369   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1370
1371   label = gtk_label_new ("Total Entities");
1372   gtk_widget_show (label);
1373   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
1374                     (GtkAttachOptions) (GTK_FILL),
1375                     (GtkAttachOptions) (0), 0, 0);
1376   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1377
1378   label = gtk_label_new ("Net brush count\n(non entity)");
1379   gtk_widget_show (label);
1380   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
1381                     (GtkAttachOptions) (GTK_FILL),
1382                     (GtkAttachOptions) (0), 0, 0);
1383   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1384
1385   vbox2 = gtk_vbox_new (FALSE, 5);
1386   gtk_widget_show (vbox2);
1387   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
1388
1389   button = gtk_button_new_with_label ("Close");
1390   gtk_widget_show (button);
1391   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
1392   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1393                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
1394   gtk_widget_set_usize (button, 60, -2);
1395
1396   label = gtk_label_new ("Entity breakdown");
1397   gtk_widget_show (label);
1398   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
1399   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1400
1401   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
1402   gtk_widget_show (scr);
1403   gtk_box_pack_start (GTK_BOX (vbox), scr, TRUE, TRUE, 0);
1404   gtk_container_set_border_width (GTK_CONTAINER (scr), 5);
1405   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1406
1407   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scr), GTK_SHADOW_IN);
1408
1409   GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
1410
1411   {
1412     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1413     gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(view), TRUE);
1414
1415     {
1416       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1417       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Entity", renderer, "text", 0, NULL);
1418       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1419       gtk_tree_view_column_set_sort_column_id(column, 0);
1420     }
1421
1422     {
1423       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1424       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Count", renderer, "text", 1, NULL);
1425       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1426       gtk_tree_view_column_set_sort_column_id(column, 1);
1427     }
1428
1429     gtk_widget_show(view);
1430
1431     gtk_container_add(GTK_CONTAINER (scr), view);
1432   }
1433
1434   // Initialize fields
1435   int TotalBrushes = 0, TotalEntities = 0, Net = 0;
1436
1437   for (brush_t* pBrush = active_brushes.next; pBrush != &active_brushes; pBrush = pBrush->next)
1438   {
1439     TotalBrushes++;
1440     if (pBrush->owner == world_entity)
1441       Net++;
1442   }
1443
1444   typedef struct
1445   {
1446     const char *name;
1447     int count;
1448   } map_t;
1449
1450   GSList *l, *entitymap = NULL;
1451   map_t *entry;
1452
1453   for (entity_t* pEntity = entities.next; pEntity != &entities; pEntity=pEntity->next)
1454   {
1455     TotalEntities++;
1456     bool add = true;
1457
1458     for (l = entitymap; l; l = g_slist_next (l))
1459     {
1460       entry = (map_t*)l->data;
1461
1462       if (strcmp (entry->name, pEntity->eclass->name) == 0)
1463       {
1464               entry->count++;
1465               add = false;
1466               break;
1467       }
1468     }
1469
1470     if (add)
1471     {
1472       entry = (map_t*)qmalloc (sizeof (map_t));
1473       entry->name = pEntity->eclass->name;
1474       entry->count = 1;
1475       entitymap = g_slist_append (entitymap, entry);
1476     }
1477   }
1478
1479   while (entitymap)
1480   {
1481     entry = (map_t*)entitymap->data;
1482     char tmp[16];
1483     sprintf (tmp, "%d", entry->count);
1484     GtkTreeIter iter;
1485     gtk_list_store_append(GTK_LIST_STORE(store), &iter);
1486     gtk_list_store_set(GTK_LIST_STORE(store), &iter, 0, entry->name, 1, tmp, -1);
1487     free (entry);
1488     entitymap = g_slist_remove (entitymap, entry);
1489   }
1490
1491   g_object_unref(G_OBJECT(store));
1492
1493   char tmp[16];
1494   sprintf (tmp, "%d", TotalBrushes);
1495   gtk_entry_set_text (GTK_ENTRY (brushes_entry), tmp);
1496   sprintf (tmp, "%d", TotalEntities);
1497   gtk_entry_set_text (GTK_ENTRY (entities_entry), tmp);
1498   sprintf (tmp, "%d", Net);
1499   gtk_entry_set_text (GTK_ENTRY (net_entry), tmp);
1500
1501   gtk_grab_add (dlg);
1502   gtk_widget_show (dlg);
1503
1504   while (loop)
1505     gtk_main_iteration ();
1506
1507   // save before exit
1508   save_window_pos(dlg, g_PrefsDlg.mWindowInfo.posMapInfoWnd);
1509
1510   gtk_grab_remove (dlg);
1511   gtk_widget_destroy (dlg);
1512   dlg = NULL;
1513 }
1514
1515 // =============================================================================
1516 // Entity List dialog
1517
1518 static void entitylist_select (GtkWidget *widget, gpointer data)
1519 {
1520   GtkTreeView* view = GTK_TREE_VIEW(g_object_get_data (G_OBJECT (data), "entities"));
1521
1522   GtkTreeSelection* selection = gtk_tree_view_get_selection(view);
1523
1524   GtkTreeModel* model;
1525   GtkTreeIter selected;
1526   if(gtk_tree_selection_get_selected(selection, &model, &selected))
1527   {
1528     entity_t* pEntity;
1529     gtk_tree_model_get(model, &selected, 1, &pEntity, -1);
1530
1531     if (pEntity)
1532     {
1533       for (epair_t* pEpair = pEntity->epairs; pEpair; pEpair = pEpair->next)
1534       {
1535               Select_Deselect ();
1536               Select_Brush (pEntity->brushes.onext);
1537               Sys_UpdateWindows(W_ALL);
1538       }
1539     }
1540   }
1541 }
1542
1543 static gint entitylist_click (GtkWidget *widget, GdkEventButton *event, gpointer data)
1544 {
1545   if (event->type == GDK_2BUTTON_PRESS)
1546   {
1547     entitylist_select (NULL, data);
1548     return TRUE;
1549   }
1550   return FALSE;
1551 }
1552
1553 static void entitylist_selection_changed(GtkTreeSelection* selection, gpointer data)
1554 {
1555   GtkListStore* store = GTK_LIST_STORE (g_object_get_data (G_OBJECT (data), "keyvalues"));
1556
1557   gtk_list_store_clear(store);
1558
1559   GtkTreeModel* model;
1560   GtkTreeIter selected;
1561   if(gtk_tree_selection_get_selected(selection, &model, &selected))
1562   {
1563     entity_t* pEntity;
1564     gtk_tree_model_get(model, &selected, 1, &pEntity, -1);
1565
1566     if (pEntity)
1567     {
1568       for (epair_t* pEpair = pEntity->epairs; pEpair; pEpair = pEpair->next)
1569       {
1570         GtkTreeIter appended;
1571         gtk_list_store_append(store, &appended);
1572         gtk_list_store_set(store, &appended, 0, pEpair->key, 1, pEpair->value, -1);
1573       }
1574     }
1575   }
1576 }
1577
1578 void DoEntityList ()
1579 {
1580   static GtkWidget *dlg;
1581   GtkWidget *vbox, *hbox, *hbox2, *button, *scr;
1582   int loop = 1, ret = IDCANCEL;
1583
1584   if (dlg != NULL)
1585     return;
1586
1587   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1588
1589   load_window_pos (dlg, g_PrefsDlg.mWindowInfo.posEntityInfoWnd);
1590
1591   gtk_window_set_title (GTK_WINDOW (dlg), "Entities");
1592   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
1593                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
1594   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
1595                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
1596   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
1597   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
1598
1599   hbox = gtk_hbox_new (TRUE, 5);
1600   gtk_widget_show (hbox);
1601   gtk_container_add (GTK_CONTAINER (dlg), hbox);
1602   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
1603
1604   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
1605   gtk_widget_show (scr);
1606   gtk_box_pack_start (GTK_BOX (hbox), scr, TRUE, TRUE, 0);
1607   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1608   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
1609
1610   {
1611     GtkTreeStore* store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
1612
1613     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1614     g_signal_connect(G_OBJECT(view), "button_press_event", G_CALLBACK(entitylist_click), dlg);
1615     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
1616
1617     {
1618       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1619       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);
1620       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1621     }
1622
1623     {
1624       GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
1625       g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(entitylist_selection_changed), dlg);
1626     }
1627
1628     gtk_widget_show(view);
1629
1630     gtk_container_add(GTK_CONTAINER (scr), view);
1631     g_object_set_data (G_OBJECT (dlg), "entities", view);
1632
1633     {
1634       {
1635         GtkTreeIter child;
1636         gtk_tree_store_append(store, &child, NULL);
1637         gtk_tree_store_set(store, &child, 0, world_entity->eclass->name, 1, world_entity, -1);
1638       }
1639
1640       GSList *l, *entitymap = NULL;
1641       typedef struct
1642       {
1643         GtkTreeIter node;
1644         const char *name;
1645       } map_t;
1646       map_t *entry;
1647
1648       for (entity_t* pEntity=entities.next; pEntity != &entities; pEntity=pEntity->next)
1649       {
1650         GtkTreeIter parent;
1651         bool found = false;
1652
1653         for (l = entitymap; l; l = g_slist_next (l))
1654         {
1655           entry = (map_t*)l->data;
1656
1657           if (strcmp (entry->name, pEntity->eclass->name) == 0)
1658           {
1659                   parent = entry->node;
1660                   found = true;
1661                   break;
1662           }
1663         }
1664
1665         if (!found)
1666         {
1667           gtk_tree_store_append(store, &parent, NULL);
1668           gtk_tree_store_set(store, &parent, 0, pEntity->eclass->name, 1, NULL, -1);
1669
1670           entry = (map_t*)malloc (sizeof(map_t));
1671           entitymap = g_slist_append (entitymap, entry);
1672           entry->name = pEntity->eclass->name;
1673           entry->node = parent;
1674         }
1675
1676         GtkTreeIter child;
1677         gtk_tree_store_append(store, &child, &parent);
1678         gtk_tree_store_set(store, &child, 0, pEntity->eclass->name, 1, pEntity, -1);
1679       }
1680
1681       while (entitymap)
1682       {
1683         free (entitymap->data);
1684         entitymap = g_slist_remove (entitymap, entitymap->data);
1685       }
1686     }
1687     
1688     g_object_unref(G_OBJECT(store));
1689   }
1690
1691   vbox = gtk_vbox_new (FALSE, 5);
1692   gtk_widget_show (vbox);
1693   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1694
1695   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
1696   gtk_widget_show (scr);
1697   gtk_box_pack_start (GTK_BOX (vbox), scr, TRUE, TRUE, 0);
1698   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1699   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
1700
1701   {
1702     GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
1703
1704     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1705
1706     {
1707       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1708       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", 0, NULL);
1709       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1710     }
1711
1712     {
1713       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
1714       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Value", renderer, "text", 1, NULL);
1715       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
1716     }
1717
1718     gtk_widget_show(view);
1719
1720     g_object_set_data(G_OBJECT(dlg), "keyvalues", store);
1721     gtk_container_add(GTK_CONTAINER (scr), view);
1722     
1723     g_object_unref(G_OBJECT(store));
1724   }
1725
1726   hbox2 = gtk_hbox_new (FALSE, 5);
1727   gtk_widget_show (hbox2);
1728   gtk_box_pack_start (GTK_BOX (vbox), hbox2, TRUE, TRUE, 0);
1729   
1730   button = gtk_button_new_with_label ("Select");
1731   gtk_widget_show (button);
1732   gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
1733   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1734                       GTK_SIGNAL_FUNC (entitylist_select), dlg);
1735   gtk_widget_set_usize (button, 60, -2);
1736
1737   button = gtk_button_new_with_label ("Close");
1738   gtk_widget_show (button);
1739   gtk_box_pack_end (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
1740   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1741                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
1742   gtk_widget_set_usize (button, 60, -2);
1743
1744   gtk_grab_add (dlg);
1745   gtk_widget_show (dlg);
1746
1747   while (loop)
1748     gtk_main_iteration ();
1749
1750   save_window_pos (dlg, g_PrefsDlg.mWindowInfo.posMapInfoWnd);
1751
1752   gtk_grab_remove (dlg);
1753   gtk_widget_destroy (dlg);
1754
1755   dlg = NULL;
1756 }
1757
1758 // =============================================================================
1759 // Rotate dialog
1760
1761 static void rotatedlg_apply (GtkWidget *widget, gpointer data)
1762 {
1763   GtkSpinButton *spin;
1764   float f;
1765
1766   spin = GTK_SPIN_BUTTON (g_object_get_data (G_OBJECT (data), "x"));
1767   f = gtk_spin_button_get_value_as_float (spin);
1768   if (f != 0.0)
1769     Select_RotateAxis(0,f);
1770   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), 0.0f); // reset to 0 on Apply
1771   
1772   spin = GTK_SPIN_BUTTON (g_object_get_data (G_OBJECT (data), "y"));
1773   f = gtk_spin_button_get_value_as_float (spin);
1774   if (f != 0.0)
1775     Select_RotateAxis(1,f);
1776   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), 0.0f);
1777   
1778   spin = GTK_SPIN_BUTTON (g_object_get_data (G_OBJECT (data), "z"));
1779   f = gtk_spin_button_get_value_as_float (spin);
1780   if (f != 0.0)
1781     Select_RotateAxis(2,f);
1782   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), 0.0f);
1783 }
1784
1785 void DoRotateDlg ()
1786 {
1787   GtkWidget *dlg, *hbox, *vbox, *table, *label, *button;
1788   GtkWidget *x, *y, *z;
1789   GtkObject *adj;
1790   int loop = 1, ret = IDCANCEL;
1791
1792   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1793   gtk_window_set_title (GTK_WINDOW (dlg), "Arbitrary rotation");
1794   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
1795                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
1796   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
1797                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
1798   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
1799   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
1800
1801   hbox = gtk_hbox_new (FALSE, 5);
1802   gtk_widget_show (hbox);
1803   gtk_container_add (GTK_CONTAINER (dlg), hbox);
1804   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
1805  
1806   table = gtk_table_new (3, 2, FALSE);
1807   gtk_widget_show (table);
1808   gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
1809   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
1810   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
1811  
1812   label = gtk_label_new ("  X  ");
1813   gtk_widget_show (label);
1814   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
1815                     (GtkAttachOptions) (0),
1816                     (GtkAttachOptions) (0), 0, 0);
1817
1818   label = gtk_label_new ("  Y  ");
1819   gtk_widget_show (label);
1820   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
1821                     (GtkAttachOptions) (0),
1822                     (GtkAttachOptions) (0), 0, 0);
1823  
1824   label = gtk_label_new ("  Z  ");
1825
1826   gtk_widget_show (label);
1827   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
1828                     (GtkAttachOptions) (0),
1829                     (GtkAttachOptions) (0), 0, 0);
1830  
1831   adj = gtk_adjustment_new (0, -359, 359, 1, 10, 10);
1832   x = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);
1833   g_object_set_data (G_OBJECT (dlg), "x", x);
1834   gtk_widget_show (x);
1835   gtk_table_attach (GTK_TABLE (table), x, 1, 2, 0, 1,
1836                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1837                     (GtkAttachOptions) (0), 0, 0);
1838   gtk_widget_set_usize (x, 60, -2);
1839   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (x), TRUE);
1840  
1841   adj = gtk_adjustment_new (0, -359, 359, 1, 10, 10);
1842   y = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);
1843   g_object_set_data (G_OBJECT (dlg), "y", y);
1844   gtk_widget_show (y);
1845   gtk_table_attach (GTK_TABLE (table), y, 1, 2, 1, 2,
1846                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1847                     (GtkAttachOptions) (0), 0, 0);
1848   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (y), TRUE);
1849  
1850   adj = gtk_adjustment_new (0, -359, 359, 1, 10, 10);
1851   z = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);
1852   g_object_set_data (G_OBJECT (dlg), "z", z);
1853   gtk_widget_show (z);
1854   gtk_table_attach (GTK_TABLE (table), z, 1, 2, 2, 3,
1855                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
1856                     (GtkAttachOptions) (0), 0, 0);
1857   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (z), TRUE);
1858  
1859   vbox = gtk_vbox_new (FALSE, 5);
1860   gtk_widget_show (vbox);
1861   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1862  
1863   button = gtk_button_new_with_label ("OK");
1864   gtk_widget_show (button);
1865   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1866   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1867                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
1868   gtk_widget_set_usize (button, 60, -2);
1869  
1870   button = gtk_button_new_with_label ("Cancel");
1871   gtk_widget_show (button);
1872   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1873   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1874                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
1875  
1876   button = gtk_button_new_with_label ("Apply");
1877   gtk_widget_show (button);
1878   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1879   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1880                       GTK_SIGNAL_FUNC (rotatedlg_apply), dlg);
1881
1882   gtk_grab_add (dlg);
1883   gtk_widget_show (dlg);
1884
1885   while (loop)
1886     gtk_main_iteration ();
1887
1888   if (ret == IDOK)
1889     rotatedlg_apply (button, dlg);
1890
1891   gtk_grab_remove (dlg);
1892   gtk_widget_destroy (dlg);
1893 }
1894
1895 // =============================================================================
1896 // Gamma dialog
1897
1898 void DoGamma ()
1899 {
1900   GtkWidget *dlg, *vbox, *hbox, *label, *button, *entry;
1901   int loop = 1, ret = IDCANCEL;
1902
1903   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1904   gtk_window_set_title (GTK_WINDOW (dlg), "Gamma");
1905   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
1906                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
1907   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
1908                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
1909   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
1910   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
1911
1912   hbox = gtk_hbox_new (FALSE, 5);
1913   gtk_widget_show (hbox);
1914   gtk_container_add (GTK_CONTAINER (dlg), hbox);
1915   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
1916
1917   vbox = gtk_vbox_new (FALSE, 5);
1918   gtk_widget_show (vbox);
1919   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1920
1921   entry = gtk_entry_new ();
1922   gtk_widget_show (entry);
1923   gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
1924
1925   label = gtk_label_new ("0.0 is brightest\n1.0 is darkest");
1926   gtk_widget_show (label);
1927   gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
1928
1929   label = gtk_label_new ("You must restart for the\nsettings to take effect");
1930   gtk_widget_show (label);
1931   gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
1932
1933   vbox = gtk_vbox_new (FALSE, 5);
1934   gtk_widget_show (vbox);
1935   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1936
1937   button = gtk_button_new_with_label ("OK");
1938   gtk_widget_show (button);
1939   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1940   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1941                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
1942   gtk_widget_set_usize (button, 60, -2);
1943  
1944   button = gtk_button_new_with_label ("Cancel");
1945   gtk_widget_show (button);
1946   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1947   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1948                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
1949
1950   // Initialize dialog
1951   char buf[16];
1952   sprintf (buf, "%1.1f", g_qeglobals.d_savedinfo.fGamma);
1953   gtk_entry_set_text (GTK_ENTRY (entry), buf);
1954
1955   gtk_grab_add (dlg);
1956   gtk_widget_show (dlg);
1957
1958   while (loop)
1959     gtk_main_iteration ();
1960
1961   if (ret == IDOK)
1962     g_qeglobals.d_savedinfo.fGamma = g_strtod (gtk_entry_get_text (GTK_ENTRY (entry)), NULL);
1963
1964   gtk_grab_remove (dlg);
1965   gtk_widget_destroy (dlg);
1966 }
1967
1968 // =============================================================================
1969 // Find Brush Dialog
1970
1971 // helper function to walk through the active brushes only and drop the regioned out ones
1972 bool WalkRegionBrush (brush_t **b, entity_t *e)
1973 {
1974   brush_t *b2;
1975   do
1976   {
1977     for(b2=active_brushes.next ; b2 != &active_brushes ; b2=b2->next)
1978     {
1979       if (b2==*b)
1980         break; // this is an active brush
1981     }
1982     if (b2==&active_brushes)
1983     {
1984       // this is a regioned out brush
1985       *b = (*b)->onext;
1986       if (*b == &e->brushes)
1987       {
1988         Sys_Status ("No such brush", 0);
1989         return false;
1990       }
1991     }
1992   } while (b2==&active_brushes);
1993   return true;
1994 }
1995
1996 void SelectBrush (int entitynum, int brushnum)
1997 {
1998   entity_t *e;
1999   brush_t *b;
2000   int i;
2001
2002   // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503
2003   // making this work when regioning is on too
2004
2005   if (entitynum == 0)
2006     e = world_entity;
2007   else
2008   {
2009     e = entities.next;
2010     while (--entitynum)
2011     {
2012       e = e->next;
2013       if (e == &entities)
2014       {
2015         Sys_Status ("No such entity", 0);
2016         return;
2017       }
2018       if (region_active)
2019       {
2020         // we need to make sure we walk to the next 'active' entity to have a valid --entitynum
2021         // that is, find a brush that belongs to this entity in the active brushes
2022         do
2023         {
2024           for (b = active_brushes.next ; b != &active_brushes ; b=b->next)
2025           {
2026             if (b->owner == e)
2027               break; // this is an active entity
2028           }
2029           if (b==&active_brushes)
2030           {
2031             // this is a regioned out entity
2032             e = e->next;        
2033             // don't walk past the end either
2034             if (e == &entities)
2035             {
2036               Sys_Status ("No such entity", 0);
2037               return;
2038             }
2039           }
2040         } while(b==&active_brushes);
2041       }
2042     }
2043   }
2044
2045   b = e->brushes.onext;
2046   if (b == &e->brushes)
2047   {
2048     Sys_Status ("No such brush", 0);
2049     return;
2050   }
2051   if (region_active)
2052   {
2053     if (!WalkRegionBrush(&b, e))
2054       return;
2055   }
2056
2057   while (brushnum--)
2058   {
2059     b = b->onext;
2060     if (b == &e->brushes)
2061     {
2062       Sys_Status ("No such brush", 0);
2063       return;
2064     }
2065     if (region_active)
2066     {
2067       if (!WalkRegionBrush(&b, e))
2068         return;
2069     }
2070   }
2071
2072   Brush_RemoveFromList (b);
2073   Brush_AddToList (b, &selected_brushes);
2074
2075   Sys_UpdateWindows (W_ALL);
2076   for (i = 0; i < 3; i++)
2077   {
2078     if (g_pParentWnd->GetXYWnd())
2079       g_pParentWnd->GetXYWnd()->GetOrigin()[i] = (b->mins[i] + b->maxs[i])/2;
2080
2081     if (g_pParentWnd->GetXZWnd())
2082       g_pParentWnd->GetXZWnd()->GetOrigin()[i] = (b->mins[i] + b->maxs[i])/2;
2083     
2084     if (g_pParentWnd->GetYZWnd())
2085       g_pParentWnd->GetYZWnd()->GetOrigin()[i] = (b->mins[i] + b->maxs[i])/2;
2086   }
2087
2088   Sys_Status ("Selected", 0);
2089 }
2090
2091 static void GetSelectionIndex (int *ent, int *brush)
2092 {
2093   brush_t *b, *b2;
2094   entity_t *entity;
2095
2096   *ent = *brush = 0;
2097
2098   b = selected_brushes.next;
2099   if (b == &selected_brushes)
2100     return;
2101
2102   // find entity
2103   if (b->owner != world_entity)
2104   {
2105     (*ent)++;
2106     for (entity = entities.next; entity != &entities; entity=entity->next, (*ent)++)
2107       ;
2108   }
2109
2110   // find brush
2111   for (b2=b->owner->brushes.onext; b2 != b && b2 != &b->owner->brushes; b2=b2->onext, (*brush)++)
2112     ;
2113 }
2114
2115 void DoFind ()
2116 {
2117   GtkWidget *dlg, *vbox, *hbox, *table, *label, *button, *entity, *brush;
2118   int loop = 1, ret = IDCANCEL;
2119
2120   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2121   gtk_window_set_title (GTK_WINDOW (dlg), "Find Brush");
2122   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2123                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2124   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2125                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2126   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2127   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2128
2129   vbox = gtk_vbox_new (FALSE, 5);
2130   gtk_widget_show (vbox);
2131   gtk_container_add (GTK_CONTAINER (dlg), vbox);
2132   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
2133
2134   table = gtk_table_new (2, 2, FALSE);
2135   gtk_widget_show (table);
2136   gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
2137   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2138   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2139  
2140   label = gtk_label_new ("Entity number");
2141   gtk_widget_show (label);
2142   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2143                     (GtkAttachOptions) (0),
2144                     (GtkAttachOptions) (0), 0, 0);
2145
2146   label = gtk_label_new ("Brush number");
2147   gtk_widget_show (label);
2148   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
2149                     (GtkAttachOptions) (0),
2150                     (GtkAttachOptions) (0), 0, 0);
2151
2152   entity = gtk_entry_new ();
2153   gtk_widget_show (entity);
2154   gtk_table_attach (GTK_TABLE (table), entity, 1, 2, 0, 1,
2155                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2156                     (GtkAttachOptions) (0), 0, 0);
2157
2158   brush = gtk_entry_new ();
2159   gtk_widget_show (brush);
2160   gtk_table_attach (GTK_TABLE (table), brush, 1, 2, 1, 2,
2161                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2162                     (GtkAttachOptions) (0), 0, 0);
2163
2164   hbox = gtk_hbox_new (FALSE, 5);
2165   gtk_widget_show (hbox);
2166   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
2167
2168   button = gtk_button_new_with_label ("OK");
2169   gtk_widget_show (button);
2170   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
2171   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2172                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2173   gtk_widget_set_usize (button, 60, -2);
2174  
2175   button = gtk_button_new_with_label ("Cancel");
2176   gtk_widget_show (button);
2177   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
2178   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2179                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
2180
2181   // Initialize dialog
2182   char buf[16];
2183   int ent, br;
2184
2185   GetSelectionIndex (&ent, &br);
2186   sprintf (buf, "%i", ent);
2187   gtk_entry_set_text (GTK_ENTRY (entity), buf);
2188   sprintf (buf, "%i", br);
2189   gtk_entry_set_text (GTK_ENTRY (brush), buf);
2190
2191   gtk_grab_add (dlg);
2192   gtk_widget_show (dlg);
2193
2194   while (loop)
2195     gtk_main_iteration ();
2196
2197   if (ret == IDOK)
2198   {
2199     const char *entstr = gtk_entry_get_text (GTK_ENTRY (entity));
2200     const char *brushstr = gtk_entry_get_text (GTK_ENTRY (brush));
2201     SelectBrush (atoi(entstr), atoi(brushstr));
2202   }
2203
2204   gtk_grab_remove (dlg);
2205   gtk_widget_destroy (dlg);
2206 }
2207
2208 // =============================================================================
2209 // Arbitrary Sides dialog
2210
2211 void DoSides (bool bCone, bool bSphere, bool bTorus)
2212 {
2213   GtkWidget *dlg, *vbox, *hbox, *button, *label, *entry;
2214   int loop = 1, ret = IDCANCEL;
2215
2216   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2217   gtk_window_set_title (GTK_WINDOW (dlg), "Arbitrary sides");
2218   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2219                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2220   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2221                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2222   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2223   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2224
2225   hbox = gtk_hbox_new (FALSE, 5);
2226   gtk_widget_show (hbox);
2227   gtk_container_add (GTK_CONTAINER (dlg), hbox);
2228   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2229
2230   label = gtk_label_new ("Sides:");
2231   gtk_widget_show (label);
2232   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
2233
2234   entry = gtk_entry_new ();
2235   gtk_widget_show (entry);
2236   gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
2237
2238   vbox = gtk_vbox_new (FALSE, 5);
2239   gtk_widget_show (vbox);
2240   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, TRUE, 0);
2241
2242   button = gtk_button_new_with_label ("OK");
2243   gtk_widget_show (button);
2244   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2245   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2246                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2247   gtk_widget_set_usize (button, 60, -2);
2248  
2249   button = gtk_button_new_with_label ("Cancel");
2250   gtk_widget_show (button);
2251   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2252   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2253                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
2254
2255   gtk_grab_add (dlg);
2256   gtk_widget_show (dlg);
2257
2258   while (loop)
2259     gtk_main_iteration ();
2260
2261   if (ret == IDOK)
2262   {
2263     const char *str = gtk_entry_get_text (GTK_ENTRY (entry));
2264
2265     if (bCone)
2266       Brush_MakeSidedCone(atoi(str));
2267     else if (bSphere)
2268       Brush_MakeSidedSphere(atoi(str));
2269     else
2270       Brush_MakeSided (atoi(str));
2271   }
2272
2273   gtk_grab_remove (dlg);
2274   gtk_widget_destroy (dlg);
2275 }
2276
2277 // =============================================================================
2278 // New Patch dialog
2279
2280 void DoNewPatchDlg ()
2281 {
2282   GtkWidget *dlg, *hbox, *table, *vbox, *label, *button, *combo;
2283   GtkWidget *width, *height;
2284   GList *combo_list = (GList*)NULL;
2285   int loop = 1, ret = IDCANCEL;
2286
2287   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2288   gtk_window_set_title (GTK_WINDOW (dlg), "Patch density");
2289   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2290                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2291   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2292                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2293   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2294   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2295
2296   hbox = gtk_hbox_new (FALSE, 5);
2297   gtk_widget_show (hbox);
2298   gtk_container_add (GTK_CONTAINER (dlg), hbox);
2299   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2300
2301   table = gtk_table_new (2, 2, FALSE);
2302   gtk_widget_show (table);
2303   gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
2304   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2305   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2306  
2307   label = gtk_label_new ("Width:");
2308   gtk_widget_show (label);
2309   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2310                     (GtkAttachOptions) (GTK_FILL),
2311                     (GtkAttachOptions) (0), 0, 0);
2312   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2313
2314   label = gtk_label_new ("Height:");
2315   gtk_widget_show (label);
2316   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
2317                     (GtkAttachOptions) (GTK_FILL),
2318                     (GtkAttachOptions) (0), 0, 0);
2319   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2320
2321   combo_list = g_list_append (combo_list, (void *)"3");
2322   combo_list = g_list_append (combo_list, (void *)"5");
2323   combo_list = g_list_append (combo_list, (void *)"7");
2324   combo_list = g_list_append (combo_list, (void *)"9");
2325   combo_list = g_list_append (combo_list, (void *)"11");
2326   combo_list = g_list_append (combo_list, (void *)"13");
2327   combo_list = g_list_append (combo_list, (void *)"15");
2328
2329   combo = gtk_combo_new ();
2330   width = GTK_COMBO (combo)->entry;
2331   gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
2332   gtk_widget_show (combo);
2333   gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 0, 1,
2334                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2335                     (GtkAttachOptions) (0), 0, 0);
2336
2337   combo = gtk_combo_new ();
2338   height = GTK_COMBO (combo)->entry;
2339   gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_list);
2340   gtk_widget_show (combo);
2341   gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 1, 2,
2342                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2343                     (GtkAttachOptions) (0), 0, 0);
2344
2345   vbox = gtk_vbox_new (FALSE, 5);
2346   gtk_widget_show (vbox);
2347   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
2348
2349   button = gtk_button_new_with_label ("OK");
2350   gtk_widget_show (button);
2351   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2352   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2353                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2354   gtk_widget_set_usize (button, 60, -2);
2355  
2356   button = gtk_button_new_with_label ("Cancel");
2357   gtk_widget_show (button);
2358   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2359   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2360                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
2361
2362   // Initialize dialog
2363   g_list_free (combo_list);
2364   gtk_entry_set_text (GTK_ENTRY (width), "3");
2365   gtk_entry_set_editable (GTK_ENTRY (width), FALSE);
2366   gtk_entry_set_text (GTK_ENTRY (height), "3");
2367   gtk_entry_set_editable (GTK_ENTRY (height), FALSE);
2368
2369   gtk_grab_add (dlg);
2370   gtk_widget_show (dlg);
2371
2372   while (loop)
2373     gtk_main_iteration ();
2374
2375   if (ret == IDOK)
2376   {
2377     const char* w = gtk_entry_get_text (GTK_ENTRY (width));
2378     const char* h = gtk_entry_get_text (GTK_ENTRY (height));
2379
2380     Patch_GenericMesh(atoi (w), atoi (h), g_pParentWnd->ActiveXY ()->GetViewType ());
2381     Sys_UpdateWindows (W_ALL);
2382   }
2383
2384   gtk_grab_remove (dlg);
2385   gtk_widget_destroy (dlg);
2386 }
2387
2388 // =============================================================================
2389 // New Patch dialog
2390
2391 void DoScaleDlg ()
2392 {
2393   GtkWidget *dlg, *hbox, *table, *vbox, *label, *button;
2394   GtkWidget *x, *y, *z;
2395   int loop = 1, ret = IDCANCEL;
2396
2397   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2398   gtk_window_set_title (GTK_WINDOW (dlg), "Scale");
2399   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2400                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2401   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2402                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2403   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2404   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2405
2406   hbox = gtk_hbox_new (FALSE, 5);
2407   gtk_widget_show (hbox);
2408   gtk_container_add (GTK_CONTAINER (dlg), hbox);
2409   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2410
2411   table = gtk_table_new (3, 2, FALSE);
2412   gtk_widget_show (table);
2413   gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
2414   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2415   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2416  
2417   label = gtk_label_new ("X:");
2418   gtk_widget_show (label);
2419   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2420                     (GtkAttachOptions) (GTK_FILL),
2421                     (GtkAttachOptions) (0), 0, 0);
2422   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2423
2424   label = gtk_label_new ("Y:");
2425   gtk_widget_show (label);
2426   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
2427                     (GtkAttachOptions) (GTK_FILL),
2428                     (GtkAttachOptions) (0), 0, 0);
2429   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2430
2431   label = gtk_label_new ("Z:");
2432   gtk_widget_show (label);
2433   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
2434                     (GtkAttachOptions) (GTK_FILL),
2435                     (GtkAttachOptions) (0), 0, 0);
2436   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2437
2438   x = gtk_entry_new ();
2439   gtk_widget_show (x);
2440   gtk_table_attach (GTK_TABLE (table), x, 1, 2, 0, 1,
2441                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2442                     (GtkAttachOptions) (0), 0, 0);
2443
2444   y = gtk_entry_new ();
2445   gtk_widget_show (y);
2446   gtk_table_attach (GTK_TABLE (table), y, 1, 2, 1, 2,
2447                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2448                     (GtkAttachOptions) (0), 0, 0);
2449
2450   z = gtk_entry_new ();
2451   gtk_widget_show (z);
2452   gtk_table_attach (GTK_TABLE (table), z, 1, 2, 2, 3,
2453                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
2454                     (GtkAttachOptions) (0), 0, 0);
2455
2456   vbox = gtk_vbox_new (FALSE, 5);
2457   gtk_widget_show (vbox);
2458   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
2459
2460   button = gtk_button_new_with_label ("OK");
2461   gtk_widget_show (button);
2462   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2463   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2464                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2465   gtk_widget_set_usize (button, 60, -2);
2466  
2467   button = gtk_button_new_with_label ("Cancel");
2468   gtk_widget_show (button);
2469   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2470   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2471                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
2472
2473   // Initialize dialog
2474   gtk_entry_set_text (GTK_ENTRY (x), "1.0");
2475   gtk_entry_set_text (GTK_ENTRY (y), "1.0");
2476   gtk_entry_set_text (GTK_ENTRY (z), "1.0");
2477
2478   gtk_grab_add (dlg);
2479   gtk_widget_show (dlg);
2480
2481   while (loop)
2482     gtk_main_iteration ();
2483
2484   if (ret == IDOK)
2485   {
2486     float sx, sy, sz;
2487     sx = atof (gtk_entry_get_text (GTK_ENTRY (x)));
2488     sy = atof (gtk_entry_get_text (GTK_ENTRY (y)));
2489     sz = atof (gtk_entry_get_text (GTK_ENTRY (z)));
2490
2491     if (sx > 0 && sy > 0 && sz > 0)
2492     {
2493       Select_Scale(sx, sy, sz);
2494       Sys_UpdateWindows (W_ALL);
2495     }
2496     else
2497       Sys_Printf("Warning.. Tried to scale by a zero value.");
2498   }
2499
2500   gtk_grab_remove (dlg);
2501   gtk_widget_destroy (dlg);
2502 }
2503
2504 // =============================================================================
2505 // Thicken Patch dialog
2506
2507 void DoThickenDlg ()
2508 {
2509   GtkWidget *dlg, *vbox, *hbox, *vbox2, *button, *label;
2510   GtkWidget *amount, *seams, *group;
2511   int loop = 1, ret = IDCANCEL;
2512   static qboolean bGroupResult = true;
2513
2514   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2515   gtk_window_set_title (GTK_WINDOW (dlg), "Thicken Patch");
2516   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2517                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2518   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2519                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2520   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2521   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2522
2523   vbox = gtk_vbox_new (FALSE, 5);
2524   gtk_widget_show (vbox);
2525   gtk_container_add (GTK_CONTAINER (dlg), vbox);
2526   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
2527
2528   hbox = gtk_hbox_new (FALSE, 5);
2529   gtk_widget_show (hbox);
2530   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
2531
2532   label = gtk_label_new ("This produces a set of patches\n"
2533                          "that contains the original patch along with the\n"
2534                          "'thick' patch and an optimal set of seam patches.");
2535   gtk_widget_show (label);
2536   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
2537
2538   vbox2 = gtk_vbox_new (FALSE, 5);
2539   gtk_widget_show (vbox2);
2540   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, TRUE, 0);
2541
2542   button = gtk_button_new_with_label ("OK");
2543   gtk_widget_show (button);
2544   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
2545   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2546                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2547   gtk_widget_set_usize (button, 60, -2);
2548  
2549   button = gtk_button_new_with_label ("Cancel");
2550   gtk_widget_show (button);
2551   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
2552   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2553                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
2554
2555   hbox = gtk_hbox_new (FALSE, 5);
2556   gtk_widget_show (hbox);
2557   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
2558
2559   label = gtk_label_new ("Amount:");
2560   gtk_widget_show (label);
2561   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
2562
2563   amount = gtk_entry_new ();
2564   gtk_widget_show (amount);
2565   gtk_box_pack_start (GTK_BOX (hbox), amount, FALSE, FALSE, 0);
2566
2567   seams = gtk_check_button_new_with_label ("Seams");
2568   gtk_widget_show (seams);
2569   gtk_box_pack_start (GTK_BOX (hbox), seams, FALSE, FALSE, 0);
2570   
2571   // bGroupResult
2572   group = gtk_check_button_new_with_label("Result to func_group");
2573   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(group), bGroupResult);
2574   gtk_box_pack_start(GTK_BOX(vbox), group, FALSE, FALSE, 0);
2575   gtk_widget_show(group);
2576   
2577
2578   // Initialize dialog
2579   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (seams), TRUE);
2580   gtk_entry_set_text (GTK_ENTRY (amount), "8");
2581
2582   gtk_grab_add (dlg);
2583   gtk_widget_show (dlg);
2584
2585   while (loop)
2586     gtk_main_iteration ();
2587
2588   if (ret == IDOK)
2589   {
2590     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(group)))
2591       bGroupResult = true;
2592     else
2593       bGroupResult = false;
2594     Patch_Thicken (atoi (gtk_entry_get_text (GTK_ENTRY (amount))),
2595                    gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (seams)), bGroupResult);
2596     Sys_UpdateWindows (W_ALL);
2597   }
2598
2599   gtk_grab_remove (dlg);
2600   gtk_widget_destroy (dlg);
2601 }
2602
2603 // =============================================================================
2604 // About dialog (no program is complete without one)
2605
2606 void about_button_changelog (GtkWidget *widget, gpointer data)
2607 {
2608   Str log;
2609   log = g_strAppPath;
2610   log += "changelog.txt";
2611   OpenURL(log.GetBuffer());
2612 }
2613
2614 void about_button_credits (GtkWidget *widget, gpointer data)
2615 {
2616   Str cred;
2617   cred = g_strAppPath;
2618   cred += "credits.html";
2619   OpenURL(cred.GetBuffer());
2620 }
2621
2622 void DoAbout ()
2623 {
2624   GtkWidget *dlg, *vbox, *vbox2, *hbox, *frame, *table, *label, *pixmap, *button, *sc_extensions, *text_extensions;
2625   int loop = 1, ret = IDCANCEL;
2626
2627   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2628   gtk_window_set_title (GTK_WINDOW (dlg), "About GtkRadiant");
2629   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2630                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2631   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2632                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2633   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2634   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2635
2636   vbox = gtk_vbox_new (FALSE, 10);
2637   gtk_widget_show (vbox);
2638   gtk_container_add (GTK_CONTAINER (dlg), vbox);
2639   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
2640
2641   hbox = gtk_hbox_new (FALSE, 5);
2642   gtk_widget_show (hbox);
2643   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
2644
2645   vbox2 = gtk_vbox_new (FALSE, 5);
2646   gtk_widget_show (vbox2);
2647   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, FALSE, 0);
2648
2649   frame = gtk_frame_new ((char*)NULL);
2650   gtk_widget_show (frame);
2651   gtk_box_pack_start (GTK_BOX (vbox2), frame, FALSE, FALSE, 0);
2652   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
2653
2654   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "logo.bmp");
2655   gtk_widget_show (pixmap);
2656   gtk_container_add (GTK_CONTAINER (frame), pixmap);
2657
2658   label = gtk_label_new ("GtkRadiant " RADIANT_VERSION "\n"
2659     __DATE__ "\n\n"
2660     RADIANT_ABOUTMSG "\n\n"
2661     "By qeradiant.com\n\n"
2662     "This product contains software technology\n"
2663     "from id Software, Inc. ('id Technology').\n"
2664     "id Technology 2000 id Software,Inc.\n\n"
2665     "GtkRadiant is unsupported, however\n"
2666     "you may report your problems at\n"
2667     "http://zerowing.idsoftware.com/bugzilla"
2668   );
2669                          
2670   gtk_widget_show (label);
2671   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
2672   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
2673   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
2674
2675   vbox2 = gtk_vbox_new (FALSE, 5);
2676   gtk_widget_show (vbox2);
2677   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, TRUE, 0);
2678
2679   button = gtk_button_new_with_label ("OK");
2680   gtk_widget_show (button);
2681   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
2682   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2683                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2684
2685   button = gtk_button_new_with_label ("Credits");
2686   gtk_widget_show (button);
2687   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
2688   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2689                       GTK_SIGNAL_FUNC (about_button_credits), NULL);
2690
2691   button = gtk_button_new_with_label ("Changelog");
2692   gtk_widget_show (button);
2693   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
2694   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2695                       GTK_SIGNAL_FUNC (about_button_changelog), NULL);
2696
2697   frame = gtk_frame_new ("OpenGL Properties");
2698   gtk_widget_show (frame);
2699   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2700
2701   table = gtk_table_new (3, 2, FALSE);
2702   gtk_widget_show (table);
2703   gtk_container_add (GTK_CONTAINER (frame), table);
2704   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
2705   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
2706   gtk_container_set_border_width (GTK_CONTAINER (table), 5);
2707  
2708   label = gtk_label_new ("Vendor:");
2709   gtk_widget_show (label);
2710   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
2711                     (GtkAttachOptions) (GTK_FILL),
2712                     (GtkAttachOptions) (0), 0, 0);
2713   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2714
2715   label = gtk_label_new ("Version:");
2716   gtk_widget_show (label);
2717   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
2718                     (GtkAttachOptions) (GTK_FILL),
2719                     (GtkAttachOptions) (0), 0, 0);
2720   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2721
2722   label = gtk_label_new ("Renderer:");
2723   gtk_widget_show (label);
2724   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
2725                     (GtkAttachOptions) (GTK_FILL),
2726                     (GtkAttachOptions) (0), 0, 0);
2727   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2728
2729   label = gtk_label_new ((char*)qglGetString (GL_VENDOR));
2730   gtk_widget_show (label);
2731   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
2732                     (GtkAttachOptions) (GTK_FILL),
2733                     (GtkAttachOptions) (0), 0, 0);
2734   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2735
2736   label = gtk_label_new ((char*)qglGetString (GL_VERSION));
2737   gtk_widget_show (label);
2738   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 1, 2,
2739                     (GtkAttachOptions) (GTK_FILL),
2740                     (GtkAttachOptions) (0), 0, 0);
2741   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2742
2743   label = gtk_label_new ((char*)qglGetString (GL_RENDERER));
2744   gtk_widget_show (label);
2745   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 2, 3,
2746                     (GtkAttachOptions) (GTK_FILL),
2747                     (GtkAttachOptions) (0), 0, 0);
2748   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2749
2750   frame = gtk_frame_new ("OpenGL Extensions");
2751   gtk_widget_show (frame);
2752   gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
2753
2754   hbox = gtk_hbox_new (FALSE, 5);
2755   gtk_widget_show (hbox);
2756   gtk_container_add (GTK_CONTAINER (frame), hbox);
2757   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2758
2759   sc_extensions = gtk_scrolled_window_new(NULL, NULL);
2760   gtk_box_pack_start(GTK_BOX(hbox), sc_extensions, TRUE, TRUE, 0);
2761   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sc_extensions), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2762   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sc_extensions), GTK_SHADOW_IN);
2763   gtk_widget_show(sc_extensions);
2764         
2765   text_extensions = gtk_text_view_new();
2766   gtk_text_view_set_editable(GTK_TEXT_VIEW(text_extensions), FALSE);
2767   gtk_container_add (GTK_CONTAINER (sc_extensions), text_extensions);
2768   GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_extensions));
2769   gtk_text_buffer_set_text(buffer, (char *)qglGetString(GL_EXTENSIONS), -1);
2770   gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_extensions), GTK_WRAP_WORD);;
2771   gtk_widget_show(text_extensions);     
2772         
2773   gtk_grab_add (dlg);
2774   gtk_widget_show (dlg);
2775
2776   while (loop)
2777     gtk_main_iteration ();
2778
2779   gtk_grab_remove (dlg);
2780   gtk_widget_destroy (dlg);
2781 }
2782
2783 // =============================================================================
2784 // Command List dialog 
2785
2786 void DoCommandListDlg ()
2787 {
2788   GtkWidget *dlg, *vbox, *hbox, *scr, *button;
2789   int loop = 1, ret = IDCANCEL;
2790
2791   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2792   gtk_window_set_title (GTK_WINDOW (dlg), "Mapped Commands");
2793   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2794                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2795   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2796                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2797   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2798   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2799   gtk_window_set_default_size (GTK_WINDOW (dlg), 400, 400);
2800
2801   hbox = gtk_hbox_new (FALSE, 5);
2802   gtk_widget_show (hbox);
2803   gtk_container_add (GTK_CONTAINER (dlg), hbox);
2804   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2805
2806   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
2807   gtk_widget_show (scr);
2808   gtk_box_pack_start (GTK_BOX (hbox), scr, TRUE, TRUE, 0);
2809   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
2810   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scr), GTK_SHADOW_IN);
2811
2812   {
2813     GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
2814
2815     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
2816
2817     {
2818       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
2819       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Command", renderer, "text", 0, NULL);
2820       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
2821     }
2822
2823     {
2824       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
2825       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", 1, NULL);
2826       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
2827     }
2828
2829     gtk_widget_show(view);
2830     gtk_container_add(GTK_CONTAINER (scr), view);
2831
2832     {
2833       // Initialize dialog
2834       CString path;
2835       path = g_strTempPath;
2836       path += "commandlist.txt";
2837
2838       GSList *cmds = NULL;
2839       int n;
2840
2841       for (n = 0; n < g_nCommandCount; n++)
2842         cmds = g_slist_append (cmds, g_Commands[n].m_strCommand);
2843       cmds = g_slist_sort (cmds, (gint (*)(const void *, const void *))strcmp);
2844
2845       Sys_Printf("Writing the command list to %s", path.GetBuffer() );
2846       FILE* fileout = fopen (path.GetBuffer (), "wt");
2847
2848       while (cmds)
2849       {
2850         for (n = 0; n < g_nCommandCount; n++)
2851           if (cmds->data == g_Commands[n].m_strCommand)
2852             break;
2853
2854         char c = g_Commands[n].m_nKey;
2855         CString strLine, strMod(""), strKeys (c);
2856
2857         for (int k = 0; k < g_nKeyCount; k++)
2858         {
2859           if (g_Keys[k].m_nVKKey == g_Commands[n].m_nKey)
2860           {
2861             strKeys = g_Keys[k].m_strName;
2862             break;
2863           }
2864         }
2865
2866         if (g_Commands[n].m_nModifiers & RAD_SHIFT)
2867           strMod = "Shift";
2868         if (g_Commands[n].m_nModifiers & RAD_ALT)
2869           strMod += (strMod.GetLength() > 0) ? " + Alt" : "Alt";
2870         if (g_Commands[n].m_nModifiers & RAD_CONTROL)
2871           strMod += (strMod.GetLength() > 0) ? " + Control" : "Control";
2872         if (strMod.GetLength() > 0)
2873           strMod += " + ";
2874         strMod += strKeys;
2875
2876         {
2877           GtkTreeIter iter;
2878           gtk_list_store_append(store, &iter);
2879           gtk_list_store_set(store, &iter, 0, g_Commands[n].m_strCommand, 1, strMod.GetBuffer (), -1);
2880         }
2881  
2882         if (fileout != NULL)
2883         {
2884           strLine.Format("%-25s %s\r\n", g_Commands[n].m_strCommand, strMod.GetBuffer ());
2885           fputs (strLine.GetBuffer (), fileout);
2886         }
2887
2888         cmds = g_slist_remove (cmds, cmds->data);
2889       }
2890
2891       if (fileout != NULL)
2892         fclose (fileout);
2893     }
2894     
2895     g_object_unref(G_OBJECT(store));
2896   }
2897
2898   vbox = gtk_vbox_new (FALSE, 5);
2899   gtk_widget_show (vbox);
2900   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
2901
2902   button = gtk_button_new_with_label ("Close");
2903   gtk_widget_show (button);
2904   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2905   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2906                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2907   gtk_widget_set_usize (button, 60, -2);
2908
2909   gtk_grab_add (dlg);
2910   gtk_widget_show (dlg);
2911
2912   while (loop)
2913     gtk_main_iteration ();
2914
2915   gtk_grab_remove (dlg);
2916   gtk_widget_destroy (dlg);
2917 }
2918
2919 // =============================================================================
2920 // Texture List dialog 
2921
2922 void DoTextureListDlg ()
2923 {
2924   GtkWidget *dlg, *vbox, *hbox, *scr, *button;
2925   int loop = 1, ret = IDCANCEL;
2926
2927   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2928   gtk_window_set_title (GTK_WINDOW (dlg), "Textures");
2929   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
2930                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
2931   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
2932                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
2933   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
2934   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
2935   gtk_window_set_default_size (GTK_WINDOW (dlg), 400, 400);
2936
2937   hbox = gtk_hbox_new (FALSE, 5);
2938   gtk_widget_show (hbox);
2939   gtk_container_add (GTK_CONTAINER (dlg), hbox);
2940   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2941
2942   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
2943   gtk_widget_show (scr);
2944   gtk_box_pack_start (GTK_BOX (hbox), scr, TRUE, TRUE, 0);
2945   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
2946   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scr), GTK_SHADOW_IN);
2947
2948   GtkWidget* texture_list;
2949
2950   {
2951     GtkListStore* store = gtk_list_store_new(1, G_TYPE_STRING);
2952
2953     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
2954     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); 
2955
2956     {
2957       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
2958       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);
2959       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
2960     }
2961
2962     gtk_widget_show(view);
2963     gtk_container_add(GTK_CONTAINER (scr), view);
2964
2965     {
2966       // Initialize dialog
2967       GSList *textures = (GSList*)NULL;
2968       FillTextureMenu(&textures);
2969       while (textures != NULL)
2970       {
2971         {
2972           GtkTreeIter iter;
2973           gtk_list_store_append(store, &iter);
2974           gtk_list_store_set(store, &iter, 0, (gchar*)textures->data, -1);
2975         }
2976         free (textures->data);
2977         textures = g_slist_remove (textures, textures->data);
2978       }
2979     }
2980     
2981     g_object_unref(G_OBJECT(store));
2982
2983     texture_list = view;
2984   }
2985
2986   vbox = gtk_vbox_new (FALSE, 5);
2987   gtk_widget_show (vbox);
2988   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
2989
2990   button = gtk_button_new_with_label ("Load");
2991   gtk_widget_show (button);
2992   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2993   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2994                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
2995   gtk_widget_set_usize (button, 60, -2);
2996
2997   button = gtk_button_new_with_label ("Close");
2998   gtk_widget_show (button);
2999   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3000   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3001                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3002   gtk_widget_set_usize (button, 60, -2);
3003
3004   gtk_grab_add (dlg);
3005   gtk_widget_show (dlg);
3006
3007   while (loop)
3008     gtk_main_iteration ();
3009
3010   if (ret == IDOK)
3011   {
3012     GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(texture_list));
3013
3014     GtkTreeModel* model;
3015     GtkTreeIter iter;
3016     if(gtk_tree_selection_get_selected(selection, &model, &iter))
3017     {
3018       GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
3019       if(gtk_tree_path_get_depth(path) == 1)
3020         Texture_ShowDirectory(gtk_tree_path_get_indices(path)[0] + CMD_TEXTUREWAD);
3021       gtk_tree_path_free(path);
3022     }
3023   }
3024
3025   gtk_grab_remove (dlg);
3026   gtk_widget_destroy (dlg);
3027 }
3028
3029 // =============================================================================
3030 // Cap dialog 
3031
3032 int DoCapDlg (int *type, bool *b_GroupResult)
3033 {
3034   GtkWidget *dlg, *vbox, *hbox, *table, *pixmap, *button, *group_toggle, *radio_vbox;
3035   GtkWidget *bevel, *endcap, *ibevel, *iendcap;
3036   GSList *group = (GSList*)NULL;
3037         int loop = 1, ret = IDCANCEL;
3038         
3039   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3040   gtk_window_set_title (GTK_WINDOW (dlg), "Cap");
3041   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3042                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3043   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3044                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3045   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3046   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3047
3048         hbox = gtk_hbox_new (FALSE, 5);
3049   gtk_widget_show (hbox);
3050   gtk_container_add (GTK_CONTAINER (dlg), hbox);
3051   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3052
3053   // Gef: Added a vbox to contain the toggle buttons
3054   radio_vbox = gtk_vbox_new(FALSE, 4);
3055   gtk_container_add(GTK_CONTAINER(hbox), radio_vbox);
3056   gtk_widget_show(radio_vbox);
3057                 
3058   table = gtk_table_new (4, 2, FALSE);
3059   gtk_widget_show (table);
3060   gtk_box_pack_start (GTK_BOX (radio_vbox), table, TRUE, TRUE, 0);
3061   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
3062   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
3063  
3064   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "cap_bevel.bmp");
3065   gtk_widget_show (pixmap);
3066   gtk_table_attach (GTK_TABLE (table), pixmap, 0, 1, 0, 1,
3067                     (GtkAttachOptions) (GTK_FILL),
3068                     (GtkAttachOptions) (0), 0, 0);
3069
3070   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "cap_endcap.bmp");
3071   gtk_widget_show (pixmap);
3072   gtk_table_attach (GTK_TABLE (table), pixmap, 0, 1, 1, 2,
3073                     (GtkAttachOptions) (GTK_FILL),
3074                     (GtkAttachOptions) (0), 0, 0);
3075
3076   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "cap_ibevel.bmp");
3077   gtk_widget_show (pixmap);
3078   gtk_table_attach (GTK_TABLE (table), pixmap, 0, 1, 2, 3,
3079                     (GtkAttachOptions) (GTK_FILL),
3080                     (GtkAttachOptions) (0), 0, 0);
3081
3082   pixmap = new_pixmap (g_pParentWnd->m_pWidget, "cap_iendcap.bmp");
3083   gtk_widget_show (pixmap);
3084   gtk_table_attach (GTK_TABLE (table), pixmap, 0, 1, 3, 4,
3085                     (GtkAttachOptions) (GTK_FILL),
3086                     (GtkAttachOptions) (0), 0, 0);
3087
3088   bevel = gtk_radio_button_new_with_label (group, "Bevel");
3089   gtk_widget_show (bevel);
3090   gtk_table_attach (GTK_TABLE (table), bevel, 1, 2, 0, 1,
3091                     (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
3092                     (GtkAttachOptions) (0), 0, 0);
3093   group = gtk_radio_button_group (GTK_RADIO_BUTTON (bevel));
3094
3095   endcap = gtk_radio_button_new_with_label (group, "Endcap");
3096   gtk_widget_show (endcap);
3097   gtk_table_attach (GTK_TABLE (table), endcap, 1, 2, 1, 2,
3098                     (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
3099                     (GtkAttachOptions) (0), 0, 0);
3100   group = gtk_radio_button_group (GTK_RADIO_BUTTON (endcap));
3101
3102   ibevel = gtk_radio_button_new_with_label (group, "Inverted Bevel");
3103   gtk_widget_show (ibevel);
3104   gtk_table_attach (GTK_TABLE (table), ibevel, 1, 2, 2, 3,
3105                     (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
3106                     (GtkAttachOptions) (0), 0, 0);
3107   group = gtk_radio_button_group (GTK_RADIO_BUTTON (ibevel));
3108
3109   iendcap = gtk_radio_button_new_with_label (group, "Inverted Endcap");
3110   gtk_widget_show (iendcap);
3111   gtk_table_attach (GTK_TABLE (table), iendcap, 1, 2, 3, 4,
3112                     (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
3113                     (GtkAttachOptions) (0), 0, 0);
3114   group = gtk_radio_button_group (GTK_RADIO_BUTTON (iendcap));
3115
3116   // Gef: added radio toggle for func_grouping capped patches
3117   group_toggle = gtk_check_button_new_with_label("Result to func_group");
3118   gtk_container_add(GTK_CONTAINER(radio_vbox), group_toggle);
3119   gtk_widget_show(group_toggle);
3120         
3121   vbox = gtk_vbox_new (FALSE, 5);
3122   gtk_widget_show (vbox);
3123   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3124
3125   button = gtk_button_new_with_label ("OK");
3126   gtk_widget_show (button);
3127   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3128   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3129                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
3130   gtk_widget_set_usize (button, 60, -2);
3131
3132   button = gtk_button_new_with_label ("Cancel");
3133   gtk_widget_show (button);
3134   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3135   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3136                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3137   gtk_widget_set_usize (button, 60, -2);
3138
3139   // Gef: Set the state of the func_group toggle
3140   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (group_toggle), *b_GroupResult);
3141         
3142   // Initialize dialog
3143   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bevel), TRUE);
3144
3145   gtk_grab_add (dlg);
3146   gtk_widget_show (dlg);
3147
3148   while (loop)
3149     gtk_main_iteration ();
3150
3151   if (ret == IDOK)
3152   {
3153     if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (bevel)))
3154       *type = BEVEL; //*type = CapDialog::BEVEL;
3155     else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (endcap)))
3156       *type = ENDCAP; //*type = CapDialog::ENDCAP;
3157     else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ibevel)))
3158       *type = IBEVEL; // *type = CapDialog::IBEVEL;
3159     else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (iendcap)))
3160       *type = IENDCAP; // *type = CapDialog::IENDCAP;
3161
3162     // Gef: Added toggle for optional cap func_grouping
3163     *b_GroupResult = (bool *)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(group_toggle));
3164   }
3165
3166   gtk_grab_remove (dlg);
3167   gtk_widget_destroy (dlg);
3168
3169   return ret;
3170 }
3171
3172 // =============================================================================
3173 // Scripts dialog 
3174
3175 void DoScriptsDlg ()
3176 {
3177   GtkWidget *dlg, *vbox, *vbox2, *hbox, *label, *button, *scr;
3178   int loop = 1, ret = IDCANCEL;
3179
3180   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3181   gtk_window_set_title (GTK_WINDOW (dlg), "Available Scripts - Not Implemented Yet");
3182   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3183                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3184   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3185                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3186   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3187   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3188
3189   vbox = gtk_vbox_new (FALSE, 5);
3190   gtk_widget_show (vbox);
3191   gtk_container_add (GTK_CONTAINER (dlg), vbox);
3192   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
3193
3194   label = gtk_label_new ("WARNING: BrushScripting is in a highly experimental state and is\n"
3195                          "far from complete. If you attempt to use them it is VERY LIKELY\n"
3196                          "that Radiant will crash. Save your work before attempting to\n"
3197                          "make use of any scripting features.");
3198   gtk_widget_show (label);
3199   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
3200   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
3201   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3202
3203   hbox = gtk_hbox_new (FALSE, 5);
3204   gtk_widget_show (hbox);
3205   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3206
3207   scr = gtk_scrolled_window_new ((GtkAdjustment*)NULL, (GtkAdjustment*)NULL);
3208   gtk_widget_show (scr);
3209   gtk_box_pack_start (GTK_BOX (hbox), scr, TRUE, TRUE, 0);
3210   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
3211   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scr), GTK_SHADOW_IN);
3212
3213   GtkWidget* scripts_list;
3214
3215   {
3216     GtkListStore* store = gtk_list_store_new(1, G_TYPE_STRING);
3217
3218     GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
3219     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); 
3220
3221     {
3222       GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
3223       GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, NULL);
3224       gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
3225     }
3226
3227     gtk_widget_show(view);
3228     gtk_container_add(GTK_CONTAINER (scr), view);
3229
3230     {
3231       // Initialize dialog
3232       CString strINI;
3233       strINI = g_strGameToolsPath;
3234       strINI += "/scripts.ini";
3235       FILE *f;
3236
3237       f = fopen (strINI.GetBuffer(), "rt");
3238       if (f != NULL)
3239       {
3240         char line[1024], *ptr;
3241
3242         // read section names
3243         while (fgets (line, 1024, f) != 0)
3244         {
3245           if (line[0] != '[')
3246             continue;
3247
3248           ptr = strchr (line, ']');
3249           *ptr = '\0';
3250
3251           {
3252             GtkTreeIter iter;
3253             gtk_list_store_append(store, &iter);
3254             gtk_list_store_set(store, &iter, 0, line, -1);
3255           }
3256         }
3257         fclose (f);
3258       }
3259     }
3260     
3261     g_object_unref(G_OBJECT(store));
3262
3263     scripts_list = view;
3264   }
3265
3266   vbox2 = gtk_vbox_new (FALSE, 5);
3267   gtk_widget_show (vbox2);
3268   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
3269
3270   button = gtk_button_new_with_label ("Run");
3271   gtk_widget_show (button);
3272   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
3273   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3274                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
3275   gtk_widget_set_usize (button, 60, -2);
3276
3277   button = gtk_button_new_with_label ("New...");
3278   gtk_widget_show (button);
3279   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
3280   gtk_widget_set_sensitive (button, FALSE);
3281   gtk_widget_set_usize (button, 60, -2);
3282
3283   button = gtk_button_new_with_label ("Edit...");
3284   gtk_widget_show (button);
3285   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
3286   gtk_widget_set_sensitive (button, FALSE);
3287   gtk_widget_set_usize (button, 60, -2);
3288
3289   button = gtk_button_new_with_label ("Close");
3290   gtk_widget_show (button);
3291   gtk_box_pack_end (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
3292   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3293                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3294   gtk_widget_set_usize (button, 60, -2);
3295
3296   gtk_grab_add (dlg);
3297   gtk_widget_show (dlg);
3298
3299   while (loop)
3300     gtk_main_iteration ();
3301
3302   if (ret == IDOK)
3303   {
3304     GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(scripts_list));
3305
3306     GtkTreeModel* model;
3307     GtkTreeIter iter;
3308     if(gtk_tree_selection_get_selected(selection, &model, &iter))
3309     {
3310       char* script;
3311       gtk_tree_model_get(model, &iter, 0, &script, -1);
3312       RunScriptByName(script, true);
3313       g_free(script);
3314     }
3315   }
3316
3317   gtk_grab_remove (dlg);
3318   gtk_widget_destroy (dlg);
3319 }
3320
3321 // =============================================================================
3322 //  dialog 
3323
3324 int DoBSInputDlg (const char *fields[5], float values[5])
3325 {
3326   GtkWidget *dlg, *vbox, *hbox, *label, *button;
3327   GtkWidget *entries[5];
3328   int i, loop = 1, ret = IDCANCEL;
3329
3330   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3331   gtk_window_set_title (GTK_WINDOW (dlg), "BrushScript Input");
3332   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3333                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3334   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3335                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3336   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3337   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3338
3339   hbox = gtk_hbox_new (FALSE, 5);
3340   gtk_widget_show (hbox);
3341   gtk_container_add (GTK_CONTAINER (dlg), hbox);
3342   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3343
3344   vbox = gtk_vbox_new (FALSE, 5);
3345   gtk_widget_show (vbox);
3346   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
3347
3348   // Create entries and initialize them
3349   for (i = 0; i < 5; i++)
3350   {
3351     if (strlen (fields[i]) == 0)
3352       continue;
3353
3354     label = gtk_label_new (fields[i]);
3355     gtk_widget_show (label);
3356     gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
3357     gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
3358     gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3359
3360     entries[i] = gtk_entry_new ();
3361     gtk_widget_show (entries[i]);
3362     gtk_box_pack_start (GTK_BOX (vbox), entries[i], TRUE, TRUE, 0);
3363
3364     char buf[32];
3365     sprintf (buf, "%f", values[i]);
3366     gtk_entry_set_text (GTK_ENTRY (entries[i]), buf);
3367   }
3368
3369   vbox = gtk_vbox_new (FALSE, 5);
3370   gtk_widget_show (vbox);
3371   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3372
3373   button = gtk_button_new_with_label ("OK");
3374   gtk_widget_show (button);
3375   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3376   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3377                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
3378   gtk_widget_set_usize (button, 60, -2);
3379
3380   button = gtk_button_new_with_label ("Cancel");
3381   gtk_widget_show (button);
3382   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3383   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3384                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3385   gtk_widget_set_usize (button, 60, -2);
3386
3387   gtk_grab_add (dlg);
3388   gtk_widget_show (dlg);
3389
3390   while (loop)
3391     gtk_main_iteration ();
3392
3393   for (i = 0; i < 5; i++)
3394   {
3395     if (strlen (fields[i]) == 0)
3396       continue;
3397
3398     values[i] = atof (gtk_entry_get_text (GTK_ENTRY (entries[i])));
3399   }
3400
3401   gtk_grab_remove (dlg);
3402   gtk_widget_destroy (dlg);
3403
3404   return ret;
3405 }
3406
3407 // =============================================================================
3408 // TextureLayout dialog 
3409
3410 int DoTextureLayout (float *fx, float *fy)
3411 {
3412   GtkWidget *dlg, *vbox, *hbox, *table, *label, *button;
3413   GtkWidget *x, *y;
3414   int loop = 1, ret = IDCANCEL;
3415
3416   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3417   gtk_window_set_title (GTK_WINDOW (dlg), "Patch texture layout");
3418   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3419                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3420   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3421                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3422   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3423   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3424
3425   hbox = gtk_hbox_new (FALSE, 5);
3426   gtk_widget_show (hbox);
3427   gtk_container_add (GTK_CONTAINER (dlg), hbox);
3428   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3429
3430   vbox = gtk_vbox_new (FALSE, 5);
3431   gtk_widget_show (vbox);
3432   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
3433
3434   label = gtk_label_new ("Texture will be fit across the patch based\n"
3435                          "on the x and y values given. Values of 1x1\n"
3436                          "will \"fit\" the texture. 2x2 will repeat\n"
3437                          "it twice, etc.");
3438   gtk_widget_show (label);
3439   gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
3440   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3441
3442   table = gtk_table_new (2, 2, FALSE);
3443   gtk_widget_show (table);
3444   gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
3445   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
3446   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
3447  
3448   label = gtk_label_new ("Texture x:");
3449   gtk_widget_show (label);
3450   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
3451                     (GtkAttachOptions) (GTK_FILL),
3452                     (GtkAttachOptions) (0), 0, 0);
3453   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3454
3455   label = gtk_label_new ("Texture y:");
3456   gtk_widget_show (label);
3457   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
3458                     (GtkAttachOptions) (GTK_FILL),
3459                     (GtkAttachOptions) (0), 0, 0);
3460   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3461
3462   x = gtk_entry_new ();
3463   gtk_widget_show (x);
3464   gtk_table_attach (GTK_TABLE (table), x, 1, 2, 0, 1,
3465                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
3466                     (GtkAttachOptions) (0), 0, 0);
3467
3468   y = gtk_entry_new ();
3469   gtk_widget_show (y);
3470   gtk_table_attach (GTK_TABLE (table), y, 1, 2, 1, 2,
3471                     (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
3472                     (GtkAttachOptions) (0), 0, 0);
3473
3474   vbox = gtk_vbox_new (FALSE, 5);
3475   gtk_widget_show (vbox);
3476   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3477
3478   button = gtk_button_new_with_label ("OK");
3479   gtk_widget_show (button);
3480   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3481   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3482                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
3483   gtk_widget_set_usize (button, 60, -2);
3484
3485   button = gtk_button_new_with_label ("Cancel");
3486   gtk_widget_show (button);
3487   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3488   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3489                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3490   gtk_widget_set_usize (button, 60, -2);
3491
3492   // Initialize
3493   gtk_entry_set_text (GTK_ENTRY (x), "4.0");
3494   gtk_entry_set_text (GTK_ENTRY (y), "4.0");
3495
3496   gtk_grab_add (dlg);
3497   gtk_widget_show (dlg);
3498
3499   while (loop)
3500     gtk_main_iteration ();
3501
3502   if (ret == IDOK)
3503   {
3504     *fx = atof (gtk_entry_get_text (GTK_ENTRY (x)));
3505     *fy = atof (gtk_entry_get_text (GTK_ENTRY (y)));
3506   }
3507
3508   gtk_grab_remove (dlg);
3509   gtk_widget_destroy (dlg);
3510
3511   return ret;
3512 }
3513
3514 // =============================================================================
3515 // Name dialog 
3516
3517 char* DoNameDlg (const char* title)
3518 {
3519   GtkWidget *dlg, *vbox, *hbox, *label, *button, *entry;
3520   int loop = 1, ret = IDCANCEL;
3521   char *str;
3522
3523   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3524   gtk_window_set_title (GTK_WINDOW (dlg), title);
3525   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3526                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3527   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3528                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3529   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3530   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3531
3532   hbox = gtk_hbox_new (FALSE, 5);
3533   gtk_widget_show (hbox);
3534   gtk_container_add (GTK_CONTAINER (dlg), hbox);
3535   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3536
3537   label = gtk_label_new ("Name:");
3538   gtk_widget_show (label);
3539   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
3540
3541   entry = gtk_entry_new ();
3542   gtk_widget_show (entry);
3543   gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
3544
3545   vbox = gtk_vbox_new (FALSE, 5);
3546   gtk_widget_show (vbox);
3547   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3548
3549   button = gtk_button_new_with_label ("OK");
3550   gtk_widget_show (button);
3551   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3552   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3553                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
3554   gtk_widget_set_usize (button, 60, -2);
3555
3556   button = gtk_button_new_with_label ("Cancel");
3557   gtk_widget_show (button);
3558   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3559   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3560                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3561   gtk_widget_set_usize (button, 60, -2);
3562
3563   gtk_grab_add (dlg);
3564   gtk_widget_show (dlg);
3565
3566   while (loop)
3567     gtk_main_iteration ();
3568
3569   if (ret == IDOK)
3570     str = strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
3571   else
3572     str = NULL;
3573
3574   gtk_grab_remove (dlg);
3575   gtk_widget_destroy (dlg);
3576
3577   return str;
3578 }
3579
3580 // =============================================================================
3581 // NewProject dialog 
3582
3583 char* DoNewProjectDlg ()
3584 {
3585   GtkWidget *dlg, *vbox, *hbox, *label, *button, *entry, *check;
3586   int loop = 1, ret = IDCANCEL;
3587   char *str;
3588
3589   // start by a warning message
3590   // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=459
3591   CString msg;
3592   msg = "Are you sure you want a new project?\n";
3593   msg += "Please note that creating a new project is not the prefered way to setup GtkRadiant for mod editing.\n";
3594   msg += "Check http://www.qeradiant.com/faq/index.cgi?file=220 for more information";
3595   if (gtk_MessageBox(NULL, msg.GetBuffer(), "Confirm", MB_YESNO, "http://www.qeradiant.com/faq/index.cgi?file=220" ) == IDNO)
3596   {
3597     return NULL;
3598   }
3599
3600   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3601   gtk_window_set_title (GTK_WINDOW (dlg), "New Project");
3602   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3603                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3604   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3605                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3606   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3607   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3608
3609   hbox = gtk_hbox_new (FALSE, 10);
3610   gtk_widget_show (hbox);
3611   gtk_container_add (GTK_CONTAINER (dlg), hbox);
3612   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3613
3614   vbox = gtk_vbox_new (FALSE, 5);
3615   gtk_widget_show (vbox);
3616   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3617
3618   label = gtk_label_new ("This will create a new directory beneath your\n"
3619                          "game path based on the project name you give.");
3620   gtk_widget_show (label);
3621   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
3622   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3623
3624   label = gtk_label_new ("Project name:");
3625   gtk_widget_show (label);
3626   gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
3627   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3628   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3629
3630   entry = gtk_entry_new ();
3631   gtk_widget_show (entry);
3632   gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
3633
3634   check = gtk_check_button_new_with_label ("Include game dll files");
3635   gtk_widget_show (check);
3636   gtk_box_pack_start (GTK_BOX (vbox), check, TRUE, TRUE, 0);
3637   gtk_widget_set_sensitive (check, FALSE);
3638
3639   vbox = gtk_vbox_new (FALSE, 5);
3640   gtk_widget_show (vbox);
3641   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3642
3643   button = gtk_button_new_with_label ("OK");
3644   gtk_widget_show (button);
3645   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3646   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3647                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
3648   gtk_widget_set_usize (button, 60, -2);
3649
3650   button = gtk_button_new_with_label ("Cancel");
3651   gtk_widget_show (button);
3652   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3653   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3654                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
3655   gtk_widget_set_usize (button, 60, -2);
3656
3657   gtk_grab_add (dlg);
3658   gtk_widget_show (dlg);
3659
3660   while (loop)
3661     gtk_main_iteration ();
3662
3663   if (ret == IDOK)
3664     str = strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
3665   else
3666     str = NULL;
3667
3668   gtk_grab_remove (dlg);
3669   gtk_widget_destroy (dlg);
3670
3671   return str;
3672 }
3673
3674 // =============================================================================
3675 // Text Editor dialog 
3676
3677 // master window widget
3678 static GtkWidget *text_editor = NULL;
3679 static GtkWidget *text_widget; // slave, text widget from the gtk editor
3680
3681 static gint editor_delete (GtkWidget *widget, gpointer data)
3682 {
3683   if (gtk_MessageBox (widget, "Close the shader editor ?", "Radiant", MB_YESNO) == IDNO)
3684     return TRUE;
3685
3686   gtk_widget_hide (text_editor);
3687
3688   return TRUE;
3689 }
3690
3691 static void editor_save (GtkWidget *widget, gpointer data)
3692 {
3693   FILE *f = fopen ((char*)g_object_get_data (G_OBJECT (data), "filename"), "w");
3694   gpointer text = g_object_get_data (G_OBJECT (data), "text");
3695
3696   if (f == NULL)
3697   {
3698     gtk_MessageBox (GTK_WIDGET(data), "Error saving file !");
3699     return;
3700   }
3701
3702   char *str = gtk_editable_get_chars (GTK_EDITABLE (text), 0, -1);
3703   fwrite (str, 1, strlen (str), f);
3704   fclose (f);
3705 }
3706
3707 static void editor_close (GtkWidget *widget, gpointer data)
3708 {
3709   if (gtk_MessageBox (text_editor, "Close the shader editor ?", "Radiant", MB_YESNO) == IDNO)
3710     return;
3711
3712   gtk_widget_hide (text_editor);
3713 }
3714
3715 // several attempts
3716 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=355
3717 #if 0
3718 #ifdef _WIN32
3719
3720 HWND FindEditWindow()
3721 {
3722   return FindWindow("TFormEditPadLite", NULL);
3723 }
3724
3725 HWND FindEditWindow()
3726 {
3727   HWND hwnd = FindWindow("TFormEditPadLite", NULL);
3728   if (hwnd)
3729   {
3730     hwnd = FindWindowEx(hwnd, NULL, "TPanel", NULL);
3731     if (hwnd)
3732     {
3733       hwnd = FindWindowEx(hwnd, NULL, "TPanel", NULL);
3734       if (hwnd)
3735       {
3736         hwnd = FindWindowEx(hwnd, NULL, "TEditPadEditor", NULL);
3737         if (hwnd)
3738         {
3739           hwnd = FindWindowEx(hwnd, NULL, "TWinControlProxy", NULL);
3740           return hwnd;
3741         }
3742       }
3743     }
3744   }
3745   return NULL;
3746 }
3747
3748 HWND FindEditWindow()
3749 {
3750   HWND hwnd = FindWindow("TFormEditPadLite", NULL);
3751   if (hwnd)
3752   {
3753     hwnd = FindWindowEx(hwnd, NULL, "TPanel", NULL);
3754     if (hwnd)
3755     {
3756       hwnd = FindWindowEx(hwnd, NULL, "TPanel", NULL);
3757       if (hwnd)
3758       {
3759         hwnd = FindWindowEx(hwnd, NULL, "TPanel", NULL);
3760         if (hwnd)
3761         {
3762           hwnd = FindWindowEx(hwnd, NULL, "TFrameSearchReplace", NULL);
3763           if (hwnd)
3764           {
3765             hwnd = FindWindowEx(hwnd, NULL, "TJGStringEditorControl", NULL);
3766             return hwnd;
3767           }
3768         }
3769       }
3770     }
3771   }
3772   return NULL;
3773 }
3774
3775 HWND FindEditWindow()
3776 {
3777   HWND hwnd = FindWindow("TEditPadForm", NULL);
3778   HWND hwndEdit = NULL;
3779   if (hwnd != NULL)
3780   {
3781     HWND hwndTab = FindWindowEx(hwnd, NULL, "TTabControl", NULL);
3782     if (hwndTab != NULL)
3783     {
3784       hwndEdit = FindWindowEx(hwndTab, NULL, "TRicherEdit", NULL);
3785     }
3786   }
3787   return hwndEdit;
3788 }
3789 #endif
3790 #endif // #if 0
3791
3792 static void CreateGtkTextEditor ()
3793 {
3794   GtkWidget *dlg;
3795   GtkWidget *vbox, *hbox, *button, *scr, *text;
3796
3797   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3798
3799   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3800                       GTK_SIGNAL_FUNC (editor_delete), NULL);
3801   gtk_window_set_default_size (GTK_WINDOW (dlg), 600, 300);
3802
3803   vbox = gtk_vbox_new (FALSE, 5);
3804   gtk_widget_show (vbox);
3805   gtk_container_add (GTK_CONTAINER (dlg), vbox);
3806   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
3807
3808   scr = gtk_scrolled_window_new (NULL, NULL);
3809   gtk_widget_show (scr);
3810   gtk_box_pack_start (GTK_BOX (vbox), scr, TRUE, TRUE, 0);
3811   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3812   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
3813
3814   text = gtk_text_view_new();
3815   gtk_container_add (GTK_CONTAINER (scr), text);
3816   gtk_widget_show (text);
3817   g_object_set_data (G_OBJECT (dlg), "text", text);
3818   gtk_text_view_set_editable (GTK_TEXT_VIEW(text), TRUE);
3819
3820   hbox = gtk_hbox_new (FALSE, 5);
3821   gtk_widget_show (hbox);
3822   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
3823
3824   button = gtk_button_new_with_label ("Close");
3825   gtk_widget_show (button);
3826   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
3827   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3828                       GTK_SIGNAL_FUNC (editor_close), dlg);
3829   gtk_widget_set_usize (button, 60, -2);
3830
3831   button = gtk_button_new_with_label ("Save");
3832   gtk_widget_show (button);
3833   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
3834   gtk_signal_connect (GTK_OBJECT (button), "clicked",
3835                       GTK_SIGNAL_FUNC (editor_save), dlg);
3836   gtk_widget_set_usize (button, 60, -2);
3837
3838   text_editor = dlg;
3839   text_widget = text;
3840 }
3841
3842 static void DoGtkTextEditor (const char* filename, guint cursorpos)
3843 {
3844   if (!text_editor)
3845     CreateGtkTextEditor(); // build it the first time we need it
3846
3847   // Load file
3848   FILE *f = fopen (filename, "r");
3849
3850   if (f == NULL)
3851   {
3852     Sys_Printf("Unable to load file %s in shader editor.\n", filename);
3853     gtk_widget_hide (text_editor);
3854   }
3855   else
3856   {
3857     fseek (f, 0, SEEK_END);
3858     int len = ftell (f);
3859     void *buf = qmalloc (len);
3860     void *old_filename;
3861
3862     rewind (f);
3863     fread (buf, 1, len, f);
3864
3865     gtk_window_set_title (GTK_WINDOW (text_editor), filename);
3866
3867     GtkTextBuffer* text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_widget));
3868     gtk_text_buffer_set_text(text_buffer, (char*)buf, len);
3869
3870     old_filename = g_object_get_data (G_OBJECT (text_editor), "filename");
3871     if (old_filename)
3872       free(old_filename);
3873     g_object_set_data (G_OBJECT (text_editor), "filename", strdup (filename));
3874
3875     // trying to show later
3876     gtk_widget_show (text_editor);
3877
3878 #ifdef _WIN32
3879     while (gtk_events_pending ())
3880       gtk_main_iteration ();
3881 #endif
3882
3883     // only move the cursor if it's not exceeding the size..
3884     // NOTE: this is erroneous, cursorpos is the offset in bytes, not in characters
3885     // len is the max size in bytes, not in characters either, but the character count is below that limit..
3886     // thinking .. the difference between character count and byte count would be only because of CR/LF?
3887     {
3888       GtkTextIter text_iter;
3889       // character offset, not byte offset
3890       gtk_text_buffer_get_iter_at_offset(text_buffer, &text_iter, cursorpos);
3891       gtk_text_buffer_place_cursor(text_buffer, &text_iter);
3892     }
3893
3894 #ifdef _WIN32
3895     gtk_widget_queue_draw(text_widget);
3896 #endif
3897
3898     free (buf);
3899     fclose (f);
3900   }
3901 }
3902
3903 void DoTextEditor (const char* filename, int cursorpos)
3904 {
3905   CString strEditCommand;
3906 #ifdef _WIN32
3907   if (g_PrefsDlg.m_bUseWin32Editor)
3908   {
3909     Sys_Printf("opening file '%s' (line %d info ignored)\n", filename);
3910     ShellExecute((HWND)GDK_WINDOW_HWND (g_pParentWnd->m_pWidget->window), "open", filename, NULL, NULL, SW_SHOW );
3911     return;
3912   }
3913 #else
3914   // check if a custom editor is set
3915   if((g_PrefsDlg.m_bUseCustomEditor) && (g_PrefsDlg.m_strEditorCommand.GetLength() > 0))
3916   {
3917     strEditCommand = g_PrefsDlg.m_strEditorCommand;
3918     strEditCommand += " \"";
3919     strEditCommand += filename;
3920     strEditCommand += "\"";
3921     
3922     Sys_Printf("Launching: %s\n", strEditCommand.GetBuffer());
3923     // note: linux does not return false if the command failed so it will assume success
3924     if (Q_Exec(NULL, (char *)strEditCommand.GetBuffer(), NULL, true) == false)
3925     {
3926       Sys_FPrintf(SYS_WRN, "Warning: Failed to execute %s, using default\n", strEditCommand.GetBuffer());
3927     }
3928     else
3929     {
3930       // the command (appeared) to run successfully, no need to do anything more
3931       return;
3932     }
3933   }
3934 #endif
3935   
3936   DoGtkTextEditor (filename, cursorpos);
3937
3938   // old win32 code with EditPad bindings, broken
3939   // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=355
3940 #if 0
3941   strEditCommand = g_strAppPath.GetBuffer();
3942   strEditCommand += "editpad.exe";
3943   strEditCommand += " \"";
3944   strEditCommand += filename;
3945   strEditCommand += "\"";
3946   if (Q_Exec(NULL, (char *)strEditCommand.GetBuffer(), NULL, true) == false)
3947   {
3948     Sys_FPrintf(SYS_WRN, "WARNING: Gtk shader editor is not fully functional on windows in general and unstable on win98 in particular.\n");
3949     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");
3950     DoGtkTextEditor (filename, cursorpos);
3951   }
3952   else
3953   {
3954     // TTimo: we used to call Delay here, to continue processing messages. But it seems to induce a lot of instabilities.
3955     // so now the user will simply have to wait.
3956     Sleep( 1500 );
3957
3958         // now grab the edit window and scroll to the shader we want to edit
3959     HWND hwndEdit = FindEditWindow();
3960
3961     if (hwndEdit != NULL)
3962       PostMessage(hwndEdit, EM_SETSEL, cursorpos, cursorpos);
3963     else
3964       Sys_Printf("Unable to load shader editor.\n");
3965   }
3966 #endif
3967 }
3968
3969 // =============================================================================
3970 // Light Intensity dialog 
3971
3972 int DoLightIntensityDlg (int *intensity)
3973 {
3974   GtkWidget *dlg, *vbox, *hbox, *label, *button, *entry;
3975   int loop = 1, ret = IDCANCEL;
3976
3977   dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3978   gtk_window_set_title (GTK_WINDOW (dlg), "Light intensity");
3979   gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
3980                       GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
3981   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
3982                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
3983   g_object_set_data (G_OBJECT (dlg), "loop", &loop);
3984   g_object_set_data (G_OBJECT (dlg), "ret", &ret);
3985
3986   GtkAccelGroup *accel_group = gtk_accel_group_new ();
3987   gtk_window_add_accel_group (GTK_WINDOW (dlg), accel_group);
3988
3989   hbox = gtk_hbox_new (FALSE, 5);
3990   gtk_widget_show (hbox);
3991   gtk_container_add (GTK_CONTAINER (dlg), hbox);
3992   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3993
3994   vbox = gtk_vbox_new (FALSE, 5);
3995   gtk_widget_show (vbox);
3996   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
3997
3998   label = gtk_label_new ("ESC for default, ENTER to validate");
3999   gtk_widget_show (label);
4000   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
4001
4002   entry = gtk_entry_new ();
4003   gtk_widget_show (entry);
4004   gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4005
4006   vbox = gtk_vbox_new (FALSE, 5);
4007   gtk_widget_show (vbox);
4008   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
4009
4010   button = gtk_button_new_with_label ("OK");
4011   gtk_widget_show (button);
4012   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
4013   gtk_signal_connect (GTK_OBJECT (button), "clicked",
4014                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDOK));
4015   gtk_widget_add_accelerator (button, "clicked", accel_group,
4016                               GDK_Return, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
4017   gtk_widget_set_usize (button, 60, -2);
4018
4019   button = gtk_button_new_with_label ("Cancel");
4020   gtk_widget_show (button);
4021   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
4022   gtk_signal_connect (GTK_OBJECT (button), "clicked",
4023                       GTK_SIGNAL_FUNC (dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
4024   gtk_widget_add_accelerator (button, "clicked", accel_group,
4025                               GDK_Escape, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
4026   gtk_widget_set_usize (button, 60, -2);
4027
4028   char buf[16];
4029   sprintf (buf, "%d", *intensity);
4030   gtk_entry_set_text (GTK_ENTRY (entry), buf);
4031
4032   gtk_grab_add (dlg);
4033   gtk_widget_show (dlg);
4034
4035   while (loop)
4036     gtk_main_iteration ();
4037
4038   if (ret == IDOK)
4039     *intensity = atoi (gtk_entry_get_text (GTK_ENTRY (entry)));
4040
4041   gtk_grab_remove (dlg);
4042   gtk_widget_destroy (dlg);
4043
4044   return ret;
4045 }