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