]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/bobtoolz/dialogs/dialogs-gtk.cpp
reformat code! now the code is only ugly on the *inside*
[xonotic/netradiant.git] / contrib / bobtoolz / dialogs / dialogs-gtk.cpp
1 /*
2    BobToolz plugin for GtkRadiant
3    Copyright (C) 2001 Gordon Biggans
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 "dialogs-gtk.h"
21 #include "../funchandlers.h"
22
23 #include "str.h"
24 #include <list>
25 #include <gtk/gtk.h>
26 #include "gtkutil/pointer.h"
27
28 #include "../lists.h"
29 #include "../misc.h"
30
31
32 /*--------------------------------
33         Callback Functions
34    ---------------------------------*/
35
36 typedef struct {
37     ui::Widget cbTexChange{ui::null};
38     ui::Widget editTexOld{ui::null}, editTexNew{ui::null};
39
40     ui::Widget cbScaleHor{ui::null}, cbScaleVert{ui::null};
41     ui::Widget editScaleHor{ui::null}, editScaleVert{ui::null};
42
43     ui::Widget cbShiftHor{ui::null}, cbShiftVert{ui::null};
44     ui::Widget editShiftHor{ui::null}, editShiftVert{ui::null};
45
46     ui::Widget cbRotation{ui::null};
47     ui::Widget editRotation{ui::null};
48 } dlg_texReset_t;
49
50 dlg_texReset_t dlgTexReset;
51
52 void Update_TextureReseter();
53
54 static void dialog_button_callback_texreset_update(ui::Widget widget, gpointer data)
55 {
56     Update_TextureReseter();
57 }
58
59 void Update_TextureReseter()
60 {
61     gboolean check;
62
63     check = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbTexChange));
64     gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editTexNew), check);
65     gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editTexOld), check);
66
67     check = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbScaleHor));
68     gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editScaleHor), check);
69
70     check = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbScaleVert));
71     gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editScaleVert), check);
72
73     check = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbShiftHor));
74     gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editShiftHor), check);
75
76     check = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbShiftVert));
77     gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editShiftVert), check);
78
79     check = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbRotation));
80     gtk_editable_set_editable(GTK_EDITABLE(dlgTexReset.editRotation), check);
81 }
82
83 static void dialog_button_callback(ui::Widget widget, gpointer data)
84 {
85     int *loop;
86     EMessageBoxReturn *ret;
87
88     auto parent = widget.window();
89     loop = (int *) g_object_get_data(G_OBJECT(parent), "loop");
90     ret = (EMessageBoxReturn *) g_object_get_data(G_OBJECT(parent), "ret");
91
92     *loop = 0;
93     *ret = (EMessageBoxReturn) gpointer_to_int(data);
94 }
95
96 static gint dialog_delete_callback(ui::Widget widget, GdkEvent *event, gpointer data)
97 {
98     widget.hide();
99     int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop");
100     *loop = 0;
101     return TRUE;
102 }
103
104 static void dialog_button_callback_settex(ui::Widget widget, gpointer data)
105 {
106     TwinWidget *tw = (TwinWidget *) data;
107
108     auto entry = ui::Entry::from(tw->one);
109     auto combo = tw->two;
110
111     const gchar *tex = gtk_entry_get_text(GTK_ENTRY (gtk_bin_get_child(combo)));
112     gtk_entry_set_text(entry, tex);
113 }
114
115 /*--------------------------------
116     Data validation Routines
117    ---------------------------------*/
118
119 bool ValidateTextFloat(const char *pData, const char *error_title, float *value)
120 {
121     if (pData) {
122         float testNum = (float) atof(pData);
123
124         if ((testNum == 0.0f) && strcmp(pData, "0")) {
125             DoMessageBox("Please Enter A Floating Point Number", error_title, eMB_OK);
126             return FALSE;
127         } else {
128             *value = testNum;
129             return TRUE;
130         }
131     }
132
133     DoMessageBox("Please Enter A Floating Point Number", error_title, eMB_OK);
134     return FALSE;
135 }
136
137 bool ValidateTextFloatRange(const char *pData, float min, float max, const char *error_title, float *value)
138 {
139     char error_buffer[256];
140     sprintf(error_buffer, "Please Enter A Floating Point Number Between %.3f and %.3f", min, max);
141
142     if (pData) {
143         float testNum = (float) atof(pData);
144
145         if ((testNum < min) || (testNum > max)) {
146             DoMessageBox(error_buffer, error_title, eMB_OK);
147             return FALSE;
148         } else {
149             *value = testNum;
150             return TRUE;
151         }
152     }
153
154     DoMessageBox(error_buffer, error_title, eMB_OK);
155     return FALSE;
156 }
157
158 bool ValidateTextIntRange(const char *pData, int min, int max, const char *error_title, int *value)
159 {
160     char error_buffer[256];
161     sprintf(error_buffer, "Please Enter An Integer Between %i and %i", min, max);
162
163     if (pData) {
164         int testNum = atoi(pData);
165
166         if ((testNum < min) || (testNum > max)) {
167             DoMessageBox(error_buffer, error_title, eMB_OK);
168             return FALSE;
169         } else {
170             *value = testNum;
171             return TRUE;
172         }
173     }
174
175     DoMessageBox(error_buffer, error_title, eMB_OK);
176     return FALSE;
177 }
178
179 bool ValidateTextInt(const char *pData, const char *error_title, int *value)
180 {
181     if (pData) {
182         int testNum = atoi(pData);
183
184         if ((testNum == 0) && strcmp(pData, "0")) {
185             DoMessageBox("Please Enter An Integer", error_title, eMB_OK);
186             return FALSE;
187         } else {
188             *value = testNum;
189             return TRUE;
190         }
191     }
192
193     DoMessageBox("Please Enter An Integer", error_title, eMB_OK);
194     return FALSE;
195 }
196
197 /*--------------------------------
198         Modal Dialog Boxes
199    ---------------------------------*/
200
201 /*
202
203    Major clean up of variable names etc required, excluding Mars's ones,
204    which are nicely done :)
205
206  */
207
208 EMessageBoxReturn DoMessageBox(const char *lpText, const char *lpCaption, EMessageBoxType type)
209 {
210     ui::Widget w{ui::null};
211     EMessageBoxReturn ret;
212     int loop = 1;
213
214     auto window = ui::Window(ui::window_type::TOP);
215     window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
216     window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
217     gtk_window_set_title(window, lpCaption);
218     gtk_container_set_border_width(GTK_CONTAINER(window), 10);
219     g_object_set_data(G_OBJECT(window), "loop", &loop);
220     g_object_set_data(G_OBJECT(window), "ret", &ret);
221     gtk_widget_realize(window);
222
223     auto vbox = ui::VBox(FALSE, 10);
224     window.add(vbox);
225     vbox.show();
226
227     w = ui::Label(lpText);
228     vbox.pack_start(w, FALSE, FALSE, 2);
229     gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
230     w.show();
231
232     w = ui::Widget::from(gtk_hseparator_new());
233     vbox.pack_start(w, FALSE, FALSE, 2);
234     w.show();
235
236     auto hbox = ui::HBox(FALSE, 10);
237     vbox.pack_start(hbox, FALSE, FALSE, 2);
238     hbox.show();
239
240     if (type == eMB_OK) {
241         w = ui::Button("Ok");
242         hbox.pack_start(w, TRUE, TRUE, 0);
243         w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
244         gtk_widget_set_can_default(w, true);
245         gtk_widget_grab_default(w);
246         w.show();
247         ret = eIDOK;
248     } else if (type == eMB_OKCANCEL) {
249         w = ui::Button("Ok");
250         hbox.pack_start(w, TRUE, TRUE, 0);
251         w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
252         gtk_widget_set_can_default(w, true);
253         gtk_widget_grab_default(w);
254         w.show();
255
256         w = ui::Button("Cancel");
257         hbox.pack_start(w, TRUE, TRUE, 0);
258         w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
259         w.show();
260         ret = eIDCANCEL;
261     } else if (type == eMB_YESNOCANCEL) {
262         w = ui::Button("Yes");
263         hbox.pack_start(w, TRUE, TRUE, 0);
264         w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDYES));
265         gtk_widget_set_can_default(w, true);
266         gtk_widget_grab_default(w);
267         w.show();
268
269         w = ui::Button("No");
270         hbox.pack_start(w, TRUE, TRUE, 0);
271         w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDNO));
272         w.show();
273
274         w = ui::Button("Cancel");
275         hbox.pack_start(w, TRUE, TRUE, 0);
276         w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
277         w.show();
278         ret = eIDCANCEL;
279     } else /* if (mode == MB_YESNO) */
280     {
281         w = ui::Button("Yes");
282         hbox.pack_start(w, TRUE, TRUE, 0);
283         w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDYES));
284         gtk_widget_set_can_default(w, true);
285         gtk_widget_grab_default(w);
286         w.show();
287
288         w = ui::Button("No");
289         hbox.pack_start(w, TRUE, TRUE, 0);
290         w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDNO));
291         w.show();
292         ret = eIDNO;
293     }
294
295     gtk_window_set_position(window, GTK_WIN_POS_CENTER);
296     window.show();
297     gtk_grab_add(window);
298
299     while (loop) {
300         gtk_main_iteration();
301     }
302
303     gtk_grab_remove(window);
304     window.destroy();
305
306     return ret;
307 }
308
309 EMessageBoxReturn DoIntersectBox(IntersectRS *rs)
310 {
311     EMessageBoxReturn ret;
312     int loop = 1;
313
314     auto window = ui::Window(ui::window_type::TOP);
315
316     window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
317     window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
318
319     gtk_window_set_title(window, "Intersect");
320     gtk_container_set_border_width(GTK_CONTAINER(window), 10);
321
322     g_object_set_data(G_OBJECT(window), "loop", &loop);
323     g_object_set_data(G_OBJECT(window), "ret", &ret);
324
325     gtk_widget_realize(window);
326
327
328     auto vbox = ui::VBox(FALSE, 10);
329     window.add(vbox);
330     vbox.show();
331
332     // ---- vbox ----
333
334
335     auto radio1 = ui::Widget::from(gtk_radio_button_new_with_label(NULL, "Use Whole Map"));
336     vbox.pack_start(radio1, FALSE, FALSE, 2);
337     radio1.show();
338
339     auto radio2 = ui::Widget::from(gtk_radio_button_new_with_label(gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio1)),
340                                                                    "Use Selected Brushes"));
341     vbox.pack_start(radio2, FALSE, FALSE, 2);
342     radio2.show();
343
344     auto hsep = ui::Widget::from(gtk_hseparator_new());
345     vbox.pack_start(hsep, FALSE, FALSE, 2);
346     hsep.show();
347
348     auto check1 = ui::CheckButton("Include Detail Brushes");
349     vbox.pack_start(check1, FALSE, FALSE, 0);
350     check1.show();
351
352     auto check2 = ui::CheckButton("Select Duplicate Brushes Only");
353     vbox.pack_start(check2, FALSE, FALSE, 0);
354     check2.show();
355
356     auto hbox = ui::HBox(FALSE, 10);
357     vbox.pack_start(hbox, FALSE, FALSE, 2);
358     hbox.show();
359
360     // ---- hbox ---- ok/cancel buttons
361
362     auto w = ui::Button("Ok");
363     hbox.pack_start(w, TRUE, TRUE, 0);
364     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
365
366     gtk_widget_set_can_default(w, true);
367     gtk_widget_grab_default(w);
368     w.show();
369
370     w = ui::Button("Cancel");
371     hbox.pack_start(w, TRUE, TRUE, 0);
372     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
373     w.show();
374     ret = eIDCANCEL;
375
376     // ---- /hbox ----
377
378     // ---- /vbox ----
379
380     gtk_window_set_position(window, GTK_WIN_POS_CENTER);
381     window.show();
382     gtk_grab_add(window);
383
384     while (loop) {
385         gtk_main_iteration();
386     }
387
388     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio1))) {
389         rs->nBrushOptions = BRUSH_OPT_WHOLE_MAP;
390     } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio2))) {
391         rs->nBrushOptions = BRUSH_OPT_SELECTED;
392     }
393
394     rs->bUseDetail = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check1)) ? true : false;
395     rs->bDuplicateOnly = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check2)) ? true : false;
396
397     gtk_grab_remove(window);
398     window.destroy();
399
400     return ret;
401 }
402
403 EMessageBoxReturn DoPolygonBox(PolygonRS *rs)
404 {
405     EMessageBoxReturn ret;
406     int loop = 1;
407
408     auto window = ui::Window(ui::window_type::TOP);
409
410     window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
411     window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
412
413     gtk_window_set_title(window, "Polygon Builder");
414     gtk_container_set_border_width(GTK_CONTAINER(window), 10);
415
416     g_object_set_data(G_OBJECT(window), "loop", &loop);
417     g_object_set_data(G_OBJECT(window), "ret", &ret);
418
419     gtk_widget_realize(window);
420
421
422     auto vbox = ui::VBox(FALSE, 10);
423     window.add(vbox);
424     vbox.show();
425
426     // ---- vbox ----
427
428     auto hbox = ui::HBox(FALSE, 10);
429     vbox.pack_start(hbox, FALSE, FALSE, 2);
430     hbox.show();
431
432     // ---- hbox ----
433
434
435     auto vbox2 = ui::VBox(FALSE, 10);
436     hbox.pack_start(vbox2, FALSE, FALSE, 2);
437     vbox2.show();
438
439     // ---- vbox2 ----
440
441     auto hbox2 = ui::HBox(FALSE, 10);
442     vbox2.pack_start(hbox2, FALSE, FALSE, 2);
443     hbox2.show();
444
445     // ---- hbox2 ----
446
447     auto text1 = ui::Entry(256);
448     gtk_entry_set_text(text1, "3");
449     hbox2.pack_start(text1, FALSE, FALSE, 2);
450     text1.show();
451
452     auto l = ui::Label("Number Of Sides");
453     hbox2.pack_start(l, FALSE, FALSE, 2);
454     gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_LEFT);
455     l.show();
456
457     // ---- /hbox2 ----
458
459     hbox2 = ui::HBox(FALSE, 10);
460     vbox2.pack_start(hbox2, FALSE, FALSE, 2);
461     hbox2.show();
462
463     // ---- hbox2 ----
464
465     auto text2 = ui::Entry(256);
466     gtk_entry_set_text(text2, "8");
467     hbox2.pack_start(text2, FALSE, FALSE, 2);
468     text2.show();
469
470     l = ui::Label("Border Width");
471     hbox2.pack_start(l, FALSE, FALSE, 2);
472     gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_LEFT);
473     l.show();
474
475     // ---- /hbox2 ----
476
477     // ---- /vbox2 ----
478
479
480
481     vbox2 = ui::VBox(FALSE, 10);
482     hbox.pack_start(vbox2, FALSE, FALSE, 2);
483     vbox2.show();
484
485     // ---- vbox2 ----
486
487     auto check1 = ui::CheckButton("Use Border");
488     vbox2.pack_start(check1, FALSE, FALSE, 0);
489     check1.show();
490
491
492     auto check2 = ui::CheckButton("Inverse Polygon");
493     vbox2.pack_start(check2, FALSE, FALSE, 0);
494     check2.show();
495
496
497     auto check3 = ui::CheckButton("Align Top Edge");
498     vbox2.pack_start(check3, FALSE, FALSE, 0);
499     check3.show();
500
501     // ---- /vbox2 ----
502
503     // ---- /hbox ----
504
505     hbox = ui::HBox(FALSE, 10);
506     vbox.pack_start(hbox, FALSE, FALSE, 2);
507     hbox.show();
508
509     // ---- hbox ----
510
511     auto w = ui::Button("Ok");
512     hbox.pack_start(w, TRUE, TRUE, 0);
513     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
514
515     gtk_widget_set_can_default(w, true);
516     gtk_widget_grab_default(w);
517     w.show();
518
519     w = ui::Button("Cancel");
520     hbox.pack_start(w, TRUE, TRUE, 0);
521     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
522     w.show();
523     ret = eIDCANCEL;
524
525     // ---- /hbox ----
526
527     // ---- /vbox ----
528
529     gtk_window_set_position(window, GTK_WIN_POS_CENTER);
530     window.show();
531     gtk_grab_add(window);
532
533     bool dialogError = TRUE;
534     while (dialogError) {
535         loop = 1;
536         while (loop) {
537             gtk_main_iteration();
538         }
539
540         dialogError = FALSE;
541
542         if (ret == eIDOK) {
543             rs->bUseBorder = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check1)) ? true : false;
544             rs->bInverse = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check2)) ? true : false;
545             rs->bAlignTop = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check3)) ? true : false;
546
547             if (!ValidateTextIntRange(gtk_entry_get_text(text1), 3, 32, "Number Of Sides", &rs->nSides)) {
548                 dialogError = TRUE;
549             }
550
551             if (rs->bUseBorder) {
552                 if (!ValidateTextIntRange(gtk_entry_get_text(text2), 8, 256, "Border Width", &rs->nBorderWidth)) {
553                     dialogError = TRUE;
554                 }
555             }
556         }
557     }
558
559     gtk_grab_remove(window);
560     window.destroy();
561
562     return ret;
563 }
564
565 // mars
566 // for stair builder stuck as close as i could to the MFC version
567 // obviously feel free to change it at will :)
568 EMessageBoxReturn DoBuildStairsBox(BuildStairsRS *rs)
569 {
570     GSList *radioDirection, *radioStyle;
571     EMessageBoxReturn ret;
572     int loop = 1;
573
574     const char *text = "Please set a value in the boxes below and press 'OK' to build the stairs";
575
576     auto window = ui::Window(ui::window_type::TOP);
577
578     window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
579     window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
580
581     gtk_window_set_title(window, "Stair Builder");
582
583     gtk_container_set_border_width(GTK_CONTAINER(window), 10);
584
585     g_object_set_data(G_OBJECT(window), "loop", &loop);
586     g_object_set_data(G_OBJECT(window), "ret", &ret);
587
588     gtk_widget_realize(window);
589
590     // new vbox
591     auto vbox = ui::VBox(FALSE, 10);
592     window.add(vbox);
593     vbox.show();
594
595     auto hbox = ui::HBox(FALSE, 10);
596     vbox.add(hbox);
597     hbox.show();
598
599     // dunno if you want this text or not ...
600     ui::Widget w = ui::Label(text);
601     hbox.pack_start(w, FALSE, FALSE, 0); // not entirely sure on all the parameters / what they do ...
602     w.show();
603
604     w = ui::Widget::from(gtk_hseparator_new());
605     vbox.pack_start(w, FALSE, FALSE, 0);
606     w.show();
607
608     // ------------------------- // indenting == good way of keeping track of lines :)
609
610     // new hbox
611     hbox = ui::HBox(FALSE, 10);
612     vbox.pack_start(hbox, FALSE, FALSE, 0);
613     hbox.show();
614
615     auto textStairHeight = ui::Entry(256);
616     hbox.pack_start(textStairHeight, FALSE, FALSE, 1);
617     textStairHeight.show();
618
619     w = ui::Label("Stair Height");
620     hbox.pack_start(w, FALSE, FALSE, 1);
621     w.show();
622
623     // ------------------------- //
624
625     hbox = ui::HBox(FALSE, 10);
626     vbox.pack_start(hbox, FALSE, FALSE, 0);
627     hbox.show();
628
629     w = ui::Label("Direction:");
630     hbox.pack_start(w, FALSE, FALSE, 5);
631     w.show();
632
633     // -------------------------- //
634
635     hbox = ui::HBox(FALSE, 10);
636     vbox.pack_start(hbox, FALSE, FALSE, 0);
637     hbox.show();
638
639     // radio buttons confuse me ...
640     // but this _looks_ right
641
642     // djbob: actually it looks very nice :), slightly better than the way i did it
643     // edit: actually it doesn't work :P, you must pass the last radio item each time, ugh
644
645     auto radioNorth = ui::Widget::from(gtk_radio_button_new_with_label(NULL, "North"));
646     hbox.pack_start(radioNorth, FALSE, FALSE, 3);
647     radioNorth.show();
648
649     radioDirection = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioNorth));
650
651     auto radioSouth = ui::Widget::from(gtk_radio_button_new_with_label(radioDirection, "South"));
652     hbox.pack_start(radioSouth, FALSE, FALSE, 2);
653     radioSouth.show();
654
655     radioDirection = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioSouth));
656
657     auto radioEast = ui::Widget::from(gtk_radio_button_new_with_label(radioDirection, "East"));
658     hbox.pack_start(radioEast, FALSE, FALSE, 1);
659     radioEast.show();
660
661     radioDirection = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioEast));
662
663     auto radioWest = ui::Widget::from(gtk_radio_button_new_with_label(radioDirection, "West"));
664     hbox.pack_start(radioWest, FALSE, FALSE, 0);
665     radioWest.show();
666
667     // --------------------------- //
668
669     hbox = ui::HBox(FALSE, 10);
670     vbox.pack_start(hbox, FALSE, FALSE, 0);
671     hbox.show();
672
673     w = ui::Label("Style:");
674     hbox.pack_start(w, FALSE, FALSE, 5);
675     w.show();
676
677     // --------------------------- //
678
679     hbox = ui::HBox(FALSE, 10);
680     vbox.pack_start(hbox, FALSE, FALSE, 0);
681     hbox.show();
682
683     auto radioOldStyle = ui::Widget::from(gtk_radio_button_new_with_label(NULL, "Original"));
684     hbox.pack_start(radioOldStyle, FALSE, FALSE, 0);
685     radioOldStyle.show();
686
687     radioStyle = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioOldStyle));
688
689     auto radioBobStyle = ui::Widget::from(gtk_radio_button_new_with_label(radioStyle, "Bob's Style"));
690     hbox.pack_start(radioBobStyle, FALSE, FALSE, 0);
691     radioBobStyle.show();
692
693     radioStyle = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioBobStyle));
694
695     auto radioCornerStyle = ui::Widget::from(gtk_radio_button_new_with_label(radioStyle, "Corner Style"));
696     hbox.pack_start(radioCornerStyle, FALSE, FALSE, 0);
697     radioCornerStyle.show();
698
699     // err, the q3r has an if or something so you need bob style checked before this
700     // is "ungreyed out" but you'll need to do that, as i suck :)
701
702     // djbob: er.... yeah um, im not at all sure how i'm gonna sort this
703     // djbob: think we need some button callback functions or smuffin
704     // FIXME: actually get around to doing what i suggested!!!!
705
706     auto checkUseDetail = ui::CheckButton("Use Detail Brushes");
707     hbox.pack_start(checkUseDetail, FALSE, FALSE, 0);
708     checkUseDetail.show();
709
710     // --------------------------- //
711
712     hbox = ui::HBox(FALSE, 10);
713     vbox.pack_start(hbox, FALSE, FALSE, 0);
714     hbox.show();
715
716     auto textMainTex = ui::Entry(512);
717     gtk_entry_set_text(GTK_ENTRY(textMainTex), rs->mainTexture);
718     hbox.pack_start(textMainTex, FALSE, FALSE, 0);
719     textMainTex.show();
720
721     w = ui::Label("Main Texture");
722     hbox.pack_start(w, FALSE, FALSE, 1);
723     w.show();
724
725     // -------------------------- //
726
727     hbox = ui::HBox(FALSE, 10);
728     vbox.pack_start(hbox, FALSE, FALSE, 0);
729     hbox.show();
730
731     auto textRiserTex = ui::Entry(512);
732     hbox.pack_start(textRiserTex, FALSE, FALSE, 0);
733     textRiserTex.show();
734
735     w = ui::Label("Riser Texture");
736     hbox.pack_start(w, FALSE, FALSE, 1);
737     w.show();
738
739     // -------------------------- //
740     w = ui::Widget::from(gtk_hseparator_new());
741     vbox.pack_start(w, FALSE, FALSE, 0);
742     w.show();
743
744     hbox = ui::HBox(FALSE, 10);
745     vbox.pack_start(hbox, FALSE, FALSE, 0);
746     hbox.show();
747
748     w = ui::Button("OK");
749     hbox.pack_start(w, TRUE, TRUE, 0);
750     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
751     gtk_widget_set_can_default(w, true);
752     gtk_widget_grab_default(w);
753     w.show();
754
755     w = ui::Button("Cancel");
756     hbox.pack_start(w, TRUE, TRUE, 0);
757     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
758     w.show();
759
760     ret = eIDCANCEL;
761
762 // +djbob: need our "little" modal loop mars :P
763     gtk_window_set_position(window, GTK_WIN_POS_CENTER);
764     window.show();
765     gtk_grab_add(window);
766
767     bool dialogError = TRUE;
768     while (dialogError) {
769         loop = 1;
770         while (loop) {
771             gtk_main_iteration();
772         }
773
774         dialogError = FALSE;
775
776         if (ret == eIDOK) {
777             rs->bUseDetail = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkUseDetail)) ? true : false;
778
779             strcpy(rs->riserTexture, gtk_entry_get_text(textRiserTex));
780             strcpy(rs->mainTexture, gtk_entry_get_text(textMainTex));
781
782             if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioNorth))) {
783                 rs->direction = MOVE_NORTH;
784             } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioSouth))) {
785                 rs->direction = MOVE_SOUTH;
786             } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioEast))) {
787                 rs->direction = MOVE_EAST;
788             } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioWest))) {
789                 rs->direction = MOVE_WEST;
790             }
791
792             if (!ValidateTextInt(gtk_entry_get_text(textStairHeight), "Stair Height", &rs->stairHeight)) {
793                 dialogError = TRUE;
794             }
795
796             if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioOldStyle))) {
797                 rs->style = STYLE_ORIGINAL;
798             } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioBobStyle))) {
799                 rs->style = STYLE_BOB;
800             } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioCornerStyle))) {
801                 rs->style = STYLE_CORNER;
802             }
803         }
804     }
805
806     gtk_grab_remove(window);
807     window.destroy();
808
809     return ret;
810 // -djbob
811
812     // there we go, all done ... on my end at least, not bad for a night's work
813 }
814
815 EMessageBoxReturn DoDoorsBox(DoorRS *rs)
816 {
817     GSList *radioOrientation;
818     TwinWidget tw1, tw2;
819     EMessageBoxReturn ret;
820     int loop = 1;
821
822     auto window = ui::Window(ui::window_type::TOP);
823
824     window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
825     window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
826
827     gtk_window_set_title(window, "Door Builder");
828
829     gtk_container_set_border_width(GTK_CONTAINER(window), 10);
830
831     g_object_set_data(G_OBJECT(window), "loop", &loop);
832     g_object_set_data(G_OBJECT(window), "ret", &ret);
833
834     gtk_widget_realize(window);
835
836     char buffer[256];
837     auto listMainTextures = ui::ListStore::from(gtk_list_store_new(1, G_TYPE_STRING));
838     auto listTrimTextures = ui::ListStore::from(gtk_list_store_new(1, G_TYPE_STRING));
839     LoadGList(GetFilename(buffer, "plugins/bt/door-tex.txt"), listMainTextures);
840     LoadGList(GetFilename(buffer, "plugins/bt/door-tex-trim.txt"), listTrimTextures);
841
842     auto vbox = ui::VBox(FALSE, 10);
843     window.add(vbox);
844     vbox.show();
845
846     // -------------------------- //
847
848     auto hbox = ui::HBox(FALSE, 10);
849     vbox.pack_start(hbox, FALSE, FALSE, 0);
850     hbox.show();
851
852     auto textFrontBackTex = ui::Entry(512);
853     gtk_entry_set_text(GTK_ENTRY(textFrontBackTex), rs->mainTexture);
854     hbox.pack_start(textFrontBackTex, FALSE, FALSE, 0);
855     textFrontBackTex.show();
856
857     ui::Widget w = ui::Label("Door Front/Back Texture");
858     hbox.pack_start(w, FALSE, FALSE, 0);
859     w.show();
860
861     // ------------------------ //
862
863     hbox = ui::HBox(FALSE, 10);
864     vbox.pack_start(hbox, FALSE, FALSE, 0);
865     hbox.show();
866
867     auto textTrimTex = ui::Entry(512);
868     hbox.pack_start(textTrimTex, FALSE, FALSE, 0);
869     textTrimTex.show();
870
871     w = ui::Label("Door Trim Texture");
872     hbox.pack_start(w, FALSE, FALSE, 0);
873     w.show();
874
875     // ----------------------- //
876
877     hbox = ui::HBox(FALSE, 10);
878     vbox.pack_start(hbox, FALSE, FALSE, 0);
879     hbox.show();
880
881     // sp: horizontally ????
882     // djbob: yes mars, u can spell :]
883     auto checkScaleMainH = ui::CheckButton("Scale Main Texture Horizontally");
884     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkScaleMainH), TRUE);
885     hbox.pack_start(checkScaleMainH, FALSE, FALSE, 0);
886     checkScaleMainH.show();
887
888     auto checkScaleTrimH = ui::CheckButton("Scale Trim Texture Horizontally");
889     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkScaleTrimH), TRUE);
890     hbox.pack_start(checkScaleTrimH, FALSE, FALSE, 0);
891     checkScaleTrimH.show();
892
893     // ---------------------- //
894
895     hbox = ui::HBox(FALSE, 10);
896     vbox.pack_start(hbox, FALSE, FALSE, 0);
897     hbox.show();
898
899     auto checkScaleMainV = ui::CheckButton("Scale Main Texture Vertically");
900     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkScaleMainV), TRUE);
901     hbox.pack_start(checkScaleMainV, FALSE, FALSE, 0);
902     checkScaleMainV.show();
903
904     auto checkScaleTrimV = ui::CheckButton("Scale Trim Texture Vertically");
905     hbox.pack_start(checkScaleTrimV, FALSE, FALSE, 0);
906     checkScaleTrimV.show();
907
908     // --------------------- //
909
910     hbox = ui::HBox(FALSE, 10);
911     vbox.pack_start(hbox, FALSE, FALSE, 0);
912     hbox.show();
913
914     // djbob: lists added
915
916     auto comboMain = ui::ComboBox::from(gtk_combo_box_new_with_model_and_entry(listMainTextures));
917     gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(comboMain), 0);
918     hbox.pack_start(comboMain, FALSE, FALSE, 0);
919     comboMain.show();
920
921     tw1.one = textFrontBackTex;
922     tw1.two = comboMain;
923
924     auto buttonSetMain = ui::Button("Set As Main Texture");
925     buttonSetMain.connect("clicked", G_CALLBACK(dialog_button_callback_settex), &tw1);
926     hbox.pack_start(buttonSetMain, FALSE, FALSE, 0);
927     buttonSetMain.show();
928
929     // ------------------- //
930
931     hbox = ui::HBox(FALSE, 10);
932     vbox.pack_start(hbox, FALSE, FALSE, 0);
933     hbox.show();
934
935     auto comboTrim = ui::ComboBox::from(gtk_combo_box_new_with_model_and_entry(listTrimTextures));
936     gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(comboMain), 0);
937     hbox.pack_start(comboTrim, FALSE, FALSE, 0);
938     comboTrim.show();
939
940     tw2.one = textTrimTex;
941     tw2.two = comboTrim;
942
943     auto buttonSetTrim = ui::Button("Set As Trim Texture");
944     buttonSetTrim.connect("clicked", G_CALLBACK(dialog_button_callback_settex), &tw2);
945     hbox.pack_start(buttonSetTrim, FALSE, FALSE, 0);
946     buttonSetTrim.show();
947
948     // ------------------ //
949
950     hbox = ui::HBox(FALSE, 10);
951     vbox.pack_start(hbox, FALSE, FALSE, 0);
952     hbox.show();
953
954     w = ui::Label("Orientation");
955     hbox.pack_start(w, FALSE, FALSE, 0);
956     w.show();
957
958     // argh more radio buttons!
959     auto radioNS = ui::Widget::from(gtk_radio_button_new_with_label(NULL, "North - South"));
960     hbox.pack_start(radioNS, FALSE, FALSE, 0);
961     radioNS.show();
962
963     radioOrientation = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radioNS));
964
965     auto radioEW = ui::Widget::from(gtk_radio_button_new_with_label(radioOrientation, "East - West"));
966     hbox.pack_start(radioEW, FALSE, FALSE, 0);
967     radioEW.show();
968
969     // ----------------- //
970
971     w = ui::Widget::from(gtk_hseparator_new());
972     vbox.pack_start(w, FALSE, FALSE, 0);
973     w.show();
974
975     // ----------------- //
976
977     hbox = ui::HBox(FALSE, 10);
978     vbox.pack_start(hbox, FALSE, FALSE, 0);
979     hbox.show();
980
981     w = ui::Button("OK");
982     hbox.pack_start(w, TRUE, TRUE, 0);
983     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
984     gtk_widget_set_can_default(w, true);
985     gtk_widget_grab_default(w);
986     w.show();
987
988     w = ui::Button("Cancel");
989     hbox.pack_start(w, TRUE, TRUE, 0);
990     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
991     w.show();
992     ret = eIDCANCEL;
993
994     // ----------------- //
995
996 //+djbob
997     gtk_window_set_position(window, GTK_WIN_POS_CENTER);
998     window.show();
999     gtk_grab_add(window);
1000
1001     while (loop) {
1002         gtk_main_iteration();
1003     }
1004
1005     strcpy(rs->mainTexture, gtk_entry_get_text(GTK_ENTRY(textFrontBackTex)));
1006     strcpy(rs->trimTexture, gtk_entry_get_text(GTK_ENTRY(textTrimTex)));
1007
1008     rs->bScaleMainH = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkScaleMainH)) ? true : false;
1009     rs->bScaleMainV = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkScaleMainV)) ? true : false;
1010     rs->bScaleTrimH = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkScaleTrimH)) ? true : false;
1011     rs->bScaleTrimV = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkScaleTrimV)) ? true : false;
1012
1013     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioNS))) {
1014         rs->nOrientation = DIRECTION_NS;
1015     } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioEW))) {
1016         rs->nOrientation = DIRECTION_EW;
1017     }
1018
1019     gtk_grab_remove(window);
1020     window.destroy();
1021
1022     return ret;
1023 //-djbob
1024 }
1025
1026 EMessageBoxReturn DoPathPlotterBox(PathPlotterRS *rs)
1027 {
1028     ui::Widget w{ui::null};
1029
1030     EMessageBoxReturn ret;
1031     int loop = 1;
1032
1033     auto window = ui::Window(ui::window_type::TOP);
1034
1035     window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
1036     window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
1037
1038     gtk_window_set_title(window, "Texture Reset");
1039     gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1040
1041     g_object_set_data(G_OBJECT(window), "loop", &loop);
1042     g_object_set_data(G_OBJECT(window), "ret", &ret);
1043
1044     gtk_widget_realize(window);
1045
1046
1047     auto vbox = ui::VBox(FALSE, 10);
1048     window.add(vbox);
1049     vbox.show();
1050
1051     // ---- vbox ----
1052
1053     auto hbox = ui::HBox(FALSE, 10);
1054     vbox.pack_start(hbox, FALSE, FALSE, 2);
1055     hbox.show();
1056
1057     // ---- hbox ----
1058
1059     auto text1 = ui::Entry(256);
1060     gtk_entry_set_text(text1, "25");
1061     hbox.pack_start(text1, FALSE, FALSE, 2);
1062     text1.show();
1063
1064     w = ui::Label("Number Of Points");
1065     hbox.pack_start(w, FALSE, FALSE, 2);
1066     gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
1067     w.show();
1068
1069     // ---- /hbox ----
1070
1071     hbox = ui::HBox(FALSE, 10);
1072     vbox.pack_start(hbox, FALSE, FALSE, 2);
1073     hbox.show();
1074
1075     // ---- hbox ----
1076
1077     auto text2 = ui::Entry(256);
1078     gtk_entry_set_text(text2, "3");
1079     hbox.pack_start(text2, FALSE, FALSE, 2);
1080     text2.show();
1081
1082     w = ui::Label("Multipler");
1083     hbox.pack_start(w, FALSE, FALSE, 2);
1084     gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
1085     w.show();
1086
1087     // ---- /hbox ----
1088
1089     w = ui::Label("Path Distance = dist(start -> apex) * multiplier");
1090     vbox.pack_start(w, FALSE, FALSE, 0);
1091     gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
1092     w.show();
1093
1094     hbox = ui::HBox(FALSE, 10);
1095     vbox.pack_start(hbox, FALSE, FALSE, 2);
1096     hbox.show();
1097
1098     // ---- hbox ----
1099
1100     auto text3 = ui::Entry(256);
1101     gtk_entry_set_text(text3, "-800");
1102     hbox.pack_start(text3, FALSE, FALSE, 2);
1103     text3.show();
1104
1105     w = ui::Label("Gravity");
1106     hbox.pack_start(w, FALSE, FALSE, 2);
1107     gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
1108     w.show();
1109
1110     // ---- /hbox ----
1111
1112     w = ui::Widget::from(gtk_hseparator_new());
1113     vbox.pack_start(w, FALSE, FALSE, 0);
1114     w.show();
1115
1116     auto check1 = ui::CheckButton("No Dynamic Update");
1117     vbox.pack_start(check1, FALSE, FALSE, 0);
1118     check1.show();
1119
1120     auto check2 = ui::CheckButton("Show Bounding Lines");
1121     vbox.pack_start(check2, FALSE, FALSE, 0);
1122     check2.show();
1123
1124     // ---- /vbox ----
1125
1126
1127     // ----------------- //
1128
1129     w = ui::Widget::from(gtk_hseparator_new());
1130     vbox.pack_start(w, FALSE, FALSE, 0);
1131     w.show();
1132
1133     // ----------------- //
1134
1135     hbox = ui::HBox(FALSE, 10);
1136     vbox.pack_start(hbox, FALSE, FALSE, 0);
1137     hbox.show();
1138
1139     w = ui::Button("Enable");
1140     hbox.pack_start(w, TRUE, TRUE, 0);
1141     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDYES));
1142     w.show();
1143
1144     gtk_widget_set_can_default(w, true);
1145     gtk_widget_grab_default(w);
1146
1147     w = ui::Button("Disable");
1148     hbox.pack_start(w, TRUE, TRUE, 0);
1149     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDNO));
1150     w.show();
1151
1152     w = ui::Button("Cancel");
1153     hbox.pack_start(w, TRUE, TRUE, 0);
1154     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
1155     w.show();
1156
1157     ret = eIDCANCEL;
1158
1159     // ----------------- //
1160
1161     gtk_window_set_position(window, GTK_WIN_POS_CENTER);
1162     window.show();
1163     gtk_grab_add(window);
1164
1165     bool dialogError = TRUE;
1166     while (dialogError) {
1167         loop = 1;
1168         while (loop) {
1169             gtk_main_iteration();
1170         }
1171
1172         dialogError = FALSE;
1173
1174         if (ret == eIDYES) {
1175             if (!ValidateTextIntRange(gtk_entry_get_text(GTK_ENTRY(text1)), 1, 200, "Number Of Points", &rs->nPoints)) {
1176                 dialogError = TRUE;
1177             }
1178
1179             if (!ValidateTextFloatRange(gtk_entry_get_text(GTK_ENTRY(text2)), 1.0f, 10.0f, "Multiplier",
1180                                         &rs->fMultiplier)) {
1181                 dialogError = TRUE;
1182             }
1183
1184             if (!ValidateTextFloatRange(gtk_entry_get_text(GTK_ENTRY(text3)), -10000.0f, -1.0f, "Gravity",
1185                                         &rs->fGravity)) {
1186                 dialogError = TRUE;
1187             }
1188
1189             rs->bNoUpdate = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check1)) ? true : false;
1190             rs->bShowExtra = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check2)) ? true : false;
1191         }
1192     }
1193
1194     gtk_grab_remove(window);
1195     window.destroy();
1196
1197     return ret;
1198 }
1199
1200 EMessageBoxReturn DoCTFColourChangeBox()
1201 {
1202     ui::Widget w{ui::null};
1203     EMessageBoxReturn ret;
1204     int loop = 1;
1205
1206     auto window = ui::Window(ui::window_type::TOP);
1207
1208     window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
1209     window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
1210
1211     gtk_window_set_title(window, "CTF Colour Changer");
1212     gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1213
1214     g_object_set_data(G_OBJECT(window), "loop", &loop);
1215     g_object_set_data(G_OBJECT(window), "ret", &ret);
1216
1217     gtk_widget_realize(window);
1218
1219
1220     auto vbox = ui::VBox(FALSE, 10);
1221     window.add(vbox);
1222     vbox.show();
1223
1224     // ---- vbox ----
1225
1226     auto hbox = ui::HBox(FALSE, 10);
1227     vbox.pack_start(hbox, TRUE, TRUE, 0);
1228     hbox.show();
1229
1230     // ---- hbox ---- ok/cancel buttons
1231
1232     w = ui::Button("Red->Blue");
1233     hbox.pack_start(w, TRUE, TRUE, 0);
1234     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
1235
1236     gtk_widget_set_can_default(w, true);
1237     gtk_widget_grab_default(w);
1238     w.show();
1239
1240     w = ui::Button("Blue->Red");
1241     hbox.pack_start(w, TRUE, TRUE, 0);
1242     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDYES));
1243     w.show();
1244
1245     w = ui::Button("Cancel");
1246     hbox.pack_start(w, TRUE, TRUE, 0);
1247     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
1248     w.show();
1249     ret = eIDCANCEL;
1250
1251     // ---- /hbox ----
1252
1253     // ---- /vbox ----
1254
1255     gtk_window_set_position(window, GTK_WIN_POS_CENTER);
1256     window.show();
1257     gtk_grab_add(window);
1258
1259     while (loop) {
1260         gtk_main_iteration();
1261     }
1262
1263     gtk_grab_remove(window);
1264     window.destroy();
1265
1266     return ret;
1267 }
1268
1269 EMessageBoxReturn DoResetTextureBox(ResetTextureRS *rs)
1270 {
1271     Str texSelected;
1272
1273     ui::Widget w{ui::null};
1274
1275     EMessageBoxReturn ret;
1276     int loop = 1;
1277
1278     auto window = ui::Window(ui::window_type::TOP);
1279
1280     window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
1281     window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
1282
1283     gtk_window_set_title(window, "Texture Reset");
1284     gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1285
1286     g_object_set_data(G_OBJECT(window), "loop", &loop);
1287     g_object_set_data(G_OBJECT(window), "ret", &ret);
1288
1289     gtk_widget_realize(window);
1290
1291     auto vbox = ui::VBox(FALSE, 10);
1292     window.add(vbox);
1293     vbox.show();
1294
1295     // ---- vbox ----
1296
1297     auto hbox = ui::HBox(FALSE, 10);
1298     vbox.pack_start(hbox, FALSE, FALSE, 2);
1299     hbox.show();
1300
1301     // ---- hbox ----
1302
1303     texSelected = "Currently Selected Texture:   ";
1304     texSelected += GetCurrentTexture();
1305
1306     w = ui::Label(texSelected);
1307     hbox.pack_start(w, FALSE, FALSE, 2);
1308     gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
1309     w.show();
1310
1311     // ---- /hbox ----
1312
1313     auto frame = ui::Frame("Reset Texture Names");
1314     frame.show();
1315     vbox.pack_start(frame, FALSE, TRUE, 0);
1316
1317     auto table = ui::Table(2, 3, TRUE);
1318     table.show();
1319     frame.add(table);
1320     gtk_table_set_row_spacings(table, 5);
1321     gtk_table_set_col_spacings(table, 5);
1322     gtk_container_set_border_width(GTK_CONTAINER(table), 5);
1323
1324     // ---- frame ----
1325
1326     dlgTexReset.cbTexChange = ui::CheckButton("Enabled");
1327     dlgTexReset.cbTexChange.connect("toggled", G_CALLBACK(dialog_button_callback_texreset_update), NULL);
1328     dlgTexReset.cbTexChange.show();
1329     table.attach(dlgTexReset.cbTexChange, {0, 1, 0, 1}, {GTK_FILL, 0});
1330
1331     w = ui::Label("Old Name: ");
1332     table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0});
1333     w.show();
1334
1335     dlgTexReset.editTexOld = ui::Entry(256);
1336     gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editTexOld), rs->textureName);
1337     table.attach(dlgTexReset.editTexOld, {2, 3, 0, 1}, {GTK_FILL, 0});
1338     dlgTexReset.editTexOld.show();
1339
1340     w = ui::Label("New Name: ");
1341     table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0});
1342     w.show();
1343
1344     dlgTexReset.editTexNew = ui::Entry(256);
1345     gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editTexNew), rs->textureName);
1346     table.attach(dlgTexReset.editTexNew, {2, 3, 1, 2}, {GTK_FILL, 0});
1347     dlgTexReset.editTexNew.show();
1348
1349     // ---- /frame ----
1350
1351     frame = ui::Frame("Reset Scales");
1352     frame.show();
1353     vbox.pack_start(frame, FALSE, TRUE, 0);
1354
1355     table = ui::Table(2, 3, TRUE);
1356     table.show();
1357     frame.add(table);
1358     gtk_table_set_row_spacings(table, 5);
1359     gtk_table_set_col_spacings(table, 5);
1360     gtk_container_set_border_width(GTK_CONTAINER(table), 5);
1361
1362     // ---- frame ----
1363
1364     dlgTexReset.cbScaleHor = ui::CheckButton("Enabled");
1365     dlgTexReset.cbScaleHor.connect("toggled", G_CALLBACK(dialog_button_callback_texreset_update), NULL);
1366     dlgTexReset.cbScaleHor.show();
1367     table.attach(dlgTexReset.cbScaleHor, {0, 1, 0, 1}, {GTK_FILL, 0});
1368
1369     w = ui::Label("New Horizontal Scale: ");
1370     table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0});
1371     w.show();
1372
1373     dlgTexReset.editScaleHor = ui::Entry(256);
1374     gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editScaleHor), "0.5");
1375     table.attach(dlgTexReset.editScaleHor, {2, 3, 0, 1}, {GTK_FILL, 0});
1376     dlgTexReset.editScaleHor.show();
1377
1378
1379     dlgTexReset.cbScaleVert = ui::CheckButton("Enabled");
1380     dlgTexReset.cbScaleVert.connect("toggled", G_CALLBACK(dialog_button_callback_texreset_update), NULL);
1381     dlgTexReset.cbScaleVert.show();
1382     table.attach(dlgTexReset.cbScaleVert, {0, 1, 1, 2}, {GTK_FILL, 0});
1383
1384     w = ui::Label("New Vertical Scale: ");
1385     table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0});
1386     w.show();
1387
1388     dlgTexReset.editScaleVert = ui::Entry(256);
1389     gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editScaleVert), "0.5");
1390     table.attach(dlgTexReset.editScaleVert, {2, 3, 1, 2}, {GTK_FILL, 0});
1391     dlgTexReset.editScaleVert.show();
1392
1393     // ---- /frame ----
1394
1395     frame = ui::Frame("Reset Shift");
1396     frame.show();
1397     vbox.pack_start(frame, FALSE, TRUE, 0);
1398
1399     table = ui::Table(2, 3, TRUE);
1400     table.show();
1401     frame.add(table);
1402     gtk_table_set_row_spacings(table, 5);
1403     gtk_table_set_col_spacings(table, 5);
1404     gtk_container_set_border_width(GTK_CONTAINER(table), 5);
1405
1406     // ---- frame ----
1407
1408     dlgTexReset.cbShiftHor = ui::CheckButton("Enabled");
1409     dlgTexReset.cbShiftHor.connect("toggled", G_CALLBACK(dialog_button_callback_texreset_update), NULL);
1410     dlgTexReset.cbShiftHor.show();
1411     table.attach(dlgTexReset.cbShiftHor, {0, 1, 0, 1}, {GTK_FILL, 0});
1412
1413     w = ui::Label("New Horizontal Shift: ");
1414     table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0});
1415     w.show();
1416
1417     dlgTexReset.editShiftHor = ui::Entry(256);
1418     gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editShiftHor), "0");
1419     table.attach(dlgTexReset.editShiftHor, {2, 3, 0, 1}, {GTK_FILL, 0});
1420     dlgTexReset.editShiftHor.show();
1421
1422
1423     dlgTexReset.cbShiftVert = ui::CheckButton("Enabled");
1424     dlgTexReset.cbShiftVert.connect("toggled", G_CALLBACK(dialog_button_callback_texreset_update), NULL);
1425     dlgTexReset.cbShiftVert.show();
1426     table.attach(dlgTexReset.cbShiftVert, {0, 1, 1, 2}, {GTK_FILL, 0});
1427
1428     w = ui::Label("New Vertical Shift: ");
1429     table.attach(w, {1, 2, 1, 2}, {GTK_FILL, 0});
1430     w.show();
1431
1432     dlgTexReset.editShiftVert = ui::Entry(256);
1433     gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editShiftVert), "0");
1434     table.attach(dlgTexReset.editShiftVert, {2, 3, 1, 2}, {GTK_FILL, 0});
1435     dlgTexReset.editShiftVert.show();
1436
1437     // ---- /frame ----
1438
1439     frame = ui::Frame("Reset Rotation");
1440     frame.show();
1441     vbox.pack_start(frame, FALSE, TRUE, 0);
1442
1443     table = ui::Table(1, 3, TRUE);
1444     table.show();
1445     frame.add(table);
1446     gtk_table_set_row_spacings(table, 5);
1447     gtk_table_set_col_spacings(table, 5);
1448     gtk_container_set_border_width(GTK_CONTAINER(table), 5);
1449
1450     // ---- frame ----
1451
1452     dlgTexReset.cbRotation = ui::CheckButton("Enabled");
1453     dlgTexReset.cbRotation.show();
1454     table.attach(dlgTexReset.cbRotation, {0, 1, 0, 1}, {GTK_FILL, 0});
1455
1456     w = ui::Label("New Rotation Value: ");
1457     table.attach(w, {1, 2, 0, 1}, {GTK_FILL, 0});
1458     w.show();
1459
1460     dlgTexReset.editRotation = ui::Entry(256);
1461     gtk_entry_set_text(GTK_ENTRY(dlgTexReset.editRotation), "0");
1462     table.attach(dlgTexReset.editRotation, {2, 3, 0, 1}, {GTK_FILL, 0});
1463     dlgTexReset.editRotation.show();
1464
1465     // ---- /frame ----
1466
1467     hbox = ui::HBox(FALSE, 10);
1468     vbox.pack_start(hbox, FALSE, FALSE, 2);
1469     hbox.show();
1470
1471     // ---- hbox ----
1472
1473     w = ui::Button("Use Selected Brushes");
1474     hbox.pack_start(w, TRUE, TRUE, 0);
1475     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
1476
1477     gtk_widget_set_can_default(w, true);
1478     gtk_widget_grab_default(w);
1479     w.show();
1480
1481     w = ui::Button("Use All Brushes");
1482     hbox.pack_start(w, TRUE, TRUE, 0);
1483     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDYES));
1484     w.show();
1485
1486     w = ui::Button("Cancel");
1487     hbox.pack_start(w, TRUE, TRUE, 0);
1488     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
1489     w.show();
1490     ret = eIDCANCEL;
1491
1492     // ---- /hbox ----
1493
1494     // ---- /vbox ----
1495
1496     gtk_window_set_position(window, GTK_WIN_POS_CENTER);
1497     window.show();
1498     gtk_grab_add(window);
1499
1500     Update_TextureReseter();
1501
1502     bool dialogError = TRUE;
1503     while (dialogError) {
1504         loop = 1;
1505         while (loop) {
1506             gtk_main_iteration();
1507         }
1508
1509         dialogError = FALSE;
1510
1511         if (ret != eIDCANCEL) {
1512             rs->bResetRotation = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbRotation));
1513             if (rs->bResetRotation) {
1514                 if (!ValidateTextInt(gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editRotation)), "Rotation",
1515                                      &rs->rotation)) {
1516                     dialogError = TRUE;
1517                 }
1518             }
1519
1520             rs->bResetScale[0] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbScaleHor));
1521             if (rs->bResetScale[0]) {
1522                 if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editScaleHor)), "Horizontal Scale",
1523                                        &rs->fScale[0])) {
1524                     dialogError = TRUE;
1525                 }
1526             }
1527
1528             rs->bResetScale[1] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbScaleVert));
1529             if (rs->bResetScale[1]) {
1530                 if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editScaleVert)), "Vertical Scale",
1531                                        &rs->fScale[1])) {
1532                     dialogError = TRUE;
1533                 }
1534             }
1535
1536             rs->bResetShift[0] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbShiftHor));
1537             if (rs->bResetShift[0]) {
1538                 if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editShiftHor)), "Horizontal Shift",
1539                                        &rs->fShift[0])) {
1540                     dialogError = TRUE;
1541                 }
1542             }
1543
1544             rs->bResetShift[1] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbShiftVert));
1545             if (rs->bResetShift[1]) {
1546                 if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editShiftVert)), "Vertical Shift",
1547                                        &rs->fShift[1])) {
1548                     dialogError = TRUE;
1549                 }
1550             }
1551
1552             rs->bResetTextureName = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlgTexReset.cbTexChange));
1553             if (rs->bResetTextureName) {
1554                 strcpy(rs->textureName, gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editTexOld)));
1555                 strcpy(rs->newTextureName, gtk_entry_get_text(GTK_ENTRY(dlgTexReset.editTexNew)));
1556             }
1557         }
1558     }
1559
1560     gtk_grab_remove(window);
1561     window.destroy();
1562
1563     return ret;
1564 }
1565
1566 EMessageBoxReturn DoTrainThingBox(TrainThingRS *rs)
1567 {
1568     Str texSelected;
1569
1570     ui::Widget w{ui::null};
1571
1572     ui::Widget radiusX{ui::null}, radiusY{ui::null};
1573     ui::Widget angleStart{ui::null}, angleEnd{ui::null};
1574     ui::Widget heightStart{ui::null}, heightEnd{ui::null};
1575     ui::Widget numPoints{ui::null};
1576
1577     EMessageBoxReturn ret;
1578     int loop = 1;
1579
1580     auto window = ui::Window(ui::window_type::TOP);
1581
1582     window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
1583     window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
1584
1585     gtk_window_set_title(window, "Train Thing");
1586     gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1587
1588     g_object_set_data(G_OBJECT(window), "loop", &loop);
1589     g_object_set_data(G_OBJECT(window), "ret", &ret);
1590
1591     gtk_widget_realize(window);
1592
1593     auto vbox = ui::VBox(FALSE, 10);
1594     window.add(vbox);
1595     vbox.show();
1596
1597     // ---- vbox ----
1598
1599     auto hbox = ui::HBox(FALSE, 10);
1600     vbox.pack_start(hbox, FALSE, FALSE, 2);
1601     hbox.show();
1602
1603     // ---- /hbox ----
1604
1605     auto frame = ui::Frame("Radii");
1606     frame.show();
1607     vbox.pack_start(frame, FALSE, TRUE, 0);
1608
1609     auto table = ui::Table(2, 3, TRUE);
1610     table.show();
1611     frame.add(table);
1612     gtk_table_set_row_spacings(table, 5);
1613     gtk_table_set_col_spacings(table, 5);
1614     gtk_container_set_border_width(GTK_CONTAINER(table), 5);
1615
1616     // ---- frame ----
1617
1618     w = ui::Label("X: ");
1619     table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0});
1620     w.show();
1621
1622     radiusX = ui::Entry(256);
1623     gtk_entry_set_text(GTK_ENTRY(radiusX), "100");
1624     table.attach(radiusX, {1, 2, 0, 1}, {GTK_FILL, 0});
1625     radiusX.show();
1626
1627
1628     w = ui::Label("Y: ");
1629     table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0});
1630     w.show();
1631
1632     radiusY = ui::Entry(256);
1633     gtk_entry_set_text(GTK_ENTRY(radiusY), "100");
1634     table.attach(radiusY, {1, 2, 1, 2}, {GTK_FILL, 0});
1635     radiusY.show();
1636
1637
1638     frame = ui::Frame("Angles");
1639     frame.show();
1640     vbox.pack_start(frame, FALSE, TRUE, 0);
1641
1642     table = ui::Table(2, 3, TRUE);
1643     table.show();
1644     frame.add(table);
1645     gtk_table_set_row_spacings((table), 5);
1646     gtk_table_set_col_spacings((table), 5);
1647     gtk_container_set_border_width(GTK_CONTAINER(table), 5);
1648
1649     // ---- frame ----
1650
1651     w = ui::Label("Start: ");
1652     table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0});
1653     w.show();
1654
1655     angleStart = ui::Entry(256);
1656     gtk_entry_set_text(GTK_ENTRY(angleStart), "0");
1657     table.attach(angleStart, {1, 2, 0, 1}, {GTK_FILL, 0});
1658     angleStart.show();
1659
1660
1661     w = ui::Label("End: ");
1662     table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0});
1663     w.show();
1664
1665     angleEnd = ui::Entry(256);
1666     gtk_entry_set_text(GTK_ENTRY(angleEnd), "90");
1667     table.attach(angleEnd, {1, 2, 1, 2}, {GTK_FILL, 0});
1668     angleEnd.show();
1669
1670
1671     frame = ui::Frame("Height");
1672     frame.show();
1673     vbox.pack_start(frame, FALSE, TRUE, 0);
1674
1675     table = ui::Table(2, 3, TRUE);
1676     table.show();
1677     frame.add(table);
1678     gtk_table_set_row_spacings(table, 5);
1679     gtk_table_set_col_spacings(table, 5);
1680     gtk_container_set_border_width(GTK_CONTAINER(table), 5);
1681
1682     // ---- frame ----
1683
1684     w = ui::Label("Start: ");
1685     table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0});
1686     w.show();
1687
1688     heightStart = ui::Entry(256);
1689     gtk_entry_set_text(GTK_ENTRY(heightStart), "0");
1690     table.attach(heightStart, {1, 2, 0, 1}, {GTK_FILL, 0});
1691     heightStart.show();
1692
1693
1694     w = ui::Label("End: ");
1695     table.attach(w, {0, 1, 1, 2}, {GTK_FILL, 0});
1696     w.show();
1697
1698     heightEnd = ui::Entry(256);
1699     gtk_entry_set_text(GTK_ENTRY(heightEnd), "0");
1700     table.attach(heightEnd, {1, 2, 1, 2}, {GTK_FILL, 0});
1701     heightEnd.show();
1702
1703
1704     frame = ui::Frame("Points");
1705     frame.show();
1706     vbox.pack_start(frame, FALSE, TRUE, 0);
1707
1708     table = ui::Table(2, 3, TRUE);
1709     table.show();
1710     frame.add(table);
1711     gtk_table_set_row_spacings(table, 5);
1712     gtk_table_set_col_spacings(table, 5);
1713     gtk_container_set_border_width(GTK_CONTAINER(table), 5);
1714
1715     // ---- frame ----
1716
1717     w = ui::Label("Number: ");
1718     table.attach(w, {0, 1, 0, 1}, {GTK_FILL, 0});
1719     w.show();
1720
1721     numPoints = ui::Entry(256);
1722     gtk_entry_set_text(GTK_ENTRY(numPoints), "0");
1723     table.attach(numPoints, {1, 2, 0, 1}, {GTK_FILL, 0});
1724     numPoints.show();
1725
1726
1727     hbox = ui::HBox(FALSE, 10);
1728     vbox.pack_start(hbox, FALSE, FALSE, 2);
1729     hbox.show();
1730
1731     // ---- hbox ----
1732
1733     w = ui::Button("Ok");
1734     hbox.pack_start(w, TRUE, TRUE, 0);
1735     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
1736
1737     gtk_widget_set_can_default(w, true);
1738     gtk_widget_grab_default(w);
1739     w.show();
1740
1741     w = ui::Button("Cancel");
1742     hbox.pack_start(w, TRUE, TRUE, 0);
1743     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
1744     w.show();
1745     ret = eIDCANCEL;
1746
1747     // ---- /hbox ----
1748
1749
1750
1751     gtk_window_set_position(window, GTK_WIN_POS_CENTER);
1752     window.show();
1753     gtk_grab_add(window);
1754
1755     bool dialogError = TRUE;
1756     while (dialogError) {
1757         loop = 1;
1758         while (loop) {
1759             gtk_main_iteration();
1760         }
1761
1762         dialogError = FALSE;
1763
1764         if (ret != eIDCANCEL) {
1765             if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(radiusX)), "Radius (X)", &rs->fRadiusX)) {
1766                 dialogError = TRUE;
1767             }
1768
1769             if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(radiusY)), "Radius (Y)", &rs->fRadiusY)) {
1770                 dialogError = TRUE;
1771             }
1772
1773             if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(angleStart)), "Angle (Start)", &rs->fStartAngle)) {
1774                 dialogError = TRUE;
1775             }
1776
1777             if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(angleEnd)), "Angle (End)", &rs->fEndAngle)) {
1778                 dialogError = TRUE;
1779             }
1780
1781             if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(heightStart)), "Height (Start)", &rs->fStartHeight)) {
1782                 dialogError = TRUE;
1783             }
1784
1785             if (!ValidateTextFloat(gtk_entry_get_text(GTK_ENTRY(heightEnd)), "Height (End)", &rs->fEndHeight)) {
1786                 dialogError = TRUE;
1787             }
1788
1789             if (!ValidateTextInt(gtk_entry_get_text(GTK_ENTRY(numPoints)), "Num Points", &rs->iNumPoints)) {
1790                 dialogError = TRUE;
1791             }
1792         }
1793     }
1794
1795     gtk_grab_remove(window);
1796     window.destroy();
1797
1798     return ret;
1799 }
1800
1801 // ailmanki
1802 // add a simple input for the MakeChain thing..
1803 EMessageBoxReturn DoMakeChainBox(MakeChainRS *rs)
1804 {
1805     ui::Widget w{ui::null};
1806     ui::Entry textlinkNum{ui::null}, textlinkName{ui::null};
1807     EMessageBoxReturn ret;
1808     int loop = 1;
1809
1810     const char *text = "Please set a value in the boxes below and press 'OK' to make a chain";
1811
1812     auto window = ui::Window(ui::window_type::TOP);
1813
1814     window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
1815     window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
1816
1817     gtk_window_set_title(window, "Make Chain");
1818
1819     gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1820
1821     g_object_set_data(G_OBJECT(window), "loop", &loop);
1822     g_object_set_data(G_OBJECT(window), "ret", &ret);
1823
1824     gtk_widget_realize(window);
1825
1826     // new vbox
1827     auto vbox = ui::VBox(FALSE, 10);
1828     window.add(vbox);
1829     vbox.show();
1830
1831     auto hbox = ui::HBox(FALSE, 10);
1832     vbox.add(hbox);
1833     hbox.show();
1834
1835     // dunno if you want this text or not ...
1836     w = ui::Label(text);
1837     hbox.pack_start(w, FALSE, FALSE, 0);
1838     w.show();
1839
1840     w = ui::Widget::from(gtk_hseparator_new());
1841     vbox.pack_start(w, FALSE, FALSE, 0);
1842     w.show();
1843
1844     // ------------------------- //
1845
1846     // new hbox
1847     hbox = ui::HBox(FALSE, 10);
1848     vbox.pack_start(hbox, FALSE, FALSE, 0);
1849     hbox.show();
1850
1851     textlinkNum = ui::Entry(256);
1852     hbox.pack_start(textlinkNum, FALSE, FALSE, 1);
1853     textlinkNum.show();
1854
1855     w = ui::Label("Number of elements in chain");
1856     hbox.pack_start(w, FALSE, FALSE, 1);
1857     w.show();
1858
1859     // -------------------------- //
1860
1861     hbox = ui::HBox(FALSE, 10);
1862     vbox.pack_start(hbox, FALSE, FALSE, 0);
1863     hbox.show();
1864
1865     textlinkName = ui::Entry(256);
1866     hbox.pack_start(textlinkName, FALSE, FALSE, 0);
1867     textlinkName.show();
1868
1869     w = ui::Label("Basename for chain's targetnames.");
1870     hbox.pack_start(w, FALSE, FALSE, 1);
1871     w.show();
1872
1873
1874     w = ui::Button("OK");
1875     hbox.pack_start(w, TRUE, TRUE, 0);
1876     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
1877     gtk_widget_set_can_default(w, true);
1878     gtk_widget_grab_default(w);
1879     w.show();
1880
1881     w = ui::Button("Cancel");
1882     hbox.pack_start(w, TRUE, TRUE, 0);
1883     w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
1884     w.show();
1885
1886     ret = eIDCANCEL;
1887
1888     gtk_window_set_position(window, GTK_WIN_POS_CENTER);
1889     window.show();
1890     gtk_grab_add(window);
1891
1892     bool dialogError = TRUE;
1893     while (dialogError) {
1894         loop = 1;
1895         while (loop) {
1896             gtk_main_iteration();
1897         }
1898
1899         dialogError = FALSE;
1900
1901         if (ret == eIDOK) {
1902             strcpy(rs->linkName, gtk_entry_get_text(textlinkName));
1903             if (!ValidateTextInt(gtk_entry_get_text(textlinkNum), "Elements", &rs->linkNum)) {
1904                 dialogError = TRUE;
1905             }
1906         }
1907     }
1908
1909     gtk_grab_remove(window);
1910     window.destroy();
1911
1912     return ret;
1913 }