fix spinbutton warning
[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 $gentry = Gtk2::SpinButton->new_with_range ($type[1], $type[2], $pagei);
477     $gentry->set_numeric (TRUE);
478     $$hash{$key}[GUI] = $gentry;
479     $gentry->signal_connect('value-changed' => sub {
480             my ($w, $e) = @_;
481             &handle_int_value($w, $e, \$HPVALUE{$name});
482         });
483     &set_widget_hint ($gentry, $$hash{$key}[DESC]);
484     &set_widget_sens ($gentry, $$hash{$key}[CMVER]);
485     $glabel->set_sensitive ($gentry->sensitive);
486     $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
487     $hbox->pack_start ($gentry, FALSE, FALSE, HBOX_SPC);
488     #
489     return $hbox;
490 }
491
492 sub new_color_button_for {
493     my ($hash, $key) = @_;
494     my $name = $$hash{$key}[NAME];
495     my $label = $$hash{$key}[LABEL];
496     #
497     my $col = &gdk_color_from_str ($HPVALUE{$name});
498     my $hbox = Gtk2::HBox->new (FALSE, 5);
499     my $glabel = Gtk2::Label->new ($label);
500     my $button = Gtk2::ColorButton->new_with_color ($col);
501     $$hash{$key}[GUI] = $button;
502     $button->set_title ($label);
503     $button->set_relief ('none');
504     $button->signal_connect ('color-set' => sub {
505             my ($w, $e) = @_;
506             &handle_color_value($w, $e, \$HPVALUE{$name}); 
507         });
508     &set_widget_hint ($button, $$hash{$key}[DESC]);
509     &set_widget_sens ($button, $$hash{$key}[CMVER]);
510     $glabel->set_sensitive ($button->sensitive);
511     $hbox->pack_start ($button, FALSE, FALSE, HBOX_SPC);
512     $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
513     #
514     return $hbox;
515 }
516
517 sub new_selection_box_for {
518     my ($hash, $key) = @_;
519     my $name = $$hash{$key}[NAME];
520     my $label = $$hash{$key}[LABEL];
521     #
522     my $hbox = Gtk2::HBox->new (FALSE, 5);
523     my $glabel = Gtk2::Label->new ($label);
524     my $combo = Gtk2::ComboBox->new_text;
525     $$hash{$key}[GUI] = $combo;
526     my @options = split (';', $$hash{$key}[TYPE]);
527     foreach my $opt (@options) {
528         my ($index, $textkey) = split ('=', $opt);
529         $combo->insert_text ($index, $xl::s{$textkey});
530     }
531     $combo->signal_connect ('changed' => sub {
532             my ($w, $e) = @_;
533             &handle_selection_value($w, $e, \$HPVALUE{$name});
534         });
535     $combo->set_active ($HPVALUE{$name});
536     &set_widget_hint ($combo, $$hash{$key}[DESC]);
537     &set_widget_sens ($combo, $$hash{$key}[CMVER]);
538     $glabel->set_sensitive ($combo->sensitive);
539     $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
540     $hbox->pack_start ($combo, FALSE, FALSE, HBOX_SPC);
541     #
542     return $hbox;
543 }
544
545 # more graphic helpers
546
547 sub new_hbox_pack() {
548     my $hbox = Gtk2::HBox->new (FALSE, 5);
549     $hbox->set_border_width (PAGE_SPC);
550     foreach my $item (@_) {
551         $hbox->pack_start ($item, FALSE, FALSE, 0);
552     }
553     return $hbox;
554 }    
555
556 sub new_vbox_pack() {
557     my $vbox = Gtk2::VBox->new (FALSE, 5);
558     $vbox->set_border_width (PAGE_SPC);
559     foreach my $item (@_) {
560         $vbox->pack_start ($item, FALSE, FALSE, 0);
561     }
562     return $vbox;
563 }    
564
565 sub new_subpage_frame () {
566     my ($box, $title, $notpacked) = @_;
567     my $frame = Gtk2::Frame->new ($title);
568     $frame->add ($box);    
569     return &new_vbox_pack ($frame) unless defined ($notpacked);
570     return $frame;
571 }
572
573 # preference maps and corresponding page creation subs
574
575 %pr::oth = ( # other preferences
576     use_dlg => [ 
577         'addressbook_use_editaddress_dialog',
578         $xl::s{l_oth_use_dlg},
579         $xl::s{h_oth_use_dlg},
580         'bool',
581         '2.7.0',
582         '0',
583         undef,
584     ],
585     max_use => [
586         'cache_max_mem_usage',
587         $xl::s{l_oth_max_use},
588         $xl::s{h_oth_max_use},
589         'int,0,262144', # 0 Kb - 256 Mb
590         '0.0.0',
591         '4096',
592         undef,
593     ],
594     min_time => [
595         'cache_min_keep_time',
596         $xl::s{l_oth_min_time},
597         $xl::s{h_oth_min_time},
598         'int,0,120', # 0 minutes - 2 hours
599         '0.0.0',
600         '15',
601         undef,
602     ],
603     use_netm => [
604         'use_networkmanager',
605         $xl::s{l_oth_use_netm},
606         $xl::s{h_oth_use_netm},
607         'bool',
608         '3.3.1',
609         '1',
610         undef,
611     ],
612 );
613
614 sub new_other_page() {
615     return &new_vbox_pack (
616                &new_subpage_frame (
617                    &new_vbox_pack (
618                        &new_check_button_for(\%pr::oth, 'use_dlg')),
619                    $xl::s{ab_frame}, 'not-packed'),
620                &new_subpage_frame (
621                    &new_vbox_pack (
622                        &new_text_box_for_int(\%pr::oth, 'max_use'),
623                        &new_text_box_for_int(\%pr::oth, 'min_time')),
624                    $xl::s{mem_frame}, 'not-packed'),
625                &new_subpage_frame (
626                    &new_vbox_pack (
627                        &new_check_button_for(\%pr::oth, 'use_netm')),
628                    $xl::s{netm_frame}, 'not-packed')
629            );
630 }
631
632 %pr::gui = ( # gui bells and whistles
633     b_unread => [ 
634         'bold_unread',
635         $xl::s{l_gui_b_unread},
636         $xl::s{h_gui_b_unread},
637         'bool',
638         '0.0.0',
639         '1',
640         undef,
641     ],
642     no_markup => [
643         'compose_no_markup',
644         $xl::s{l_gui_no_markup},
645         $xl::s{h_gui_no_markup},
646         'bool',
647         '0.0.0',
648         '0',
649         undef,
650     ],
651     dot_lines => [
652         'enable_dotted_lines',
653         $xl::s{l_gui_dot_lines},
654         $xl::s{h_gui_dot_lines},
655         'bool',
656         '0.0.0',
657         '0',
658         undef,
659     ],
660     h_scroll => [
661         'enable_hscrollbar',
662         $xl::s{l_gui_h_scroll},
663         $xl::s{h_gui_h_scroll},
664         'bool',
665         '0.0.0',
666         '1',
667         undef,
668     ],
669     swp_from => [
670         'enable_swap_from',
671         $xl::s{l_gui_swp_from},
672         $xl::s{h_gui_swp_from},
673         'bool',
674         '0.0.0',
675         '0',
676         undef,
677     ],
678     v_scroll => [
679         'folderview_vscrollbar_policy',
680         $xl::s{l_gui_v_scroll},
681         $xl::s{h_gui_v_scroll},
682         '0=l_gui_v_scroll_show;1=l_gui_v_scroll_auto;2=l_gui_v_scroll_hide',
683         '0.0.0',
684         '0',
685         undef,
686     ],
687     strip_off => [
688         'stripes_color_offset',
689         $xl::s{l_gui_strip_off},
690         $xl::s{h_gui_strip_off},
691         'int,0,10000', # no idea what this number means
692         '0.0.0',
693         '4000',
694         undef,
695     ],
696     cursor_v => [
697         'textview_cursor_visible',
698         $xl::s{l_gui_cursor_v},
699         $xl::s{h_gui_cursor_v},
700         'bool',
701         '0.0.0',
702         '0',
703         undef,
704     ],
705     toolbar_d => [
706         'toolbar_detachable',
707         $xl::s{l_gui_toolbar_d},
708         $xl::s{h_gui_toolbar_d},
709         'bool',
710         '0.0.0',
711         '0',
712         undef,
713     ],
714     strip_all => [
715         'use_stripes_everywhere',
716         $xl::s{l_gui_strip_all},
717         $xl::s{h_gui_strip_all},
718         'bool',
719         '0.0.0',
720         '1',
721         undef,
722     ],
723     strip_sum => [
724         'use_stripes_in_summaries',
725         $xl::s{l_gui_strip_sum},
726         $xl::s{h_gui_strip_sum},
727         'bool',
728         '0.0.0',
729         '1',
730         undef,
731     ],
732     two_linev => [
733         'two_line_vertical',
734         $xl::s{l_gui_two_line_v},
735         $xl::s{h_gui_two_line_v},
736         'bool',
737         '3.4.0.7',
738         '0',
739         undef,
740     ],
741 );
742
743 sub new_gui_page() {
744     my $gf = Gtk2::VBox->new (FALSE, 5);
745     $gf->set_border_width (PAGE_SPC);
746
747     my $cb_no_markup = &new_check_button_for (\%pr::gui, 'no_markup'); 
748     my $cb_dot_lines = &new_check_button_for (\%pr::gui, 'dot_lines'); 
749     my $cb_cursor_v = &new_check_button_for (\%pr::gui, 'cursor_v');
750     my $cb_toolbar_d = &new_check_button_for (\%pr::gui, 'toolbar_d');
751     my $cb_two_linev = &new_check_button_for (\%pr::gui, 'two_linev');
752
753     $gf->pack_start (&new_subpage_frame (
754                          &new_vbox_pack (
755                              &new_check_button_for (\%pr::gui, 'strip_all'),
756                              &new_check_button_for (\%pr::gui, 'strip_sum'),
757                              &new_text_box_for_int (\%pr::gui, 'strip_off')),
758                          $xl::s{stripes_frame}, 'not-packed'),
759                      FALSE, FALSE, FRAME_SPC);
760     $gf->pack_start (&new_subpage_frame (
761                          &new_vbox_pack (
762                              &new_check_button_for (\%pr::gui, 'b_unread'),
763                              &new_check_button_for (\%pr::gui, 'swp_from')),
764                          $xl::s{mlist_frame}, 'not-packed'), 
765                      FALSE, FALSE, FRAME_SPC);
766     $gf->pack_start ($cb_no_markup, FALSE, FALSE, 0);
767     $gf->pack_start ($cb_dot_lines, FALSE, FALSE, 0);
768     $gf->pack_start ($cb_cursor_v, FALSE, FALSE, 0);
769     $gf->pack_start ($cb_toolbar_d, FALSE, FALSE, 0);
770     $gf->pack_start ($cb_two_linev, FALSE, FALSE, 0);
771     $gf->pack_start (&new_subpage_frame (
772                          &new_vbox_pack (
773                              &new_check_button_for (\%pr::gui, 'h_scroll'),
774                              &new_selection_box_for (\%pr::gui, 'v_scroll')),
775                          $xl::s{sbar_frame}, 'not-packed'),
776                      FALSE, FALSE, FRAME_SPC);
777
778     return $gf;
779 }
780
781 %pr::beh = ( # tweak some behaviour
782     hover_t => [
783         'hover_timeout',
784         $xl::s{l_beh_hover_t},
785         $xl::s{h_beh_hover_t},
786         'int,100,3000', # 0.1 seconds - 3 seconds
787         '0.0.0',
788         '500',
789         undef,
790     ],
791     dangerous => [
792         'live_dangerously',
793         $xl::s{l_beh_dangerous},
794         $xl::s{h_beh_dangerous},
795         'bool',
796         '0.0.0',
797         '0',
798         undef,
799     ],
800     flowed => [
801         'respect_flowed_format',
802         $xl::s{l_beh_flowed},
803         $xl::s{h_beh_flowed},
804         'bool',
805         '0.0.0',
806         '0',
807         undef,
808     ],
809     parts_rw => [
810         'save_parts_readwrite',
811         $xl::s{l_beh_parts_rw},
812         $xl::s{h_beh_parts_rw},
813         'bool',
814         '0.0.0',
815         '0',
816         undef,
817     ],
818     skip_ssl => [
819         'skip_ssl_cert_check',
820         $xl::s{l_beh_skip_ssl},
821         $xl::s{h_beh_skip_ssl},
822         'bool',
823         '0.0.0',
824         '0',
825         undef,
826     ],
827     up_step => [
828         'statusbar_update_step',
829         $xl::s{l_beh_up_step},
830         $xl::s{h_beh_up_step},
831         'int,1,200', # 1 item - 200 items
832         '0.0.0',
833         '10',
834         undef,
835     ],
836     thread_a => [
837         'thread_by_subject_max_age',
838         $xl::s{l_beh_thread_a},
839         $xl::s{h_beh_thread_a},
840         'int,1,30', # 1 day - 30 days
841         '0.0.0',
842         '10',
843         undef,
844     ],
845     unsafe_ssl => [
846         'unsafe_ssl_certs',
847         $xl::s{l_beh_unsafe_ssl},
848         $xl::s{h_beh_unsafe_ssl},
849         'bool',
850         '0.0.0',
851         '0',
852         undef,
853     ],
854     use_utf8 => [
855         'utf8_instead_of_locale_for_broken_mail',
856         $xl::s{l_beh_use_utf8},
857         $xl::s{h_beh_use_utf8},
858         'bool',
859         '0.0.0',
860         '0',
861         undef,
862     ],
863     warn_dnd => [
864         'warn_dnd',
865         $xl::s{l_beh_warn_dnd},
866         $xl::s{h_beh_warn_dnd},
867         'bool',
868         '0.0.0',
869         '1',
870         undef,
871     ],
872     out_ascii => [
873         'outgoing_fallback_to_ascii',
874         $xl::s{l_beh_out_ascii},
875         $xl::s{h_beh_out_ascii},
876         'bool',
877         '3.4.0.37',
878         '1',
879         undef,
880     ],
881     pp_unsel => [
882         'primary_paste_unselects',
883         $xl::s{l_beh_pp_unsel},
884         $xl::s{h_beh_pp_unsel},
885         'bool',
886         '3.6.1.35',
887         '0',
888         undef,
889     ],
890 );
891
892 sub new_behaviour_page() {
893     my $bf = Gtk2::VBox->new (FALSE, 5);
894     $bf->set_border_width (PAGE_SPC);
895
896     my $tb_up_step = &new_text_box_for_int (\%pr::beh, 'up_step');
897     my $tb_thread_a = &new_text_box_for_int (\%pr::beh, 'thread_a');
898
899     $bf->pack_start (&new_subpage_frame (
900                          &new_vbox_pack (
901                              &new_text_box_for_int (\%pr::beh, 'hover_t'),
902                              &new_check_button_for (\%pr::beh, 'warn_dnd')),
903                          $xl::s{dnd_frame}, 'not-packed'), 
904                      FALSE, FALSE, FRAME_SPC);
905     $bf->pack_start (&new_subpage_frame (
906                          &new_hbox_pack (
907                              &new_check_button_for (\%pr::beh, 'skip_ssl'),
908                              &new_check_button_for (\%pr::beh, 'unsafe_ssl')),
909                          $xl::s{ssl_frame}, 'not-packed'),
910                      FALSE, FALSE, FRAME_SPC);
911     $bf->pack_start ($tb_up_step, FALSE, FALSE, 0);
912     $bf->pack_start ($tb_thread_a, FALSE, FALSE, 0);
913     $bf->pack_start (&new_subpage_frame (
914                          &new_vbox_pack (
915                              &new_check_button_for (\%pr::beh, 'flowed'),
916                              &new_check_button_for (\%pr::beh, 'parts_rw'),
917                              &new_check_button_for (\%pr::beh, 'use_utf8'),
918                              &new_check_button_for (\%pr::beh, 'dangerous'),
919                              &new_check_button_for (\%pr::beh, 'out_ascii'),
920                              &new_check_button_for (\%pr::beh, 'pp_unsel')),
921                          $xl::s{msgs_frame}, 'not-packed'),
922                      FALSE, FALSE, FRAME_SPC);
923
924     return $bf;
925 }
926
927 %pr::col = ( # a variety of colours
928     emphasis => [
929         'emphasis_color',
930         $xl::s{l_col_emphasis},
931         $xl::s{h_col_emphasis},
932         'color',
933         '0.0.0',
934         '#0000cf',
935         undef,
936     ],
937     log_err => [
938         'log_error_color',
939         $xl::s{l_col_log_err},
940         $xl::s{h_col_log_err},
941         'color',
942         '0.0.0',
943         '#af0000',
944         undef,
945     ],
946     log_in => [
947         'log_in_color',
948         $xl::s{l_col_log_in},
949         $xl::s{h_col_log_in},
950         'color',
951         '0.0.0',
952         '#000000',
953         undef,
954     ],
955     log_msg => [
956         'log_msg_color',
957         $xl::s{l_col_log_msg},
958         $xl::s{h_col_log_msg},
959         'color',
960         '0.0.0',
961         '#00af00',
962         undef,
963     ],
964     log_out => [
965         'log_out_color',
966         $xl::s{l_col_log_out},
967         $xl::s{h_col_log_out},
968         'color',
969         '0.0.0',
970         '#0000ef',
971         undef,
972     ],
973     log_warn => [
974         'log_warn_color',
975         $xl::s{l_col_log_warn},
976         $xl::s{h_col_log_warn},
977         'color',
978         '0.0.0',
979         '#af0000',
980         undef,
981     ],
982 );
983
984 sub new_colours_page() {
985     return &new_vbox_pack (
986                &new_subpage_frame (
987                    &new_vbox_pack (
988                        &new_color_button_for (\%pr::col, 'emphasis')),
989                    $xl::s{msgview_frame}, 'not-packed'),
990                &new_subpage_frame (
991                    &new_vbox_pack (
992                        &new_color_button_for (\%pr::col, 'log_err'),
993                        &new_color_button_for (\%pr::col, 'log_in'),
994                        &new_color_button_for (\%pr::col, 'log_msg'),
995                        &new_color_button_for (\%pr::col, 'log_out'),
996                        &new_color_button_for (\%pr::col, 'log_warn')),
997                    $xl::s{log_frame}, 'not-packed')
998            );
999 }
1000
1001 %pr::win = ( # tweak window positions and/or sizes
1002     main_x => [
1003         'mainwin_x',
1004         $xl::s{l_win_x},
1005         $xl::s{h_win_x},
1006         'int,0,3000', # 0 pixels - 3000 pixels
1007         '0.0.0',
1008         '16',
1009         undef,
1010     ],
1011     main_y => [
1012         'mainwin_y',
1013         $xl::s{l_win_y},
1014         $xl::s{h_win_y},
1015         'int,0,3000', # 0 pixels - 3000 pixels
1016         '0.0.0',
1017         '16',
1018         undef,
1019     ],
1020     main_w => [
1021         'mainwin_width',
1022         $xl::s{l_win_w},
1023         $xl::s{h_win_w},
1024         'int,0,3000', # 0 pixels - 3000 pixels
1025         '0.0.0',
1026         '779',
1027         undef,
1028     ],
1029     main_h => [
1030         'mainwin_height',
1031         $xl::s{l_win_h},
1032         $xl::s{h_win_h},
1033         'int,0,3000', # 0 pixels - 3000 pixels
1034         '0.0.0',
1035         '568',
1036         undef,
1037     ],
1038     main_mx => [
1039         'mainwin_maximised',
1040         $xl::s{l_win_main_mx},
1041         $xl::s{h_win_main_mx},
1042         'bool',
1043         '0.0.0',
1044         '0',
1045         undef,
1046     ],
1047     main_fs => [
1048         'mainwin_fullscreen',
1049         $xl::s{l_win_main_fs},
1050         $xl::s{h_win_main_fs},
1051         'bool',
1052         '0.0.0',
1053         '0',
1054         undef,
1055     ],
1056     msgs_x => [
1057         'main_messagewin_x',
1058         $xl::s{l_win_x},
1059         $xl::s{h_win_x},
1060         'int,0,3000', # 0 pixels - 3000 pixels
1061         '0.0.0',
1062         '256',
1063         undef,
1064     ],
1065     msgs_y => [
1066         'main_messagewin_y',
1067         $xl::s{l_win_y},
1068         $xl::s{h_win_y},
1069         'int,0,3000', # 0 pixels - 3000 pixels
1070         '0.0.0',
1071         '210',
1072         undef,
1073     ],
1074     msgs_w => [
1075         'messagewin_width',
1076         $xl::s{l_win_w},
1077         $xl::s{h_win_w},
1078         'int,0,3000', # 0 pixels - 3000 pixels
1079         '0.0.0',
1080         '600',
1081         undef,
1082     ],
1083     msgs_h => [
1084         'messagewin_height',
1085         $xl::s{l_win_h},
1086         $xl::s{h_win_h},
1087         'int,0,3000', # 0 pixels - 3000 pixels
1088         '0.0.0',
1089         '540',
1090         undef,
1091     ],
1092     send_w => [
1093         'sendwin_width',
1094         $xl::s{l_win_w},
1095         $xl::s{h_win_w},
1096         'int,0,3000', # 0 pixels - 3000 pixels
1097         '0.0.0',
1098         '460',
1099         undef,
1100     ],
1101     send_h => [
1102         'sendwin_height',
1103         $xl::s{l_win_h},
1104         $xl::s{h_win_h},
1105         'int,0,3000', # 0 pixels - 3000 pixels
1106         '0.0.0',
1107         '-1',
1108         undef,
1109     ],
1110     recv_w => [
1111         'receivewin_width',
1112         $xl::s{l_win_w},
1113         $xl::s{h_win_w},
1114         'int,0,3000', # 0 pixels - 3000 pixels
1115         '0.0.0',
1116         '460',
1117         undef,
1118     ],
1119     recv_h => [
1120         'receivewin_height',
1121         $xl::s{l_win_h},
1122         $xl::s{h_win_h},
1123         'int,0,3000', # 0 pixels - 3000 pixels
1124         '0.0.0',
1125         '-1',
1126         undef,
1127     ],
1128     fold_x => [
1129         'folderwin_x',
1130         $xl::s{l_win_x},
1131         $xl::s{h_win_x},
1132         'int,0,3000', # 0 pixels - 3000 pixels
1133         '0.0.0',
1134         '16',
1135         undef,
1136     ],
1137     fold_y => [
1138         'folderwin_y',
1139         $xl::s{l_win_y},
1140         $xl::s{h_win_y},
1141         'int,0,3000', # 0 pixels - 3000 pixels
1142         '0.0.0',
1143         '16',
1144         undef,
1145     ],
1146     fold_w => [
1147         'folderitemwin_width',
1148         $xl::s{l_win_w},
1149         $xl::s{h_win_w},
1150         'int,0,3000', # 0 pixels - 3000 pixels
1151         '0.0.0',
1152         '500',
1153         undef,
1154     ],
1155     fold_h => [
1156         'folderitemwin_height',
1157         $xl::s{l_win_h},
1158         $xl::s{h_win_h},
1159         'int,0,3000', # 0 pixels - 3000 pixels
1160         '0.0.0',
1161         '-1',
1162         undef,
1163     ],
1164     fsel_w => [
1165         'folderselwin_width',
1166         $xl::s{l_win_w},
1167         $xl::s{h_win_w},
1168         'int,0,3000', # 0 pixels - 3000 pixels
1169         '0.0.0',
1170         '300',
1171         undef,
1172     ],
1173     fsel_h => [
1174         'folderselwin_height',
1175         $xl::s{l_win_h},
1176         $xl::s{h_win_h},
1177         'int,0,3000', # 0 pixels - 3000 pixels
1178         '0.0.0',
1179         '-1',
1180         undef,
1181     ],
1182     sour_w => [
1183         'sourcewin_width',
1184         $xl::s{l_win_w},
1185         $xl::s{h_win_w},
1186         'int,0,3000', # 0 pixels - 3000 pixels
1187         '0.0.0',
1188         '600',
1189         undef,
1190     ],
1191     sour_h => [
1192         'sourcewin_height',
1193         $xl::s{l_win_h},
1194         $xl::s{h_win_h},
1195         'int,0,3000', # 0 pixels - 3000 pixels
1196         '0.0.0',
1197         '500',
1198         undef,
1199     ],
1200     addr_w => [
1201         'addressbookwin_width',
1202         $xl::s{l_win_w},
1203         $xl::s{h_win_w},
1204         'int,0,3000', # 0 pixels - 3000 pixels
1205         '0.0.0',
1206         '520',
1207         undef,
1208     ],
1209     addr_h => [
1210         'addressbookwin_height',
1211         $xl::s{l_win_h},
1212         $xl::s{h_win_h},
1213         'int,0,3000', # 0 pixels - 3000 pixels
1214         '0.0.0',
1215         '-1',
1216         undef,
1217     ],
1218     adep_w => [
1219         'addressbookeditpersonwin_width',
1220         $xl::s{l_win_w},
1221         $xl::s{h_win_w},
1222         'int,0,3000', # 0 pixels - 3000 pixels
1223         '0.0.0',
1224         '640',
1225         undef,
1226     ],
1227     adep_h => [
1228         'addressbookeditpersonwin_height',
1229         $xl::s{l_win_h},
1230         $xl::s{h_win_h},
1231         'int,0,3000', # 0 pixels - 3000 pixels
1232         '0.0.0',
1233         '320',
1234         undef,
1235     ],
1236     adeg_w => [
1237         'addressbookeditgroupwin_width',
1238         $xl::s{l_win_w},
1239         $xl::s{h_win_w},
1240         'int,0,3000', # 0 pixels - 3000 pixels
1241         '0.0.0',
1242         '580',
1243         undef,
1244     ],
1245     adeg_h => [
1246         'addressbookeditgroupwin_height',
1247         $xl::s{l_win_h},
1248         $xl::s{h_win_h},
1249         'int,0,3000', # 0 pixels - 3000 pixels
1250         '0.0.0',
1251         '340',
1252         undef,
1253     ],
1254     adda_w => [
1255         'addressaddwin_width',
1256         $xl::s{l_win_w},
1257         $xl::s{h_win_w},
1258         'int,0,3000', # 0 pixels - 3000 pixels
1259         '0.0.0',
1260         '300',
1261         undef,
1262     ],
1263     adda_h => [
1264         'addressaddwin_height',
1265         $xl::s{l_win_h},
1266         $xl::s{h_win_h},
1267         'int,0,3000', # 0 pixels - 3000 pixels
1268         '0.0.0',
1269         '-1',
1270         undef,
1271     ],
1272     addf_w => [
1273         'addressbook_folderselwin_width',
1274         $xl::s{l_win_w},
1275         $xl::s{h_win_w},
1276         'int,0,3000', # 0 pixels - 3000 pixels
1277         '0.0.0',
1278         '300',
1279         undef,
1280     ],
1281     addf_h => [
1282         'addressbook_folderselwin_height',
1283         $xl::s{l_win_h},
1284         $xl::s{h_win_h},
1285         'int,0,3000', # 0 pixels - 3000 pixels
1286         '0.0.0',
1287         '-1',
1288         undef,
1289     ],
1290     acce_w => [
1291         'editaccountwin_width',
1292         $xl::s{l_win_w},
1293         $xl::s{h_win_w},
1294         'int,0,3000', # 0 pixels - 3000 pixels
1295         '0.0.0',
1296         '500',
1297         undef,
1298     ],
1299     acce_h => [
1300         'editaccountwin_height',
1301         $xl::s{l_win_h},
1302         $xl::s{h_win_h},
1303         'int,0,3000', # 0 pixels - 3000 pixels
1304         '0.0.0',
1305         '-1',
1306         undef,
1307     ],
1308     acco_w => [
1309         'accountswin_width',
1310         $xl::s{l_win_w},
1311         $xl::s{h_win_w},
1312         'int,0,3000', # 0 pixels - 3000 pixels
1313         '0.0.0',
1314         '500',
1315         undef,
1316     ],
1317     acco_h => [
1318         'accountswin_height',
1319         $xl::s{l_win_h},
1320         $xl::s{h_win_h},
1321         'int,0,3000', # 0 pixels - 3000 pixels
1322         '0.0.0',
1323         '-1',
1324         undef,
1325     ],
1326     filt_w => [
1327         'filteringwin_width',
1328         $xl::s{l_win_w},
1329         $xl::s{h_win_w},
1330         'int,0,3000', # 0 pixels - 3000 pixels
1331         '0.0.0',
1332         '500',
1333         undef,
1334     ],
1335     filt_h => [
1336         'filteringwin_height',
1337         $xl::s{l_win_h},
1338         $xl::s{h_win_h},
1339         'int,0,3000', # 0 pixels - 3000 pixels
1340         '0.0.0',
1341         '-1',
1342         undef,
1343     ],
1344     fila_w => [
1345         'filteringactionwin_width',
1346         $xl::s{l_win_w},
1347         $xl::s{h_win_w},
1348         'int,0,3000', # 0 pixels - 3000 pixels
1349         '0.0.0',
1350         '490',
1351         undef,
1352     ],
1353     fila_h => [
1354         'filteringactionwin_height',
1355         $xl::s{l_win_h},
1356         $xl::s{h_win_h},
1357         'int,0,3000', # 0 pixels - 3000 pixels
1358         '0.0.0',
1359         '-1',
1360         undef,
1361     ],
1362     fild_w => [
1363         'filtering_debugwin_width',
1364         $xl::s{l_win_w},
1365         $xl::s{h_win_w},
1366         'int,0,3000', # 0 pixels - 3000 pixels
1367         '0.0.0',
1368         '600',
1369         undef,
1370     ],
1371     fild_h => [
1372         'filtering_debugwin_height',
1373         $xl::s{l_win_h},
1374         $xl::s{h_win_h},
1375         'int,0,3000', # 0 pixels - 3000 pixels
1376         '0.0.0',
1377         '-1',
1378         undef,
1379     ],
1380     matc_w => [
1381         'matcherwin_width',
1382         $xl::s{l_win_w},
1383         $xl::s{h_win_w},
1384         'int,0,3000', # 0 pixels - 3000 pixels
1385         '0.0.0',
1386         '520',
1387         undef,
1388     ],
1389     matc_h => [
1390         'matcherwin_height',
1391         $xl::s{l_win_h},
1392         $xl::s{h_win_h},
1393         'int,0,3000', # 0 pixels - 3000 pixels
1394         '0.0.0',
1395         '-1',
1396         undef,
1397     ],
1398     pref_w => [
1399         'prefswin_width',
1400         $xl::s{l_win_w},
1401         $xl::s{h_win_w},
1402         'int,0,3000', # 0 pixels - 3000 pixels
1403         '0.0.0',
1404         '600',
1405         undef,
1406     ],
1407     pref_h => [
1408         'prefswin_height',
1409         $xl::s{l_win_h},
1410         $xl::s{h_win_h},
1411         'int,0,3000', # 0 pixels - 3000 pixels
1412         '0.0.0',
1413         '-1',
1414         undef,
1415     ],
1416     temp_w => [
1417         'templateswin_width',
1418         $xl::s{l_win_w},
1419         $xl::s{h_win_w},
1420         'int,0,3000', # 0 pixels - 3000 pixels
1421         '0.0.0',
1422         '480',
1423         undef,
1424     ],
1425     temp_h => [
1426         'templateswin_height',
1427         $xl::s{l_win_h},
1428         $xl::s{h_win_h},
1429         'int,0,3000', # 0 pixels - 3000 pixels
1430         '0.0.0',
1431         '-1',
1432         undef,
1433     ],
1434     acti_w => [
1435         'actionswin_width',
1436         $xl::s{l_win_w},
1437         $xl::s{h_win_w},
1438         'int,0,3000', # 0 pixels - 3000 pixels
1439         '0.0.0',
1440         '486',
1441         undef,
1442     ],
1443     acti_h => [
1444         'actionswin_height',
1445         $xl::s{l_win_h},
1446         $xl::s{h_win_h},
1447         'int,0,3000', # 0 pixels - 3000 pixels
1448         '0.0.0',
1449         '-1',
1450         undef,
1451     ],
1452     tags_w => [
1453         'tagswin_width',
1454         $xl::s{l_win_w},
1455         $xl::s{h_win_w},
1456         'int,0,3000', # 0 pixels - 3000 pixels
1457         '0.0.0',
1458         '486',
1459         undef,
1460     ],
1461     tags_h => [
1462         'tagswin_height',
1463         $xl::s{l_win_h},
1464         $xl::s{h_win_h},
1465         'int,0,3000', # 0 pixels - 3000 pixels
1466         '0.0.0',
1467         '-1',
1468         undef,
1469     ],
1470     plug_w => [
1471         'pluginswin_width',
1472         $xl::s{l_win_w},
1473         $xl::s{h_win_w},
1474         'int,0,3000', # 0 pixels - 3000 pixels
1475         '0.0.0',
1476         '-1',
1477         undef,
1478     ],
1479     plug_h => [
1480         'pluginswin_height',
1481         $xl::s{l_win_h},
1482         $xl::s{h_win_h},
1483         'int,0,3000', # 0 pixels - 3000 pixels
1484         '0.0.0',
1485         '-1',
1486         undef,
1487     ],
1488     logw_w => [
1489         'logwin_width',
1490         $xl::s{l_win_w},
1491         $xl::s{h_win_w},
1492         'int,0,3000', # 0 pixels - 3000 pixels
1493         '0.0.0',
1494         '520',
1495         undef,
1496     ],
1497     logw_h => [
1498         'logwin_height',
1499         $xl::s{l_win_h},
1500         $xl::s{h_win_h},
1501         'int,0,3000', # 0 pixels - 3000 pixels
1502         '0.0.0',
1503         '-1',
1504         undef,
1505     ],
1506     prin_w => [
1507         'print_previewwin_width',
1508         $xl::s{l_win_w},
1509         $xl::s{h_win_w},
1510         'int,0,3000', # 0 pixels - 3000 pixels
1511         '0.0.0',
1512         '600',
1513         undef,
1514     ],
1515     prin_h => [
1516         'print_previewwin_height',
1517         $xl::s{l_win_h},
1518         $xl::s{h_win_h},
1519         'int,0,3000', # 0 pixels - 3000 pixels
1520         '0.0.0',
1521         '-1',
1522         undef,
1523     ],
1524 );
1525
1526 sub new_winpos_subpage_main() {
1527     return &new_subpage_frame (
1528                &new_vbox_pack (
1529                    &new_text_box_for_int (\%pr::win, 'main_x'), 
1530                    &new_text_box_for_int (\%pr::win, 'main_y'), 
1531                    &new_text_box_for_int (\%pr::win, 'main_w'), 
1532                    &new_text_box_for_int (\%pr::win, 'main_h'), 
1533                    &new_hbox_pack (
1534                        &new_check_button_for (\%pr::win, 'main_fs'), 
1535                        &new_check_button_for (\%pr::win, 'main_mx'))),
1536                _('Main window')
1537            );
1538 }
1539
1540 sub new_winpos_subpage_msgs() {
1541     return &new_subpage_frame (
1542                &new_vbox_pack (
1543                    &new_text_box_for_int (\%pr::win, 'msgs_x'),
1544                    &new_text_box_for_int (\%pr::win, 'msgs_y'),
1545                    &new_text_box_for_int (\%pr::win, 'msgs_w'),
1546                    &new_text_box_for_int (\%pr::win, 'msgs_h')),
1547                _('Message window')
1548            );
1549 }
1550
1551 sub new_winpos_subpage_sendrecv() {
1552     return &new_vbox_pack (
1553                &new_subpage_frame (
1554                    &new_vbox_pack (
1555                        &new_hbox_pack (
1556                            &new_text_box_for_int (\%pr::win, 'send_w'),
1557                            &new_text_box_for_int (\%pr::win, 'send_h'))),
1558                    _('Send window'), 'not-packed'),
1559                &new_subpage_frame (
1560                    &new_vbox_pack (
1561                        &new_hbox_pack (
1562                            &new_text_box_for_int (\%pr::win, 'recv_w'),
1563                            &new_text_box_for_int (\%pr::win, 'recv_h'))),
1564                    _('Receive window'), 'not-packed')
1565            );
1566 }
1567
1568 sub new_winpos_subpage_fold() {
1569     return &new_vbox_pack (
1570                &new_subpage_frame (
1571                    &new_vbox_pack (
1572                        &new_text_box_for_int (\%pr::win, 'fold_x'), 
1573                        &new_text_box_for_int (\%pr::win, 'fold_y'), 
1574                        &new_text_box_for_int (\%pr::win, 'fold_w'), 
1575                        &new_text_box_for_int (\%pr::win, 'fold_h')),
1576                    _('Folder window'), 'not-packed'),
1577                &new_subpage_frame (
1578                    &new_vbox_pack (
1579                        &new_text_box_for_int (\%pr::win, 'fsel_w'),
1580                        &new_text_box_for_int (\%pr::win, 'fsel_h')),
1581                    _('Folder selection window'), 'not-packed')
1582            );
1583 }
1584
1585 sub new_winpos_subpage_addrbook() {
1586     return &new_vbox_pack (
1587                 &new_subpage_frame (
1588                      &new_vbox_pack (
1589                           &new_hbox_pack (
1590                                &new_text_box_for_int (\%pr::win, 'addr_w'),
1591                                &new_text_box_for_int (\%pr::win, 'addr_h'))),
1592                      _('Addressbook main window'), 'not-packed'),
1593                 &new_subpage_frame (
1594                      &new_vbox_pack (
1595                           &new_hbox_pack (
1596                                &new_text_box_for_int (\%pr::win, 'adep_w'),
1597                                &new_text_box_for_int (\%pr::win, 'adep_h'))),
1598                      _('Edit person window'), 'not-packed'),
1599                 &new_subpage_frame (
1600                      &new_vbox_pack (
1601                           &new_hbox_pack (
1602                                &new_text_box_for_int (\%pr::win, 'adeg_w'),
1603                                &new_text_box_for_int (\%pr::win, 'adeg_h'))),
1604                      _('Edit group window'), 'not-packed'),
1605                 &new_subpage_frame (
1606                      &new_vbox_pack (
1607                           &new_hbox_pack (
1608                                &new_text_box_for_int (\%pr::win, 'adda_w'),
1609                                &new_text_box_for_int (\%pr::win, 'adda_h'))),
1610                      _('Add address window'), 'not-packed'),
1611                 &new_subpage_frame (
1612                      &new_vbox_pack (
1613                           &new_hbox_pack (
1614                                &new_text_box_for_int (\%pr::win, 'addf_w'),
1615                                &new_text_box_for_int (\%pr::win, 'addf_h'))),
1616                      _('Folder select window'), 'not-packed')
1617            );
1618 }
1619
1620 sub new_winpos_subpage_accounts() {
1621     return &new_vbox_pack (
1622                 &new_subpage_frame (
1623                      &new_vbox_pack (
1624                           &new_hbox_pack (
1625                                &new_text_box_for_int (\%pr::win, 'acco_w'),
1626                                &new_text_box_for_int (\%pr::win, 'acco_h'))),
1627                      _('Accounts window'), 'not-packed'),
1628                 &new_subpage_frame (
1629                      &new_vbox_pack (
1630                           &new_hbox_pack (
1631                                &new_text_box_for_int (\%pr::win, 'acce_w'),
1632                                &new_text_box_for_int (\%pr::win, 'acce_h'))),
1633                      _('Edit account window'), 'not-packed')
1634            );
1635 }
1636
1637 sub new_winpos_subpage_filtering() {
1638     return &new_vbox_pack (
1639                 &new_subpage_frame (
1640                      &new_vbox_pack (
1641                           &new_hbox_pack (
1642                                &new_text_box_for_int (\%pr::win, 'filt_w'),
1643                                &new_text_box_for_int (\%pr::win, 'filt_h'))),
1644                      _('Filtering window'), 'not-packed'),
1645                 &new_subpage_frame (
1646                      &new_vbox_pack (
1647                           &new_hbox_pack (
1648                                &new_text_box_for_int (\%pr::win, 'fila_w'),
1649                                &new_text_box_for_int (\%pr::win, 'fila_h'))),
1650                      _('Filtering actions window'), 'not-packed'),
1651                 &new_subpage_frame (
1652                      &new_vbox_pack (
1653                           &new_hbox_pack (
1654                                &new_text_box_for_int (\%pr::win, 'fild_w'),
1655                                &new_text_box_for_int (\%pr::win, 'fild_h'))),
1656                      _('Filtering debug window'), 'not-packed'),
1657                 &new_subpage_frame (
1658                      &new_vbox_pack (
1659                           &new_hbox_pack (
1660                                &new_text_box_for_int (\%pr::win, 'matc_w'),
1661                                &new_text_box_for_int (\%pr::win, 'matc_h'))),
1662                      _('Matcher window'), 'not-packed')
1663            );
1664 }
1665
1666 sub new_winpos_subpage_prefs() {
1667     return &new_vbox_pack (
1668                 &new_subpage_frame (
1669                      &new_vbox_pack (
1670                           &new_hbox_pack (
1671                                &new_text_box_for_int (\%pr::win, 'pref_w'),
1672                                &new_text_box_for_int (\%pr::win, 'pref_h'))),
1673                      _('Preferences window'), 'not-packed'),
1674                 &new_subpage_frame (
1675                      &new_vbox_pack (
1676                           &new_hbox_pack (
1677                                &new_text_box_for_int (\%pr::win, 'temp_w'),
1678                                &new_text_box_for_int (\%pr::win, 'temp_h'))),
1679                      _('Templates window'), 'not-packed'),
1680                 &new_subpage_frame (
1681                      &new_vbox_pack (
1682                           &new_hbox_pack (
1683                                &new_text_box_for_int (\%pr::win, 'acti_w'),
1684                                &new_text_box_for_int (\%pr::win, 'acti_h'))),
1685                      _('Actions window'), 'not-packed'),
1686                 &new_subpage_frame (
1687                      &new_vbox_pack (
1688                           &new_hbox_pack (
1689                                &new_text_box_for_int (\%pr::win, 'tags_w'),
1690                                &new_text_box_for_int (\%pr::win, 'tags_h'))),
1691                      _('Tags window'), 'not-packed'),
1692                 &new_subpage_frame (
1693                      &new_vbox_pack (
1694                           &new_hbox_pack (
1695                                &new_text_box_for_int (\%pr::win, 'plug_w'),
1696                                &new_text_box_for_int (\%pr::win, 'plug_h'))),
1697                      _('Plugins window'), 'not-packed')
1698            );
1699 }
1700
1701 sub new_winpos_subpage_misc() {
1702     return &new_vbox_pack (
1703                 &new_subpage_frame (
1704                      &new_vbox_pack (
1705                           &new_hbox_pack (
1706                                &new_text_box_for_int (\%pr::win, 'logw_w'),
1707                                &new_text_box_for_int (\%pr::win, 'logw_h'))),
1708                      _('Log window'), 'not-packed'),
1709                 &new_subpage_frame (
1710                      &new_vbox_pack (
1711                           &new_hbox_pack (
1712                                &new_text_box_for_int (\%pr::win, 'prin_w'),
1713                                &new_text_box_for_int (\%pr::win, 'prin_h'))),
1714                      _('Print preview window'), 'not-packed'),
1715                 &new_subpage_frame (
1716                      &new_vbox_pack (
1717                           &new_text_box_for_int (\%pr::win, 'sour_w'),
1718                           &new_text_box_for_int (\%pr::win, 'sour_h')),
1719                      _('View source window'), 'not-packed')
1720            );
1721 }
1722
1723 sub new_winpos_page() {
1724     my $winbook = Gtk2::Notebook->new;
1725     $winbook->set_tab_pos ('right');
1726     $winbook->append_page (&new_winpos_subpage_main, _('Main'));
1727     $winbook->append_page (&new_winpos_subpage_msgs, _('Message'));
1728     $winbook->append_page (&new_winpos_subpage_sendrecv, _('Send/Receive'));
1729     $winbook->append_page (&new_winpos_subpage_fold, _('Folder'));
1730     $winbook->append_page (&new_winpos_subpage_addrbook, _('Addressbook'));
1731     $winbook->append_page (&new_winpos_subpage_accounts, _('Accounts'));
1732     $winbook->append_page (&new_winpos_subpage_filtering, _('Filtering'));
1733     $winbook->append_page (&new_winpos_subpage_prefs, _('Preferences'));
1734     $winbook->append_page (&new_winpos_subpage_misc, _('Other'));
1735     return $winbook;
1736 }
1737
1738 # version info
1739 sub print_version() {
1740     print $xl::s{about_title} . "\n";
1741     print $xl::s{about_version} . " $VERSION\n";
1742     print "Perl-GLib " . $Glib::VERSION;
1743     # version info stuff appeared in 1.040
1744     if ($Glib::VERSION >= 1.040) {
1745         print _(", built for ") . join(".", Glib->GET_VERSION_INFO) 
1746               . _(", running with ") . join(".", &Glib::major_version, 
1747                   &Glib::minor_version, &Glib::micro_version);
1748     }
1749     print "\n";
1750     print "Perl-GTK2 " . $Gtk2::VERSION;
1751     if ($Gtk2::VERSION >= 1.040) {
1752         print _(", built for ") . join(".", Gtk2->GET_VERSION_INFO)
1753               . _(", running with ") . join(".", &Gtk2::major_version, 
1754                   &Gtk2::minor_version, &Gtk2::micro_version);
1755     }
1756     print "\n";
1757     my $clawsver = ($CLAWSV eq "") ? 
1758                 _("was not found!") : 
1759                 (_("returned version ") . $CLAWSV);
1760     print "Claws Mail " . $clawsver . "\n";
1761 }
1762
1763 # the command line help
1764 sub print_help() {
1765     my $line = '-' x length ($xl::s{about_title}) . "\n";
1766     print $line;
1767     print $xl::s{about_title} . "\n";
1768     print $line;
1769     print _("Syntax:\n");
1770     print _("    clawsker [options]\n");
1771     print _("Options:\n");
1772     print _("    --help                         Prints this help screen.\n");
1773     print _("    --version                      Prints version infos.\n");
1774     print _("    --verbose                      More messages on standard output.\n");
1775     print _("    --alternate-config-dir <dir>   Uses <dir> as Claws Mail config dir.\n");
1776     print _("    --clawsrc <file>               Uses <file> as full resource name.\n");
1777 }
1778
1779 # handle errors which don't allow to run
1780 sub command_line_fatal() {
1781     my $reason = shift;
1782     my $emsg = $xl::s{e_error} . $reason;
1783     error_dialog ($emsg);
1784     log_message ("$emsg", 'die');
1785 }
1786
1787 # parse the command line
1788 sub parse_command_line() {
1789     $CLAWSV = &get_claws_version;
1790     my $arg = 0;
1791     while (defined($ARGV[$arg])) {
1792         for ($ARGV[$arg]) {
1793             /--help/ && do { 
1794                 &print_help; 
1795                 return FALSE;
1796             };
1797             /--version/ && do { 
1798                 &print_version; 
1799                 return FALSE;
1800             };
1801             /--verbose/ && do {
1802                 $VERBOSE = TRUE;
1803                 last;
1804             };
1805             /--use-claws-version/ && do {
1806                 ++$arg;
1807                 &command_line_fatal ("required version")
1808                     unless defined($ARGV[$arg]);
1809                 &command_line_fatal ("required a dotted numeric value")
1810                     unless ($ARGV[$arg] =~ /[\d\.]+/);
1811                 $CLAWSV = $ARGV[$arg];
1812                 last;
1813             };
1814             /--alternate-config-dir/ && do {
1815                 ++$arg;
1816                 &command_line_fatal ($xl::s{e_requireddir})
1817                     unless defined($ARGV[$arg]);
1818                 &command_line_fatal ($xl::s{e_notadir})
1819                     unless -d $ARGV[$arg];
1820                 $CONFIGDIR = $ARGV[$arg];
1821                 $CONFIGDIR .= "/" 
1822                     unless ($CONFIGDIR =~ /.*\/$/);
1823                 $ALTCONFIGDIR = TRUE;
1824                 last;
1825             };
1826             /--clawsrc/ && do {
1827                 ++$arg;
1828                 &command_line_fatal($xl::s{e_requiredfile}) 
1829                     unless defined($ARGV[$arg]);
1830                 &command_line_fatal($xl::s{e_notafile}) 
1831                     unless -f $ARGV[$arg];
1832                 &set_rc_filename ($ARGV[$arg]);
1833                 last;
1834             };
1835             /.*/ && &command_line_fatal (
1836                         _("unknown option '{opt}'.\n", opt => $ARGV[$arg]));
1837         }
1838         ++$arg;
1839     }
1840     # eveything continues...
1841     return TRUE;
1842 }
1843
1844 # update the hidden preferences status from loaded values
1845 sub init_hidden_preferences() {
1846     foreach my $hash (\%pr::beh, \%pr::col, \%pr::gui, \%pr::oth, \%pr::win) {
1847         foreach my $key (keys %$hash) { 
1848             $HPVALUE{${$hash}{$key}[NAME]} = $PREFS{${$hash}{$key}[NAME]};
1849         }
1850     }
1851     return TRUE;
1852 }
1853
1854 # load current status from disc
1855 sub load_preferences() {
1856     my $rc = &get_rc_filename;
1857     &log_message ("Loading preferences from $rc\n");
1858     return FALSE unless &check_rc_file ($rc);
1859     return FALSE unless &check_claws_not_running;
1860     open (RCF, "<$rc");
1861     while (<RCF>) {
1862         chomp;
1863         if (/^([8a-z_]+)=(.*)$/) {
1864             $PREFS{$1} = "$2";
1865         }
1866     }
1867     close (RCF);
1868     return TRUE;
1869 }
1870
1871 # save current preferences to disc
1872 sub save_preferences() {
1873     my $rc = &get_rc_filename;
1874     &log_message ("Saving preferences to $rc\n");
1875     return FALSE unless &check_rc_file ($rc);
1876     return FALSE unless &check_claws_not_running;
1877     my $rcbak = "$rc.backup";
1878     rename ($rc, $rcbak);
1879     open (RCF, ">$rc");
1880     open (RCB, "<$rcbak");
1881     while (<RCB>) {
1882         chomp;
1883         if (/^([8a-z_]+)=(.*)$/) {
1884             if (defined($HPVALUE{$1})) {
1885                 print RCF $1 . "=" . $HPVALUE{$1} . "\n";
1886             }
1887             else {
1888                 print RCF $_ . "\n";
1889             }
1890         }
1891         else {
1892             print RCF $_ . "\n";
1893         }
1894     }
1895     close (RCB);
1896     close (RCF);
1897     return TRUE;
1898 }
1899
1900 # create notebook
1901 sub new_notebook() {
1902     my $nb = Gtk2::Notebook->new;
1903     # 
1904     $nb->append_page (&new_behaviour_page, $xl::s{tab_behaviour});
1905     $nb->append_page (&new_colours_page, $xl::s{tab_colours});
1906     $nb->append_page (&new_gui_page, $xl::s{tab_gui});
1907     $nb->append_page (&new_other_page, $xl::s{tab_other});
1908     $nb->append_page (&new_winpos_page, $xl::s{tab_winpos});
1909
1910     return $nb;
1911 }
1912
1913 # create an about dialog
1914 sub new_about_dialog() {
1915     my ($parent) = @_;
1916     my $title = $xl::s{about_title};
1917     my $lic = $xl::s{about_license};
1918     my $vers = $xl::s{about_version} . " $VERSION";
1919     my $license = 
1920 "This program is free software: you can redistribute it and/or modify
1921 it under the terms of the GNU General Public License as published by
1922 the Free Software Foundation, either version 3 of the License, or
1923 (at your option) any later version.
1924
1925 This program is distributed in the hope that it will be useful,
1926 but WITHOUT ANY WARRANTY; without even the implied warranty of
1927 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1928 GNU General Public License for more details.
1929
1930 You should have received a copy of the GNU General Public License
1931 along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.";
1932     my $year = "2007-2009";
1933     my $holder = "Ricardo Mones &lt;ricardo\@mones.org&gt;";
1934     my $url = "http://www.claws-mail.org/clawsker";
1935
1936     my $dialog = Gtk2::MessageDialog->new_with_markup ($parent, 
1937                     [qw/modal destroy-with-parent/], 
1938                     'info', 'close', 
1939                     "<span size=\"x-large\" weight=\"bold\">$title</span>\n"
1940                     . "<span size=\"large\">$vers</span>\n\n"
1941                     . "<span color=\"blue\" size=\"large\">$url</span>\n\n"
1942                     . "<span>Copyright $year by $holder</span>\n\n"
1943                     . "<span size=\"large\">$lic</span>\n\n"
1944                     . "<span size=\"small\">$license</span>");
1945     $dialog->set_title ($xl::s{about});
1946     #
1947     return $dialog;
1948 }
1949
1950 # create buttons box
1951 sub new_button_box() {
1952     my ($parent, $adlg) = @_;
1953     my $b_about = Gtk2::Button->new_from_stock ('gtk-about');
1954     my $b_exit = Gtk2::Button->new_from_stock ('gtk-quit');
1955     my $b_apply = Gtk2::Button->new_from_stock ('gtk-apply');
1956     # disable button until is really implemented
1957     # my $b_undo = Gtk2::Button->new_from_stock ('gtk-undo');
1958     my $hbox = Gtk2::HBox->new (FALSE, 5);
1959     # signal handlers 
1960     $b_exit->signal_connect (clicked => sub { Gtk2->main_quit });
1961     $b_apply->signal_connect (clicked => sub { &save_preferences ($parent) });
1962     # $b_undo->signal_connect (clicked => sub { &undo_current_changes });
1963     $b_about->signal_connect (clicked => sub { $adlg->run; $adlg->hide });
1964     # package them
1965     $hbox->pack_end ($b_apply, FALSE, FALSE, 0);
1966     $hbox->pack_end ($b_exit, FALSE, FALSE, 0);
1967     # $hbox->pack_end ($b_undo, FALSE, FALSE, 0);
1968     $hbox->pack_start ($b_about, FALSE, FALSE, 0);
1969     #
1970     return $hbox;
1971 }
1972
1973 # initialise
1974 $main_window = Gtk2::Window->new ('toplevel');
1975 exit unless &parse_command_line;
1976 exit unless &load_preferences;
1977 exit unless &init_hidden_preferences;
1978 # create main GUI
1979 my $box = Gtk2::VBox->new (FALSE, 5);
1980 $box->set_border_width(3);
1981 my $about = &new_about_dialog;
1982 $box->pack_start (&new_notebook, FALSE, FALSE, 0);
1983 $box->pack_end (&new_button_box ($main_window, $about), FALSE, FALSE, 0);
1984 $main_window->signal_connect (delete_event => sub { Gtk2->main_quit });
1985 $main_window->set_title ($xl::s{win_title});
1986 $main_window->add ($box);
1987 $main_window->show_all;
1988 Gtk2->main;
1989