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