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