fix --help output to be proper UTF-8
[clawsker.git] / clawsker
1 #!/usr/bin/perl -w
2 #
3 # Clawsker :: A Claws Mail Tweaker
4 #
5 use strict;
6 use encoding 'utf8';
7 use Glib qw(TRUE FALSE);
8 use Gtk2 -init;
9 use POSIX qw(setlocale);
10 use Locale::gettext;
11 use Encode;
12
13 my $NAME = 'clawsker';
14 my $PREFIX = '@PREFIX@';
15 my $LIBDIR = '@LIBDIR@';
16 my $VERSION = '@VERSION@';
17 my $VERBOSE = FALSE;
18 my $CLAWSV = undef;
19 my $main_window = undef;
20
21 my $locale = (defined($ENV{LC_MESSAGES}) ? $ENV{LC_MESSAGES} : $ENV{LANG});
22 $locale = "C" unless defined($locale);
23 setlocale (LC_ALL, $locale);
24 bindtextdomain ($NAME, sprintf ('%s/share/locale', $PREFIX));
25 textdomain ($NAME);
26
27 my $SHOWHINTS = FALSE;
28 $SHOWHINTS = TRUE if ($Gtk2::VERSION >= 1.040 and Gtk2->CHECK_VERSION (2, 12, 0));
29
30 sub _ {
31     my $str = shift;
32     my %par = @_;
33     my $xla = gettext ($str);
34     if (scalar(keys(%par)) > 0) {
35         foreach my $key (keys %par) {
36             $xla =~ s/\{$key\}/$par{$key}/g;
37         }
38     }
39     return decode_utf8($xla);
40 }
41
42 # default messages
43 %xl::s = (
44     win_title => _('Claws Mail Hidden Preferences'),
45     about => _('About...'),
46     about_title => _('Clawsker :: A Claws Mail Tweaker'),
47     about_license => _('License:'),
48     about_version => _('Version:'),
49
50     tab_colours => _('Colours'),
51     tab_behaviour => _('Behaviour'),
52     tab_gui => _('GUI'),
53     tab_other => _('Other'),
54     tab_winpos => _('Windows'),
55
56     ab_frame => _('Addressbook'),
57     mem_frame => _('Memory'),
58     msgview_frame => _('Message View'),
59     log_frame => _('Log window'),
60     dnd_frame => _('Drag \'n\' drop'),
61     ssl_frame => _('Secure Sockets Layer'),
62     msgs_frame => _('Messages'),
63     stripes_frame => _('Coloured stripes'),
64     sbar_frame => _('Scroll bars'),
65     mlist_frame => _('Message List'),
66     mview_frame => _('Message View'),
67     compo_frame => _('Compose window'),
68     netm_frame => _('NetworkManager'),
69
70     l_oth_use_dlg => _('Use detached address book edit dialogue'),
71     h_oth_use_dlg => _('If true use a separate dialogue to edit a person\'s details. Otherwise will use a form embedded in the address book\'s main window.'),
72     l_oth_max_use => _('Maximum memory for message cache (kB)'),
73     h_oth_max_use => _('The maximum amount of memory to use to cache messages, in kilobytes.'),
74     l_oth_min_time => _('Minimun time for cache elements (minutes)'),
75     h_oth_min_time => _('The minimum time in minutes to keep a cache in memory. Caches more recent than this time will not be freed, even if the memory usage is too high.'),
76     l_oth_use_netm => _('Use NetworkManager'),
77     h_oth_use_netm => _('Use NetworkManager to switch offline automatically.'),
78     
79     l_gui_b_unread => _('Show unread messages with bold font'),
80     h_gui_b_unread => _('Show unread messages in the Message List using a bold font.'),
81     l_gui_no_markup => _('Don\'t use markup in compose window'),
82     h_gui_no_markup => _('Don\'t use bold and italic text in Compose dialogue\'s account selector.'),
83     l_gui_dot_lines => _('Use dotted lines in tree view components'),
84     h_gui_dot_lines => _('Use the old dotted line look in the main window tree views (Folder, Message and other lists) instead of the modern lineless look.'),
85     l_gui_h_scroll => _('Enable horizontal scrollbar'),
86     h_gui_h_scroll => _('Enable the horizontal scrollbar in the Message List.'),
87     l_gui_swp_from => _('Display To column instead From column in Sent folder'),
88     h_gui_swp_from => _('Display the recipient\'s email address in a To column of the Sent folder instead of the originator\'s one in a From column.'),
89     l_gui_v_scroll => _('Folder List scrollbar behaviour'),
90     h_gui_v_scroll => _('Specify the policy of vertical scrollbar of Folder List: show always, automatic or hide always.'),
91     l_gui_v_scroll_show => _('Show always'),
92     l_gui_v_scroll_auto => _('Automatic'),
93     l_gui_v_scroll_hide => _('Hide always'),
94     l_gui_from_show => _('From column displays'),
95     h_gui_from_show => _('Selects the data displayed in the From column of the Message List: name, address or both'),
96     l_gui_from_show_name => _('Name only'),
97     l_gui_from_show_addr => _('Address only'),
98     l_gui_from_show_both => _('Both name and address'),
99     l_gui_strip_off => _('Coloured lines contrast'),
100     h_gui_strip_off => _('Specify the value to use when creating alternately coloured lines in tree view components. The smaller the value, the less visible the difference in the alternating colours of the lines.'),
101     l_gui_cursor_v => _('Show cursor'),
102     h_gui_cursor_v => _('Display the cursor in the Message View.'),
103     l_gui_toolbar_d => _('Detachable toolbars'),
104     h_gui_toolbar_d => _('Show handles in the toolbars.'),
105     l_gui_strip_all => _('Use stripes in all tree view components'),
106     h_gui_strip_all => _('Enable alternately coloured lines in all tree view components.'),
107     l_gui_strip_sum => _('Use stripes in Folder List and Message List'),
108     h_gui_strip_sum => _('Enable alternately coloured lines in Message List and Folder List.'),
109     l_gui_two_line_v => _('2 lines per Message List item in 3-column layout'),
110     h_gui_two_line_v => _('Spread Message List information over two lines when using the three column mode.'),
111     l_gui_margin_co => _('Show compose margin'),
112     h_gui_margin_co => _('Shows a small margin in the Compose View.'),
113     l_gui_mview_date => _('Don\'t display localized date'),
114     h_gui_mview_date => _('Toggles localization of date format in Message View'),
115
116     l_beh_hover_t => _('Drag \'n\' drop hover timeout (ms)'),
117     h_beh_hover_t => _('Time in milliseconds that will cause a folder tree to expand when the mouse cursor is held over it during drag and drop.'),
118     l_beh_dangerous => _('Don\'t confirm deletions (dangerous!)'),
119     h_beh_dangerous => _('Don\'t ask for confirmation before definitive deletion of emails.'),
120     l_beh_flowed => _('Respect format=flowed in messages'),
121     h_beh_flowed => _('Respect format=flowed on text/plain message parts. This will cause some mails to have long lines, but will fix some URLs that would otherwise be wrapped.'),
122     l_beh_parts_rw => _('Allow writable temporary files'),
123     h_beh_parts_rw => _('Saves temporary files when opening attachment with write bit set.'),
124     l_beh_skip_ssl => _('Don\'t check SSL certificates'),
125     h_beh_skip_ssl => _('Disables the verification of SSL certificates.'),
126     l_beh_up_step => _('Progress bar update step (items)'),
127     h_beh_up_step => _('Update stepping in progress bars.'),
128     l_beh_thread_a => _('Maximum age when threading by subject (days)'),
129     h_beh_thread_a => _('Number of days to include a message in a thread when using "Thread using subject in addition to standard headers".'),
130     l_beh_unsafe_ssl => _('Allow unsafe SSL certificates'),
131     h_beh_unsafe_ssl => _('Allows Claws Mail to remember multiple SSL certificates for a given server/port.'),
132     l_beh_use_utf8 => _('Force UTF-8 for broken mails'),
133     h_beh_use_utf8 => _('Use UTF-8 encoding for broken mails instead of current locale.'),
134     l_beh_warn_dnd => _('Warn on drag \'n\' drop'),
135     h_beh_warn_dnd => _('Display a confirmation dialogue on drag \'n\' drop of folders.'),
136     l_beh_out_ascii => _('Outgoing messages fallback to ASCII'),
137     h_beh_out_ascii => _('If content allows, ASCII will be used to encode outgoing messages, otherwise the user-defined encoding is enforced always.'),
138     l_beh_pp_unsel => _('Primary paste unselects selection'),
139     h_beh_pp_unsel => _('Controls how pasting using middle-click changes the selected text and insertion point.'),
140     l_beh_inline_at => _('Show inline attachments'),
141     h_beh_inline_at => _('Allows hiding inline attachments already shown in mail structure view'),
142
143     l_col_emphasis => _('X-Mailer header'),
144     h_col_emphasis => _('The colour used for the X-Mailer line when its value is Claws Mail.'),
145     l_col_log_err => _('Error messages'),
146     h_col_log_err => _('Colour for error messages in log window.'),
147     l_col_log_in => _('Server messages'),
148     h_col_log_in => _('Colour for messages received from servers in log window.'),
149     l_col_log_msg => _('Standard messages'),
150     h_col_log_msg => _('Colour for messages in log window.'),
151     l_col_log_out => _('Client messages'),
152     h_col_log_out => _('Colour for messages sent to servers in log window.'),
153     l_col_log_warn => _('Warnings'),
154     h_col_log_warn => _('Colour for warning messages in log window.'),
155
156     l_win_x => _('X position'),
157     h_win_x => _('X coordinate for window\'s top-left corner.'),
158     l_win_y => _('Y position'),
159     h_win_y => _('Y coordinate for window\'s top-left corner.'),
160     l_win_w => _('Width'),
161     h_win_w => _('Window\'s width in pixels.'),
162     l_win_h => _('Height'),
163     h_win_h => _('Window\'s height in pixels.'),
164
165     l_win_main_mx => _('Maximized'),
166     h_win_main_mx => _('Changes window maximized status.'),
167     l_win_main_fs => _('Full-screen'),
168     h_win_main_fs => _('Changes full screen status.'),
169
170     e_error => _('Error: '),
171     e_noclawsrc => _('resource file for Claws Mail was not found.'),
172     e_running => _('seems Claws Mail is currently running, close it first.'),
173     e_requireddir => _('option requires a directory name.'),
174     e_requiredfile => _('option requires a file name.'),
175     e_notadir => _('specified name is not a directory or does not exist.'),
176     e_notafile => _('specified name is not a file or does not exist.'),
177 );
178
179 # all preferences read by load_preferences
180 my %PREFS = ();
181 # values of all preferences handled by clawsker
182 my %HPVALUE = ();
183 # default config dir and file name
184 my $ALTCONFIGDIR = FALSE;
185 my $CONFIGDIR = $ENV{HOME} . '/.claws-mail/';
186 my $CONFIGRC = 'clawsrc';
187
188 # index constants for preference arrays
189 use constant NAME  => 0; # the name on the rc file
190 use constant LABEL => 1; # the label on the GUI
191 use constant DESC  => 2; # the description for the hint/help
192 use constant TYPE  => 3; # data type: bool, int, float, string, color
193 use constant CMVER => 4; # lowest Claws Mail version the feature exists
194 use constant CMDEF => 5; # default value for the preference in Claws Mail
195 use constant GUI   => 6; # GUI element
196
197 # constants for GUI spacing
198 use constant HBOX_SPC => 5;
199 use constant FRAME_SPC => 2;
200 use constant PAGE_SPC => 5;
201
202 # version functions
203
204 sub version_greater_or_equal() {
205     my ($version, $refvers) = @_;
206     my @version = split (/\./, $version);
207     my @refvers = split (/\./, $refvers);
208     while ($#version < $#refvers) {
209         push (@version, '0');
210     }
211     my $idx = 0;
212     while (($idx <= $#refvers) 
213             and (int ($version[$idx]) == int ($refvers[$idx]))) {
214         ++$idx;
215     }
216     return TRUE if (($idx > $#refvers)
217         or (int ($version[$idx]) >= int ($refvers[$idx])));
218     return FALSE;
219 }
220
221 sub get_claws_version() {
222     my @cmbin = (
223         'claws-mail',
224     );
225     my $res = "";
226     foreach my $bin (@cmbin) {
227         $_ = qx/which $bin/;
228         chomp;
229         last if ($_ ne "");
230     }
231     return "" unless ($_); # not installed
232     $_ = qx/$_ -v/;
233     chomp;
234     my @fver = split (/ /);
235     die "Invalid version string" unless ($fver[2] eq "version");
236     my @ver = split (/\./, $fver[3]);
237     $res .= "$ver[0].";
238     $res .= "$ver[1].";
239     if ($ver[2] =~ /(\d+)cvs(\d+)/) {
240         $res .= "$1.$2";
241     }
242     else {
243         $res .= "$ver[2].0";
244     }
245     return $res;
246 }
247
248 # data handlers and auxiliar functions
249
250 sub handle_bool_value {
251     my ($widget, $event, $dataref) = @_;
252     $$dataref = ($widget->get_active ())? '1': '0';
253 }
254
255 sub handle_int_value {
256     my ($widget, $event, $dataref) = @_;
257     $_ = $widget->get_text ();
258     s/^\s+//;
259     s/\s+$//;
260     if (/^[0-9]+$/) {
261         $$dataref = $_;
262         $widget->set_text ($_);
263     }
264     else {
265         $widget->set_text ($$dataref);
266     }
267 }
268
269 sub handle_string_value {
270     my ($widget, $event, $dataref) = @_;
271     $$dataref = $widget->get_text ();
272 }
273
274 sub gdk_color_from_str {
275     my ($str) = @_;
276     my ($rr, $gg, $bb) = (0, 0 ,0);
277     $_ = uc ($str);
278     if (/\#([A-F0-9][A-F0-9])([A-F0-9][A-F0-9])([A-F0-9][A-F0-9])/) {
279         $rr = hex($1) * 256;
280         $gg = hex($2) * 256; 
281         $bb = hex($3) * 256;
282     }
283     my $color = Gtk2::Gdk::Color->new ($rr, $gg, $bb);
284     return $color;
285 }
286
287 sub str_from_gdk_color {
288     my ($color) = @_;
289     my $rr = $color->red / 256;
290     my $gg = $color->green / 256;
291     my $bb = $color->blue / 256;
292     my $str = sprintf ("#%.2x%.2x%.2x", $rr, $gg, $bb);
293     return $str;
294 }
295
296 sub handle_color_value {
297     my ($widget, $event, $dataref) = @_;
298     my $newcol = $widget->get_color;
299     $$dataref = &str_from_gdk_color ($newcol);
300 }
301
302 sub handle_selection_value {
303     my ($widget, $event, $dataref) = @_;
304     $$dataref = $widget->get_active;
305 }
306
307 sub get_rc_filename {
308     return $CONFIGDIR . $CONFIGRC;
309 }
310
311 sub set_rc_filename {
312     my ($fullname) = @_;
313     my @parts = split ('/', $fullname);
314     $CONFIGRC = $parts[$#parts];
315     $parts[$#parts] = '';
316     $CONFIGDIR = join ('/', @parts);
317 }
318
319 sub log_message {
320     my ($mesg, $fatal) = @_;
321     if (defined($fatal) && $fatal eq 'die') {
322         die "$NAME: $mesg\n";
323     }
324     if ($VERBOSE) {
325         print "$NAME: $mesg\n";
326     }
327 }
328
329 sub error_dialog {
330     my ($emsg) = @_;
331     my $markup = "<span weight=\"bold\" size=\"large\">" . $emsg . "</span>";
332     my $errordlg = Gtk2::MessageDialog->new_with_markup ($main_window, 'modal', 'error', 'cancel', $markup);
333     $errordlg->set_title (_('Error message'));
334     $errordlg->run;
335     $errordlg->destroy;
336 }
337
338 sub check_claws_not_running() {
339     my $socket = (not $ALTCONFIGDIR)? "/tmp/": $CONFIGDIR;
340     $socket .= "claws-mail-$<";
341     -S $socket and do {
342         my $emsg = "$xl::s{e_error}$xl::s{e_running}";
343         log_message ($emsg);
344         error_dialog ($emsg);
345         return FALSE;
346      };
347      return TRUE;
348 }
349
350 sub check_rc_file() {
351     my ($rcfile) = @_;
352     (defined($rcfile) && -f $rcfile) or do {
353        my $emsg = "$xl::s{e_error}$xl::s{e_noclawsrc}\n";
354         log_message ($emsg);
355         error_dialog ($emsg);
356         return FALSE;
357     };
358     return TRUE;
359 }
360
361 sub set_widget_hint() {
362     if ($SHOWHINTS) {
363         my ($wdgt, $hint) = @_;    
364         $wdgt->set_tooltip_text ($hint);
365         $wdgt->set_has_tooltip (TRUE);
366     }
367 }
368
369 sub set_widget_sens() {
370     my ($wdgt, $minver) = @_;
371     $wdgt->set_sensitive (&version_greater_or_equal ($CLAWSV, $minver));
372 }
373
374 # graphic element creation 
375
376 sub new_check_button_for {
377     my ($hash, $key) = @_;
378     my $name = $$hash{$key}[NAME];
379     my $label = $$hash{$key}[LABEL];
380     #
381     my $hbox = Gtk2::HBox->new (FALSE, 5);
382     my $cb = Gtk2::CheckButton->new ($label);
383     $$hash{$key}[GUI] = $cb;
384     if (defined ($HPVALUE{$name})) {
385         $cb->set_active ($HPVALUE{$name} eq '1');
386     }
387     $cb->signal_connect (clicked => sub {
388             my ($w, $e) = @_;
389             &handle_bool_value($w, $e, \$HPVALUE{$name});
390         });
391     &set_widget_hint ($cb, $$hash{$key}[DESC]);
392     &set_widget_sens ($cb, $$hash{$key}[CMVER]);
393     $hbox->pack_start ($cb, FALSE, FALSE, HBOX_SPC);
394     #
395     return $hbox;
396 }
397
398 sub new_text_box_for_int {
399     my ($hash, $key) = @_;
400     my $name = $$hash{$key}[NAME];
401     my $label = $$hash{$key}[LABEL];
402     my @type = split (/,/, $$hash{$key}[TYPE]);
403     push (@type, 0), push (@type, 10000) unless ($#type > 0); 
404     #
405     my $hbox = Gtk2::HBox->new (FALSE, 5);
406     my $glabel = Gtk2::Label->new ($label);
407     my $pagei = int (($type[2] - $type[1]) / 10);
408     my $gentry = Gtk2::SpinButton->new_with_range ($type[1], $type[2], $pagei);
409     $gentry->set_numeric (TRUE);
410     $gentry->set_value ($HPVALUE{$name});
411     $$hash{$key}[GUI] = $gentry;
412     $gentry->signal_connect('value-changed' => sub {
413             my ($w, $e) = @_;
414             &handle_int_value($w, $e, \$HPVALUE{$name});
415         });
416     &set_widget_hint ($gentry, $$hash{$key}[DESC]);
417     &set_widget_sens ($gentry, $$hash{$key}[CMVER]);
418     $glabel->set_sensitive ($gentry->sensitive);
419     $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
420     $hbox->pack_start ($gentry, FALSE, FALSE, HBOX_SPC);
421     #
422     return $hbox;
423 }
424
425 sub new_color_button_for {
426     my ($hash, $key) = @_;
427     my $name = $$hash{$key}[NAME];
428     my $label = $$hash{$key}[LABEL];
429     #
430     my $col = &gdk_color_from_str ($HPVALUE{$name});
431     my $hbox = Gtk2::HBox->new (FALSE, 5);
432     my $glabel = Gtk2::Label->new ($label);
433     my $button = Gtk2::ColorButton->new_with_color ($col);
434     $$hash{$key}[GUI] = $button;
435     $button->set_title ($label);
436     $button->set_relief ('none');
437     $button->signal_connect ('color-set' => sub {
438             my ($w, $e) = @_;
439             &handle_color_value($w, $e, \$HPVALUE{$name}); 
440         });
441     &set_widget_hint ($button, $$hash{$key}[DESC]);
442     &set_widget_sens ($button, $$hash{$key}[CMVER]);
443     $glabel->set_sensitive ($button->sensitive);
444     $hbox->pack_start ($button, FALSE, FALSE, HBOX_SPC);
445     $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
446     #
447     return $hbox;
448 }
449
450 sub new_selection_box_for {
451     my ($hash, $key) = @_;
452     my $name = $$hash{$key}[NAME];
453     my $label = $$hash{$key}[LABEL];
454     #
455     my $hbox = Gtk2::HBox->new (FALSE, 5);
456     my $glabel = Gtk2::Label->new ($label);
457     my $combo = Gtk2::ComboBox->new_text;
458     $$hash{$key}[GUI] = $combo;
459     my @options = split (';', $$hash{$key}[TYPE]);
460     foreach my $opt (@options) {
461         my ($index, $textkey) = split ('=', $opt);
462         $combo->insert_text ($index, $xl::s{$textkey});
463     }
464     $combo->signal_connect ('changed' => sub {
465             my ($w, $e) = @_;
466             &handle_selection_value($w, $e, \$HPVALUE{$name});
467         });
468     $combo->set_active ($HPVALUE{$name});
469     &set_widget_hint ($combo, $$hash{$key}[DESC]);
470     &set_widget_sens ($combo, $$hash{$key}[CMVER]);
471     $glabel->set_sensitive ($combo->sensitive);
472     $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
473     $hbox->pack_start ($combo, FALSE, FALSE, HBOX_SPC);
474     #
475     return $hbox;
476 }
477
478 # more graphic helpers
479
480 sub new_hbox_pack() {
481     my $hbox = Gtk2::HBox->new (FALSE, 5);
482     $hbox->set_border_width (PAGE_SPC);
483     foreach my $item (@_) {
484         $hbox->pack_start ($item, FALSE, FALSE, 0);
485     }
486     return $hbox;
487 }    
488
489 sub new_vbox_pack() {
490     my $vbox = Gtk2::VBox->new (FALSE, 5);
491     $vbox->set_border_width (PAGE_SPC);
492     foreach my $item (@_) {
493         $vbox->pack_start ($item, FALSE, FALSE, 0);
494     }
495     return $vbox;
496 }    
497
498 sub new_vbox_pack_compact() {
499     my $vbox = Gtk2::VBox->new (FALSE, 0);
500     $vbox->set_border_width (0);
501     foreach my $item (@_) {
502         $vbox->pack_start ($item, FALSE, FALSE, 0);
503     }
504     return $vbox;
505 }    
506
507 sub new_subpage_frame () {
508     my ($box, $title, $notpacked) = @_;
509     my $frame = Gtk2::Frame->new ($title);
510     $frame->add ($box);    
511     return &new_vbox_pack ($frame) unless defined ($notpacked);
512     return $frame;
513 }
514
515 # preference maps and corresponding page creation subs
516
517 %pr::oth = ( # other preferences
518     use_dlg => [ 
519         'addressbook_use_editaddress_dialog',
520         $xl::s{l_oth_use_dlg},
521         $xl::s{h_oth_use_dlg},
522         'bool',
523         '2.7.0',
524         '0',
525         undef,
526     ],
527     max_use => [
528         'cache_max_mem_usage',
529         $xl::s{l_oth_max_use},
530         $xl::s{h_oth_max_use},
531         'int,0,262144', # 0 Kb - 256 Mb
532         '0.0.0',
533         '4096',
534         undef,
535     ],
536     min_time => [
537         'cache_min_keep_time',
538         $xl::s{l_oth_min_time},
539         $xl::s{h_oth_min_time},
540         'int,0,120', # 0 minutes - 2 hours
541         '0.0.0',
542         '15',
543         undef,
544     ],
545     use_netm => [
546         'use_networkmanager',
547         $xl::s{l_oth_use_netm},
548         $xl::s{h_oth_use_netm},
549         'bool',
550         '3.3.1',
551         '1',
552         undef,
553     ],
554 );
555
556 sub new_other_page() {
557     return &new_vbox_pack (
558                &new_subpage_frame (
559                    &new_vbox_pack (
560                        &new_check_button_for(\%pr::oth, 'use_dlg')),
561                    $xl::s{ab_frame}, 'not-packed'),
562                &new_subpage_frame (
563                    &new_vbox_pack (
564                        &new_text_box_for_int(\%pr::oth, 'max_use'),
565                        &new_text_box_for_int(\%pr::oth, 'min_time')),
566                    $xl::s{mem_frame}, 'not-packed'),
567                &new_subpage_frame (
568                    &new_vbox_pack (
569                        &new_check_button_for(\%pr::oth, 'use_netm')),
570                    $xl::s{netm_frame}, 'not-packed')
571            );
572 }
573
574 %pr::gui = ( # gui bells and whistles
575     b_unread => [ 
576         'bold_unread',
577         $xl::s{l_gui_b_unread},
578         $xl::s{h_gui_b_unread},
579         'bool',
580         '0.0.0',
581         '1',
582         undef,
583     ],
584     no_markup => [
585         'compose_no_markup',
586         $xl::s{l_gui_no_markup},
587         $xl::s{h_gui_no_markup},
588         'bool',
589         '0.0.0',
590         '0',
591         undef,
592     ],
593     dot_lines => [
594         'enable_dotted_lines',
595         $xl::s{l_gui_dot_lines},
596         $xl::s{h_gui_dot_lines},
597         'bool',
598         '0.0.0',
599         '0',
600         undef,
601     ],
602     h_scroll => [
603         'enable_hscrollbar',
604         $xl::s{l_gui_h_scroll},
605         $xl::s{h_gui_h_scroll},
606         'bool',
607         '0.0.0',
608         '1',
609         undef,
610     ],
611     swp_from => [
612         'enable_swap_from',
613         $xl::s{l_gui_swp_from},
614         $xl::s{h_gui_swp_from},
615         'bool',
616         '0.0.0',
617         '0',
618         undef,
619     ],
620     v_scroll => [
621         'folderview_vscrollbar_policy',
622         $xl::s{l_gui_v_scroll},
623         $xl::s{h_gui_v_scroll},
624         '0=l_gui_v_scroll_show;1=l_gui_v_scroll_auto;2=l_gui_v_scroll_hide',
625         '0.0.0',
626         '0',
627         undef,
628     ],
629     from_show => [
630         'summary_from_show',
631         $xl::s{l_gui_from_show},
632         $xl::s{h_gui_from_show},
633         '0=l_gui_from_show_name;1=l_gui_from_show_addr;2=l_gui_from_show_both',
634         '3.7.10',
635         '0',
636         undef,
637     ],
638     strip_off => [
639         'stripes_color_offset',
640         $xl::s{l_gui_strip_off},
641         $xl::s{h_gui_strip_off},
642         'int,0,40000', # no idea what this number means
643         '0.0.0',
644         '4000',
645         undef,
646     ],
647     cursor_v => [
648         'textview_cursor_visible',
649         $xl::s{l_gui_cursor_v},
650         $xl::s{h_gui_cursor_v},
651         'bool',
652         '0.0.0',
653         '0',
654         undef,
655     ],
656     toolbar_d => [
657         'toolbar_detachable',
658         $xl::s{l_gui_toolbar_d},
659         $xl::s{h_gui_toolbar_d},
660         'bool',
661         '0.0.0',
662         '0',
663         undef,
664     ],
665     strip_all => [
666         'use_stripes_everywhere',
667         $xl::s{l_gui_strip_all},
668         $xl::s{h_gui_strip_all},
669         'bool',
670         '0.0.0',
671         '1',
672         undef,
673     ],
674     strip_sum => [
675         'use_stripes_in_summaries',
676         $xl::s{l_gui_strip_sum},
677         $xl::s{h_gui_strip_sum},
678         'bool',
679         '0.0.0',
680         '1',
681         undef,
682     ],
683     two_linev => [
684         'two_line_vertical',
685         $xl::s{l_gui_two_line_v},
686         $xl::s{h_gui_two_line_v},
687         'bool',
688         '3.4.0.7',
689         '0',
690         undef,
691     ],
692     margin_co => [
693         'show_compose_margin',
694         $xl::s{l_gui_margin_co},
695         $xl::s{h_gui_margin_co},
696         'bool',
697         '3.7.6.7',
698         '0',
699         undef,
700     ],
701     mview_date => [
702         'msgview_date_format',
703         $xl::s{l_gui_mview_date},
704         $xl::s{h_gui_mview_date},
705         'bool',
706         '3.7.8.42',
707         '0',
708         undef,
709     ],
710 );
711
712 sub new_gui_page() {
713     my $gf = Gtk2::VBox->new (FALSE, 5);
714     $gf->set_border_width (PAGE_SPC);
715
716     my $cb_dot_lines = &new_check_button_for (\%pr::gui, 'dot_lines'); 
717     my $cb_toolbar_d = &new_check_button_for (\%pr::gui, 'toolbar_d');
718
719     $gf->pack_start (&new_subpage_frame (
720                          &new_vbox_pack (
721                              &new_check_button_for (\%pr::gui, 'strip_all'),
722                              &new_check_button_for (\%pr::gui, 'strip_sum'),
723                              &new_text_box_for_int (\%pr::gui, 'strip_off')),
724                          $xl::s{stripes_frame}, 'not-packed'),
725                      FALSE, FALSE, FRAME_SPC);
726     $gf->pack_start (&new_subpage_frame (
727                          &new_vbox_pack (
728                              &new_check_button_for (\%pr::gui, 'b_unread'),
729                              &new_check_button_for (\%pr::gui, 'swp_from'),
730                              &new_check_button_for (\%pr::gui, 'two_linev'),
731                              &new_selection_box_for (\%pr::gui, 'from_show')),
732                          $xl::s{mlist_frame}, 'not-packed'), 
733                      FALSE, FALSE, FRAME_SPC);
734     $gf->pack_start (&new_subpage_frame (
735                          &new_hbox_pack (
736                              &new_check_button_for (\%pr::gui, 'cursor_v'),
737                              &new_check_button_for (\%pr::gui, 'mview_date')),
738                          $xl::s{mview_frame}, 'not-packed'), 
739                      FALSE, FALSE, FRAME_SPC);
740     $gf->pack_start (&new_subpage_frame (
741                          &new_hbox_pack (
742                              &new_check_button_for (\%pr::gui, 'no_markup'),
743                              &new_check_button_for (\%pr::gui, 'margin_co')),
744                          $xl::s{compo_frame}, 'not-packed'), 
745                      FALSE, FALSE, FRAME_SPC);
746     $gf->pack_start ($cb_dot_lines, FALSE, FALSE, 0);
747     $gf->pack_start ($cb_toolbar_d, FALSE, FALSE, 0);
748     $gf->pack_start (&new_subpage_frame (
749                          &new_vbox_pack (
750                              &new_check_button_for (\%pr::gui, 'h_scroll'),
751                              &new_selection_box_for (\%pr::gui, 'v_scroll')),
752                          $xl::s{sbar_frame}, 'not-packed'),
753                      FALSE, FALSE, FRAME_SPC);
754
755     return $gf;
756 }
757
758 %pr::beh = ( # tweak some behaviour
759     hover_t => [
760         'hover_timeout',
761         $xl::s{l_beh_hover_t},
762         $xl::s{h_beh_hover_t},
763         'int,100,3000', # 0.1 seconds - 3 seconds
764         '0.0.0',
765         '500',
766         undef,
767     ],
768     dangerous => [
769         'live_dangerously',
770         $xl::s{l_beh_dangerous},
771         $xl::s{h_beh_dangerous},
772         'bool',
773         '0.0.0',
774         '0',
775         undef,
776     ],
777     flowed => [
778         'respect_flowed_format',
779         $xl::s{l_beh_flowed},
780         $xl::s{h_beh_flowed},
781         'bool',
782         '0.0.0',
783         '0',
784         undef,
785     ],
786     parts_rw => [
787         'save_parts_readwrite',
788         $xl::s{l_beh_parts_rw},
789         $xl::s{h_beh_parts_rw},
790         'bool',
791         '0.0.0',
792         '0',
793         undef,
794     ],
795     skip_ssl => [
796         'skip_ssl_cert_check',
797         $xl::s{l_beh_skip_ssl},
798         $xl::s{h_beh_skip_ssl},
799         'bool',
800         '0.0.0',
801         '0',
802         undef,
803     ],
804     up_step => [
805         'statusbar_update_step',
806         $xl::s{l_beh_up_step},
807         $xl::s{h_beh_up_step},
808         'int,1,200', # 1 item - 200 items
809         '0.0.0',
810         '10',
811         undef,
812     ],
813     thread_a => [
814         'thread_by_subject_max_age',
815         $xl::s{l_beh_thread_a},
816         $xl::s{h_beh_thread_a},
817         'int,1,30', # 1 day - 30 days
818         '0.0.0',
819         '10',
820         undef,
821     ],
822     unsafe_ssl => [
823         'unsafe_ssl_certs',
824         $xl::s{l_beh_unsafe_ssl},
825         $xl::s{h_beh_unsafe_ssl},
826         'bool',
827         '0.0.0',
828         '0',
829         undef,
830     ],
831     use_utf8 => [
832         'utf8_instead_of_locale_for_broken_mail',
833         $xl::s{l_beh_use_utf8},
834         $xl::s{h_beh_use_utf8},
835         'bool',
836         '0.0.0',
837         '0',
838         undef,
839     ],
840     warn_dnd => [
841         'warn_dnd',
842         $xl::s{l_beh_warn_dnd},
843         $xl::s{h_beh_warn_dnd},
844         'bool',
845         '0.0.0',
846         '1',
847         undef,
848     ],
849     out_ascii => [
850         'outgoing_fallback_to_ascii',
851         $xl::s{l_beh_out_ascii},
852         $xl::s{h_beh_out_ascii},
853         'bool',
854         '3.4.0.37',
855         '1',
856         undef,
857     ],
858     pp_unsel => [
859         'primary_paste_unselects',
860         $xl::s{l_beh_pp_unsel},
861         $xl::s{h_beh_pp_unsel},
862         'bool',
863         '3.6.1.35',
864         '0',
865         undef,
866     ],
867     inline_at => [
868         'show_inline_attachments',
869         $xl::s{l_beh_inline_at},
870         $xl::s{h_beh_inline_at},
871         'bool',
872         '3.7.8.48',
873         '1',
874         undef,
875     ],
876 );
877
878 sub new_behaviour_page() {
879     my $bf = Gtk2::VBox->new (FALSE, 5);
880     $bf->set_border_width (PAGE_SPC);
881
882     my $tb_up_step = &new_text_box_for_int (\%pr::beh, 'up_step');
883     my $tb_thread_a = &new_text_box_for_int (\%pr::beh, 'thread_a');
884
885     $bf->pack_start (&new_subpage_frame (
886                          &new_vbox_pack (
887                              &new_text_box_for_int (\%pr::beh, 'hover_t'),
888                              &new_check_button_for (\%pr::beh, 'warn_dnd')),
889                          $xl::s{dnd_frame}, 'not-packed'), 
890                      FALSE, FALSE, FRAME_SPC);
891     $bf->pack_start (&new_subpage_frame (
892                          &new_hbox_pack (
893                              &new_check_button_for (\%pr::beh, 'skip_ssl'),
894                              &new_check_button_for (\%pr::beh, 'unsafe_ssl')),
895                          $xl::s{ssl_frame}, 'not-packed'),
896                      FALSE, FALSE, FRAME_SPC);
897     $bf->pack_start ($tb_up_step, FALSE, FALSE, 0);
898     $bf->pack_start ($tb_thread_a, FALSE, FALSE, 0);
899     $bf->pack_start (&new_subpage_frame (
900                          &new_vbox_pack (
901                              &new_check_button_for (\%pr::beh, 'flowed'),
902                              &new_check_button_for (\%pr::beh, 'parts_rw'),
903                              &new_check_button_for (\%pr::beh, 'use_utf8'),
904                              &new_check_button_for (\%pr::beh, 'dangerous'),
905                              &new_check_button_for (\%pr::beh, 'out_ascii'),
906                              &new_check_button_for (\%pr::beh, 'pp_unsel'),
907                              &new_check_button_for (\%pr::beh, 'inline_at')),
908                          $xl::s{msgs_frame}, 'not-packed'),
909                      FALSE, FALSE, FRAME_SPC);
910
911     return $bf;
912 }
913
914 %pr::col = ( # a variety of colours
915     emphasis => [
916         'emphasis_color',
917         $xl::s{l_col_emphasis},
918         $xl::s{h_col_emphasis},
919         'color',
920         '0.0.0',
921         '#0000cf',
922         undef,
923     ],
924     log_err => [
925         'log_error_color',
926         $xl::s{l_col_log_err},
927         $xl::s{h_col_log_err},
928         'color',
929         '0.0.0',
930         '#af0000',
931         undef,
932     ],
933     log_in => [
934         'log_in_color',
935         $xl::s{l_col_log_in},
936         $xl::s{h_col_log_in},
937         'color',
938         '0.0.0',
939         '#000000',
940         undef,
941     ],
942     log_msg => [
943         'log_msg_color',
944         $xl::s{l_col_log_msg},
945         $xl::s{h_col_log_msg},
946         'color',
947         '0.0.0',
948         '#00af00',
949         undef,
950     ],
951     log_out => [
952         'log_out_color',
953         $xl::s{l_col_log_out},
954         $xl::s{h_col_log_out},
955         'color',
956         '0.0.0',
957         '#0000ef',
958         undef,
959     ],
960     log_warn => [
961         'log_warn_color',
962         $xl::s{l_col_log_warn},
963         $xl::s{h_col_log_warn},
964         'color',
965         '0.0.0',
966         '#af0000',
967         undef,
968     ],
969 );
970
971 sub new_colours_page() {
972     return &new_vbox_pack (
973                &new_subpage_frame (
974                    &new_vbox_pack (
975                        &new_color_button_for (\%pr::col, 'emphasis')),
976                    $xl::s{msgview_frame}, 'not-packed'),
977                &new_subpage_frame (
978                    &new_vbox_pack (
979                        &new_color_button_for (\%pr::col, 'log_err'),
980                        &new_color_button_for (\%pr::col, 'log_in'),
981                        &new_color_button_for (\%pr::col, 'log_msg'),
982                        &new_color_button_for (\%pr::col, 'log_out'),
983                        &new_color_button_for (\%pr::col, 'log_warn')),
984                    $xl::s{log_frame}, 'not-packed')
985            );
986 }
987
988 %pr::win = ( # tweak window positions and/or sizes
989     main_x => [
990         'mainwin_x',
991         $xl::s{l_win_x},
992         $xl::s{h_win_x},
993         'int,0,3000', # 0 pixels - 3000 pixels
994         '0.0.0',
995         '16',
996         undef,
997     ],
998     main_y => [
999         'mainwin_y',
1000         $xl::s{l_win_y},
1001         $xl::s{h_win_y},
1002         'int,0,3000', # 0 pixels - 3000 pixels
1003         '0.0.0',
1004         '16',
1005         undef,
1006     ],
1007     main_w => [
1008         'mainwin_width',
1009         $xl::s{l_win_w},
1010         $xl::s{h_win_w},
1011         'int,0,3000', # 0 pixels - 3000 pixels
1012         '0.0.0',
1013         '779',
1014         undef,
1015     ],
1016     main_h => [
1017         'mainwin_height',
1018         $xl::s{l_win_h},
1019         $xl::s{h_win_h},
1020         'int,0,3000', # 0 pixels - 3000 pixels
1021         '0.0.0',
1022         '568',
1023         undef,
1024     ],
1025     main_mx => [
1026         'mainwin_maximised',
1027         $xl::s{l_win_main_mx},
1028         $xl::s{h_win_main_mx},
1029         'bool',
1030         '0.0.0',
1031         '0',
1032         undef,
1033     ],
1034     main_fs => [
1035         'mainwin_fullscreen',
1036         $xl::s{l_win_main_fs},
1037         $xl::s{h_win_main_fs},
1038         'bool',
1039         '0.0.0',
1040         '0',
1041         undef,
1042     ],
1043     msgs_x => [
1044         'main_messagewin_x',
1045         $xl::s{l_win_x},
1046         $xl::s{h_win_x},
1047         'int,0,3000', # 0 pixels - 3000 pixels
1048         '0.0.0',
1049         '256',
1050         undef,
1051     ],
1052     msgs_y => [
1053         'main_messagewin_y',
1054         $xl::s{l_win_y},
1055         $xl::s{h_win_y},
1056         'int,0,3000', # 0 pixels - 3000 pixels
1057         '0.0.0',
1058         '210',
1059         undef,
1060     ],
1061     msgs_w => [
1062         'messagewin_width',
1063         $xl::s{l_win_w},
1064         $xl::s{h_win_w},
1065         'int,0,3000', # 0 pixels - 3000 pixels
1066         '0.0.0',
1067         '600',
1068         undef,
1069     ],
1070     msgs_h => [
1071         'messagewin_height',
1072         $xl::s{l_win_h},
1073         $xl::s{h_win_h},
1074         'int,0,3000', # 0 pixels - 3000 pixels
1075         '0.0.0',
1076         '540',
1077         undef,
1078     ],
1079     send_w => [
1080         'sendwin_width',
1081         $xl::s{l_win_w},
1082         $xl::s{h_win_w},
1083         'int,0,3000', # 0 pixels - 3000 pixels
1084         '0.0.0',
1085         '460',
1086         undef,
1087     ],
1088     send_h => [
1089         'sendwin_height',
1090         $xl::s{l_win_h},
1091         $xl::s{h_win_h},
1092         'int,0,3000', # 0 pixels - 3000 pixels
1093         '0.0.0',
1094         '-1',
1095         undef,
1096     ],
1097     recv_w => [
1098         'receivewin_width',
1099         $xl::s{l_win_w},
1100         $xl::s{h_win_w},
1101         'int,0,3000', # 0 pixels - 3000 pixels
1102         '0.0.0',
1103         '460',
1104         undef,
1105     ],
1106     recv_h => [
1107         'receivewin_height',
1108         $xl::s{l_win_h},
1109         $xl::s{h_win_h},
1110         'int,0,3000', # 0 pixels - 3000 pixels
1111         '0.0.0',
1112         '-1',
1113         undef,
1114     ],
1115     fold_x => [
1116         'folderwin_x',
1117         $xl::s{l_win_x},
1118         $xl::s{h_win_x},
1119         'int,0,3000', # 0 pixels - 3000 pixels
1120         '0.0.0',
1121         '16',
1122         undef,
1123     ],
1124     fold_y => [
1125         'folderwin_y',
1126         $xl::s{l_win_y},
1127         $xl::s{h_win_y},
1128         'int,0,3000', # 0 pixels - 3000 pixels
1129         '0.0.0',
1130         '16',
1131         undef,
1132     ],
1133     fold_w => [
1134         'folderitemwin_width',
1135         $xl::s{l_win_w},
1136         $xl::s{h_win_w},
1137         'int,0,3000', # 0 pixels - 3000 pixels
1138         '0.0.0',
1139         '500',
1140         undef,
1141     ],
1142     fold_h => [
1143         'folderitemwin_height',
1144         $xl::s{l_win_h},
1145         $xl::s{h_win_h},
1146         'int,0,3000', # 0 pixels - 3000 pixels
1147         '0.0.0',
1148         '-1',
1149         undef,
1150     ],
1151     fsel_w => [
1152         'folderselwin_width',
1153         $xl::s{l_win_w},
1154         $xl::s{h_win_w},
1155         'int,0,3000', # 0 pixels - 3000 pixels
1156         '0.0.0',
1157         '300',
1158         undef,
1159     ],
1160     fsel_h => [
1161         'folderselwin_height',
1162         $xl::s{l_win_h},
1163         $xl::s{h_win_h},
1164         'int,0,3000', # 0 pixels - 3000 pixels
1165         '0.0.0',
1166         '-1',
1167         undef,
1168     ],
1169     sour_w => [
1170         'sourcewin_width',
1171         $xl::s{l_win_w},
1172         $xl::s{h_win_w},
1173         'int,0,3000', # 0 pixels - 3000 pixels
1174         '0.0.0',
1175         '600',
1176         undef,
1177     ],
1178     sour_h => [
1179         'sourcewin_height',
1180         $xl::s{l_win_h},
1181         $xl::s{h_win_h},
1182         'int,0,3000', # 0 pixels - 3000 pixels
1183         '0.0.0',
1184         '500',
1185         undef,
1186     ],
1187     addr_w => [
1188         'addressbookwin_width',
1189         $xl::s{l_win_w},
1190         $xl::s{h_win_w},
1191         'int,0,3000', # 0 pixels - 3000 pixels
1192         '0.0.0',
1193         '520',
1194         undef,
1195     ],
1196     addr_h => [
1197         'addressbookwin_height',
1198         $xl::s{l_win_h},
1199         $xl::s{h_win_h},
1200         'int,0,3000', # 0 pixels - 3000 pixels
1201         '0.0.0',
1202         '-1',
1203         undef,
1204     ],
1205     adep_w => [
1206         'addressbookeditpersonwin_width',
1207         $xl::s{l_win_w},
1208         $xl::s{h_win_w},
1209         'int,0,3000', # 0 pixels - 3000 pixels
1210         '0.0.0',
1211         '640',
1212         undef,
1213     ],
1214     adep_h => [
1215         'addressbookeditpersonwin_height',
1216         $xl::s{l_win_h},
1217         $xl::s{h_win_h},
1218         'int,0,3000', # 0 pixels - 3000 pixels
1219         '0.0.0',
1220         '320',
1221         undef,
1222     ],
1223     adeg_w => [
1224         'addressbookeditgroupwin_width',
1225         $xl::s{l_win_w},
1226         $xl::s{h_win_w},
1227         'int,0,3000', # 0 pixels - 3000 pixels
1228         '0.0.0',
1229         '580',
1230         undef,
1231     ],
1232     adeg_h => [
1233         'addressbookeditgroupwin_height',
1234         $xl::s{l_win_h},
1235         $xl::s{h_win_h},
1236         'int,0,3000', # 0 pixels - 3000 pixels
1237         '0.0.0',
1238         '340',
1239         undef,
1240     ],
1241     adda_w => [
1242         'addressaddwin_width',
1243         $xl::s{l_win_w},
1244         $xl::s{h_win_w},
1245         'int,0,3000', # 0 pixels - 3000 pixels
1246         '0.0.0',
1247         '300',
1248         undef,
1249     ],
1250     adda_h => [
1251         'addressaddwin_height',
1252         $xl::s{l_win_h},
1253         $xl::s{h_win_h},
1254         'int,0,3000', # 0 pixels - 3000 pixels
1255         '0.0.0',
1256         '-1',
1257         undef,
1258     ],
1259     addf_w => [
1260         'addressbook_folderselwin_width',
1261         $xl::s{l_win_w},
1262         $xl::s{h_win_w},
1263         'int,0,3000', # 0 pixels - 3000 pixels
1264         '0.0.0',
1265         '300',
1266         undef,
1267     ],
1268     addf_h => [
1269         'addressbook_folderselwin_height',
1270         $xl::s{l_win_h},
1271         $xl::s{h_win_h},
1272         'int,0,3000', # 0 pixels - 3000 pixels
1273         '0.0.0',
1274         '-1',
1275         undef,
1276     ],
1277     acce_w => [
1278         'editaccountwin_width',
1279         $xl::s{l_win_w},
1280         $xl::s{h_win_w},
1281         'int,0,3000', # 0 pixels - 3000 pixels
1282         '0.0.0',
1283         '500',
1284         undef,
1285     ],
1286     acce_h => [
1287         'editaccountwin_height',
1288         $xl::s{l_win_h},
1289         $xl::s{h_win_h},
1290         'int,0,3000', # 0 pixels - 3000 pixels
1291         '0.0.0',
1292         '-1',
1293         undef,
1294     ],
1295     acco_w => [
1296         'accountswin_width',
1297         $xl::s{l_win_w},
1298         $xl::s{h_win_w},
1299         'int,0,3000', # 0 pixels - 3000 pixels
1300         '0.0.0',
1301         '500',
1302         undef,
1303     ],
1304     acco_h => [
1305         'accountswin_height',
1306         $xl::s{l_win_h},
1307         $xl::s{h_win_h},
1308         'int,0,3000', # 0 pixels - 3000 pixels
1309         '0.0.0',
1310         '-1',
1311         undef,
1312     ],
1313     filt_w => [
1314         'filteringwin_width',
1315         $xl::s{l_win_w},
1316         $xl::s{h_win_w},
1317         'int,0,3000', # 0 pixels - 3000 pixels
1318         '0.0.0',
1319         '500',
1320         undef,
1321     ],
1322     filt_h => [
1323         'filteringwin_height',
1324         $xl::s{l_win_h},
1325         $xl::s{h_win_h},
1326         'int,0,3000', # 0 pixels - 3000 pixels
1327         '0.0.0',
1328         '-1',
1329         undef,
1330     ],
1331     fila_w => [
1332         'filteringactionwin_width',
1333         $xl::s{l_win_w},
1334         $xl::s{h_win_w},
1335         'int,0,3000', # 0 pixels - 3000 pixels
1336         '0.0.0',
1337         '490',
1338         undef,
1339     ],
1340     fila_h => [
1341         'filteringactionwin_height',
1342         $xl::s{l_win_h},
1343         $xl::s{h_win_h},
1344         'int,0,3000', # 0 pixels - 3000 pixels
1345         '0.0.0',
1346         '-1',
1347         undef,
1348     ],
1349     fild_w => [
1350         'filtering_debugwin_width',
1351         $xl::s{l_win_w},
1352         $xl::s{h_win_w},
1353         'int,0,3000', # 0 pixels - 3000 pixels
1354         '0.0.0',
1355         '600',
1356         undef,
1357     ],
1358     fild_h => [
1359         'filtering_debugwin_height',
1360         $xl::s{l_win_h},
1361         $xl::s{h_win_h},
1362         'int,0,3000', # 0 pixels - 3000 pixels
1363         '0.0.0',
1364         '-1',
1365         undef,
1366     ],
1367     matc_w => [
1368         'matcherwin_width',
1369         $xl::s{l_win_w},
1370         $xl::s{h_win_w},
1371         'int,0,3000', # 0 pixels - 3000 pixels
1372         '0.0.0',
1373         '520',
1374         undef,
1375     ],
1376     matc_h => [
1377         'matcherwin_height',
1378         $xl::s{l_win_h},
1379         $xl::s{h_win_h},
1380         'int,0,3000', # 0 pixels - 3000 pixels
1381         '0.0.0',
1382         '-1',
1383         undef,
1384     ],
1385     pref_w => [
1386         'prefswin_width',
1387         $xl::s{l_win_w},
1388         $xl::s{h_win_w},
1389         'int,0,3000', # 0 pixels - 3000 pixels
1390         '0.0.0',
1391         '600',
1392         undef,
1393     ],
1394     pref_h => [
1395         'prefswin_height',
1396         $xl::s{l_win_h},
1397         $xl::s{h_win_h},
1398         'int,0,3000', # 0 pixels - 3000 pixels
1399         '0.0.0',
1400         '-1',
1401         undef,
1402     ],
1403     temp_w => [
1404         'templateswin_width',
1405         $xl::s{l_win_w},
1406         $xl::s{h_win_w},
1407         'int,0,3000', # 0 pixels - 3000 pixels
1408         '0.0.0',
1409         '480',
1410         undef,
1411     ],
1412     temp_h => [
1413         'templateswin_height',
1414         $xl::s{l_win_h},
1415         $xl::s{h_win_h},
1416         'int,0,3000', # 0 pixels - 3000 pixels
1417         '0.0.0',
1418         '-1',
1419         undef,
1420     ],
1421     acti_w => [
1422         'actionswin_width',
1423         $xl::s{l_win_w},
1424         $xl::s{h_win_w},
1425         'int,0,3000', # 0 pixels - 3000 pixels
1426         '0.0.0',
1427         '486',
1428         undef,
1429     ],
1430     acti_h => [
1431         'actionswin_height',
1432         $xl::s{l_win_h},
1433         $xl::s{h_win_h},
1434         'int,0,3000', # 0 pixels - 3000 pixels
1435         '0.0.0',
1436         '-1',
1437         undef,
1438     ],
1439     tags_w => [
1440         'tagswin_width',
1441         $xl::s{l_win_w},
1442         $xl::s{h_win_w},
1443         'int,0,3000', # 0 pixels - 3000 pixels
1444         '0.0.0',
1445         '486',
1446         undef,
1447     ],
1448     tags_h => [
1449         'tagswin_height',
1450         $xl::s{l_win_h},
1451         $xl::s{h_win_h},
1452         'int,0,3000', # 0 pixels - 3000 pixels
1453         '0.0.0',
1454         '-1',
1455         undef,
1456     ],
1457     plug_w => [
1458         'pluginswin_width',
1459         $xl::s{l_win_w},
1460         $xl::s{h_win_w},
1461         'int,0,3000', # 0 pixels - 3000 pixels
1462         '0.0.0',
1463         '-1',
1464         undef,
1465     ],
1466     plug_h => [
1467         'pluginswin_height',
1468         $xl::s{l_win_h},
1469         $xl::s{h_win_h},
1470         'int,0,3000', # 0 pixels - 3000 pixels
1471         '0.0.0',
1472         '-1',
1473         undef,
1474     ],
1475     logw_w => [
1476         'logwin_width',
1477         $xl::s{l_win_w},
1478         $xl::s{h_win_w},
1479         'int,0,3000', # 0 pixels - 3000 pixels
1480         '0.0.0',
1481         '520',
1482         undef,
1483     ],
1484     logw_h => [
1485         'logwin_height',
1486         $xl::s{l_win_h},
1487         $xl::s{h_win_h},
1488         'int,0,3000', # 0 pixels - 3000 pixels
1489         '0.0.0',
1490         '-1',
1491         undef,
1492     ],
1493     prin_w => [
1494         'print_previewwin_width',
1495         $xl::s{l_win_w},
1496         $xl::s{h_win_w},
1497         'int,0,3000', # 0 pixels - 3000 pixels
1498         '0.0.0',
1499         '600',
1500         undef,
1501     ],
1502     prin_h => [
1503         'print_previewwin_height',
1504         $xl::s{l_win_h},
1505         $xl::s{h_win_h},
1506         'int,0,3000', # 0 pixels - 3000 pixels
1507         '0.0.0',
1508         '-1',
1509         undef,
1510     ],
1511 );
1512
1513 sub new_winpos_subpage_main() {
1514     return &new_subpage_frame (
1515                &new_vbox_pack_compact (
1516                    &new_vbox_pack (
1517                        &new_text_box_for_int (\%pr::win, 'main_x'), 
1518                        &new_text_box_for_int (\%pr::win, 'main_y')), 
1519                    &new_hbox_pack (
1520                        &new_text_box_for_int (\%pr::win, 'main_w'), 
1521                        &new_text_box_for_int (\%pr::win, 'main_h')), 
1522                    &new_vbox_pack (
1523                        &new_check_button_for (\%pr::win, 'main_fs'), 
1524                        &new_check_button_for (\%pr::win, 'main_mx'))),
1525                _('Main window')
1526            );
1527 }
1528
1529 sub new_winpos_subpage_msgs() {
1530     return &new_subpage_frame (
1531                &new_vbox_pack_compact (
1532                    &new_vbox_pack (
1533                        &new_text_box_for_int (\%pr::win, 'msgs_x'),
1534                        &new_text_box_for_int (\%pr::win, 'msgs_y')),
1535                    &new_hbox_pack (
1536                        &new_text_box_for_int (\%pr::win, 'msgs_w'),
1537                        &new_text_box_for_int (\%pr::win, 'msgs_h'))),
1538                _('Message window')
1539            );
1540 }
1541
1542 sub new_winpos_subpage_sendrecv() {
1543     return &new_vbox_pack (
1544                &new_subpage_frame (
1545                    &new_hbox_pack (
1546                        &new_text_box_for_int (\%pr::win, 'send_w'),
1547                        &new_text_box_for_int (\%pr::win, 'send_h')),
1548                    _('Send window'), 'not-packed'),
1549                &new_subpage_frame (
1550                    &new_hbox_pack (
1551                        &new_text_box_for_int (\%pr::win, 'recv_w'),
1552                        &new_text_box_for_int (\%pr::win, 'recv_h')),
1553                    _('Receive window'), 'not-packed')
1554            );
1555 }
1556
1557 sub new_winpos_subpage_fold() {
1558     return &new_vbox_pack (
1559                &new_subpage_frame (
1560                    &new_vbox_pack_compact (
1561                        &new_vbox_pack (
1562                             &new_text_box_for_int (\%pr::win, 'fold_x'), 
1563                             &new_text_box_for_int (\%pr::win, 'fold_y')), 
1564                        &new_hbox_pack (
1565                            &new_text_box_for_int (\%pr::win, 'fold_w'), 
1566                            &new_text_box_for_int (\%pr::win, 'fold_h'))),
1567                    _('Folder window'), 'not-packed'),
1568                &new_subpage_frame (
1569                    &new_hbox_pack (
1570                        &new_text_box_for_int (\%pr::win, 'fsel_w'),
1571                        &new_text_box_for_int (\%pr::win, 'fsel_h')),
1572                    _('Folder selection window'), 'not-packed')
1573            );
1574 }
1575
1576 sub new_winpos_subpage_addrbook() {
1577     return &new_vbox_pack (
1578                 &new_subpage_frame (
1579                      &new_hbox_pack (
1580                           &new_text_box_for_int (\%pr::win, 'addr_w'),
1581                           &new_text_box_for_int (\%pr::win, 'addr_h')),
1582                      _('Addressbook main window'), 'not-packed'),
1583                 &new_subpage_frame (
1584                      &new_hbox_pack (
1585                           &new_text_box_for_int (\%pr::win, 'adep_w'),
1586                           &new_text_box_for_int (\%pr::win, 'adep_h')),
1587                      _('Edit person window'), 'not-packed'),
1588                 &new_subpage_frame (
1589                      &new_hbox_pack (
1590                           &new_text_box_for_int (\%pr::win, 'adeg_w'),
1591                           &new_text_box_for_int (\%pr::win, 'adeg_h')),
1592                      _('Edit group window'), 'not-packed'),
1593                 &new_subpage_frame (
1594                      &new_hbox_pack (
1595                           &new_text_box_for_int (\%pr::win, 'adda_w'),
1596                           &new_text_box_for_int (\%pr::win, 'adda_h')),
1597                      _('Add address window'), 'not-packed'),
1598                 &new_subpage_frame (
1599                      &new_hbox_pack (
1600                           &new_text_box_for_int (\%pr::win, 'addf_w'),
1601                           &new_text_box_for_int (\%pr::win, 'addf_h')),
1602                      _('Folder select window'), 'not-packed')
1603            );
1604 }
1605
1606 sub new_winpos_subpage_accounts() {
1607     return &new_vbox_pack (
1608                 &new_subpage_frame (
1609                      &new_hbox_pack (
1610                           &new_text_box_for_int (\%pr::win, 'acco_w'),
1611                           &new_text_box_for_int (\%pr::win, 'acco_h')),
1612                      _('Accounts window'), 'not-packed'),
1613                 &new_subpage_frame (
1614                      &new_hbox_pack (
1615                           &new_text_box_for_int (\%pr::win, 'acce_w'),
1616                           &new_text_box_for_int (\%pr::win, 'acce_h')),
1617                      _('Edit account window'), 'not-packed')
1618            );
1619 }
1620
1621 sub new_winpos_subpage_filtering() {
1622     return &new_vbox_pack (
1623                 &new_subpage_frame (
1624                      &new_hbox_pack (
1625                           &new_text_box_for_int (\%pr::win, 'filt_w'),
1626                           &new_text_box_for_int (\%pr::win, 'filt_h')),
1627                      _('Filtering window'), 'not-packed'),
1628                 &new_subpage_frame (
1629                      &new_hbox_pack (
1630                           &new_text_box_for_int (\%pr::win, 'fila_w'),
1631                           &new_text_box_for_int (\%pr::win, 'fila_h')),
1632                      _('Filtering actions window'), 'not-packed'),
1633                 &new_subpage_frame (
1634                      &new_hbox_pack (
1635                           &new_text_box_for_int (\%pr::win, 'fild_w'),
1636                           &new_text_box_for_int (\%pr::win, 'fild_h')),
1637                      _('Filtering debug window'), 'not-packed'),
1638                 &new_subpage_frame (
1639                      &new_hbox_pack (
1640                           &new_text_box_for_int (\%pr::win, 'matc_w'),
1641                           &new_text_box_for_int (\%pr::win, 'matc_h')),
1642                      _('Matcher window'), 'not-packed')
1643            );
1644 }
1645
1646 sub new_winpos_subpage_prefs() {
1647     return &new_vbox_pack (
1648                 &new_subpage_frame (
1649                      &new_hbox_pack (
1650                           &new_text_box_for_int (\%pr::win, 'pref_w'),
1651                           &new_text_box_for_int (\%pr::win, 'pref_h')),
1652                      _('Preferences window'), 'not-packed'),
1653                 &new_subpage_frame (
1654                      &new_hbox_pack (
1655                           &new_text_box_for_int (\%pr::win, 'temp_w'),
1656                           &new_text_box_for_int (\%pr::win, 'temp_h')),
1657                      _('Templates window'), 'not-packed'),
1658                 &new_subpage_frame (
1659                      &new_hbox_pack (
1660                           &new_text_box_for_int (\%pr::win, 'acti_w'),
1661                           &new_text_box_for_int (\%pr::win, 'acti_h')),
1662                      _('Actions window'), 'not-packed'),
1663                 &new_subpage_frame (
1664                      &new_hbox_pack (
1665                           &new_text_box_for_int (\%pr::win, 'tags_w'),
1666                           &new_text_box_for_int (\%pr::win, 'tags_h')),
1667                      _('Tags window'), 'not-packed'),
1668                 &new_subpage_frame (
1669                      &new_hbox_pack (
1670                           &new_text_box_for_int (\%pr::win, 'plug_w'),
1671                           &new_text_box_for_int (\%pr::win, 'plug_h')),
1672                      _('Plugins window'), 'not-packed')
1673            );
1674 }
1675
1676 sub new_winpos_subpage_misc() {
1677     return &new_vbox_pack (
1678                 &new_subpage_frame (
1679                      &new_hbox_pack (
1680                           &new_text_box_for_int (\%pr::win, 'logw_w'),
1681                           &new_text_box_for_int (\%pr::win, 'logw_h')),
1682                      _('Log window'), 'not-packed'),
1683                 &new_subpage_frame (
1684                      &new_hbox_pack (
1685                           &new_text_box_for_int (\%pr::win, 'prin_w'),
1686                           &new_text_box_for_int (\%pr::win, 'prin_h')),
1687                      _('Print preview window'), 'not-packed'),
1688                 &new_subpage_frame (
1689                      &new_hbox_pack (
1690                           &new_text_box_for_int (\%pr::win, 'sour_w'),
1691                           &new_text_box_for_int (\%pr::win, 'sour_h')),
1692                      _('View source window'), 'not-packed')
1693            );
1694 }
1695
1696 sub new_winpos_page() {
1697     my $winbook = Gtk2::Notebook->new;
1698     $winbook->set_tab_pos ('right');
1699     $winbook->append_page (&new_winpos_subpage_main, _('Main'));
1700     $winbook->append_page (&new_winpos_subpage_msgs, _('Message'));
1701     $winbook->append_page (&new_winpos_subpage_sendrecv, _('Send/Receive'));
1702     $winbook->append_page (&new_winpos_subpage_fold, _('Folder'));
1703     $winbook->append_page (&new_winpos_subpage_addrbook, _('Addressbook'));
1704     $winbook->append_page (&new_winpos_subpage_accounts, _('Accounts'));
1705     $winbook->append_page (&new_winpos_subpage_filtering, _('Filtering'));
1706     $winbook->append_page (&new_winpos_subpage_prefs, _('Preferences'));
1707     $winbook->append_page (&new_winpos_subpage_misc, _('Other'));
1708     return $winbook;
1709 }
1710
1711 # version info
1712 sub print_version() {
1713     print $xl::s{about_title} . "\n";
1714     print $xl::s{about_version} . " $VERSION\n";
1715     print "Perl-GLib " . $Glib::VERSION;
1716     # version info stuff appeared in 1.040
1717     if ($Glib::VERSION >= 1.040) {
1718         print _(", built for ") . join(".", Glib->GET_VERSION_INFO) 
1719               . _(", running with ") . join(".", &Glib::major_version, 
1720               &Glib::minor_version, &Glib::micro_version);
1721     }
1722     print "\n";
1723     print "Perl-GTK2 " . $Gtk2::VERSION;
1724     if ($Gtk2::VERSION >= 1.040) {
1725         print _(", built for ") . join(".", Gtk2->GET_VERSION_INFO)
1726               . _(", running with ") . join(".", &Gtk2::major_version, 
1727               &Gtk2::minor_version, &Gtk2::micro_version);
1728     }
1729     print "\n";
1730     my $clawsver = ($CLAWSV eq "") ? 
1731                 _("was not found!") : 
1732                 (_("returned version ") . $CLAWSV);
1733     print "Claws Mail " . $clawsver . "\n";
1734 }
1735
1736 # the command line help
1737 sub print_help() {
1738     my $line = '-' x length ($xl::s{about_title}) . "\n";
1739     print $line;
1740     print $xl::s{about_title} . "\n";
1741     print $line;
1742     print _("Syntax:\n");
1743     print _("    clawsker [options]\n");
1744     print _("Options:\n");
1745     print _("    --help                         Prints this help screen.\n");
1746     print _("    --version                      Prints version infos.\n");
1747     print _("    --verbose                      More messages on standard output.\n");
1748     print _("    --alternate-config-dir <dir>   Uses <dir> as Claws Mail config dir.\n");
1749     print _("    --clawsrc <file>               Uses <file> as full resource name.\n");
1750 }
1751
1752 # handle errors which don't allow to run
1753 sub command_line_fatal() {
1754     my $reason = shift;
1755     my $emsg = $xl::s{e_error} . $reason;
1756     error_dialog ($emsg);
1757     log_message ("$emsg", 'die');
1758 }
1759
1760 # parse the command line
1761 sub parse_command_line() {
1762     $CLAWSV = &get_claws_version;
1763     my $arg = 0;
1764     while (defined($ARGV[$arg])) {
1765         for ($ARGV[$arg]) {
1766             /--help/ && do { 
1767                 &print_help; 
1768                 return FALSE;
1769             };
1770             /--version/ && do { 
1771                 &print_version; 
1772                 return FALSE;
1773             };
1774             /--verbose/ && do {
1775                 $VERBOSE = TRUE;
1776                 last;
1777             };
1778             /--use-claws-version/ && do {
1779                 ++$arg;
1780                 &command_line_fatal ("required version")
1781                     unless defined($ARGV[$arg]);
1782                 &command_line_fatal ("required a dotted numeric value")
1783                     unless ($ARGV[$arg] =~ /[\d\.]+/);
1784                 $CLAWSV = $ARGV[$arg];
1785                 last;
1786             };
1787             /--alternate-config-dir/ && do {
1788                 ++$arg;
1789                 &command_line_fatal ($xl::s{e_requireddir})
1790                     unless defined($ARGV[$arg]);
1791                 &command_line_fatal ($xl::s{e_notadir})
1792                     unless -d $ARGV[$arg];
1793                 $CONFIGDIR = $ARGV[$arg];
1794                 $CONFIGDIR .= "/" 
1795                     unless ($CONFIGDIR =~ /.*\/$/);
1796                 $ALTCONFIGDIR = TRUE;
1797                 last;
1798             };
1799             /--clawsrc/ && do {
1800                 ++$arg;
1801                 &command_line_fatal($xl::s{e_requiredfile}) 
1802                     unless defined($ARGV[$arg]);
1803                 &command_line_fatal($xl::s{e_notafile}) 
1804                     unless -f $ARGV[$arg];
1805                 &set_rc_filename ($ARGV[$arg]);
1806                 last;
1807             };
1808             /.*/ && &command_line_fatal (
1809                 _("unknown option '{opt}'.\n", opt => $ARGV[$arg]));
1810         }
1811         ++$arg;
1812     }
1813     # eveything continues...
1814     return TRUE;
1815 }
1816
1817 # update the hidden preferences status from loaded values
1818 sub init_hidden_preferences() {
1819     foreach my $hash (\%pr::beh, \%pr::col, \%pr::gui, \%pr::oth, \%pr::win) {
1820         foreach my $key (keys %$hash) { 
1821             $HPVALUE{${$hash}{$key}[NAME]} = $PREFS{${$hash}{$key}[NAME]};
1822         }
1823     }
1824     return TRUE;
1825 }
1826
1827 # load current status from disc
1828 sub load_preferences() {
1829     my $rc = &get_rc_filename;
1830     &log_message ("Loading preferences from $rc\n");
1831     return FALSE unless &check_rc_file ($rc);
1832     return FALSE unless &check_claws_not_running;
1833     open (RCF, "<$rc");
1834     while (<RCF>) {
1835         chomp;
1836         if (/^([8a-z_]+)=(.*)$/) {
1837             $PREFS{$1} = "$2";
1838         }
1839     }
1840     close (RCF);
1841     return TRUE;
1842 }
1843
1844 # save current preferences to disc
1845 sub save_preferences() {
1846     my $rc = &get_rc_filename;
1847     &log_message ("Saving preferences to $rc\n");
1848     return FALSE unless &check_rc_file ($rc);
1849     return FALSE unless &check_claws_not_running;
1850     my $rcbak = "$rc.backup";
1851     rename ($rc, $rcbak);
1852     open (RCF, ">$rc");
1853     open (RCB, "<$rcbak");
1854     while (<RCB>) {
1855         chomp;
1856         if (/^([8a-z_]+)=(.*)$/) {
1857             if (defined($HPVALUE{$1})) {
1858                 print RCF $1 . "=" . $HPVALUE{$1} . "\n";
1859             }
1860             else {
1861                 print RCF $_ . "\n";
1862             }
1863         }
1864         else {
1865             print RCF $_ . "\n";
1866         }
1867     }
1868     close (RCB);
1869     close (RCF);
1870     return TRUE;
1871 }
1872
1873 # create notebook
1874 sub new_notebook() {
1875     my $nb = Gtk2::Notebook->new;
1876     # 
1877     $nb->append_page (&new_behaviour_page, $xl::s{tab_behaviour});
1878     $nb->append_page (&new_colours_page, $xl::s{tab_colours});
1879     $nb->append_page (&new_gui_page, $xl::s{tab_gui});
1880     $nb->append_page (&new_other_page, $xl::s{tab_other});
1881     $nb->append_page (&new_winpos_page, $xl::s{tab_winpos});
1882
1883     return $nb;
1884 }
1885
1886 # create an about dialog
1887 sub new_about_dialog() {
1888     my ($parent) = @_;
1889     my $title = $xl::s{about_title};
1890     my $lic = $xl::s{about_license};
1891     my $vers = $xl::s{about_version} . " $VERSION";
1892     my $license = 
1893 "This program is free software: you can redistribute it and/or modify
1894 it under the terms of the GNU General Public License as published by
1895 the Free Software Foundation, either version 3 of the License, or
1896 (at your option) any later version.
1897
1898 This program is distributed in the hope that it will be useful,
1899 but WITHOUT ANY WARRANTY; without even the implied warranty of
1900 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1901 GNU General Public License for more details.
1902
1903 You should have received a copy of the GNU General Public License
1904 along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.";
1905     my $year = "2007-2012";
1906     my $holder = "Ricardo Mones &lt;ricardo\@mones.org&gt;";
1907     my $url = "http://www.claws-mail.org/clawsker";
1908
1909     my $dialog = Gtk2::MessageDialog->new_with_markup ($parent, 
1910                     [qw/modal destroy-with-parent/], 
1911                     'info', 'close', 
1912                     "<span size=\"x-large\" weight=\"bold\">$title</span>\n"
1913                     . "<span size=\"large\">$vers</span>\n\n"
1914                     . "<span color=\"blue\" size=\"large\">$url</span>\n\n"
1915                     . "<span>Copyright $year by $holder</span>\n\n"
1916                     . "<span size=\"large\">$lic</span>\n\n"
1917                     . "<span size=\"small\">$license</span>");
1918     $dialog->set_title ($xl::s{about});
1919     #
1920     return $dialog;
1921 }
1922
1923 # create buttons box
1924 sub new_button_box() {
1925     my ($parent, $adlg) = @_;
1926     my $b_about = Gtk2::Button->new_from_stock ('gtk-about');
1927     my $b_exit = Gtk2::Button->new_from_stock ('gtk-quit');
1928     my $b_apply = Gtk2::Button->new_from_stock ('gtk-apply');
1929     # disable button until is really implemented
1930     # my $b_undo = Gtk2::Button->new_from_stock ('gtk-undo');
1931     my $hbox = Gtk2::HBox->new (FALSE, 5);
1932     # signal handlers 
1933     $b_exit->signal_connect (clicked => sub { Gtk2->main_quit });
1934     $b_apply->signal_connect (clicked => sub { &save_preferences ($parent) });
1935     # $b_undo->signal_connect (clicked => sub { &undo_current_changes });
1936     $b_about->signal_connect (clicked => sub { $adlg->run; $adlg->hide });
1937     # package them
1938     $hbox->pack_end ($b_apply, FALSE, FALSE, 0);
1939     $hbox->pack_end ($b_exit, FALSE, FALSE, 0);
1940     # $hbox->pack_end ($b_undo, FALSE, FALSE, 0);
1941     $hbox->pack_start ($b_about, FALSE, FALSE, 0);
1942     #
1943     return $hbox;
1944 }
1945
1946 # initialise
1947 $main_window = Gtk2::Window->new ('toplevel');
1948 exit unless &parse_command_line;
1949 exit unless &load_preferences;
1950 exit unless &init_hidden_preferences;
1951 # create main GUI
1952 my $box = Gtk2::VBox->new (FALSE, 5);
1953 $box->set_border_width(3);
1954 my $about = &new_about_dialog;
1955 $box->pack_start (&new_notebook, FALSE, FALSE, 0);
1956 $box->pack_end (&new_button_box ($main_window, $about), FALSE, FALSE, 0);
1957 $main_window->signal_connect (delete_event => sub { Gtk2->main_quit });
1958 $main_window->set_title ($xl::s{win_title});
1959 $main_window->add ($box);
1960 $main_window->show_all;
1961 Gtk2->main;
1962