3 # Clawsker :: A Claws Mail Tweaker
8 use Glib qw(TRUE FALSE);
10 use POSIX qw(setlocale);
13 my $NAME = 'clawsker';
14 my $PREFIX = '@PREFIX@';
15 my $LIBDIR = '@LIBDIR@';
16 my $VERSION = '@VERSION@';
19 my $main_window = undef;
21 my $locale = (defined($ENV{LC_MESSAGES}) ? $ENV{LC_MESSAGES} : $ENV{LANG});
22 $locale = "C" unless defined($locale);
23 setlocale (LC_ALL, $locale);
24 bindtextdomain ($NAME, sprintf ('%s/share/locale', $PREFIX));
27 my $SHOWHINTS = FALSE;
28 $SHOWHINTS = TRUE if ($Gtk2::VERSION >= 1.040 and Gtk2->CHECK_VERSION (2, 12, 0));
33 my $xla = gettext ($str);
34 if (scalar(keys(%par)) > 0) {
35 foreach my $key (keys %par) {
36 $xla =~ s/\{$key\}/$par{$key}/g;
44 win_title => _('Claws Mail Hidden Preferences'),
45 about => _('About...'),
46 about_title => _('Clawsker :: A Claws Mail Tweaker'),
47 about_license => _('License:'),
48 about_version => _('Version:'),
50 tab_colours => _('Colours'),
51 tab_behaviour => _('Behaviour'),
53 tab_other => _('Other'),
54 tab_winpos => _('Windows'),
56 ab_frame => _('Addressbook'),
57 mem_frame => _('Memory'),
58 msgview_frame => _('Message View'),
59 log_frame => _('Log window'),
60 dnd_frame => _('Drag \'n\' drop'),
61 ssl_frame => _('Secure Sockets Layer'),
62 msgs_frame => _('Messages'),
63 stripes_frame => _('Coloured stripes'),
64 sbar_frame => _('Scroll bars'),
65 mlist_frame => _('Message List'),
66 mview_frame => _('Message View'),
67 compo_frame => _('Compose window'),
68 netm_frame => _('NetworkManager'),
70 l_oth_use_dlg => _('Use detached address book edit dialogue'),
71 h_oth_use_dlg => _('If true use a separate dialogue to edit a person\'s details. Otherwise will use a form embedded in the address book\'s main window.'),
72 l_oth_max_use => _('Maximum memory for message cache (kB)'),
73 h_oth_max_use => _('The maximum amount of memory to use to cache messages, in kilobytes.'),
74 l_oth_min_time => _('Minimun time for cache elements (minutes)'),
75 h_oth_min_time => _('The minimum time in minutes to keep a cache in memory. Caches more recent than this time will not be freed, even if the memory usage is too high.'),
76 l_oth_use_netm => _('Use NetworkManager'),
77 h_oth_use_netm => _('Use NetworkManager to switch offline automatically.'),
79 l_gui_b_unread => _('Show unread messages with bold font'),
80 h_gui_b_unread => _('Show unread messages in the Message List using a bold font.'),
81 l_gui_no_markup => _('Don\'t use markup in compose window'),
82 h_gui_no_markup => _('Don\'t use bold and italic text in Compose dialogue\'s account selector.'),
83 l_gui_dot_lines => _('Use dotted lines in tree view components'),
84 h_gui_dot_lines => _('Use the old dotted line look in the main window tree views (Folder, Message and other lists) instead of the modern lineless look.'),
85 l_gui_h_scroll => _('Enable horizontal scrollbar'),
86 h_gui_h_scroll => _('Enable the horizontal scrollbar in the Message List.'),
87 l_gui_swp_from => _('Display To column instead From column in Sent folder'),
88 h_gui_swp_from => _('Display the recipient\'s email address in a To column of the Sent folder instead of the originator\'s one in a From column.'),
89 l_gui_v_scroll => _('Folder List scrollbar behaviour'),
90 h_gui_v_scroll => _('Specify the policy of vertical scrollbar of Folder List: show always, automatic or hide always.'),
91 l_gui_v_scroll_show => _('Show always'),
92 l_gui_v_scroll_auto => _('Automatic'),
93 l_gui_v_scroll_hide => _('Hide always'),
94 l_gui_strip_off => _('Coloured lines contrast'),
95 h_gui_strip_off => _('Specify the value to use when creating alternately coloured lines in tree view components. The smaller the value, the less visible the difference in the alternating colours of the lines.'),
96 l_gui_cursor_v => _('Show cursor in message view'),
97 h_gui_cursor_v => _('Display the cursor in the Message View.'),
98 l_gui_toolbar_d => _('Detachable toolbars'),
99 h_gui_toolbar_d => _('Show handles in the toolbars.'),
100 l_gui_strip_all => _('Use stripes in all tree view components'),
101 h_gui_strip_all => _('Enable alternately coloured lines in all tree view components.'),
102 l_gui_strip_sum => _('Use stripes in Folder List and Message List'),
103 h_gui_strip_sum => _('Enable alternately coloured lines in Message List and Folder List.'),
104 l_gui_two_line_v => _('2 lines per Message List item in 3-column layout'),
105 h_gui_two_line_v => _('Spread Message List information over two lines when using the three column mode.'),
106 l_gui_margin_co => _('Show compose margin'),
107 h_gui_margin_co => _('Shows a small margin in the Compose View.'),
108 l_gui_mview_date => _('Don\'t display localized date in Message View'),
109 h_gui_mview_date => _('Toggles localization of date format in Message View'),
111 l_beh_hover_t => _('Drag \'n\' drop hover timeout (ms)'),
112 h_beh_hover_t => _('Time in milliseconds that will cause a folder tree to expand when the mouse cursor is held over it during drag and drop.'),
113 l_beh_dangerous => _('Don\'t confirm deletions (dangerous!)'),
114 h_beh_dangerous => _('Don\'t ask for confirmation before definitive deletion of emails.'),
115 l_beh_flowed => _('Respect format=flowed in messages'),
116 h_beh_flowed => _('Respect format=flowed on text/plain message parts. This will cause some mails to have long lines, but will fix some URLs that would otherwise be wrapped.'),
117 l_beh_parts_rw => _('Allow writable temporary files'),
118 h_beh_parts_rw => _('Saves temporary files when opening attachment with write bit set.'),
119 l_beh_skip_ssl => _('Don\'t check SSL certificates'),
120 h_beh_skip_ssl => _('Disables the verification of SSL certificates.'),
121 l_beh_up_step => _('Progress bar update step (items)'),
122 h_beh_up_step => _('Update stepping in progress bars.'),
123 l_beh_thread_a => _('Maximum age when threading by subject (days)'),
124 h_beh_thread_a => _('Number of days to include a message in a thread when using "Thread using subject in addition to standard headers".'),
125 l_beh_unsafe_ssl => _('Allow unsafe SSL certificates'),
126 h_beh_unsafe_ssl => _('Allows Claws Mail to remember multiple SSL certificates for a given server/port.'),
127 l_beh_use_utf8 => _('Force UTF-8 for broken mails'),
128 h_beh_use_utf8 => _('Use UTF-8 encoding for broken mails instead of current locale.'),
129 l_beh_warn_dnd => _('Warn on drag \'n\' drop'),
130 h_beh_warn_dnd => _('Display a confirmation dialogue on drag \'n\' drop of folders.'),
131 l_beh_out_ascii => _('Outgoing messages fallback to ASCII'),
132 h_beh_out_ascii => _('If content allows, ASCII will be used to encode outgoing messages, otherwise the user-defined encoding is enforced always.'),
133 l_beh_pp_unsel => _('Primary paste unselects selection'),
134 h_beh_pp_unsel => _('Controls how pasting using middle-click changes the selected text and insertion point.'),
135 l_beh_inline_at => _('Show inline attachments'),
136 h_beh_inline_at => _('Allows hiding inline attachments already shown in mail structure view'),
138 l_col_emphasis => _('X-Mailer header'),
139 h_col_emphasis => _('The colour used for the X-Mailer line when its value is Claws Mail.'),
140 l_col_log_err => _('Error messages'),
141 h_col_log_err => _('Colour for error messages in log window.'),
142 l_col_log_in => _('Server messages'),
143 h_col_log_in => _('Colour for messages received from servers in log window.'),
144 l_col_log_msg => _('Standard messages'),
145 h_col_log_msg => _('Colour for messages in log window.'),
146 l_col_log_out => _('Client messages'),
147 h_col_log_out => _('Colour for messages sent to servers in log window.'),
148 l_col_log_warn => _('Warnings'),
149 h_col_log_warn => _('Colour for warning messages in log window.'),
151 l_win_x => _('X position'),
152 h_win_x => _('X coordinate for window\'s top-left corner.'),
153 l_win_y => _('Y position'),
154 h_win_y => _('Y coordinate for window\'s top-left corner.'),
155 l_win_w => _('Width'),
156 h_win_w => _('Window\'s width in pixels.'),
157 l_win_h => _('Height'),
158 h_win_h => _('Window\'s height in pixels.'),
160 l_win_main_mx => _('Maximized'),
161 h_win_main_mx => _('Changes window maximized status.'),
162 l_win_main_fs => _('Full-screen'),
163 h_win_main_fs => _('Changes full screen status.'),
165 e_error => _('Error: '),
166 e_noclawsrc => _('resource file for Claws Mail was not found.'),
167 e_running => _('seems Claws Mail is currently running, close it first.'),
168 e_requireddir => _('option requires a directory name.'),
169 e_requiredfile => _('option requires a file name.'),
170 e_notadir => _('specified name is not a directory or does not exist.'),
171 e_notafile => _('specified name is not a file or does not exist.'),
174 # all preferences read by load_preferences
176 # values of all preferences handled by clawsker
178 # default config dir and file name
179 my $ALTCONFIGDIR = FALSE;
180 my $CONFIGDIR = $ENV{HOME} . '/.claws-mail/';
181 my $CONFIGRC = 'clawsrc';
183 # index constants for preference arrays
184 use constant NAME => 0; # the name on the rc file
185 use constant LABEL => 1; # the label on the GUI
186 use constant DESC => 2; # the description for the hint/help
187 use constant TYPE => 3; # data type: bool, int, float, string, color
188 use constant CMVER => 4; # lowest Claws Mail version the feature exists
189 use constant CMDEF => 5; # default value for the preference in Claws Mail
190 use constant GUI => 6; # GUI element
192 # constants for GUI spacing
193 use constant HBOX_SPC => 5;
194 use constant FRAME_SPC => 2;
195 use constant PAGE_SPC => 5;
199 sub version_greater_or_equal() {
200 my ($version, $refvers) = @_;
201 my @version = split (/\./, $version);
202 my @refvers = split (/\./, $refvers);
203 while ($#version < $#refvers) {
204 push (@version, '0');
207 while (($idx <= $#refvers)
208 and (int ($version[$idx]) == int ($refvers[$idx]))) {
211 return TRUE if (($idx > $#refvers)
212 or (int ($version[$idx]) >= int ($refvers[$idx])));
216 sub get_claws_version() {
221 foreach my $bin (@cmbin) {
226 return "" unless ($_); # not installed
229 my @fver = split (/ /);
230 die "Invalid version string" unless ($fver[2] eq "version");
231 my @ver = split (/\./, $fver[3]);
234 if ($ver[2] =~ /(\d+)cvs(\d+)/) {
243 # data handlers and auxiliar functions
245 sub handle_bool_value {
246 my ($widget, $event, $dataref) = @_;
247 $$dataref = ($widget->get_active ())? '1': '0';
250 sub handle_int_value {
251 my ($widget, $event, $dataref) = @_;
252 $_ = $widget->get_text ();
257 $widget->set_text ($_);
260 $widget->set_text ($$dataref);
264 sub handle_string_value {
265 my ($widget, $event, $dataref) = @_;
266 $$dataref = $widget->get_text ();
269 sub gdk_color_from_str {
271 my ($rr, $gg, $bb) = (0, 0 ,0);
273 if (/\#([A-F0-9][A-F0-9])([A-F0-9][A-F0-9])([A-F0-9][A-F0-9])/) {
278 my $color = Gtk2::Gdk::Color->new ($rr, $gg, $bb);
282 sub str_from_gdk_color {
284 my $rr = $color->red / 256;
285 my $gg = $color->green / 256;
286 my $bb = $color->blue / 256;
287 my $str = sprintf ("#%.2x%.2x%.2x", $rr, $gg, $bb);
291 sub handle_color_value {
292 my ($widget, $event, $dataref) = @_;
293 my $newcol = $widget->get_color;
294 $$dataref = &str_from_gdk_color ($newcol);
297 sub handle_selection_value {
298 my ($widget, $event, $dataref) = @_;
299 $$dataref = $widget->get_active;
302 sub get_rc_filename {
303 return $CONFIGDIR . $CONFIGRC;
306 sub set_rc_filename {
308 my @parts = split ('/', $fullname);
309 $CONFIGRC = $parts[$#parts];
310 $parts[$#parts] = '';
311 $CONFIGDIR = join ('/', @parts);
315 my ($mesg, $fatal) = @_;
316 if (defined($fatal) && $fatal eq 'die') {
317 die "$NAME: $mesg\n";
320 print "$NAME: $mesg\n";
326 my $markup = "<span weight=\"bold\" size=\"large\">" . $emsg . "</span>";
327 my $errordlg = Gtk2::MessageDialog->new_with_markup ($main_window, 'modal', 'error', 'cancel', $markup);
328 $errordlg->set_title (_('Error message'));
333 sub check_claws_not_running() {
334 my $socket = (not $ALTCONFIGDIR)? "/tmp/": $CONFIGDIR;
335 $socket .= "claws-mail-$<";
337 my $emsg = "$xl::s{e_error}$xl::s{e_running}";
339 error_dialog ($emsg);
345 sub check_rc_file() {
347 (defined($rcfile) && -f $rcfile) or do {
348 my $emsg = "$xl::s{e_error}$xl::s{e_noclawsrc}\n";
350 error_dialog ($emsg);
356 sub set_widget_hint() {
358 my ($wdgt, $hint) = @_;
359 $wdgt->set_tooltip_text ($hint);
360 $wdgt->set_has_tooltip (TRUE);
364 sub set_widget_sens() {
365 my ($wdgt, $minver) = @_;
366 $wdgt->set_sensitive (&version_greater_or_equal ($CLAWSV, $minver));
369 # graphic element creation
371 sub new_check_button_for {
372 my ($hash, $key) = @_;
373 my $name = $$hash{$key}[NAME];
374 my $label = $$hash{$key}[LABEL];
376 my $hbox = Gtk2::HBox->new (FALSE, 5);
377 my $cb = Gtk2::CheckButton->new ($label);
378 $$hash{$key}[GUI] = $cb;
379 if (defined ($HPVALUE{$name})) {
380 $cb->set_active ($HPVALUE{$name} eq '1');
382 $cb->signal_connect (clicked => sub {
384 &handle_bool_value($w, $e, \$HPVALUE{$name});
386 &set_widget_hint ($cb, $$hash{$key}[DESC]);
387 &set_widget_sens ($cb, $$hash{$key}[CMVER]);
388 $hbox->pack_start ($cb, FALSE, FALSE, HBOX_SPC);
393 sub new_text_box_for_int {
394 my ($hash, $key) = @_;
395 my $name = $$hash{$key}[NAME];
396 my $label = $$hash{$key}[LABEL];
397 my @type = split (/,/, $$hash{$key}[TYPE]);
398 push (@type, 0), push (@type, 10000) unless ($#type > 0);
400 my $hbox = Gtk2::HBox->new (FALSE, 5);
401 my $glabel = Gtk2::Label->new ($label);
402 my $pagei = int (($type[2] - $type[1]) / 10);
403 my $gentry = Gtk2::SpinButton->new_with_range ($type[1], $type[2], $pagei);
404 $gentry->set_numeric (TRUE);
405 $$hash{$key}[GUI] = $gentry;
406 $gentry->signal_connect('value-changed' => sub {
408 &handle_int_value($w, $e, \$HPVALUE{$name});
410 &set_widget_hint ($gentry, $$hash{$key}[DESC]);
411 &set_widget_sens ($gentry, $$hash{$key}[CMVER]);
412 $glabel->set_sensitive ($gentry->sensitive);
413 $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
414 $hbox->pack_start ($gentry, FALSE, FALSE, HBOX_SPC);
419 sub new_color_button_for {
420 my ($hash, $key) = @_;
421 my $name = $$hash{$key}[NAME];
422 my $label = $$hash{$key}[LABEL];
424 my $col = &gdk_color_from_str ($HPVALUE{$name});
425 my $hbox = Gtk2::HBox->new (FALSE, 5);
426 my $glabel = Gtk2::Label->new ($label);
427 my $button = Gtk2::ColorButton->new_with_color ($col);
428 $$hash{$key}[GUI] = $button;
429 $button->set_title ($label);
430 $button->set_relief ('none');
431 $button->signal_connect ('color-set' => sub {
433 &handle_color_value($w, $e, \$HPVALUE{$name});
435 &set_widget_hint ($button, $$hash{$key}[DESC]);
436 &set_widget_sens ($button, $$hash{$key}[CMVER]);
437 $glabel->set_sensitive ($button->sensitive);
438 $hbox->pack_start ($button, FALSE, FALSE, HBOX_SPC);
439 $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
444 sub new_selection_box_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 $glabel = Gtk2::Label->new ($label);
451 my $combo = Gtk2::ComboBox->new_text;
452 $$hash{$key}[GUI] = $combo;
453 my @options = split (';', $$hash{$key}[TYPE]);
454 foreach my $opt (@options) {
455 my ($index, $textkey) = split ('=', $opt);
456 $combo->insert_text ($index, $xl::s{$textkey});
458 $combo->signal_connect ('changed' => sub {
460 &handle_selection_value($w, $e, \$HPVALUE{$name});
462 $combo->set_active ($HPVALUE{$name});
463 &set_widget_hint ($combo, $$hash{$key}[DESC]);
464 &set_widget_sens ($combo, $$hash{$key}[CMVER]);
465 $glabel->set_sensitive ($combo->sensitive);
466 $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
467 $hbox->pack_start ($combo, FALSE, FALSE, HBOX_SPC);
472 # more graphic helpers
474 sub new_hbox_pack() {
475 my $hbox = Gtk2::HBox->new (FALSE, 5);
476 $hbox->set_border_width (PAGE_SPC);
477 foreach my $item (@_) {
478 $hbox->pack_start ($item, FALSE, FALSE, 0);
483 sub new_vbox_pack() {
484 my $vbox = Gtk2::VBox->new (FALSE, 5);
485 $vbox->set_border_width (PAGE_SPC);
486 foreach my $item (@_) {
487 $vbox->pack_start ($item, FALSE, FALSE, 0);
492 sub new_vbox_pack_compact() {
493 my $vbox = Gtk2::VBox->new (FALSE, 0);
494 $vbox->set_border_width (0);
495 foreach my $item (@_) {
496 $vbox->pack_start ($item, FALSE, FALSE, 0);
501 sub new_subpage_frame () {
502 my ($box, $title, $notpacked) = @_;
503 my $frame = Gtk2::Frame->new ($title);
505 return &new_vbox_pack ($frame) unless defined ($notpacked);
509 # preference maps and corresponding page creation subs
511 %pr::oth = ( # other preferences
513 'addressbook_use_editaddress_dialog',
514 $xl::s{l_oth_use_dlg},
515 $xl::s{h_oth_use_dlg},
522 'cache_max_mem_usage',
523 $xl::s{l_oth_max_use},
524 $xl::s{h_oth_max_use},
525 'int,0,262144', # 0 Kb - 256 Mb
531 'cache_min_keep_time',
532 $xl::s{l_oth_min_time},
533 $xl::s{h_oth_min_time},
534 'int,0,120', # 0 minutes - 2 hours
540 'use_networkmanager',
541 $xl::s{l_oth_use_netm},
542 $xl::s{h_oth_use_netm},
550 sub new_other_page() {
551 return &new_vbox_pack (
554 &new_check_button_for(\%pr::oth, 'use_dlg')),
555 $xl::s{ab_frame}, 'not-packed'),
558 &new_text_box_for_int(\%pr::oth, 'max_use'),
559 &new_text_box_for_int(\%pr::oth, 'min_time')),
560 $xl::s{mem_frame}, 'not-packed'),
563 &new_check_button_for(\%pr::oth, 'use_netm')),
564 $xl::s{netm_frame}, 'not-packed')
568 %pr::gui = ( # gui bells and whistles
571 $xl::s{l_gui_b_unread},
572 $xl::s{h_gui_b_unread},
580 $xl::s{l_gui_no_markup},
581 $xl::s{h_gui_no_markup},
588 'enable_dotted_lines',
589 $xl::s{l_gui_dot_lines},
590 $xl::s{h_gui_dot_lines},
598 $xl::s{l_gui_h_scroll},
599 $xl::s{h_gui_h_scroll},
607 $xl::s{l_gui_swp_from},
608 $xl::s{h_gui_swp_from},
615 'folderview_vscrollbar_policy',
616 $xl::s{l_gui_v_scroll},
617 $xl::s{h_gui_v_scroll},
618 '0=l_gui_v_scroll_show;1=l_gui_v_scroll_auto;2=l_gui_v_scroll_hide',
624 'stripes_color_offset',
625 $xl::s{l_gui_strip_off},
626 $xl::s{h_gui_strip_off},
627 'int,0,10000', # no idea what this number means
633 'textview_cursor_visible',
634 $xl::s{l_gui_cursor_v},
635 $xl::s{h_gui_cursor_v},
642 'toolbar_detachable',
643 $xl::s{l_gui_toolbar_d},
644 $xl::s{h_gui_toolbar_d},
651 'use_stripes_everywhere',
652 $xl::s{l_gui_strip_all},
653 $xl::s{h_gui_strip_all},
660 'use_stripes_in_summaries',
661 $xl::s{l_gui_strip_sum},
662 $xl::s{h_gui_strip_sum},
670 $xl::s{l_gui_two_line_v},
671 $xl::s{h_gui_two_line_v},
678 'show_compose_margin',
679 $xl::s{l_gui_margin_co},
680 $xl::s{h_gui_margin_co},
687 'msgview_date_format',
688 $xl::s{l_gui_mview_date},
689 $xl::s{h_gui_mview_date},
698 my $gf = Gtk2::VBox->new (FALSE, 5);
699 $gf->set_border_width (PAGE_SPC);
701 my $cb_dot_lines = &new_check_button_for (\%pr::gui, 'dot_lines');
702 my $cb_toolbar_d = &new_check_button_for (\%pr::gui, 'toolbar_d');
704 $gf->pack_start (&new_subpage_frame (
706 &new_check_button_for (\%pr::gui, 'strip_all'),
707 &new_check_button_for (\%pr::gui, 'strip_sum'),
708 &new_text_box_for_int (\%pr::gui, 'strip_off')),
709 $xl::s{stripes_frame}, 'not-packed'),
710 FALSE, FALSE, FRAME_SPC);
711 $gf->pack_start (&new_subpage_frame (
713 &new_check_button_for (\%pr::gui, 'b_unread'),
714 &new_check_button_for (\%pr::gui, 'swp_from'),
715 &new_check_button_for (\%pr::gui, 'two_linev')),
716 $xl::s{mlist_frame}, 'not-packed'),
717 FALSE, FALSE, FRAME_SPC);
718 $gf->pack_start (&new_subpage_frame (
720 &new_check_button_for (\%pr::gui, 'cursor_v'),
721 &new_check_button_for (\%pr::gui, 'mview_date')),
722 $xl::s{mview_frame}, 'not-packed'),
723 FALSE, FALSE, FRAME_SPC);
724 $gf->pack_start (&new_subpage_frame (
726 &new_check_button_for (\%pr::gui, 'no_markup'),
727 &new_check_button_for (\%pr::gui, 'margin_co')),
728 $xl::s{compo_frame}, 'not-packed'),
729 FALSE, FALSE, FRAME_SPC);
730 $gf->pack_start ($cb_dot_lines, FALSE, FALSE, 0);
731 $gf->pack_start ($cb_toolbar_d, FALSE, FALSE, 0);
732 $gf->pack_start (&new_subpage_frame (
734 &new_check_button_for (\%pr::gui, 'h_scroll'),
735 &new_selection_box_for (\%pr::gui, 'v_scroll')),
736 $xl::s{sbar_frame}, 'not-packed'),
737 FALSE, FALSE, FRAME_SPC);
742 %pr::beh = ( # tweak some behaviour
745 $xl::s{l_beh_hover_t},
746 $xl::s{h_beh_hover_t},
747 'int,100,3000', # 0.1 seconds - 3 seconds
754 $xl::s{l_beh_dangerous},
755 $xl::s{h_beh_dangerous},
762 'respect_flowed_format',
763 $xl::s{l_beh_flowed},
764 $xl::s{h_beh_flowed},
771 'save_parts_readwrite',
772 $xl::s{l_beh_parts_rw},
773 $xl::s{h_beh_parts_rw},
780 'skip_ssl_cert_check',
781 $xl::s{l_beh_skip_ssl},
782 $xl::s{h_beh_skip_ssl},
789 'statusbar_update_step',
790 $xl::s{l_beh_up_step},
791 $xl::s{h_beh_up_step},
792 'int,1,200', # 1 item - 200 items
798 'thread_by_subject_max_age',
799 $xl::s{l_beh_thread_a},
800 $xl::s{h_beh_thread_a},
801 'int,1,30', # 1 day - 30 days
808 $xl::s{l_beh_unsafe_ssl},
809 $xl::s{h_beh_unsafe_ssl},
816 'utf8_instead_of_locale_for_broken_mail',
817 $xl::s{l_beh_use_utf8},
818 $xl::s{h_beh_use_utf8},
826 $xl::s{l_beh_warn_dnd},
827 $xl::s{h_beh_warn_dnd},
834 'outgoing_fallback_to_ascii',
835 $xl::s{l_beh_out_ascii},
836 $xl::s{h_beh_out_ascii},
843 'primary_paste_unselects',
844 $xl::s{l_beh_pp_unsel},
845 $xl::s{h_beh_pp_unsel},
852 'show_inline_attachments',
853 $xl::s{l_beh_inline_at},
854 $xl::s{h_beh_inline_at},
862 sub new_behaviour_page() {
863 my $bf = Gtk2::VBox->new (FALSE, 5);
864 $bf->set_border_width (PAGE_SPC);
866 my $tb_up_step = &new_text_box_for_int (\%pr::beh, 'up_step');
867 my $tb_thread_a = &new_text_box_for_int (\%pr::beh, 'thread_a');
869 $bf->pack_start (&new_subpage_frame (
871 &new_text_box_for_int (\%pr::beh, 'hover_t'),
872 &new_check_button_for (\%pr::beh, 'warn_dnd')),
873 $xl::s{dnd_frame}, 'not-packed'),
874 FALSE, FALSE, FRAME_SPC);
875 $bf->pack_start (&new_subpage_frame (
877 &new_check_button_for (\%pr::beh, 'skip_ssl'),
878 &new_check_button_for (\%pr::beh, 'unsafe_ssl')),
879 $xl::s{ssl_frame}, 'not-packed'),
880 FALSE, FALSE, FRAME_SPC);
881 $bf->pack_start ($tb_up_step, FALSE, FALSE, 0);
882 $bf->pack_start ($tb_thread_a, FALSE, FALSE, 0);
883 $bf->pack_start (&new_subpage_frame (
885 &new_check_button_for (\%pr::beh, 'flowed'),
886 &new_check_button_for (\%pr::beh, 'parts_rw'),
887 &new_check_button_for (\%pr::beh, 'use_utf8'),
888 &new_check_button_for (\%pr::beh, 'dangerous'),
889 &new_check_button_for (\%pr::beh, 'out_ascii'),
890 &new_check_button_for (\%pr::beh, 'pp_unsel'),
891 &new_check_button_for (\%pr::beh, 'inline_at')),
892 $xl::s{msgs_frame}, 'not-packed'),
893 FALSE, FALSE, FRAME_SPC);
898 %pr::col = ( # a variety of colours
901 $xl::s{l_col_emphasis},
902 $xl::s{h_col_emphasis},
910 $xl::s{l_col_log_err},
911 $xl::s{h_col_log_err},
919 $xl::s{l_col_log_in},
920 $xl::s{h_col_log_in},
928 $xl::s{l_col_log_msg},
929 $xl::s{h_col_log_msg},
937 $xl::s{l_col_log_out},
938 $xl::s{h_col_log_out},
946 $xl::s{l_col_log_warn},
947 $xl::s{h_col_log_warn},
955 sub new_colours_page() {
956 return &new_vbox_pack (
959 &new_color_button_for (\%pr::col, 'emphasis')),
960 $xl::s{msgview_frame}, 'not-packed'),
963 &new_color_button_for (\%pr::col, 'log_err'),
964 &new_color_button_for (\%pr::col, 'log_in'),
965 &new_color_button_for (\%pr::col, 'log_msg'),
966 &new_color_button_for (\%pr::col, 'log_out'),
967 &new_color_button_for (\%pr::col, 'log_warn')),
968 $xl::s{log_frame}, 'not-packed')
972 %pr::win = ( # tweak window positions and/or sizes
977 'int,0,3000', # 0 pixels - 3000 pixels
986 'int,0,3000', # 0 pixels - 3000 pixels
995 'int,0,3000', # 0 pixels - 3000 pixels
1004 'int,0,3000', # 0 pixels - 3000 pixels
1010 'mainwin_maximised',
1011 $xl::s{l_win_main_mx},
1012 $xl::s{h_win_main_mx},
1019 'mainwin_fullscreen',
1020 $xl::s{l_win_main_fs},
1021 $xl::s{h_win_main_fs},
1028 'main_messagewin_x',
1031 'int,0,3000', # 0 pixels - 3000 pixels
1037 'main_messagewin_y',
1040 'int,0,3000', # 0 pixels - 3000 pixels
1049 'int,0,3000', # 0 pixels - 3000 pixels
1055 'messagewin_height',
1058 'int,0,3000', # 0 pixels - 3000 pixels
1067 'int,0,3000', # 0 pixels - 3000 pixels
1076 'int,0,3000', # 0 pixels - 3000 pixels
1085 'int,0,3000', # 0 pixels - 3000 pixels
1091 'receivewin_height',
1094 'int,0,3000', # 0 pixels - 3000 pixels
1103 'int,0,3000', # 0 pixels - 3000 pixels
1112 'int,0,3000', # 0 pixels - 3000 pixels
1118 'folderitemwin_width',
1121 'int,0,3000', # 0 pixels - 3000 pixels
1127 'folderitemwin_height',
1130 'int,0,3000', # 0 pixels - 3000 pixels
1136 'folderselwin_width',
1139 'int,0,3000', # 0 pixels - 3000 pixels
1145 'folderselwin_height',
1148 'int,0,3000', # 0 pixels - 3000 pixels
1157 'int,0,3000', # 0 pixels - 3000 pixels
1166 'int,0,3000', # 0 pixels - 3000 pixels
1172 'addressbookwin_width',
1175 'int,0,3000', # 0 pixels - 3000 pixels
1181 'addressbookwin_height',
1184 'int,0,3000', # 0 pixels - 3000 pixels
1190 'addressbookeditpersonwin_width',
1193 'int,0,3000', # 0 pixels - 3000 pixels
1199 'addressbookeditpersonwin_height',
1202 'int,0,3000', # 0 pixels - 3000 pixels
1208 'addressbookeditgroupwin_width',
1211 'int,0,3000', # 0 pixels - 3000 pixels
1217 'addressbookeditgroupwin_height',
1220 'int,0,3000', # 0 pixels - 3000 pixels
1226 'addressaddwin_width',
1229 'int,0,3000', # 0 pixels - 3000 pixels
1235 'addressaddwin_height',
1238 'int,0,3000', # 0 pixels - 3000 pixels
1244 'addressbook_folderselwin_width',
1247 'int,0,3000', # 0 pixels - 3000 pixels
1253 'addressbook_folderselwin_height',
1256 'int,0,3000', # 0 pixels - 3000 pixels
1262 'editaccountwin_width',
1265 'int,0,3000', # 0 pixels - 3000 pixels
1271 'editaccountwin_height',
1274 'int,0,3000', # 0 pixels - 3000 pixels
1280 'accountswin_width',
1283 'int,0,3000', # 0 pixels - 3000 pixels
1289 'accountswin_height',
1292 'int,0,3000', # 0 pixels - 3000 pixels
1298 'filteringwin_width',
1301 'int,0,3000', # 0 pixels - 3000 pixels
1307 'filteringwin_height',
1310 'int,0,3000', # 0 pixels - 3000 pixels
1316 'filteringactionwin_width',
1319 'int,0,3000', # 0 pixels - 3000 pixels
1325 'filteringactionwin_height',
1328 'int,0,3000', # 0 pixels - 3000 pixels
1334 'filtering_debugwin_width',
1337 'int,0,3000', # 0 pixels - 3000 pixels
1343 'filtering_debugwin_height',
1346 'int,0,3000', # 0 pixels - 3000 pixels
1355 'int,0,3000', # 0 pixels - 3000 pixels
1361 'matcherwin_height',
1364 'int,0,3000', # 0 pixels - 3000 pixels
1373 'int,0,3000', # 0 pixels - 3000 pixels
1382 'int,0,3000', # 0 pixels - 3000 pixels
1388 'templateswin_width',
1391 'int,0,3000', # 0 pixels - 3000 pixels
1397 'templateswin_height',
1400 'int,0,3000', # 0 pixels - 3000 pixels
1409 'int,0,3000', # 0 pixels - 3000 pixels
1415 'actionswin_height',
1418 'int,0,3000', # 0 pixels - 3000 pixels
1427 'int,0,3000', # 0 pixels - 3000 pixels
1436 'int,0,3000', # 0 pixels - 3000 pixels
1445 'int,0,3000', # 0 pixels - 3000 pixels
1451 'pluginswin_height',
1454 'int,0,3000', # 0 pixels - 3000 pixels
1463 'int,0,3000', # 0 pixels - 3000 pixels
1472 'int,0,3000', # 0 pixels - 3000 pixels
1478 'print_previewwin_width',
1481 'int,0,3000', # 0 pixels - 3000 pixels
1487 'print_previewwin_height',
1490 'int,0,3000', # 0 pixels - 3000 pixels
1497 sub new_winpos_subpage_main() {
1498 return &new_subpage_frame (
1499 &new_vbox_pack_compact (
1501 &new_text_box_for_int (\%pr::win, 'main_x'),
1502 &new_text_box_for_int (\%pr::win, 'main_y')),
1504 &new_text_box_for_int (\%pr::win, 'main_w'),
1505 &new_text_box_for_int (\%pr::win, 'main_h')),
1507 &new_check_button_for (\%pr::win, 'main_fs'),
1508 &new_check_button_for (\%pr::win, 'main_mx'))),
1513 sub new_winpos_subpage_msgs() {
1514 return &new_subpage_frame (
1515 &new_vbox_pack_compact (
1517 &new_text_box_for_int (\%pr::win, 'msgs_x'),
1518 &new_text_box_for_int (\%pr::win, 'msgs_y')),
1520 &new_text_box_for_int (\%pr::win, 'msgs_w'),
1521 &new_text_box_for_int (\%pr::win, 'msgs_h'))),
1526 sub new_winpos_subpage_sendrecv() {
1527 return &new_vbox_pack (
1528 &new_subpage_frame (
1530 &new_text_box_for_int (\%pr::win, 'send_w'),
1531 &new_text_box_for_int (\%pr::win, 'send_h')),
1532 _('Send window'), 'not-packed'),
1533 &new_subpage_frame (
1535 &new_text_box_for_int (\%pr::win, 'recv_w'),
1536 &new_text_box_for_int (\%pr::win, 'recv_h')),
1537 _('Receive window'), 'not-packed')
1541 sub new_winpos_subpage_fold() {
1542 return &new_vbox_pack (
1543 &new_subpage_frame (
1544 &new_vbox_pack_compact (
1546 &new_text_box_for_int (\%pr::win, 'fold_x'),
1547 &new_text_box_for_int (\%pr::win, 'fold_y')),
1549 &new_text_box_for_int (\%pr::win, 'fold_w'),
1550 &new_text_box_for_int (\%pr::win, 'fold_h'))),
1551 _('Folder window'), 'not-packed'),
1552 &new_subpage_frame (
1554 &new_text_box_for_int (\%pr::win, 'fsel_w'),
1555 &new_text_box_for_int (\%pr::win, 'fsel_h')),
1556 _('Folder selection window'), 'not-packed')
1560 sub new_winpos_subpage_addrbook() {
1561 return &new_vbox_pack (
1562 &new_subpage_frame (
1564 &new_text_box_for_int (\%pr::win, 'addr_w'),
1565 &new_text_box_for_int (\%pr::win, 'addr_h')),
1566 _('Addressbook main window'), 'not-packed'),
1567 &new_subpage_frame (
1569 &new_text_box_for_int (\%pr::win, 'adep_w'),
1570 &new_text_box_for_int (\%pr::win, 'adep_h')),
1571 _('Edit person window'), 'not-packed'),
1572 &new_subpage_frame (
1574 &new_text_box_for_int (\%pr::win, 'adeg_w'),
1575 &new_text_box_for_int (\%pr::win, 'adeg_h')),
1576 _('Edit group window'), 'not-packed'),
1577 &new_subpage_frame (
1579 &new_text_box_for_int (\%pr::win, 'adda_w'),
1580 &new_text_box_for_int (\%pr::win, 'adda_h')),
1581 _('Add address window'), 'not-packed'),
1582 &new_subpage_frame (
1584 &new_text_box_for_int (\%pr::win, 'addf_w'),
1585 &new_text_box_for_int (\%pr::win, 'addf_h')),
1586 _('Folder select window'), 'not-packed')
1590 sub new_winpos_subpage_accounts() {
1591 return &new_vbox_pack (
1592 &new_subpage_frame (
1594 &new_text_box_for_int (\%pr::win, 'acco_w'),
1595 &new_text_box_for_int (\%pr::win, 'acco_h')),
1596 _('Accounts window'), 'not-packed'),
1597 &new_subpage_frame (
1599 &new_text_box_for_int (\%pr::win, 'acce_w'),
1600 &new_text_box_for_int (\%pr::win, 'acce_h')),
1601 _('Edit account window'), 'not-packed')
1605 sub new_winpos_subpage_filtering() {
1606 return &new_vbox_pack (
1607 &new_subpage_frame (
1609 &new_text_box_for_int (\%pr::win, 'filt_w'),
1610 &new_text_box_for_int (\%pr::win, 'filt_h')),
1611 _('Filtering window'), 'not-packed'),
1612 &new_subpage_frame (
1614 &new_text_box_for_int (\%pr::win, 'fila_w'),
1615 &new_text_box_for_int (\%pr::win, 'fila_h')),
1616 _('Filtering actions window'), 'not-packed'),
1617 &new_subpage_frame (
1619 &new_text_box_for_int (\%pr::win, 'fild_w'),
1620 &new_text_box_for_int (\%pr::win, 'fild_h')),
1621 _('Filtering debug window'), 'not-packed'),
1622 &new_subpage_frame (
1624 &new_text_box_for_int (\%pr::win, 'matc_w'),
1625 &new_text_box_for_int (\%pr::win, 'matc_h')),
1626 _('Matcher window'), 'not-packed')
1630 sub new_winpos_subpage_prefs() {
1631 return &new_vbox_pack (
1632 &new_subpage_frame (
1634 &new_text_box_for_int (\%pr::win, 'pref_w'),
1635 &new_text_box_for_int (\%pr::win, 'pref_h')),
1636 _('Preferences window'), 'not-packed'),
1637 &new_subpage_frame (
1639 &new_text_box_for_int (\%pr::win, 'temp_w'),
1640 &new_text_box_for_int (\%pr::win, 'temp_h')),
1641 _('Templates window'), 'not-packed'),
1642 &new_subpage_frame (
1644 &new_text_box_for_int (\%pr::win, 'acti_w'),
1645 &new_text_box_for_int (\%pr::win, 'acti_h')),
1646 _('Actions window'), 'not-packed'),
1647 &new_subpage_frame (
1649 &new_text_box_for_int (\%pr::win, 'tags_w'),
1650 &new_text_box_for_int (\%pr::win, 'tags_h')),
1651 _('Tags window'), 'not-packed'),
1652 &new_subpage_frame (
1654 &new_text_box_for_int (\%pr::win, 'plug_w'),
1655 &new_text_box_for_int (\%pr::win, 'plug_h')),
1656 _('Plugins window'), 'not-packed')
1660 sub new_winpos_subpage_misc() {
1661 return &new_vbox_pack (
1662 &new_subpage_frame (
1664 &new_text_box_for_int (\%pr::win, 'logw_w'),
1665 &new_text_box_for_int (\%pr::win, 'logw_h')),
1666 _('Log window'), 'not-packed'),
1667 &new_subpage_frame (
1669 &new_text_box_for_int (\%pr::win, 'prin_w'),
1670 &new_text_box_for_int (\%pr::win, 'prin_h')),
1671 _('Print preview window'), 'not-packed'),
1672 &new_subpage_frame (
1674 &new_text_box_for_int (\%pr::win, 'sour_w'),
1675 &new_text_box_for_int (\%pr::win, 'sour_h')),
1676 _('View source window'), 'not-packed')
1680 sub new_winpos_page() {
1681 my $winbook = Gtk2::Notebook->new;
1682 $winbook->set_tab_pos ('right');
1683 $winbook->append_page (&new_winpos_subpage_main, _('Main'));
1684 $winbook->append_page (&new_winpos_subpage_msgs, _('Message'));
1685 $winbook->append_page (&new_winpos_subpage_sendrecv, _('Send/Receive'));
1686 $winbook->append_page (&new_winpos_subpage_fold, _('Folder'));
1687 $winbook->append_page (&new_winpos_subpage_addrbook, _('Addressbook'));
1688 $winbook->append_page (&new_winpos_subpage_accounts, _('Accounts'));
1689 $winbook->append_page (&new_winpos_subpage_filtering, _('Filtering'));
1690 $winbook->append_page (&new_winpos_subpage_prefs, _('Preferences'));
1691 $winbook->append_page (&new_winpos_subpage_misc, _('Other'));
1696 sub print_version() {
1697 print $xl::s{about_title} . "\n";
1698 print $xl::s{about_version} . " $VERSION\n";
1699 print "Perl-GLib " . $Glib::VERSION;
1700 # version info stuff appeared in 1.040
1701 if ($Glib::VERSION >= 1.040) {
1702 print _(", built for ") . join(".", Glib->GET_VERSION_INFO)
1703 . _(", running with ") . join(".", &Glib::major_version,
1704 &Glib::minor_version, &Glib::micro_version);
1707 print "Perl-GTK2 " . $Gtk2::VERSION;
1708 if ($Gtk2::VERSION >= 1.040) {
1709 print _(", built for ") . join(".", Gtk2->GET_VERSION_INFO)
1710 . _(", running with ") . join(".", &Gtk2::major_version,
1711 &Gtk2::minor_version, &Gtk2::micro_version);
1714 my $clawsver = ($CLAWSV eq "") ?
1715 _("was not found!") :
1716 (_("returned version ") . $CLAWSV);
1717 print "Claws Mail " . $clawsver . "\n";
1720 # the command line help
1722 my $line = '-' x length ($xl::s{about_title}) . "\n";
1724 print $xl::s{about_title} . "\n";
1726 print _("Syntax:\n");
1727 print _(" clawsker [options]\n");
1728 print _("Options:\n");
1729 print _(" --help Prints this help screen.\n");
1730 print _(" --version Prints version infos.\n");
1731 print _(" --verbose More messages on standard output.\n");
1732 print _(" --alternate-config-dir <dir> Uses <dir> as Claws Mail config dir.\n");
1733 print _(" --clawsrc <file> Uses <file> as full resource name.\n");
1736 # handle errors which don't allow to run
1737 sub command_line_fatal() {
1739 my $emsg = $xl::s{e_error} . $reason;
1740 error_dialog ($emsg);
1741 log_message ("$emsg", 'die');
1744 # parse the command line
1745 sub parse_command_line() {
1746 $CLAWSV = &get_claws_version;
1748 while (defined($ARGV[$arg])) {
1762 /--use-claws-version/ && do {
1764 &command_line_fatal ("required version")
1765 unless defined($ARGV[$arg]);
1766 &command_line_fatal ("required a dotted numeric value")
1767 unless ($ARGV[$arg] =~ /[\d\.]+/);
1768 $CLAWSV = $ARGV[$arg];
1771 /--alternate-config-dir/ && do {
1773 &command_line_fatal ($xl::s{e_requireddir})
1774 unless defined($ARGV[$arg]);
1775 &command_line_fatal ($xl::s{e_notadir})
1776 unless -d $ARGV[$arg];
1777 $CONFIGDIR = $ARGV[$arg];
1779 unless ($CONFIGDIR =~ /.*\/$/);
1780 $ALTCONFIGDIR = TRUE;
1785 &command_line_fatal($xl::s{e_requiredfile})
1786 unless defined($ARGV[$arg]);
1787 &command_line_fatal($xl::s{e_notafile})
1788 unless -f $ARGV[$arg];
1789 &set_rc_filename ($ARGV[$arg]);
1792 /.*/ && &command_line_fatal (
1793 _("unknown option '{opt}'.\n", opt => $ARGV[$arg]));
1797 # eveything continues...
1801 # update the hidden preferences status from loaded values
1802 sub init_hidden_preferences() {
1803 foreach my $hash (\%pr::beh, \%pr::col, \%pr::gui, \%pr::oth, \%pr::win) {
1804 foreach my $key (keys %$hash) {
1805 $HPVALUE{${$hash}{$key}[NAME]} = $PREFS{${$hash}{$key}[NAME]};
1811 # load current status from disc
1812 sub load_preferences() {
1813 my $rc = &get_rc_filename;
1814 &log_message ("Loading preferences from $rc\n");
1815 return FALSE unless &check_rc_file ($rc);
1816 return FALSE unless &check_claws_not_running;
1820 if (/^([8a-z_]+)=(.*)$/) {
1828 # save current preferences to disc
1829 sub save_preferences() {
1830 my $rc = &get_rc_filename;
1831 &log_message ("Saving preferences to $rc\n");
1832 return FALSE unless &check_rc_file ($rc);
1833 return FALSE unless &check_claws_not_running;
1834 my $rcbak = "$rc.backup";
1835 rename ($rc, $rcbak);
1837 open (RCB, "<$rcbak");
1840 if (/^([8a-z_]+)=(.*)$/) {
1841 if (defined($HPVALUE{$1})) {
1842 print RCF $1 . "=" . $HPVALUE{$1} . "\n";
1845 print RCF $_ . "\n";
1849 print RCF $_ . "\n";
1858 sub new_notebook() {
1859 my $nb = Gtk2::Notebook->new;
1861 $nb->append_page (&new_behaviour_page, $xl::s{tab_behaviour});
1862 $nb->append_page (&new_colours_page, $xl::s{tab_colours});
1863 $nb->append_page (&new_gui_page, $xl::s{tab_gui});
1864 $nb->append_page (&new_other_page, $xl::s{tab_other});
1865 $nb->append_page (&new_winpos_page, $xl::s{tab_winpos});
1870 # create an about dialog
1871 sub new_about_dialog() {
1873 my $title = $xl::s{about_title};
1874 my $lic = $xl::s{about_license};
1875 my $vers = $xl::s{about_version} . " $VERSION";
1877 "This program is free software: you can redistribute it and/or modify
1878 it under the terms of the GNU General Public License as published by
1879 the Free Software Foundation, either version 3 of the License, or
1880 (at your option) any later version.
1882 This program is distributed in the hope that it will be useful,
1883 but WITHOUT ANY WARRANTY; without even the implied warranty of
1884 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1885 GNU General Public License for more details.
1887 You should have received a copy of the GNU General Public License
1888 along with this program. If not, see <http://www.gnu.org/licenses/>.";
1889 my $year = "2007-2010";
1890 my $holder = "Ricardo Mones <ricardo\@mones.org>";
1891 my $url = "http://www.claws-mail.org/clawsker";
1893 my $dialog = Gtk2::MessageDialog->new_with_markup ($parent,
1894 [qw/modal destroy-with-parent/],
1896 "<span size=\"x-large\" weight=\"bold\">$title</span>\n"
1897 . "<span size=\"large\">$vers</span>\n\n"
1898 . "<span color=\"blue\" size=\"large\">$url</span>\n\n"
1899 . "<span>Copyright $year by $holder</span>\n\n"
1900 . "<span size=\"large\">$lic</span>\n\n"
1901 . "<span size=\"small\">$license</span>");
1902 $dialog->set_title ($xl::s{about});
1907 # create buttons box
1908 sub new_button_box() {
1909 my ($parent, $adlg) = @_;
1910 my $b_about = Gtk2::Button->new_from_stock ('gtk-about');
1911 my $b_exit = Gtk2::Button->new_from_stock ('gtk-quit');
1912 my $b_apply = Gtk2::Button->new_from_stock ('gtk-apply');
1913 # disable button until is really implemented
1914 # my $b_undo = Gtk2::Button->new_from_stock ('gtk-undo');
1915 my $hbox = Gtk2::HBox->new (FALSE, 5);
1917 $b_exit->signal_connect (clicked => sub { Gtk2->main_quit });
1918 $b_apply->signal_connect (clicked => sub { &save_preferences ($parent) });
1919 # $b_undo->signal_connect (clicked => sub { &undo_current_changes });
1920 $b_about->signal_connect (clicked => sub { $adlg->run; $adlg->hide });
1922 $hbox->pack_end ($b_apply, FALSE, FALSE, 0);
1923 $hbox->pack_end ($b_exit, FALSE, FALSE, 0);
1924 # $hbox->pack_end ($b_undo, FALSE, FALSE, 0);
1925 $hbox->pack_start ($b_about, FALSE, FALSE, 0);
1931 $main_window = Gtk2::Window->new ('toplevel');
1932 exit unless &parse_command_line;
1933 exit unless &load_preferences;
1934 exit unless &init_hidden_preferences;
1936 my $box = Gtk2::VBox->new (FALSE, 5);
1937 $box->set_border_width(3);
1938 my $about = &new_about_dialog;
1939 $box->pack_start (&new_notebook, FALSE, FALSE, 0);
1940 $box->pack_end (&new_button_box ($main_window, $about), FALSE, FALSE, 0);
1941 $main_window->signal_connect (delete_event => sub { Gtk2->main_quit });
1942 $main_window->set_title ($xl::s{win_title});
1943 $main_window->add ($box);
1944 $main_window->show_all;