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