GTK: wrap gtk_widget_set_size_request
[xonotic/netradiant.git] / contrib / gtkgensurf / gendlgs.cpp
1 /*
2    GenSurf plugin for GtkRadiant
3    Copyright (C) 2001 David Hyde, Loki software and qeradiant.com
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include <gtk/gtk.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <math.h>
25 #include "gensurf.h"
26
27 #define GENERAL_TAB   0
28 #define EXTENTS_TAB   1
29 #define BITMAP_TAB    2
30 #define FIXPOINTS_TAB 3
31 #define TEXTURE_TAB   4
32 //#define BUFF_SIZE     32768
33
34 #define ENABLE_WIDGET( name,enable ) \
35         gtk_widget_set_sensitive( g_object_get_data( G_OBJECT( g_pWnd , ( name ) ) ), ( enable ) )
36 #define CHECK_WIDGET( name,check ) \
37         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), name ) ), check )
38
39 static GtkWidget *game_radios[NUMGAMES];
40 static GtkWidget *wave_radios[5];
41 static GtkWidget *plane_radios[6];
42 static guint current_tab;
43 static int OldPreview;
44 static int WasDetail;
45 static GtkTooltips *tooltips;
46 static int FirstPassComplete = 0;
47
48 void About( GtkWidget *parent ){
49 /*
50    char *icon_xpm[] = {
51    "32 32 4 1",
52    "    c None",
53    ".   c #000000",
54    "+   c #FFFFFF",
55    "@   c #838183",
56    "................................",
57    "................................",
58    "................................",
59    "................................",
60    "................................",
61    "................................",
62    "................................",
63    "...............++...............",
64    ".............++++++.............",
65    "............++@+++@+............",
66    "..........+++..++..+++..........",
67    "........++.+.++..++.+.@+........",
68    ".......+..+..+.++.+..+..++......",
69    ".....++..++.+..++..+.++..++.....",
70    "...++..++...+.+..+.++..++..++...",
71    "..++.+.++....++..++....++.+..+..",
72    ".+.+..+..++....++....++..++.+.+.",
73    "..+++....+.++++++++++.+....+++..",
74    "....++.@@+++++.++.++++@++.++....",
75    "......+++++++......++@+++++.....",
76    ".......+++.+.++..++.+..++.......",
77    ".........++..+.++.+..++.........",
78    "...........++..++..++...........",
79    ".............++..+.+............",
80    "..............+..+@.............",
81    "...............@@...............",
82    "................................",
83    "................................",
84    "................................",
85    "................................",
86    "................................",
87    "................................"
88    };
89  */
90         // leo: I'm too lazy to create a nice about box
91         // ^Fishman - I am lazy too :P.
92         g_FuncTable.m_pfnMessageBox( parent, "GtkGenSurf 1.05\n\n"
93                                                                                  "Original version\n"
94                                                                                  "David Hyde (rascal@vicksburg.com)\n\n"
95                                                                                  "Porting\n"
96                                                                                  "Leonardo Zide (leo@lokigames.com)\n\n"
97                                                                                  "Enhancements\n"
98                                                                                  "Pablo Zurita (pablo@qeradiant.com)\n"
99                                                                                  "Hydra (hydra@hydras-world.com)",
100                                                                  "About GtkGenSurf", eMB_OK );
101 }
102
103 // =============================================================================
104 // main dialog
105
106 static void SetupControls(){
107         switch ( current_tab )
108         {
109         case GENERAL_TAB:
110                 break;
111
112         case EXTENTS_TAB:
113                 if ( Game != QUAKE3 ) {
114                         gtk_widget_hide( g_object_get_data( G_OBJECT( g_pWnd , "use_patches" ) ) );
115                         ENABLE_WIDGET( "use_patches", FALSE );
116                 }
117                 else
118                 {
119                         gtk_widget_show( g_object_get_data( G_OBJECT( g_pWnd , "use_patches" ) ) );
120                         ENABLE_WIDGET( "use_patches", TRUE );
121                 }
122
123                 if ( Game == QUAKE3 && UsePatches != 0 ) {
124                         ENABLE_WIDGET( "decimate", FALSE );
125                 }
126                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "snap_text" ) ), "Snap to grid:" ); // ^Fishman - Snap to grid.
127                 break;
128
129         case BITMAP_TAB:
130                 if ( WaveType != WAVE_BITMAP ) {
131                         ENABLE_WIDGET( "bmp_file", FALSE );
132                         ENABLE_WIDGET( "bmp_file_browse", FALSE );
133                         ENABLE_WIDGET( "bmp_black", FALSE );
134                         ENABLE_WIDGET( "bmp_white", FALSE );
135                         ENABLE_WIDGET( "bmp_text1", FALSE );
136                         ENABLE_WIDGET( "bmp_text2", FALSE );
137                         ENABLE_WIDGET( "bmp_text3", FALSE );
138                         ENABLE_WIDGET( "bmp_reload", FALSE );
139                         gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_note" ) ),
140                                                                 "These options are disabled unless \"From Bitmap\"\n"
141                                                                 "is selected as the Waveform on the General tab." );
142                 }
143                 else
144                 {
145                         ENABLE_WIDGET( "bmp_file", TRUE );
146                         ENABLE_WIDGET( "bmp_file_browse", TRUE );
147                         ENABLE_WIDGET( "bmp_black", TRUE );
148                         ENABLE_WIDGET( "bmp_white", TRUE );
149                         ENABLE_WIDGET( "bmp_text1", TRUE );
150                         ENABLE_WIDGET( "bmp_text2", TRUE );
151                         ENABLE_WIDGET( "bmp_text3", TRUE );
152                         ENABLE_WIDGET( "bmp_reload", strlen( gbmp.name ) != 0 );
153                         gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_note" ) ),
154                                                                 "GenSurf works only with 8-bit bitmaps. Color indices are\n"
155                                                                 "mapped to values for each vertex. Generally, gray scale\n"
156                                                                 "images are stored with black as color 0, white as color 255." );
157                 }
158                 break;
159
160         case FIXPOINTS_TAB:
161                 ENABLE_WIDGET( "fix_value", ( NumVerticesSelected != 0 ) );
162                 ENABLE_WIDGET( "fix_value_text", ( NumVerticesSelected != 0 ) );
163                 ENABLE_WIDGET( "fix_free", ( NumVerticesSelected != 0 ) );
164                 ENABLE_WIDGET( "fix_range", ( ( NumVerticesSelected != 0 ) && ( WaveType != WAVE_ROUGH_ONLY ) ) );
165                 ENABLE_WIDGET( "fix_range_text", ( ( NumVerticesSelected != 0 ) && ( WaveType != WAVE_ROUGH_ONLY ) ) );
166                 ENABLE_WIDGET( "fix_rate", ( ( NumVerticesSelected != 0 ) && ( WaveType != WAVE_ROUGH_ONLY ) ) );
167                 ENABLE_WIDGET( "fix_rate_text", ( ( NumVerticesSelected != 0 ) && ( WaveType != WAVE_ROUGH_ONLY ) ) );
168                 break;
169
170         case TEXTURE_TAB:
171                 ENABLE_WIDGET( "texture2", ( UsePatches == 0 ) );
172                 ENABLE_WIDGET( "texture3", ( UsePatches == 0 ) );
173                 ENABLE_WIDGET( "tex_slant", ( UsePatches == 0 ) );
174                 ENABLE_WIDGET( "detail", ( UsePatches == 0 ) );
175                 if ( Game != QUAKE3 ) {
176                         ENABLE_WIDGET( "terrain_ent", FALSE ); // ^Fishman - Adds terrain key to func_group.
177                         ENABLE_WIDGET( "hint", ( UsePatches == 0 ) );
178                 }
179                 break;
180         }
181
182         switch ( WaveType )
183         {
184         case WAVE_HCYLINDER:
185         case WAVE_VCYLINDER:
186                 ENABLE_WIDGET( "amplitude", TRUE );
187                 ENABLE_WIDGET( "wavelength", TRUE );
188                 ENABLE_WIDGET( "z00", TRUE );
189                 ENABLE_WIDGET( "z01", TRUE );
190                 ENABLE_WIDGET( "z10", TRUE );
191                 ENABLE_WIDGET( "z11", TRUE );
192                 ENABLE_WIDGET( "linearborder", TRUE );
193                 ENABLE_WIDGET( "go", TRUE );
194                 break;
195         case WAVE_BITMAP:
196                 ENABLE_WIDGET( "amplitude", FALSE );
197                 ENABLE_WIDGET( "wavelength", FALSE );
198                 ENABLE_WIDGET( "z00", FALSE );
199                 ENABLE_WIDGET( "z01", FALSE );
200                 ENABLE_WIDGET( "z10", FALSE );
201                 ENABLE_WIDGET( "z11", FALSE );
202                 ENABLE_WIDGET( "linearborder", FALSE );
203                 ENABLE_WIDGET( "go", ( gbmp.colors != NULL ? TRUE : FALSE ) );
204                 break;
205         case WAVE_ROUGH_ONLY:
206                 ENABLE_WIDGET( "amplitude", FALSE );
207                 ENABLE_WIDGET( "wavelength", FALSE );
208                 ENABLE_WIDGET( "z00", TRUE );
209                 ENABLE_WIDGET( "z01", TRUE );
210                 ENABLE_WIDGET( "z10", TRUE );
211                 ENABLE_WIDGET( "z11", TRUE );
212                 ENABLE_WIDGET( "linearborder", TRUE );
213                 ENABLE_WIDGET( "go", TRUE );
214                 break;
215         default:
216                 ENABLE_WIDGET( "amplitude", TRUE );
217                 ENABLE_WIDGET( "wavelength", TRUE );
218                 ENABLE_WIDGET( "z00", TRUE );
219                 ENABLE_WIDGET( "z01", TRUE );
220                 ENABLE_WIDGET( "z10", TRUE );
221                 ENABLE_WIDGET( "z11", TRUE );
222                 ENABLE_WIDGET( "linearborder", TRUE );
223                 ENABLE_WIDGET( "go", TRUE );
224         }
225
226         switch ( Plane )
227         {
228         case PLANE_XZ0:
229         case PLANE_XZ1:
230                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "hmin_text" ) ), "X:" );
231                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "hmax_text" ) ), "X:" );
232                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "vmin_text" ) ), "Z:" );
233                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "vmax_text" ) ), "Z:" );
234                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "nh_text" ) ), "X:" );
235                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "nv_text" ) ), "Z:" );
236                 break;
237         case PLANE_YZ0:
238         case PLANE_YZ1:
239                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "hmin_text" ) ), "Y:" );
240                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "hmax_text" ) ), "Y:" );
241                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "vmin_text" ) ), "Z:" );
242                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "vmax_text" ) ), "Z:" );
243                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "nh_text" ) ), "Y:" );
244                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "nv_text" ) ), "Z:" );
245                 break;
246         default:
247                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "hmin_text" ) ), "X:" );
248                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "hmax_text" ) ), "X:" );
249                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "vmin_text" ) ), "Y:" );
250                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "vmax_text" ) ), "Y:" );
251                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "nh_text" ) ), "X:" );
252                 gtk_label_set_text( GTK_LABEL( g_object_get_data( G_OBJECT( g_pWnd ), "nv_text" ) ), "Y:" );
253                 break;
254         }
255 }
256
257 // SetDlgValues fills in text boxes and initializes other input controls
258 static void SetDlgValues( int tab ){
259         char Text[256];
260         char RForm[16] = "%.5g";
261         int i;
262
263         switch ( tab )
264         {
265         case GENERAL_TAB:
266                 // Hell if I know why, but in the release build the 2nd pass thru the
267                 // set_sensitive loop for game_radios crashes. No need to do this more
268                 // than once anyhow.
269                 if ( !FirstPassComplete ) {
270                         for ( i = 0; i < NUMGAMES; i++ )
271                                 gtk_widget_set_sensitive( game_radios[i], ( i == Game ? TRUE : FALSE ) );
272                         for ( i = 0; i < 6; i++ )
273                                 gtk_widget_set_sensitive( plane_radios[i], ( i == Plane ? TRUE : FALSE ) );
274                 }
275                 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( game_radios[Game] ), TRUE );
276                 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( plane_radios[Plane] ), TRUE );
277                 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( wave_radios[WaveType] ), TRUE );
278                 gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "random" ) ),
279                                                                    RandomSeed );
280                 sprintf( Text, RForm, WaveLength );
281                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "wavelength" ) ), Text );
282                 sprintf( Text, RForm, Amplitude );
283                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "amplitude" ) ), Text );
284                 sprintf( Text, RForm, Roughness );
285                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "roughness" ) ), Text );
286                 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data
287                                                                                                                          ( G_OBJECT( g_pWnd ), "main_antialiasing" ) ), Antialiasing );
288                 break;
289
290         case EXTENTS_TAB:
291                 sprintf( Text,RForm,Hll );
292                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "hmin" ) ), Text );
293                 sprintf( Text,RForm,Vll );
294                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "vmin" ) ), Text );
295                 sprintf( Text,RForm,Hur );
296                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "hmax" ) ), Text );
297                 sprintf( Text,RForm,Vur );
298                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "vmax" ) ), Text );
299                 sprintf( Text,RForm,Z00 );
300                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "z00" ) ), Text );
301                 sprintf( Text,RForm,Z01 );
302                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "z01" ) ), Text );
303                 sprintf( Text,RForm,Z10 );
304                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "z10" ) ), Text );
305                 sprintf( Text,RForm,Z11 );
306                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "z11" ) ), Text );
307                 gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "nh" ) ), NH );
308                 gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "nv" ) ), NV );
309                 gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "sp" ) ), SP ); // ^Fishman - Snap to grid.
310
311                 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data
312                                                                                                                          ( G_OBJECT( g_pWnd ), "linearborder" ) ), FixBorders );
313                 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data
314                                                                                                                          ( G_OBJECT( g_pWnd ), "use_patches" ) ), UsePatches );
315                 gtk_adjustment_set_value( GTK_ADJUSTMENT( g_object_get_data( G_OBJECT( g_pWnd ), "decimate_adj" ) ),
316                                                                   Decimate );
317
318                 if ( Game == QUAKE3 && UsePatches ) {
319                         gtk_widget_set_sensitive( g_object_get_data( G_OBJECT( g_pWnd , "decimate" ) ), FALSE );
320
321                         if ( NH % 2 ) {
322                                 NH++;
323                                 if ( NH > MAX_ROWS ) {
324                                         NH -= 2;
325                                 }
326                                 SetDlgValues( current_tab );
327                         }
328
329                         if ( NV % 2 ) {
330                                 NV++;
331                                 if ( NV > MAX_ROWS ) {
332                                         NV -= 2;
333                                 }
334                                 SetDlgValues( current_tab );
335                         }
336                         if ( NH % 2 ) {
337                                 NH++;
338                         }
339                         if ( NH < 2 ) {
340                                 NH = 2;
341                         }
342                         if ( NH > MAX_ROWS ) {
343                                 NH = MAX_ROWS;
344                         }
345                         if ( NV % 2 ) {
346                                 NV++;
347                         }
348                         if ( NV < 2 ) {
349                                 NV = 2;
350                         }
351                         if ( NV > MAX_ROWS ) {
352                                 NV = MAX_ROWS;
353                         }
354
355                         gpointer spin = g_object_get_data( G_OBJECT( g_pWnd ), "nh" );
356                         GtkAdjustment *adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON( spin ) );
357                         adj->lower = 2;
358                         gtk_adjustment_changed( adj );
359                         spin = g_object_get_data( G_OBJECT( g_pWnd ), "nv" );
360                         adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON( spin ) );
361                         adj->lower = 2;
362                         gtk_adjustment_changed( adj );
363                 }
364                 else
365                 {
366                         gtk_widget_set_sensitive( g_object_get_data( G_OBJECT( g_pWnd , "decimate" ) ), TRUE );
367
368                         gpointer spin = g_object_get_data( G_OBJECT( g_pWnd ), "nh" );
369                         GtkAdjustment *adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON( spin ) );
370                         adj->lower = 1;
371                         gtk_adjustment_changed( adj );
372                         spin = g_object_get_data( G_OBJECT( g_pWnd ), "nv" );
373                         adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON( spin ) );
374                         adj->lower = 1;
375                         gtk_adjustment_changed( adj );
376                 }
377
378                 gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "nh" ) ), NH );
379                 gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "nv" ) ), NV );
380
381                 break;
382
383         case BITMAP_TAB:
384                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_file" ) ), gbmp.name );
385                 sprintf( Text,"%g",gbmp.black_value );
386                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_black" ) ), Text );
387                 sprintf( Text,"%g",gbmp.white_value );
388                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_white" ) ), Text );
389                 break;
390
391         case FIXPOINTS_TAB:
392                 break;
393
394         case TEXTURE_TAB:
395                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texture1" ) ), Texture[Game][0] );
396                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texture2" ) ), Texture[Game][1] );
397                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texture3" ) ), Texture[Game][2] );
398                 gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "tex_slant" ) ),
399                                                                    SlantAngle );
400                 sprintf( Text,RForm,TexOffset[0] );
401                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texoffsetx" ) ), Text );
402                 sprintf( Text,RForm,TexOffset[1] );
403                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texoffsety" ) ), Text );
404                 sprintf( Text,RForm,TexScale[0] );
405                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texscalex" ) ), Text );
406                 sprintf( Text,RForm,TexScale[1] );
407                 gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "texscaley" ) ), Text );
408                 CHECK_WIDGET( "detail", UseDetail );
409
410                 if ( Game == QUAKE3 ) {
411                         ENABLE_WIDGET( "hint", FALSE );
412                         AddHints = 0;
413                 }
414                 else{
415                         ENABLE_WIDGET( "hint", TRUE );
416                 }
417                 CHECK_WIDGET( "hint", AddHints );
418
419                 /*
420                    if (Game==SIN)
421                    {
422                    // ArghRad doesn't currently support SiN
423                    EnableWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2),       0);
424                    EnableWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_SPIN),  0);
425                    ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_TEXT),  SW_HIDE);
426                    ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2),       SW_HIDE);
427                    ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_SPIN),  SW_HIDE);
428                    SetDlgItemText(hwndDisplay,DLG_TEX_USEPAK,"Use sin file");
429                    SetDlgItemText(hwndDisplay,DLG_TEX_PAK_TEXT,"Sin:");
430                    }
431                  */
432
433                 if ( Game == QUAKE3 ) {
434                         /*
435                            // ArghRad sun is inapplicable (so far)
436                            EnableWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2),       0);
437                            EnableWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_SPIN),  0);
438                            ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_TEXT),  SW_HIDE);
439                            ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2),       SW_HIDE);
440                            ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_SPIN),  SW_HIDE);
441                            // No ladders in Q3
442                            EnableWindow(GetDlgItem(hwndDisplay,DLG_LADDER),         0);
443                            ShowWindow(GetDlgItem(hwndDisplay,DLG_LADDER),         SW_HIDE);
444                            SetDlgItemText(hwndDisplay,DLG_TEX_USEPAK,"Use pk3 file");
445                            SetDlgItemText(hwndDisplay,DLG_TEX_PAK_TEXT,"PK3:");
446                          */
447                 }
448
449 /*trix  if(Game==HERETIC2)
450         {
451             // ArghRad doesn't currently support Heretic2
452             EnableWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2),       0);
453             EnableWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_SPIN),  0);
454             ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_TEXT),  SW_HIDE);
455             ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2),       SW_HIDE);
456             ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_SPIN),  SW_HIDE);
457
458             SetDlgItemText(hwndDisplay,DLG_TEX_USEPAK,"Use pak file");
459             SetDlgItemText(hwndDisplay,DLG_TEX_PAK_TEXT,"Pak:");
460         } */
461                 /*
462                     if(Game==HALFLIFE)
463                     {
464                         // A bunch of controls aren't applicable to HL
465                         EnableWindow(GetDlgItem(hwndDisplay,DLG_TEXTURE_BROWSE), 0);
466                         EnableWindow(GetDlgItem(hwndDisplay,DLG_TEXTURE2_BROWSE),0);
467                         EnableWindow(GetDlgItem(hwndDisplay,DLG_TEXTURE3_BROWSE),0);
468                         EnableWindow(GetDlgItem(hwndDisplay,DLG_DETAIL),         0);
469                         EnableWindow(GetDlgItem(hwndDisplay,DLG_LADDER),         0);
470                         EnableWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2),       0);
471                         EnableWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_SPIN),  0);
472                         ShowWindow(GetDlgItem(hwndDisplay,DLG_TEXTURE_BROWSE), SW_HIDE);
473                         ShowWindow(GetDlgItem(hwndDisplay,DLG_TEXTURE2_BROWSE),SW_HIDE);
474                         ShowWindow(GetDlgItem(hwndDisplay,DLG_TEXTURE3_BROWSE),SW_HIDE);
475                         ShowWindow(GetDlgItem(hwndDisplay,DLG_DETAIL),         SW_HIDE);
476                         ShowWindow(GetDlgItem(hwndDisplay,DLG_LADDER),         SW_HIDE);
477                         ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_TEXT),  SW_HIDE);
478                         ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2),       SW_HIDE);
479                         ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_SPIN),  SW_HIDE);
480
481                         SetDlgItemText(hwndDisplay,DLG_TEX_USEPAK,"Use wad file");
482                         SetDlgItemText(hwndDisplay,DLG_TEX_PAK_TEXT,"Wad:");
483                         SetDlgItemText(hwndDisplay,DLG_HINT,"Hint brushes");
484                     }
485
486                     if(Game==GENESIS3D)
487                     {
488                         // No Q2-type compilers support Genesis3D (including ArghRad)
489                         EnableWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2),       0);
490                         EnableWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_SPIN),  0);
491                         ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_TEXT),  SW_HIDE);
492                         ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2),       SW_HIDE);
493                         ShowWindow(GetDlgItem(hwndDisplay,DLG_ARGHRAD2_SPIN),  SW_HIDE);
494
495                         SetDlgItemText(hwndDisplay,DLG_TEX_USEPAK,"Use sin file");
496                         SetDlgItemText(hwndDisplay,DLG_TEX_PAK_TEXT,"Sin:");
497                     }
498                  */
499                 break;
500         }
501         SetupControls();
502 }
503
504 static void ReadDlgValues( int tab ){
505         //  char Text[256];
506         //  int i;
507
508         switch ( tab )
509         {
510         case GENERAL_TAB:
511                 gpointer spin;
512                 Roughness  = atof( gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "roughness" ) ) ) );
513                 WaveLength = atof( gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "wavelength" ) ) ) );
514                 Amplitude  = atof( gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "amplitude" ) ) ) );
515                 spin = g_object_get_data( G_OBJECT( g_pWnd ), "random" );
516                 RandomSeed = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spin ) );
517                 break;
518
519         case EXTENTS_TAB:
520                 SP = atoi( gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "sp" ) ) ) );
521                 NH = atoi( gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "nh" ) ) ) );
522                 NV = atoi( gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "nv" ) ) ) );
523
524                 if ( Game == QUAKE3 && UsePatches != 0 ) {
525                         if ( NH % 2 ) {
526                                 NH++;
527                         }
528                         if ( NH < 2 ) {
529                                 NH = 2;
530                         }
531                         if ( NH > MAX_ROWS ) {
532                                 NH = MAX_ROWS;
533                         }
534                         if ( NV % 2 ) {
535                                 NV++;
536                         }
537                         if ( NV < 2 ) {
538                                 NV = 2;
539                         }
540                         if ( NV > MAX_ROWS ) {
541                                 NV = MAX_ROWS;
542                         }
543                 }
544                 break;
545
546 #if 0
547         case BITMAP_TAB:
548
549                 if ( WaveType == WAVE_BITMAP ) {
550                         GetDlgItemText( hwnd,DLG_BMP_FILE,gbmp.name,sizeof( gbmp.name ) );
551                         CheckValidDIB( hwnd );
552                         GetDlgItemText( hwnd,DLG_BMP_BLACK,Text,sizeof( Text ) );
553                         gbmp.black_value = atof( Text );
554                         GetDlgItemText( hwnd,DLG_BMP_WHITE,Text,sizeof( Text ) );
555                         gbmp.white_value = atof( Text );
556                         UpdatePreview( TRUE );
557                 }
558                 break;
559
560         case FIXPOINTS_TAB:
561                 GetDlgItemText( hwnd,DLG_FIX_VALUE,Text,sizeof( Text ) );
562                 temp.fixed_value = atoi( Text );
563                 GetDlgItemText( hwnd,DLG_FIX_RANGE,Text,sizeof( Text ) );
564                 temp.range = atoi( Text );
565                 GetDlgItemText( hwnd,DLG_FIX_RATE, Text,sizeof( Text ) );
566                 temp.rate = atof( Text );
567                 for ( k = 0; k < NumVerticesSelected; k++ )
568                 {
569                         xyz[Vertex[k].i][Vertex[k].j].fixed_value = temp.fixed_value;
570                         xyz[Vertex[k].i][Vertex[k].j].range       = temp.range;
571                         xyz[Vertex[k].i][Vertex[k].j].rate        = temp.rate;
572                 }
573                 if ( !OldPreview ) {
574                         Preview = 0;
575                         CheckDlgButton( ghwnd,DLG_PREVIEW,0 );
576                         SendMessage( ghwnd,WM_COMMAND,DLG_PREVIEW,0 );
577                 }
578                 VertexMode = 0;
579                 UpdatePreview( TRUE );
580                 break;
581
582         case TEXTURE_TAB:
583                 if ( UsePak[Game] ) {
584                         i = SendDlgItemMessage( hwndDisplay, DLG_TEX_LIST1, CB_GETCURSEL, 0, 0 );
585                         if ( i == CB_ERR ) {
586                                 Texture[Game][0][0] = '\0';
587                         }
588                         else{
589                                 SendDlgItemMessage( hwndDisplay, DLG_TEX_LIST1, CB_GETLBTEXT, i,
590                                                                         (LPARAM)(LPCSTR)Texture[Game][0] );
591                         }
592
593                         i = SendDlgItemMessage( hwndDisplay, DLG_TEX_LIST2, CB_GETCURSEL, 0, 0 );
594                         if ( i == CB_ERR ) {
595                                 Texture[Game][1][0] = '\0';
596                         }
597                         else{
598                                 SendDlgItemMessage( hwndDisplay, DLG_TEX_LIST2, CB_GETLBTEXT, i,
599                                                                         (LPARAM)(LPCSTR)Texture[Game][1] );
600                         }
601
602                         i = SendDlgItemMessage( hwndDisplay, DLG_TEX_LIST3, CB_GETCURSEL, 0, 0 );
603                         if ( i == CB_ERR ) {
604                                 Texture[Game][2][0] = '\0';
605                         }
606                         else{
607                                 SendDlgItemMessage( hwndDisplay, DLG_TEX_LIST3, CB_GETLBTEXT, i,
608                                                                         (LPARAM)(LPCSTR)Texture[Game][2] );
609                         }
610                 }
611                 else
612                 {
613                         GetDlgItemText( hwndDisplay,DLG_TEXTURE, Texture[Game][0],sizeof( Texture[Game][0] ) );
614                         GetDlgItemText( hwndDisplay,DLG_TEXTURE2,Texture[Game][1],sizeof( Texture[Game][1] ) );
615                         GetDlgItemText( hwndDisplay,DLG_TEXTURE3,Texture[Game][2],sizeof( Texture[Game][2] ) );
616                 }
617                 GetDlgItemText( hwndDisplay,DLG_TEX_SLANT,Text,sizeof( Text ) );
618                 SlantAngle = atoi( Text );
619                 SlantAngle = max( 0,min( SlantAngle,90 ) );
620                 GetDlgItemText( hwndDisplay,DLG_TEXOFFSETX,Text,sizeof( Text ) );
621                 TexOffset[0] = atof( Text );
622                 GetDlgItemText( hwndDisplay,DLG_TEXOFFSETY,Text,sizeof( Text ) );
623                 TexOffset[1] = atof( Text );
624                 GetDlgItemText( hwndDisplay,DLG_TEXSCALEX,Text,sizeof( Text ) );
625                 TexScale[0] = atof( Text );
626                 if ( TexScale[0] == 0. ) {
627                         TexScale[0] = 1.0;
628                 }
629                 GetDlgItemText( hwndDisplay,DLG_TEXSCALEY,Text,sizeof( Text ) );
630                 TexScale[1] = atof( Text );
631                 if ( TexScale[1] == 0. ) {
632                         TexScale[1] = 1.0;
633                 }
634                 GetDlgItemText( hwndDisplay,DLG_ARGHRAD2,Text,sizeof( Text ) );
635                 ArghRad2 = atoi( Text );
636                 break;
637 #endif
638         }
639 }
640
641 // =============================================================================
642 // main dialog callbacks
643
644 static void switch_page( GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer data ){
645         if ( current_tab != page_num ) {
646                 if ( page_num == FIXPOINTS_TAB ) {
647                         OldPreview = Preview;
648                         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ),
649                                                                                                                                                                 "main_preview" ) ), TRUE );
650                         VertexMode = 1;
651                         UpdatePreview( true );
652                         NumVerticesSelected = 0;
653                 }
654
655                 if ( current_tab == FIXPOINTS_TAB ) {
656                         if ( !OldPreview ) {
657                                 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ),
658                                                                                                                                                                         "main_preview" ) ), FALSE );
659                         }
660                         VertexMode = 0;
661                         UpdatePreview( true );
662                         NumVerticesSelected = 0;
663                 }
664
665                 if ( page_num == TEXTURE_TAB ) {
666                         WasDetail = UseDetail;
667                         if ( AddHints ) {
668                                 UseDetail = 1;
669                                 ENABLE_WIDGET( "detail", FALSE );
670                         }
671                 }
672
673                 ReadDlgValues( current_tab );
674                 current_tab = page_num;
675                 SetDlgValues( current_tab );
676         }
677 }
678
679 static gint main_close( GtkWidget *widget, gpointer data ){
680         gtk_widget_hide( g_pWnd );
681         gtk_widget_hide( g_pWndPreview );
682
683         return TRUE;
684 }
685
686 static void main_save( GtkWidget *widget, gpointer data ){
687         ReadDlgValues( current_tab );
688         SaveSetup( g_pWnd );
689 }
690
691 static void main_open( GtkWidget *widget, gpointer data ){
692         OpenSetup( g_pWnd, 0 );
693         for ( int i = 0; i < 5; i++ )
694                 SetDlgValues( i );
695         ShowPreview();
696 }
697
698 static void main_defaults( GtkWidget *widget, gpointer data ){
699         OpenSetup( g_pWnd, 1 );
700         for ( int i = 0; i < 5; i++ )
701                 SetDlgValues( i );
702         ShowPreview();
703 }
704
705 static void main_preview( GtkWidget *widget, gpointer data ){
706         Preview = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) );
707         ShowPreview();
708 }
709
710 // ^Fishman - Antializing for the preview window.
711 static void main_antialiasing( GtkWidget *widget, gpointer data ){
712         Antialiasing = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( widget ) );
713         UpdatePreview( true );
714 }
715
716 static void main_about( GtkWidget *widget, gpointer data ){
717         About( g_pWnd );
718 }
719
720 static void main_go( GtkWidget *widget, gpointer data ){
721         GtkWidget *notebook = g_object_get_data( G_OBJECT( g_pWnd , "notebook" ) );
722         char Text[256];
723
724         ReadDlgValues( current_tab );
725         if ( NH < 1 || NH > MAX_ROWS ) {
726                 sprintf( Text, "The number of divisions must be > 0 and no greater than %d.", MAX_ROWS );
727                 g_FuncTable.m_pfnMessageBox( g_pWnd, Text, "GenSurf", eMB_OK, eMB_ICONWARNING );
728                 gtk_notebook_set_page( GTK_NOTEBOOK( notebook ), EXTENTS_TAB );
729                 return;
730         }
731
732         if ( NV < 1 || NV > MAX_ROWS ) {
733                 sprintf( Text, "The number of divisions must be > 0 and no greater than %d.", MAX_ROWS );
734                 g_FuncTable.m_pfnMessageBox( g_pWnd, Text, "GenSurf", eMB_OK, eMB_ICONWARNING );
735                 gtk_notebook_set_page( GTK_NOTEBOOK( notebook ), EXTENTS_TAB );
736                 return;
737         }
738
739         if ( Hll >= Hur ) {
740                 g_FuncTable.m_pfnMessageBox( g_pWnd, "The \"lower-left\" values must be less than "
741                                                                                          "the corresponding \"upper-right\" values in "
742                                                                                          "the \"Extent\" box.","GenSurf", eMB_OK, eMB_ICONWARNING );
743                 gtk_notebook_set_page( GTK_NOTEBOOK( notebook ), EXTENTS_TAB );
744                 return;
745         }
746
747         if ( Vll >= Vur ) {
748                 g_FuncTable.m_pfnMessageBox( g_pWnd,"The \"lower-left\" values must be less than "
749                                                                                         "the corresponding \"upper-right\" values in "
750                                                                                         "the \"Extent\" box.","GenSurf", eMB_OK, eMB_ICONWARNING );
751                 gtk_notebook_set_page( GTK_NOTEBOOK( notebook ), EXTENTS_TAB );
752                 return;
753         }
754
755         if ( !strlen( Texture[Game][0] ) ) {
756                 g_FuncTable.m_pfnMessageBox( g_pWnd, "You must supply a texture name.", "GenSurf", eMB_OK, eMB_ICONWARNING );
757                 gtk_notebook_set_page( GTK_NOTEBOOK( notebook ), EXTENTS_TAB );
758                 return;
759         }
760
761 /*  if (Decimate>0 && GimpHints!=0)
762    {
763     MessageBox(hwnd,"You've elected to use a decimated grid and gimp's non-detail hint brushes. "
764                "This combination usually produces bizarre visual errors in the game, "
765                "so GenSurf has turned off the hint brush option.",
766                "GenSurf",eMB_ICONWARNING);
767     GimpHints = 0;
768    } */
769
770         gtk_widget_hide( g_pWnd );
771         if ( g_pWndPreview ) {
772                 gtk_widget_hide( g_pWndPreview );
773         }
774
775         GenerateMap();
776         WriteIniFile( gszIni );
777 }
778
779 // =============================================================================
780 // general tab callbacks
781
782 static void general_game( GtkToggleButton *widget, gpointer data ){
783         if ( gtk_toggle_button_get_active( widget ) ) {
784                 Game = GPOINTER_TO_INT( data );
785                 UpdatePreview( TRUE );
786         }
787 }
788
789 static void general_plane( GtkToggleButton *widget, gpointer data ){
790         if ( gtk_toggle_button_get_active( widget ) ) {
791                 Plane = GPOINTER_TO_INT( data );
792                 SetupControls();
793                 UpdatePreview( TRUE );
794         }
795 }
796
797 static void general_wave( GtkToggleButton *widget, gpointer data ){
798         if ( gtk_toggle_button_get_active( widget ) ) {
799                 WaveType = GPOINTER_TO_INT( data );
800                 SetupControls();
801                 UpdatePreview( TRUE );
802         }
803 }
804
805 static void general_random( GtkAdjustment *adj, gpointer data ){
806         int nPos = (int)adj->value;
807
808         if ( RandomSeed != nPos ) {
809                 RandomSeed = nPos;
810                 UpdatePreview( true );
811         }
812 }
813
814 // =============================================================================
815 // extents tab callbacks
816
817 static void extents_linearborder( GtkToggleButton *check, gpointer data ){
818         FixBorders = gtk_toggle_button_get_active( check );
819         UpdatePreview( true );
820 }
821
822 static void extents_use_patches( GtkToggleButton *check, gpointer data ){
823         if ( Game != QUAKE3 ) {
824                 return;
825         }
826
827         UsePatches = gtk_toggle_button_get_active( check );
828         SetDlgValues( current_tab );
829         SetupControls();
830         UpdatePreview( true );
831 }
832
833 static void extents_nhnv_spin( GtkAdjustment *adj, int *data ){
834         int nPos = (int)adj->value;
835
836         if ( *data != nPos ) {
837                 if ( Game == QUAKE3 && UsePatches && ( nPos % 2 ) ) {
838                         if ( *data < nPos ) {
839                                 *data += 2;
840                         }
841                         else{
842                                 *data -= 2;
843                         }
844                         gtk_adjustment_set_value( adj, *data );
845                 }
846                 else{
847                         *data = nPos;
848                 }
849                 UpdatePreview( true );
850         }
851 }
852
853 static void extents_decimate( GtkAdjustment *adj, gpointer data ){
854         int nPos = (int)adj->value;
855
856         Decimate = nPos;
857         UpdatePreview( true );
858 }
859
860 // Hydra : snap to grid begin
861 /*static void extents_snaptogrid (GtkAdjustment *adj, gpointer data)
862    {
863    int nPos = (int)adj->value;
864
865    SnapToGrid = nPos;
866    UpdatePreview (true);
867    }*/
868
869 // ^Fishman - Modified version of Hydra's snap to grid code.
870 static void extents_snaptogrid_spin( GtkAdjustment *adj, int *data ){
871         int nPos = (int)adj->value;
872         SnapToGrid = nPos;
873         UpdatePreview( true );
874 }
875
876 // =============================================================================
877 // bitmap tab callbacks
878
879 static gint bitmap_file_entryfocusout( GtkWidget* widget, GdkEventFocus* event, gpointer data ){
880         char filename[NAME_MAX];
881
882         strcpy( filename, gtk_entry_get_text( GTK_ENTRY( widget ) ) );
883         if ( strcmp( filename,gbmp.name ) ) {
884                 strcpy( gbmp.name,filename );
885                 if ( strlen( gbmp.name ) ) {
886                         OpenBitmap();
887                 }
888                 ENABLE_WIDGET( "go", ( gbmp.colors != NULL ? TRUE : FALSE ) );
889         }
890         return FALSE;
891 }
892
893 static void bitmap_browse( GtkWidget *widget, gpointer data ){
894         const char *filename;
895         char *ptr;
896
897         filename = g_FuncTable.m_pfnFileDialog( g_pWnd, TRUE, "Bitmap File", gbmp.defpath );
898
899         if ( filename != NULL ) {
900                 strcpy( gbmp.name, filename );
901
902                 ptr = strrchr( filename, G_DIR_SEPARATOR );
903                 if ( ptr != NULL ) {
904                         *( ptr + 1 ) = '\0';
905                         strcpy( gbmp.defpath, filename );
906                 }
907
908                 OpenBitmap();
909                 ENABLE_WIDGET( "go", ( gbmp.colors != NULL ? TRUE : FALSE ) );
910         }
911 }
912
913 static void bitmap_reload( GtkWidget *widget, gpointer data ){
914         strcpy( gbmp.name, gtk_entry_get_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "bmp_file" ) ) ) );
915         if ( strlen( gbmp.name ) ) {
916                 OpenBitmap();
917                 ENABLE_WIDGET( "go", ( gbmp.colors != NULL ? TRUE : FALSE ) );
918         }
919         else{
920                 ENABLE_WIDGET( "go", FALSE );
921         }
922 }
923
924 // =============================================================================
925 // fix points tab callbacks
926
927 static gint fix_value_entryfocusout( GtkWidget* widget, GdkEventFocus *event, gpointer data ){
928         int i = atoi( gtk_entry_get_text( GTK_ENTRY( widget ) ) ), k;
929         char Text[32];
930
931         if ( i < -65536 || i > 65536 ) {
932                 gdk_beep();
933                 g_FuncTable.m_pfnMessageBox( g_pWnd, "The value must be between -65536 and 65536, inclusive.",
934                                                                          "GenSurf", eMB_OK, eMB_ICONWARNING );
935                 sprintf( Text, "%d", (int)xyz[Vertex[0].i][Vertex[0].j].fixed_value );
936                 gtk_entry_set_text( GTK_ENTRY( widget ), Text );
937                 gtk_window_set_focus( widget.window(), widget );
938         }
939         else if ( i != xyz[Vertex[0].i][Vertex[0].j].fixed_value ) {
940                 for ( k = 0; k < NumVerticesSelected; k++ )
941                         xyz[Vertex[k].i][Vertex[k].j].fixed_value = i;
942
943                 gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "fix_value" ) ),
944                                                                    (int)xyz[Vertex[0].i][Vertex[0].j].fixed_value );
945                 UpdatePreview( true );
946         }
947         return FALSE;
948 }
949
950 static void fix_value_changed( GtkAdjustment *adj, gpointer data ){
951         int k, i = (int)adj->value;
952
953         if ( xyz[Vertex[0].i][Vertex[0].j].fixed_value != i ) {
954                 for ( k = 0; k < NumVerticesSelected; k++ )
955                         xyz[Vertex[k].i][Vertex[k].j].fixed_value = i;
956                 UpdatePreview( true );
957         }
958 }
959
960 static gint fix_range_entryfocusout( GtkWidget *widget, GdkEventFocus *event, gpointer data ){
961         int i = atoi( gtk_entry_get_text( GTK_ENTRY( widget ) ) ), k;
962
963         if ( i != xyz[Vertex[0].i][Vertex[0].j].range ) {
964                 for ( k = 0; k < NumVerticesSelected; k++ )
965                         xyz[Vertex[k].i][Vertex[k].j].range = i;
966                 UpdatePreview( true );
967         }
968         return FALSE;
969 }
970
971 static gint fix_rate_entryfocusout( GtkWidget *widget, GdkEventFocus *event, gpointer data ){
972         double r = atof( gtk_entry_get_text( GTK_ENTRY( widget ) ) );
973         int k;
974
975         if ( r != xyz[Vertex[0].i][Vertex[0].j].rate ) {
976                 for ( k = 0; k < NumVerticesSelected; k++ )
977                         xyz[Vertex[k].i][Vertex[k].j].rate = r;
978                 UpdatePreview( true );
979         }
980         return FALSE;
981 }
982
983 static void fix_free( GtkWidget *widget, gpointer data ){
984         int k;
985
986         for ( k = 0; k < NumVerticesSelected; k++ )
987                 xyz[Vertex[k].i][Vertex[k].j].fixed = 0;
988         NumVerticesSelected = 0;
989         SetupControls();
990         UpdatePreview( true );
991 }
992
993 static void fix_freeall( GtkWidget *widget, gpointer data ){
994         int i, j;
995
996         for ( i = 0; i <= NH; i++ )
997         {
998                 for ( j = 0; j <= NV; j++ )
999                         xyz[i][j].fixed = 0;
1000         }
1001         fix_free( NULL, data ); // keep these together
1002 }
1003
1004 void vertex_selected(){
1005         char Text[32];
1006         int k;
1007
1008         SetupControls();
1009
1010         switch ( Plane )
1011         {
1012         case PLANE_XZ0:
1013         case PLANE_XZ1:
1014                 for ( k = 0; k < NumVerticesSelected; k++ )
1015                         xyz[Vertex[k].i][Vertex[k].j].fixed_value = xyz[Vertex[0].i][Vertex[0].j].p[1];
1016                 break;
1017         case PLANE_YZ0:
1018         case PLANE_YZ1:
1019                 for ( k = 0; k < NumVerticesSelected; k++ )
1020                         xyz[Vertex[k].i][Vertex[k].j].fixed_value = xyz[Vertex[0].i][Vertex[0].j].p[0];
1021                 break;
1022         default:
1023                 for ( k = 0; k < NumVerticesSelected; k++ )
1024                         xyz[Vertex[k].i][Vertex[k].j].fixed_value = xyz[Vertex[0].i][Vertex[0].j].p[2];
1025                 break;
1026         }
1027
1028         gtk_spin_button_set_value( GTK_SPIN_BUTTON( g_object_get_data( G_OBJECT( g_pWnd ), "fix_value" ) ),
1029                                                            (int)xyz[Vertex[0].i][Vertex[0].j].fixed_value );
1030
1031         sprintf( Text,"%d",(int)xyz[Vertex[0].i][Vertex[0].j].range );
1032         gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "fix_range" ) ), Text );
1033         sprintf( Text,"%.5g",xyz[Vertex[0].i][Vertex[0].j].rate );
1034         gtk_entry_set_text( GTK_ENTRY( g_object_get_data( G_OBJECT( g_pWnd ), "fix_rate" ) ), Text );
1035
1036         for ( k = 0; k < NumVerticesSelected; k++ )
1037                 xyz[Vertex[k].i][Vertex[k].j].fixed = 1;
1038
1039         UpdatePreview( true );
1040 }
1041
1042 // =============================================================================
1043 // texture tab callbacks
1044
1045 static void texture_detail( GtkToggleButton *check, gpointer data ){
1046         UseDetail = gtk_toggle_button_get_active( check );
1047         WasDetail = UseDetail;
1048 }
1049
1050 static void texture_hint( GtkToggleButton *check, gpointer data ){
1051         AddHints = gtk_toggle_button_get_active( check );
1052         if ( AddHints == 1 ) {
1053                 UseDetail = 1;
1054                 ENABLE_WIDGET( "detail", FALSE );
1055         }
1056         else
1057         {
1058                 UseDetail = WasDetail;
1059                 ENABLE_WIDGET( "detail", FALSE );
1060         }
1061         CHECK_WIDGET( "detail", UseDetail );
1062 }
1063
1064 // ^Fishman - Add terrain key to func_group.
1065 static void texture_terrainent( GtkToggleButton *check, gpointer data ){
1066         AddTerrainKey = gtk_toggle_button_get_active( check );
1067 }
1068
1069 static void texture_set( int index, const char* name ){
1070         strcpy( Texture[Game][index], name );
1071 }
1072
1073 static gint texture_entryfocusout( GtkWidget* widget, GdkEventFocus* event, gpointer data ){
1074         texture_set( GPOINTER_TO_INT( data ), gtk_entry_get_text( GTK_ENTRY( widget ) ) );
1075         return FALSE;
1076 }
1077
1078 // =============================================================================
1079 // misc stuff
1080
1081 static void UpdateVariable( GtkEntry *entry, GdkEventFocus *event, double *data ){
1082         double x = atof( gtk_entry_get_text( entry ) );
1083
1084         if ( x != *data ) {
1085                 *data = x;
1086                 UpdatePreview( true );
1087         }
1088 }
1089
1090 static gint doublevariable_entryfocusout( GtkWidget* widget, GdkEventFocus* event, gpointer data ){
1091         UpdateVariable( GTK_ENTRY( widget ), event, reinterpret_cast<double*>( data ) );
1092         return FALSE;
1093 }
1094
1095 // =============================================================================
1096 // create tooltips
1097
1098 void create_tooltips(){
1099         tooltips = gtk_tooltips_new();
1100
1101         // Main
1102         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1103                                                   g_object_get_data( G_OBJECT( g_pWnd , "go" ) ),
1104                                                   "Accept all input and generate a surface in Q3Radiant",
1105                                                   "" );
1106         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1107                                                   g_object_get_data( G_OBJECT( g_pWnd , "open" ) ),
1108                                                   "Open a previously saved GenSurf settings file.",
1109                                                   "" );
1110         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1111                                                   g_object_get_data( G_OBJECT( g_pWnd , "save" ) ),
1112                                                   "Save all settings to a file.",
1113                                                   "" );
1114         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1115                                                   g_object_get_data( G_OBJECT( g_pWnd , "defaults" ) ),
1116                                                   "Restore default values from DEFAULTS.SRF. If this file does not exist, GenSurf "
1117                                                   "initializes all input parameters to reasonable values. You can create your own "
1118                                                   "default surface by setting all parameters to your liking, then saving a settings "
1119                                                   "file as DEFAULTS.SRF with the Save As button.",
1120                                                   "" );
1121
1122         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1123                                                   g_object_get_data( G_OBJECT( g_pWnd , "main_preview" ) ),
1124                                                   "View a wire-frame representation of the surface",
1125                                                   "" );
1126
1127         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1128                                                   g_object_get_data( G_OBJECT( g_pWnd , "main_antialiasing" ) ),
1129                                                   "The lines in the preview window are antialiased for better quality",
1130                                                   "" );
1131
1132         // General tab
1133         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1134                                                   wave_radios[0] ,
1135                                                   "Builds a surface with alternating hills and valleys. Uses the general form Z=cos(X) "
1136                                                   "x sin(Y)",
1137                                                   "" );
1138         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1139                                                   wave_radios[1] ,
1140                                                   "Builds a surface with ridges parallel to the vertical axis.",
1141                                                   "" );
1142         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1143                                                   wave_radios[2] ,
1144                                                   "Builds a surface with ridges parallel to the horizontal axis.",
1145                                                   "" );
1146         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1147                                                   wave_radios[3] ,
1148                                                   "Builds a map from a bitmap image representing a contour plot. Click the \"Bitmap\" "
1149                                                   "tab to select the image. GenSurf only supports 256-color (8 bit) "
1150                                                   "bitmaps. GenSurf will work with any 256-color bitmap, but gray scale bitmaps are a bit "
1151                                                   "more intuitive.",
1152                                                   "" );
1153         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1154                                                   wave_radios[4] ,
1155                                                   "Builds a random surface using the Plasma Cloud technique. Variance is controlled "
1156                                                   "by the Roughness input. To build a surface with completely random values not "
1157                                                   "dependent on neighboring vertices, use one of the other waveforms with 0 amplitude.",
1158                                                   "" );
1159         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1160                                                   g_object_get_data( G_OBJECT( g_pWnd , "wavelength" ) ),
1161                                                   "Enter the wavelength (distance between crests). NOTE: Wavelengths equal to the grid "
1162                                                   "size or 2 times the grid size will result in 0 amplitudes. For best results, the "
1163                                                   "wavelength value should be at least 4 times the grid size (extents divided by the "
1164                                                   "number of divisions",
1165                                                   "" );
1166         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1167                                                   g_object_get_data( G_OBJECT( g_pWnd , "amplitude" ) ),
1168                                                   "Enter the height of hills/ridges.",
1169                                                   "" );
1170         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1171                                                   g_object_get_data( G_OBJECT( g_pWnd , "roughness" ) ),
1172                                                   "Enter the roughness value (noise) for the surface. For fractal surfaces, this value "
1173                                                   "is used as a variance in the fractal calculations.",
1174                                                   "" );
1175         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1176                                                   g_object_get_data( G_OBJECT( g_pWnd , "random" ) ),
1177                                                   "Seed value for the pseudo-random number generator.",
1178                                                   "" );
1179         // Extents tab
1180         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1181                                                   g_object_get_data( G_OBJECT( g_pWnd , "hmin" ) ),
1182                                                   "Minimum horizontal coordinate of the surface, i.e. X for a surface parallel to "
1183                                                   "the XY or XZ planes, Y for a surface parallel to the YZ plane. For best results, "
1184                                                   "the extents (maximum-minimum values) in a given direction should be evenly "
1185                                                   "divisible by the number of divisions in that direction.",
1186                                                   "" );
1187         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1188                                                   g_object_get_data( G_OBJECT( g_pWnd , "hmax" ) ),
1189                                                   "Maximum horizontal coordinate of the surface, i.e. X for a surface parallel to "
1190                                                   "the XY or XZ planes, Y for a surface parallel to the YZ plane. For best results, "
1191                                                   "the extents (maximum-minimum values) in a given direction should be evenly "
1192                                                   "divisible by the number of divisions in that direction.",
1193                                                   "" );
1194         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1195                                                   g_object_get_data( G_OBJECT( g_pWnd , "vmin" ) ),
1196                                                   "Minimum vertical coordinate of the surface, i.e. Y for a surface parallel to "
1197                                                   "the XY plane, Z for a surface parallel to the XZ or YZ planes. For best results, "
1198                                                   "the extents (maximum-minimum values) in a given direction should be evenly "
1199                                                   "divisible by the number of divisions in that direction.",
1200                                                   "" );
1201         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1202                                                   g_object_get_data( G_OBJECT( g_pWnd , "vmax" ) ),
1203                                                   "Maximum vertical coordinate of the surface, i.e. Y for a surface parallel to "
1204                                                   "the XY plane, Z for a surface parallel to the XZ or YZ planes. For best results, "
1205                                                   "the extents (maximum-minimum values) in a given direction should be evenly "
1206                                                   "divisible by the number of divisions in that direction.",
1207                                                   "" );
1208         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1209                                                   g_object_get_data( G_OBJECT( g_pWnd , "nh" ) ),
1210                                                   "Number of divisions in the horizontal direction. For best results, the extents "
1211                                                   "in a given direction should be evenly divisible by the number of divisions in "
1212                                                   "that direction.",
1213                                                   "" );
1214         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1215                                                   g_object_get_data( G_OBJECT( g_pWnd , "nv" ) ),
1216                                                   "Number of divisions in the vertical direction. For best results, the extents "
1217                                                   "in a given direction should be evenly divisible by the number of divisions in "
1218                                                   "that direction.",
1219                                                   "" );
1220         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1221                                                   g_object_get_data( G_OBJECT( g_pWnd , "use_patches" ) ),
1222                                                   "Produce one or more curved patches in the shape of your selected surface rather "
1223                                                   "than producing solid brushes. Depending on the size of your surface (and the "
1224                                                   "user's graphic detail settings, which you cannot control), curved surfaces will "
1225                                                   "be represented in the game by a very large number of polygons. Read the warnings "
1226                                                   "concerning curved surfaces on the GenSurf web page before using this feature.",
1227                                                   "" );
1228         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1229                                                   g_object_get_data( G_OBJECT( g_pWnd , "decimate" ) ),
1230                                                   "Use the slider to control the number of vertices discarded by GenSurf. For many "
1231                                                   "surfaces, you can produce roughly the same shape surface with a high decimation "
1232                                                   "value. This will generally result in a map with lower polygon counts (and better "
1233                                                   "in-game performance). However, this feature should NOT be used for large terrain "
1234                                                   "surfaces in Q3",
1235                                                   "" );
1236         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1237                                                   g_object_get_data( G_OBJECT( g_pWnd , "z00" ) ),
1238                                                   "Enter the height of the surface at the lower left corner. This value will likely "
1239                                                   "be modified unless \"Linear Borders\" is checked.",
1240                                                   "" );
1241         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1242                                                   g_object_get_data( G_OBJECT( g_pWnd , "z01" ) ),
1243                                                   "Enter the height of the surface at the upper left corner. This value will likely "
1244                                                   "be modified unless \"Linear Borders\" is checked.",
1245                                                   "" );
1246         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1247                                                   g_object_get_data( G_OBJECT( g_pWnd , "z10" ) ),
1248                                                   "Enter the height of the surface at the lower right corner. This value will likely "
1249                                                   "be modified unless \"Linear Borders\" is checked.",
1250                                                   "" );
1251         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1252                                                   g_object_get_data( G_OBJECT( g_pWnd , "z11" ) ),
1253                                                   "Enter the height of the surface at the upper right corner. This value will likely "
1254                                                   "be modified unless \"Linear Borders\" is checked.",
1255                                                   "" );
1256         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1257                                                   g_object_get_data( G_OBJECT( g_pWnd , "linearborder" ) ),
1258                                                   "Restrict the edges of the surface to a straight line. This will help match up "
1259                                                   "brush edges if you drop this surface into another map.",
1260                                                   "" );
1261         // Bitmap tab
1262         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1263                                                   g_object_get_data( G_OBJECT( g_pWnd , "bmp_file" ) ),
1264                                                   "Type the name of an 8-bit bitmap image file, or click Browse to select an image "
1265                                                   "from a list of those available on your system.",
1266                                                   "" );
1267         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1268                                                   g_object_get_data( G_OBJECT( g_pWnd , "bmp_file_browse" ) ),
1269                                                   "Select a bitmap image file from a list of those available on your system.",
1270                                                   "" );
1271         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1272                                                   g_object_get_data( G_OBJECT( g_pWnd , "bmp_reload" ) ),
1273                                                   "Reload the selected bitmap file after making changes in an external image editor.",
1274                                                   "" );
1275         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1276                                                   g_object_get_data( G_OBJECT( g_pWnd , "bmp_black" ) ),
1277                                                   "Enter the value corresponding to color index 0 in the bitmap file. For gray scale "
1278                                                   "images, color 0 is normally black.",
1279                                                   "" );
1280         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1281                                                   g_object_get_data( G_OBJECT( g_pWnd , "bmp_white" ) ),
1282                                                   "Enter the value corresponding to color index 255 in the bitmap file. For gray scale "
1283                                                   "images, color 255 is normally white.",
1284                                                   "" );
1285         // Fixpoints tab
1286         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1287                                                   g_object_get_data( G_OBJECT( g_pWnd , "fix_value" ) ),
1288                                                   "Enter a value for the selected vertex. This value will not be adjusted when applying "
1289                                                   "a waveform or roughness to the surface. Unlock this vertex (so that it will be "
1290                                                   "adjusted normally) by clicking \"Free\". This vertex will influence vertices within "
1291                                                   "the \"Range affected\" of this vertex.",
1292                                                   "" );
1293         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1294                                                   g_object_get_data( G_OBJECT( g_pWnd , "fix_range" ) ),
1295                                                   "Enter the range away from the selected vertex that other vertices will be affected. "
1296                                                   "Use 0 if you don't want other vertices to be influenced by the currently selected "
1297                                                   "one. Note: this box is disabled if you've chosen the fractal generator, as it uses "
1298                                                   "a completely different method for determining values.",
1299                                                   "" );
1300         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1301                                                   g_object_get_data( G_OBJECT( g_pWnd , "fix_rate" ) ),
1302                                                   "Enter a rate of change for the surface affected by the fixed value. 0 gives a smooth "
1303                                                   "sinusoidal curve, values less than 0 give progressively sharper spikes, and values "
1304                                                   "greater than 0 take on a square shape. Values less than -30 or greater than 30 are "
1305                                                   "set to -30 and 30, respectively. Note that this entry will have no effect unless "
1306                                                   "you also specify a \"range affected\".",
1307                                                   "" );
1308         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1309                                                   g_object_get_data( G_OBJECT( g_pWnd , "fix_free" ) ),
1310                                                   "Click this to free (unlock the value of) the currently selected vertex.",
1311                                                   "" );
1312         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1313                                                   g_object_get_data( G_OBJECT( g_pWnd , "fix_freeall" ) ),
1314                                                   "Click this to free (unlock the values of) all vertices.",
1315                                                   "" );
1316         // Texture tab
1317         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1318                                                   g_object_get_data( G_OBJECT( g_pWnd , "texture1" ) ),
1319                                                   "Enter the name of the texture or shader used for the surface faces.",
1320                                                   "" );
1321         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1322                                                   g_object_get_data( G_OBJECT( g_pWnd , "texture2" ) ),
1323                                                   "Enter the name of the texture or shader used for faces other than the surface. Under "
1324                                                   "normal circumstances this should be \"common/caulk\"",
1325                                                   "" );
1326         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1327                                                   g_object_get_data( G_OBJECT( g_pWnd , "texture3" ) ),
1328                                                   "Enter the name of the texture or shader used for \"steep\" surface faces, where \"steep\" "
1329                                                   "is the angle specified below. If this entry is left blank or if the \"steep\" angle is 0, "
1330                                                   "all surface faces will use the texture specified by \"Surface\".",
1331                                                   "" );
1332
1333         gtk_tooltips_set_tip( GTK_TOOLTIPS( tooltips ),
1334                                                   g_object_get_data( G_OBJECT( g_pWnd , "detail" ) ),
1335                                                   "Check this box to use the detail content property on the generated brushes. Compile "
1336                                                   "times will be considerably shorter if the detail property is used, though the surface "
1337                                                   "will not block visibility at all. If you use the detail property, you should make sure "
1338                                                   "that \"common/caulk\" is used for the non-surface faces, or the polygon count will be "
1339                                                   "much higher than necessary.",
1340                                                   "" );
1341 }
1342
1343 // =============================================================================
1344 // create main dialog
1345
1346 GtkWidget* create_main_dialog(){
1347         GtkWidget *hbox2, *button, *notebook, *table2;
1348         GtkWidget *check, *spin, *radio, *label, *entry, *scale;
1349         ui::Adjustment adj;
1350         GSList *group;
1351         int i;
1352         const char *games[] = { "Quake 2", "Half-Life", "SiN", "Heretic 2", "Kingpin", "Genesis3D", "Quake 3 Arena" };
1353         const char *waveforms[] = { "Alternating hill/valley", "Cylindrical left-to-right", "Cylindrical top-to-bottom",
1354                                                                 "From bitmap", "Fractal" };
1355         const char *orientations[] = { "Ground surface", "Ceiling", "Wall facing 0", "Wall facing 90",
1356                                                                    "Wall facing 180","Wall facing 270" };
1357
1358         auto dlg = g_pWnd = ui::Window( ui::window_type::TOP );
1359         gtk_window_set_title( dlg, gszCaption );
1360         dlg.connect( "delete_event", G_CALLBACK( main_close ), NULL );
1361         //  dlg.connect( "destroy", G_CALLBACK (gtk_widget_destroy), NULL);
1362         gtk_window_set_transient_for( dlg, g_pRadiantWnd );
1363
1364         auto hbox = ui::HBox( FALSE, 5 );
1365         hbox.show();
1366         dlg.add(hbox);
1367         gtk_container_set_border_width( GTK_CONTAINER( hbox ), 5 );
1368
1369         notebook = gtk_notebook_new();
1370         notebook.show();
1371         hbox.pack_start( notebook, TRUE, TRUE, 0 );
1372         notebook.connect( "switch_page",
1373                                           G_CALLBACK( switch_page ), NULL );
1374         gtk_notebook_set_tab_pos( GTK_NOTEBOOK( notebook ), GTK_POS_TOP );
1375         g_object_set_data( G_OBJECT( dlg ), "notebook", notebook );
1376
1377         table = ui::Table( 2, 2, FALSE );
1378         table.show();
1379         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1380     gtk_table_set_row_spacings(table, 5);
1381     gtk_table_set_col_spacings(table, 5);
1382
1383         label = ui::Label( "General" );
1384         label.show();
1385         gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), table, label );
1386
1387         auto frame = ui::Frame( "Game" );
1388         frame.show();
1389         table.attach(frame, {0, 1, 0, 1});
1390
1391         auto vbox = ui::VBox( TRUE, 5 );
1392         vbox.show();
1393         frame.add(vbox);
1394         gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
1395
1396         for ( i = 0, group = NULL; i < NUMGAMES; i++ )
1397         {
1398                 radio = gtk_radio_button_new_with_label( group, games[i] );
1399                 radio.show();
1400                 vbox.pack_start( radio, TRUE, TRUE, 0 );
1401                 group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radio ) );
1402                 game_radios[i] = radio;
1403                 radio.connect( "toggled", G_CALLBACK( general_game ), GINT_TO_POINTER( i ) );
1404         }
1405
1406         frame = ui::Frame( "Waveform" );
1407         frame.show();
1408         table.attach(frame, {1, 2, 0, 1});
1409
1410         vbox = ui::VBox( TRUE, 5 );
1411         vbox.show();
1412         frame.add(vbox);
1413         gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
1414
1415         for ( i = 0, group = NULL; i < 5; i++ )
1416         {
1417                 radio = gtk_radio_button_new_with_label( group, waveforms[i] );
1418                 radio.show();
1419                 vbox.pack_start( radio, TRUE, TRUE, 0 );
1420                 group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radio ) );
1421                 wave_radios[i] = radio;
1422                 radio.connect( "toggled", G_CALLBACK( general_wave ), GINT_TO_POINTER( i ) );
1423         }
1424
1425         frame = ui::Frame( "Orientation" );
1426         frame.show();
1427         table.attach(frame, {0, 1, 1, 2});
1428
1429         vbox = ui::VBox( TRUE, 5 );
1430         vbox.show();
1431         frame.add(vbox);
1432         gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
1433
1434         for ( i = 0, group = NULL; i < 6; i++ )
1435         {
1436                 radio = gtk_radio_button_new_with_label( group, orientations[i] );
1437                 radio.show();
1438                 vbox.pack_start( radio, TRUE, TRUE, 0 );
1439                 group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( radio ) );
1440                 plane_radios[i] = radio;
1441                 radio.connect( "toggled", G_CALLBACK( general_plane ), GINT_TO_POINTER( i ) );
1442         }
1443
1444         table2 = ui::Table( 4, 2, FALSE );
1445         table2.show();
1446     gtk_table_set_row_spacings(table2, 5);
1447     gtk_table_set_col_spacings(table2, 5);
1448         table.attach(table2, {1, 2, 1, 2});
1449
1450         label = ui::Label( "Wavelength:" );
1451         label.show();
1452         table2.attach(label, {0, 1, 0, 1});
1453         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
1454         gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_RIGHT );
1455
1456         label = ui::Label( "Max. amplitude:" );
1457         label.show();
1458         table2.attach(label, {0, 1, 1, 2});
1459         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
1460         gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_RIGHT );
1461
1462         label = ui::Label( "Roughness:" );
1463         label.show();
1464     table2.attach(label, {0, 1, 2, 3});
1465         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
1466         gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_RIGHT );
1467
1468         label = ui::Label( "Random seed:" );
1469         label.show();
1470     table2.attach(label, {0, 1, 3, 4});
1471         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
1472         gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_RIGHT );
1473
1474         entry = ui::Entry();
1475         entry.show();
1476     table2.attach(entry, {1, 2, 0, 1});
1477         entry.dimensions( 50, -1 );
1478         g_object_set_data( G_OBJECT( dlg ), "wavelength", entry );
1479         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &WaveLength );
1480
1481         entry = ui::Entry();
1482         entry.show();
1483     table2.attach(entry, {1, 2, 1, 2});
1484         entry.dimensions( 50, -1 );
1485         g_object_set_data( G_OBJECT( dlg ), "amplitude", entry );
1486         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Amplitude );
1487
1488         entry = ui::Entry();
1489         entry.show();
1490         table2.attach(entry, {1, 2, 2, 3});
1491         entry.dimensions( 50, -1 );
1492         g_object_set_data( G_OBJECT( dlg ), "roughness", entry );
1493         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Roughness );
1494
1495         adj = ui::Adjustment( 1, 1, 32767, 1, 10, 0 );
1496         adj.connect( "value_changed", G_CALLBACK( general_random ), NULL );
1497         spin = ui::SpinButton( adj, 1, 0 );
1498         spin.show();
1499         table2.attach(spin, {1, 2, 3, 4});
1500         spin.dimensions( 60, -1 );
1501         g_object_set_data( G_OBJECT( dlg ), "random", spin );
1502
1503         vbox = ui::VBox( FALSE, 5 );
1504         vbox.show();
1505         gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
1506
1507         label = ui::Label( "Extents" );
1508         label.show();
1509         gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), vbox, label );
1510
1511         hbox2 = ui::HBox( FALSE, 5 );
1512         hbox2.show();
1513         vbox.pack_start( hbox2, FALSE, TRUE, 0 );
1514
1515         frame = ui::Frame( "Extents" );
1516         frame.show();
1517         hbox2.pack_start( frame, TRUE, TRUE, 0 );
1518
1519         auto table = ui::Table( 3, 4, FALSE );
1520         table.show();
1521         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1522         frame.add(table);
1523     gtk_table_set_row_spacings(table, 5);
1524     gtk_table_set_col_spacings(table, 5);
1525
1526         label = ui::Label( "X:" );
1527         label.show();
1528         table.attach( label, {0, 1, 1, 2}, {GTK_FILL, GTK_FILL});
1529         g_object_set_data( G_OBJECT( dlg ), "hmin_text", label );
1530
1531         label = ui::Label( "X:" );
1532         label.show();
1533         table.attach(label, {2, 3, 1, 2}, {GTK_FILL, GTK_FILL});
1534         g_object_set_data( G_OBJECT( dlg ), "hmax_text", label );
1535
1536         label = ui::Label( "Y:" );
1537         label.show();
1538         table.attach(label, {0, 1, 2, 3}, {GTK_FILL, GTK_FILL});
1539         g_object_set_data( G_OBJECT( dlg ), "vmin_text", label );
1540
1541         label = ui::Label( "Y:" );
1542         label.show();
1543         table.attach(label, {2, 3, 2, 3}, {GTK_FILL, GTK_FILL});
1544         g_object_set_data( G_OBJECT( dlg ), "vmax_text", label );
1545
1546         label = ui::Label( "Lower-left" );
1547         label.show();
1548         table.attach(label, {1, 2, 0, 1}, {GTK_FILL, GTK_FILL});
1549
1550         label = ui::Label( "Upper-right" );
1551         label.show();
1552         table.attach(label, {3, 4, 0, 1},, {GTK_FILL, GTK_FILL});
1553
1554         entry = ui::Entry();
1555         entry.show();
1556         table.attach(entry, {1, 2, 1, 2});
1557         entry.dimensions( 50, -1 );
1558         g_object_set_data( G_OBJECT( dlg ), "hmin", entry );
1559         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Hll );
1560
1561         entry = ui::Entry();
1562         entry.show();
1563         table.attach(entry, {3, 4, 1, 2});
1564         entry.dimensions( 50, -1 );
1565         g_object_set_data( G_OBJECT( dlg ), "hmax", entry );
1566         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Hur );
1567
1568         entry = ui::Entry();
1569         entry.show();
1570         table.attach(entry, {1, 2, 2, 3});
1571         entry.dimensions( 50, -1 );
1572         g_object_set_data( G_OBJECT( dlg ), "vmin", entry );
1573         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Vll );
1574
1575         entry = ui::Entry();
1576         entry.show();
1577         table.attach(entry, {3, 4, 2, 3});
1578         entry.dimensions( 50, -1 );
1579         g_object_set_data( G_OBJECT( dlg ), "vmax", entry );
1580         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Vur );
1581
1582         frame = ui::Frame( "Divisions" );
1583         frame.show();
1584         hbox2.pack_start( frame, TRUE, TRUE, 0 );
1585
1586         table = ui::Table( 2, 2, FALSE );
1587         table.show();
1588         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1589         frame.add(table);
1590     gtk_table_set_row_spacings(table, 5);
1591     gtk_table_set_col_spacings(table, 5);
1592
1593         label = ui::Label( "X:" );
1594         label.show();
1595         table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_EXPAND | GTK_FILL});
1596         g_object_set_data( G_OBJECT( dlg ), "nh_text", label );
1597
1598         label = ui::Label( "Y:" );
1599         label.show();
1600         table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_EXPAND | GTK_FILL});
1601         g_object_set_data( G_OBJECT( dlg ), "nv_text", label );
1602
1603         adj = ui::Adjustment( 8, 1, MAX_ROWS, 1, 10, 0 );
1604         adj.connect( "value_changed", G_CALLBACK( extents_nhnv_spin ), &NH );
1605         spin = ui::SpinButton( adj, 1, 0 );
1606         spin.show();
1607         table.attach(spin, {1, 2, 0, 1});
1608         spin.dimensions( 60, -1 );
1609         g_object_set_data( G_OBJECT( dlg ), "nh", spin );
1610
1611         adj = ui::Adjustment( 8, 1, MAX_ROWS, 1, 10, 0 );
1612         adj.connect( "value_changed", G_CALLBACK( extents_nhnv_spin ), &NV );
1613         spin = ui::SpinButton( adj, 1, 0 );
1614         spin.show();
1615         table.attach(spin, {1, 2, 1, 2});
1616         spin.dimensions( 60, -1 );
1617         g_object_set_data( G_OBJECT( dlg ), "nv", spin );
1618
1619         check = ui::CheckButton( "Use Bezier patches" );
1620         check.show();
1621         vbox.pack_start( check, FALSE, TRUE, 0 );
1622         g_object_set_data( G_OBJECT( dlg ), "use_patches", check );
1623         check.connect( "toggled", G_CALLBACK( extents_use_patches ), NULL );
1624
1625         // ^Fishman - Snap to grid, replaced scroll bar with a texbox.
1626         label = ui::Label( "Snap to grid:" );
1627         label.show();
1628         vbox.pack_start( label, FALSE, TRUE, 0 );
1629         gtk_object_set_data( GTK_OBJECT( dlg ), "snap_text", label );
1630
1631         adj = ui::Adjustment( 8, 0, 256, 1, 10, 0 );
1632         adj.connect( "value_changed", G_CALLBACK( extents_snaptogrid_spin ), &SP );
1633         spin = ui::SpinButton( adj, 1, 0 );
1634         spin.show();
1635         vbox.pack_start( spin, FALSE, TRUE, 0 );
1636         spin.dimensions( 60, -1 );
1637         g_object_set_data( G_OBJECT( dlg ), "sp", spin );
1638         // ^Fishman - End of Snap to grid code.
1639
1640         hbox2 = ui::HBox( FALSE, 5 );
1641         hbox2.show();
1642         vbox.pack_start( hbox2, FALSE, TRUE, 10 );
1643
1644         label = ui::Label( "Decimate:" );
1645         label.show();
1646         hbox2.pack_start( label, FALSE, TRUE, 0 );
1647
1648         adj = ui::Adjustment( 0, 0, 110, 1, 10, 0 );
1649         adj.connect( "value_changed", G_CALLBACK( extents_decimate ), NULL );
1650         g_object_set_data( G_OBJECT( dlg ), "decimate_adj", adj );
1651         scale = ui::HScale( adj );
1652         scale.show();
1653         hbox2.pack_start( scale, TRUE, TRUE, 0 );
1654         gtk_scale_set_value_pos( GTK_SCALE( scale ), GTK_POS_RIGHT );
1655         gtk_scale_set_digits( GTK_SCALE( scale ), 0 );
1656         g_object_set_data( G_OBJECT( dlg ), "decimate", scale );
1657
1658         frame = ui::Frame( "Corner values" );
1659         frame.show();
1660         vbox.pack_start( frame, FALSE, TRUE, 0 );
1661
1662         table = ui::Table( 3, 4, FALSE );
1663         table.show();
1664         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1665         frame.add(table);
1666     gtk_table_set_row_spacings(table, 5);
1667     gtk_table_set_col_spacings(table, 5);
1668
1669         label = ui::Label( "Upper-left:" );
1670         label.show();
1671         table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_FILL});
1672
1673         label = ui::Label( "Lower-left:" );
1674         label.show();
1675         table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_FILL});
1676
1677         label = ui::Label( "Upper-right:" );
1678         label.show();
1679         table.attach(label, {2, 3, 0, 1}, {GTK_FILL, GTK_FILL});
1680
1681         label = ui::Label( "Lower-right:" );
1682         label.show();
1683         table.attach(label, {2, 3, 1, 2}, {GTK_FILL, GTK_FILL});
1684
1685         entry = ui::Entry();
1686         entry.show();
1687         table.attach(entry, {1, 2, 0, 1});
1688         entry.dimensions( 50, -1 );
1689         g_object_set_data( G_OBJECT( dlg ), "z01", entry );
1690         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Z01 );
1691
1692         entry = ui::Entry();
1693         entry.show();
1694         table.attach(entry, {1, 2, 1, 2});
1695         entry.dimensions( 50, -1 );
1696         g_object_set_data( G_OBJECT( dlg ), "z00", entry );
1697         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Z00 );
1698
1699         entry = ui::Entry();
1700         entry.show();
1701         table.attach(entry, {3, 4, 0, 1});
1702         entry.dimensions( 50, -1 );
1703         g_object_set_data( G_OBJECT( dlg ), "z11", entry );
1704         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Z11 );
1705
1706         entry = ui::Entry();
1707         entry.show();
1708         table.attach(entry, {3, 4, 1, 2});
1709         entry.dimensions( 50, -1 );
1710         g_object_set_data( G_OBJECT( dlg ), "z10", entry );
1711         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &Z10 );
1712
1713         check = ui::CheckButton( "Linear borders" );
1714         check.show();
1715         table.attach(check, {0, 4, 2, 3});
1716         g_object_set_data( G_OBJECT( dlg ), "linearborder", check );
1717         check.connect( "toggled", G_CALLBACK( extents_linearborder ), NULL );
1718
1719         vbox = ui::VBox( FALSE, 10 );
1720         vbox.show();
1721         gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
1722
1723         label = ui::Label( "Bitmap" );
1724         label.show();
1725         gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), vbox, label );
1726
1727         label = ui::Label( "" );
1728         label.show();
1729         vbox.pack_start( label, FALSE, TRUE, 0 );
1730         g_object_set_data( G_OBJECT( dlg ), "bmp_note", label );
1731
1732         table = ui::Table( 2, 2, FALSE );
1733         table.show();
1734         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1735         vbox.pack_start( table, FALSE, TRUE, 0 );
1736     gtk_table_set_row_spacings(table, 5);
1737     gtk_table_set_col_spacings(table, 5);
1738
1739         label = ui::Label( "Filename:" );
1740         label.show();
1741         table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_FILL});
1742         g_object_set_data( G_OBJECT( dlg ), "bmp_text1", label );
1743
1744         entry = ui::Entry();
1745         entry.show();
1746         table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1747         g_object_set_data( G_OBJECT( dlg ), "bmp_file", entry );
1748         entry.connect( "focus_out_event", G_CALLBACK( bitmap_file_entryfocusout ), NULL );
1749
1750         hbox2 = ui::HBox( TRUE, 5 );
1751         hbox2.show();
1752         table.attach(hbox2, {1, 2, 1, 2}, {0, GTK_EXPAND | GTK_FILL});
1753
1754         button = ui::Button( "Browse..." );
1755         button.show();
1756         hbox2.pack_start( button, FALSE, FALSE, 0 );
1757         button.dimensions( 60, -1 );
1758         g_object_set_data( G_OBJECT( dlg ), "bmp_file_browse", button );
1759         button.connect( "clicked", G_CALLBACK( bitmap_browse ), NULL );
1760
1761         button = ui::Button( "Reload" );
1762         button.show();
1763         hbox2.pack_start( button, FALSE, FALSE, 0 );
1764         button.dimensions( 60, -1 );
1765         g_object_set_data( G_OBJECT( dlg ), "bmp_reload", button );
1766         button.connect( "clicked", G_CALLBACK( bitmap_reload ), NULL );
1767
1768         table = ui::Table( 2, 2, TRUE );
1769         table.show();
1770         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1771         vbox.pack_start( table, FALSE, TRUE, 0 );
1772     gtk_table_set_row_spacings(table, 5);
1773     gtk_table_set_col_spacings(table, 5);
1774
1775         label = ui::Label( "Map color 0 to:" );
1776         label.show();
1777         table.attach(label, {0, 1, 0, 1}, {GTK_FILL | GTK_EXPAND, GTK_FILL});
1778         g_object_set_data( G_OBJECT( dlg ), "bmp_text2", label );
1779         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
1780         gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_RIGHT );
1781
1782         label = ui::Label( "Map color 255 to:" );
1783         label.show();
1784         table.attach(label, {0, 1, 1, 2}, {GTK_FILL | GTK_EXPAND, GTK_FILL});
1785         g_object_set_data( G_OBJECT( dlg ), "bmp_text3", label );
1786         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
1787         gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_RIGHT );
1788
1789         hbox2 = ui::HBox( FALSE, 5 );
1790         hbox2.show();
1791         table.attach(hbox2, {1, 2, 0, 1});
1792
1793         entry = ui::Entry();
1794         entry.show();
1795         hbox2.pack_start( entry, FALSE, FALSE, 0 );
1796         entry.dimensions( 50, -1 );
1797         g_object_set_data( G_OBJECT( dlg ), "bmp_black", entry );
1798         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &gbmp.black_value );
1799
1800         hbox2 = ui::HBox( FALSE, 5 );
1801         hbox2.show();
1802         table.attach(hbox2, {1, 2, 1, 2});
1803
1804         entry = ui::Entry();
1805         entry.show();
1806         hbox2.pack_start( entry, FALSE, FALSE, 0 );
1807         entry.dimensions( 50, -1 );
1808         g_object_set_data( G_OBJECT( dlg ), "bmp_white", entry );
1809         entry.connect( "focus_out_event", G_CALLBACK( doublevariable_entryfocusout ), &gbmp.white_value );
1810
1811         vbox = ui::VBox( FALSE, 10 );
1812         vbox.show();
1813         gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
1814
1815         label = ui::Label( "Fix Points" );
1816         label.show();
1817         gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), vbox, label );
1818
1819         label = ui::Label( "Click on a vertex in the lower half of the preview window,\n"
1820                                                    "then use the arrow keys or text box to assign a value.\n"
1821                                                    "Use Ctrl+Click to select multiple vertices/toggle a\n"
1822                                                    "selection. Use Shift+Click to select a range of vertices.\n\n"
1823                                                    "Click \"Free\" to unlock a vertex. Vertices within \"Range\n"
1824                                                    "affected\" will be influenced by this vertex." );
1825         label.show();
1826         vbox.pack_start( label, FALSE, TRUE, 0 );
1827
1828         table = ui::Table( 3, 3, FALSE );
1829         table.show();
1830         gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1831         vbox.pack_start( table, FALSE, TRUE, 0 );
1832     gtk_table_set_row_spacings(table, 5);
1833     gtk_table_set_col_spacings(table, 5);
1834
1835         label = ui::Label( "Value:" );
1836         label.show();
1837         table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_FILL});
1838         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
1839         g_object_set_data( G_OBJECT( dlg ), "fix_value_text", label );
1840
1841         label = ui::Label( "Range affected:" );
1842         label.show();
1843         table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_FILL});
1844         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
1845         g_object_set_data( G_OBJECT( dlg ), "fix_range_text", label );
1846
1847         label = ui::Label( "Rate of change:" );
1848         label.show();
1849         table.attach(label, {0, 1, 2, 3}, {GTK_FILL, GTK_FILL});
1850         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
1851         g_object_set_data( G_OBJECT( dlg ), "fix_rate_text", label );
1852
1853         adj = ui::Adjustment( 0, -65536, 65536, 1, 16, 0 );
1854         adj.connect( "value_changed", G_CALLBACK( fix_value_changed ), NULL );
1855         spin = ui::SpinButton( adj, 1, 0 );
1856         spin.show();
1857         table.attach(spin, {1, 2, 0, 1}, {GTK_EXPAND, GTK_EXPAND});
1858         spin.dimensions( 60, -1 );
1859         g_object_set_data( G_OBJECT( dlg ), "fix_value", spin );
1860         spin.connect( "focus_out_event", G_CALLBACK( fix_value_entryfocusout ), NULL );
1861
1862         entry = ui::Entry();
1863         entry.show();
1864         table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND, GTK_FILL});
1865         entry.dimensions( 60, -1 );
1866         g_object_set_data( G_OBJECT( dlg ), "fix_range", entry );
1867         entry.connect( "focus_out_event", G_CALLBACK( fix_range_entryfocusout ), NULL );
1868
1869         entry = ui::Entry();
1870         entry.show();
1871         table.attach(entry, {1, 2, 2, 3}, {GTK_EXPAND, GTK_FILL});
1872         entry.dimensions( 60, -1 );
1873         g_object_set_data( G_OBJECT( dlg ), "fix_rate", entry );
1874         entry.connect( "focus_out_event", G_CALLBACK( fix_rate_entryfocusout ), NULL );
1875
1876         button = ui::Button( "Free" );
1877         button.show();
1878         table.attach(button, {2, 3, 0, 1}, {GTK_EXPAND, GTK_FILL});
1879         button.dimensions( 60, -1 );
1880         g_object_set_data( G_OBJECT( dlg ), "fix_free", button );
1881         button.connect( "clicked", G_CALLBACK( fix_free ), NULL );
1882
1883         button = ui::Button( "Free All" );
1884         button.show();
1885         table.attach(button, {2, 3, 1, 2}, {GTK_EXPAND, GTK_FILL});
1886         button.dimensions( 60, -1 );
1887         g_object_set_data( G_OBJECT( dlg ), "fix_freeall", button );
1888         button.connect( "clicked", G_CALLBACK( fix_freeall ), NULL );
1889
1890         vbox = ui::VBox( FALSE, 10 );
1891         vbox.show();
1892         gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
1893
1894         label = ui::Label( "Texture" );
1895         label.show();
1896         gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), vbox, label );
1897
1898         // ^Fishman - Modified to add more labels and textboxes.
1899         table = ui::Table( 5, 2, FALSE );
1900         table.show();
1901         vbox.pack_start( table, FALSE, TRUE, 0 );
1902     gtk_table_set_row_spacings(table, 5);
1903     gtk_table_set_col_spacings(table, 5);
1904
1905         label = ui::Label( "Surface:" );
1906         label.show();
1907         table.attach(label, {0, 1, 0, 1}, {GTK_FILL, GTK_FILL});
1908         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
1909
1910         label = ui::Label( "Other:" );
1911         label.show();
1912         table.attach(label, {0, 1, 1, 2}, {GTK_FILL, GTK_FILL});
1913         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
1914
1915         label = ui::Label( "Steep:" );
1916         label.show();
1917         table.attach(label, {0, 1, 2, 3}, {GTK_FILL, GTK_FILL});
1918         gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
1919
1920         entry = ui::Entry();
1921         entry.show();
1922         table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1923         entry.dimensions( 60, -1 );
1924         g_object_set_data( G_OBJECT( dlg ), "texture1", entry );
1925         entry.connect( "focus_out_event", G_CALLBACK( texture_entryfocusout ), GINT_TO_POINTER( 0 ) );
1926
1927         entry = ui::Entry();
1928         entry.show();
1929         table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1930         entry.dimensions( 60, -1 );
1931         g_object_set_data( G_OBJECT( dlg ), "texture2", entry );
1932         entry.connect( "focus_out_event", G_CALLBACK( texture_entryfocusout ), GINT_TO_POINTER( 1 ) );
1933
1934         entry = ui::Entry();
1935         entry.show();
1936         table.attach(entry, {1, 2, 2, 3}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1937         entry.dimensions( 60, -1 );
1938         g_object_set_data( G_OBJECT( dlg ), "texture3", entry );
1939
1940         hbox2 = ui::HBox( FALSE, 5 );
1941         hbox2.show();
1942         vbox.pack_start( hbox2, FALSE, TRUE, 0 );
1943
1944         label = ui::Label( "\"Steep\" angle:" );
1945         label.show();
1946         hbox2.pack_start( label, FALSE, TRUE, 0 );
1947
1948         adj = ui::Adjustment( 60, 0, 90, 1, 10, 0 );
1949         spin = ui::SpinButton( adj, 1, 0 );
1950         spin.show();
1951         hbox2.pack_start( spin, FALSE, TRUE, 0 );
1952         g_object_set_data( G_OBJECT( dlg ), "tex_slant", spin );
1953
1954         table = ui::Table( 2, 4, TRUE );
1955         table.show();
1956         vbox.pack_start( table, FALSE, TRUE, 0 );
1957     gtk_table_set_row_spacings(table, 5);
1958     gtk_table_set_col_spacings(table, 5);
1959
1960         label = ui::Label( "Offset <h,v>" );
1961         label.show();
1962         table.attach(label, {0, 2, 0, 1}, {GTK_FILL, GTK_FILL});
1963
1964         label = ui::Label( "Scale <h,v>" );
1965         label.show();
1966         table.attach(label, {2, 4, 0, 1}, {GTK_FILL, GTK_FILL});
1967
1968         entry = ui::Entry();
1969         entry.show();
1970         table.attach(entry, {0, 1, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1971         entry.dimensions( 60, -1 );
1972         g_object_set_data( G_OBJECT( dlg ), "texoffsetx", entry );
1973
1974         entry = ui::Entry();
1975         entry.show();
1976         table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1977         entry.dimensions( 60, -1 );
1978         g_object_set_data( G_OBJECT( dlg ), "texoffsety", entry );
1979
1980         entry = ui::Entry();
1981         entry.show();
1982         table.attach(entry, {2, 3, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1983         entry.dimensions( 60, -1 );
1984         g_object_set_data( G_OBJECT( dlg ), "texscalex", entry );
1985
1986         entry = ui::Entry();
1987         entry.show();
1988         table.attach(entry, {3, 4, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1989         entry.dimensions( 60, -1 );
1990         g_object_set_data( G_OBJECT( dlg ), "texscaley", entry );
1991
1992
1993
1994         check = ui::CheckButton( "Use detail brushes" );
1995         check.show();
1996         vbox.pack_start( check, FALSE, TRUE, 0 );
1997         g_object_set_data( G_OBJECT( dlg ), "detail", check );
1998         check.connect( "toggled", G_CALLBACK( texture_detail ), NULL );
1999
2000         check = ui::CheckButton( "Detail hint brushes" );
2001         check.show();
2002         vbox.pack_start( check, FALSE, TRUE, 0 );
2003         g_object_set_data( G_OBJECT( dlg ), "hint", check );
2004         check.connect( "toggled", G_CALLBACK( texture_hint ), NULL );
2005
2006         // ^Fishman - Add terrain key to func_group.
2007         check = ui::CheckButton( "Add terrain key" );
2008         check.show();
2009         vbox.pack_start( check, FALSE, TRUE, 0 );
2010         g_object_set_data( G_OBJECT( dlg ), "terrain_ent", check );
2011         check.connect( "toggled", G_CALLBACK( texture_terrainent ), NULL );
2012
2013         vbox = ui::VBox( FALSE, 5 );
2014         vbox.show();
2015         hbox.pack_start( vbox, FALSE, TRUE, 0 );
2016
2017         button = ui::Button( "OK" );
2018         button.show();
2019         vbox.pack_start( button, FALSE, TRUE, 0 );
2020         button.dimensions( 60, -1 );
2021         g_object_set_data( G_OBJECT( dlg ), "go", button );
2022         button.connect( "clicked", G_CALLBACK( main_go ), NULL );
2023
2024         label = ui::Label( "Settings:" );
2025         label.show();
2026         vbox.pack_start( label, FALSE, TRUE, 0 );
2027
2028         button = ui::Button( "Open..." );
2029         button.show();
2030         vbox.pack_start( button, FALSE, TRUE, 0 );
2031         g_object_set_data( G_OBJECT( dlg ), "open", button );
2032         button.connect( "clicked", G_CALLBACK( main_open ), NULL );
2033
2034         button = ui::Button( "Save as..." );
2035         button.show();
2036         vbox.pack_start( button, FALSE, TRUE, 0 );
2037         g_object_set_data( G_OBJECT( dlg ), "save", button );
2038         button.connect( "clicked", G_CALLBACK( main_save ), NULL );
2039
2040         button = ui::Button( "Defaults" );
2041         button.show();
2042         vbox.pack_start( button, FALSE, TRUE, 0 );
2043         g_object_set_data( G_OBJECT( dlg ), "defaults", button );
2044         button.connect( "clicked", G_CALLBACK( main_defaults ), NULL );
2045
2046         button = ui::Button( "About..." );
2047         button.show();
2048         vbox.pack_start( button, FALSE, TRUE, 0 );
2049         button.connect( "clicked", G_CALLBACK( main_about ), NULL );
2050
2051         check = ui::CheckButton( "Preview" );
2052         check.show();
2053         vbox.pack_start( check, FALSE, TRUE, 0 );
2054         check.connect( "toggled", G_CALLBACK( main_preview ), NULL );
2055         g_object_set_data( G_OBJECT( dlg ), "main_preview", check );
2056
2057         // ^Fishman - Antializing for the preview window.
2058         check = ui::CheckButton( "Antialised lines" );
2059         check.show();
2060         vbox.pack_start( check, FALSE, TRUE, 0 );
2061         g_object_set_data( G_OBJECT( dlg ), "main_antialiasing", check );
2062         check.connect( "toggled", G_CALLBACK( main_antialiasing ), NULL );
2063
2064         for ( i = 0; i < 5; i++ )
2065                 SetDlgValues( i );
2066
2067         CreateViewWindow();
2068
2069         create_tooltips();
2070
2071         FirstPassComplete = 1;
2072
2073         return dlg;
2074 }
2075
2076
2077 #if 0
2078
2079 HWND hwndDisplay = (HWND)NULL;
2080 HWND ghwndTab    = (HWND)NULL;
2081 int iTab = 0;
2082 Rect rcTab;
2083 FILE *ftex;
2084
2085 char GenSurfURL[40] = {"http://tarot.telefragged.com/gensurf"};
2086 char GenSurfBoard[40] = {"http://tarot.telefragged.com/board"};
2087
2088 /*
2089  * AboutDlgProc - processes messages for the about dialog.
2090  */
2091
2092 qboolean CALLBACK AboutDlgProc( HWND hwnd, unsigned msg, UINT wparam, LONG lparam ){
2093         char szText[256];
2094         DRAWITEMSTRUCT *dis;
2095         HDC hdc;
2096         HPEN hpen;
2097         HWND hwndURL;
2098         Rect rc;
2099         SIZE size;
2100
2101         lparam = lparam;                    /* turn off warning */
2102
2103         switch ( msg ) {
2104         case WM_INITDIALOG:
2105                 strcpy( szText,"About " );
2106                 strcat( szText,gszCaption );
2107                 SetWindowText( hwnd,gszCaption );
2108                 SetDlgItemText( hwnd,DLG_ABOUT_APP,szText );
2109                 /*      Application icon: */
2110                 SendDlgItemMessage( hwnd, DLG_ABOUT_ICON,
2111                                                         STM_SETICON, (WPARAM)(HICON)LoadIcon( ghInst,"GENSURF" ),
2112                                                         (LPARAM) NULL );
2113
2114                 hwndURL = GetDlgItem( hwnd,DLG_ABOUT_URL );
2115                 hdc = GetDC( hwndURL );
2116                 GetTextExtentPoint( hdc,GenSurfURL,strlen( GenSurfURL ),&size );
2117                 ReleaseDC( hwndURL,hdc );
2118                 GetWindowRect( hwndURL,&rc );
2119                 SetWindowPos( hwndURL,(HWND)NULL,0,0,size.cx,size.cy + 2,
2120                                           SWP_NOMOVE | SWP_NOZORDER );
2121
2122                 hwndURL = GetDlgItem( hwnd,DLG_ABOUT_BOARD );
2123                 hdc = GetDC( hwndURL );
2124                 GetTextExtentPoint( hdc,GenSurfBoard,strlen( GenSurfBoard ),&size );
2125                 ReleaseDC( hwndURL,hdc );
2126                 GetWindowRect( hwndURL,&rc );
2127                 SetWindowPos( hwndURL,(HWND)NULL,0,0,size.cx,size.cy + 2,
2128                                           SWP_NOMOVE | SWP_NOZORDER );
2129
2130                 return TRUE;
2131
2132         case WM_COMMAND:
2133                 switch ( LOWORD( wparam ) )
2134                 {
2135                 case DLG_ABOUT_URL:
2136                         HTTP( GenSurfURL );
2137                         break;
2138                 case DLG_ABOUT_BOARD:
2139                         HTTP( GenSurfBoard );
2140                         break;
2141                 case IDOK:
2142                         EndDialog( hwnd,1 );
2143                         return TRUE;
2144                 }
2145                 break;
2146
2147         case WM_DRAWITEM:
2148                 if ( wparam == DLG_ABOUT_URL ) {
2149                         dis = (LPDRAWITEMSTRUCT)lparam;
2150                         SetTextColor( dis->hDC,RGB( 0,0,255 ) );
2151                         TextOut( dis->hDC,0,0,GenSurfURL,strlen( GenSurfURL ) );
2152                         GetWindowRect( dis->hwndItem,&rc );
2153                         GetTextExtentPoint( dis->hDC,GenSurfURL,strlen( GenSurfURL ),&size );
2154                         hpen = CreatePen( PS_SOLID,0,RGB( 0,0,255 ) );
2155                         SelectObject( dis->hDC,hpen );
2156                         MoveToEx( dis->hDC,0,size.cy,NULL );
2157                         LineTo( dis->hDC,size.cx,size.cy );
2158                         SelectObject( dis->hDC,GetStockObject( BLACK_PEN ) );
2159                         DeleteObject( hpen );
2160                 }
2161                 else if ( wparam == DLG_ABOUT_BOARD ) {
2162                         dis = (LPDRAWITEMSTRUCT)lparam;
2163                         SetTextColor( dis->hDC,RGB( 0,0,255 ) );
2164                         TextOut( dis->hDC,0,0,GenSurfBoard,strlen( GenSurfBoard ) );
2165                         GetWindowRect( dis->hwndItem,&rc );
2166                         GetTextExtentPoint( dis->hDC,GenSurfBoard,strlen( GenSurfBoard ),&size );
2167                         hpen = CreatePen( PS_SOLID,0,RGB( 0,0,255 ) );
2168                         SelectObject( dis->hDC,hpen );
2169                         MoveToEx( dis->hDC,0,size.cy,NULL );
2170                         LineTo( dis->hDC,size.cx,size.cy );
2171                         SelectObject( dis->hDC,GetStockObject( BLACK_PEN ) );
2172                         DeleteObject( hpen );
2173                 }
2174                 break;
2175
2176         case WM_CLOSE:
2177                 EndDialog( hwnd,1 );
2178                 return TRUE;
2179
2180         default:
2181                 return FALSE;
2182         }
2183         return FALSE;
2184
2185 } /* AboutDlgProc */
2186
2187 void About(){
2188         if ( DialogBox( ghInst,"About", ghwnd_main, (DLGPROC)AboutDlgProc ) < 0 ) {
2189                 char Text[256];
2190                 sprintf( Text,"In About(), GetLastError()=0x%08x",GetLastError() );
2191                 MessageBox( ghwnd_main,Text,"GenSurf",eMB_ICONWARNING );
2192         }
2193 }
2194
2195 #endif