]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/gtkdlgs.cpp
7174c8d06d5886aea5813b66fa1d412a68b980b0
[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 static const int ABT_WIDGET_PADDING = 8;
2501
2502 void about_button_changelog( GtkWidget *widget, gpointer data ){
2503         Str log;
2504         log = g_strAppPath;
2505         log += "changelog.txt";
2506         OpenURL( log.GetBuffer() );
2507 }
2508
2509 void about_button_credits( GtkWidget *widget, gpointer data ){
2510         Str cred;
2511         cred = g_strAppPath;
2512         cred += "credits.html";
2513         OpenURL( cred.GetBuffer() );
2514 }
2515
2516 void DoAbout(){
2517         int loop = 1, ret = IDCANCEL;
2518
2519         GtkWidget *main_vbox, *button_hbox, *gl_ext_hbox, *gl_ext_sc, *gl_ext_text;
2520         GtkWidget *frame, *button, *table, *label, *image; 
2521
2522         // dialog
2523         GtkWidget *dlg = gtk_window_new( GTK_WINDOW_TOPLEVEL );
2524         gtk_window_set_title( GTK_WINDOW( dlg ), _( "About GtkRadiant" ) );
2525         gtk_window_set_resizable( GTK_WINDOW( dlg ), FALSE );  
2526         gtk_signal_connect( GTK_OBJECT( dlg ), "delete_event",
2527                                                 GTK_SIGNAL_FUNC( dialog_delete_callback ), NULL );
2528         gtk_signal_connect( GTK_OBJECT( dlg ), "destroy",
2529                                                 GTK_SIGNAL_FUNC( gtk_widget_destroy ), NULL );
2530         g_object_set_data( G_OBJECT( dlg ), "loop", &loop );
2531         g_object_set_data( G_OBJECT( dlg ), "ret", &ret );
2532
2533         // layout top logo and everything else vertically without border padding
2534         GtkWidget *outer_vbox = gtk_vbox_new( FALSE, 0 );
2535         gtk_widget_show( outer_vbox );
2536         gtk_container_add( GTK_CONTAINER( dlg ), outer_vbox );
2537         gtk_container_set_border_width( GTK_CONTAINER( outer_vbox ), 0 );
2538
2539         // radiant logo
2540         CString s = g_strBitmapsPath;
2541         s += "logo.png";
2542         image = gtk_image_new_from_file( s.GetBuffer() );
2543         gtk_widget_show( image );
2544         gtk_box_pack_start( GTK_BOX( outer_vbox ), image, FALSE, FALSE, 0 );
2545
2546         // all other widgets layout
2547         main_vbox = gtk_vbox_new( FALSE, ABT_WIDGET_PADDING );
2548         gtk_widget_show( main_vbox );
2549         gtk_box_pack_start( GTK_BOX( outer_vbox ), main_vbox, FALSE, FALSE, 0 );
2550         gtk_container_set_border_width( GTK_CONTAINER( main_vbox ), ABT_WIDGET_PADDING );
2551
2552         // informative text
2553         GtkWidget *info_hbox = gtk_hbox_new( FALSE, 0 );
2554         gtk_widget_show( info_hbox );
2555         gtk_box_pack_start( GTK_BOX( main_vbox ), info_hbox, FALSE, FALSE, 0 );
2556
2557         label = gtk_label_new( "GtkRadiant " RADIANT_VERSION " - " __DATE__ "\n"
2558                                                    RADIANT_ABOUTMSG "\n\n"
2559                                                    "By http://icculus.org/gtkradiant/\n\n"
2560                                                    "This product contains software technology from id Software, Inc.\n"
2561                                                    "('id Technology'). id Technology 2000 id Software, Inc.\n\n"
2562                                                    "GtkRadiant is unsupported, however you may report your\n"
2563                                                    "problems at https://github.com/TTimo/GtkRadiant/issues" );
2564
2565         gtk_widget_show( label );
2566         gtk_box_pack_start( GTK_BOX( info_hbox ), label, FALSE, FALSE, 0 );
2567         gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT );
2568
2569         // OpenGL properties 
2570         frame = gtk_frame_new( _( "OpenGL Properties" ) );
2571         gtk_widget_show( frame );
2572         gtk_box_pack_start( GTK_BOX( main_vbox ), frame, FALSE, FALSE, 0 );
2573
2574         table = gtk_table_new( 3, 2, FALSE );
2575         gtk_widget_show( table );
2576         gtk_container_add( GTK_CONTAINER( frame ), table );
2577         gtk_table_set_row_spacings( GTK_TABLE( table ), 4 );
2578         gtk_table_set_col_spacings( GTK_TABLE( table ), 4 );
2579         gtk_container_set_border_width( GTK_CONTAINER( table ), 4 );
2580
2581         label = gtk_label_new( _( "Vendor:" ) );
2582         gtk_widget_show( label );
2583         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1,
2584                                           (GtkAttachOptions) ( GTK_FILL ),
2585                                           (GtkAttachOptions) ( 0 ), 0, 0 );
2586         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
2587
2588         label = gtk_label_new( _( "Version:" ) );
2589         gtk_widget_show( label );
2590         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 1, 2,
2591                                           (GtkAttachOptions) ( GTK_FILL ),
2592                                           (GtkAttachOptions) ( 0 ), 0, 0 );
2593         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
2594
2595         label = gtk_label_new( _( "Renderer:" ) );
2596         gtk_widget_show( label );
2597         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 2, 3,
2598                                           (GtkAttachOptions) ( GTK_FILL ),
2599                                           (GtkAttachOptions) ( 0 ), 0, 0 );
2600         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
2601
2602         label = gtk_label_new( (char*)qglGetString( GL_VENDOR ) );
2603         gtk_widget_show( label );
2604         gtk_table_attach( GTK_TABLE( table ), label, 1, 2, 0, 1,
2605                                           (GtkAttachOptions) ( GTK_FILL ),
2606                                           (GtkAttachOptions) ( 0 ), 0, 0 );
2607         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
2608
2609         label = gtk_label_new( (char*)qglGetString( GL_VERSION ) );
2610         gtk_widget_show( label );
2611         gtk_table_attach( GTK_TABLE( table ), label, 1, 2, 1, 2,
2612                                           (GtkAttachOptions) ( GTK_FILL ),
2613                                           (GtkAttachOptions) ( 0 ), 0, 0 );
2614         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
2615
2616         label = gtk_label_new( (char*)qglGetString( GL_RENDERER ) );
2617         gtk_widget_show( label );
2618         gtk_table_attach( GTK_TABLE( table ), label, 1, 2, 2, 3,
2619                                           (GtkAttachOptions) ( GTK_FILL ),
2620                                           (GtkAttachOptions) ( 0 ), 0, 0 );
2621         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
2622
2623         // OpenGL extensions
2624         frame = gtk_frame_new( _( "OpenGL Extensions" ) );
2625         gtk_widget_show( frame );
2626         gtk_box_pack_start( GTK_BOX( main_vbox ), frame, TRUE, TRUE, 0 );
2627
2628         gl_ext_hbox = gtk_hbox_new( FALSE, ABT_WIDGET_PADDING );
2629         gtk_widget_show( gl_ext_hbox );
2630         gtk_container_add( GTK_CONTAINER( frame ), gl_ext_hbox );
2631         gtk_container_set_border_width( GTK_CONTAINER( gl_ext_hbox ), 4 );
2632
2633         gl_ext_sc = gtk_scrolled_window_new( NULL, NULL );
2634         gtk_box_pack_start( GTK_BOX( gl_ext_hbox ), gl_ext_sc, TRUE, TRUE, 0 );
2635         gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( gl_ext_sc ), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS );
2636         gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( gl_ext_sc ), GTK_SHADOW_IN );
2637         gtk_widget_show( gl_ext_sc );
2638
2639         gl_ext_text = gtk_text_view_new();
2640         gtk_text_view_set_editable( GTK_TEXT_VIEW( gl_ext_text ), FALSE );
2641         gtk_container_add( GTK_CONTAINER( gl_ext_sc ), gl_ext_text );
2642         GtkTextBuffer* buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW( gl_ext_text ) );
2643         gtk_text_buffer_set_text( buffer, (char *)qglGetString( GL_EXTENSIONS ), -1 );
2644         gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW( gl_ext_text ), GTK_WRAP_WORD );;
2645         gtk_widget_show( gl_ext_text );
2646
2647         // buttons
2648         button_hbox = gtk_hbox_new( FALSE, 4 );
2649         gtk_widget_show( button_hbox );
2650         gtk_box_pack_start( GTK_BOX( main_vbox ), button_hbox, FALSE, TRUE, 0 );
2651
2652         button = gtk_button_new_with_label( _( "OK" ) );
2653         gtk_widget_show( button );
2654         gtk_box_pack_end( GTK_BOX( button_hbox ), button, FALSE, FALSE, 0 );
2655         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
2656                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDOK ) );
2657
2658         button = gtk_button_new_with_label( _( "Credits" ) );
2659         gtk_widget_show( button );
2660         gtk_box_pack_end( GTK_BOX( button_hbox ), button, FALSE, FALSE, 0 );
2661         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
2662                                                 GTK_SIGNAL_FUNC( about_button_credits ), NULL );
2663
2664         button = gtk_button_new_with_label( _( "Changelog" ) );
2665         gtk_widget_show( button );
2666         gtk_box_pack_end( GTK_BOX( button_hbox ), button, FALSE, FALSE, 0 );
2667         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
2668                                                 GTK_SIGNAL_FUNC( about_button_changelog ), NULL );
2669
2670         gtk_grab_add( dlg );
2671         gtk_widget_show( dlg );
2672
2673         while ( loop )
2674                 gtk_main_iteration();
2675
2676         gtk_grab_remove( dlg );
2677         gtk_widget_destroy( dlg );
2678 }
2679
2680 // =============================================================================
2681 // Command List dialog
2682
2683 void DoCommandListDlg(){
2684         GtkWidget *dlg, *vbox, *hbox, *scr, *button;
2685         int loop = 1, ret = IDCANCEL;
2686
2687         dlg = gtk_window_new( GTK_WINDOW_TOPLEVEL );
2688         gtk_window_set_title( GTK_WINDOW( dlg ), _( "Mapped Commands" ) );
2689         gtk_signal_connect( GTK_OBJECT( dlg ), "delete_event",
2690                                                 GTK_SIGNAL_FUNC( dialog_delete_callback ), NULL );
2691         gtk_signal_connect( GTK_OBJECT( dlg ), "destroy",
2692                                                 GTK_SIGNAL_FUNC( gtk_widget_destroy ), NULL );
2693         g_object_set_data( G_OBJECT( dlg ), "loop", &loop );
2694         g_object_set_data( G_OBJECT( dlg ), "ret", &ret );
2695         gtk_window_set_default_size( GTK_WINDOW( dlg ), 400, 400 );
2696
2697         hbox = gtk_hbox_new( FALSE, 5 );
2698         gtk_widget_show( hbox );
2699         gtk_container_add( GTK_CONTAINER( dlg ), hbox );
2700         gtk_container_set_border_width( GTK_CONTAINER( hbox ), 5 );
2701
2702         scr = gtk_scrolled_window_new( (GtkAdjustment*)NULL, (GtkAdjustment*)NULL );
2703         gtk_widget_show( scr );
2704         gtk_box_pack_start( GTK_BOX( hbox ), scr, TRUE, TRUE, 0 );
2705         gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scr ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );
2706         gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( scr ), GTK_SHADOW_IN );
2707
2708         {
2709                 GtkListStore* store = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_STRING );
2710
2711                 GtkWidget* view = gtk_tree_view_new_with_model( GTK_TREE_MODEL( store ) );
2712
2713                 {
2714                         GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
2715                         GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes( _( "Command" ), renderer, "text", 0, NULL );
2716                         gtk_tree_view_append_column( GTK_TREE_VIEW( view ), column );
2717                 }
2718
2719                 {
2720                         GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
2721                         GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes( _( "Key" ), renderer, "text", 1, NULL );
2722                         gtk_tree_view_append_column( GTK_TREE_VIEW( view ), column );
2723                 }
2724
2725                 gtk_widget_show( view );
2726                 gtk_container_add( GTK_CONTAINER( scr ), view );
2727
2728                 {
2729                         // Initialize dialog
2730                         CString path;
2731                         path = g_strTempPath;
2732                         path += "commandlist.txt";
2733
2734                         GSList *cmds = NULL;
2735                         int n;
2736
2737                         for ( n = 0; n < g_nCommandCount; n++ )
2738                                 cmds = g_slist_append( cmds, g_Commands[n].m_strCommand );
2739                         cmds = g_slist_sort( cmds, ( gint ( * )( const void *, const void * ) )strcmp );
2740
2741                         Sys_Printf( "Writing the command list to %s", path.GetBuffer() );
2742                         FILE * fileout = fopen( path.GetBuffer(), "wt" );
2743
2744                         while ( cmds )
2745                         {
2746                                 for ( n = 0; n < g_nCommandCount; n++ )
2747                                         if ( cmds->data == g_Commands[n].m_strCommand ) {
2748                                                 break;
2749                                         }
2750
2751                                 char c = g_Commands[n].m_nKey;
2752                                 CString strLine, strMod( "" ), strKeys( c );
2753
2754                                 for ( int k = 0; k < g_nKeyCount; k++ )
2755                                 {
2756                                         if ( g_Keys[k].m_nVKKey == g_Commands[n].m_nKey ) {
2757                                                 strKeys = g_Keys[k].m_strName;
2758                                                 break;
2759                                         }
2760                                 }
2761
2762                                 if ( g_Commands[n].m_nModifiers & RAD_SHIFT ) {
2763                                         strMod = "Shift";
2764                                 }
2765                                 if ( g_Commands[n].m_nModifiers & RAD_ALT ) {
2766                                         strMod += ( strMod.GetLength() > 0 ) ? " + Alt" : "Alt";
2767                                 }
2768                                 if ( g_Commands[n].m_nModifiers & RAD_CONTROL ) {
2769                                         strMod += ( strMod.GetLength() > 0 ) ? " + Control" : "Control";
2770                                 }
2771                                 if ( strMod.GetLength() > 0 ) {
2772                                         strMod += " + ";
2773                                 }
2774                                 strMod += strKeys;
2775
2776                                 {
2777                                         GtkTreeIter iter;
2778                                         gtk_list_store_append( store, &iter );
2779                                         gtk_list_store_set( store, &iter, 0, g_Commands[n].m_strCommand, 1, strMod.GetBuffer(), -1 );
2780                                 }
2781
2782                                 if ( fileout != NULL ) {
2783                                         strLine.Format( "%-25s %s\r\n", g_Commands[n].m_strCommand, strMod.GetBuffer() );
2784                                         fputs( strLine.GetBuffer(), fileout );
2785                                 }
2786
2787                                 cmds = g_slist_remove( cmds, cmds->data );
2788                         }
2789
2790                         if ( fileout != NULL ) {
2791                                 fclose( fileout );
2792                         }
2793                 }
2794
2795                 g_object_unref( G_OBJECT( store ) );
2796         }
2797
2798         vbox = gtk_vbox_new( FALSE, 5 );
2799         gtk_widget_show( vbox );
2800         gtk_box_pack_start( GTK_BOX( hbox ), vbox, FALSE, FALSE, 0 );
2801
2802         button = gtk_button_new_with_label( _( "Close" ) );;
2803         gtk_widget_show( button );
2804         gtk_box_pack_end( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
2805         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
2806                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDOK ) );
2807         gtk_widget_set_usize( button, 60, -2 );
2808
2809         gtk_grab_add( dlg );
2810         gtk_widget_show( dlg );
2811
2812         while ( loop )
2813                 gtk_main_iteration();
2814
2815         gtk_grab_remove( dlg );
2816         gtk_widget_destroy( dlg );
2817 }
2818
2819 // =============================================================================
2820 // Texture List dialog
2821
2822 void DoTextureListDlg(){
2823         GtkWidget *dlg, *vbox, *hbox, *scr, *button;
2824         int loop = 1, ret = IDCANCEL;
2825
2826         dlg = gtk_window_new( GTK_WINDOW_TOPLEVEL );
2827         gtk_window_set_title( GTK_WINDOW( dlg ), _( "Textures" ) );
2828         gtk_signal_connect( GTK_OBJECT( dlg ), "delete_event",
2829                                                 GTK_SIGNAL_FUNC( dialog_delete_callback ), NULL );
2830         gtk_signal_connect( GTK_OBJECT( dlg ), "destroy",
2831                                                 GTK_SIGNAL_FUNC( gtk_widget_destroy ), NULL );
2832         g_object_set_data( G_OBJECT( dlg ), "loop", &loop );
2833         g_object_set_data( G_OBJECT( dlg ), "ret", &ret );
2834         gtk_window_set_default_size( GTK_WINDOW( dlg ), 400, 400 );
2835
2836         hbox = gtk_hbox_new( FALSE, 5 );
2837         gtk_widget_show( hbox );
2838         gtk_container_add( GTK_CONTAINER( dlg ), hbox );
2839         gtk_container_set_border_width( GTK_CONTAINER( hbox ), 5 );
2840
2841         scr = gtk_scrolled_window_new( (GtkAdjustment*)NULL, (GtkAdjustment*)NULL );
2842         gtk_widget_show( scr );
2843         gtk_box_pack_start( GTK_BOX( hbox ), scr, TRUE, TRUE, 0 );
2844         gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scr ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );
2845         gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( scr ), GTK_SHADOW_IN );
2846
2847         GtkWidget* texture_list;
2848
2849         {
2850                 GtkListStore* store = gtk_list_store_new( 1, G_TYPE_STRING );
2851
2852                 GtkWidget* view = gtk_tree_view_new_with_model( GTK_TREE_MODEL( store ) );
2853                 gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( view ), FALSE );
2854
2855                 {
2856                         GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
2857                         GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes( "", renderer, "text", 0, NULL );
2858                         gtk_tree_view_append_column( GTK_TREE_VIEW( view ), column );
2859                 }
2860
2861                 gtk_widget_show( view );
2862                 gtk_container_add( GTK_CONTAINER( scr ), view );
2863
2864                 {
2865                         // Initialize dialog
2866                         GSList *textures = (GSList*)NULL;
2867                         FillTextureMenu( &textures );
2868                         while ( textures != NULL )
2869                         {
2870                                 {
2871                                         GtkTreeIter iter;
2872                                         gtk_list_store_append( store, &iter );
2873                                         gtk_list_store_set( store, &iter, 0, (gchar*)textures->data, -1 );
2874                                 }
2875                                 free( textures->data );
2876                                 textures = g_slist_remove( textures, textures->data );
2877                         }
2878                 }
2879
2880                 g_object_unref( G_OBJECT( store ) );
2881
2882                 texture_list = view;
2883         }
2884
2885         vbox = gtk_vbox_new( FALSE, 5 );
2886         gtk_widget_show( vbox );
2887         gtk_box_pack_start( GTK_BOX( hbox ), vbox, FALSE, FALSE, 0 );
2888
2889         button = gtk_button_new_with_label( _( "Load" ) );;
2890         gtk_widget_show( button );
2891         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
2892         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
2893                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDOK ) );
2894         gtk_widget_set_usize( button, 60, -2 );
2895
2896         button = gtk_button_new_with_label( _( "Close" ) );;
2897         gtk_widget_show( button );
2898         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
2899         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
2900                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) );
2901         gtk_widget_set_usize( button, 60, -2 );
2902
2903         gtk_grab_add( dlg );
2904         gtk_widget_show( dlg );
2905
2906         while ( loop )
2907                 gtk_main_iteration();
2908
2909         if ( ret == IDOK ) {
2910                 GtkTreeSelection* selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( texture_list ) );
2911
2912                 GtkTreeModel* model;
2913                 GtkTreeIter iter;
2914                 if ( gtk_tree_selection_get_selected( selection, &model, &iter ) ) {
2915                         GtkTreePath* path = gtk_tree_model_get_path( model, &iter );
2916                         if ( gtk_tree_path_get_depth( path ) == 1 ) {
2917                                 Texture_ShowDirectory( gtk_tree_path_get_indices( path )[0] + CMD_TEXTUREWAD );
2918                         }
2919                         gtk_tree_path_free( path );
2920                 }
2921         }
2922
2923         gtk_grab_remove( dlg );
2924         gtk_widget_destroy( dlg );
2925 }
2926
2927 // =============================================================================
2928 // Cap dialog
2929
2930 int DoCapDlg( int *type, bool *b_GroupResult ){
2931         GtkWidget *dlg, *vbox, *hbox, *table, *pixmap, *button, *group_toggle, *radio_vbox;
2932         GtkWidget *bevel, *endcap, *ibevel, *iendcap;
2933         GSList *group = (GSList*)NULL;
2934         int loop = 1, ret = IDCANCEL;
2935
2936         dlg = gtk_window_new( GTK_WINDOW_TOPLEVEL );
2937         gtk_window_set_title( GTK_WINDOW( dlg ), _( "Cap" ) );
2938         gtk_signal_connect( GTK_OBJECT( dlg ), "delete_event",
2939                                                 GTK_SIGNAL_FUNC( dialog_delete_callback ), NULL );
2940         gtk_signal_connect( GTK_OBJECT( dlg ), "destroy",
2941                                                 GTK_SIGNAL_FUNC( gtk_widget_destroy ), NULL );
2942         g_object_set_data( G_OBJECT( dlg ), "loop", &loop );
2943         g_object_set_data( G_OBJECT( dlg ), "ret", &ret );
2944
2945         hbox = gtk_hbox_new( FALSE, 5 );
2946         gtk_widget_show( hbox );
2947         gtk_container_add( GTK_CONTAINER( dlg ), hbox );
2948         gtk_container_set_border_width( GTK_CONTAINER( hbox ), 5 );
2949
2950         // Gef: Added a vbox to contain the toggle buttons
2951         radio_vbox = gtk_vbox_new( FALSE, 4 );
2952         gtk_container_add( GTK_CONTAINER( hbox ), radio_vbox );
2953         gtk_widget_show( radio_vbox );
2954
2955         table = gtk_table_new( 4, 2, FALSE );
2956         gtk_widget_show( table );
2957         gtk_box_pack_start( GTK_BOX( radio_vbox ), table, TRUE, TRUE, 0 );
2958         gtk_table_set_row_spacings( GTK_TABLE( table ), 5 );
2959         gtk_table_set_col_spacings( GTK_TABLE( table ), 5 );
2960
2961         pixmap = new_pixmap( g_pParentWnd->m_pWidget, "cap_bevel.bmp" );
2962         gtk_widget_show( pixmap );
2963         gtk_table_attach( GTK_TABLE( table ), pixmap, 0, 1, 0, 1,
2964                                           (GtkAttachOptions) ( GTK_FILL ),
2965                                           (GtkAttachOptions) ( 0 ), 0, 0 );
2966
2967         pixmap = new_pixmap( g_pParentWnd->m_pWidget, "cap_endcap.bmp" );
2968         gtk_widget_show( pixmap );
2969         gtk_table_attach( GTK_TABLE( table ), pixmap, 0, 1, 1, 2,
2970                                           (GtkAttachOptions) ( GTK_FILL ),
2971                                           (GtkAttachOptions) ( 0 ), 0, 0 );
2972
2973         pixmap = new_pixmap( g_pParentWnd->m_pWidget, "cap_ibevel.bmp" );
2974         gtk_widget_show( pixmap );
2975         gtk_table_attach( GTK_TABLE( table ), pixmap, 0, 1, 2, 3,
2976                                           (GtkAttachOptions) ( GTK_FILL ),
2977                                           (GtkAttachOptions) ( 0 ), 0, 0 );
2978
2979         pixmap = new_pixmap( g_pParentWnd->m_pWidget, "cap_iendcap.bmp" );
2980         gtk_widget_show( pixmap );
2981         gtk_table_attach( GTK_TABLE( table ), pixmap, 0, 1, 3, 4,
2982                                           (GtkAttachOptions) ( GTK_FILL ),
2983                                           (GtkAttachOptions) ( 0 ), 0, 0 );
2984
2985         bevel = gtk_radio_button_new_with_label( group, _( "Bevel" ) );
2986         gtk_widget_show( bevel );
2987         gtk_table_attach( GTK_TABLE( table ), bevel, 1, 2, 0, 1,
2988                                           (GtkAttachOptions) ( GTK_FILL | GTK_EXPAND ),
2989                                           (GtkAttachOptions) ( 0 ), 0, 0 );
2990         group = gtk_radio_button_group( GTK_RADIO_BUTTON( bevel ) );
2991
2992         endcap = gtk_radio_button_new_with_label( group, _( "Endcap" ) );
2993         gtk_widget_show( endcap );
2994         gtk_table_attach( GTK_TABLE( table ), endcap, 1, 2, 1, 2,
2995                                           (GtkAttachOptions) ( GTK_FILL | GTK_EXPAND ),
2996                                           (GtkAttachOptions) ( 0 ), 0, 0 );
2997         group = gtk_radio_button_group( GTK_RADIO_BUTTON( endcap ) );
2998
2999         ibevel = gtk_radio_button_new_with_label( group, _( "Inverted Bevel" ) );
3000         gtk_widget_show( ibevel );
3001         gtk_table_attach( GTK_TABLE( table ), ibevel, 1, 2, 2, 3,
3002                                           (GtkAttachOptions) ( GTK_FILL | GTK_EXPAND ),
3003                                           (GtkAttachOptions) ( 0 ), 0, 0 );
3004         group = gtk_radio_button_group( GTK_RADIO_BUTTON( ibevel ) );
3005
3006         iendcap = gtk_radio_button_new_with_label( group, _( "Inverted Endcap" ) );
3007         gtk_widget_show( iendcap );
3008         gtk_table_attach( GTK_TABLE( table ), iendcap, 1, 2, 3, 4,
3009                                           (GtkAttachOptions) ( GTK_FILL | GTK_EXPAND ),
3010                                           (GtkAttachOptions) ( 0 ), 0, 0 );
3011         group = gtk_radio_button_group( GTK_RADIO_BUTTON( iendcap ) );
3012
3013         // Gef: added radio toggle for func_grouping capped patches
3014         group_toggle = gtk_check_button_new_with_label( _( "Result to func_group" ) );
3015         gtk_container_add( GTK_CONTAINER( radio_vbox ), group_toggle );
3016         gtk_widget_show( group_toggle );
3017
3018         vbox = gtk_vbox_new( FALSE, 5 );
3019         gtk_widget_show( vbox );
3020         gtk_box_pack_start( GTK_BOX( hbox ), vbox, FALSE, FALSE, 0 );
3021
3022         button = gtk_button_new_with_label( _( "OK" ) );
3023         gtk_widget_show( button );
3024         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
3025         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3026                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDOK ) );
3027         gtk_widget_set_usize( button, 60, -2 );
3028
3029         button = gtk_button_new_with_label( _( "Cancel" ) );
3030         gtk_widget_show( button );
3031         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
3032         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3033                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) );
3034         gtk_widget_set_usize( button, 60, -2 );
3035
3036         // Gef: Set the state of the func_group toggle
3037         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( group_toggle ), *b_GroupResult );
3038
3039         // Initialize dialog
3040         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( bevel ), TRUE );
3041
3042         gtk_grab_add( dlg );
3043         gtk_widget_show( dlg );
3044
3045         while ( loop )
3046                 gtk_main_iteration();
3047
3048         if ( ret == IDOK ) {
3049                 if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( bevel ) ) ) {
3050                         *type = BEVEL; //*type = CapDialog::BEVEL;
3051                 }
3052                 else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( endcap ) ) ) {
3053                         *type = ENDCAP; //*type = CapDialog::ENDCAP;
3054                 }
3055                 else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( ibevel ) ) ) {
3056                         *type = IBEVEL; // *type = CapDialog::IBEVEL;
3057                 }
3058                 else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( iendcap ) ) ) {
3059                         *type = IENDCAP; // *type = CapDialog::IENDCAP;
3060
3061                 }
3062                 // Gef: Added toggle for optional cap func_grouping
3063                 *b_GroupResult = (bool)gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( group_toggle ) );
3064         }
3065
3066         gtk_grab_remove( dlg );
3067         gtk_widget_destroy( dlg );
3068
3069         return ret;
3070 }
3071
3072 // =============================================================================
3073 // Scripts dialog
3074
3075 void DoScriptsDlg(){
3076         GtkWidget *dlg, *vbox, *vbox2, *hbox, *label, *button, *scr;
3077         int loop = 1, ret = IDCANCEL;
3078
3079         dlg = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3080         gtk_window_set_title( GTK_WINDOW( dlg ), _( "Available Scripts - Not Implemented Yet" ) );
3081         gtk_signal_connect( GTK_OBJECT( dlg ), "delete_event",
3082                                                 GTK_SIGNAL_FUNC( dialog_delete_callback ), NULL );
3083         gtk_signal_connect( GTK_OBJECT( dlg ), "destroy",
3084                                                 GTK_SIGNAL_FUNC( gtk_widget_destroy ), NULL );
3085         g_object_set_data( G_OBJECT( dlg ), "loop", &loop );
3086         g_object_set_data( G_OBJECT( dlg ), "ret", &ret );
3087
3088         vbox = gtk_vbox_new( FALSE, 5 );
3089         gtk_widget_show( vbox );
3090         gtk_container_add( GTK_CONTAINER( dlg ), vbox );
3091         gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
3092
3093         label = gtk_label_new( _( "WARNING: BrushScripting is in a highly experimental state and is\n"
3094                                                           "far from complete. If you attempt to use them it is VERY LIKELY\n"
3095                                                           "that Radiant will crash. Save your work before attempting to\n"
3096                                                           "make use of any scripting features." ) );
3097         gtk_widget_show( label );
3098         gtk_box_pack_start( GTK_BOX( vbox ), label, FALSE, FALSE, 0 );
3099         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
3100         gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT );
3101
3102         hbox = gtk_hbox_new( FALSE, 5 );
3103         gtk_widget_show( hbox );
3104         gtk_box_pack_start( GTK_BOX( vbox ), hbox, TRUE, TRUE, 0 );
3105
3106         scr = gtk_scrolled_window_new( (GtkAdjustment*)NULL, (GtkAdjustment*)NULL );
3107         gtk_widget_show( scr );
3108         gtk_box_pack_start( GTK_BOX( hbox ), scr, TRUE, TRUE, 0 );
3109         gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scr ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );
3110         gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( scr ), GTK_SHADOW_IN );
3111
3112         GtkWidget* scripts_list;
3113
3114         {
3115                 GtkListStore* store = gtk_list_store_new( 1, G_TYPE_STRING );
3116
3117                 GtkWidget* view = gtk_tree_view_new_with_model( GTK_TREE_MODEL( store ) );
3118                 gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( view ), FALSE );
3119
3120                 {
3121                         GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
3122                         GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes( "", renderer, "text", 0, NULL );
3123                         gtk_tree_view_append_column( GTK_TREE_VIEW( view ), column );
3124                 }
3125
3126                 gtk_widget_show( view );
3127                 gtk_container_add( GTK_CONTAINER( scr ), view );
3128
3129                 {
3130                         // Initialize dialog
3131                         CString strINI;
3132                         strINI = g_strGameToolsPath;
3133                         strINI += "/scripts.ini";
3134                         FILE *f;
3135
3136                         f = fopen( strINI.GetBuffer(), "rt" );
3137                         if ( f != NULL ) {
3138                                 char line[1024], *ptr;
3139
3140                                 // read section names
3141                                 while ( fgets( line, 1024, f ) != 0 )
3142                                 {
3143                                         if ( line[0] != '[' ) {
3144                                                 continue;
3145                                         }
3146
3147                                         ptr = strchr( line, ']' );
3148                                         *ptr = '\0';
3149
3150                                         {
3151                                                 GtkTreeIter iter;
3152                                                 gtk_list_store_append( store, &iter );
3153                                                 gtk_list_store_set( store, &iter, 0, line, -1 );
3154                                         }
3155                                 }
3156                                 fclose( f );
3157                         }
3158                 }
3159
3160                 g_object_unref( G_OBJECT( store ) );
3161
3162                 scripts_list = view;
3163         }
3164
3165         vbox2 = gtk_vbox_new( FALSE, 5 );
3166         gtk_widget_show( vbox2 );
3167         gtk_box_pack_start( GTK_BOX( hbox ), vbox2, FALSE, FALSE, 0 );
3168
3169         button = gtk_button_new_with_label( _( "Run" ) );
3170         gtk_widget_show( button );
3171         gtk_box_pack_start( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 );
3172         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3173                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDOK ) );
3174         gtk_widget_set_usize( button, 60, -2 );
3175
3176         button = gtk_button_new_with_label( _( "New..." ) );
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( _( "Edit..." ) );
3183         gtk_widget_show( button );
3184         gtk_box_pack_start( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 );
3185         gtk_widget_set_sensitive( button, FALSE );
3186         gtk_widget_set_usize( button, 60, -2 );
3187
3188         button = gtk_button_new_with_label( _( "Close" ) );
3189         gtk_widget_show( button );
3190         gtk_box_pack_end( GTK_BOX( vbox2 ), button, FALSE, FALSE, 0 );
3191         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3192                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) );
3193         gtk_widget_set_usize( button, 60, -2 );
3194
3195         gtk_grab_add( dlg );
3196         gtk_widget_show( dlg );
3197
3198         while ( loop )
3199                 gtk_main_iteration();
3200
3201         if ( ret == IDOK ) {
3202                 GtkTreeSelection* selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( scripts_list ) );
3203
3204                 GtkTreeModel* model;
3205                 GtkTreeIter iter;
3206                 if ( gtk_tree_selection_get_selected( selection, &model, &iter ) ) {
3207                         char* script;
3208                         gtk_tree_model_get( model, &iter, 0, &script, -1 );
3209                         RunScriptByName( script, true );
3210                         g_free( script );
3211                 }
3212         }
3213
3214         gtk_grab_remove( dlg );
3215         gtk_widget_destroy( dlg );
3216 }
3217
3218 // =============================================================================
3219 //  dialog
3220
3221 int DoBSInputDlg( const char *fields[5], float values[5] ){
3222         GtkWidget *dlg, *vbox, *hbox, *label, *button;
3223         GtkWidget *entries[5];
3224         int i, loop = 1, ret = IDCANCEL;
3225
3226         dlg = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3227         gtk_window_set_title( GTK_WINDOW( dlg ), _( "BrushScript Input" ) );
3228         gtk_signal_connect( GTK_OBJECT( dlg ), "delete_event",
3229                                                 GTK_SIGNAL_FUNC( dialog_delete_callback ), NULL );
3230         gtk_signal_connect( GTK_OBJECT( dlg ), "destroy",
3231                                                 GTK_SIGNAL_FUNC( gtk_widget_destroy ), NULL );
3232         g_object_set_data( G_OBJECT( dlg ), "loop", &loop );
3233         g_object_set_data( G_OBJECT( dlg ), "ret", &ret );
3234
3235         hbox = gtk_hbox_new( FALSE, 5 );
3236         gtk_widget_show( hbox );
3237         gtk_container_add( GTK_CONTAINER( dlg ), hbox );
3238         gtk_container_set_border_width( GTK_CONTAINER( hbox ), 5 );
3239
3240         vbox = gtk_vbox_new( FALSE, 5 );
3241         gtk_widget_show( vbox );
3242         gtk_box_pack_start( GTK_BOX( hbox ), vbox, TRUE, TRUE, 0 );
3243
3244         // Create entries and initialize them
3245         for ( i = 0; i < 5; i++ )
3246         {
3247                 if ( strlen( fields[i] ) == 0 ) {
3248                         continue;
3249                 }
3250
3251                 label = gtk_label_new( fields[i] );
3252                 gtk_widget_show( label );
3253                 gtk_box_pack_start( GTK_BOX( vbox ), label, FALSE, FALSE, 0 );
3254                 gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
3255                 gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT );
3256
3257                 entries[i] = gtk_entry_new();
3258                 gtk_widget_show( entries[i] );
3259                 gtk_box_pack_start( GTK_BOX( vbox ), entries[i], TRUE, TRUE, 0 );
3260
3261                 char buf[32];
3262                 sprintf( buf, "%f", values[i] );
3263                 gtk_entry_set_text( GTK_ENTRY( entries[i] ), buf );
3264         }
3265
3266         vbox = gtk_vbox_new( FALSE, 5 );
3267         gtk_widget_show( vbox );
3268         gtk_box_pack_start( GTK_BOX( hbox ), vbox, FALSE, FALSE, 0 );
3269
3270         button = gtk_button_new_with_label( _( "OK" ) );
3271         gtk_widget_show( button );
3272         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
3273         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3274                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDOK ) );
3275         gtk_widget_set_usize( button, 60, -2 );
3276
3277         button = gtk_button_new_with_label( _( "Cancel" ) );
3278         gtk_widget_show( button );
3279         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
3280         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3281                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) );
3282         gtk_widget_set_usize( button, 60, -2 );
3283
3284         gtk_grab_add( dlg );
3285         gtk_widget_show( dlg );
3286
3287         while ( loop )
3288                 gtk_main_iteration();
3289
3290         for ( i = 0; i < 5; i++ )
3291         {
3292                 if ( strlen( fields[i] ) == 0 ) {
3293                         continue;
3294                 }
3295
3296                 values[i] = atof( gtk_entry_get_text( GTK_ENTRY( entries[i] ) ) );
3297         }
3298
3299         gtk_grab_remove( dlg );
3300         gtk_widget_destroy( dlg );
3301
3302         return ret;
3303 }
3304
3305 // =============================================================================
3306 // TextureLayout dialog
3307
3308 int DoTextureLayout( float *fx, float *fy ){
3309         GtkWidget *dlg, *vbox, *hbox, *table, *label, *button;
3310         GtkWidget *x, *y;
3311         int loop = 1, ret = IDCANCEL;
3312
3313         dlg = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3314         gtk_window_set_title( GTK_WINDOW( dlg ), _( "Patch texture layout" ) );
3315         gtk_signal_connect( GTK_OBJECT( dlg ), "delete_event",
3316                                                 GTK_SIGNAL_FUNC( dialog_delete_callback ), NULL );
3317         gtk_signal_connect( GTK_OBJECT( dlg ), "destroy",
3318                                                 GTK_SIGNAL_FUNC( gtk_widget_destroy ), NULL );
3319         g_object_set_data( G_OBJECT( dlg ), "loop", &loop );
3320         g_object_set_data( G_OBJECT( dlg ), "ret", &ret );
3321
3322         hbox = gtk_hbox_new( FALSE, 5 );
3323         gtk_widget_show( hbox );
3324         gtk_container_add( GTK_CONTAINER( dlg ), hbox );
3325         gtk_container_set_border_width( GTK_CONTAINER( hbox ), 5 );
3326
3327         vbox = gtk_vbox_new( FALSE, 5 );
3328         gtk_widget_show( vbox );
3329         gtk_box_pack_start( GTK_BOX( hbox ), vbox, TRUE, TRUE, 0 );
3330
3331         label = gtk_label_new( _( "Texture will be fit across the patch based\n"
3332                                                           "on the x and y values given. Values of 1x1\n"
3333                                                           "will \"fit\" the texture. 2x2 will repeat\n"
3334                                                           "it twice, etc." ) );
3335         gtk_widget_show( label );
3336         gtk_box_pack_start( GTK_BOX( vbox ), label, TRUE, TRUE, 0 );
3337         gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT );
3338
3339         table = gtk_table_new( 2, 2, FALSE );
3340         gtk_widget_show( table );
3341         gtk_box_pack_start( GTK_BOX( vbox ), table, TRUE, TRUE, 0 );
3342         gtk_table_set_row_spacings( GTK_TABLE( table ), 5 );
3343         gtk_table_set_col_spacings( GTK_TABLE( table ), 5 );
3344
3345         label = gtk_label_new( _( "Texture x:" ) );
3346         gtk_widget_show( label );
3347         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1,
3348                                           (GtkAttachOptions) ( GTK_FILL ),
3349                                           (GtkAttachOptions) ( 0 ), 0, 0 );
3350         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
3351
3352         label = gtk_label_new( _( "Texture y:" ) );
3353         gtk_widget_show( label );
3354         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 1, 2,
3355                                           (GtkAttachOptions) ( GTK_FILL ),
3356                                           (GtkAttachOptions) ( 0 ), 0, 0 );
3357         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
3358
3359         x = gtk_entry_new();
3360         gtk_widget_show( x );
3361         gtk_table_attach( GTK_TABLE( table ), x, 1, 2, 0, 1,
3362                                           (GtkAttachOptions) ( GTK_EXPAND | GTK_FILL ),
3363                                           (GtkAttachOptions) ( 0 ), 0, 0 );
3364
3365         y = gtk_entry_new();
3366         gtk_widget_show( y );
3367         gtk_table_attach( GTK_TABLE( table ), y, 1, 2, 1, 2,
3368                                           (GtkAttachOptions) ( GTK_EXPAND | GTK_FILL ),
3369                                           (GtkAttachOptions) ( 0 ), 0, 0 );
3370
3371         vbox = gtk_vbox_new( FALSE, 5 );
3372         gtk_widget_show( vbox );
3373         gtk_box_pack_start( GTK_BOX( hbox ), vbox, FALSE, FALSE, 0 );
3374
3375         button = gtk_button_new_with_label( _( "OK" ) );
3376         gtk_widget_show( button );
3377         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
3378         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3379                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDOK ) );
3380         gtk_widget_set_usize( button, 60, -2 );
3381
3382         button = gtk_button_new_with_label( _( "Cancel" ) );
3383         gtk_widget_show( button );
3384         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
3385         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3386                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) );
3387         gtk_widget_set_usize( button, 60, -2 );
3388
3389         // Initialize
3390         gtk_entry_set_text( GTK_ENTRY( x ), _( "4.0" ) );
3391         gtk_entry_set_text( GTK_ENTRY( y ), _( "4.0" ) );
3392
3393         gtk_grab_add( dlg );
3394         gtk_widget_show( dlg );
3395
3396         while ( loop )
3397                 gtk_main_iteration();
3398
3399         if ( ret == IDOK ) {
3400                 *fx = atof( gtk_entry_get_text( GTK_ENTRY( x ) ) );
3401                 *fy = atof( gtk_entry_get_text( GTK_ENTRY( y ) ) );
3402         }
3403
3404         gtk_grab_remove( dlg );
3405         gtk_widget_destroy( dlg );
3406
3407         return ret;
3408 }
3409
3410 // =============================================================================
3411 // Name dialog
3412
3413 char* DoNameDlg( const char* title ){
3414         GtkWidget *dlg, *vbox, *hbox, *label, *button, *entry;
3415         int loop = 1, ret = IDCANCEL;
3416         char *str;
3417
3418         dlg = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3419         gtk_window_set_title( GTK_WINDOW( dlg ), title );
3420         gtk_signal_connect( GTK_OBJECT( dlg ), "delete_event",
3421                                                 GTK_SIGNAL_FUNC( dialog_delete_callback ), NULL );
3422         gtk_signal_connect( GTK_OBJECT( dlg ), "destroy",
3423                                                 GTK_SIGNAL_FUNC( gtk_widget_destroy ), NULL );
3424         g_object_set_data( G_OBJECT( dlg ), "loop", &loop );
3425         g_object_set_data( G_OBJECT( dlg ), "ret", &ret );
3426
3427         hbox = gtk_hbox_new( FALSE, 5 );
3428         gtk_widget_show( hbox );
3429         gtk_container_add( GTK_CONTAINER( dlg ), hbox );
3430         gtk_container_set_border_width( GTK_CONTAINER( hbox ), 5 );
3431
3432         label = gtk_label_new( _( "Name:" ) );
3433         gtk_widget_show( label );
3434         gtk_box_pack_start( GTK_BOX( hbox ), label, FALSE, FALSE, 0 );
3435
3436         entry = gtk_entry_new();
3437         gtk_widget_show( entry );
3438         gtk_box_pack_start( GTK_BOX( hbox ), entry, TRUE, TRUE, 0 );
3439
3440         vbox = gtk_vbox_new( FALSE, 5 );
3441         gtk_widget_show( vbox );
3442         gtk_box_pack_start( GTK_BOX( hbox ), vbox, FALSE, FALSE, 0 );
3443
3444         button = gtk_button_new_with_label( _( "OK" ) );
3445         gtk_widget_show( button );
3446         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
3447         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3448                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDOK ) );
3449         gtk_widget_set_usize( button, 60, -2 );
3450
3451         button = gtk_button_new_with_label( _( "Cancel" ) );
3452         gtk_widget_show( button );
3453         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
3454         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3455                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) );
3456         gtk_widget_set_usize( button, 60, -2 );
3457
3458         gtk_grab_add( dlg );
3459         gtk_widget_show( dlg );
3460
3461         while ( loop )
3462                 gtk_main_iteration();
3463
3464         if ( ret == IDOK ) {
3465                 str = strdup( gtk_entry_get_text( GTK_ENTRY( entry ) ) );
3466         }
3467         else{
3468                 str = NULL;
3469         }
3470
3471         gtk_grab_remove( dlg );
3472         gtk_widget_destroy( dlg );
3473
3474         return str;
3475 }
3476
3477 // =============================================================================
3478 // NewProject dialog
3479
3480 char* DoNewProjectDlg(){
3481         GtkWidget *dlg, *vbox, *hbox, *label, *button, *entry, *check;
3482         int loop = 1, ret = IDCANCEL;
3483         char *str;
3484
3485         // start by a warning message
3486 // mattn: URLs no longer valid
3487 //  CString msg;
3488 //  msg = "Are you sure you want a new project?\n";
3489 //  msg += "Please note that creating a new project is not the prefered way to setup GtkRadiant for mod editing.\n";
3490 //  msg += "Check http://www.qeradiant.com/faq/index.cgi?file=220 for more information";
3491 //  if (gtk_MessageBox(NULL, msg.GetBuffer(), _("Confirm"), MB_YESNO, "http://www.qeradiant.com/faq/index.cgi?file=220" ) == IDNO)
3492 //  {
3493 //    return NULL;
3494 //  }
3495
3496         dlg = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3497         gtk_window_set_title( GTK_WINDOW( dlg ), _( "New Project" ) );
3498         gtk_signal_connect( GTK_OBJECT( dlg ), "delete_event",
3499                                                 GTK_SIGNAL_FUNC( dialog_delete_callback ), NULL );
3500         gtk_signal_connect( GTK_OBJECT( dlg ), "destroy",
3501                                                 GTK_SIGNAL_FUNC( gtk_widget_destroy ), NULL );
3502         g_object_set_data( G_OBJECT( dlg ), "loop", &loop );
3503         g_object_set_data( G_OBJECT( dlg ), "ret", &ret );
3504
3505         hbox = gtk_hbox_new( FALSE, 10 );
3506         gtk_widget_show( hbox );
3507         gtk_container_add( GTK_CONTAINER( dlg ), hbox );
3508         gtk_container_set_border_width( GTK_CONTAINER( hbox ), 5 );
3509
3510         vbox = gtk_vbox_new( FALSE, 5 );
3511         gtk_widget_show( vbox );
3512         gtk_box_pack_start( GTK_BOX( hbox ), vbox, FALSE, FALSE, 0 );
3513
3514         label = gtk_label_new( _( "This will create a new directory beneath your\n"
3515                                                           "game path based on the project name you give." ) );
3516         gtk_widget_show( label );
3517         gtk_box_pack_start( GTK_BOX( vbox ), label, FALSE, FALSE, 0 );
3518         gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT );
3519
3520         label = gtk_label_new( _( "Project name:" ) );
3521         gtk_widget_show( label );
3522         gtk_box_pack_start( GTK_BOX( vbox ), label, TRUE, TRUE, 0 );
3523         gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT );
3524         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
3525
3526         entry = gtk_entry_new();
3527         gtk_widget_show( entry );
3528         gtk_box_pack_start( GTK_BOX( vbox ), entry, TRUE, TRUE, 0 );
3529
3530         check = gtk_check_button_new_with_label( _( "Include game dll files" ) );
3531         gtk_widget_show( check );
3532         gtk_box_pack_start( GTK_BOX( vbox ), check, TRUE, TRUE, 0 );
3533         gtk_widget_set_sensitive( check, FALSE );
3534
3535         vbox = gtk_vbox_new( FALSE, 5 );
3536         gtk_widget_show( vbox );
3537         gtk_box_pack_start( GTK_BOX( hbox ), vbox, FALSE, FALSE, 0 );
3538
3539         button = gtk_button_new_with_label( _( "OK" ) );
3540         gtk_widget_show( button );
3541         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
3542         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3543                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDOK ) );
3544         gtk_widget_set_usize( button, 60, -2 );
3545
3546         button = gtk_button_new_with_label( _( "Cancel" ) );
3547         gtk_widget_show( button );
3548         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
3549         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3550                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) );
3551         gtk_widget_set_usize( button, 60, -2 );
3552
3553         gtk_grab_add( dlg );
3554         gtk_widget_show( dlg );
3555
3556         while ( loop )
3557                 gtk_main_iteration();
3558
3559         if ( ret == IDOK ) {
3560                 str = strdup( gtk_entry_get_text( GTK_ENTRY( entry ) ) );
3561         }
3562         else{
3563                 str = NULL;
3564         }
3565
3566         gtk_grab_remove( dlg );
3567         gtk_widget_destroy( dlg );
3568
3569         return str;
3570 }
3571
3572 // =============================================================================
3573 // Text Editor dialog
3574
3575 // master window widget
3576 static GtkWidget *text_editor = NULL;
3577 static GtkWidget *text_widget; // slave, text widget from the gtk editor
3578
3579 static gint editor_delete( GtkWidget *widget, gpointer data ){
3580         if ( gtk_MessageBox( widget, _( "Close the shader editor ?" ), _( "Radiant" ), MB_YESNO ) == IDNO ) {
3581                 return TRUE;
3582         }
3583
3584         gtk_widget_hide( text_editor );
3585
3586         return TRUE;
3587 }
3588
3589 static void editor_save( GtkWidget *widget, gpointer data ){
3590         FILE *f = fopen( (char*)g_object_get_data( G_OBJECT( data ), "filename" ), "w" );
3591         gpointer text = g_object_get_data( G_OBJECT( data ), "text" );
3592
3593         if ( f == NULL ) {
3594                 gtk_MessageBox( GTK_WIDGET( data ), _( "Error saving file !" ) );
3595                 return;
3596         }
3597
3598         GtkTextBuffer *buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW( text ) );
3599         GtkTextIter start, end;
3600         gtk_text_buffer_get_bounds( buffer, &start, &end );
3601         char *str = gtk_text_buffer_get_text( buffer, &start, &end, FALSE );
3602         fwrite( str, 1, strlen( str ), f );
3603         fclose( f );
3604         g_free( str );
3605 }
3606
3607 static void editor_close( GtkWidget *widget, gpointer data ){
3608         if ( gtk_MessageBox( text_editor, _( "Close the shader editor ?" ), _( "Radiant" ), MB_YESNO ) == IDNO ) {
3609                 return;
3610         }
3611
3612         gtk_widget_hide( text_editor );
3613 }
3614
3615 // several attempts
3616 #if 0
3617 #ifdef _WIN32
3618
3619 HWND FindEditWindow(){
3620         return FindWindow( "TFormEditPadLite", NULL );
3621 }
3622
3623 HWND FindEditWindow(){
3624         HWND hwnd = FindWindow( "TFormEditPadLite", NULL );
3625         if ( hwnd ) {
3626                 hwnd = FindWindowEx( hwnd, NULL, "TPanel", NULL );
3627                 if ( hwnd ) {
3628                         hwnd = FindWindowEx( hwnd, NULL, "TPanel", NULL );
3629                         if ( hwnd ) {
3630                                 hwnd = FindWindowEx( hwnd, NULL, "TEditPadEditor", NULL );
3631                                 if ( hwnd ) {
3632                                         hwnd = FindWindowEx( hwnd, NULL, "TWinControlProxy", NULL );
3633                                         return hwnd;
3634                                 }
3635                         }
3636                 }
3637         }
3638         return NULL;
3639 }
3640
3641 HWND FindEditWindow(){
3642         HWND hwnd = FindWindow( "TFormEditPadLite", NULL );
3643         if ( hwnd ) {
3644                 hwnd = FindWindowEx( hwnd, NULL, "TPanel", NULL );
3645                 if ( hwnd ) {
3646                         hwnd = FindWindowEx( hwnd, NULL, "TPanel", NULL );
3647                         if ( hwnd ) {
3648                                 hwnd = FindWindowEx( hwnd, NULL, "TPanel", NULL );
3649                                 if ( hwnd ) {
3650                                         hwnd = FindWindowEx( hwnd, NULL, "TFrameSearchReplace", NULL );
3651                                         if ( hwnd ) {
3652                                                 hwnd = FindWindowEx( hwnd, NULL, "TJGStringEditorControl", NULL );
3653                                                 return hwnd;
3654                                         }
3655                                 }
3656                         }
3657                 }
3658         }
3659         return NULL;
3660 }
3661
3662 HWND FindEditWindow(){
3663         HWND hwnd = FindWindow( "TEditPadForm", NULL );
3664         HWND hwndEdit = NULL;
3665         if ( hwnd != NULL ) {
3666                 HWND hwndTab = FindWindowEx( hwnd, NULL, "TTabControl", NULL );
3667                 if ( hwndTab != NULL ) {
3668                         hwndEdit = FindWindowEx( hwndTab, NULL, "TRicherEdit", NULL );
3669                 }
3670         }
3671         return hwndEdit;
3672 }
3673 #endif
3674 #endif // #if 0
3675
3676 static void CreateGtkTextEditor(){
3677         GtkWidget *dlg;
3678         GtkWidget *vbox, *hbox, *button, *scr, *text;
3679
3680         dlg = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3681
3682         gtk_signal_connect( GTK_OBJECT( dlg ), "delete_event",
3683                                                 GTK_SIGNAL_FUNC( editor_delete ), NULL );
3684         gtk_window_set_default_size( GTK_WINDOW( dlg ), 600, 300 );
3685
3686         vbox = gtk_vbox_new( FALSE, 5 );
3687         gtk_widget_show( vbox );
3688         gtk_container_add( GTK_CONTAINER( dlg ), vbox );
3689         gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
3690
3691         scr = gtk_scrolled_window_new( NULL, NULL );
3692         gtk_widget_show( scr );
3693         gtk_box_pack_start( GTK_BOX( vbox ), scr, TRUE, TRUE, 0 );
3694         gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scr ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
3695         gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( scr ), GTK_SHADOW_IN );
3696
3697         text = gtk_text_view_new();
3698         gtk_container_add( GTK_CONTAINER( scr ), text );
3699         gtk_widget_show( text );
3700         g_object_set_data( G_OBJECT( dlg ), "text", text );
3701         gtk_text_view_set_editable( GTK_TEXT_VIEW( text ), TRUE );
3702
3703         hbox = gtk_hbox_new( FALSE, 5 );
3704         gtk_widget_show( hbox );
3705         gtk_box_pack_start( GTK_BOX( vbox ), hbox, FALSE, TRUE, 0 );
3706
3707         button = gtk_button_new_with_label( _( "Close" ) );
3708         gtk_widget_show( button );
3709         gtk_box_pack_end( GTK_BOX( hbox ), button, FALSE, FALSE, 0 );
3710         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3711                                                 GTK_SIGNAL_FUNC( editor_close ), dlg );
3712         gtk_widget_set_usize( button, 60, -2 );
3713
3714         button = gtk_button_new_with_label( _( "Save" ) );
3715         gtk_widget_show( button );
3716         gtk_box_pack_end( GTK_BOX( hbox ), button, FALSE, FALSE, 0 );
3717         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3718                                                 GTK_SIGNAL_FUNC( editor_save ), dlg );
3719         gtk_widget_set_usize( button, 60, -2 );
3720
3721         text_editor = dlg;
3722         text_widget = text;
3723 }
3724
3725 static void DoGtkTextEditor( const char* filename, guint cursorpos ){
3726         if ( !text_editor ) {
3727                 CreateGtkTextEditor(); // build it the first time we need it
3728
3729         }
3730         // Load file
3731         FILE *f = fopen( filename, "r" );
3732
3733         if ( f == NULL ) {
3734                 Sys_Printf( "Unable to load file %s in shader editor.\n", filename );
3735                 gtk_widget_hide( text_editor );
3736         }
3737         else
3738         {
3739                 fseek( f, 0, SEEK_END );
3740                 int len = ftell( f );
3741                 void *buf = qmalloc( len );
3742                 void *old_filename;
3743
3744                 rewind( f );
3745                 fread( buf, 1, len, f );
3746
3747                 gtk_window_set_title( GTK_WINDOW( text_editor ), filename );
3748
3749                 GtkTextBuffer* text_buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW( text_widget ) );
3750                 gtk_text_buffer_set_text( text_buffer, (char*)buf, len );
3751
3752                 old_filename = g_object_get_data( G_OBJECT( text_editor ), "filename" );
3753                 if ( old_filename ) {
3754                         free( old_filename );
3755                 }
3756                 g_object_set_data( G_OBJECT( text_editor ), "filename", strdup( filename ) );
3757
3758                 // trying to show later
3759                 gtk_widget_show( text_editor );
3760
3761 #ifdef _WIN32
3762                 while ( gtk_events_pending() )
3763                         gtk_main_iteration();
3764 #endif
3765
3766                 // only move the cursor if it's not exceeding the size..
3767                 // NOTE: this is erroneous, cursorpos is the offset in bytes, not in characters
3768                 // len is the max size in bytes, not in characters either, but the character count is below that limit..
3769                 // thinking .. the difference between character count and byte count would be only because of CR/LF?
3770                 {
3771                         GtkTextIter text_iter;
3772                         // character offset, not byte offset
3773                         gtk_text_buffer_get_iter_at_offset( text_buffer, &text_iter, cursorpos );
3774                         gtk_text_buffer_place_cursor( text_buffer, &text_iter );
3775                 }
3776
3777 #ifdef _WIN32
3778                 gtk_widget_queue_draw( text_widget );
3779 #endif
3780
3781                 free( buf );
3782                 fclose( f );
3783         }
3784 }
3785
3786 void DoTextEditor( const char* filename, int cursorpos ){
3787         CString strEditCommand;
3788 #ifdef _WIN32
3789         if ( g_PrefsDlg.m_bUseWin32Editor ) {
3790                 Sys_Printf( "opening file '%s' (line %d info ignored)\n", filename );
3791                 ShellExecute( (HWND)GDK_WINDOW_HWND( g_pParentWnd->m_pWidget->window ), "open", filename, NULL, NULL, SW_SHOW );
3792                 return;
3793         }
3794 #else
3795         // check if a custom editor is set
3796         if ( ( g_PrefsDlg.m_bUseCustomEditor ) && ( g_PrefsDlg.m_strEditorCommand.GetLength() > 0 ) ) {
3797                 strEditCommand = g_PrefsDlg.m_strEditorCommand;
3798                 strEditCommand += " \"";
3799                 strEditCommand += filename;
3800                 strEditCommand += "\"";
3801
3802                 Sys_Printf( "Launching: %s\n", strEditCommand.GetBuffer() );
3803                 // note: linux does not return false if the command failed so it will assume success
3804                 if ( Q_Exec( NULL, (char *)strEditCommand.GetBuffer(), NULL, true ) == false ) {
3805                         Sys_FPrintf( SYS_WRN, "Warning: Failed to execute %s, using default\n", strEditCommand.GetBuffer() );
3806                 }
3807                 else
3808                 {
3809                         // the command (appeared) to run successfully, no need to do anything more
3810                         return;
3811                 }
3812         }
3813 #endif
3814
3815         DoGtkTextEditor( filename, cursorpos );
3816
3817         // old win32 code with EditPad bindings, broken
3818 #if 0
3819         strEditCommand = g_strAppPath.GetBuffer();
3820         strEditCommand += "editpad.exe";
3821         strEditCommand += " \"";
3822         strEditCommand += filename;
3823         strEditCommand += "\"";
3824         if ( Q_Exec( NULL, (char *)strEditCommand.GetBuffer(), NULL, true ) == false ) {
3825                 Sys_FPrintf( SYS_WRN, "WARNING: Gtk shader editor is not fully functional on windows in general and unstable on win98 in particular.\n" );
3826                 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" );
3827                 DoGtkTextEditor( filename, cursorpos );
3828         }
3829         else
3830         {
3831                 // TTimo: we used to call Delay here, to continue processing messages. But it seems to induce a lot of instabilities.
3832                 // so now the user will simply have to wait.
3833                 Sleep( 1500 );
3834
3835                 // now grab the edit window and scroll to the shader we want to edit
3836                 HWND hwndEdit = FindEditWindow();
3837
3838                 if ( hwndEdit != NULL ) {
3839                         PostMessage( hwndEdit, EM_SETSEL, cursorpos, cursorpos );
3840                 }
3841                 else{
3842                         Sys_Printf( "Unable to load shader editor.\n" );
3843                 }
3844         }
3845 #endif
3846 }
3847
3848 // =============================================================================
3849 // Light Intensity dialog
3850
3851 int DoLightIntensityDlg( int *intensity ){
3852         GtkWidget *dlg, *vbox, *hbox, *label, *button, *entry;
3853         int loop = 1, ret = IDCANCEL;
3854
3855         dlg = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3856         gtk_window_set_title( GTK_WINDOW( dlg ), _( "Light intensity" ) );
3857         gtk_signal_connect( GTK_OBJECT( dlg ), "delete_event",
3858                                                 GTK_SIGNAL_FUNC( dialog_delete_callback ), NULL );
3859         gtk_signal_connect( GTK_OBJECT( dlg ), "destroy",
3860                                                 GTK_SIGNAL_FUNC( gtk_widget_destroy ), NULL );
3861         g_object_set_data( G_OBJECT( dlg ), "loop", &loop );
3862         g_object_set_data( G_OBJECT( dlg ), "ret", &ret );
3863
3864         GtkAccelGroup *accel_group = gtk_accel_group_new();
3865         gtk_window_add_accel_group( GTK_WINDOW( dlg ), accel_group );
3866
3867         hbox = gtk_hbox_new( FALSE, 5 );
3868         gtk_widget_show( hbox );
3869         gtk_container_add( GTK_CONTAINER( dlg ), hbox );
3870         gtk_container_set_border_width( GTK_CONTAINER( hbox ), 5 );
3871
3872         vbox = gtk_vbox_new( FALSE, 5 );
3873         gtk_widget_show( vbox );
3874         gtk_box_pack_start( GTK_BOX( hbox ), vbox, TRUE, TRUE, 0 );
3875
3876         label = gtk_label_new( _( "ESC for default, ENTER to validate" ) );
3877         gtk_widget_show( label );
3878         gtk_box_pack_start( GTK_BOX( vbox ), label, FALSE, FALSE, 0 );
3879
3880         entry = gtk_entry_new();
3881         gtk_widget_show( entry );
3882         gtk_box_pack_start( GTK_BOX( vbox ), entry, TRUE, TRUE, 0 );
3883
3884         vbox = gtk_vbox_new( FALSE, 5 );
3885         gtk_widget_show( vbox );
3886         gtk_box_pack_start( GTK_BOX( hbox ), vbox, FALSE, FALSE, 0 );
3887
3888         button = gtk_button_new_with_label( _( "OK" ) );
3889         gtk_widget_show( button );
3890         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
3891         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3892                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDOK ) );
3893         gtk_widget_add_accelerator( button, "clicked", accel_group,
3894                                                                 GDK_Return, (GdkModifierType)0, GTK_ACCEL_VISIBLE );
3895         gtk_widget_set_usize( button, 60, -2 );
3896
3897         button = gtk_button_new_with_label( _( "Cancel" ) );
3898         gtk_widget_show( button );
3899         gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
3900         gtk_signal_connect( GTK_OBJECT( button ), "clicked",
3901                                                 GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( IDCANCEL ) );
3902         gtk_widget_add_accelerator( button, "clicked", accel_group,
3903                                                                 GDK_Escape, (GdkModifierType)0, GTK_ACCEL_VISIBLE );
3904         gtk_widget_set_usize( button, 60, -2 );
3905
3906         char buf[16];
3907         sprintf( buf, "%d", *intensity );
3908         gtk_entry_set_text( GTK_ENTRY( entry ), buf );
3909
3910         gtk_grab_add( dlg );
3911         gtk_widget_show( dlg );
3912
3913         while ( loop )
3914                 gtk_main_iteration();
3915
3916         if ( ret == IDOK ) {
3917                 *intensity = atoi( gtk_entry_get_text( GTK_ENTRY( entry ) ) );
3918         }
3919
3920         gtk_grab_remove( dlg );
3921         gtk_widget_destroy( dlg );
3922
3923         return ret;
3924 }