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