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