Do not fail comparing with empty versions
[clawsker.git] / clawsker
index 27ea596e7135364d2a8a0cc33625546a06372b26..6594bd73cb16469132eddc7563b8dd4d281aed4c 100755 (executable)
--- a/clawsker
+++ b/clawsker
@@ -17,6 +17,7 @@ binmode STDOUT, ":encoding(utf8)";
 use 5.010_000;
 use strict;
 use utf8;
+use version 0.77;
 use Glib qw(TRUE FALSE);
 use Gtk2;
 use POSIX qw(setlocale);
@@ -71,6 +72,7 @@ sub _ {
     tab_winpos => _('Windows'),
     tab_accounts => _('Accounts'),
     tab_plugins => _('Plugins'),
+    tab_info => _('Info'),
 
     ab_frame => _('Addressbook'),
     mem_frame => _('Memory'),
@@ -88,6 +90,8 @@ sub _ {
     netm_frame => _('NetworkManager'),
     diff_frame => _('Viewing patches'),
     mpass_frame => _('Master passphrase'),
+    compose_frame => _('Compose window'),
+    qs_frame => _('Quick search'),
 
     l_oth_use_dlg => _('Use detached address book edit dialogue'),
     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.'),
@@ -140,6 +144,10 @@ sub _ {
     h_gui_zero_char => _('Replaces \'0\' with the given character in Folder List.'),
     l_gui_type_any => _('Editable headers'),
     h_gui_type_any => _('Allows to manually type any value in Compose Window header entries or just select from the available choices in the associated dropdown list.'),
+    l_gui_warn_send_multi => _('Warn when sending to more than'),
+    h_gui_warn_send_multi => _('Warn when sending to multiple recipients.'),
+    l_gui_warn_send_multi_threshold => _('recipients'),
+    h_gui_warn_send_multi_threshold => _('Warn when sending to multiple recipients.'),
     l_gui_next_del => _('Select next message on delete'),
     h_gui_next_del => _('When deleting a message, toggles between selecting the next one (newer message) or the previous one (older message).'),
 
@@ -164,15 +172,17 @@ sub _ {
     l_beh_warn_dnd => _('Warn on drag \'n\' drop'),
     h_beh_warn_dnd => _('Display a confirmation dialogue on drag \'n\' drop of folders.'),
     l_beh_out_ascii => _('Outgoing messages fallback to ASCII'),
-    h_beh_out_ascii => _('If content allows, ASCII will be used to encode outgoing messages, otherwise the user-defined encoding is enforced always.'),
+    h_beh_out_ascii => _('If allowed by content, ASCII will be used to encode outgoing messages, otherwise the user-defined encoding is always enforced.'),
     l_beh_pp_unsel => _('Primary paste unselects selection'),
     h_beh_pp_unsel => _('Controls how pasting using middle-click changes the selected text and insertion point.'),
     l_beh_inline_at => _('Show inline attachments'),
-    h_beh_inline_at => _('Allows hiding inline attachments already shown in mail structure view.'),
+    h_beh_inline_at => _('Allows to hide inline attachments already shown in mail structure view.'),
     l_beh_addr_swc => _('Address search in compose window matches any'),
     h_beh_addr_swc => _('On Tab-key completion, address text will match any part of the string or only from the start.'),
     l_beh_fold_swc => _('Folder search in folder selector matches any'),
     h_beh_fold_swc => _('On folder name completion text will match any part of the string or only from the start.'),
+    l_beh_rewrite_ff => _('Rewrite first \'From\' using QP encoding'),
+    h_beh_rewrite_ff => _('Workaround some servers which convert first \'From\' to \'>From\' by using Quoted-Printable transfer encoding instead of 7bit/8bit encoding.'),
 
     l_col_emphasis => _('X-Mailer header'),
     h_col_emphasis => _('The colour used for the X-Mailer line when its value is Claws Mail.'),
@@ -184,15 +194,34 @@ sub _ {
     h_col_log_msg => _('Colour for messages in log window.'),
     l_col_log_out => _('Client messages'),
     h_col_log_out => _('Colour for messages sent to servers in log window.'),
-    l_col_log_warn => _('Warnings'),
+    l_col_log_warn => _('Warning messages'),
     h_col_log_warn => _('Colour for warning messages in log window.'),
 
+    l_col_tags_bg => _('Tags background'),
+    h_col_tags_bg => _('Background colour for tags in message view.'),
+    l_col_tags_text => _('Tags text'),
+    h_col_tags_text => _('Text colour for tags in message view.'),
+
+    l_col_default_header_bg => _('Default headers background'),
+    h_col_default_header_bg => _('Background colour for default headers in compose window.'),
+    l_col_default_header_text => _('Default headers text'),
+    h_col_default_header_text => _('Text colour for default headers in compose window.'),
+
+    l_col_qs_active_bg => _('Active quick search background'),
+    h_col_qs_active_bg => _('Background colour for active quick search.'),
+    l_col_qs_active_text => _('Active quick search text'),
+    h_col_qs_active_text => _('Text colour for active quick search.'),
+    l_col_qs_error_bg => _('Quick search error background'),
+    h_col_qs_error_bg => _('Background colour for quick search error.'),
+    l_col_qs_error_text => _('Quick search error text'),
+    h_col_qs_error_text => _('Text colour for quick search error.'),
+
     l_col_diff_add => _('Added lines'),
     h_col_diff_add => _('Colour for added lines in patches.'),
     l_col_diff_del => _('Deleted lines'),
     h_col_diff_del => _('Colour for deleted lines in patches.'),
     l_col_diff_hunk => _('Hunk lines'),
-    h_col_diff_hunk => _('Color for hunk headers in patches.'),
+    h_col_diff_hunk => _('Colour for hunk headers in patches.'),
 
     l_win_x => _('X position'),
     h_win_x => _('X coordinate for window\'s top-left corner.'),
@@ -214,19 +243,15 @@ sub _ {
     h_acc_gtls_pri => _('Value to use as GnuTLS priority string if custom priority check is enabled. Otherwise this value is ignored.'),
 
     l_plu_gpg_alimit => _('Autocompletion limit'),
-    h_plu_gpg_alimit => _('Limits the number of addresses obtained from from keyring through autocompletion. Use 0 to get all matches.'),
+    h_plu_gpg_alimit => _('Limits the number of addresses obtained from keyring through autocompletion. Use 0 to get all matches.'),
     l_plu_lav_burl => _('Base URL'),
     h_plu_lav_burl => _('This is the URL where avatar requests are sent. You can use the one of your own libravatar server, if available.'),
     l_plu_prl_flvb => _('Log level'),
-    h_plu_prl_flvb => _('Verbosity level of log, acumulative.'),
+    h_plu_prl_flvb => _('Verbosity level of log, accumulative.'),
     l_plu_prl_none => _('None'),
     l_plu_prl_manual => _('Manual'),
     l_plu_prl_action => _('Actions'),
     l_plu_prl_match => _('Matches'),
-
-    e_error => _('Error: '),
-    e_noclawsrc => _('resource file for Claws Mail was not found.'),
-    e_running => _('seems Claws Mail is currently running, close it first.'),
 );
 
 # data and metadata of resource files
@@ -250,6 +275,8 @@ my $ACCOUNTRC = 'accountrc';
 # supported and available plugins lists
 my @PLUGINS = qw(AttRemover GPG ManageSieve Libravatar PerlPlugin);
 my @AVPLUGINS = ();
+# loaded icons
+my @APPICONS = ();
 
 # index constants for preference arrays
 use constant NAME  => 0; # the name on the rc file
@@ -261,7 +288,7 @@ use constant CMDEF => 5; # default value for the preference in Claws Mail
 use constant PLUGIN => 6; # plugin section (only in plugin preferences)
 
 # constants for GUI spacing
-use constant HBOX_SPC => 5;
+use constant HBOX_PAD => 5;
 use constant FRAME_SPC => 2;
 use constant PAGE_SPC => 5;
 
@@ -269,18 +296,9 @@ use constant PAGE_SPC => 5;
 
 sub version_greater_or_equal {
     my ($version, $refvers) = @_;
-    my @version = split (/\./, $version);
-    my @refvers = split (/\./, $refvers);
-    while ($#version < $#refvers) {
-        push (@version, '0');
-    }
-    my $idx = 0;
-    while (($idx <= $#refvers)
-            and (int ($version[$idx]) == int ($refvers[$idx]))) {
-        ++$idx;
-    }
-    return TRUE if (($idx > $#refvers)
-        or (int ($version[$idx]) >= int ($refvers[$idx])));
+    return TRUE if (length($version) == 0 and length($refvers) >= 0);
+    return FALSE if (length($version) >= 0 and length($refvers) == 0);
+    return TRUE if (version->parse($version) >= version->parse($refvers));
     return FALSE;
 }
 
@@ -407,7 +425,7 @@ sub error_dialog {
 }
 
 sub claws_is_running {
-    my $emsg = "$xl::s{e_error}$xl::s{e_running}";
+    my $emsg = _('Error: seems Claws Mail is currently running, close it first.');
     log_message ($emsg);
     error_dialog ($emsg);
     return FALSE;
@@ -430,7 +448,7 @@ sub check_claws_not_running {
 sub check_rc_file {
     my ($rcfile) = @_;
     (defined($rcfile) && -f $rcfile) or do {
-        my $emsg = "$xl::s{e_error}$xl::s{e_noclawsrc}\n";
+        my $emsg = _('Error: resource file for Claws Mail was not found.');
         log_message ($emsg);
         error_dialog ($emsg);
         return FALSE;
@@ -461,12 +479,19 @@ sub set_widget_sens {
 
 # graphic element creation
 
+sub new_hbox_spaced_pack {
+    my $hbox = Gtk2::HBox->new (FALSE);
+    foreach (@_) {
+        $hbox->pack_start ($_, FALSE, FALSE, HBOX_PAD);
+    }
+    return $hbox;
+}
+
 sub new_check_button_for($$$) {
     my ($hash, $key, $vhash) = @_;
     my $name = $$hash{$key}[NAME];
     my $label = $$hash{$key}[LABEL];
     #
-    my $hbox = Gtk2::HBox->new (FALSE, 5);
     my $cb = Gtk2::CheckButton->new ($label);
     my $value = $$vhash{$name};
     $value //= $$hash{$key}[CMDEF];
@@ -477,9 +502,8 @@ sub new_check_button_for($$$) {
         });
     set_widget_hint ($cb, $$hash{$key}[DESC]);
     set_widget_sens ($cb, $$hash{$key}[CMVER]);
-    $hbox->pack_start ($cb, FALSE, FALSE, HBOX_SPC);
     #
-    return $hbox;
+    return new_hbox_spaced_pack ($cb);
 }
 
 sub new_text_box_for_int($$$) {
@@ -489,7 +513,6 @@ sub new_text_box_for_int($$$) {
     my @type = split (/,/, $$hash{$key}[TYPE]);
     push (@type, 0), push (@type, 10000) unless ($#type > 0);
     #
-    my $hbox = Gtk2::HBox->new (FALSE, 5);
     my $glabel = Gtk2::Label->new ($label);
     my $pagei = int (($type[2] - $type[1]) / 10);
     my $gentry = Gtk2::SpinButton->new_with_range ($type[1], $type[2], $pagei);
@@ -504,10 +527,55 @@ sub new_text_box_for_int($$$) {
     set_widget_hint ($gentry, $$hash{$key}[DESC]);
     set_widget_sens ($gentry, $$hash{$key}[CMVER]);
     $glabel->set_sensitive ($gentry->sensitive);
-    $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
-    $hbox->pack_start ($gentry, FALSE, FALSE, HBOX_SPC);
     #
-    return $hbox;
+    return new_hbox_spaced_pack ($glabel, $gentry);
+}
+
+sub check_button_and_text_box_update_sens($$$) {
+    my ($cb, $gentry, $glabel) = @_;
+    $gentry->set_sensitive ($cb->get_active);
+    $glabel->set_sensitive ($cb->get_active);
+}
+
+sub new_check_button_and_text_box_for_int($$$$) {
+    my ($hash, $key, $key2, $vhash) = @_;
+    my $name = $$hash{$key}[NAME];
+    my $label = $$hash{$key}[LABEL];
+    #
+    my $cb = Gtk2::CheckButton->new ($label);
+    my $value = $$vhash{$name};
+    $value //= $$hash{$key}[CMDEF];
+    $cb->set_active ($value eq '1');
+    set_widget_hint ($cb, $$hash{$key}[DESC]);
+    set_widget_sens ($cb, $$hash{$key}[CMVER]);
+       #
+    my $name2 = $$hash{$key2}[NAME];
+    my $label2 = $$hash{$key2}[LABEL];
+    my @type = split (/,/, $$hash{$key2}[TYPE]);
+    push (@type, 0), push (@type, 10000) unless ($#type > 0);
+    #
+    my $pagei = int (($type[2] - $type[1]) / 10);
+    my $gentry = Gtk2::SpinButton->new_with_range ($type[1], $type[2], $pagei);
+    my $value2 = $$vhash{$name2};
+    my $glabel = Gtk2::Label->new ($label2);
+    $value2 //= $$hash{$key2}[CMDEF];
+    $gentry->set_numeric (TRUE);
+    $gentry->set_value ($value2);
+    $gentry->signal_connect('value-changed' => sub {
+            my ($w, $e) = @_;
+            handle_int_value ($w, $e, \$$vhash{$name});
+        });
+    set_widget_hint ($gentry, $$hash{$key2}[DESC]);
+    set_widget_sens ($gentry, $$hash{$key2}[CMVER]);
+       check_button_and_text_box_update_sens($cb, $gentry, $glabel);
+    #
+    $cb->signal_connect ('clicked' => sub {
+                   my ($w, $e) = @_;
+            handle_bool_value ($w, $e, \$$vhash{$name});
+                       check_button_and_text_box_update_sens($w, $gentry, $glabel);
+       });
+       #
+    return new_hbox_spaced_pack ($cb, $gentry, $glabel);
 }
 
 sub new_text_box_for_nchar($$$) {
@@ -515,7 +583,6 @@ sub new_text_box_for_nchar($$$) {
     my $name = $$hash{$key}[NAME];
     my $label = $$hash{$key}[LABEL];
     my @type = split (/,/, $$hash{$key}[TYPE]); # char,minlen,maxlen,width
-    my $hbox = Gtk2::HBox->new (FALSE, 5);
     my $glabel = Gtk2::Label->new ($label);
     my $gentry = Gtk2::Entry->new ();
     $gentry->set_max_length($type[2]) if defined ($type[2]);
@@ -532,10 +599,8 @@ sub new_text_box_for_nchar($$$) {
     set_widget_hint ($gentry, $$hash{$key}[DESC]);
     set_widget_sens ($gentry, $$hash{$key}[CMVER]);
     $glabel->set_sensitive ($gentry->sensitive);
-    $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
-    $hbox->pack_start ($gentry, FALSE, FALSE, HBOX_SPC);
     #
-    return $hbox;
+    return new_hbox_spaced_pack ($glabel, $gentry);
 }
 
 sub new_color_button_for($$$) {
@@ -546,7 +611,6 @@ sub new_color_button_for($$$) {
     my $value = $$vhash{$name};
     $value //= $$hash{$key}[CMDEF];
     my $col = gdk_color_from_str ($value);
-    my $hbox = Gtk2::HBox->new (FALSE, 5);
     my $glabel = Gtk2::Label->new ($label);
     my $button = Gtk2::ColorButton->new_with_color ($col);
     $button->set_title ($label);
@@ -558,10 +622,8 @@ sub new_color_button_for($$$) {
     set_widget_hint ($button, $$hash{$key}[DESC]);
     set_widget_sens ($button, $$hash{$key}[CMVER]);
     $glabel->set_sensitive ($button->sensitive);
-    $hbox->pack_start ($button, FALSE, FALSE, HBOX_SPC);
-    $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
     #
-    return $hbox;
+    return new_hbox_spaced_pack ($button, $glabel);
 }
 
 sub new_selection_box_for($$$) {
@@ -569,7 +631,6 @@ sub new_selection_box_for($$$) {
     my $name = $$hash{$key}[NAME];
     my $label = $$hash{$key}[LABEL];
     #
-    my $hbox = Gtk2::HBox->new (FALSE, 5);
     my $glabel = Gtk2::Label->new ($label);
     my $combo = Gtk2::ComboBox->new_text;
     my @options = split (';', $$hash{$key}[TYPE]);
@@ -587,19 +648,26 @@ sub new_selection_box_for($$$) {
     set_widget_hint ($combo, $$hash{$key}[DESC]);
     set_widget_sens ($combo, $$hash{$key}[CMVER]);
     $glabel->set_sensitive ($combo->sensitive);
-    $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
-    $hbox->pack_start ($combo, FALSE, FALSE, HBOX_SPC);
     #
-    return $hbox;
+    return new_hbox_spaced_pack ($glabel, $combo);
 }
 
 # more graphic helpers
 
 sub new_hbox_pack {
-    my $hbox = Gtk2::HBox->new (FALSE, 5);
+    my $hbox = Gtk2::HBox->new (FALSE);
     $hbox->set_border_width (PAGE_SPC);
-    foreach my $item (@_) {
-        $hbox->pack_start ($item, FALSE, FALSE, 0);
+    foreach (@_) {
+        $hbox->pack_start ($_, FALSE, FALSE, 0);
+    }
+    return $hbox;
+}
+
+sub new_hbox_pack_compact {
+    my $hbox = Gtk2::HBox->new (FALSE);
+    $hbox->set_border_width (0);
+    foreach (@_) {
+        $hbox->pack_start ($_, FALSE, FALSE, 0);
     }
     return $hbox;
 }
@@ -607,8 +675,8 @@ sub new_hbox_pack {
 sub new_vbox_pack {
     my $vbox = Gtk2::VBox->new (FALSE, 5);
     $vbox->set_border_width (PAGE_SPC);
-    foreach my $item (@_) {
-        $vbox->pack_start ($item, FALSE, FALSE, 0);
+    foreach (@_) {
+        $vbox->pack_start ($_, FALSE, FALSE, 0);
     }
     return $vbox;
 }
@@ -616,8 +684,8 @@ sub new_vbox_pack {
 sub new_vbox_pack_compact {
     my $vbox = Gtk2::VBox->new (FALSE, 0);
     $vbox->set_border_width (0);
-    foreach my $item (@_) {
-        $vbox->pack_start ($item, FALSE, FALSE, 0);
+    foreach (@_) {
+        $vbox->pack_start ($_, FALSE, FALSE, 0);
     }
     return $vbox;
 }
@@ -646,7 +714,7 @@ sub new_subpage_frame {
         $xl::s{l_oth_max_use},
         $xl::s{h_oth_max_use},
         'int,0,262144', # 0 Kb - 256 Mb
-        '0.0.0',
+        '0.7.8.36',
         '4096',
     ],
     min_time => [
@@ -654,7 +722,7 @@ sub new_subpage_frame {
         $xl::s{l_oth_min_time},
         $xl::s{h_oth_min_time},
         'int,0,120', # 0 minutes - 2 hours
-        '0.0.0',
+        '0.7.8.36',
         '15',
     ],
     use_netm => [
@@ -703,7 +771,7 @@ sub new_other_page() {
         $xl::s{l_gui_b_unread},
         $xl::s{h_gui_b_unread},
         'bool',
-        '0.0.0',
+        '0.5.3',
         '1',
     ],
     no_markup => [
@@ -711,7 +779,7 @@ sub new_other_page() {
         $xl::s{l_gui_no_markup},
         $xl::s{h_gui_no_markup},
         'bool',
-        '0.0.0',
+        '2.1.0.16',
         '0',
     ],
     dot_lines => [
@@ -719,7 +787,7 @@ sub new_other_page() {
         $xl::s{l_gui_dot_lines},
         $xl::s{h_gui_dot_lines},
         'bool',
-        '0.0.0,3.7.10.44',
+        '2.4.0.115,3.7.10.44',
         '0',
     ],
     h_scroll => [
@@ -727,7 +795,7 @@ sub new_other_page() {
         $xl::s{l_gui_h_scroll},
         $xl::s{h_gui_h_scroll},
         'bool',
-        '0.0.0',
+        '0.8.6.18',
         '1',
     ],
     swp_from => [
@@ -735,7 +803,7 @@ sub new_other_page() {
         $xl::s{l_gui_swp_from},
         $xl::s{h_gui_swp_from},
         'bool',
-        '0.0.0',
+        '1.9.13.40',
         '0',
     ],
     v_scroll => [
@@ -743,7 +811,7 @@ sub new_other_page() {
         $xl::s{l_gui_v_scroll},
         $xl::s{h_gui_v_scroll},
         '0=l_gui_v_scroll_show;1=l_gui_v_scroll_auto;2=l_gui_v_scroll_hide',
-        '0.0.0',
+        '0.7.8.14',
         '0',
     ],
     from_show => [
@@ -759,7 +827,7 @@ sub new_other_page() {
         $xl::s{l_gui_strip_off},
         $xl::s{h_gui_strip_off},
         'int,0,40000', # no idea what this number means
-        '0.0.0',
+        '2.4.0.186',
         '4000',
     ],
     cursor_v => [
@@ -834,6 +902,22 @@ sub new_other_page() {
         '3.12.0.44',
         '0',
     ],
+    warn_send_multi => [
+        'warn_sending_many_recipients',
+        $xl::s{l_gui_warn_send_multi},
+        $xl::s{l_gui_warn_send_multi},
+        'bool',
+        '3.14.1.125',
+        '0',
+    ],
+    warn_send_multi_threshold => [
+        'warn_sending_many_recipients_num',
+        $xl::s{l_gui_warn_send_multi_threshold},
+        $xl::s{l_gui_warn_send_multi_threshold},
+        'int,1,1000',
+        '3.14.1.125',
+        '2',
+    ],
     next_del => [
         'next_on_delete',
         $xl::s{l_gui_next_del},
@@ -878,7 +962,8 @@ sub new_gui_page() {
                          new_hbox_pack (
                              new_check_button_for (\%pr::gui, 'no_markup', \%HPVALUE),
                              new_check_button_for (\%pr::gui, 'margin_co', \%HPVALUE),
-                             new_check_button_for (\%pr::gui, 'type_any', \%HPVALUE)),
+                             new_check_button_for (\%pr::gui, 'type_any', \%HPVALUE),
+                             new_check_button_and_text_box_for_int (\%pr::gui, 'warn_send_multi', 'warn_send_multi_threshold', \%HPVALUE)),
                          $xl::s{compo_frame}, 'not-packed'),
                      FALSE, FALSE, FRAME_SPC);
     $gf->pack_start ($cb_dot_lines, FALSE, FALSE, 0);
@@ -964,7 +1049,7 @@ sub new_gui_page() {
         $xl::s{l_beh_use_utf8},
         $xl::s{h_beh_use_utf8},
         'bool',
-        '0.0.0',
+        '1.9.14.49',
         '0',
     ],
     warn_dnd => [
@@ -1015,6 +1100,14 @@ sub new_gui_page() {
         '3.9.3.18',
         '0',
     ],
+    rewrite_ff => [
+        'rewrite_first_from',
+        $xl::s{l_beh_rewrite_ff},
+        $xl::s{h_beh_rewrite_ff},
+        'bool',
+        '3.14.0.94',
+        '0',
+    ],
 );
 
 sub new_behaviour_page() {
@@ -1046,7 +1139,8 @@ sub new_behaviour_page() {
                              new_check_button_for (\%pr::beh, 'dangerous', \%HPVALUE),
                              new_check_button_for (\%pr::beh, 'out_ascii', \%HPVALUE),
                              new_check_button_for (\%pr::beh, 'pp_unsel', \%HPVALUE),
-                             new_check_button_for (\%pr::beh, 'inline_at', \%HPVALUE)),
+                             new_check_button_for (\%pr::beh, 'inline_at', \%HPVALUE),
+                             new_check_button_for (\%pr::beh, 'rewrite_ff', \%HPVALUE)),
                          $xl::s{msgs_frame}, 'not-packed'),
                      FALSE, FALSE, FRAME_SPC);
     $bf->pack_start (new_subpage_frame (
@@ -1131,28 +1225,111 @@ sub new_behaviour_page() {
         '3.8.0.54',
         '#a52a2a',
     ],
+    tags_bg => [
+        'tags_bgcolor',
+        $xl::s{l_col_tags_bg},
+        $xl::s{h_col_tags_bg},
+        'color',
+        '3.14.1.31',
+        '#f5f6be',
+    ],
+    tags_text => [
+        'tags_color',
+        $xl::s{l_col_tags_text},
+        $xl::s{h_col_tags_text},
+        'color',
+        '3.14.1.31',
+        '#000000',
+    ],
+    default_header_bg => [
+        'default_header_bgcolor',
+        $xl::s{l_col_default_header_bg},
+        $xl::s{h_col_default_header_bg},
+        'color',
+        '3.14.1.31',
+        '#f5f6be',
+    ],
+    default_header_text => [
+        'default_header_color',
+        $xl::s{l_col_default_header_text},
+        $xl::s{h_col_default_header_text},
+        'color',
+        '3.14.1.31',
+        '#000000',
+    ],
+    qs_active_bg => [
+        'qs_active_bgcolor',
+        $xl::s{l_col_qs_active_bg},
+        $xl::s{h_col_qs_active_bg},
+        'color',
+        '3.14.1.31',
+        '#f5f6be',
+    ],
+    qs_active_text => [
+        'qs_active_color',
+        $xl::s{l_col_qs_active_text},
+        $xl::s{h_col_qs_active_text},
+        'color',
+        '3.14.1.31',
+        '#000000',
+    ],
+    qs_error_bg => [
+        '',
+        $xl::s{l_col_qs_error_bg},
+        $xl::s{h_col_qs_error_bg},
+        'qs_error_bgcolor',
+        '3.14.1.31',
+        '#ff7070',
+    ],
+    qs_error_text => [
+        '',
+        $xl::s{l_col_qs_error_text},
+        $xl::s{h_col_qs_error_text},
+        'qs_error_color',
+        '3.14.1.31',
+        '#000000',
+    ],
 );
 
 sub new_colours_page() {
     return new_vbox_pack (
                new_subpage_frame (
                    new_vbox_pack (
-                       new_color_button_for (\%pr::col, 'emphasis', \%HPVALUE)),
+                       new_color_button_for (\%pr::col, 'emphasis', \%HPVALUE),
+                       new_hbox_pack_compact (
+                           new_color_button_for (\%pr::col, 'tags_text', \%HPVALUE),
+                           new_color_button_for (\%pr::col, 'tags_bg', \%HPVALUE))),
                    $xl::s{msgview_frame}, 'not-packed'),
                new_subpage_frame (
-                   new_vbox_pack (
-                       new_color_button_for (\%pr::col, 'log_err', \%HPVALUE),
-                       new_color_button_for (\%pr::col, 'log_in', \%HPVALUE),
-                       new_color_button_for (\%pr::col, 'log_msg', \%HPVALUE),
-                       new_color_button_for (\%pr::col, 'log_out', \%HPVALUE),
-                       new_color_button_for (\%pr::col, 'log_warn', \%HPVALUE)),
+                   new_hbox_pack (
+                       new_vbox_pack_compact (
+                           new_color_button_for (\%pr::col, 'log_err', \%HPVALUE),
+                           new_color_button_for (\%pr::col, 'log_warn', \%HPVALUE),
+                           new_color_button_for (\%pr::col, 'log_msg', \%HPVALUE)),
+                       new_vbox_pack_compact (
+                           new_color_button_for (\%pr::col, 'log_in', \%HPVALUE),
+                           new_color_button_for (\%pr::col, 'log_out', \%HPVALUE))),
                    $xl::s{log_frame}, 'not-packed'),
                new_subpage_frame (
                    new_vbox_pack (
                        new_color_button_for (\%pr::col, 'diff_add', \%HPVALUE),
                        new_color_button_for (\%pr::col, 'diff_del', \%HPVALUE),
                        new_color_button_for (\%pr::col, 'diff_hunk', \%HPVALUE)),
-                   $xl::s{diff_frame}, 'not-packed')
+                   $xl::s{diff_frame}, 'not-packed'),
+               new_subpage_frame (
+                   new_hbox_pack (
+                       new_color_button_for (\%pr::col, 'default_header_text', \%HPVALUE),
+                       new_color_button_for (\%pr::col, 'default_header_bg', \%HPVALUE)),
+                   $xl::s{compose_frame}, 'not-packed'),
+               new_subpage_frame (
+                   new_hbox_pack (
+                       new_vbox_pack_compact (
+                           new_color_button_for (\%pr::col, 'qs_active_text', \%HPVALUE),
+                           new_color_button_for (\%pr::col, 'qs_error_text', \%HPVALUE)),
+                       new_vbox_pack_compact (
+                           new_color_button_for (\%pr::col, 'qs_active_bg', \%HPVALUE),
+                           new_color_button_for (\%pr::col, 'qs_error_bg', \%HPVALUE))),
+                   $xl::s{qs_frame}, 'not-packed')
            );
 }
 
@@ -1854,10 +2031,20 @@ sub new_account_subpage($) {
 sub new_accounts_page() {
     my $accbook = Gtk2::Notebook->new;
     $accbook->set_tab_pos ('right');
-    foreach (keys %ACPREFS) {
+    my @akeys = sort {
+        $ACPREFS{$a}{'account_name'} cmp $ACPREFS{$b}{'account_name'}
+    } keys %ACPREFS;
+    foreach (@akeys) {
         my $name = $ACPREFS{$_}{'account_name'};
-        $accbook->append_page (new_account_subpage ($_), $name);
+        my $isdef = ($ACPREFS{$_}{'is_default'} eq '1');
+        my $page = new_account_subpage ($_);
+        $accbook->append_page ($page, $isdef? '<b>' . $name . '</b>': $name);
+        if ($isdef) {
+            my $label = $accbook->get_tab_label ($page);
+            $label->set_use_markup (TRUE);
+        }
     }
+    $accbook->set_scrollable (TRUE);
     return $accbook;
 }
 
@@ -1972,6 +2159,50 @@ sub new_plugins_page() {
                 $frame{'PerlPlugin'});
 }
 
+sub new_info_page() {
+    my $t0 = Gtk2::Table->new (7, 2, FALSE);
+    my $v = get_toolkit_versions ();
+    my %labels = (
+        'glib' => 'Perl-GLib',
+        'glib-r' => _('GLib runtime'),
+        'glib-b' => _('GLib built'),
+        'gtk2' => 'Perl-GTK2',
+        'gtk2-r' => _('GTK2 runtime'),
+        'gtk2-b' => _('GTK2 built'),
+    );
+    my $row = 0;
+    foreach (sort keys %$v) {
+        if (defined $v->{$_}) {
+            my $label = Gtk2::Label->new ($labels{$_});
+            my $value = Gtk2::Label->new ('<b>' . $v->{$_} . '</b>');
+            $label->set_alignment (0, 0.5);
+            $value->set_alignment (0, 0.5);
+            $value->set_use_markup (TRUE);
+            $t0->attach ($label, 0, 1, $row, $row + 1, 'fill', 'shrink', 8, 6);
+            $t0->attach ($value, 1, 2, $row, $row + 1, 'fill', 'shrink', 8, 6);
+            ++$row;
+        }
+    }
+    my $t1 = Gtk2::Table->new (2, 2, FALSE);
+    my @lbl = map { $_->set_alignment (0, 0.5); $_ } (
+        Gtk2::Label->new (_('Binary')),
+        Gtk2::Label->new (_('Configuration'))
+    );
+    my $cfgv = $CONFIGDATA->{'Common'}{'config_version'};
+    $cfgv //= '';
+    my @val = map { $_->set_alignment (0, 0.5); $_->set_use_markup (TRUE); $_ } (
+        Gtk2::Label->new ('<b>' . $CLAWSV . '</b>'),
+        Gtk2::Label->new ('<b>' . $cfgv . '</b>')
+    );
+    for (my $i = 0; $i <= $#lbl; ++$i) {
+        $t1->attach ($lbl[$i], 0, 1, $i, $i + 1, 'fill', 'shrink', 8, 6);
+        $t1->attach ($val[$i], 1, 2, $i, $i + 1, 'fill', 'shrink', 8, 6);
+    }
+    return new_vbox_pack (
+                new_subpage_frame ($t0, _('Library versions'), 'not-packed'),
+                new_subpage_frame ($t1, _('Claws Mail versions'), 'not-packed'));
+}
+
 # version info
 sub get_toolkit_versions {
     my %versions = ();
@@ -1995,35 +2226,48 @@ sub print_version() {
     print $xl::s{about_title} . "\n";
     print $xl::s{about_version} . " $VERSION\n";
     my $v = get_toolkit_versions ();
-    print "Perl-GLib " . $v->{'glib'};
-    print _(", built for ") . $v->{'glib-b'}
-        . _(", running with ") . $v->{'glib-r'} if $v->{'glib-b'};
+    if ($v->{'glib-b'}) {
+        print _("Perl-GLib version {glibv}, built for {glibb}, running with {glibr}.",
+                glibv => $v->{'glib'},
+                glibb => $v->{'glib-b'},
+                glibr => $v->{'glib-r'});
+    } else {
+        print _("Perl-GLib version {glibv}.", glibv => $v->{'glib'});
+    }
     print "\n";
-    print "Perl-GTK2 " . $v->{'gtk2'};
-    print _(", built for ") . $v->{'gtk2-b'}
-        . _(", running with ") . $v->{'gtk2-r'} if $v->{'gtk2-b'};
+    if ($v->{'gtk2-b'}) {
+        print _("Perl-GTK2 version {gtkv}, built for {gtkb}, running with {gtkr}.",
+                gtkv => $v->{'gtk2'},
+                gtkb => $v->{'gtk2-b'},
+                gtkr => $v->{'gtk2-r'});
+    } else {
+        print _("Perl-GTK2 version {gtkv}.", gtkv => $v->{'gtk2'});
+    }
     print "\n";
     my $clawsver = ($CLAWSV eq "") ?
-                _("was not found!") :
-                (_("returned version ") . $CLAWSV);
-    print "Claws Mail " . $clawsver . "\n";
+                _("Claws Mail was not found!") :
+                _("Claws Mail returned version {cmv}.", cmv => $CLAWSV);
+    print $clawsver . "\n";
 }
 
 # the command line help
 sub print_help() {
-    my $line = '-' x length ($xl::s{about_title}) . "\n";
-    print $line;
-    print $xl::s{about_title} . "\n";
-    print $line;
-    print _("Syntax:\n");
-    print _("  clawsker [options]\n");
-    print _("Options:\n");
-    print _("  -a|--alternate-config-dir <dir>  Uses <dir> as Claws Mail config dir.\n");
-    print _("  -b|--verbose                     More messages on standard output.\n");
-    print _("  -c|--clawsrc <file>              Uses <file> as full resource name.\n");
-    print _("  -h|--help                        Prints this help screen.\n");
-    print _("  -r|--read-only                   Disables writing changes to disk.\n");
-    print _("  -v|--version                     Prints version infos.\n");
+    my $line = '-' x length ($xl::s{about_title});
+    say $line;
+    say $xl::s{about_title};
+    say $line;
+    my @help = (
+        _("Syntax:"),
+        _("  clawsker [options]"),
+        _("Options:"),
+        _("  -a|--alternate-config-dir <dir>  Uses <dir> as Claws Mail configuration."),
+        _("  -b|--verbose                     More messages on standard output."),
+        _("  -c|--clawsrc <file>              Uses <file> as full resource name."),
+        _("  -h|--help                        Prints this help screen and exits."),
+        _("  -r|--read-only                   Disables writing changes to disk."),
+        _("  -v|--version                     Prints version information and exits.")
+    );
+    foreach (@help) { say $_ }
 }
 
 sub parse_command_line {
@@ -2080,20 +2324,12 @@ sub init_hidden_preferences {
             $HPVALUE{${$hash}{$key}[NAME]} = $PREFS{${$hash}{$key}[NAME]};
         }
     }
-    return TRUE;
-}
-
-sub init_ac_hidden_preferences {
     foreach my $akey (keys %ACPREFS) {
         foreach my $key (keys %pr::acc) {
             my $pname = $pr::acc{$key}[NAME];
             $ACHPVALUE{$akey}{$pname} = $ACPREFS{$akey}{$pname};
         }
     }
-    return TRUE;
-}
-
-sub init_plu_hidden_preferences {
     foreach my $key (keys %pr::plu) {
         my $plugin = $pr::plu{$key}[PLUGIN];
         my $pname = $pr::plu{$key}[NAME];
@@ -2111,7 +2347,7 @@ sub load_resource {
     my %meta = ();
     my $line = 0;
     open (RCF, '<:encoding(utf8)', $rc)
-        or die _("Error: opening '{file}' for reading", file => $rc) . ": $!";
+        or die _("Error: opening '{file}' for reading", file => $rc) . ": $!\n";
     my $section = '_'; # default unnamed section
     while (<RCF>) {
         chomp;
@@ -2139,7 +2375,7 @@ sub load_resource {
 sub save_resource {
     my ($rc, $data, $meta) = @_;
     open (RCF, '>:utf8', $rc)
-        or die _("Error: opening '{file}' for writing", file => $rc) . ": $!";
+        or die _("Error: opening '{file}' for writing", file => $rc) . ": $!\n";
     my @sections = keys %$data;
     if (defined $meta) {
         @sections = sort {
@@ -2170,11 +2406,10 @@ sub save_resource {
 }
 
 # load current status from disc
-sub load_preferences {
+sub load_rc_preferences {
     my $rc = get_rc_filename ();
     log_message ("Loading preferences from $rc\n");
     return FALSE unless check_rc_file ($rc);
-    return FALSE unless check_claws_not_running ();
     ($CONFIGDATA, $CONFIGMETA) = load_resource ($rc);
     foreach (keys %{$CONFIGDATA->{'Common'}}) {
         $PREFS{$_} = $CONFIGDATA->{'Common'}{$_};
@@ -2194,7 +2429,6 @@ sub load_ac_preferences {
     my $rc = get_ac_rc_filename ();
     log_message ("Loading account preferences from $rc\n");
     return FALSE unless check_rc_file ($rc);
-    return FALSE unless check_claws_not_running ();
     ($ACCOUNTDATA, $ACCOUNTMETA) = load_resource ($rc);
     foreach my $asect (keys %$ACCOUNTDATA) {
         if ($asect =~ /^Account: (\d+)$/) {
@@ -2206,6 +2440,11 @@ sub load_ac_preferences {
     return TRUE;
 }
 
+sub load_preferences {
+    return FALSE unless check_claws_not_running ();
+    return (load_rc_preferences () and load_ac_preferences ());
+}
+
 # save current preferences to disc
 sub save_preferences {
     my $rc = get_rc_filename ();
@@ -2261,6 +2500,7 @@ sub new_notebook {
     $nb->append_page (new_winpos_page (), $xl::s{tab_winpos});
     $nb->append_page (new_accounts_page (), $xl::s{tab_accounts});
     $nb->append_page (new_plugins_page (), $xl::s{tab_plugins});
+    $nb->append_page (new_info_page (), $xl::s{tab_info});
 
     return $nb;
 }
@@ -2298,6 +2538,13 @@ along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.";
                     . "<span size=\"large\">$lic</span>\n\n"
                     . "<span size=\"small\">$license</span>");
     $dialog->set_title ($xl::s{about});
+    if (Gtk2->CHECK_VERSION (2, 10, 0)) {
+        my @icons = get_app_icons ();
+        my $image = Gtk2::Image->new_from_pixbuf ($icons[-1]);
+        $image->show ();
+        $image->set_alignment (0, 0);
+        $dialog->set_image ($image);
+    }
     #
     return $dialog;
 }
@@ -2330,17 +2577,24 @@ sub new_button_box {
 }
 
 sub get_app_icons {
-    my $dir = $DATADIR . '/icons/hicolor';
-    my @names = map {
-      join ('/', ($dir, , $_ . 'x' . $_, 'apps', $NAME . '.png'))
-    } (64, 128);
-    my @icons = ();
+    return @APPICONS if (@APPICONS);
+    my @names;
+    if (-d $DATADIR) { # installed
+        my $dir = $DATADIR . '/icons/hicolor';
+        @names = map {
+            join ('/', ($dir, $_ . 'x' . $_, 'apps', $NAME . '.png'))
+        } (48, 64, 128);
+    } else { # unpacked tarball or git clone
+        @names = map {
+            join ('/', ('./icons', $NAME . '-' . $_ . '.png'));
+        } (48, 64, 128);
+    }
     foreach (@names) {
         my $icon = undef;
         $icon = Gtk2::Gdk::Pixbuf->new_from_file($_) if (-f $_);
-        push @icons, $icon if ($icon);
+        push @APPICONS, $icon if ($icon);
     }
-    return @icons;
+    return @APPICONS;
 }
 
 # initialise
@@ -2348,10 +2602,7 @@ exit unless parse_command_line ();
 Gtk2->init;
 $main_window = Gtk2::Window->new ('toplevel');
 exit unless load_preferences ();
-exit unless load_ac_preferences ();
 exit unless init_hidden_preferences ();
-exit unless init_ac_hidden_preferences ();
-exit unless init_plu_hidden_preferences ();
 # create main GUI
 my $box = Gtk2::VBox->new (FALSE, 5);
 $box->set_border_width(3);