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