#!/usr/bin/perl -w # # Clawsker :: A Claws Mail Tweaker # Copyright 2007-2014 Ricardo Mones # # 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 # (at your option) any later version. # # See COPYING file for license details. # See AUTHORS file for a complete list of contributors. # use strict; use utf8; use Glib qw(TRUE FALSE); use Gtk2 -init; use POSIX qw(setlocale); use Locale::gettext; use Encode; use Digest::MD5 qw(md5_hex); my $NAME = 'clawsker'; my $PREFIX = '@PREFIX@'; my $LIBDIR = '@LIBDIR@'; my $VERSION = '@VERSION@'; my $VERBOSE = FALSE; my $CLAWSV = undef; my $main_window = undef; my $locale = (defined($ENV{LC_MESSAGES}) ? $ENV{LC_MESSAGES} : $ENV{LANG}); $locale = "C" unless defined($locale); setlocale (LC_ALL, $locale); bindtextdomain ($NAME, sprintf ('%s/share/locale', $PREFIX)); textdomain ($NAME); my $SHOWHINTS = FALSE; $SHOWHINTS = TRUE if ($Gtk2::VERSION >= 1.040 and Gtk2->CHECK_VERSION (2, 12, 0)); sub _ { my $str = shift; my %par = @_; my $xla = gettext ($str); if (scalar(keys(%par)) > 0) { foreach my $key (keys %par) { $xla =~ s/\{$key\}/$par{$key}/g; } } return decode_utf8($xla); } # default messages %xl::s = ( win_title => _('Claws Mail Hidden Preferences'), about => _('About...'), about_title => _('Clawsker :: A Claws Mail Tweaker'), about_license => _('License:'), about_version => _('Version:'), tab_colours => _('Colours'), tab_behaviour => _('Behaviour'), tab_gui => _('GUI'), tab_other => _('Other'), tab_winpos => _('Windows'), ab_frame => _('Addressbook'), mem_frame => _('Memory'), msgview_frame => _('Message View'), log_frame => _('Log window'), dnd_frame => _('Drag \'n\' drop'), ssl_frame => _('Secure Sockets Layer'), msgs_frame => _('Messages'), swc_frame => _('Completion'), stripes_frame => _('Coloured stripes'), sbar_frame => _('Scroll bars'), mlist_frame => _('Message List'), mview_frame => _('Message View'), compo_frame => _('Compose window'), netm_frame => _('NetworkManager'), diff_frame => _('Viewing patches'), 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.'), l_oth_max_use => _('Maximum memory for message cache (kB)'), h_oth_max_use => _('The maximum amount of memory to use to cache messages, in kilobytes.'), l_oth_min_time => _('Minimun time for cache elements (minutes)'), 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.'), l_oth_use_netm => _('Use NetworkManager'), h_oth_use_netm => _('Use NetworkManager to switch offline automatically.'), 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 in compose window'), h_gui_no_markup => _('Don\'t use bold and italic text in Compose dialogue\'s account selector.'), l_gui_dot_lines => _('Use dotted lines in tree view components'), 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.'), l_gui_h_scroll => _('Enable horizontal scrollbar'), h_gui_h_scroll => _('Enable the horizontal scrollbar in the Message List.'), l_gui_swp_from => _('Display To column instead From column in Sent folder'), 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.'), l_gui_v_scroll => _('Folder List scrollbar behaviour'), h_gui_v_scroll => _('Specify the policy of vertical scrollbar of Folder List: show always, automatic or hide always.'), l_gui_v_scroll_show => _('Show always'), l_gui_v_scroll_auto => _('Automatic'), l_gui_v_scroll_hide => _('Hide always'), l_gui_from_show => _('From column displays'), h_gui_from_show => _('Selects the data displayed in the From column of the Message List: name, address or both'), l_gui_from_show_name => _('Name only'), l_gui_from_show_addr => _('Address only'), l_gui_from_show_both => _('Both name and address'), l_gui_strip_off => _('Coloured lines contrast'), 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.'), l_gui_cursor_v => _('Show cursor'), h_gui_cursor_v => _('Display the cursor in the Message View.'), l_gui_toolbar_d => _('Detachable toolbars'), h_gui_toolbar_d => _('Show handles in the toolbars.'), l_gui_strip_all => _('Use stripes in all tree view components'), h_gui_strip_all => _('Enable alternately coloured lines in all tree view components.'), l_gui_strip_sum => _('Use stripes in Folder List and Message List'), h_gui_strip_sum => _('Enable alternately coloured lines in Message List and Folder List.'), l_gui_two_line_v => _('2 lines per Message List item in 3-column layout'), h_gui_two_line_v => _('Spread Message List information over two lines when using the three column mode.'), l_gui_margin_co => _('Show compose margin'), h_gui_margin_co => _('Shows a small margin in the Compose View.'), l_gui_mview_date => _('Don\'t display localized date'), h_gui_mview_date => _('Toggles localization of date format in Message View'), l_gui_zero_char => _('Zero replacement character'), h_gui_zero_char => _('Replaces \'0\' with the given character in Folder List'), l_beh_hover_t => _('Drag \'n\' drop hover timeout (ms)'), 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.'), l_beh_dangerous => _('Don\'t confirm deletions (dangerous!)'), h_beh_dangerous => _('Don\'t ask for confirmation before definitive deletion of emails.'), l_beh_flowed => _('Respect format=flowed in messages'), 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.'), l_beh_parts_rw => _('Allow writable temporary files'), h_beh_parts_rw => _('Saves temporary files when opening attachment with write bit set.'), l_beh_skip_ssl => _('Don\'t check SSL certificates'), h_beh_skip_ssl => _('Disables the verification of SSL certificates.'), l_beh_up_step => _('Progress bar update step (items)'), h_beh_up_step => _('Update stepping in progress bars.'), l_beh_thread_a => _('Maximum age when threading by subject (days)'), h_beh_thread_a => _('Number of days to include a message in a thread when using "Thread using subject in addition to standard headers".'), l_beh_unsafe_ssl => _('Allow unsafe SSL certificates'), h_beh_unsafe_ssl => _('Allows Claws Mail to remember multiple SSL certificates for a given server/port.'), l_beh_use_utf8 => _('Force UTF-8 for broken mails'), h_beh_use_utf8 => _('Use UTF-8 encoding for broken mails instead of current locale.'), 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.'), 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'), 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 the 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_col_emphasis => _('X-Mailer header'), h_col_emphasis => _('The colour used for the X-Mailer line when its value is Claws Mail.'), l_col_log_err => _('Error messages'), h_col_log_err => _('Colour for error messages in log window.'), l_col_log_in => _('Server messages'), h_col_log_in => _('Colour for messages received from servers in log window.'), l_col_log_msg => _('Standard messages'), 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'), h_col_log_warn => _('Colour for warning messages in log window.'), 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.'), l_win_x => _('X position'), h_win_x => _('X coordinate for window\'s top-left corner.'), l_win_y => _('Y position'), h_win_y => _('Y coordinate for window\'s top-left corner.'), l_win_w => _('Width'), h_win_w => _('Window\'s width in pixels.'), l_win_h => _('Height'), h_win_h => _('Window\'s height in pixels.'), l_win_main_mx => _('Maximized'), h_win_main_mx => _('Changes window maximized status.'), l_win_main_fs => _('Full-screen'), h_win_main_fs => _('Changes full screen status.'), e_error => _('Error: '), e_noclawsrc => _('resource file for Claws Mail was not found.'), e_running => _('seems Claws Mail is currently running, close it first.'), e_requireddir => _('option requires a directory name.'), e_requiredfile => _('option requires a file name.'), e_notadir => _('specified name is not a directory or does not exist.'), e_notafile => _('specified name is not a file or does not exist.'), ); # all preferences read by load_preferences my %PREFS = (); # values of all preferences handled by clawsker my %HPVALUE = (); # default config dir and file name my $ALTCONFIGDIR = FALSE; my $CONFIGDIR = $ENV{HOME} . '/.claws-mail/'; my $CONFIGRC = 'clawsrc'; # index constants for preference arrays use constant NAME => 0; # the name on the rc file use constant LABEL => 1; # the label on the GUI 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; use constant FRAME_SPC => 2; use constant PAGE_SPC => 5; # version functions 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 FALSE; } sub get_claws_version { my @cmbin = ( 'claws-mail', ); my $res = ""; foreach my $bin (@cmbin) { $_ = qx/which $bin/; chomp; last if ($_ ne ""); } return "" unless ($_); # not installed $_ = qx/$_ -v/; chomp; my @fver = split (/ /); die "Invalid version string" unless ($fver[2] eq "version"); my @ver = split (/\./, $fver[3]); $res .= "$ver[0]."; $res .= "$ver[1]."; if ($ver[2] =~ /(\d+)cvs(\d+)/) { $res .= "$1.$2"; } else { $res .= "$ver[2].0"; } return $res; } # data handlers and auxiliar functions sub handle_bool_value { my ($widget, $event, $dataref) = @_; $$dataref = ($widget->get_active ())? '1': '0'; } sub handle_int_value { my ($widget, $event, $dataref) = @_; $_ = $widget->get_text (); s/^\s+//; s/\s+$//; if (/^[0-9]+$/) { $$dataref = $_; $widget->set_text ($_); } else { $widget->set_text ($$dataref); } } sub handle_string_value { my ($widget, $event, $dataref) = @_; $$dataref = $widget->get_text (); } sub handle_nchar_value { my ($widget, $event, $dataref, $minlen) = @_; $_ = substr ($widget->get_text (), 0, $minlen); $widget->set_text ($_); $$dataref = $_; } sub gdk_color_from_str { my ($str) = @_; my ($rr, $gg, $bb) = (0, 0 ,0); $_ = 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; $bb = hex($3) * 256; } my $color = Gtk2::Gdk::Color->new ($rr, $gg, $bb); return $color; } sub str_from_gdk_color { my ($color) = @_; my $rr = $color->red / 256; my $gg = $color->green / 256; my $bb = $color->blue / 256; my $str = sprintf ("#%.2x%.2x%.2x", $rr, $gg, $bb); return $str; } sub handle_color_value { my ($widget, $event, $dataref) = @_; my $newcol = $widget->get_color; $$dataref = str_from_gdk_color ($newcol); } sub handle_selection_value { my ($widget, $event, $dataref) = @_; $$dataref = $widget->get_active; } sub get_rc_filename { return $CONFIGDIR . $CONFIGRC; } sub set_rc_filename { my ($fullname) = @_; my @parts = split ('/', $fullname); $CONFIGRC = $parts[$#parts]; $parts[$#parts] = ''; $CONFIGDIR = join ('/', @parts); } sub log_message { my ($mesg, $fatal) = @_; if (defined($fatal) && $fatal eq 'die') { die "$NAME: $mesg\n"; } if ($VERBOSE) { print "$NAME: $mesg\n"; } } sub error_dialog { my ($emsg) = @_; my $markup = "" . $emsg . ""; my $errordlg = Gtk2::MessageDialog->new_with_markup ($main_window, 'modal', 'error', 'cancel', $markup); $errordlg->set_title (_('Error message')); $errordlg->run; $errordlg->destroy; } sub claws_is_running { my $emsg = "$xl::s{e_error}$xl::s{e_running}"; log_message ($emsg); error_dialog ($emsg); return FALSE; } sub check_claws_not_running { my $socket = (not $ALTCONFIGDIR)? "/tmp/": $CONFIGDIR; $socket .= "claws-mail-$<"; -S $socket and return claws_is_running (); # since 3.9.0cvs36 my $lockdir = "/tmp/claws-mail-$<"; -d $lockdir and do { $_ = $CONFIGDIR; s/\/$//; $socket = "$lockdir/" . md5_hex ($_); -S $socket and return claws_is_running (); }; return TRUE; } sub check_rc_file { my ($rcfile) = @_; (defined($rcfile) && -f $rcfile) or do { my $emsg = "$xl::s{e_error}$xl::s{e_noclawsrc}\n"; log_message ($emsg); error_dialog ($emsg); return FALSE; }; return TRUE; } sub set_widget_hint { if ($SHOWHINTS) { my ($wdgt, $hint) = @_; $wdgt->set_tooltip_text ($hint); $wdgt->set_has_tooltip (TRUE); } } sub set_widget_sens { my ($wdgt, $versions) = @_; my @ver = split(/,/, $versions); if ($#ver == 1) { $wdgt->set_sensitive ( version_greater_or_equal ($CLAWSV, $ver[0]) and version_greater_or_equal ($ver[1], $CLAWSV) ); } else { $wdgt->set_sensitive (version_greater_or_equal ($CLAWSV, $ver[0])); } } # graphic element creation sub new_check_button_for { my ($hash, $key) = @_; my $name = $$hash{$key}[NAME]; my $label = $$hash{$key}[LABEL]; # my $hbox = Gtk2::HBox->new (FALSE, 5); my $cb = Gtk2::CheckButton->new ($label); $$hash{$key}[GUI] = $cb; if (defined ($HPVALUE{$name})) { $cb->set_active ($HPVALUE{$name} eq '1'); } $cb->signal_connect (clicked => sub { my ($w, $e) = @_; handle_bool_value ($w, $e, \$HPVALUE{$name}); }); set_widget_hint ($cb, $$hash{$key}[DESC]); set_widget_sens ($cb, $$hash{$key}[CMVER]); $hbox->pack_start ($cb, FALSE, FALSE, HBOX_SPC); # return $hbox; } sub new_text_box_for_int { my ($hash, $key) = @_; 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); # 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); $gentry->set_numeric (TRUE); $gentry->set_value ($HPVALUE{$name}); $$hash{$key}[GUI] = $gentry; $gentry->signal_connect('value-changed' => sub { my ($w, $e) = @_; handle_int_value ($w, $e, \$HPVALUE{$name}); }); 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; } sub new_text_box_for_nchar { my ($hash, $key) = @_; my $name = $$hash{$key}[NAME]; my $label = $$hash{$key}[LABEL]; my @type = split (/,/, $$hash{$key}[TYPE]); # char,minlen,maxlen 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]); $gentry->set_width_chars(int ($type[2]) + 2) if defined ($type[2]); $gentry->set_text ($HPVALUE{$name}); $$hash{$key}[GUI] = $gentry; $gentry->signal_connect('key-release-event' => sub { my ($w, $e) = @_; handle_nchar_value ($w, $e, \$HPVALUE{$name}, $type[1]); }); 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; } sub new_color_button_for { my ($hash, $key) = @_; my $name = $$hash{$key}[NAME]; my $label = $$hash{$key}[LABEL]; # my $col = gdk_color_from_str ($HPVALUE{$name}); my $hbox = Gtk2::HBox->new (FALSE, 5); my $glabel = Gtk2::Label->new ($label); my $button = Gtk2::ColorButton->new_with_color ($col); $$hash{$key}[GUI] = $button; $button->set_title ($label); $button->set_relief ('none'); $button->signal_connect ('color-set' => sub { my ($w, $e) = @_; handle_color_value ($w, $e, \$HPVALUE{$name}); }); 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; } sub new_selection_box_for { my ($hash, $key) = @_; 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; $$hash{$key}[GUI] = $combo; my @options = split (';', $$hash{$key}[TYPE]); foreach my $opt (@options) { my ($index, $textkey) = split ('=', $opt); $combo->insert_text ($index, $xl::s{$textkey}); } $combo->signal_connect ('changed' => sub { my ($w, $e) = @_; handle_selection_value ($w, $e, \$HPVALUE{$name}); }); $combo->set_active ($HPVALUE{$name}); 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; } # more graphic helpers sub new_hbox_pack { my $hbox = Gtk2::HBox->new (FALSE, 5); $hbox->set_border_width (PAGE_SPC); foreach my $item (@_) { $hbox->pack_start ($item, FALSE, FALSE, 0); } return $hbox; } 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); } return $vbox; } 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); } return $vbox; } sub new_subpage_frame { my ($box, $title, $notpacked) = @_; my $frame = Gtk2::Frame->new ($title); $frame->add ($box); return new_vbox_pack ($frame) unless defined ($notpacked); return $frame; } # preference maps and corresponding page creation subs %pr::oth = ( # other preferences 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', $xl::s{l_oth_max_use}, $xl::s{h_oth_max_use}, 'int,0,262144', # 0 Kb - 256 Mb '0.0.0', '4096', undef, ], min_time => [ 'cache_min_keep_time', $xl::s{l_oth_min_time}, $xl::s{h_oth_min_time}, 'int,0,120', # 0 minutes - 2 hours '0.0.0', '15', undef, ], use_netm => [ 'use_networkmanager', $xl::s{l_oth_use_netm}, $xl::s{h_oth_use_netm}, 'bool', '3.3.1', '1', undef, ], ); sub new_other_page() { return new_vbox_pack ( new_subpage_frame ( new_vbox_pack ( new_check_button_for(\%pr::oth, 'use_dlg')), $xl::s{ab_frame}, 'not-packed'), new_subpage_frame ( new_vbox_pack ( new_text_box_for_int(\%pr::oth, 'max_use'), new_text_box_for_int(\%pr::oth, 'min_time')), $xl::s{mem_frame}, 'not-packed'), new_subpage_frame ( new_vbox_pack ( new_check_button_for(\%pr::oth, 'use_netm')), $xl::s{netm_frame}, 'not-packed') ); } %pr::gui = ( # gui bells and whistles 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', $xl::s{l_gui_no_markup}, $xl::s{h_gui_no_markup}, 'bool', '0.0.0', '0', undef, ], dot_lines => [ 'enable_dotted_lines', $xl::s{l_gui_dot_lines}, $xl::s{h_gui_dot_lines}, 'bool', '0.0.0,3.7.10.44', '0', undef, ], h_scroll => [ 'enable_hscrollbar', $xl::s{l_gui_h_scroll}, $xl::s{h_gui_h_scroll}, 'bool', '0.0.0', '1', undef, ], swp_from => [ 'enable_swap_from', $xl::s{l_gui_swp_from}, $xl::s{h_gui_swp_from}, 'bool', '0.0.0', '0', undef, ], v_scroll => [ 'folderview_vscrollbar_policy', $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', undef, ], from_show => [ 'summary_from_show', $xl::s{l_gui_from_show}, $xl::s{h_gui_from_show}, '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', $xl::s{l_gui_strip_off}, $xl::s{h_gui_strip_off}, 'int,0,40000', # no idea what this number means '0.0.0', '4000', undef, ], cursor_v => [ 'textview_cursor_visible', $xl::s{l_gui_cursor_v}, $xl::s{h_gui_cursor_v}, 'bool', '0.0.0', '0', undef, ], toolbar_d => [ 'toolbar_detachable', $xl::s{l_gui_toolbar_d}, $xl::s{h_gui_toolbar_d}, 'bool', '0.0.0', '0', undef, ], strip_all => [ 'use_stripes_everywhere', $xl::s{l_gui_strip_all}, $xl::s{h_gui_strip_all}, 'bool', '0.0.0', '1', undef, ], strip_sum => [ 'use_stripes_in_summaries', $xl::s{l_gui_strip_sum}, $xl::s{h_gui_strip_sum}, 'bool', '0.0.0', '1', undef, ], two_linev => [ 'two_line_vertical', $xl::s{l_gui_two_line_v}, $xl::s{h_gui_two_line_v}, 'bool', '3.4.0.7', '0', undef, ], margin_co => [ 'show_compose_margin', $xl::s{l_gui_margin_co}, $xl::s{h_gui_margin_co}, 'bool', '3.7.6.7', '0', undef, ], mview_date => [ 'msgview_date_format', $xl::s{l_gui_mview_date}, $xl::s{h_gui_mview_date}, 'bool', '3.7.8.42', '0', undef, ], zero_char => [ 'zero_replacement_char', $xl::s{l_gui_zero_char}, $xl::s{h_gui_zero_char}, 'char,1,1', '2.8.1.77', '0', undef, ], ); sub new_gui_page() { my $gf = Gtk2::VBox->new (FALSE, 5); $gf->set_border_width (PAGE_SPC); my $cb_dot_lines = new_check_button_for (\%pr::gui, 'dot_lines'); my $cb_toolbar_d = new_check_button_for (\%pr::gui, 'toolbar_d'); my $tb_zero_char = new_text_box_for_nchar (\%pr::gui, 'zero_char'); $gf->pack_start (new_subpage_frame ( new_vbox_pack ( new_check_button_for (\%pr::gui, 'strip_all'), new_check_button_for (\%pr::gui, 'strip_sum'), new_text_box_for_int (\%pr::gui, 'strip_off')), $xl::s{stripes_frame}, 'not-packed'), FALSE, FALSE, FRAME_SPC); $gf->pack_start (new_subpage_frame ( new_vbox_pack ( new_check_button_for (\%pr::gui, 'b_unread'), new_check_button_for (\%pr::gui, 'swp_from'), new_check_button_for (\%pr::gui, 'two_linev'), new_selection_box_for (\%pr::gui, 'from_show')), $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'), new_check_button_for (\%pr::gui, 'mview_date')), $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'), new_check_button_for (\%pr::gui, 'margin_co')), $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); $gf->pack_start (new_subpage_frame ( new_vbox_pack ( new_check_button_for (\%pr::gui, 'h_scroll'), new_selection_box_for (\%pr::gui, 'v_scroll')), $xl::s{sbar_frame}, 'not-packed'), FALSE, FALSE, FRAME_SPC); $gf->pack_start ($tb_zero_char, FALSE, FALSE, 0); return $gf; } %pr::beh = ( # tweak some behaviour hover_t => [ 'hover_timeout', $xl::s{l_beh_hover_t}, $xl::s{h_beh_hover_t}, 'int,100,3000', # 0.1 seconds - 3 seconds '0.0.0', '500', undef, ], dangerous => [ 'live_dangerously', $xl::s{l_beh_dangerous}, $xl::s{h_beh_dangerous}, 'bool', '0.0.0', '0', undef, ], flowed => [ 'respect_flowed_format', $xl::s{l_beh_flowed}, $xl::s{h_beh_flowed}, 'bool', '0.0.0', '0', undef, ], parts_rw => [ 'save_parts_readwrite', $xl::s{l_beh_parts_rw}, $xl::s{h_beh_parts_rw}, 'bool', '0.0.0', '0', undef, ], skip_ssl => [ 'skip_ssl_cert_check', $xl::s{l_beh_skip_ssl}, $xl::s{h_beh_skip_ssl}, 'bool', '0.0.0', '0', undef, ], up_step => [ 'statusbar_update_step', $xl::s{l_beh_up_step}, $xl::s{h_beh_up_step}, 'int,1,200', # 1 item - 200 items '0.0.0', '10', undef, ], thread_a => [ 'thread_by_subject_max_age', $xl::s{l_beh_thread_a}, $xl::s{h_beh_thread_a}, 'int,1,30', # 1 day - 30 days '0.0.0', '10', undef, ], unsafe_ssl => [ 'unsafe_ssl_certs', $xl::s{l_beh_unsafe_ssl}, $xl::s{h_beh_unsafe_ssl}, 'bool', '0.0.0', '0', undef, ], use_utf8 => [ 'utf8_instead_of_locale_for_broken_mail', $xl::s{l_beh_use_utf8}, $xl::s{h_beh_use_utf8}, 'bool', '0.0.0', '0', undef, ], warn_dnd => [ 'warn_dnd', $xl::s{l_beh_warn_dnd}, $xl::s{h_beh_warn_dnd}, 'bool', '0.0.0', '1', undef, ], out_ascii => [ 'outgoing_fallback_to_ascii', $xl::s{l_beh_out_ascii}, $xl::s{h_beh_out_ascii}, 'bool', '3.4.0.37', '1', undef, ], pp_unsel => [ 'primary_paste_unselects', $xl::s{l_beh_pp_unsel}, $xl::s{h_beh_pp_unsel}, 'bool', '3.6.1.35', '0', undef, ], inline_at => [ 'show_inline_attachments', $xl::s{l_beh_inline_at}, $xl::s{h_beh_inline_at}, 'bool', '3.7.8.48', '1', undef, ], addr_swc => [ 'address_search_wildcard', $xl::s{l_beh_addr_swc}, $xl::s{h_beh_addr_sw1}, 'bool', '3.9.3.18', '0', undef, ], fold_swc => [ 'folder_search_wildcard', $xl::s{l_beh_fold_swc}, $xl::s{h_beh_fold_sw1}, 'bool', '3.9.3.18', '0', undef, ], ); sub new_behaviour_page() { my $bf = Gtk2::VBox->new (FALSE, 5); $bf->set_border_width (PAGE_SPC); my $tb_up_step = new_text_box_for_int (\%pr::beh, 'up_step'); my $tb_thread_a = new_text_box_for_int (\%pr::beh, 'thread_a'); $bf->pack_start (new_subpage_frame ( new_vbox_pack ( new_text_box_for_int (\%pr::beh, 'hover_t'), new_check_button_for (\%pr::beh, 'warn_dnd')), $xl::s{dnd_frame}, 'not-packed'), FALSE, FALSE, FRAME_SPC); $bf->pack_start (new_subpage_frame ( new_hbox_pack ( new_check_button_for (\%pr::beh, 'skip_ssl'), new_check_button_for (\%pr::beh, 'unsafe_ssl')), $xl::s{ssl_frame}, 'not-packed'), FALSE, FALSE, FRAME_SPC); $bf->pack_start ($tb_up_step, FALSE, FALSE, 0); $bf->pack_start ($tb_thread_a, FALSE, FALSE, 0); $bf->pack_start (new_subpage_frame ( new_vbox_pack ( new_check_button_for (\%pr::beh, 'flowed'), new_check_button_for (\%pr::beh, 'parts_rw'), new_check_button_for (\%pr::beh, 'use_utf8'), new_check_button_for (\%pr::beh, 'dangerous'), new_check_button_for (\%pr::beh, 'out_ascii'), new_check_button_for (\%pr::beh, 'pp_unsel'), new_check_button_for (\%pr::beh, 'inline_at')), $xl::s{msgs_frame}, 'not-packed'), FALSE, FALSE, FRAME_SPC); $bf->pack_start (new_subpage_frame ( new_vbox_pack ( new_check_button_for (\%pr::beh, 'addr_swc'), new_check_button_for (\%pr::beh, 'fold_swc')), $xl::s{swc_frame}, 'not-packed'), FALSE, FALSE, FRAME_SPC); return $bf; } %pr::col = ( # a variety of colours emphasis => [ 'emphasis_color', $xl::s{l_col_emphasis}, $xl::s{h_col_emphasis}, 'color', '0.0.0', '#0000cf', undef, ], log_err => [ 'log_error_color', $xl::s{l_col_log_err}, $xl::s{h_col_log_err}, 'color', '0.0.0', '#af0000', undef, ], log_in => [ 'log_in_color', $xl::s{l_col_log_in}, $xl::s{h_col_log_in}, 'color', '0.0.0', '#000000', undef, ], log_msg => [ 'log_msg_color', $xl::s{l_col_log_msg}, $xl::s{h_col_log_msg}, 'color', '0.0.0', '#00af00', undef, ], log_out => [ 'log_out_color', $xl::s{l_col_log_out}, $xl::s{h_col_log_out}, 'color', '0.0.0', '#0000ef', undef, ], log_warn => [ 'log_warn_color', $xl::s{l_col_log_warn}, $xl::s{h_col_log_warn}, 'color', '0.0.0', '#af0000', undef, ], diff_add => [ 'diff_added_color', $xl::s{l_col_diff_add}, $xl::s{h_col_diff_add}, 'color', '3.8.0.54', '#008b8b', undef, ], diff_del => [ 'diff_deleted_color', $xl::s{l_col_diff_del}, $xl::s{h_col_diff_del}, 'color', '3.8.0.54', '#6a5acd', undef, ], diff_hunk => [ 'diff_hunk_color', $xl::s{l_col_diff_hunk}, $xl::s{h_col_diff_hunk}, 'color', '3.8.0.54', '#a52a2a', undef, ], ); sub new_colours_page() { return new_vbox_pack ( new_subpage_frame ( new_vbox_pack ( new_color_button_for (\%pr::col, 'emphasis')), $xl::s{msgview_frame}, 'not-packed'), new_subpage_frame ( new_vbox_pack ( new_color_button_for (\%pr::col, 'log_err'), new_color_button_for (\%pr::col, 'log_in'), new_color_button_for (\%pr::col, 'log_msg'), new_color_button_for (\%pr::col, 'log_out'), new_color_button_for (\%pr::col, 'log_warn')), $xl::s{log_frame}, 'not-packed'), new_subpage_frame ( new_vbox_pack ( new_color_button_for (\%pr::col, 'diff_add'), new_color_button_for (\%pr::col, 'diff_del'), new_color_button_for (\%pr::col, 'diff_hunk')), $xl::s{diff_frame}, 'not-packed') ); } %pr::win = ( # tweak window positions and/or sizes main_x => [ 'mainwin_x', $xl::s{l_win_x}, $xl::s{h_win_x}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '16', undef, ], main_y => [ 'mainwin_y', $xl::s{l_win_y}, $xl::s{h_win_y}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '16', undef, ], main_w => [ 'mainwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '779', undef, ], main_h => [ 'mainwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '568', undef, ], main_mx => [ 'mainwin_maximised', $xl::s{l_win_main_mx}, $xl::s{h_win_main_mx}, 'bool', '0.0.0', '0', undef, ], main_fs => [ 'mainwin_fullscreen', $xl::s{l_win_main_fs}, $xl::s{h_win_main_fs}, 'bool', '0.0.0', '0', undef, ], msgs_x => [ 'main_messagewin_x', $xl::s{l_win_x}, $xl::s{h_win_x}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '256', undef, ], msgs_y => [ 'main_messagewin_y', $xl::s{l_win_y}, $xl::s{h_win_y}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '210', undef, ], msgs_w => [ 'messagewin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '600', undef, ], msgs_h => [ 'messagewin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '540', undef, ], send_w => [ 'sendwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '460', undef, ], send_h => [ 'sendwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], recv_w => [ 'receivewin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '460', undef, ], recv_h => [ 'receivewin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], fold_x => [ 'folderwin_x', $xl::s{l_win_x}, $xl::s{h_win_x}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '16', undef, ], fold_y => [ 'folderwin_y', $xl::s{l_win_y}, $xl::s{h_win_y}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '16', undef, ], fold_w => [ 'folderitemwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '500', undef, ], fold_h => [ 'folderitemwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], fsel_w => [ 'folderselwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '300', undef, ], fsel_h => [ 'folderselwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], sour_w => [ 'sourcewin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '600', undef, ], sour_h => [ 'sourcewin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '500', undef, ], addr_w => [ 'addressbookwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '520', undef, ], addr_h => [ 'addressbookwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], adep_w => [ 'addressbookeditpersonwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '640', undef, ], adep_h => [ 'addressbookeditpersonwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '320', undef, ], adeg_w => [ 'addressbookeditgroupwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '580', undef, ], adeg_h => [ 'addressbookeditgroupwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '340', undef, ], adda_w => [ 'addressaddwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '300', undef, ], adda_h => [ 'addressaddwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], addf_w => [ 'addressbook_folderselwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '300', undef, ], addf_h => [ 'addressbook_folderselwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], acce_w => [ 'editaccountwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '500', undef, ], acce_h => [ 'editaccountwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], acco_w => [ 'accountswin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '500', undef, ], acco_h => [ 'accountswin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], filt_w => [ 'filteringwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '500', undef, ], filt_h => [ 'filteringwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], fila_w => [ 'filteringactionwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '490', undef, ], fila_h => [ 'filteringactionwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], fild_w => [ 'filtering_debugwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '600', undef, ], fild_h => [ 'filtering_debugwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], matc_w => [ 'matcherwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '520', undef, ], matc_h => [ 'matcherwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], pref_w => [ 'prefswin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '600', undef, ], pref_h => [ 'prefswin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], temp_w => [ 'templateswin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '480', undef, ], temp_h => [ 'templateswin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], acti_w => [ 'actionswin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '486', undef, ], acti_h => [ 'actionswin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], tags_w => [ 'tagswin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '486', undef, ], tags_h => [ 'tagswin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], plug_w => [ 'pluginswin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], plug_h => [ 'pluginswin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], logw_w => [ 'logwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '520', undef, ], logw_h => [ 'logwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], prin_w => [ 'print_previewwin_width', $xl::s{l_win_w}, $xl::s{h_win_w}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '600', undef, ], prin_h => [ 'print_previewwin_height', $xl::s{l_win_h}, $xl::s{h_win_h}, 'int,0,3000', # 0 pixels - 3000 pixels '0.0.0', '-1', undef, ], ); sub new_winpos_subpage_main() { return new_subpage_frame ( new_vbox_pack_compact ( new_vbox_pack ( new_text_box_for_int (\%pr::win, 'main_x'), new_text_box_for_int (\%pr::win, 'main_y')), new_hbox_pack ( new_text_box_for_int (\%pr::win, 'main_w'), new_text_box_for_int (\%pr::win, 'main_h')), new_vbox_pack ( new_check_button_for (\%pr::win, 'main_fs'), new_check_button_for (\%pr::win, 'main_mx'))), _('Main window') ); } sub new_winpos_subpage_msgs() { return new_subpage_frame ( new_vbox_pack_compact ( new_vbox_pack ( new_text_box_for_int (\%pr::win, 'msgs_x'), new_text_box_for_int (\%pr::win, 'msgs_y')), new_hbox_pack ( new_text_box_for_int (\%pr::win, 'msgs_w'), new_text_box_for_int (\%pr::win, 'msgs_h'))), _('Message window') ); } sub new_winpos_subpage_sendrecv() { return new_vbox_pack ( new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'send_w'), new_text_box_for_int (\%pr::win, 'send_h')), _('Send window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'recv_w'), new_text_box_for_int (\%pr::win, 'recv_h')), _('Receive window'), 'not-packed') ); } sub new_winpos_subpage_fold() { return new_vbox_pack ( new_subpage_frame ( new_vbox_pack_compact ( new_vbox_pack ( new_text_box_for_int (\%pr::win, 'fold_x'), new_text_box_for_int (\%pr::win, 'fold_y')), new_hbox_pack ( new_text_box_for_int (\%pr::win, 'fold_w'), new_text_box_for_int (\%pr::win, 'fold_h'))), _('Folder window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'fsel_w'), new_text_box_for_int (\%pr::win, 'fsel_h')), _('Folder selection window'), 'not-packed') ); } sub new_winpos_subpage_addrbook() { return new_vbox_pack ( new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'addr_w'), new_text_box_for_int (\%pr::win, 'addr_h')), _('Addressbook main window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'adep_w'), new_text_box_for_int (\%pr::win, 'adep_h')), _('Edit person window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'adeg_w'), new_text_box_for_int (\%pr::win, 'adeg_h')), _('Edit group window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'adda_w'), new_text_box_for_int (\%pr::win, 'adda_h')), _('Add address window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'addf_w'), new_text_box_for_int (\%pr::win, 'addf_h')), _('Folder select window'), 'not-packed') ); } sub new_winpos_subpage_accounts() { return new_vbox_pack ( new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'acco_w'), new_text_box_for_int (\%pr::win, 'acco_h')), _('Accounts window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'acce_w'), new_text_box_for_int (\%pr::win, 'acce_h')), _('Edit account window'), 'not-packed') ); } sub new_winpos_subpage_filtering() { return new_vbox_pack ( new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'filt_w'), new_text_box_for_int (\%pr::win, 'filt_h')), _('Filtering window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'fila_w'), new_text_box_for_int (\%pr::win, 'fila_h')), _('Filtering actions window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'fild_w'), new_text_box_for_int (\%pr::win, 'fild_h')), _('Filtering debug window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'matc_w'), new_text_box_for_int (\%pr::win, 'matc_h')), _('Matcher window'), 'not-packed') ); } sub new_winpos_subpage_prefs() { return new_vbox_pack ( new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'pref_w'), new_text_box_for_int (\%pr::win, 'pref_h')), _('Preferences window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'temp_w'), new_text_box_for_int (\%pr::win, 'temp_h')), _('Templates window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'acti_w'), new_text_box_for_int (\%pr::win, 'acti_h')), _('Actions window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'tags_w'), new_text_box_for_int (\%pr::win, 'tags_h')), _('Tags window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'plug_w'), new_text_box_for_int (\%pr::win, 'plug_h')), _('Plugins window'), 'not-packed') ); } sub new_winpos_subpage_misc() { return new_vbox_pack ( new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'logw_w'), new_text_box_for_int (\%pr::win, 'logw_h')), _('Log window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'prin_w'), new_text_box_for_int (\%pr::win, 'prin_h')), _('Print preview window'), 'not-packed'), new_subpage_frame ( new_hbox_pack ( new_text_box_for_int (\%pr::win, 'sour_w'), new_text_box_for_int (\%pr::win, 'sour_h')), _('View source window'), 'not-packed') ); } sub new_winpos_page() { my $winbook = Gtk2::Notebook->new; $winbook->set_tab_pos ('right'); $winbook->append_page (new_winpos_subpage_main, _('Main')); $winbook->append_page (new_winpos_subpage_msgs, _('Message')); $winbook->append_page (new_winpos_subpage_sendrecv, _('Send/Receive')); $winbook->append_page (new_winpos_subpage_fold, _('Folder')); $winbook->append_page (new_winpos_subpage_addrbook, _('Addressbook')); $winbook->append_page (new_winpos_subpage_accounts, _('Accounts')); $winbook->append_page (new_winpos_subpage_filtering, _('Filtering')); $winbook->append_page (new_winpos_subpage_prefs, _('Preferences')); $winbook->append_page (new_winpos_subpage_misc, _('Other')); return $winbook; } # version info sub print_version() { print $xl::s{about_title} . "\n"; print $xl::s{about_version} . " $VERSION\n"; 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, &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, &Gtk2::minor_version, &Gtk2::micro_version); } print "\n"; my $clawsver = ($CLAWSV eq "") ? _("was not found!") : (_("returned version ") . $CLAWSV); print "Claws Mail " . $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 _(" --help Prints this help screen.\n"); print _(" --version Prints version infos.\n"); print _(" --verbose More messages on standard output.\n"); print _(" --alternate-config-dir Uses as Claws Mail config dir.\n"); print _(" --clawsrc Uses as full resource name.\n"); } # handle errors which don't allow to run sub command_line_fatal { my $reason = shift; my $emsg = $xl::s{e_error} . $reason; error_dialog ($emsg); log_message ("$emsg", 'die'); } # parse the command line sub parse_command_line { $CLAWSV = get_claws_version (); my $arg = 0; while (defined($ARGV[$arg])) { for ($ARGV[$arg]) { /--help/ && do { print_help (); return FALSE; }; /--version/ && do { print_version (); return FALSE; }; /--verbose/ && do { $VERBOSE = TRUE; last; }; /--use-claws-version/ && do { ++$arg; command_line_fatal ("required version") unless defined($ARGV[$arg]); command_line_fatal ("required a dotted numeric value") unless ($ARGV[$arg] =~ /[\d\.]+/); $CLAWSV = $ARGV[$arg]; last; }; /--alternate-config-dir/ && do { ++$arg; command_line_fatal ($xl::s{e_requireddir}) unless defined($ARGV[$arg]); command_line_fatal ($xl::s{e_notadir}) unless -d $ARGV[$arg]; $CONFIGDIR = $ARGV[$arg]; $CONFIGDIR .= "/" unless ($CONFIGDIR =~ /.*\/$/); $ALTCONFIGDIR = TRUE; last; }; /--clawsrc/ && do { ++$arg; command_line_fatal($xl::s{e_requiredfile}) unless defined($ARGV[$arg]); command_line_fatal($xl::s{e_notafile}) unless -f $ARGV[$arg]; set_rc_filename ($ARGV[$arg]); last; }; /.*/ && command_line_fatal ( _("unknown option '{opt}'.\n", opt => $ARGV[$arg])); } ++$arg; } # eveything continues... return TRUE; } # 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) { $HPVALUE{${$hash}{$key}[NAME]} = $PREFS{${$hash}{$key}[NAME]}; } } return TRUE; } # 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 () { chomp; if (/^([8a-z_]+)=(.*)$/) { $PREFS{$1} = decode('UTF-8', $2); } } close (RCF); return TRUE; } # save current preferences to disc sub save_preferences { my $rc = get_rc_filename (); log_message ("Saving preferences to $rc\n"); return FALSE unless check_rc_file ($rc); return FALSE unless check_claws_not_running (); my $rcbak = "$rc.backup"; rename ($rc, $rcbak); open (RCF, ">$rc"); open (RCB, "<$rcbak"); while () { chomp; if (/^([8a-z_]+)=(.*)$/) { if (defined($HPVALUE{$1})) { print RCF $1 . "=" . $HPVALUE{$1} . "\n"; } else { print RCF $_ . "\n"; } } else { print RCF $_ . "\n"; } } close (RCB); close (RCF); 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}); return $nb; } # create an about dialog sub new_about_dialog { my ($parent) = @_; my $title = $xl::s{about_title}; my $lic = $xl::s{about_license}; my $vers = $xl::s{about_version} . " $VERSION"; 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 (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>."; my $year = "2007-2014"; my $holder = "Ricardo Mones <ricardo\@mones.org>"; my $url = "http://www.claws-mail.org/clawsker.php"; my $dialog = Gtk2::MessageDialog->new_with_markup ($parent, [qw/modal destroy-with-parent/], 'info', 'close', "$title\n" . "$vers\n\n" . "$url\n\n" . "Copyright $year by $holder\n\n" . "$lic\n\n" . "$license"); $dialog->set_title ($xl::s{about}); # return $dialog; } # create buttons box sub new_button_box { my ($parent, $adlg) = @_; my $b_about = Gtk2::Button->new_from_stock ('gtk-about'); my $b_exit = Gtk2::Button->new_from_stock ('gtk-quit'); my $b_apply = Gtk2::Button->new_from_stock ('gtk-apply'); # 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 $b_exit->signal_connect (clicked => sub { Gtk2->main_quit }); $b_apply->signal_connect (clicked => sub { save_preferences ($parent) }); # $b_undo->signal_connect (clicked => sub { undo_current_changes }); $b_about->signal_connect (clicked => sub { $adlg->run; $adlg->hide }); # package them $hbox->pack_end ($b_apply, FALSE, FALSE, 0); $hbox->pack_end ($b_exit, FALSE, FALSE, 0); # $hbox->pack_end ($b_undo, FALSE, FALSE, 0); $hbox->pack_start ($b_about, FALSE, FALSE, 0); # return $hbox; } # initialise $main_window = Gtk2::Window->new ('toplevel'); exit unless parse_command_line (); exit unless load_preferences (); exit unless init_hidden_preferences (); # create main GUI my $box = Gtk2::VBox->new (FALSE, 5); $box->set_border_width(3); my $about = new_about_dialog (); $box->pack_start (new_notebook (), FALSE, FALSE, 0); $box->pack_end (new_button_box ($main_window, $about), FALSE, FALSE, 0); $main_window->signal_connect (delete_event => sub { Gtk2->main_quit }); $main_window->set_title ($xl::s{win_title}); $main_window->add ($box); $main_window->show_all; Gtk2->main;