XML serialization for set files, bug fixes and a new full screen mode
[terminatorX.git] / src / tX_dialog.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2002  Alexander K├Ânig
4  
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9  
10     This program 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
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  
19     File: tX_dialog.c
20  
21     Description: Contains the implementation of the Options and About
22                  Dialogs. (And some really ugly "WE WANT TO 
23                  TYPE LESS" macros)
24                  
25     Changes:
26     
27     28 Jul 1999: Now display compiletime settings in the about dialog.
28 */    
29
30 #include "tX_types.h"
31 #include "tX_global.h"
32 #include "tX_dialog.h"
33 #include <gtk/gtk.h>
34 #include <string.h>
35 #include <gdk/gdk.h>
36 #include "tX_icon.h"
37
38 #ifndef WIN32
39 #include <X11/extensions/XInput.h>
40 #include <X11/X.h>
41 #endif
42
43 #include "license.c"
44 #include "tX_mastergui.h"
45 #include "version.h"
46
47 extern char *logo_xpm[];
48
49 GdkWindow *opt_window=NULL;
50 GtkWidget *opt_dialog;
51 GtkWidget *menu=NULL;
52
53 GtkWidget *audio_device;
54 GtkWidget *use_stdout;
55 GtkWidget *prelis;
56
57 GtkAdjustment *buff_no=NULL;
58 GtkWidget *buff_no_slider;
59 GtkAdjustment *buff_size=NULL;
60 GtkWidget *buff_size_slider;
61
62 GtkAdjustment *sense_cycles=NULL;
63 GtkWidget *sense_cycles_slider;
64
65 GtkWidget *xinput_enable;
66 GtkWidget *xinput_device;
67 GtkAdjustment *mouse_speed=NULL;
68 GtkWidget *mouse_speed_slider;
69
70 GtkWidget *tooltips;
71 GtkWidget *show_nag;
72 GtkAdjustment *update_idle=NULL;
73 GtkAdjustment *update_delay_adj=NULL;
74 GtkAdjustment *flash_response;
75 GtkWidget *update_idle_slider;
76 GtkWidget *update_delay_slider;
77
78 GtkWidget *opt_ok;
79 GtkWidget *opt_apply;
80 GtkWidget *opt_cancel;
81
82 GtkWidget *but_text;
83 GtkWidget *but_icon;
84 GtkWidget *but_both;
85
86 GtkWidget *sound_editor;
87
88 GtkTooltips *opt_tips;
89
90 int opt_hidden=0;
91
92 void apply_options() {
93         char *text;
94         
95         strcpy(globals.audio_device, gtk_entry_get_text(GTK_ENTRY(audio_device)));
96         globals.buff_no=(int)buff_no->value;    
97         globals.buff_size=(int)buff_size->value;
98         
99         globals.prelis=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prelis));
100                 
101         globals.sense_cycles=(int) sense_cycles->value;
102         globals.xinput_enable=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xinput_enable));
103         text=(char *) gtk_button_get_label(GTK_BUTTON(xinput_device));
104         strcpy(globals.xinput_device, text);    
105         
106         globals.mouse_speed=mouse_speed->value;
107         globals.tooltips=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tooltips));
108         if (globals.tooltips) gtk_tooltips_enable(gui_tooltips);
109         else gtk_tooltips_disable(gui_tooltips);
110         
111         globals.show_nag=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(show_nag));
112         globals.update_idle=(int) update_idle->value;
113         globals.update_delay=(int) update_delay_adj->value;     
114         globals.flash_response=flash_response->value;
115         
116         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(but_text))) globals.button_type=BUTTON_TYPE_TEXT;
117         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(but_icon))) globals.button_type=BUTTON_TYPE_ICON;
118         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(but_both))) globals.button_type=BUTTON_TYPE_BOTH;
119         strcpy(globals.file_editor, gtk_entry_get_text(GTK_ENTRY(sound_editor)));
120 }
121
122 #define WID_DYN TRUE, TRUE, 0
123 #define WID_FIX FALSE, FALSE, 0
124
125 #define my_new_subsec(s); \
126         separator=gtk_hseparator_new(); \
127         gtk_box_pack_start(GTK_BOX(vbox), separator, WID_DYN);\
128         gtk_widget_show(separator); \
129         label=gtk_label_new(s); \
130         gtk_misc_set_alignment (GTK_MISC(label), 0 ,0.5); \
131         gtk_box_pack_start(GTK_BOX(vbox), label, WID_DYN); \
132         gtk_widget_show(label); 
133
134 #define my_new_button(btn, s); \
135         btn=gtk_button_new_with_label(s); \
136         gtk_box_pack_start(GTK_BOX(aa), btn, WID_DYN); \
137         gtk_widget_show(btn);
138         
139
140 #define begin_box(); box=gtk_hbox_new(FALSE, 5);
141
142 #define begin_hom_box(); box=gtk_hbox_new(TRUE, 5);
143
144 #define end_box(); gtk_box_pack_start(GTK_BOX(vbox), box, WID_DYN); \
145         gtk_widget_show(box);
146
147 #define add_widget_dyn(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_DYN);\
148         gtk_widget_show(wid);
149         
150 #define add_widget_fix(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_FIX);\
151         gtk_widget_show(wid);
152
153 #define add_expl(s); label=gtk_label_new(s); \
154         gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);\
155         add_widget_fix(label);
156
157 #define add_expl_dyn(s); label=gtk_label_new(s); \
158         gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);\
159         add_widget_dyn(label);
160         
161 static gint showdevmenu(GtkWidget *widget, GdkEvent *event)
162 {
163         if (event->type == GDK_BUTTON_PRESS) {
164                 GdkEventButton *bevent = (GdkEventButton *) event; 
165                 gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
166                 bevent->button, bevent->time);
167         return TRUE;
168         }
169         
170         return FALSE;   
171 }
172
173 #ifndef WIN32
174 XDeviceInfo *xdev=NULL;
175 #endif
176
177 void options_destroy(GtkWidget *widget)
178 {
179         /* Destroying everything that is NOT a direct part of
180           the dialog: adjustments, menu and XDeviceList.
181         */
182
183         gdk_window_hide(opt_window);    
184         opt_hidden=1;
185         
186         gtk_object_destroy(GTK_OBJECT(opt_dialog));
187
188 #ifndef WIN32
189         XFreeDeviceList(xdev);  
190 #endif  
191         opt_window=NULL;
192 }
193
194 void ok_options(GtkWidget *widget)
195 {
196         apply_options();
197         options_destroy(widget);
198 }
199
200 void  use_stdout_changed(GtkWidget *widget)
201 {
202         globals.use_stdout=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
203         globals.use_stdout_cmdline = 0;
204 }
205 void select_input(GtkWidget *w, char *dev)
206 {
207         gtk_button_set_label(GTK_BUTTON(xinput_device), dev);
208 }
209
210 void create_options()
211 {
212         GtkWidget *box;
213         GtkWidget *vbox;
214         GtkWidget *aa;
215         GtkWidget *label;
216         GtkWidget *separator;
217         GtkWindow *w;
218         GtkWidget *item;
219         GSList *button_type_group;
220         
221         Display *dpy;
222         
223         int i, devmax;
224                 
225         opt_dialog=gtk_dialog_new();
226         w=&(GTK_DIALOG(opt_dialog)->window);
227         gtk_window_set_wmclass(GTK_WINDOW(w), "terminatorX", "tX_options");
228         gtk_window_set_title(w, "terminatorX - Options");
229
230         opt_tips=gtk_tooltips_new();
231         
232         vbox=GTK_WIDGET(GTK_DIALOG(opt_dialog)->vbox);
233         gtk_box_set_spacing(GTK_BOX(vbox), 5);
234         gtk_container_set_border_width(GTK_CONTAINER(w), 5);
235 //      gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE);
236         aa=GTK_WIDGET(GTK_DIALOG(opt_dialog)->action_area);
237         gtk_box_set_spacing(GTK_BOX(aa), 5);
238 //      gtk_box_set_homogeneous(GTK_BOX(aa), FALSE);
239         
240         label=gtk_label_new("Options:");
241         gtk_misc_set_alignment (GTK_MISC(label), 0.5 ,0.5);     
242         gtk_box_pack_start(GTK_BOX(vbox), label, WID_DYN);
243         gtk_widget_show(label);
244         
245         my_new_subsec("[ Audio: ]");
246         
247         begin_box();
248
249         add_expl("Device:");
250         
251         audio_device=gtk_entry_new_with_max_length(PATH_MAX);
252         gtk_entry_set_text(GTK_ENTRY(audio_device), globals.audio_device);
253         gtk_tooltips_set_tip(opt_tips, audio_device, "Enter the path to your audio device here. For most systems this should be /dev/dsp.", NULL);
254         add_widget_dyn(audio_device);
255         
256         end_box();
257
258         begin_box();
259         use_stdout=gtk_check_button_new_with_label("Use standard output instead of the above device");
260         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_stdout), globals.use_stdout);        
261         gtk_signal_connect(GTK_OBJECT(use_stdout), "clicked", (GtkSignalFunc) use_stdout_changed, NULL);
262         add_widget_fix(use_stdout);     
263         end_box();      
264                 
265         begin_box();
266         
267         add_expl("No. of Buffers:");
268         
269         buff_no=(GtkAdjustment*) gtk_adjustment_new(globals.buff_no, 1, 16, 1, 1, 1);
270         buff_no_slider=gtk_hscale_new(buff_no);
271         gtk_scale_set_digits(GTK_SCALE(buff_no_slider), 0);
272         gtk_scale_set_value_pos(GTK_SCALE(buff_no_slider), GTK_POS_LEFT);
273         gtk_tooltips_set_tip(opt_tips, buff_no_slider, "Sets the number of kernel level audio buffers. Actually most systems should run just fine with two.", NULL);
274         add_widget_dyn(buff_no_slider);
275
276         end_box();
277
278         begin_box();
279
280         add_expl("Size of Buffers:");
281         
282         buff_size=(GtkAdjustment*) gtk_adjustment_new(globals.buff_size, 1, 16, 1, 1, 1);
283         buff_size_slider=gtk_hscale_new(buff_size);
284         gtk_scale_set_digits(GTK_SCALE(buff_size_slider), 0);
285         gtk_scale_set_value_pos(GTK_SCALE(buff_size_slider), GTK_POS_LEFT);
286         gtk_tooltips_set_tip(opt_tips, buff_size_slider, "Sets the size of the kernel level audio buffers. On slower systems you might have to increase this value (if you hear \"clicks\"). Lower values mean lower latency though.", NULL);
287         add_widget_dyn(buff_size_slider);
288                 
289         end_box();
290
291         begin_box();
292
293         begin_box();
294
295         prelis=gtk_check_button_new_with_label("Pre-Listen to audio files");
296         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(prelis), globals.prelis);
297         add_widget_fix(prelis);         
298         
299         end_box();
300         
301         my_new_subsec("[ Mouse / Input: ]");
302
303 #ifndef WIN32   
304         dpy=XOpenDisplay(NULL);
305         xdev=XListInputDevices(dpy, &devmax);
306         XCloseDisplay(dpy);
307
308         if (menu) gtk_object_destroy(GTK_OBJECT(menu));
309                 
310         menu = gtk_menu_new();  
311         
312         for (i=0; i<devmax; i++)
313         {
314                 item = gtk_menu_item_new_with_label(xdev[i].name);
315                 gtk_menu_append(GTK_MENU(menu), item);
316                 gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(select_input), xdev[i].name);
317                 gtk_widget_show(item);
318         }
319
320         begin_box();
321
322         xinput_enable=gtk_check_button_new_with_label("XInput Device:");
323         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xinput_enable), globals.xinput_enable);          
324         gtk_tooltips_set_tip(opt_tips,  xinput_enable, "CAREFUL! Enable this *only* if you want to use an input device than your default X-Pointer (yes, your mouse ;). You have to select your desired device as well. Selecting the default mouse pointer will crash terminatorX so if you want to use that keep this option disabled.", NULL);
325         add_widget_fix(xinput_enable);
326         
327         if (strlen(globals.xinput_device)>0)    
328         {
329                 xinput_device=gtk_button_new_with_label(globals.xinput_device);
330         }
331         else
332         {
333                 xinput_device=gtk_button_new_with_label("");
334         }
335                 
336         gtk_signal_connect_object (GTK_OBJECT (xinput_device), "event", GTK_SIGNAL_FUNC (showdevmenu), GTK_OBJECT (menu));
337         add_widget_dyn(xinput_device);
338                 
339         end_box();
340         
341 #endif  
342         
343         begin_box();
344         
345         add_expl("Mouse Speed:");
346                 
347         mouse_speed=(GtkAdjustment*) gtk_adjustment_new(globals.mouse_speed, -10, 10, 0.5, 0.1, 0.1);
348         mouse_speed_slider=gtk_hscale_new(mouse_speed);
349         gtk_scale_set_digits(GTK_SCALE(mouse_speed_slider), 1);
350         gtk_scale_set_value_pos(GTK_SCALE(mouse_speed_slider), GTK_POS_LEFT);
351         gtk_tooltips_set_tip(opt_tips, mouse_speed_slider, "The speed of your mouse in scratch mode. Use negative values to invert motion.", NULL);
352         add_widget_dyn(mouse_speed_slider);
353         
354         end_box();
355         
356         begin_box();
357         
358         add_expl("Stop Sense Cycles:");
359         
360         sense_cycles=(GtkAdjustment*) gtk_adjustment_new(globals.sense_cycles, 1, 150, 5, 1, 1);
361         sense_cycles_slider=gtk_hscale_new(sense_cycles);
362         gtk_scale_set_digits(GTK_SCALE(sense_cycles_slider), 0);
363         gtk_scale_set_value_pos(GTK_SCALE(sense_cycles_slider), GTK_POS_LEFT);
364         gtk_tooltips_set_tip(opt_tips, sense_cycles_slider, "If there is no \"motion-event\" for x cycles, where x is the number of cycles you select here, terminatorX assumes mouse motion has stopped. For smaller buffer sizes (=> shorter cycle times) you might have to increase this value", NULL);
365         add_widget_dyn(sense_cycles_slider);
366         
367         end_box();
368         
369         my_new_subsec("[ Graphics / GUI: ]");
370         
371         begin_box();
372         
373         tooltips=gtk_check_button_new_with_label("Main Window Tooltips");
374         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltips), globals.tooltips);    
375         add_widget_dyn(tooltips);       
376         
377         end_box();
378         
379         begin_box();
380         
381         add_expl("Update Idle:");
382                 
383         update_idle=(GtkAdjustment*) gtk_adjustment_new(globals.update_idle, 1, 100, 1, 10, 10);
384         update_idle_slider=gtk_hscale_new(update_idle);
385         gtk_scale_set_digits(GTK_SCALE(update_idle_slider), 0);
386         gtk_scale_set_value_pos(GTK_SCALE(update_idle_slider), GTK_POS_LEFT);
387         gtk_tooltips_set_tip(opt_tips,  update_idle_slider, "The update thread will idle for the selcted amount of milliseconds. If you want to have a more responsive display update increase this value - if you have performance problems reduce this value.", NULL);
388         add_widget_dyn(update_idle_slider);
389                 
390         end_box();
391
392         begin_box();
393         
394         add_expl("Update Delay:");
395                 
396         update_delay_adj=(GtkAdjustment*) gtk_adjustment_new(globals.update_delay, 0, 15, 1, 10, 10);
397         update_delay_slider=gtk_hscale_new(update_delay_adj);
398         gtk_scale_set_digits(GTK_SCALE(update_delay_slider), 0);
399         gtk_scale_set_value_pos(GTK_SCALE(update_delay_slider), GTK_POS_LEFT);
400         gtk_tooltips_set_tip(opt_tips,  update_delay_slider, "How often to update the slow widgets.", NULL);
401         add_widget_dyn(update_delay_slider);
402                 
403         end_box();
404
405         begin_box();
406         
407         add_expl("Flash Decay:  ");
408         
409         flash_response=GTK_ADJUSTMENT(gtk_adjustment_new(globals.flash_response, 0.8, 0.99, 0.01, 0.01, 0.001));
410         item=gtk_hscale_new(flash_response);
411         gtk_scale_set_digits(GTK_SCALE(item), 2);
412         gtk_scale_set_value_pos(GTK_SCALE(item), GTK_POS_LEFT);
413 //      gtk_tooltips_set_tip(opt_tips,  update_idle_slider, "The update thread will idle for the selcted amount of milliseconds. If you want to have a more responsive display update increase this value - if you have performance problems reduce this value.", NULL);
414         add_widget_dyn(item);
415         
416         end_box();
417
418         begin_box();
419         
420         add_expl("Buttons as ");
421         but_both=item=gtk_radio_button_new_with_label(NULL, "Text+Icon");
422         add_widget_fix(item);
423         button_type_group=gtk_radio_button_group(GTK_RADIO_BUTTON(item));       
424         but_text=item=gtk_radio_button_new_with_label(button_type_group, "Text");
425         button_type_group=gtk_radio_button_group(GTK_RADIO_BUTTON(item));       
426         add_widget_fix(item);
427         but_icon=item=gtk_radio_button_new_with_label(button_type_group, "Icon");
428         add_widget_fix(item);
429         
430         switch (globals.button_type)
431         {
432                 case BUTTON_TYPE_TEXT:
433                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(but_text), 1);
434                 break;
435                 case BUTTON_TYPE_ICON:
436                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(but_icon), 1);
437                 break;
438                 case BUTTON_TYPE_BOTH:
439                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(but_both), 1);
440                 break;
441                 default: fprintf (stderr, "oops: Unknown button type.\n");
442         }
443         
444         end_box();
445
446         begin_box();    
447
448         show_nag=gtk_check_button_new_with_label("Display nagbox on startup while loading data");
449         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_nag), globals.show_nag);    
450         add_widget_dyn(show_nag);               
451         
452         end_box();
453
454         begin_box();
455         
456         add_expl("Soundfile editor:");
457                 
458         sound_editor=gtk_entry_new_with_max_length(PATH_MAX);
459         gtk_entry_set_text(GTK_ENTRY(sound_editor), globals.file_editor);
460         gtk_tooltips_set_tip(opt_tips, sound_editor, "Enter your favourite soundfile editor.", NULL);
461         add_widget_dyn(sound_editor);   
462         
463         end_box();      
464         my_new_button(opt_ok, "Ok");
465         gtk_signal_connect(GTK_OBJECT(opt_ok), "clicked", (GtkSignalFunc) ok_options, NULL);
466         my_new_button(opt_apply, "Apply");
467         gtk_signal_connect(GTK_OBJECT(opt_apply), "clicked", (GtkSignalFunc) apply_options, NULL);
468         my_new_button(opt_cancel, "Cancel");
469         gtk_signal_connect(GTK_OBJECT(opt_cancel), "clicked", (GtkSignalFunc) options_destroy, NULL);
470
471         
472         gtk_widget_show(opt_dialog);
473         opt_window=opt_dialog->window;
474         tX_set_icon(opt_dialog, "tX Options");
475         gtk_signal_connect(GTK_OBJECT(opt_dialog), "delete-event", (GtkSignalFunc) options_destroy, NULL);      
476
477 }
478
479 void display_options()
480 {
481         if (opt_window)
482         {
483                 gdk_window_raise(opt_window);   
484         }
485         else
486         {
487                 create_options();
488         }
489 }
490
491 GtkWidget *about=NULL;
492
493 void raise_about()
494 {
495         if (about)
496         gdk_window_raise(about->window);
497 }
498
499
500 void destroy_about()
501 {
502         if (about)
503         {       
504                 gtk_widget_destroy(about);
505                 about=NULL;
506         }
507 }
508
509
510
511 #define add_about_wid(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_DYN); \
512         gtk_widget_show(wid);
513
514 #define add_about_wid_fix(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_FIX); \
515         gtk_widget_show(wid);
516
517 GdkFont *GPL_font=NULL;
518
519 void show_about(int nag)
520 {
521         GtkWidget *window, *pwid;
522         GdkBitmap *mask;
523         GtkStyle *style;
524         GtkWidget *btn;
525         GtkWidget *box;
526         GtkWidget *hbox;
527         GtkWidget *label;
528         GtkWidget *sep;
529         GtkWidget *text;
530         GtkWidget *scroll;
531         GdkPixmap *pmap=NULL;
532         
533         if (about) 
534         {
535                 gdk_window_raise(about->window);
536                 return;
537         }
538         
539         window = gtk_window_new(GTK_WINDOW_TOPLEVEL);   
540         gtk_window_set_wmclass(GTK_WINDOW(window), "terminatorX", "tX_about");
541
542         gtk_container_set_border_width(GTK_CONTAINER(window), 5);
543
544 //      GTK_WINDOW(window)->use_uposition=TRUE;
545
546         gtk_widget_realize(window);
547         
548         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
549         gtk_window_set_title(GTK_WINDOW(window), "terminatorX - About");
550         
551         if (nag)
552         {
553                 gdk_window_set_decorations(window->window, (enum GdkWMDecoration) 0);
554         }
555
556         
557         style = gtk_widget_get_style( window );
558
559         if (!pmap)
560         {
561                 pmap=gdk_pixmap_create_from_xpm_d(window->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar **)logo_xpm );
562         }
563
564
565         pwid = gtk_pixmap_new( pmap, mask );
566         
567         gtk_widget_show( pwid );
568
569         if (nag) {
570                 GtkWidget *box=gtk_vbox_new(FALSE, 2);
571                 GtkWidget *box2=gtk_hbox_new(FALSE, 2);
572                 GtkWidget *label;
573                 
574                 gtk_container_add(GTK_CONTAINER(window), box);
575                 gtk_box_pack_start(GTK_BOX(box), pwid, WID_FIX);
576                 gtk_box_pack_start(GTK_BOX(box), box2, WID_FIX);
577                 
578                 label=gtk_label_new(PACKAGE" release "VERSION);
579                 gtk_box_pack_start(GTK_BOX(box2), label, WID_DYN);
580                 gtk_misc_set_alignment(GTK_MISC(label), 0.1, 0.5);
581                 gtk_widget_show(label);
582
583                 label=gtk_label_new("Copyright (C) 1999-2002 by Alexander K\xC3\xB6nig");
584                 gtk_box_pack_start(GTK_BOX(box2), label, WID_DYN);
585                 gtk_misc_set_alignment(GTK_MISC(label), 0.9, 0.5);
586                 gtk_widget_show(label);
587                 
588                 gtk_widget_show(box2);
589                 gtk_widget_show(box);
590                 gtk_widget_show(window);
591                 
592                 while (gtk_events_pending()) gtk_main_iteration();      
593         }
594         else
595         {
596                 box=gtk_vbox_new(FALSE, 5);
597                 add_about_wid_fix(pwid);
598                 
599                 sep=gtk_hseparator_new();
600                 add_about_wid_fix(sep);
601                 char about_prefix_umlaut[]="\nThis is "PACKAGE" Release "VERSION" - Copyright (C) 1999-2002 by Alexander K\xC3\xB6nig";
602                 char about_rest[]="\n\nSend comments, patches and scratches to: alex@lisas.de\n"
603                 "terminatorX-homepage: http://www.terminatorX.cx\n\nThis binary has been compiled with the following flags: "
604                 "Sox support: "
605 #ifdef USE_SOX_INPUT
606                 "ON"
607 #else
608                 "OFF"
609 #endif          
610                 " - mpg123 support: "
611 #ifdef USE_MPG123_INPUT
612                 "ON"
613 #else
614                 "OFF"
615 #endif
616                 " - \nogg123 support: "
617 #ifdef USE_OGG123_INPUT
618                 "ON"
619 #else
620                 "OFF"
621 #endif
622
623                 " - 3DNow!: "
624 #ifdef USE_3DNOW
625                 "ON"
626 #else
627                 "OFF"
628 #endif
629                 
630                 " - enhanced scheduling: "
631 #ifdef USE_SCHEDULER
632                 "ON"
633 #else
634                 "OFF"
635 #endif
636                 " - for a "
637 #ifdef WORDS_BIGENDIAN
638                 "big"
639                 
640 #else
641                 "little"
642 #endif
643                 " endian machine.\n";
644                 
645                 char buffer[4096];
646                 
647                 strcpy(buffer, about_prefix_umlaut);
648                 strcat(buffer, about_rest);
649                 
650                 label=gtk_label_new(buffer);
651
652                 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
653                 add_about_wid_fix(label);
654                 
655                 sep=gtk_hseparator_new();
656                 add_about_wid_fix(sep);
657
658                 label=gtk_label_new("License (GPL V2):");
659                 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
660                 add_about_wid_fix(label);
661
662                 hbox=gtk_hbox_new(FALSE, 5);            
663
664                 GtkTextIter iter;
665                 GtkTextBuffer *tbuffer;
666
667                 text=gtk_text_view_new();
668                 tbuffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
669                 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_NONE);
670                 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), false);
671                 gtk_text_buffer_get_iter_at_offset (tbuffer, &iter, 0);
672                 
673                 scroll=gtk_scrolled_window_new (NULL, NULL);
674                 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
675                 gtk_container_add (GTK_CONTAINER (scroll), text);
676                 gtk_text_buffer_create_tag (tbuffer, "courier", "family", "courier", NULL);
677                 
678                 gtk_text_buffer_insert_with_tags_by_name(tbuffer, &iter, license, -1, "courier", NULL);
679                 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 5);
680                 gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text), 5);
681                 gtk_widget_set_usize(GTK_WIDGET(text), 640, 180);
682                 gtk_widget_show(text);          
683                 
684                 gtk_box_pack_start(GTK_BOX(hbox), scroll, WID_DYN);
685                 gtk_widget_show(scroll);                
686                 
687                 add_about_wid(hbox);
688
689                 sep=gtk_hseparator_new();
690                 add_about_wid_fix(sep);
691
692                 btn=gtk_button_new_with_label("Close");
693                 add_about_wid_fix(btn);
694
695                 gtk_container_add(GTK_CONTAINER(window), box);
696                 gtk_widget_show(box);
697                 
698                 gtk_signal_connect(GTK_OBJECT(btn), "clicked", (GtkSignalFunc) destroy_about, NULL);            
699                 gtk_signal_connect(GTK_OBJECT(window), "delete-event", (GtkSignalFunc) destroy_about, NULL);            
700         }
701         gtk_widget_show(window);
702         tX_set_icon(window, "tX About");
703         
704         about=window;
705 }
706
707 GdkBitmap *tX_icon_mask=NULL;
708 GdkPixmap *tX_icon_pmap=NULL;
709 GtkWidget *tX_icon_widget=NULL;
710
711 void tX_set_icon(GtkWidget *widget, char *name)
712 {
713         GtkStyle *style;
714
715         style = gtk_widget_get_style( widget );
716
717         if (!tX_icon_pmap)
718         {
719                 tX_icon_pmap=gdk_pixmap_create_from_xpm_d(widget->window, &tX_icon_mask, &style->bg[GTK_STATE_NORMAL], (gchar **) tX_icon_xpm );
720                 //tX_icon_widget = gtk_pixmap_new( tX_icon_pmap, tX_icon_mask );                
721                 //gtk_widget_realize(tX_icon_widget);           
722         }
723
724         gdk_window_set_icon(widget->window, NULL, tX_icon_pmap, tX_icon_mask);
725         gdk_window_set_icon_name(widget->window, name); 
726 }