Save resources with generic functions
[clawsker.git] / clawsker
index 98270f37b27a52cfb3756eb1a04970b5fa5d9f62..6ac83b8af1ca802563c5e5af0fa7ea3f37323bfb 100755 (executable)
--- a/clawsker
+++ b/clawsker
@@ -70,6 +70,7 @@ sub _ {
     tab_other => _('Other'),
     tab_winpos => _('Windows'),
     tab_accounts => _('Accounts'),
+    tab_plugins => _('Plugins'),
 
     ab_frame => _('Addressbook'),
     mem_frame => _('Memory'),
@@ -98,7 +99,7 @@ sub _ {
     h_oth_use_netm => _('Use NetworkManager to switch offline automatically.'),
     l_oth_mp_rounds => _('Rounds for PBKDF2 function'),
     h_oth_mp_rounds => _('Specify the number of iterations the key derivation function will be applied on master passphrase computation. Does not modify currently stored passphrase, only master passphrases computed after changing this value are affected.'),
-    
+
     l_gui_b_unread => _('Show unread messages with bold font'),
     h_gui_b_unread => _('Show unread messages in the Message List using a bold font.'),
     l_gui_no_markup => _('Don\'t use markup'),
@@ -212,11 +213,25 @@ sub _ {
     l_acc_gtls_pri => _('GnuTLS priority'),
     h_acc_gtls_pri => _('Value to use as GnuTLS priority string if custom priority check is enabled. Otherwise this value is ignored.'),
 
+    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.'),
+    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
+my $CONFIGDATA;
+my $CONFIGMETA;
+my $ACCOUNTDATA;
+my $ACCOUNTMETA;
 # all preferences read by load_preferences
 my %PREFS = ();
 my %ACPREFS = ();
@@ -236,7 +251,6 @@ use constant DESC  => 2; # the description for the hint/help
 use constant TYPE  => 3; # data type: bool, int, float, string, color
 use constant CMVER => 4; # lowest[,highest] Claws Mail version(s) the feature exists
 use constant CMDEF => 5; # default value for the preference in Claws Mail
-use constant GUI   => 6; # GUI element
 
 # constants for GUI spacing
 use constant HBOX_SPC => 5;
@@ -253,7 +267,7 @@ sub version_greater_or_equal {
         push (@version, '0');
     }
     my $idx = 0;
-    while (($idx <= $#refvers) 
+    while (($idx <= $#refvers)
             and (int ($version[$idx]) == int ($refvers[$idx]))) {
         ++$idx;
     }
@@ -322,7 +336,7 @@ sub gdk_color_from_str {
     $_ = uc ($str);
     if (/\#([A-F0-9][A-F0-9])([A-F0-9][A-F0-9])([A-F0-9][A-F0-9])/) {
         $rr = hex($1) * 256;
-        $gg = hex($2) * 256; 
+        $gg = hex($2) * 256;
         $bb = hex($3) * 256;
     }
     my $color = Gtk2::Gdk::Color->new ($rr, $gg, $bb);
@@ -396,7 +410,7 @@ sub check_claws_not_running {
     my $tmpdir = (defined $ENV{TMPDIR})? $ENV{TMPDIR}: '/tmp';
     $tmpdir = '/tmp' if ($tmpdir eq '');
     my $lockdir = "$tmpdir/claws-mail-$<";
-    -d $lockdir and do { 
+    -d $lockdir and do {
         $_ = $CONFIGDIR;
         s/\/$//;
         my $socket = "$lockdir/" . md5_hex ($_);
@@ -418,7 +432,7 @@ sub check_rc_file {
 
 sub set_widget_hint {
     if ($SHOWHINTS) {
-        my ($wdgt, $hint) = @_;    
+        my ($wdgt, $hint) = @_;
         $wdgt->set_tooltip_text ($hint);
         $wdgt->set_has_tooltip (TRUE);
     }
@@ -437,7 +451,7 @@ sub set_widget_sens {
     }
 }
 
-# graphic element creation 
+# graphic element creation
 
 sub new_check_button_for($$$) {
     my ($hash, $key, $vhash) = @_;
@@ -465,7 +479,7 @@ sub new_text_box_for_int($$$) {
     my $name = $$hash{$key}[NAME];
     my $label = $$hash{$key}[LABEL];
     my @type = split (/,/, $$hash{$key}[TYPE]);
-    push (@type, 0), push (@type, 10000) unless ($#type > 0); 
+    push (@type, 0), push (@type, 10000) unless ($#type > 0);
     #
     my $hbox = Gtk2::HBox->new (FALSE, 5);
     my $glabel = Gtk2::Label->new ($label);
@@ -580,7 +594,7 @@ sub new_hbox_pack {
         $hbox->pack_start ($item, FALSE, FALSE, 0);
     }
     return $hbox;
-}    
+}
 
 sub new_vbox_pack {
     my $vbox = Gtk2::VBox->new (FALSE, 5);
@@ -589,7 +603,7 @@ sub new_vbox_pack {
         $vbox->pack_start ($item, FALSE, FALSE, 0);
     }
     return $vbox;
-}    
+}
 
 sub new_vbox_pack_compact {
     my $vbox = Gtk2::VBox->new (FALSE, 0);
@@ -598,12 +612,12 @@ sub new_vbox_pack_compact {
         $vbox->pack_start ($item, FALSE, FALSE, 0);
     }
     return $vbox;
-}    
+}
 
 sub new_subpage_frame {
     my ($box, $title, $notpacked) = @_;
     my $frame = Gtk2::Frame->new ($title);
-    $frame->add ($box);    
+    $frame->add ($box);
     return new_vbox_pack ($frame) unless defined ($notpacked);
     return $frame;
 }
@@ -611,14 +625,13 @@ sub new_subpage_frame {
 # preference maps and corresponding page creation subs
 
 %pr::oth = ( # other preferences
-    use_dlg => [ 
+    use_dlg => [
         'addressbook_use_editaddress_dialog',
         $xl::s{l_oth_use_dlg},
         $xl::s{h_oth_use_dlg},
         'bool',
         '2.7.0',
         '0',
-        undef,
     ],
     max_use => [
         'cache_max_mem_usage',
@@ -627,7 +640,6 @@ sub new_subpage_frame {
         'int,0,262144', # 0 Kb - 256 Mb
         '0.0.0',
         '4096',
-        undef,
     ],
     min_time => [
         'cache_min_keep_time',
@@ -636,7 +648,6 @@ sub new_subpage_frame {
         'int,0,120', # 0 minutes - 2 hours
         '0.0.0',
         '15',
-        undef,
     ],
     use_netm => [
         'use_networkmanager',
@@ -645,7 +656,6 @@ sub new_subpage_frame {
         'bool',
         '3.3.1',
         '1',
-        undef,
     ],
     mp_rounds => [
         'master_passphrase_pbkdf2_rounds',
@@ -654,7 +664,6 @@ sub new_subpage_frame {
         'int,50000,1000000',
         '3.13.2.110',
         '50000',
-        undef,
     ],
 );
 
@@ -681,14 +690,13 @@ sub new_other_page() {
 }
 
 %pr::gui = ( # gui bells and whistles
-    b_unread => [ 
+    b_unread => [
         'bold_unread',
         $xl::s{l_gui_b_unread},
         $xl::s{h_gui_b_unread},
         'bool',
         '0.0.0',
         '1',
-        undef,
     ],
     no_markup => [
         'compose_no_markup',
@@ -697,7 +705,6 @@ sub new_other_page() {
         'bool',
         '0.0.0',
         '0',
-        undef,
     ],
     dot_lines => [
         'enable_dotted_lines',
@@ -706,7 +713,6 @@ sub new_other_page() {
         'bool',
         '0.0.0,3.7.10.44',
         '0',
-        undef,
     ],
     h_scroll => [
         'enable_hscrollbar',
@@ -715,7 +721,6 @@ sub new_other_page() {
         'bool',
         '0.0.0',
         '1',
-        undef,
     ],
     swp_from => [
         'enable_swap_from',
@@ -724,7 +729,6 @@ sub new_other_page() {
         'bool',
         '0.0.0',
         '0',
-        undef,
     ],
     v_scroll => [
         'folderview_vscrollbar_policy',
@@ -733,7 +737,6 @@ sub new_other_page() {
         '0=l_gui_v_scroll_show;1=l_gui_v_scroll_auto;2=l_gui_v_scroll_hide',
         '0.0.0',
         '0',
-        undef,
     ],
     from_show => [
         'summary_from_show',
@@ -742,7 +745,6 @@ sub new_other_page() {
         '0=l_gui_from_show_name;1=l_gui_from_show_addr;2=l_gui_from_show_both',
         '3.7.10',
         '0',
-        undef,
     ],
     strip_off => [
         'stripes_color_offset',
@@ -751,7 +753,6 @@ sub new_other_page() {
         'int,0,40000', # no idea what this number means
         '0.0.0',
         '4000',
-        undef,
     ],
     cursor_v => [
         'textview_cursor_visible',
@@ -760,7 +761,6 @@ sub new_other_page() {
         'bool',
         '0.0.0',
         '0',
-        undef,
     ],
     toolbar_d => [
         'toolbar_detachable',
@@ -769,7 +769,6 @@ sub new_other_page() {
         'bool',
         '0.0.0',
         '0',
-        undef,
     ],
     strip_all => [
         'use_stripes_everywhere',
@@ -778,7 +777,6 @@ sub new_other_page() {
         'bool',
         '0.0.0',
         '1',
-        undef,
     ],
     strip_sum => [
         'use_stripes_in_summaries',
@@ -787,7 +785,6 @@ sub new_other_page() {
         'bool',
         '0.0.0',
         '1',
-        undef,
     ],
     two_linev => [
         'two_line_vertical',
@@ -796,7 +793,6 @@ sub new_other_page() {
         'bool',
         '3.4.0.7',
         '0',
-        undef,
     ],
     margin_co => [
         'show_compose_margin',
@@ -805,7 +801,6 @@ sub new_other_page() {
         'bool',
         '3.7.6.7',
         '0',
-        undef,
     ],
     mview_date => [
         'msgview_date_format',
@@ -814,7 +809,6 @@ sub new_other_page() {
         'bool',
         '3.7.8.42',
         '0',
-        undef,
     ],
     zero_char => [
         'zero_replacement_char',
@@ -823,7 +817,6 @@ sub new_other_page() {
         'char,1,1',
         '2.8.1.77',
         '0',
-        undef,
     ],
     type_any => [
         'type_any_header',
@@ -832,7 +825,6 @@ sub new_other_page() {
         'bool',
         '3.12.0.44',
         '0',
-        undef,
     ],
     next_del => [
         'next_on_delete',
@@ -841,7 +833,6 @@ sub new_other_page() {
         'bool',
         '3.13.0.5',
         '0',
-        undef,
     ],
 );
 
@@ -867,20 +858,20 @@ sub new_gui_page() {
                              new_check_button_for (\%pr::gui, 'two_linev', \%HPVALUE),
                              new_check_button_for (\%pr::gui, 'next_del', \%HPVALUE),
                              new_selection_box_for (\%pr::gui, 'from_show', \%HPVALUE)),
-                         $xl::s{mlist_frame}, 'not-packed'), 
+                         $xl::s{mlist_frame}, 'not-packed'),
                      FALSE, FALSE, FRAME_SPC);
     $gf->pack_start (new_subpage_frame (
                          new_hbox_pack (
                              new_check_button_for (\%pr::gui, 'cursor_v', \%HPVALUE),
                              new_check_button_for (\%pr::gui, 'mview_date', \%HPVALUE)),
-                         $xl::s{mview_frame}, 'not-packed'), 
+                         $xl::s{mview_frame}, 'not-packed'),
                      FALSE, FALSE, FRAME_SPC);
     $gf->pack_start (new_subpage_frame (
                          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)),
-                         $xl::s{compo_frame}, 'not-packed'), 
+                         $xl::s{compo_frame}, 'not-packed'),
                      FALSE, FALSE, FRAME_SPC);
     $gf->pack_start ($cb_dot_lines, FALSE, FALSE, 0);
     $gf->pack_start ($cb_toolbar_d, FALSE, FALSE, 0);
@@ -903,7 +894,6 @@ sub new_gui_page() {
         'int,100,3000', # 0.1 seconds - 3 seconds
         '0.0.0',
         '500',
-        undef,
     ],
     dangerous => [
         'live_dangerously',
@@ -912,7 +902,6 @@ sub new_gui_page() {
         'bool',
         '0.0.0',
         '0',
-        undef,
     ],
     flowed => [
         'respect_flowed_format',
@@ -921,7 +910,6 @@ sub new_gui_page() {
         'bool',
         '0.0.0',
         '0',
-        undef,
     ],
     parts_rw => [
         'save_parts_readwrite',
@@ -930,7 +918,6 @@ sub new_gui_page() {
         'bool',
         '0.0.0',
         '0',
-        undef,
     ],
     skip_ssl => [
         'skip_ssl_cert_check',
@@ -939,7 +926,6 @@ sub new_gui_page() {
         'bool',
         '0.0.0',
         '0',
-        undef,
     ],
     up_step => [
         'statusbar_update_step',
@@ -948,7 +934,6 @@ sub new_gui_page() {
         'int,1,200', # 1 item - 200 items
         '0.0.0',
         '10',
-        undef,
     ],
     thread_a => [
         'thread_by_subject_max_age',
@@ -957,7 +942,6 @@ sub new_gui_page() {
         'int,1,30', # 1 day - 30 days
         '0.0.0',
         '10',
-        undef,
     ],
     unsafe_ssl => [
         'unsafe_ssl_certs',
@@ -966,7 +950,6 @@ sub new_gui_page() {
         'bool',
         '0.0.0',
         '0',
-        undef,
     ],
     use_utf8 => [
         'utf8_instead_of_locale_for_broken_mail',
@@ -975,7 +958,6 @@ sub new_gui_page() {
         'bool',
         '0.0.0',
         '0',
-        undef,
     ],
     warn_dnd => [
         'warn_dnd',
@@ -984,7 +966,6 @@ sub new_gui_page() {
         'bool',
         '0.0.0',
         '1',
-        undef,
     ],
     out_ascii => [
         'outgoing_fallback_to_ascii',
@@ -993,7 +974,6 @@ sub new_gui_page() {
         'bool',
         '3.4.0.37',
         '1',
-        undef,
     ],
     pp_unsel => [
         'primary_paste_unselects',
@@ -1002,7 +982,6 @@ sub new_gui_page() {
         'bool',
         '3.6.1.35',
         '0',
-        undef,
     ],
     inline_at => [
         'show_inline_attachments',
@@ -1011,7 +990,6 @@ sub new_gui_page() {
         'bool',
         '3.7.8.48',
         '1',
-        undef,
     ],
     addr_swc => [
         'address_search_wildcard',
@@ -1020,7 +998,6 @@ sub new_gui_page() {
         'bool',
         '3.9.3.18',
         '0',
-        undef,
     ],
     fold_swc => [
         'folder_search_wildcard',
@@ -1029,7 +1006,6 @@ sub new_gui_page() {
         'bool',
         '3.9.3.18',
         '0',
-        undef,
     ],
 );
 
@@ -1044,7 +1020,7 @@ sub new_behaviour_page() {
                          new_vbox_pack (
                              new_text_box_for_int (\%pr::beh, 'hover_t', \%HPVALUE),
                              new_check_button_for (\%pr::beh, 'warn_dnd', \%HPVALUE)),
-                         $xl::s{dnd_frame}, 'not-packed'), 
+                         $xl::s{dnd_frame}, 'not-packed'),
                      FALSE, FALSE, FRAME_SPC);
     $bf->pack_start (new_subpage_frame (
                          new_hbox_pack (
@@ -1082,7 +1058,6 @@ sub new_behaviour_page() {
         'color',
         '0.0.0',
         '#0000cf',
-        undef,
     ],
     log_err => [
         'log_error_color',
@@ -1091,7 +1066,6 @@ sub new_behaviour_page() {
         'color',
         '0.0.0',
         '#af0000',
-        undef,
     ],
     log_in => [
         'log_in_color',
@@ -1100,7 +1074,6 @@ sub new_behaviour_page() {
         'color',
         '0.0.0',
         '#000000',
-        undef,
     ],
     log_msg => [
         'log_msg_color',
@@ -1109,7 +1082,6 @@ sub new_behaviour_page() {
         'color',
         '0.0.0',
         '#00af00',
-        undef,
     ],
     log_out => [
         'log_out_color',
@@ -1118,7 +1090,6 @@ sub new_behaviour_page() {
         'color',
         '0.0.0',
         '#0000ef',
-        undef,
     ],
     log_warn => [
         'log_warn_color',
@@ -1127,7 +1098,6 @@ sub new_behaviour_page() {
         'color',
         '0.0.0',
         '#af0000',
-        undef,
     ],
     diff_add => [
         'diff_added_color',
@@ -1136,7 +1106,6 @@ sub new_behaviour_page() {
         'color',
         '3.8.0.54',
         '#008b8b',
-        undef,
     ],
     diff_del => [
         'diff_deleted_color',
@@ -1145,7 +1114,6 @@ sub new_behaviour_page() {
         'color',
         '3.8.0.54',
         '#6a5acd',
-        undef,
     ],
     diff_hunk => [
         'diff_hunk_color',
@@ -1154,7 +1122,6 @@ sub new_behaviour_page() {
         'color',
         '3.8.0.54',
         '#a52a2a',
-        undef,
     ],
 );
 
@@ -1189,7 +1156,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '16',
-        undef,
     ],
     main_y => [
         'mainwin_y',
@@ -1198,7 +1164,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '16',
-        undef,
     ],
     main_w => [
         'mainwin_width',
@@ -1207,7 +1172,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '779',
-        undef,
     ],
     main_h => [
         'mainwin_height',
@@ -1216,7 +1180,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '568',
-        undef,
     ],
     main_mx => [
         'mainwin_maximised',
@@ -1225,7 +1188,6 @@ sub new_colours_page() {
         'bool',
         '0.0.0',
         '0',
-        undef,
     ],
     main_fs => [
         'mainwin_fullscreen',
@@ -1234,7 +1196,6 @@ sub new_colours_page() {
         'bool',
         '0.0.0',
         '0',
-        undef,
     ],
     msgs_x => [
         'main_messagewin_x',
@@ -1243,7 +1204,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '256',
-        undef,
     ],
     msgs_y => [
         'main_messagewin_y',
@@ -1252,7 +1212,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '210',
-        undef,
     ],
     msgs_w => [
         'messagewin_width',
@@ -1261,7 +1220,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '600',
-        undef,
     ],
     msgs_h => [
         'messagewin_height',
@@ -1270,7 +1228,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '540',
-        undef,
     ],
     send_w => [
         'sendwin_width',
@@ -1279,7 +1236,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '460',
-        undef,
     ],
     send_h => [
         'sendwin_height',
@@ -1288,7 +1244,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     recv_w => [
         'receivewin_width',
@@ -1297,7 +1252,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '460',
-        undef,
     ],
     recv_h => [
         'receivewin_height',
@@ -1306,7 +1260,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     fold_x => [
         'folderwin_x',
@@ -1315,7 +1268,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '16',
-        undef,
     ],
     fold_y => [
         'folderwin_y',
@@ -1324,7 +1276,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '16',
-        undef,
     ],
     fold_w => [
         'folderitemwin_width',
@@ -1333,7 +1284,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '500',
-        undef,
     ],
     fold_h => [
         'folderitemwin_height',
@@ -1342,7 +1292,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     fsel_w => [
         'folderselwin_width',
@@ -1351,7 +1300,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '300',
-        undef,
     ],
     fsel_h => [
         'folderselwin_height',
@@ -1360,7 +1308,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     sour_w => [
         'sourcewin_width',
@@ -1369,7 +1316,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '600',
-        undef,
     ],
     sour_h => [
         'sourcewin_height',
@@ -1378,7 +1324,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '500',
-        undef,
     ],
     addr_w => [
         'addressbookwin_width',
@@ -1387,7 +1332,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '520',
-        undef,
     ],
     addr_h => [
         'addressbookwin_height',
@@ -1396,7 +1340,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     adep_w => [
         'addressbookeditpersonwin_width',
@@ -1405,7 +1348,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '640',
-        undef,
     ],
     adep_h => [
         'addressbookeditpersonwin_height',
@@ -1414,7 +1356,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '320',
-        undef,
     ],
     adeg_w => [
         'addressbookeditgroupwin_width',
@@ -1423,7 +1364,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '580',
-        undef,
     ],
     adeg_h => [
         'addressbookeditgroupwin_height',
@@ -1432,7 +1372,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '340',
-        undef,
     ],
     adda_w => [
         'addressaddwin_width',
@@ -1441,7 +1380,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '300',
-        undef,
     ],
     adda_h => [
         'addressaddwin_height',
@@ -1450,7 +1388,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     addf_w => [
         'addressbook_folderselwin_width',
@@ -1459,7 +1396,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '300',
-        undef,
     ],
     addf_h => [
         'addressbook_folderselwin_height',
@@ -1468,7 +1404,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     acce_w => [
         'editaccountwin_width',
@@ -1477,7 +1412,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '500',
-        undef,
     ],
     acce_h => [
         'editaccountwin_height',
@@ -1486,7 +1420,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     acco_w => [
         'accountswin_width',
@@ -1495,7 +1428,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '500',
-        undef,
     ],
     acco_h => [
         'accountswin_height',
@@ -1504,7 +1436,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     filt_w => [
         'filteringwin_width',
@@ -1513,7 +1444,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '500',
-        undef,
     ],
     filt_h => [
         'filteringwin_height',
@@ -1522,7 +1452,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     fila_w => [
         'filteringactionwin_width',
@@ -1531,7 +1460,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '490',
-        undef,
     ],
     fila_h => [
         'filteringactionwin_height',
@@ -1540,7 +1468,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     fild_w => [
         'filtering_debugwin_width',
@@ -1549,7 +1476,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '600',
-        undef,
     ],
     fild_h => [
         'filtering_debugwin_height',
@@ -1558,7 +1484,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     matc_w => [
         'matcherwin_width',
@@ -1567,7 +1492,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '520',
-        undef,
     ],
     matc_h => [
         'matcherwin_height',
@@ -1576,7 +1500,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     pref_w => [
         'prefswin_width',
@@ -1585,7 +1508,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '600',
-        undef,
     ],
     pref_h => [
         'prefswin_height',
@@ -1594,7 +1516,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     temp_w => [
         'templateswin_width',
@@ -1603,7 +1524,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '480',
-        undef,
     ],
     temp_h => [
         'templateswin_height',
@@ -1612,7 +1532,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     acti_w => [
         'actionswin_width',
@@ -1621,7 +1540,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '486',
-        undef,
     ],
     acti_h => [
         'actionswin_height',
@@ -1630,7 +1548,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     tags_w => [
         'tagswin_width',
@@ -1639,7 +1556,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '486',
-        undef,
     ],
     tags_h => [
         'tagswin_height',
@@ -1648,7 +1564,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     plug_w => [
         'pluginswin_width',
@@ -1657,7 +1572,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     plug_h => [
         'pluginswin_height',
@@ -1666,7 +1580,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     logw_w => [
         'logwin_width',
@@ -1675,7 +1588,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '520',
-        undef,
     ],
     logw_h => [
         'logwin_height',
@@ -1684,7 +1596,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
     prin_w => [
         'print_previewwin_width',
@@ -1693,7 +1604,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '600',
-        undef,
     ],
     prin_h => [
         'print_previewwin_height',
@@ -1702,7 +1612,6 @@ sub new_colours_page() {
         'int,0,3000', # 0 pixels - 3000 pixels
         '0.0.0',
         '-1',
-        undef,
     ],
 );
 
@@ -1912,7 +1821,6 @@ sub new_winpos_page() {
         'bool',
         '3.9.0.181',
         '0',
-        undef,
     ],
     tls_pri => [
         'gnutls_priority',
@@ -1921,7 +1829,6 @@ sub new_winpos_page() {
         'char,0,256,32',
         '3.9.0.181',
         '0',
-        undef,
     ],
 );
 
@@ -1946,6 +1853,62 @@ sub new_accounts_page() {
     return $accbook;
 }
 
+%pr::plu = ( # plugins hidden preferences
+    # att_remover
+    arm_winw => [
+        'win_width',
+        $xl::s{l_win_w},
+        $xl::s{h_win_w},
+        'int,0,3000', # 0 pixels - 3000 pixels
+        '3.9.0.74',
+        '-1',
+    ],
+    arm_winh => [
+        'win_height',
+        $xl::s{l_win_h},
+        $xl::s{h_win_h},
+        'int,0,3000', # 0 pixels - 3000 pixels
+        '3.9.0.74',
+        '-1',
+    ],
+    # libravatar
+    lav_burl => [
+        'base_url',
+        $xl::s{l_plu_lav_burl},
+        $xl::s{h_plu_lav_burl},
+        'char,0,1024,32',
+        '3.9.3.32',
+        'http://cdn.libravatar.org/avatar',
+    ],
+    # perl
+    prl_flvb => [
+        'filter_log_verbosity',
+        $xl::s{l_plu_prl_flvb},
+        $xl::s{h_plu_prl_flvb},
+        '0=l_plu_prl_none;1=l_plu_prl_manual;2=l_plu_prl_action;3=l_plu_prl_match',
+        '3.9.0.75',
+        '2',
+    ],
+);
+
+sub new_plugins_page() {
+    return new_vbox_pack (
+                new_subpage_frame (
+                     new_hbox_pack (
+                          new_text_box_for_int (\%pr::plu, 'arm_winw', \%HPVALUE),
+                          new_text_box_for_int (\%pr::plu, 'arm_winh', \%HPVALUE)),
+                     _('Attachment remover'), 'not-packed'),
+                new_subpage_frame (
+                     new_hbox_pack (
+                          new_text_box_for_nchar (\%pr::plu, 'lav_burl', \%HPVALUE)),
+                     _('Libravatar'), 'not-packed'),
+                new_subpage_frame (
+                     new_hbox_pack (
+                          new_selection_box_for (\%pr::plu, 'prl_flvb', \%HPVALUE)),
+                     _('Perl'), 'not-packed')
+           );
+}
+
 # version info
 sub print_version() {
     print $xl::s{about_title} . "\n";
@@ -1953,20 +1916,20 @@ sub print_version() {
     print "Perl-GLib " . $Glib::VERSION;
     # version info stuff appeared in 1.040
     if ($Glib::VERSION >= 1.040) {
-        print _(", built for ") . join(".", Glib->GET_VERSION_INFO) 
-              . _(", running with ") . join(".", &Glib::major_version, 
+        print _(", built for ") . join(".", Glib->GET_VERSION_INFO)
+              . _(", running with ") . join(".", &Glib::major_version,
               &Glib::minor_version, &Glib::micro_version);
     }
     print "\n";
     print "Perl-GTK2 " . $Gtk2::VERSION;
     if ($Gtk2::VERSION >= 1.040) {
         print _(", built for ") . join(".", Gtk2->GET_VERSION_INFO)
-              . _(", running with ") . join(".", &Gtk2::major_version, 
+              . _(", running with ") . join(".", &Gtk2::major_version,
               &Gtk2::minor_version, &Gtk2::micro_version);
     }
     print "\n";
-    my $clawsver = ($CLAWSV eq "") ? 
-                _("was not found!") : 
+    my $clawsver = ($CLAWSV eq "") ?
+                _("was not found!") :
                 (_("returned version ") . $CLAWSV);
     print "Claws Mail " . $clawsver . "\n";
 }
@@ -2037,7 +2000,7 @@ sub opt_clawsrc {
 # update the hidden preferences status from loaded values
 sub init_hidden_preferences {
     foreach my $hash (\%pr::beh, \%pr::col, \%pr::gui, \%pr::oth, \%pr::win) {
-        foreach my $key (keys %$hash) { 
+        foreach my $key (keys %$hash) {
             $HPVALUE{${$hash}{$key}[NAME]} = $PREFS{${$hash}{$key}[NAME]};
         }
     }
@@ -2054,20 +2017,81 @@ sub init_ac_hidden_preferences {
     return TRUE;
 }
 
+# generic load/save resource files
+sub load_resource {
+    my $rc = shift;
+    my %data = ();
+    my %meta = ();
+    my $line = 0;
+    open (RCF, '<:encoding(utf8)', $rc)
+        or die _("Error: opening '{file}' for reading", file => $rc) . ": $!";
+    my $section = '_'; # default unnamed section
+    while (<RCF>) {
+        chomp;
+        ++$line;
+        next if (/^\s*$/);
+        if (/^\[([^\]]+)\]$/) { # new section
+            $section = $1;
+            die _("Error: duplicate section '{sect}' in resource file '{file}'\n",
+                sect => $section, file => $rc) if ($data{$section});
+            $data{$section} = {};
+            $meta{$section}{'#'} = $line;
+        }
+        elsif (/^([0-9a-z_]+)=(.*)$/) { # key=value
+            $data{$section}{$1} = $2;
+            $meta{$section}{$1} = $line;
+        }
+        elsif (/^(.*)$/) { # lone value
+            push (@{$data{$section}{'_'}}, $1);
+        }
+    }
+    close (RCF);
+    return (\%data, \%meta);
+}
+
+sub save_resource {
+    my ($rc, $data, $meta) = @_;
+    open (RCF, '>:utf8', $rc)
+        or die _("Error: opening '{file}' for writing", file => $rc) . ": $!";
+    my @sections = keys %$data;
+    if (defined $meta) {
+        @sections = sort {
+            $meta->{$a}{'#'} <=> $meta->{$b}{'#'}
+        } @sections
+    }
+    foreach my $section (@sections) {
+        say RCF "[$section]";
+        if (ref ($data->{$section}{'_'}) eq 'ARRAY') {
+            foreach my $val (@{$data->{$section}{'_'}}) {
+                say RCF $val;
+            }
+        } else {
+            my @keys = keys %{$data->{$section}};
+            if (defined $meta) {
+                @keys = sort {
+                    $meta->{$section}{$a} <=> $meta->{$section}{$b}
+                } @keys
+            }
+            foreach my $key (@keys) {
+                my $val = $data->{$section}{$key};
+                say RCF "$key=$val";
+            }
+        }
+        say RCF "";
+    }
+    close (RCF);
+}
+
 # load current status from disc
 sub load_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 ();
-    open (RCF, "<$rc");
-    while (<RCF>) {
-        chomp;
-        if (/^([8a-z_]+)=(.*)$/) {
-            $PREFS{$1} = decode('UTF-8', $2);
-        }
+    ($CONFIGDATA, $CONFIGMETA) = load_resource ($rc);
+    foreach (keys %{$CONFIGDATA->{'Common'}}) {
+        $PREFS{$_} = $CONFIGDATA->{'Common'}{$_};
     }
-    close (RCF);
     return TRUE;
 }
 
@@ -2076,19 +2100,14 @@ sub load_ac_preferences {
     log_message ("Loading account preferences from $rc\n");
     return FALSE unless check_rc_file ($rc);
     return FALSE unless check_claws_not_running ();
-    open (RCF, "<$rc");
-    my $akey;
-    while (<RCF>) {
-        chomp;
-        if (/^\[Account: (\d+)\]$/) {
-          $akey = $1;
-          next;
-        }
-        if (/^([8a-z_]+)=(.*)$/) {
-            $ACPREFS{$akey}{$1} = decode('UTF-8', $2);
+    ($ACCOUNTDATA, $ACCOUNTMETA) = load_resource ($rc);
+    foreach my $asect (keys %$ACCOUNTDATA) {
+        if ($asect =~ /^Account: (\d+)$/) {
+            foreach (keys %{$ACCOUNTDATA->{$asect}}) {
+                $ACPREFS{$1}{$_} = $ACCOUNTDATA->{$asect}{$_};
+            }
         }
     }
-    close (RCF);
     return TRUE;
 }
 
@@ -2100,24 +2119,12 @@ sub save_preferences {
     return FALSE unless check_claws_not_running ();
     my $rcbak = "$rc.backup";
     rename ($rc, $rcbak);
-    open (RCF, ">$rc");
-    open (RCB, "<$rcbak");
-    while (<RCB>) {
-        chomp;
-        if (/^([8a-z_]+)=(.*)$/) {
-            if (defined($HPVALUE{$1})) {
-                print RCF $1 . "=" . $HPVALUE{$1} . "\n";
-            }
-            else {
-                print RCF $_ . "\n";
-            }
-        }
-        else {
-            print RCF $_ . "\n";
+    foreach (keys %PREFS) {
+        if (defined $HPVALUE{$_}) {
+            $CONFIGDATA->{'Common'}{$_} = $HPVALUE{$_};
         }
     }
-    close (RCB);
-    close (RCF);
+    save_resource ($rc, $CONFIGDATA, $CONFIGMETA);
     return TRUE;
 }
 
@@ -2128,43 +2135,30 @@ sub save_ac_preferences {
     return FALSE unless check_claws_not_running ();
     my $rcbak = "$rc.backup";
     rename ($rc, $rcbak);
-    open (RCF, ">$rc");
-    open (RCB, "<$rcbak");
-    my $akey;
-    while (<RCB>) {
-        chomp;
-        if (/^\[Account: (\d+)\]$/) {
-          $akey = $1;
-          print RCF $_ . "\n";
-          next;
-        }
-        if (/^([8a-z_]+)=(.*)$/) {
-            if (defined($ACHPVALUE{$akey}{$1})) {
-                print RCF $1 . "=" . $ACHPVALUE{$akey}{$1} . "\n";
+    foreach my $asect (keys %$ACCOUNTDATA) {
+        if ($asect =~ /^Account: (\d+)$/) {
+            foreach (keys %{$ACCOUNTDATA->{$asect}}) {
+                if (defined $ACHPVALUE{$1}{$_}) {
+                    $ACCOUNTDATA->{$asect}{$_} = $ACHPVALUE{$1}{$_};
+                }
             }
-            else {
-                print RCF $_ . "\n";
-            }
-        }
-        else {
-            print RCF $_ . "\n";
         }
     }
-    close (RCB);
-    close (RCF);
+    save_resource ($rc, $ACCOUNTDATA, $ACCOUNTMETA);
     return TRUE;
 }
 
 # create notebook
 sub new_notebook {
     my $nb = Gtk2::Notebook->new;
-    # 
+    #
     $nb->append_page (new_behaviour_page (), $xl::s{tab_behaviour});
     $nb->append_page (new_colours_page (), $xl::s{tab_colours});
     $nb->append_page (new_gui_page (), $xl::s{tab_gui});
     $nb->append_page (new_other_page (), $xl::s{tab_other});
     $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});
 
     return $nb;
 }
@@ -2175,7 +2169,7 @@ sub new_about_dialog {
     my $title = $xl::s{about_title};
     my $lic = $xl::s{about_license};
     my $vers = $xl::s{about_version} . " $VERSION";
-    my $license = 
+    my $license =
 "This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
@@ -2192,9 +2186,9 @@ along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.";
     my $holder = "Ricardo Mones &lt;ricardo\@mones.org&gt;";
     my $url = "http://www.claws-mail.org/clawsker.php";
 
-    my $dialog = Gtk2::MessageDialog->new_with_markup ($parent, 
-                    [qw/modal destroy-with-parent/], 
-                    'info', 'close', 
+    my $dialog = Gtk2::MessageDialog->new_with_markup ($parent,
+                    [qw/modal destroy-with-parent/],
+                    'info', 'close',
                     "<span size=\"x-large\" weight=\"bold\">$title</span>\n"
                     . "<span size=\"large\">$vers</span>\n\n"
                     . "<span color=\"blue\" size=\"large\">$url</span>\n\n"
@@ -2215,7 +2209,7 @@ sub new_button_box {
     # disable button until is really implemented
     # my $b_undo = Gtk2::Button->new_from_stock ('gtk-undo');
     my $hbox = Gtk2::HBox->new (FALSE, 5);
-    # signal handlers 
+    # signal handlers
     $b_exit->signal_connect (clicked => sub { Gtk2->main_quit });
     $b_apply->set_sensitive (not $READONLY);
     $b_apply->signal_connect (clicked => sub {