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