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