10 Clawsker - A Claws Mail Tweaker
18 Clawsker is an applet to edit the so called Claws Mail hidden preferences.
20 Claws Mail is a fast, lightweight and feature-rich MUA with a high number
21 of configurable options. To keep the binary small and fast some of these
22 preferences which are not widely used are not provided with a graphical
23 interface for inspection and/or modification.
25 Users wanting to edit such preferences had to face raw editing of their
26 configuration files, now you can do it with a convenient GTK2 interface
32 Shows a brief help screen.
35 Show information about program, Claws Mail and Perl-GTK versions.
38 Tells more on the standard output.
40 --alternate-config-dir <dir>
41 Uses <dir> as Claws Mail configuration dir.
44 Uses <file> as Claws Mail resource configuration file. This sets
45 the full file name overriding any previous setting.
47 Multiple options are allowed, although only the last one has effect. Weird
48 option specifications may produce weird results (but otherwise correct).
52 A running Claws Mail cannot be detected if using the --clawsrc option because
53 the directory is not assumed to be a Claws Mail configuration dir. If that is
54 the case use the --alternate-config-dir option instead.
58 Clawsker homepage "L<http://www.claws-mail.org/clawsker>"
62 Main author is Ricardo Mones E<lt>ricardo@mones.orgE<gt> with the help of
63 others. See the AUTHORS file on source tarball for a detailed list of
68 Copyright (c) 2007-2009 by Ricardo Mones Lastra
70 This program is free software: you can redistribute it and/or modify
71 it under the terms of the GNU General Public License as published by
72 the Free Software Foundation, either version 3 of the License, or
73 (at your option) any later version.
75 This program is distributed in the hope that it will be useful,
76 but WITHOUT ANY WARRANTY; without even the implied warranty of
77 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
78 GNU General Public License for more details.
80 You should have received a copy of the GNU General Public License
81 along with this program. If not, see E<lt>http://www.gnu.org/licenses/E<gt>.
87 use Glib qw(TRUE FALSE);
89 use POSIX qw(setlocale);
92 my $NAME = 'clawsker';
93 my $PREFIX = '@PREFIX@';
94 my $LIBDIR = '@LIBDIR@';
95 my $VERSION = '@VERSION@';
98 my $main_window = undef;
100 my $locale = (defined($ENV{LC_MESSAGES}) ? $ENV{LC_MESSAGES} : $ENV{LANG});
101 $locale = "C" unless defined($locale);
102 setlocale (LC_ALL, $locale);
103 bindtextdomain ($NAME, sprintf ('%s/share/locale', $PREFIX));
106 my $SHOWHINTS = FALSE;
107 $SHOWHINTS = TRUE if ($Gtk2::VERSION >= 1.040 and Gtk2->CHECK_VERSION (2, 12, 0));
112 my $xla = gettext ($str);
113 if (scalar(keys(%par)) > 0) {
114 foreach my $key (keys %par) {
115 $xla =~ s/\{$key\}/$par{$key}/g;
123 win_title => _('Claws Mail Hidden Preferences'),
124 about => _('About...'),
125 about_title => _('Clawsker :: A Claws Mail Tweaker'),
126 about_license => _('License:'),
127 about_version => _('Version:'),
129 tab_colours => _('Colours'),
130 tab_behaviour => _('Behaviour'),
132 tab_other => _('Other'),
133 tab_winpos => _('Windows'),
135 ab_frame => _('Addressbook'),
136 mem_frame => _('Memory'),
137 msgview_frame => _('Message view'),
138 log_frame => _('Log window'),
139 dnd_frame => _('Drag \'n\' drop'),
140 ssl_frame => _('Secure Sockets Layer'),
141 msgs_frame => _('Messages'),
142 stripes_frame => _('Coloured stripes'),
143 sbar_frame => _('Scroll bars'),
144 mlist_frame => _('Message List'),
145 netm_frame => _('NetworkManager'),
147 l_oth_use_dlg => _('Use detached address book edit dialogue'),
148 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.'),
149 l_oth_max_use => _('Maximum memory for message cache (kB)'),
150 h_oth_max_use => _('The maximum amount of memory to use to cache messages, in kilobytes.'),
151 l_oth_min_time => _('Minimun time for cache elements (minutes)'),
152 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.'),
153 l_oth_use_netm => _('Use NetworkManager'),
154 h_oth_use_netm => _('Use NetworkManager to switch offline automatically.'),
156 l_gui_b_unread => _('Show unread messages with bold font'),
157 h_gui_b_unread => _('Show unread messages in the Message List using a bold font.'),
158 l_gui_no_markup => _('Don\'t use markup in compose window'),
159 h_gui_no_markup => _('Don\'t use bold and italic text in Compose dialogue\'s account selector.'),
160 l_gui_dot_lines => _('Use dotted lines in tree view components'),
161 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.'),
162 l_gui_h_scroll => _('Enable horizontal scrollbar'),
163 h_gui_h_scroll => _('Enable the horizontal scrollbar in the Message List.'),
164 l_gui_swp_from => _('Display To column instead From column in Sent folder'),
165 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.'),
166 l_gui_v_scroll => _('Folder List scrollbar behaviour'),
167 h_gui_v_scroll => _('Specify the policy of vertical scrollbar of Folder List: show always, automatic or hide always.'),
168 l_gui_v_scroll_show => _('Show always'),
169 l_gui_v_scroll_auto => _('Automatic'),
170 l_gui_v_scroll_hide => _('Hide always'),
171 l_gui_strip_off => _('Coloured lines contrast'),
172 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.'),
173 l_gui_cursor_v => _('Show Cursor in message view'),
174 h_gui_cursor_v => _('Display the cursor in the message view.'),
175 l_gui_toolbar_d => _('Detachable toolbars'),
176 h_gui_toolbar_d => _('Show handles in the toolbars.'),
177 l_gui_strip_all => _('Use stripes in all tree view components'),
178 h_gui_strip_all => _('Enable alternately coloured lines in all tree view components.'),
179 l_gui_strip_sum => _('Use stripes in Folder List and Message List'),
180 h_gui_strip_sum => _('Enable alternately coloured lines in Message list and Folder list.'),
181 l_gui_two_line_v => _('2 lines per Message List item in 3-column layout'),
182 h_gui_two_line_v => _('Spread Message List information over two lines when using the three column mode.'),
184 l_beh_hover_t => _('Drag \'n\' drop hover timeout (ms)'),
185 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.'),
186 l_beh_dangerous => _('Don\'t confirm deletions (dangerous!)'),
187 h_beh_dangerous => _('Don\'t ask for confirmation before definitive deletion of emails.'),
188 l_beh_flowed => _('Respect format=flowed in messages'),
189 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.'),
190 l_beh_parts_rw => _('Allow writable temporary files'),
191 h_beh_parts_rw => _('Saves temporary files when opening attachment with write bit set.'),
192 l_beh_skip_ssl => _('Don\'t check SSL certificates'),
193 h_beh_skip_ssl => _('Disables the verification of SSL certificates.'),
194 l_beh_up_step => _('Progress bar update step (items)'),
195 h_beh_up_step => _('Update stepping in progress bars.'),
196 l_beh_thread_a => _('Maximum age when threading by subject (days)'),
197 h_beh_thread_a => _('Number of days to include a message in a thread when using "Thread using subject in addition to standard headers".'),
198 l_beh_unsafe_ssl => _('Allow unsafe SSL certificates'),
199 h_beh_unsafe_ssl => _('Allows Claws Mail to remember multiple SSL certificates for a given server/port.'),
200 l_beh_use_utf8 => _('Force UTF-8 for broken mails'),
201 h_beh_use_utf8 => _('Use UTF-8 encoding for broken mails instead of current locale.'),
202 l_beh_warn_dnd => _('Warn on drag \'n\' drop'),
203 h_beh_warn_dnd => _('Display a confirmation dialogue on drag \'n\' drop of folders.'),
204 l_beh_out_ascii => _('Ougoing messages fallback to ASCII'),
205 h_beh_out_ascii => _('If content allows, ASCII will be used to encode outgoing messages, otherwise the user-defined encoding is enforced always.'),
206 l_beh_pp_unsel => _('Primary paste unselects selection'),
207 h_beh_pp_unsel => _('Controls how pasting using middle-click changes the selected text and insertion point.'),
209 l_col_emphasis => _('X-Mailer header'),
210 h_col_emphasis => _('The colour used for the X-Mailer line when its value is Claws Mail.'),
211 l_col_log_err => _('Error messages'),
212 h_col_log_err => _('Colour for error messages in log window.'),
213 l_col_log_in => _('Server messages'),
214 h_col_log_in => _('Colour for messages received from servers in log window.'),
215 l_col_log_msg => _('Standard messages'),
216 h_col_log_msg => _('Colour for messages in log window.'),
217 l_col_log_out => _('Client messages'),
218 h_col_log_out => _('Colour for messages sent to servers in log window.'),
219 l_col_log_warn => _('Warnings'),
220 h_col_log_warn => _('Colour for warning messages in log window.'),
222 l_win_x => _('X position'),
223 h_win_x => _('X coordinate for window\'s top-left corner.'),
224 l_win_y => _('Y position'),
225 h_win_y => _('Y coordinate for window\'s top-left corner.'),
226 l_win_w => _('Width'),
227 h_win_w => _('Window\'s width in pixels.'),
228 l_win_h => _('Height'),
229 h_win_h => _('Window\'s height in pixels.'),
231 l_win_main_mx => _('Maximized'),
232 h_win_main_mx => _('Changes window maximized status.'),
233 l_win_main_fs => _('Full-screen'),
234 h_win_main_fs => _('Changes full screen status.'),
236 e_error => _('Error: '),
237 e_noclawsrc => _('resource file for Claws Mail was not found.'),
238 e_running => _('seems Claws Mail is currently running, close it first.'),
239 e_requireddir => _('option requires a directory name.'),
240 e_requiredfile => _('option requires a file name.'),
241 e_notadir => _('specified name is not a directory or does not exist.'),
242 e_notafile => _('specified name is not a file or does not exist.'),
245 # all preferences read by load_preferences
247 # values of all preferences handled by clawsker
249 # default config dir and file name
250 my $ALTCONFIGDIR = FALSE;
251 my $CONFIGDIR = $ENV{HOME} . '/.claws-mail/';
252 my $CONFIGRC = 'clawsrc';
254 # index constants for preference arrays
255 use constant NAME => 0; # the name on the rc file
256 use constant LABEL => 1; # the label on the GUI
257 use constant DESC => 2; # the description for the hint/help
258 use constant TYPE => 3; # data type: bool, int, float, string, color
259 use constant CMVER => 4; # lowest Claws Mail version the feature exists
260 use constant CMDEF => 5; # default value for the preference in Claws Mail
261 use constant GUI => 6; # GUI element
263 # constants for GUI spacing
264 use constant HBOX_SPC => 5;
265 use constant FRAME_SPC => 2;
266 use constant PAGE_SPC => 5;
270 sub version_greater_or_equal() {
271 my ($version, $refvers) = @_;
272 my @version = split (/\./, $version);
273 my @refvers = split (/\./, $refvers);
274 while ($#version < $#refvers) {
275 push (@version, '0');
278 while (($idx <= $#refvers)
279 and (int ($version[$idx]) == int ($refvers[$idx]))) {
282 return TRUE if (($idx > $#refvers)
283 or (int ($version[$idx]) >= int ($refvers[$idx])));
287 sub get_claws_version() {
292 foreach my $bin (@cmbin) {
297 return "" unless ($_); # not installed
300 my @fver = split (/ /);
301 die "Invalid version string" unless ($fver[2] eq "version");
302 my @ver = split (/\./, $fver[3]);
305 if ($ver[2] =~ /(\d+)cvs(\d+)/) {
314 # data handlers and auxiliar functions
316 sub handle_bool_value {
317 my ($widget, $event, $dataref) = @_;
318 $$dataref = ($widget->get_active ())? '1': '0';
321 sub handle_int_value {
322 my ($widget, $event, $dataref) = @_;
323 $_ = $widget->get_text ();
328 $widget->set_text ($_);
331 $widget->set_text ($$dataref);
335 sub handle_string_value {
336 my ($widget, $event, $dataref) = @_;
337 $$dataref = $widget->get_text ();
340 sub gdk_color_from_str {
342 my ($rr, $gg, $bb) = (0, 0 ,0);
344 if (/\#([A-F0-9][A-F0-9])([A-F0-9][A-F0-9])([A-F0-9][A-F0-9])/) {
349 my $color = Gtk2::Gdk::Color->new ($rr, $gg, $bb);
353 sub str_from_gdk_color {
355 my $rr = $color->red / 256;
356 my $gg = $color->green / 256;
357 my $bb = $color->blue / 256;
358 my $str = sprintf ("#%.2x%.2x%.2x", $rr, $gg, $bb);
362 sub handle_color_value {
363 my ($widget, $event, $dataref) = @_;
364 my $newcol = $widget->get_color;
365 $$dataref = &str_from_gdk_color ($newcol);
368 sub handle_selection_value {
369 my ($widget, $event, $dataref) = @_;
370 $$dataref = $widget->get_active;
373 sub get_rc_filename {
374 return $CONFIGDIR . $CONFIGRC;
377 sub set_rc_filename {
379 my @parts = split ('/', $fullname);
380 $CONFIGRC = $parts[$#parts];
381 $parts[$#parts] = '';
382 $CONFIGDIR = join ('/', @parts);
386 my ($mesg, $fatal) = @_;
387 if (defined($fatal) && $fatal eq 'die') {
388 die "$NAME: $mesg\n";
391 print "$NAME: $mesg\n";
397 my $markup = "<span weight=\"bold\" size=\"large\">" . $emsg . "</span>";
398 my $errordlg = Gtk2::MessageDialog->new_with_markup ($main_window, 'modal', 'error', 'cancel', $markup);
399 $errordlg->set_title (_('Error message'));
404 sub check_claws_not_running() {
405 my $socket = (not $ALTCONFIGDIR)? "/tmp/": $CONFIGDIR;
406 $socket .= "claws-mail-$<";
408 my $emsg = "$xl::s{e_error}$xl::s{e_running}";
410 error_dialog ($emsg);
417 sub check_rc_file() {
419 (defined($rcfile) && -f $rcfile) or do {
420 my $emsg = "$xl::s{e_error}$xl::s{e_noclawsrc}\n";
422 error_dialog ($emsg);
429 sub set_widget_hint() {
431 my ($wdgt, $hint) = @_;
432 $wdgt->set_tooltip_text ($hint);
433 $wdgt->set_has_tooltip (TRUE);
437 sub set_widget_sens() {
438 my ($wdgt, $minver) = @_;
439 $wdgt->set_sensitive (&version_greater_or_equal ($CLAWSV, $minver));
442 # graphic element creation
444 sub new_check_button_for {
445 my ($hash, $key) = @_;
446 my $name = $$hash{$key}[NAME];
447 my $label = $$hash{$key}[LABEL];
449 my $hbox = Gtk2::HBox->new (FALSE, 5);
450 my $cb = Gtk2::CheckButton->new ($label);
451 $$hash{$key}[GUI] = $cb;
452 if (defined ($HPVALUE{$name})) {
453 $cb->set_active ($HPVALUE{$name} eq '1');
455 $cb->signal_connect (clicked => sub {
457 &handle_bool_value($w, $e, \$HPVALUE{$name});
459 &set_widget_hint ($cb, $$hash{$key}[DESC]);
460 &set_widget_sens ($cb, $$hash{$key}[CMVER]);
461 $hbox->pack_start ($cb, FALSE, FALSE, HBOX_SPC);
466 sub new_text_box_for_int {
467 my ($hash, $key) = @_;
468 my $name = $$hash{$key}[NAME];
469 my $label = $$hash{$key}[LABEL];
470 my @type = split (/,/, $$hash{$key}[TYPE]);
471 push (@type, 0), push (@type, 10000) unless ($#type > 0);
473 my $hbox = Gtk2::HBox->new (FALSE, 5);
474 my $glabel = Gtk2::Label->new ($label);
475 my $pagei = int (($type[2] - $type[1]) / 10);
476 my $adjust = Gtk2::Adjustment->new (
477 $HPVALUE{$name}, $type[1], $type[2], 1, $pagei, 10
479 my $gentry = Gtk2::SpinButton->new ($adjust, 1, 0);
480 $gentry->set_numeric (TRUE);
481 $$hash{$key}[GUI] = $gentry;
482 $gentry->signal_connect('value-changed' => sub {
484 &handle_int_value($w, $e, \$HPVALUE{$name});
486 &set_widget_hint ($gentry, $$hash{$key}[DESC]);
487 &set_widget_sens ($gentry, $$hash{$key}[CMVER]);
488 $glabel->set_sensitive ($gentry->sensitive);
489 $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
490 $hbox->pack_start ($gentry, FALSE, FALSE, HBOX_SPC);
495 sub new_color_button_for {
496 my ($hash, $key) = @_;
497 my $name = $$hash{$key}[NAME];
498 my $label = $$hash{$key}[LABEL];
500 my $col = &gdk_color_from_str ($HPVALUE{$name});
501 my $hbox = Gtk2::HBox->new (FALSE, 5);
502 my $glabel = Gtk2::Label->new ($label);
503 my $button = Gtk2::ColorButton->new_with_color ($col);
504 $$hash{$key}[GUI] = $button;
505 $button->set_title ($label);
506 $button->set_relief ('none');
507 $button->signal_connect ('color-set' => sub {
509 &handle_color_value($w, $e, \$HPVALUE{$name});
511 &set_widget_hint ($button, $$hash{$key}[DESC]);
512 &set_widget_sens ($button, $$hash{$key}[CMVER]);
513 $glabel->set_sensitive ($button->sensitive);
514 $hbox->pack_start ($button, FALSE, FALSE, HBOX_SPC);
515 $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
520 sub new_selection_box_for {
521 my ($hash, $key) = @_;
522 my $name = $$hash{$key}[NAME];
523 my $label = $$hash{$key}[LABEL];
525 my $hbox = Gtk2::HBox->new (FALSE, 5);
526 my $glabel = Gtk2::Label->new ($label);
527 my $combo = Gtk2::ComboBox->new_text;
528 $$hash{$key}[GUI] = $combo;
529 my @options = split (';', $$hash{$key}[TYPE]);
530 foreach my $opt (@options) {
531 my ($index, $textkey) = split ('=', $opt);
532 $combo->insert_text ($index, $xl::s{$textkey});
534 $combo->signal_connect ('changed' => sub {
536 &handle_selection_value($w, $e, \$HPVALUE{$name});
538 $combo->set_active ($HPVALUE{$name});
539 &set_widget_hint ($combo, $$hash{$key}[DESC]);
540 &set_widget_sens ($combo, $$hash{$key}[CMVER]);
541 $glabel->set_sensitive ($combo->sensitive);
542 $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
543 $hbox->pack_start ($combo, FALSE, FALSE, HBOX_SPC);
548 # more graphic helpers
550 sub new_hbox_pack() {
551 my $hbox = Gtk2::HBox->new (FALSE, 5);
552 $hbox->set_border_width (PAGE_SPC);
553 foreach my $item (@_) {
554 $hbox->pack_start ($item, FALSE, FALSE, 0);
559 sub new_vbox_pack() {
560 my $vbox = Gtk2::VBox->new (FALSE, 5);
561 $vbox->set_border_width (PAGE_SPC);
562 foreach my $item (@_) {
563 $vbox->pack_start ($item, FALSE, FALSE, 0);
568 sub new_subpage_frame () {
569 my ($box, $title, $notpacked) = @_;
570 my $frame = Gtk2::Frame->new ($title);
572 return &new_vbox_pack ($frame) unless defined ($notpacked);
576 # preference maps and corresponding page creation subs
578 %pr::oth = ( # other preferences
580 'addressbook_use_editaddress_dialog',
581 $xl::s{l_oth_use_dlg},
582 $xl::s{h_oth_use_dlg},
589 'cache_max_mem_usage',
590 $xl::s{l_oth_max_use},
591 $xl::s{h_oth_max_use},
592 'int,0,262144', # 0 Kb - 256 Mb
598 'cache_min_keep_time',
599 $xl::s{l_oth_min_time},
600 $xl::s{h_oth_min_time},
601 'int,0,120', # 0 minutes - 2 hours
607 'use_networkmanager',
608 $xl::s{l_oth_use_netm},
609 $xl::s{h_oth_use_netm},
617 sub new_other_page() {
618 return &new_vbox_pack (
621 &new_check_button_for(\%pr::oth, 'use_dlg')),
622 $xl::s{ab_frame}, 'not-packed'),
625 &new_text_box_for_int(\%pr::oth, 'max_use'),
626 &new_text_box_for_int(\%pr::oth, 'min_time')),
627 $xl::s{mem_frame}, 'not-packed'),
630 &new_check_button_for(\%pr::oth, 'use_netm')),
631 $xl::s{netm_frame}, 'not-packed')
635 %pr::gui = ( # gui bells and whistles
638 $xl::s{l_gui_b_unread},
639 $xl::s{h_gui_b_unread},
647 $xl::s{l_gui_no_markup},
648 $xl::s{h_gui_no_markup},
655 'enable_dotted_lines',
656 $xl::s{l_gui_dot_lines},
657 $xl::s{h_gui_dot_lines},
665 $xl::s{l_gui_h_scroll},
666 $xl::s{h_gui_h_scroll},
674 $xl::s{l_gui_swp_from},
675 $xl::s{h_gui_swp_from},
682 'folderview_vscrollbar_policy',
683 $xl::s{l_gui_v_scroll},
684 $xl::s{h_gui_v_scroll},
685 '0=l_gui_v_scroll_show;1=l_gui_v_scroll_auto;2=l_gui_v_scroll_hide',
691 'stripes_color_offset',
692 $xl::s{l_gui_strip_off},
693 $xl::s{h_gui_strip_off},
694 'int,0,10000', # no idea what this number means
700 'textview_cursor_visible',
701 $xl::s{l_gui_cursor_v},
702 $xl::s{h_gui_cursor_v},
709 'toolbar_detachable',
710 $xl::s{l_gui_toolbar_d},
711 $xl::s{h_gui_toolbar_d},
718 'use_stripes_everywhere',
719 $xl::s{l_gui_strip_all},
720 $xl::s{h_gui_strip_all},
727 'use_stripes_in_summaries',
728 $xl::s{l_gui_strip_sum},
729 $xl::s{h_gui_strip_sum},
737 $xl::s{l_gui_two_line_v},
738 $xl::s{h_gui_two_line_v},
747 my $gf = Gtk2::VBox->new (FALSE, 5);
748 $gf->set_border_width (PAGE_SPC);
750 my $cb_no_markup = &new_check_button_for (\%pr::gui, 'no_markup');
751 my $cb_dot_lines = &new_check_button_for (\%pr::gui, 'dot_lines');
752 my $cb_cursor_v = &new_check_button_for (\%pr::gui, 'cursor_v');
753 my $cb_toolbar_d = &new_check_button_for (\%pr::gui, 'toolbar_d');
754 my $cb_two_linev = &new_check_button_for (\%pr::gui, 'two_linev');
756 $gf->pack_start (&new_subpage_frame (
758 &new_check_button_for (\%pr::gui, 'strip_all'),
759 &new_check_button_for (\%pr::gui, 'strip_sum'),
760 &new_text_box_for_int (\%pr::gui, 'strip_off')),
761 $xl::s{stripes_frame}, 'not-packed'),
762 FALSE, FALSE, FRAME_SPC);
763 $gf->pack_start (&new_subpage_frame (
765 &new_check_button_for (\%pr::gui, 'b_unread'),
766 &new_check_button_for (\%pr::gui, 'swp_from')),
767 $xl::s{mlist_frame}, 'not-packed'),
768 FALSE, FALSE, FRAME_SPC);
769 $gf->pack_start ($cb_no_markup, FALSE, FALSE, 0);
770 $gf->pack_start ($cb_dot_lines, FALSE, FALSE, 0);
771 $gf->pack_start ($cb_cursor_v, FALSE, FALSE, 0);
772 $gf->pack_start ($cb_toolbar_d, FALSE, FALSE, 0);
773 $gf->pack_start ($cb_two_linev, FALSE, FALSE, 0);
774 $gf->pack_start (&new_subpage_frame (
776 &new_check_button_for (\%pr::gui, 'h_scroll'),
777 &new_selection_box_for (\%pr::gui, 'v_scroll')),
778 $xl::s{sbar_frame}, 'not-packed'),
779 FALSE, FALSE, FRAME_SPC);
784 %pr::beh = ( # tweak some behaviour
787 $xl::s{l_beh_hover_t},
788 $xl::s{h_beh_hover_t},
789 'int,100,3000', # 0.1 seconds - 3 seconds
796 $xl::s{l_beh_dangerous},
797 $xl::s{h_beh_dangerous},
804 'respect_flowed_format',
805 $xl::s{l_beh_flowed},
806 $xl::s{h_beh_flowed},
813 'save_parts_readwrite',
814 $xl::s{l_beh_parts_rw},
815 $xl::s{h_beh_parts_rw},
822 'skip_ssl_cert_check',
823 $xl::s{l_beh_skip_ssl},
824 $xl::s{h_beh_skip_ssl},
831 'statusbar_update_step',
832 $xl::s{l_beh_up_step},
833 $xl::s{h_beh_up_step},
834 'int,1,200', # 1 item - 200 items
840 'thread_by_subject_max_age',
841 $xl::s{l_beh_thread_a},
842 $xl::s{h_beh_thread_a},
843 'int,1,30', # 1 day - 30 days
850 $xl::s{l_beh_unsafe_ssl},
851 $xl::s{h_beh_unsafe_ssl},
858 'utf8_instead_of_locale_for_broken_mail',
859 $xl::s{l_beh_use_utf8},
860 $xl::s{h_beh_use_utf8},
868 $xl::s{l_beh_warn_dnd},
869 $xl::s{h_beh_warn_dnd},
876 'outgoing_fallback_to_ascii',
877 $xl::s{l_beh_out_ascii},
878 $xl::s{h_beh_out_ascii},
885 'primary_paste_unselects',
886 $xl::s{l_beh_pp_unsel},
887 $xl::s{h_beh_pp_unsel},
895 sub new_behaviour_page() {
896 my $bf = Gtk2::VBox->new (FALSE, 5);
897 $bf->set_border_width (PAGE_SPC);
899 my $tb_up_step = &new_text_box_for_int (\%pr::beh, 'up_step');
900 my $tb_thread_a = &new_text_box_for_int (\%pr::beh, 'thread_a');
902 $bf->pack_start (&new_subpage_frame (
904 &new_text_box_for_int (\%pr::beh, 'hover_t'),
905 &new_check_button_for (\%pr::beh, 'warn_dnd')),
906 $xl::s{dnd_frame}, 'not-packed'),
907 FALSE, FALSE, FRAME_SPC);
908 $bf->pack_start (&new_subpage_frame (
910 &new_check_button_for (\%pr::beh, 'skip_ssl'),
911 &new_check_button_for (\%pr::beh, 'unsafe_ssl')),
912 $xl::s{ssl_frame}, 'not-packed'),
913 FALSE, FALSE, FRAME_SPC);
914 $bf->pack_start ($tb_up_step, FALSE, FALSE, 0);
915 $bf->pack_start ($tb_thread_a, FALSE, FALSE, 0);
916 $bf->pack_start (&new_subpage_frame (
918 &new_check_button_for (\%pr::beh, 'flowed'),
919 &new_check_button_for (\%pr::beh, 'parts_rw'),
920 &new_check_button_for (\%pr::beh, 'use_utf8'),
921 &new_check_button_for (\%pr::beh, 'dangerous'),
922 &new_check_button_for (\%pr::beh, 'out_ascii'),
923 &new_check_button_for (\%pr::beh, 'pp_unsel')),
924 $xl::s{msgs_frame}, 'not-packed'),
925 FALSE, FALSE, FRAME_SPC);
930 %pr::col = ( # a variety of colours
933 $xl::s{l_col_emphasis},
934 $xl::s{h_col_emphasis},
942 $xl::s{l_col_log_err},
943 $xl::s{h_col_log_err},
951 $xl::s{l_col_log_in},
952 $xl::s{h_col_log_in},
960 $xl::s{l_col_log_msg},
961 $xl::s{h_col_log_msg},
969 $xl::s{l_col_log_out},
970 $xl::s{h_col_log_out},
978 $xl::s{l_col_log_warn},
979 $xl::s{h_col_log_warn},
987 sub new_colours_page() {
988 return &new_vbox_pack (
991 &new_color_button_for (\%pr::col, 'emphasis')),
992 $xl::s{msgview_frame}, 'not-packed'),
995 &new_color_button_for (\%pr::col, 'log_err'),
996 &new_color_button_for (\%pr::col, 'log_in'),
997 &new_color_button_for (\%pr::col, 'log_msg'),
998 &new_color_button_for (\%pr::col, 'log_out'),
999 &new_color_button_for (\%pr::col, 'log_warn')),
1000 $xl::s{log_frame}, 'not-packed')
1004 %pr::win = ( # tweak window positions and/or sizes
1009 'int,0,3000', # 0 pixels - 3000 pixels
1018 'int,0,3000', # 0 pixels - 3000 pixels
1027 'int,0,3000', # 0 pixels - 3000 pixels
1036 'int,0,3000', # 0 pixels - 3000 pixels
1042 'mainwin_maximised',
1043 $xl::s{l_win_main_mx},
1044 $xl::s{h_win_main_mx},
1051 'mainwin_fullscreen',
1052 $xl::s{l_win_main_fs},
1053 $xl::s{h_win_main_fs},
1060 'main_messagewin_x',
1063 'int,0,3000', # 0 pixels - 3000 pixels
1069 'main_messagewin_y',
1072 'int,0,3000', # 0 pixels - 3000 pixels
1081 'int,0,3000', # 0 pixels - 3000 pixels
1087 'messagewin_height',
1090 'int,0,3000', # 0 pixels - 3000 pixels
1099 'int,0,3000', # 0 pixels - 3000 pixels
1108 'int,0,3000', # 0 pixels - 3000 pixels
1117 'int,0,3000', # 0 pixels - 3000 pixels
1123 'receivewin_height',
1126 'int,0,3000', # 0 pixels - 3000 pixels
1135 'int,0,3000', # 0 pixels - 3000 pixels
1144 'int,0,3000', # 0 pixels - 3000 pixels
1150 'folderitemwin_width',
1153 'int,0,3000', # 0 pixels - 3000 pixels
1159 'folderitemwin_height',
1162 'int,0,3000', # 0 pixels - 3000 pixels
1168 'folderselwin_width',
1171 'int,0,3000', # 0 pixels - 3000 pixels
1177 'folderselwin_height',
1180 'int,0,3000', # 0 pixels - 3000 pixels
1189 'int,0,3000', # 0 pixels - 3000 pixels
1198 'int,0,3000', # 0 pixels - 3000 pixels
1204 'addressbookwin_width',
1207 'int,0,3000', # 0 pixels - 3000 pixels
1213 'addressbookwin_height',
1216 'int,0,3000', # 0 pixels - 3000 pixels
1222 'addressbookeditpersonwin_width',
1225 'int,0,3000', # 0 pixels - 3000 pixels
1231 'addressbookeditpersonwin_height',
1234 'int,0,3000', # 0 pixels - 3000 pixels
1240 'addressbookeditgroupwin_width',
1243 'int,0,3000', # 0 pixels - 3000 pixels
1249 'addressbookeditgroupwin_height',
1252 'int,0,3000', # 0 pixels - 3000 pixels
1258 'addressaddwin_width',
1261 'int,0,3000', # 0 pixels - 3000 pixels
1267 'addressaddwin_height',
1270 'int,0,3000', # 0 pixels - 3000 pixels
1276 'addressbook_folderselwin_width',
1279 'int,0,3000', # 0 pixels - 3000 pixels
1285 'addressbook_folderselwin_height',
1288 'int,0,3000', # 0 pixels - 3000 pixels
1294 'editaccountwin_width',
1297 'int,0,3000', # 0 pixels - 3000 pixels
1303 'editaccountwin_height',
1306 'int,0,3000', # 0 pixels - 3000 pixels
1312 'accountswin_width',
1315 'int,0,3000', # 0 pixels - 3000 pixels
1321 'accountswin_height',
1324 'int,0,3000', # 0 pixels - 3000 pixels
1330 'filteringwin_width',
1333 'int,0,3000', # 0 pixels - 3000 pixels
1339 'filteringwin_height',
1342 'int,0,3000', # 0 pixels - 3000 pixels
1348 'filteringactionwin_width',
1351 'int,0,3000', # 0 pixels - 3000 pixels
1357 'filteringactionwin_height',
1360 'int,0,3000', # 0 pixels - 3000 pixels
1366 'filtering_debugwin_width',
1369 'int,0,3000', # 0 pixels - 3000 pixels
1375 'filtering_debugwin_height',
1378 'int,0,3000', # 0 pixels - 3000 pixels
1387 'int,0,3000', # 0 pixels - 3000 pixels
1393 'matcherwin_height',
1396 'int,0,3000', # 0 pixels - 3000 pixels
1405 'int,0,3000', # 0 pixels - 3000 pixels
1414 'int,0,3000', # 0 pixels - 3000 pixels
1420 'templateswin_width',
1423 'int,0,3000', # 0 pixels - 3000 pixels
1429 'templateswin_height',
1432 'int,0,3000', # 0 pixels - 3000 pixels
1441 'int,0,3000', # 0 pixels - 3000 pixels
1447 'actionswin_height',
1450 'int,0,3000', # 0 pixels - 3000 pixels
1459 'int,0,3000', # 0 pixels - 3000 pixels
1468 'int,0,3000', # 0 pixels - 3000 pixels
1477 'int,0,3000', # 0 pixels - 3000 pixels
1483 'pluginswin_height',
1486 'int,0,3000', # 0 pixels - 3000 pixels
1495 'int,0,3000', # 0 pixels - 3000 pixels
1504 'int,0,3000', # 0 pixels - 3000 pixels
1510 'print_previewwin_width',
1513 'int,0,3000', # 0 pixels - 3000 pixels
1519 'print_previewwin_height',
1522 'int,0,3000', # 0 pixels - 3000 pixels
1529 sub new_winpos_subpage_main() {
1530 return &new_subpage_frame (
1532 &new_text_box_for_int (\%pr::win, 'main_x'),
1533 &new_text_box_for_int (\%pr::win, 'main_y'),
1534 &new_text_box_for_int (\%pr::win, 'main_w'),
1535 &new_text_box_for_int (\%pr::win, 'main_h'),
1537 &new_check_button_for (\%pr::win, 'main_fs'),
1538 &new_check_button_for (\%pr::win, 'main_mx'))),
1543 sub new_winpos_subpage_msgs() {
1544 return &new_subpage_frame (
1546 &new_text_box_for_int (\%pr::win, 'msgs_x'),
1547 &new_text_box_for_int (\%pr::win, 'msgs_y'),
1548 &new_text_box_for_int (\%pr::win, 'msgs_w'),
1549 &new_text_box_for_int (\%pr::win, 'msgs_h')),
1554 sub new_winpos_subpage_sendrecv() {
1555 return &new_vbox_pack (
1556 &new_subpage_frame (
1559 &new_text_box_for_int (\%pr::win, 'send_w'),
1560 &new_text_box_for_int (\%pr::win, 'send_h'))),
1561 _('Send window'), 'not-packed'),
1562 &new_subpage_frame (
1565 &new_text_box_for_int (\%pr::win, 'recv_w'),
1566 &new_text_box_for_int (\%pr::win, 'recv_h'))),
1567 _('Receive window'), 'not-packed')
1571 sub new_winpos_subpage_fold() {
1572 return &new_vbox_pack (
1573 &new_subpage_frame (
1575 &new_text_box_for_int (\%pr::win, 'fold_x'),
1576 &new_text_box_for_int (\%pr::win, 'fold_y'),
1577 &new_text_box_for_int (\%pr::win, 'fold_w'),
1578 &new_text_box_for_int (\%pr::win, 'fold_h')),
1579 _('Folder window'), 'not-packed'),
1580 &new_subpage_frame (
1582 &new_text_box_for_int (\%pr::win, 'fsel_w'),
1583 &new_text_box_for_int (\%pr::win, 'fsel_h')),
1584 _('Folder selection window'), 'not-packed')
1588 sub new_winpos_subpage_sour() {
1589 return &new_subpage_frame (
1591 &new_text_box_for_int (\%pr::win, 'sour_w'),
1592 &new_text_box_for_int (\%pr::win, 'sour_h')),
1593 _('View source window')
1597 sub new_winpos_subpage_addrbook() {
1598 return &new_vbox_pack (
1599 &new_subpage_frame (
1602 &new_text_box_for_int (\%pr::win, 'addr_w'),
1603 &new_text_box_for_int (\%pr::win, 'addr_h'))),
1604 _('Addressbook main window'), 'not-packed'),
1605 &new_subpage_frame (
1608 &new_text_box_for_int (\%pr::win, 'adep_w'),
1609 &new_text_box_for_int (\%pr::win, 'adep_h'))),
1610 _('Edit person window'), 'not-packed'),
1611 &new_subpage_frame (
1614 &new_text_box_for_int (\%pr::win, 'adeg_w'),
1615 &new_text_box_for_int (\%pr::win, 'adeg_h'))),
1616 _('Edit group window'), 'not-packed'),
1617 &new_subpage_frame (
1620 &new_text_box_for_int (\%pr::win, 'adda_w'),
1621 &new_text_box_for_int (\%pr::win, 'adda_h'))),
1622 _('Add address window'), 'not-packed'),
1623 &new_subpage_frame (
1626 &new_text_box_for_int (\%pr::win, 'addf_w'),
1627 &new_text_box_for_int (\%pr::win, 'addf_h'))),
1628 _('Folder select window'), 'not-packed')
1632 sub new_winpos_subpage_accounts() {
1633 return &new_vbox_pack (
1634 &new_subpage_frame (
1637 &new_text_box_for_int (\%pr::win, 'acco_w'),
1638 &new_text_box_for_int (\%pr::win, 'acco_h'))),
1639 _('Accounts window'), 'not-packed'),
1640 &new_subpage_frame (
1643 &new_text_box_for_int (\%pr::win, 'acce_w'),
1644 &new_text_box_for_int (\%pr::win, 'acce_h'))),
1645 _('Edit account window'), 'not-packed')
1649 sub new_winpos_subpage_filtering() {
1650 return &new_vbox_pack (
1651 &new_subpage_frame (
1654 &new_text_box_for_int (\%pr::win, 'filt_w'),
1655 &new_text_box_for_int (\%pr::win, 'filt_h'))),
1656 _('Filtering window'), 'not-packed'),
1657 &new_subpage_frame (
1660 &new_text_box_for_int (\%pr::win, 'fila_w'),
1661 &new_text_box_for_int (\%pr::win, 'fila_h'))),
1662 _('Filtering actions window'), 'not-packed'),
1663 &new_subpage_frame (
1666 &new_text_box_for_int (\%pr::win, 'fild_w'),
1667 &new_text_box_for_int (\%pr::win, 'fild_h'))),
1668 _('Filtering debug window'), 'not-packed'),
1669 &new_subpage_frame (
1672 &new_text_box_for_int (\%pr::win, 'matc_w'),
1673 &new_text_box_for_int (\%pr::win, 'matc_h'))),
1674 _('Matcher window'), 'not-packed')
1678 sub new_winpos_subpage_prefs() {
1679 return &new_vbox_pack (
1680 &new_subpage_frame (
1683 &new_text_box_for_int (\%pr::win, 'pref_w'),
1684 &new_text_box_for_int (\%pr::win, 'pref_h'))),
1685 _('Preferences window'), 'not-packed'),
1686 &new_subpage_frame (
1689 &new_text_box_for_int (\%pr::win, 'temp_w'),
1690 &new_text_box_for_int (\%pr::win, 'temp_h'))),
1691 _('Templates window'), 'not-packed'),
1692 &new_subpage_frame (
1695 &new_text_box_for_int (\%pr::win, 'acti_w'),
1696 &new_text_box_for_int (\%pr::win, 'acti_h'))),
1697 _('Actions window'), 'not-packed'),
1698 &new_subpage_frame (
1701 &new_text_box_for_int (\%pr::win, 'tags_w'),
1702 &new_text_box_for_int (\%pr::win, 'tags_h'))),
1703 _('Tags window'), 'not-packed'),
1704 &new_subpage_frame (
1707 &new_text_box_for_int (\%pr::win, 'plug_w'),
1708 &new_text_box_for_int (\%pr::win, 'plug_h'))),
1709 _('Plugins window'), 'not-packed')
1713 sub new_winpos_subpage_misc() {
1714 return &new_vbox_pack (
1715 &new_subpage_frame (
1718 &new_text_box_for_int (\%pr::win, 'logw_w'),
1719 &new_text_box_for_int (\%pr::win, 'logw_h'))),
1720 _('Log window'), 'not-packed'),
1721 &new_subpage_frame (
1724 &new_text_box_for_int (\%pr::win, 'prin_w'),
1725 &new_text_box_for_int (\%pr::win, 'prin_h'))),
1726 _('Print preview window'), 'not-packed')
1730 sub new_winpos_page() {
1731 my $winbook = Gtk2::Notebook->new;
1732 $winbook->set_tab_pos ('right');
1733 $winbook->append_page (&new_winpos_subpage_main, _('Main'));
1734 $winbook->append_page (&new_winpos_subpage_msgs, _('Message'));
1735 $winbook->append_page (&new_winpos_subpage_sendrecv, _('Send/Receive'));
1736 $winbook->append_page (&new_winpos_subpage_fold, _('Folder'));
1737 $winbook->append_page (&new_winpos_subpage_sour, _('View source'));
1738 $winbook->append_page (&new_winpos_subpage_addrbook, _('Addressbook'));
1739 $winbook->append_page (&new_winpos_subpage_accounts, _('Accounts'));
1740 $winbook->append_page (&new_winpos_subpage_filtering, _('Filtering'));
1741 $winbook->append_page (&new_winpos_subpage_prefs, _('Preferences'));
1742 $winbook->append_page (&new_winpos_subpage_misc, _('Other'));
1747 sub print_version() {
1748 print $xl::s{about_title} . "\n";
1749 print $xl::s{about_version} . " $VERSION\n";
1750 print "Perl-GLib " . $Glib::VERSION;
1751 # version info stuff appeared in 1.040
1752 if ($Glib::VERSION >= 1.040) {
1753 print _(", built for ") . join(".", Glib->GET_VERSION_INFO)
1754 . _(", running with ") . join(".", &Glib::major_version,
1755 &Glib::minor_version, &Glib::micro_version);
1758 print "Perl-GTK2 " . $Gtk2::VERSION;
1759 if ($Gtk2::VERSION >= 1.040) {
1760 print _(", built for ") . join(".", Gtk2->GET_VERSION_INFO)
1761 . _(", running with ") . join(".", &Gtk2::major_version,
1762 &Gtk2::minor_version, &Gtk2::micro_version);
1765 my $clawsver = ($CLAWSV eq "") ?
1766 _("was not found!") :
1767 (_("returned version ") . $CLAWSV);
1768 print "Claws Mail " . $clawsver . "\n";
1771 # the command line help
1773 my $line = '-' x length ($xl::s{about_title}) . "\n";
1775 print $xl::s{about_title} . "\n";
1777 print _("Syntax:\n");
1778 print _(" clawsker [options]\n");
1779 print _("Options:\n");
1780 print _(" --help Prints this help screen.\n");
1781 print _(" --version Prints version infos.\n");
1782 print _(" --verbose More messages on standard output.\n");
1783 print _(" --alternate-config-dir <dir> Uses <dir> as Claws Mail config dir.\n");
1784 print _(" --clawsrc <file> Uses <file> as full resource name.\n");
1787 # handle errors which don't allow to run
1788 sub command_line_fatal() {
1790 my $emsg = $xl::s{e_error} . $reason;
1791 error_dialog ($emsg);
1792 log_message ("$emsg", 'die');
1795 # parse the command line
1796 sub parse_command_line() {
1797 $CLAWSV = &get_claws_version;
1799 while (defined($ARGV[$arg])) {
1813 /--use-claws-version/ && do {
1815 &command_line_fatal ("required version")
1816 unless defined($ARGV[$arg]);
1817 &command_line_fatal ("required a dotted numeric value")
1818 unless ($ARGV[$arg] =~ /[\d\.]+/);
1819 $CLAWSV = $ARGV[$arg];
1822 /--alternate-config-dir/ && do {
1824 &command_line_fatal ($xl::s{e_requireddir})
1825 unless defined($ARGV[$arg]);
1826 &command_line_fatal ($xl::s{e_notadir})
1827 unless -d $ARGV[$arg];
1828 $CONFIGDIR = $ARGV[$arg];
1830 unless ($CONFIGDIR =~ /.*\/$/);
1831 $ALTCONFIGDIR = TRUE;
1836 &command_line_fatal($xl::s{e_requiredfile})
1837 unless defined($ARGV[$arg]);
1838 &command_line_fatal($xl::s{e_notafile})
1839 unless -f $ARGV[$arg];
1840 &set_rc_filename ($ARGV[$arg]);
1843 /.*/ && &command_line_fatal (
1844 _("unknown option '{opt}'.\n", opt => $ARGV[$arg]));
1848 # eveything continues...
1852 # update the hidden preferences status from loaded values
1853 sub init_hidden_preferences() {
1854 foreach my $hash (\%pr::beh, \%pr::col, \%pr::gui, \%pr::oth, \%pr::win) {
1855 foreach my $key (keys %$hash) {
1856 $HPVALUE{${$hash}{$key}[NAME]} = $PREFS{${$hash}{$key}[NAME]};
1862 # load current status from disc
1863 sub load_preferences() {
1864 my $rc = &get_rc_filename;
1865 &log_message ("Loading preferences from $rc\n");
1866 return FALSE unless &check_rc_file ($rc);
1867 return FALSE unless &check_claws_not_running;
1871 if (/^([8a-z_]+)=(.*)$/) {
1879 # save current preferences to disc
1880 sub save_preferences() {
1881 my $rc = &get_rc_filename;
1882 &log_message ("Saving preferences to $rc\n");
1883 return FALSE unless &check_rc_file ($rc);
1884 return FALSE unless &check_claws_not_running;
1885 my $rcbak = "$rc.backup";
1886 rename ($rc, $rcbak);
1888 open (RCB, "<$rcbak");
1891 if (/^([8a-z_]+)=(.*)$/) {
1892 if (defined($HPVALUE{$1})) {
1893 print RCF $1 . "=" . $HPVALUE{$1} . "\n";
1896 print RCF $_ . "\n";
1900 print RCF $_ . "\n";
1909 sub new_notebook() {
1910 my $nb = Gtk2::Notebook->new;
1912 $nb->append_page (&new_behaviour_page, $xl::s{tab_behaviour});
1913 $nb->append_page (&new_colours_page, $xl::s{tab_colours});
1914 $nb->append_page (&new_gui_page, $xl::s{tab_gui});
1915 $nb->append_page (&new_other_page, $xl::s{tab_other});
1916 $nb->append_page (&new_winpos_page, $xl::s{tab_winpos});
1921 # create an about dialog
1922 sub new_about_dialog() {
1924 my $title = $xl::s{about_title};
1925 my $lic = $xl::s{about_license};
1926 my $vers = $xl::s{about_version} . " $VERSION";
1928 "This program is free software: you can redistribute it and/or modify
1929 it under the terms of the GNU General Public License as published by
1930 the Free Software Foundation, either version 3 of the License, or
1931 (at your option) any later version.
1933 This program is distributed in the hope that it will be useful,
1934 but WITHOUT ANY WARRANTY; without even the implied warranty of
1935 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1936 GNU General Public License for more details.
1938 You should have received a copy of the GNU General Public License
1939 along with this program. If not, see <http://www.gnu.org/licenses/>.";
1940 my $year = "2007-2009";
1941 my $holder = "Ricardo Mones <ricardo\@mones.org>";
1942 my $url = "http://www.claws-mail.org/clawsker";
1944 my $dialog = Gtk2::MessageDialog->new_with_markup ($parent,
1945 [qw/modal destroy-with-parent/],
1947 "<span size=\"x-large\" weight=\"bold\">$title</span>\n"
1948 . "<span size=\"large\">$vers</span>\n\n"
1949 . "<span color=\"blue\" size=\"large\">$url</span>\n\n"
1950 . "<span>Copyright $year by $holder</span>\n\n"
1951 . "<span size=\"large\">$lic</span>\n\n"
1952 . "<span size=\"small\">$license</span>");
1953 $dialog->set_title ($xl::s{about});
1958 # create buttons box
1959 sub new_button_box() {
1960 my ($parent, $adlg) = @_;
1961 my $b_about = Gtk2::Button->new_from_stock ('gtk-about');
1962 my $b_exit = Gtk2::Button->new_from_stock ('gtk-quit');
1963 my $b_apply = Gtk2::Button->new_from_stock ('gtk-apply');
1964 # disable button until is really implemented
1965 # my $b_undo = Gtk2::Button->new_from_stock ('gtk-undo');
1966 my $hbox = Gtk2::HBox->new (FALSE, 5);
1968 $b_exit->signal_connect (clicked => sub { Gtk2->main_quit });
1969 $b_apply->signal_connect (clicked => sub { &save_preferences ($parent) });
1970 # $b_undo->signal_connect (clicked => sub { &undo_current_changes });
1971 $b_about->signal_connect (clicked => sub { $adlg->run; $adlg->hide });
1973 $hbox->pack_end ($b_apply, FALSE, FALSE, 0);
1974 $hbox->pack_end ($b_exit, FALSE, FALSE, 0);
1975 # $hbox->pack_end ($b_undo, FALSE, FALSE, 0);
1976 $hbox->pack_start ($b_about, FALSE, FALSE, 0);
1982 $main_window = Gtk2::Window->new ('toplevel');
1983 exit unless &parse_command_line;
1984 exit unless &load_preferences;
1985 exit unless &init_hidden_preferences;
1987 my $box = Gtk2::VBox->new (FALSE, 5);
1988 $box->set_border_width(3);
1989 my $about = &new_about_dialog;
1990 $box->pack_start (&new_notebook, FALSE, FALSE, 0);
1991 $box->pack_end (&new_button_box ($main_window, $about), FALSE, FALSE, 0);
1992 $main_window->signal_connect (delete_event => sub { Gtk2->main_quit });
1993 $main_window->set_title ($xl::s{win_title});
1994 $main_window->add ($box);
1995 $main_window->show_all;