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