Restore ability to show dialog on error
[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;
21 use POSIX qw(setlocale);
22 use Locale::gettext;
23 use Encode;
24 use Digest::MD5 qw(md5_hex);
25 use Getopt::Long;
26
27 my $NAME = 'clawsker';
28 my $PREFIX = '@PREFIX@';
29 my $LIBDIR = '@LIBDIR@';
30 my $VERSION = '@VERSION@';
31 my $VERBOSE = FALSE;
32 my $CLAWSV = undef;
33 my $main_window = undef;
34
35 my $locale = (defined($ENV{LC_MESSAGES}) ? $ENV{LC_MESSAGES} : $ENV{LANG});
36 $locale = "C" unless defined($locale);
37 setlocale (LC_ALL, $locale);
38 bindtextdomain ($NAME, sprintf ('%s/share/locale', $PREFIX));
39 textdomain ($NAME);
40
41 my $SHOWHINTS = FALSE;
42 $SHOWHINTS = TRUE if ($Gtk2::VERSION >= 1.040 and Gtk2->CHECK_VERSION (2, 12, 0));
43
44 sub _ {
45     my $str = shift;
46     my %par = @_;
47     my $xla = gettext ($str);
48     if (scalar(keys(%par)) > 0) {
49         foreach my $key (keys %par) {
50             $xla =~ s/\{$key\}/$par{$key}/g;
51         }
52     }
53     return decode_utf8($xla);
54 }
55
56 # default messages
57 %xl::s = (
58     win_title => _('Claws Mail Hidden Preferences'),
59     about => _('About...'),
60     about_title => _('Clawsker :: A Claws Mail Tweaker'),
61     about_license => _('License:'),
62     about_version => _('Version:'),
63
64     tab_colours => _('Colours'),
65     tab_behaviour => _('Behaviour'),
66     tab_gui => _('GUI'),
67     tab_other => _('Other'),
68     tab_winpos => _('Windows'),
69
70     ab_frame => _('Addressbook'),
71     mem_frame => _('Memory'),
72     msgview_frame => _('Message View'),
73     log_frame => _('Log window'),
74     dnd_frame => _('Drag \'n\' drop'),
75     ssl_frame => _('Secure Sockets Layer'),
76     msgs_frame => _('Messages'),
77     swc_frame => _('Completion'),
78     stripes_frame => _('Coloured stripes'),
79     sbar_frame => _('Scroll bars'),
80     mlist_frame => _('Message List'),
81     mview_frame => _('Message View'),
82     compo_frame => _('Compose window'),
83     netm_frame => _('NetworkManager'),
84     diff_frame => _('Viewing patches'),
85
86     l_oth_use_dlg => _('Use detached address book edit dialogue'),
87     h_oth_use_dlg => _('If true use a separate dialogue to edit a person\'s details. Otherwise will use a form embedded in the address book\'s main window.'),
88     l_oth_max_use => _('Maximum memory for message cache (kB)'),
89     h_oth_max_use => _('The maximum amount of memory to use to cache messages, in kilobytes.'),
90     l_oth_min_time => _('Minimun time for cache elements (minutes)'),
91     h_oth_min_time => _('The minimum time in minutes to keep a cache in memory. Caches more recent than this time will not be freed, even if the memory usage is too high.'),
92     l_oth_use_netm => _('Use NetworkManager'),
93     h_oth_use_netm => _('Use NetworkManager to switch offline automatically.'),
94     
95     l_gui_b_unread => _('Show unread messages with bold font'),
96     h_gui_b_unread => _('Show unread messages in the Message List using a bold font.'),
97     l_gui_no_markup => _('Don\'t use markup in compose window'),
98     h_gui_no_markup => _('Don\'t use bold and italic text in Compose dialogue\'s account selector.'),
99     l_gui_dot_lines => _('Use dotted lines in tree view components'),
100     h_gui_dot_lines => _('Use the old dotted line look in the main window tree views (Folder, Message and other lists) instead of the modern lineless look.'),
101     l_gui_h_scroll => _('Enable horizontal scrollbar'),
102     h_gui_h_scroll => _('Enable the horizontal scrollbar in the Message List.'),
103     l_gui_swp_from => _('Display To column instead From column in Sent folder'),
104     h_gui_swp_from => _('Display the recipient\'s email address in a To column of the Sent folder instead of the originator\'s one in a From column.'),
105     l_gui_v_scroll => _('Folder List scrollbar behaviour'),
106     h_gui_v_scroll => _('Specify the policy of vertical scrollbar of Folder List: show always, automatic or hide always.'),
107     l_gui_v_scroll_show => _('Show always'),
108     l_gui_v_scroll_auto => _('Automatic'),
109     l_gui_v_scroll_hide => _('Hide always'),
110     l_gui_from_show => _('From column displays'),
111     h_gui_from_show => _('Selects the data displayed in the From column of the Message List: name, address or both'),
112     l_gui_from_show_name => _('Name only'),
113     l_gui_from_show_addr => _('Address only'),
114     l_gui_from_show_both => _('Both name and address'),
115     l_gui_strip_off => _('Coloured lines contrast'),
116     h_gui_strip_off => _('Specify the value to use when creating alternately coloured lines in tree view components. The smaller the value, the less visible the difference in the alternating colours of the lines.'),
117     l_gui_cursor_v => _('Show cursor'),
118     h_gui_cursor_v => _('Display the cursor in the Message View.'),
119     l_gui_toolbar_d => _('Detachable toolbars'),
120     h_gui_toolbar_d => _('Show handles in the toolbars.'),
121     l_gui_strip_all => _('Use stripes in all tree view components'),
122     h_gui_strip_all => _('Enable alternately coloured lines in all tree view components.'),
123     l_gui_strip_sum => _('Use stripes in Folder List and Message List'),
124     h_gui_strip_sum => _('Enable alternately coloured lines in Message List and Folder List.'),
125     l_gui_two_line_v => _('2 lines per Message List item in 3-column layout'),
126     h_gui_two_line_v => _('Spread Message List information over two lines when using the three column mode.'),
127     l_gui_margin_co => _('Show compose margin'),
128     h_gui_margin_co => _('Shows a small margin in the Compose View.'),
129     l_gui_mview_date => _('Don\'t display localized date'),
130     h_gui_mview_date => _('Toggles localization of date format in Message View'),
131     l_gui_zero_char => _('Zero replacement character'),
132     h_gui_zero_char => _('Replaces \'0\' with the given character in Folder List'),
133
134     l_beh_hover_t => _('Drag \'n\' drop hover timeout (ms)'),
135     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.'),
136     l_beh_dangerous => _('Don\'t confirm deletions (dangerous!)'),
137     h_beh_dangerous => _('Don\'t ask for confirmation before definitive deletion of emails.'),
138     l_beh_flowed => _('Respect format=flowed in messages'),
139     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.'),
140     l_beh_parts_rw => _('Allow writable temporary files'),
141     h_beh_parts_rw => _('Saves temporary files when opening attachment with write bit set.'),
142     l_beh_skip_ssl => _('Don\'t check SSL certificates'),
143     h_beh_skip_ssl => _('Disables the verification of SSL certificates.'),
144     l_beh_up_step => _('Progress bar update step (items)'),
145     h_beh_up_step => _('Update stepping in progress bars.'),
146     l_beh_thread_a => _('Maximum age when threading by subject (days)'),
147     h_beh_thread_a => _('Number of days to include a message in a thread when using "Thread using subject in addition to standard headers".'),
148     l_beh_unsafe_ssl => _('Allow unsafe SSL certificates'),
149     h_beh_unsafe_ssl => _('Allows Claws Mail to remember multiple SSL certificates for a given server/port.'),
150     l_beh_use_utf8 => _('Force UTF-8 for broken mails'),
151     h_beh_use_utf8 => _('Use UTF-8 encoding for broken mails instead of current locale.'),
152     l_beh_warn_dnd => _('Warn on drag \'n\' drop'),
153     h_beh_warn_dnd => _('Display a confirmation dialogue on drag \'n\' drop of folders.'),
154     l_beh_out_ascii => _('Outgoing messages fallback to ASCII'),
155     h_beh_out_ascii => _('If content allows, ASCII will be used to encode outgoing messages, otherwise the user-defined encoding is enforced always.'),
156     l_beh_pp_unsel => _('Primary paste unselects selection'),
157     h_beh_pp_unsel => _('Controls how pasting using middle-click changes the selected text and insertion point.'),
158     l_beh_inline_at => _('Show inline attachments'),
159     h_beh_inline_at => _('Allows hiding inline attachments already shown in mail structure view'),
160     l_beh_addr_swc => _('Address search in compose window matches any'),
161     h_beh_addr_swc => _('On Tab-key completion, address text will match any part of the string or only the from the start'),
162     l_beh_fold_swc => _('Folder search in folder selector matches any'),
163     h_beh_fold_swc => _('On folder name completion text will match any part of the string or only from the start'),
164
165     l_col_emphasis => _('X-Mailer header'),
166     h_col_emphasis => _('The colour used for the X-Mailer line when its value is Claws Mail.'),
167     l_col_log_err => _('Error messages'),
168     h_col_log_err => _('Colour for error messages in log window.'),
169     l_col_log_in => _('Server messages'),
170     h_col_log_in => _('Colour for messages received from servers in log window.'),
171     l_col_log_msg => _('Standard messages'),
172     h_col_log_msg => _('Colour for messages in log window.'),
173     l_col_log_out => _('Client messages'),
174     h_col_log_out => _('Colour for messages sent to servers in log window.'),
175     l_col_log_warn => _('Warnings'),
176     h_col_log_warn => _('Colour for warning messages in log window.'),
177
178     l_col_diff_add => _('Added lines'),
179     h_col_diff_add => _('Colour for added lines in patches.'),
180     l_col_diff_del => _('Deleted lines'),
181     h_col_diff_del => _('Colour for deleted lines in patches.'),
182     l_col_diff_hunk => _('Hunk lines'),
183     h_col_diff_hunk => _('Color for hunk headers in patches.'),
184
185     l_win_x => _('X position'),
186     h_win_x => _('X coordinate for window\'s top-left corner.'),
187     l_win_y => _('Y position'),
188     h_win_y => _('Y coordinate for window\'s top-left corner.'),
189     l_win_w => _('Width'),
190     h_win_w => _('Window\'s width in pixels.'),
191     l_win_h => _('Height'),
192     h_win_h => _('Window\'s height in pixels.'),
193
194     l_win_main_mx => _('Maximized'),
195     h_win_main_mx => _('Changes window maximized status.'),
196     l_win_main_fs => _('Full-screen'),
197     h_win_main_fs => _('Changes full screen status.'),
198
199     e_error => _('Error: '),
200     e_noclawsrc => _('resource file for Claws Mail was not found.'),
201     e_running => _('seems Claws Mail is currently running, close it first.'),
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 (_('Clawsker error'));
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 _("  -h|--help                        Prints this help screen.\n");
1888     print _("  -v|--version                     Prints version infos.\n");
1889     print _("  -b|--verbose                     More messages on standard output.\n");
1890     print _("  -a|--alternate-config-dir <dir>  Uses <dir> as Claws Mail config dir.\n");
1891     print _("  -c|--clawsrc <file>              Uses <file> as full resource name.\n");
1892 }
1893
1894 sub parse_command_line {
1895     my $cont = TRUE;
1896     $CLAWSV = get_claws_version ();
1897     eval {
1898         GetOptions('h|help' => sub { print_help (); $cont = FALSE },
1899             'v|version' => sub { print_version (); $cont = FALSE },
1900             'b|verbose' => sub { $VERBOSE = TRUE },
1901             'u|use-claws-version=s' => \&opt_use_claws_version,
1902             'a|alternate-config-dir=s' => \&opt_alternate_config_dir,
1903             'r|clawsrc=s' => \&opt_clawsrc)
1904         or die _("try -h or --help for syntax.\n");
1905     };
1906     if ($@) {
1907         my $msg = _("Error in options: {msg}\n", msg => $@);
1908         if (defined $ENV{'DISPLAY'} and $ENV{'DISPLAY'} ne '') {
1909             eval { Gtk2->init };
1910             error_dialog ($msg) unless $@;
1911         }
1912         die $msg;
1913     }
1914     return $cont;
1915 }
1916
1917 sub opt_use_claws_version {
1918     my ($name, $value) = @_;
1919     die _("Error: {opt} requires a dotted numeric value argument\n", opt => $name)
1920         unless ($value =~ /^[\d\.]+$/);
1921     $CLAWSV = $value;
1922 }
1923
1924 sub opt_alternate_config_dir {
1925     my ($name, $value) = @_;
1926     die _("Error: '{dir}' is not a directory or does not exist\n", dir => $value)
1927         unless -d $value;
1928     $CONFIGDIR = $value;
1929     $CONFIGDIR .= "/" unless ($CONFIGDIR =~ /.*\/$/);
1930     $ALTCONFIGDIR = TRUE;
1931 }
1932
1933 sub opt_clawsrc {
1934     my ($name, $value) = @_;
1935     die _("Error: '{value}' is not a file or does not exist", value => $value)
1936         unless -f $value;
1937     set_rc_filename ($value);
1938 }
1939
1940 # update the hidden preferences status from loaded values
1941 sub init_hidden_preferences {
1942     foreach my $hash (\%pr::beh, \%pr::col, \%pr::gui, \%pr::oth, \%pr::win) {
1943         foreach my $key (keys %$hash) { 
1944             $HPVALUE{${$hash}{$key}[NAME]} = $PREFS{${$hash}{$key}[NAME]};
1945         }
1946     }
1947     return TRUE;
1948 }
1949
1950 # load current status from disc
1951 sub load_preferences {
1952     my $rc = get_rc_filename ();
1953     log_message ("Loading preferences from $rc\n");
1954     return FALSE unless check_rc_file ($rc);
1955     return FALSE unless check_claws_not_running ();
1956     open (RCF, "<$rc");
1957     while (<RCF>) {
1958         chomp;
1959         if (/^([8a-z_]+)=(.*)$/) {
1960             $PREFS{$1} = decode('UTF-8', $2);
1961         }
1962     }
1963     close (RCF);
1964     return TRUE;
1965 }
1966
1967 # save current preferences to disc
1968 sub save_preferences {
1969     my $rc = get_rc_filename ();
1970     log_message ("Saving preferences to $rc\n");
1971     return FALSE unless check_rc_file ($rc);
1972     return FALSE unless check_claws_not_running ();
1973     my $rcbak = "$rc.backup";
1974     rename ($rc, $rcbak);
1975     open (RCF, ">$rc");
1976     open (RCB, "<$rcbak");
1977     while (<RCB>) {
1978         chomp;
1979         if (/^([8a-z_]+)=(.*)$/) {
1980             if (defined($HPVALUE{$1})) {
1981                 print RCF $1 . "=" . $HPVALUE{$1} . "\n";
1982             }
1983             else {
1984                 print RCF $_ . "\n";
1985             }
1986         }
1987         else {
1988             print RCF $_ . "\n";
1989         }
1990     }
1991     close (RCB);
1992     close (RCF);
1993     return TRUE;
1994 }
1995
1996 # create notebook
1997 sub new_notebook {
1998     my $nb = Gtk2::Notebook->new;
1999     # 
2000     $nb->append_page (new_behaviour_page (), $xl::s{tab_behaviour});
2001     $nb->append_page (new_colours_page (), $xl::s{tab_colours});
2002     $nb->append_page (new_gui_page (), $xl::s{tab_gui});
2003     $nb->append_page (new_other_page (), $xl::s{tab_other});
2004     $nb->append_page (new_winpos_page (), $xl::s{tab_winpos});
2005
2006     return $nb;
2007 }
2008
2009 # create an about dialog
2010 sub new_about_dialog {
2011     my ($parent) = @_;
2012     my $title = $xl::s{about_title};
2013     my $lic = $xl::s{about_license};
2014     my $vers = $xl::s{about_version} . " $VERSION";
2015     my $license = 
2016 "This program is free software: you can redistribute it and/or modify
2017 it under the terms of the GNU General Public License as published by
2018 the Free Software Foundation, either version 3 of the License, or
2019 (at your option) any later version.
2020
2021 This program is distributed in the hope that it will be useful,
2022 but WITHOUT ANY WARRANTY; without even the implied warranty of
2023 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2024 GNU General Public License for more details.
2025
2026 You should have received a copy of the GNU General Public License
2027 along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.";
2028     my $year = "2007-2014";
2029     my $holder = "Ricardo Mones &lt;ricardo\@mones.org&gt;";
2030     my $url = "http://www.claws-mail.org/clawsker.php";
2031
2032     my $dialog = Gtk2::MessageDialog->new_with_markup ($parent, 
2033                     [qw/modal destroy-with-parent/], 
2034                     'info', 'close', 
2035                     "<span size=\"x-large\" weight=\"bold\">$title</span>\n"
2036                     . "<span size=\"large\">$vers</span>\n\n"
2037                     . "<span color=\"blue\" size=\"large\">$url</span>\n\n"
2038                     . "<span>Copyright $year by $holder</span>\n\n"
2039                     . "<span size=\"large\">$lic</span>\n\n"
2040                     . "<span size=\"small\">$license</span>");
2041     $dialog->set_title ($xl::s{about});
2042     #
2043     return $dialog;
2044 }
2045
2046 # create buttons box
2047 sub new_button_box {
2048     my ($parent, $adlg) = @_;
2049     my $b_about = Gtk2::Button->new_from_stock ('gtk-about');
2050     my $b_exit = Gtk2::Button->new_from_stock ('gtk-quit');
2051     my $b_apply = Gtk2::Button->new_from_stock ('gtk-apply');
2052     # disable button until is really implemented
2053     # my $b_undo = Gtk2::Button->new_from_stock ('gtk-undo');
2054     my $hbox = Gtk2::HBox->new (FALSE, 5);
2055     # signal handlers 
2056     $b_exit->signal_connect (clicked => sub { Gtk2->main_quit });
2057     $b_apply->signal_connect (clicked => sub { save_preferences ($parent) });
2058     # $b_undo->signal_connect (clicked => sub { undo_current_changes });
2059     $b_about->signal_connect (clicked => sub { $adlg->run; $adlg->hide });
2060     # package them
2061     $hbox->pack_end ($b_apply, FALSE, FALSE, 0);
2062     $hbox->pack_end ($b_exit, FALSE, FALSE, 0);
2063     # $hbox->pack_end ($b_undo, FALSE, FALSE, 0);
2064     $hbox->pack_start ($b_about, FALSE, FALSE, 0);
2065     #
2066     return $hbox;
2067 }
2068
2069 # initialise
2070 exit unless parse_command_line ();
2071 Gtk2->init;
2072 $main_window = Gtk2::Window->new ('toplevel');
2073 exit unless load_preferences ();
2074 exit unless init_hidden_preferences ();
2075 # create main GUI
2076 my $box = Gtk2::VBox->new (FALSE, 5);
2077 $box->set_border_width(3);
2078 my $about = new_about_dialog ();
2079 $box->pack_start (new_notebook (), FALSE, FALSE, 0);
2080 $box->pack_end (new_button_box ($main_window, $about), FALSE, FALSE, 0);
2081 $main_window->signal_connect (delete_event => sub { Gtk2->main_quit });
2082 $main_window->set_title ($xl::s{win_title});
2083 $main_window->add ($box);
2084 $main_window->show_all;
2085 Gtk2->main;
2086