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