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