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