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