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