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