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