# $Id: Compose.pm,v 1.19 2002/05/16 04:32:06 muhri Exp $
# -*- perl -*-
package Pronto::Compose;
use strict;
use Lingua::Ispell;
use Text::ParseWords;
use SelfLoader;
my $spellstarted = 0;
use vars qw($last_dir);
$last_dir = undef;
1;
__DATA__
sub init_msg_window {
my ($vbox, $toolbar, $tb_item1, $tb_item2, $tb_item3, $tb_item4, $tb_item5, $hbox1, $hbox5, $scrollwin, $scrollbar, $window, $bg, $accel_group, $msg_window, $i, @entry, $textbox, $from_combo, @poplist,@msgbody, $from_label, $msglbl, @frmlabels, $sql, $query, @row, $default, $sigid, $pgp_hbox, $pgp_enc_togg, $pgp_sign_tog, $pgp_keycheck_tog, $width, $height, $spell_window);
my @fields = ("","","","");
my ($widget, $data, $fildref, $msgid, $actid, $forrep) = @_;
# i inserted a hack for the fields, so the interface to send_mail does not change for the bcc field as field #2 (the ex-to field) is now bcc
if ($fildref) {
@fields = @$fildref;
my $tmp = $fields[3];
$fields[3]=$fields[2];
$fields[2]=$tmp;
}
my (@attachments);
my ($rcptcheck,$optbox,$priocombo);
my @priolist=(_("1 (Highest)"),_("2 (High)"),_("3 (Normal)"),
_("4 (Low)"),_("5 (Lowest)"));
my $priodefault=_("3 (Normal)");
my ($notebook, $nbox1, $nbox2);
my ($smenu, $sm_message, $smm_menu, $sm_options, $smo_menu, $sm_sep, $sm_help, $hmm_help);
my $font = Gtk::Gdk::Font->load($main::prefs{'FontComposer'});
if ($main::prefs{'useGtkFontComposer'} eq "y") { $font = "" }
$sql = "select descr, def,id from accounts";
$query=$main::conn->prepare($sql);
$query->execute();
$i = 0;
while (@row=$query->fetchrow_array()) {
$poplist[$i] = $row[0];
if (($row[1] eq "y") and (!$actid)) {
$default = $row[0];
$sigid = $row[2];
}
if (($actid) and ($row[2] == $actid)) {
$default = $row[0];
$sigid = $row[2];
}
$i++;
}
$msg_window = new Gtk::Window("toplevel");
$msg_window->position(-mouse);
$msg_window->set_title(_("Compose Message"));
$msg_window->signal_connect("delete_event" =>
sub {
if(defined $spell_window) {
$spell_window->destroy;
undef $spell_window;
}
Gtk::false;
});
($width,$height) = &main::get_win_size("MsgWinstartUp",500,540);
$msg_window->set_default_size($width,$height);
$msg_window->set_policy(1,1,0);
$msg_window->show;
$msg_window->{'folder'} = 2;
$accel_group = new Gtk::AccelGroup;
$msg_window->add_accel_group($accel_group);
$window = $msg_window->window;
$bg = $msg_window->style->bg('normal');
$vbox = new Gtk::VBox('0','0');
$vbox->show;
$msg_window->add($vbox);
## the toolbar
my $handlebox = new Gtk::HandleBox;
$toolbar = new Gtk::Toolbar('horizontal','both');
$toolbar->set_button_relief('none');
$toolbar->set_tooltips($main::prefs{'ToolTips'});
$toolbar->border_width('2');
$handlebox->add($toolbar);
## the send menubar
$smenu=new Gtk::MenuBar;
$smenu->show;
## the Message Menu
my ($smm_send, $smm_draft, $smm_spell, $smm_cancel, $smm_insert,$restore);
$sm_message=new Gtk::MenuItem(_("Message"));
$sm_message->show;
$smenu->append($sm_message);
$smm_menu=new Gtk::Menu;
$smm_insert= new Gtk::MenuItem(_("Insert from file..."));
$smm_insert->show;
$smm_menu->append($smm_insert);
$restore = new Gtk::MenuItem(_("Restore a session..."));
$restore->show();
$smm_menu->append($restore);
$sm_sep=new Gtk::MenuItem;
$sm_sep->show();
$smm_menu->append($sm_sep);
$smm_send=new Gtk::MenuItem(_("Send"));
$accel_group->add( 0x073, "mod1-mask" ,['visible'], $smm_send, "activate");
$smm_send->show();
$smm_menu->append($smm_send);
$smm_draft=new Gtk::MenuItem(_("Save as Draft"));
$smm_draft->show();
$smm_draft->signal_connect('activate' => sub { $msg_window->{'folder'} = 5; &Pronto::Data::Message::send_message(undef, $msg_window, $msgid, $forrep); });
$smm_menu->append($smm_draft);
$smm_spell=new Gtk::MenuItem(_("Spelling"));
$smm_spell->signal_connect('activate', \&spellcheck,$msg_window,\$spell_window,$sigid,'n');
$smm_spell->show();
$accel_group->add( 0xFFC4, "release-mask" ,['visible'], $smm_spell, "activate");
$smm_menu->append($smm_spell);
$sm_sep=new Gtk::MenuItem;
$sm_sep->show();
$smm_menu->append($sm_sep);
$smm_cancel=new Gtk::MenuItem(_("Cancel"));
$accel_group->add( 0x063, "mod1-mask" ,['visible'], $smm_cancel, "activate");
$smm_cancel->show();
$smm_menu->append($smm_cancel);
$sm_message->set_submenu($smm_menu);
if (defined $main::ONETIME && $main::ONETIME == 1) { $smm_cancel->signal_connect('activate'=> sub { $msg_window->destroy; Gtk->exit(0);});}
$smm_cancel->signal_connect('activate'=> sub {$msg_window->destroy;});
## the options menu
my ($smo_receipt, $smo_prio, $smo_encrypt, $smoe_menu, $smop_menu);
$sm_options=new Gtk::MenuItem(_("Options"));
$sm_options->show;
$smenu->append($sm_options);
$smo_menu=new Gtk::Menu;
$msg_window->{'receiptCheck'}=new Gtk::CheckMenuItem(_("Return-Receipt"));
$msg_window->{'receiptCheck'}->set_show_toggle('1');
$msg_window->{'receiptCheck'}->show();
$smo_menu->append($msg_window->{'receiptCheck'});
$smo_prio=new Gtk::MenuItem(_("Priority"));
$smo_prio->show();
$smo_menu->append($smo_prio);
## the priority sub
my ($smop_1, $smop_2, $smop_3, $smop_4, $smop_5);
$smop_menu=new Gtk::Menu;
$msg_window->{'priorityRadio'}[0]=new Gtk::RadioMenuItem($priolist[0]);
$msg_window->{'priorityRadio'}[0]->show;
$smop_menu->append($msg_window->{'priorityRadio'}[0]);
$msg_window->{'priorityRadio'}[1]=new Gtk::RadioMenuItem($priolist[1],$msg_window->{'priorityRadio'}[0]);
$msg_window->{'priorityRadio'}[1]->show;
$smop_menu->append($msg_window->{'priorityRadio'}[1]);
$msg_window->{'priorityRadio'}[2]=new Gtk::RadioMenuItem($priolist[2],$msg_window->{'priorityRadio'}[0]);
$msg_window->{'priorityRadio'}[2]->set_active(1);
$msg_window->{'priorityRadio'}[2]->show;
$smop_menu->append($msg_window->{'priorityRadio'}[2]);
$msg_window->{'priorityRadio'}[3]=new Gtk::RadioMenuItem($priolist[3],$msg_window->{'priorityRadio'}[0]);
$msg_window->{'priorityRadio'}[3]->show;
$smop_menu->append($msg_window->{'priorityRadio'}[3]);
$msg_window->{'priorityRadio'}[4]=new Gtk::RadioMenuItem($priolist[4],$msg_window->{'priorityRadio'}[0]);
$msg_window->{'priorityRadio'}[4]->show;
$smop_menu->append($msg_window->{'priorityRadio'}[4]);
$smo_prio->set_submenu($smop_menu);
$sm_sep=new Gtk::MenuItem;
$sm_sep->show();
$smo_menu->append($sm_sep);
$smo_encrypt=new Gtk::MenuItem(_("Encryption"));
$smo_encrypt->show();
$smo_menu->append($smo_encrypt);
## the encription sub
my ($smoe_encrypt, $smoe_sign, $smoe_keycheck);
$smoe_menu=new Gtk::Menu;
$msg_window->{'encryptCheck'}=new Gtk::CheckMenuItem(_("Encrypt"));
$msg_window->{'encryptCheck'}->set_show_toggle('1');
$msg_window->{'Encrypt'} = 0;
# if ($main::prefs{'Encrypt'}) {$msg_window->{'encryptCheck'}->set_active(1);}
$msg_window->{'encryptCheck'}->show();
$smoe_menu->append($msg_window->{'encryptCheck'});
$msg_window->{'signCheck'}=new Gtk::CheckMenuItem(_("Sign"));
$msg_window->{'signCheck'}->set_show_toggle('1');
if ($main::prefs{'Sign'}) {$msg_window->{'signCheck'}->set_active(1);}
$msg_window->{'signCheck'}->show();
$smoe_menu->append($msg_window->{'signCheck'});
# $smoe_keycheck=new Gtk::MenuItem("Key check");
# $smoe_keycheck->signal_connect('activate', \&Pronto::Crypt::GUI::keyserver_search_window);
# $smoe_keycheck->show();
# $smoe_menu->append($smoe_keycheck);
$smo_encrypt->set_submenu($smoe_menu);
$sm_options->set_submenu($smo_menu);
## the help menu
$sm_help=new Gtk::MenuItem(_("Help"));
$sm_help->show;
$smenu->append($sm_help);
my $smh_menu=new Gtk::Menu;
$hmm_help=new Gtk::MenuItem(_("Help"));
$accel_group->add( 0xFFBE, "release-mask" ,['visible'], $hmm_help, "activate");
$hmm_help->show();
$sm_help->set_submenu($smh_menu);
$smh_menu->append($hmm_help);
my $mailSupport = new Gtk::MenuItem(_("Mail Support"));
$mailSupport->show();
$smh_menu->append($mailSupport);
$vbox->pack_start($smenu,0,0,0);
$toolbar->show;
$handlebox->show;
$vbox->pack_start($handlebox,0,0,0);
$tb_item1 = $toolbar->append_item(_("Send"),_("Click here to send this message"), "",&main::new_pixmap("$main::prefs{'PixmapDir'}/tb_send.xpm", $window, $bg));
$tb_item2 = $toolbar->append_item(_("Spelling"),_("Click here to spell-check this message"), "",&main::new_pixmap("$main::prefs{'PixmapDir'}/spellcheck.xpm", $window, $bg));
$tb_item4 = $toolbar->append_item(_("Addressbook"), _("Click here to open the Addressbook"), "",&main::new_pixmap("$main::prefs{'PixmapDir'}/addressbook.xpm", $window, $bg));
## notebook tab Mail
$nbox1=new Gtk::VBox(0,0);
$nbox1->show();
$hbox1 = new Gtk::HBox(0,0);
$hbox1->border_width('3');
$hbox1->show;
$from_label = new Gtk::Label("From:");
$from_label->set_padding('5','5');
$from_label->set_usize(40,10);
$from_label->show;
$hbox1->pack_start($from_label,0,0,0);
$msg_window->{'fromCombo'} = new Gtk::Combo;
$msg_window->{'fromCombo'}->set_case_sensitive('0');
$msg_window->{'fromCombo'}->set_use_arrows('1');
$msg_window->{'fromCombo'}->set_popdown_strings(@poplist);
$msg_window->{'fromCombo'}->entry->set_text($default);
$msg_window->{'fromCombo'}->show;
$hbox1->pack_start( $msg_window->{'fromCombo'},1,1,0);
$nbox1->pack_start($hbox1,0,0,0);
@frmlabels = ("To:","Cc:","Bcc:","Subj:");
my $tmp;
$i=0;
foreach $msglbl (@frmlabels) {
my ($hbox, $label);
$hbox = new Gtk::HBox(0,0);
$hbox->border_width('3');
$hbox->show;
$label = new Gtk::Label($msglbl);
$label->set_padding('5','5');
$label->set_usize(40,10);
$label->show;
$hbox->pack_start($label,0,0,0);
$tmp=$msglbl;
$tmp=~s/://;
$msg_window->{$tmp.'Entry'}= new Gtk::Entry;
$msg_window->{$tmp.'Entry'}->set_text($fields[$i]);
$msg_window->{$tmp.'Entry'}->set_editable('1');
$msg_window->{$tmp.'Entry'}->show;
if ($tmp ne "Subj") { #drag and drop signals.
&main::set_composer_entry_drag_signals($msg_window->{$tmp.'Entry'});
}
$hbox->pack_start($msg_window->{$tmp.'Entry'},1,1,0);
$nbox1->pack_start($hbox,0,0,0);
$i++;
}
my ($avbox,$ahbox,$abutbox,$abutton,$afilelist,$ahbox2, $afilewin);
$avbox= new Gtk::VBox(0,0);
$avbox->border_width(3);
$avbox->show;
$ahbox=new Gtk::HBox(0,5);
$ahbox->show();
$avbox->pack_start($ahbox, 1,1,0);
$afilewin=new Gtk::ScrolledWindow(undef,undef);
$afilewin->set_policy('automatic','automatic');
$ahbox->pack_start($afilewin, 1,1,0);
$afilewin->can_focus(0);
my @titles=(_("Filename"),_("Size"));
$msg_window->{'attachClist'}=new_with_titles Gtk::CList(@titles);
&main::set_attachment_clist_drag_signals($msg_window->{'attachClist'});
$msg_window->{'attachClist'}->set_selection_mode("single");
$msg_window->{'attachClist'}->set_usize(50,50);
$msg_window->{'attachClist'}->set_column_width(0,260);
$afilewin->add($msg_window->{'attachClist'});
$msg_window->{'attachClist'}->show();
$afilewin->show();
$abutbox = new Gtk::VButtonBox;
$abutbox->set_usize(-1,32);
$abutbox->set_layout_default('start');
$ahbox->pack_start($abutbox, 0,1,5);
$abutton = new_with_label Gtk::Button(_("Add..."));
$abutton->set_usize(50,-1);
$abutton->signal_connect('clicked', \&selectAttachFile,$msg_window->{'attachClist'});
$abutbox->add($abutton);
$abutton->show;
$abutton = new_with_label Gtk::Button(_("Delete"));
$abutton->set_usize(50,-1);
$abutton->signal_connect('clicked', \&deleteAttachFile,$msg_window->{'attachClist'});
$abutbox->add($abutton);
$abutton->show;
$abutton = new_with_label Gtk::Button(_("Clear All"));
$abutton->set_usize(50,-1);
$abutton->signal_connect('clicked', \&clearAttachFile,$msg_window->{'attachClist'});
$abutbox->add($abutton);
$abutton->show;
$abutbox->show;
$abutbox->show;
$notebook=new Gtk::Notebook;
my $lbl1=new Gtk::Label(_("Message"));
$lbl1->show;
$notebook->append_page($nbox1,$lbl1);
my $lbl2=new Gtk::Label(_("Attachments"));
$lbl2->show;
$notebook->append_page($avbox,$lbl2);
$notebook->show();
$vbox->pack_start($notebook, 0,0,0);
$msg_window->{'ToEntry'}->signal_connect('focus_out_event' => \&alias_expand, $msg_window->{'ToEntry'});
$msg_window->{'CcEntry'}->signal_connect('focus_out_event' => \&alias_expand, $msg_window->{'CcEntry'});
$msg_window->{'BccEntry'}->signal_connect('focus_out_event' => \&alias_expand, $msg_window->{'BccEntry'});
$msg_window->{'mailText'} = new Gtk::Text(undef,undef);
$msg_window->{'ToEntry'}->signal_connect('focus_in_event', sub {
my ($this) = @_; $data->{'focused'} = $this; });
$msg_window->{'CcEntry'}->signal_connect('focus_in_event', sub { my ($this) = @_; $data->{'focused'} = $this;});
$msg_window->{'BccEntry'}->signal_connect('focus_in_event', sub { my ($this) = @_; $data->{'focused'} = $this; });
# if (!$spellstarted) {
# Gtk::Text::start_spell();
# $spellstarted = 1;
# }
# Gtk::Text::attach($msg_window->{'mailText'});
$msg_window->{'mailText'}->set_word_wrap(1);
$msg_window->{'SubjEntry'}->signal_connect("key_press_event" => sub {my($this, $event)=@_; if($event->{keyval} == 65289) {$this->signal_emit_stop("key_press_event");$msg_window->{'mailText'}->grab_focus;return 1}});
$scrollbar = new Gtk::VScrollbar($msg_window->{'mailText'}->vadj);
$scrollbar->show;
$msg_window->{'mailText'}->set_editable('1');
if ($msgid) {
&Pronto::Read::view_message($main::conn, $msgid, $msg_window->{'mailText'}, 2, $forrep, undef, undef, undef, $msg_window->{'attachClist'});
}
unless (defined $forrep && $forrep == 3) {
my @sig;
if (($sigid) and (open(TMP, "<$main::prefs{'MailDir'}/sig/$sigid.sig")) && !$main::prefs{'ExternalSig'}) {
undef $/;
@sig = <TMP>;
$/ = "\n";
close(TMP);
} elsif ($sigid && $main::prefs{'ExternalSig'}) {
@sig = `$main::prefs{'SigCmd'}`;
# if (!@sig) { @sig = (" "); }
}
if (@sig) {
$msg_window->{'mailText'}->insert($font,'','',"\n-- \n");
foreach(@sig) {
$msg_window->{'mailText'}->insert($font,'','',"$_");
}
$msg_window->{'mailText'}->insert($font,'','',"\n");
}
}
$msg_window->{'mailText'}->set_point(0);
$msg_window->{'mailText'}->insert($font,'','',"\n");
$msg_window->{'mailText'}->show;
$hbox5 = new Gtk::HBox(0,0);
$hbox5->border_width('3');
$hbox5->pack_start($msg_window->{'mailText'},1,1,0);
$hbox5->pack_start($scrollbar,0,0,0);
$hbox5->show;
$vbox->add($hbox5);
if($main::prefs{'autospell'} eq 'y') {
$tb_item1->signal_connect('clicked', \&spellcheck, $msg_window, \$spell_window, $sigid, 'y', $msgid, $forrep);
$smm_send->signal_connect('activate', \&spellcheck, $msg_window, \$spell_window, $sigid, 'y', $msgid, $forrep);
} else {
$tb_item1->signal_connect('clicked', \&Pronto::Data::Message::send_message, $msg_window, $msgid, $forrep);
$smm_send->signal_connect('activate', \&Pronto::Data::Message::send_message, $msg_window, $msgid, $forrep);
}
$smm_insert->signal_connect('activate', \&insertFromFileSelect, $msg_window );
$restore->signal_connect('activate', \&Restore_Session, $msg_window);
$tb_item2->signal_connect('clicked', \&spellcheck, $msg_window,\$spell_window,$sigid,'n');
$data->{'to'} = $msg_window->{'ToEntry'};
$data->{'cc'} = $msg_window->{'CcEntry'};
$data->{'bcc'} = $msg_window->{'BccEntry'};
$tb_item4->signal_connect('clicked', \&Pronto::AddressBook::init_win, $data);
$msg_window->{'fromCombo'}->popwin->signal_connect("hide", \&switch_sig, $msg_window->{'fromCombo'}, $msg_window->{'mailText'});
$scrollbar->can_focus(0);
$notebook->can_focus(1);
$lbl1->can_focus(0);
$lbl2->can_focus(0);
$msg_window->{'ToEntry'}->grab_focus;
$msg_window->{'encryptCheck'}->signal_connect('toggled', \&toggle_enc, $msg_window);
$msg_window->{'signCheck'}->signal_connect('toggled', \&toggle_sign);
$toolbar->set_style($main::prefs{'toolbarstyle'});
if ($main::prefs{'toolbar'} eq "n") { $handlebox->hide; }
if (defined $main::ONETIME && $main::ONETIME == 1) { $msg_window->signal_connect("destroy", sub { $msg_window->destroy; Gtk->exit(0) });}
$msg_window->signal_connect("destroy" => \&msg_window_destroy, $data);
$msg_window->signal_connect("size-request" => \&main::save_win_size, "MsgWinstartUp", $msg_window->window);
$msg_window->{'session_id'} = localtime;
$mailSupport->signal_connect("activate", sub {
my $info = &Pronto::About::UserInfo();
$msg_window->{'ToEntry'}->set_text("pronto\@muhri.net");
$msg_window->{'mailText'}->insert('','','',"UserInfo\n--------------\n$info");
return;
});
#do we enable auto_save
if ($main::prefs{'autosave'}) {
$msg_window->{'timer'} = Gtk->timeout_add(1000, \&do_auto_save, $msg_window);
}
return 1;
}
sub Drag_Data_Entry
{
my ($entry, $context, $x, $y, $data, $info, $time) = @_;
if (($data->length >=0) && ($data->format == 8)) {
my @tmp = split(/\n/,$data->data);
my $isemail = 0;
my $email="";
foreach my $line (@tmp) {
chomp($line);
$line=~ s/E-mail://ig;
$line=~ s/ //g;
if ($line =~ /([-_a-zA-Z0-9.]+\@[-_a-zA-Z0-9.]+\.[-_a-zA-Z0-9]+)/) {
$isemail = 1;
$email = $line;
}
}
if ($isemail) {
my $tmp2 = $entry->get_text();
if ($tmp2 && $tmp2 ne "") {
my $text = $tmp2.", ".$email;
$entry->set_text($text);
} else {
$entry->set_text($email);
}
$context->finish(1,0,$time);
return 1;
}
}
$context->finish(0, 0, $time);
return 0;
}
sub Drag_Data_Received
{
my ($clist, $context, $x, $y, $data, $info, $time) = @_;
if (($data->length >= 0) && ($data->format == 8)) {
my @files = split(/\n/,$data->data);
foreach my $file (@files) {
chop($file);
$file =~ s/^file:\/\///g; #netscape/mozilla
$file =~ s/^file://g; #gmc
next if (!-f $file);
next if (!-e $file);
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size)=stat $file;
$size=$size/1024;
$clist->append(($file,(sprintf("%8.2f",$size)."kb")));
}
$context->finish(1, 0, $time);
return 1;
}
$context->finish(0, 0, $time);
return 0;
}
sub do_auto_save
{
my ($msg_window) = @_;
if (defined $msg_window->{'mailText'}) {
open(TMP,">$main::prefs{'MailDir'}/sessions/".$msg_window->{'session_id'}) or return 0;
print TMP $msg_window->{'mailText'}->get_chars(0,-1);
close(TMP);
return 1;
} else {
# print "timer going out\n";
return 0;
}
}
sub Restore_Session
{
my ($menuitem, $msg_window) = @_;
my (@list,$dialog);
opendir(DIR,"$main::prefs{'MailDir'}/sessions") or return &main::err_dialog("Couldn't read sessions dir !");
while (defined (my $file = readdir DIR)) {
next if $file =~ /^\.\.?$/;
next if ($file eq $msg_window->{'session_id'});
push @list, $file;
}
closedir(DIR);
return &main::err_dialog(_("No stale sessions found !")) if (scalar(@list) == 0);
$dialog = new Gtk::Dialog();
$dialog->set_title(_("Restore Session"));
$dialog->{'clist'} = new Gtk::CList(1);
$dialog->{'sw'} = new Gtk::ScrolledWindow(undef,undef);
$dialog->{'sw'}->set_policy('automatic','automatic');
$dialog->{'sw'}->add($dialog->{'clist'});
$dialog->vbox->pack_start($dialog->{'sw'},1,1,0);
$dialog->{'restore'} = new Gtk::Button(_("Restore"));
$dialog->{'delete'} = new Gtk::Button(_("Delete"));
$dialog->action_area->pack_start($dialog->{'restore'},1,1,0);
$dialog->action_area->pack_start($dialog->{'delete'},1,1,0);
$dialog->set_default_size(200,150);
foreach(@list) {
chomp($_);
$dialog->{'clist'}->append($_);
}
$dialog->{'restore'}->signal_connect("clicked", \&restore_clicked, $msg_window, $dialog);
$dialog->{'delete'}->signal_connect("clicked", \&delete_session, $dialog);
$dialog->show_all();
return;
}
sub delete_session
{
my ($button,$dialog)=@_;
my @selection = $dialog->{'clist'}->selection();
return if (!@selection);
my $file = $dialog->{'clist'}->get_text($selection[0],0);
unlink($main::prefs{'MailDir'}."/sessions/".$file) or return &main::err_dialog(_("Couldn't remove session file!"));
$dialog->{'clist'}->remove($selection[0]);
return;
}
sub restore_clicked
{
my ($button, $msg_window, $dialog) = @_;
return if (!defined($msg_window->{'mailText'}));
my @selection = $dialog->{'clist'}->selection();
return if (!@selection);
my $file = $dialog->{'clist'}->get_text($selection[0],0);
open(TMP,"$main::prefs{'MailDir'}/sessions/$file") or return &main::err_dialog(_("Couldn't read session file !"));
$msg_window->{'mailText'}->freeze();
$msg_window->{'mailText'}->set_point(0);
$msg_window->{'mailText'}->forward_delete($msg_window->{'mailText'}->get_length());
while (<TMP>) {
$msg_window->{'mailText'}->insert('','','',"$_");
}
close(TMP);
$msg_window->{'mailText'}->thaw();
$dialog->destroy();
return;
}
sub msg_window_destroy {
my ($window, $data) = @_;
undef $data->{'to'};
undef $data->{'cc'};
undef $window->{'mailText'};
# print("deleting session file $window->{'session_id'}\n");
unlink($main::prefs{'MailDir'}."/sessions/".$window->{'session_id'});
$window->destroy;
}
sub alias_expand {
my ($widget, $entry, $event) = @_;
my ($sql, $text, @fields, $alias_check, $group_check, @new_fields, %new_fields);
my ($aprox_id);
$text = $entry->get_text;
# Queries to check if the entry is in a group or an alias
$sql = "SELECT id FROM groups WHERE name LIKE ?";
$group_check = $main::conn->prepare ($sql);
$sql = "SELECT address, alias FROM addresses WHERE alias LIKE ?";
$alias_check = $main::conn->prepare ($sql);
$sql = "SELECT address, alias, groups FROM addresses WHERE groups LIKE ?";
$aprox_id = $main::conn->prepare ($sql);
# Get the fields from the text field
@fields = quotewords(", ", 1, $text);
# Go through all the fields
for (@fields) {
if (defined $_) {
if (index ($_, '@') == -1) {
my $rows;
# Check groups first
$rows = $group_check->execute ("%$_%");
if ($rows > 0) {
while (my ($id) = $group_check->fetchrow) {
$aprox_id->execute ("%$id%");
while (my ($address, $alias, $groups) = $aprox_id->fetchrow) {
next unless $groups;
if (grep { $id eq $_ } split "," => $groups) {
$new_fields{$alias} = $address;
}
}
}
next;
}
# Check for aliases
$rows = $alias_check->execute ("%$_%");
if ($rows > 0) {
my ($address, $alias) = $alias_check->fetchrow;
$new_fields{$alias} = $address;
next;
}
}
else {
push @new_fields, $_;
}
}
}
$text = (@new_fields) ? (join (", " => @new_fields)) : '';
if (keys %new_fields) {
$text .= ', ' if (@new_fields);
for (keys %new_fields) {
$text .= qq{"$_" <$new_fields{$_}>, };
}
chop $text; chop $text;
}
$entry->set_text ($text) if ($text && $text ne "");
$entry->{'focus'} = 0;
return 1;
}
sub toggle_enc {
my ($button, $msg_window)=@_;
if ($msg_window->{'Encrypt'}) {
$msg_window->{'Encrypt'} = 0;
} else {
$msg_window->{'Encrypt'} = 1;
}
}
sub toggle_sign {
if ($main::prefs{'Sign'}) {
$main::prefs{'Sign'} = 0;
} else {
$main::prefs{'Sign'} = 1;
}
&main::save_prefs();
}
sub switch_sig {
my ($widget, $from_combo, $textbox) = @_;
my ($friendly, $sql, $query, @row, @sig, $sigid, $body);
my $font = Gtk::Gdk::Font->load($main::prefs{'FontComposer'});
if ($main::prefs{'useGtkFontComposer'} eq "y") { $font = "" }
$body = $textbox->get_chars(0,-1);
$textbox->freeze;
$textbox->set_point(length($body));
$textbox->backward_delete(length($body));
$body =~ s/\n-- \n.*//s;
$textbox->insert($font,'','',$body);
$friendly = $from_combo->entry->get_text();
$sql = "select id from accounts where descr=?";
$query=$main::conn->prepare($sql);
$query->execute($friendly);
@row = $query->fetchrow_array();
$sigid = $row[0];
if (open(TMP,"<$main::prefs{'MailDir'}/sig/$sigid.sig") && !$main::prefs{'ExternalSig'}) {
@sig = <TMP>;
close(TMP);
} elsif ($sigid && $main::prefs{'ExternalSig'}) {
@sig = `$main::prefs{'SigCmd'}`;
}
if (@sig) {
$textbox->insert($font,'','',"\n-- \n");
foreach (@sig) {
$textbox->insert($font,'','',$_);
}
$textbox->insert($font,'','',"\n");
}
$textbox->thaw;
return 1;
}
sub insertFromFileSelect {
my ($widget, $win)=@_ ;
my ($fs_window);
$fs_window = new Gtk::FileSelection _("Choose file to insert into Message...");
$fs_window->position(-mouse);
$fs_window->signal_connect("destroy", sub {$fs_window->destroy;});
$fs_window->signal_connect("delete_event" => \&Gtk::false);
$fs_window->ok_button->signal_connect("clicked", \&insertFromFile, $fs_window, $win);
$fs_window->cancel_button->signal_connect("clicked", sub {$fs_window->destroy;});
$fs_window->show;
return 1;
}
sub insertFromFile {
my ($widget, $filewin, $win)=@_;
my ($filename, $error, $tmp, $textbox);
$textbox=$win->{'mailText'};
$error=0;
$filename=$filewin->get_filename();
$filewin->destroy;
open FILE, $filename or $error=1;
if ($error == 1){
&main::err_dialog("$filename " ._("could not get opened!"));
} else {
$tmp="";
while (<FILE>){
$tmp.=$_;
}
close FILE;
$tmp.="\n".$textbox->get_chars(0,-1);
$textbox->set_point(0);
$textbox->forward_delete($textbox->get_length);
$textbox->insert('','','',"$tmp");
}
return 1;
}
sub spellcheck {
my ($window,$msg_window,$spell_window,$sigid,$autospell,$msgid,$forrep) = @_;
my ($textbox,$body,@spell_list,$vbox,$tbox,$bg,$butbox,$ok_button,$combo,$i,$sum,$replace_button,$last_combo_connect,$next_button,$add_button,$last_add_connect);
if(defined $$spell_window) {
return 1;
}
$textbox=$msg_window->{'mailText'};
if(-f $main::prefs{'ispellpath'}) {
$Lingua::Ispell::path = $main::prefs{'ispellpath'};
if ($main::prefs{'dictionary'} && $main::prefs{'dictionary'} ne "") {
Lingua::Ispell::use_dictionary($main::prefs{'dictionary'});
}
}
else {
&main::err_dialog(_("The path to ispell or aspell is not set correctly"));
return 1;
}
exec_ispell($textbox,\@spell_list,$sigid,\$sum);
if(($sum == 0) && ($autospell eq 'y')) {
&Pronto::Data::Message::send_message($msg_window,$msg_window,$msgid,$forrep);
return 1;
}
$i = 0;
$$spell_window = new Gtk::Window("toplevel");
$$spell_window->set_position("mouse");
$$spell_window->set_title(_("Spell Check"));
$$spell_window->signal_connect("destroy" =>
sub {
$$spell_window->destroy;
undef $$spell_window;
});
$$spell_window->signal_connect("delete_event" => \&Gtk::false);
$$spell_window->set_default_size('180','130');
$$spell_window->set_policy(1,1,0);
$$spell_window->show;
$window = $$spell_window->window;
$vbox = new Gtk::VBox(0,0);
$$spell_window->add($vbox);
$vbox->show;
$tbox = new Gtk::Label("");
$vbox->pack_start($tbox,1,1,1);
$tbox->show;
$combo = new Gtk::Combo();
$vbox->pack_start($combo,1,1,1);
$combo->hide;
$replace_button = new Gtk::Button(_("Replace"));
$vbox->pack_start($replace_button,1,1,1);
$replace_button->hide;
$add_button = new Gtk::Button(_("Add to Dictionary"));
$vbox->pack_start($add_button,1,1,1);
$add_button->hide;
$butbox = new Gtk::HButtonBox;
$butbox->show;
$vbox->pack_start($butbox,1,1,1);
if($autospell eq 'y') {
$ok_button = new_with_label Gtk::Button(_("Send"));
}
else {
$ok_button = new_with_label Gtk::Button(_("OK"));
}
$ok_button->set_usize(50,-1);
$ok_button->signal_connect('clicked',
sub {
$$spell_window->destroy;
if($autospell eq 'y') {
&Pronto::Data::Message::send_message($msg_window,$msg_window,$msgid,$forrep);
}
});
$ok_button->can_default(1);
$ok_button->grab_default;
$next_button = new_with_label Gtk::Button(_("Next"));
$next_button->set_usize(50,-1);
$next_button->signal_connect('clicked',
sub {
if((++$i == $sum) && (0 != $sum)) {
$i=-1;
$tbox->set_text(_("End of Message\nPress Next to\nGo Back to Top"));
$replace_button->hide;
$combo->hide;
$add_button->hide;
exec_ispell($textbox,\@spell_list,$sigid,\$sum);
}
else {
spellcheck_next($textbox,$spell_list[$i],$tbox,$combo,$replace_button,$add_button,$i,$sum,\$last_combo_connect,\$last_add_connect,$next_button);
}
});
$next_button->can_default(1);
$next_button->grab_default;
$butbox->add($next_button);
$next_button->show;
$butbox->add($ok_button);
$ok_button->show;
spellcheck_next($textbox,$spell_list[$i],$tbox,$combo,$replace_button,$add_button,$i,$sum,\$last_combo_connect,\$last_add_connect,$next_button);
return 1;
}
sub spellcheck_next {
my($textbox, $r, $tbox, $combo, $replace_button, $add_button, $i, $sum, $last_combo_connect,$last_add_connect,$next_button) = @_;
my($body,$end,$start,$word_num,$miss,$misses,$array,$j);
$word_num = $i+1;
$misses ="";
if($sum==0) {
$tbox->set_text(_("Found No Mispelled Words"));
$next_button->hide;
$combo->hide;
$replace_button->hide;
$add_button->hide;
}
if(defined $r) {
$array = $r->{'misses'};
$j=0;
$body = $textbox->get_chars(0,-1);
$body =~ s/\n/ /g;
$body =~ s/_/ /g;
$body =~ s/[0-9]/ /g;
if($body =~ m/\b$r->{'term'}\b/g) {
$end = pos $body;
$start = $end - length($r->{'term'});
if (!$array) {
$tbox->set_text("$word_num of $sum [$r->{'term'}]\n was not found in dictionary");
$replace_button->hide;
$combo->hide;
}
else {
$tbox->set_text("$word_num of $sum Mispelled Words\nSuggestions:");
$combo->set_popdown_strings(@$array);
$replace_button->show;
$combo->show;
}
if(defined $$last_combo_connect) {
if($replace_button->signal_n_emissions('clicked')) {
$replace_button->signal_emit_stop('clicked');
}
$replace_button->signal_disconnect($$last_combo_connect);
}
$$last_combo_connect=$replace_button->signal_connect('clicked',
sub{
$textbox->freeze;
$textbox->set_point($start);
$textbox->forward_delete($end-$start);
$textbox->insert("","","",$combo->entry->get_text());
$textbox->thaw;
$end = $start + length($combo->entry->get_text());
$textbox->freeze;
$textbox->select_region($start,$end);
$textbox->thaw;
$next_button->signal_emit('clicked');
});
if(defined $$last_add_connect) {
if($add_button->signal_n_emissions('clicked')) {
$add_button->signal_emit_stop('clicked');
}
$add_button->signal_disconnect($$last_add_connect);
}
$$last_add_connect=$add_button->signal_connect('clicked', sub{add_word($r->{'term'},$next_button);});
$add_button->show;
$textbox->freeze;
$textbox->select_region($start,$end);
$textbox->thaw;
}
else {
$tbox->set_text("$word_num of $sum Spelling Changed");
$combo->hide;
$replace_button->hide;
$add_button->hide;
}
}
$tbox->show;
return 1;
}
sub exec_ispell{
my($textbox,$spell_list,$sigid,$sum) = @_;
my($body);
$body = $textbox->get_chars(0,-1);
$body =~ s/\n/ /g;
if (($sigid) and (open(TMP, "<$main::prefs{'MailDir'}/sig/$sigid.sig"))) {
my @sig = <TMP>;
close(TMP);
my $sig=join("",@sig);
$body=~ s/\Q$sig\E//;
}
$$sum=0;
@$spell_list = Lingua::Ispell::spellcheck( $body );
while(defined $$spell_list[$$sum]) {
$$sum++;
}
return 1;
}
sub add_word {
my ($word,$next_button) = @_;
my ($window,$vbox,$butbox,$button,$tbox);
$window = new Gtk::Window("toplevel");
$window->set_position("mouse");
$window->set_title("Add Word to Dictionary");
$window->signal_connect("destroy" => sub{$window->destroy;});
$window->signal_connect("delete_event" => \&Gtk::false);
$window->set_default_size('200','70');
$window->set_policy(1,1,0);
$window->show;
$vbox = new Gtk::VBox(1,1);
$window->add($vbox);
$vbox->show;
$tbox = new Gtk::Label("Add $word\nto the Dictionary?");
$vbox->pack_start($tbox,1,1,1);
$tbox->show;
$butbox = new Gtk::HButtonBox;
$vbox->pack_start($butbox,1,1,1);
$button = new Gtk::Button("No");
$button->signal_connect('clicked', sub{$window->destroy;});
$butbox->add($button);
$button->show;
$button = new Gtk::Button("Yes");
$button->signal_connect('clicked',
sub{
Lingua::Ispell::add_word($word);
$next_button->signal_emit('clicked');
$window->destroy;
});
$butbox->add($button);
$button->show;
$butbox->show;
return 1;
}
sub attach_file {
my ($widget)=shift;
my ($attachments)=shift;
my ($attach_win,$window,$bg,$tbox,$hbox,$sep,$butbox,$button,$butbox1,$filelist,
$tmp,$hbox2, $filewin);
my ($attach_rows,$arrtmp);
$attach_rows=-1;
$attach_win = new Gtk::Window("dialog");
$attach_win->set_title(_("Attach files"));
$attach_win->signal_connect("destroy" => sub { $attach_win->destroy; });
$attach_win->signal_connect("delete_event" => \&Gtk::false);
$attach_win->set_default_size('350','200');
$attach_win->set_policy(1,1,0);
$attach_win->show;
$window = $attach_win->window;
$bg = $attach_win->style->bg('normal');
$hbox= new Gtk::VBox(0,0);
$attach_win->add($hbox);
$hbox->show;
$hbox2=new Gtk::HBox(0,5);
$hbox->pack_start($hbox2, 1,1,0);
$hbox2->show();
$filewin=new Gtk::ScrolledWindow(undef,undef);
$filewin->set_policy('automatic','automatic');
$hbox2->pack_start($filewin, 1,1,0);
my @titles=(_("Filename"),_("Size"));
$filelist=new_with_titles Gtk::CList(@titles);
$filelist->set_selection_mode("single");
$filelist->set_usize(50,50);
$filelist->set_column_width(0,160);
# $filelist->signal_connect('select_row', \&selectAttach,\$attach_rows);
# $filelist->signal_connect('unselect_row', \&unSelectAttach,\$attach_rows);
$filewin->add($filelist);
# $hbox->pack_start($filelist, 0,0,0);
if (scalar(@$attachments)>0){
for ($tmp=0;$tmp<scalar(@$attachments);$tmp++){
$arrtmp=@$attachments[$tmp];
$filelist->append((@$arrtmp[0],@$arrtmp[1]));
}
}
$filelist->show();
$filewin->show();
$butbox1 = new Gtk::VButtonBox;
$butbox1->set_usize(-1,32);
$butbox1->set_layout_default('start');
$hbox2->pack_start($butbox1, 0,1,5);
$button = new_with_label Gtk::Button("Add...");
$button->set_usize(50,-1);
$button->signal_connect('clicked', \&selectAttachFile,$filelist);
$butbox1->add($button);
$button->show;
$button = new_with_label Gtk::Button("Delete");
$button->set_usize(50,-1);
$button->signal_connect('clicked', \&deleteAttachFile,$filelist);
$butbox1->add($button);
$button->show;
$butbox1->show;
$button = new_with_label Gtk::Button("Clear All");
$button->set_usize(50,-1);
$button->signal_connect('clicked', \&clearAttachFile,$filelist);
$butbox1->add($button);
$button->show;
$butbox1->show;
$sep = new Gtk::HSeparator;
$sep->set_usize(-1,5);
$hbox->pack_start($sep,0,1,0);
$sep->show;
$butbox = new Gtk::HButtonBox;
$butbox->set_usize(-1,32);
$hbox->pack_start($butbox, 0,1,0);
$butbox->show;
$button = new_with_label Gtk::Button(_("OK"));
$button->set_usize(50,-1);
$button->signal_connect('clicked', \&okAttach,$attach_win, $filelist, $attachments);
$button->can_default(1);
$button->grab_default;
$butbox->add($button);
$button->show;
$button = new_with_label Gtk::Button(_("Cancel"));
$button->set_usize(50,-1);
$button->signal_connect('clicked', sub { $attach_win->destroy; });
$button->can_default(1);
$button->grab_default;
$butbox->add($button);
$button->show;
return 1;
}
sub okAttach {
my ($widget,$attach_win,$list,$attachments)=@_;
my ($tmp,$tmp1,$tmp2);
if ($list->rows>=1){
for ($tmp=0;$tmp<$list->rows;$tmp++){
$tmp1=$list->get_text($tmp,0);
$tmp2=$list->get_text($tmp,1);
@$attachments[$tmp]=[$tmp1,$tmp2];
}
} else {
}
$attach_win->destroy;
}
sub clearAttachFile {
my ($widget,$listwidget)=@_;
$listwidget->clear();
return 1;
}
sub selectAttachFile {
my ($widget,$listwidget)=@_;
my ($fs_window);
$fs_window = new Gtk::FileSelection _("Select File to Attach...");
$fs_window->position(-mouse);
$fs_window->file_list->set_selection_mode('extended');
$fs_window->signal_connect("destroy", sub {$fs_window->destroy;});
$fs_window->signal_connect("delete_event" => \&Gtk::false);
$fs_window->ok_button->signal_connect("clicked", \&addAttachFile, $fs_window, $listwidget);
$fs_window->cancel_button->signal_connect("clicked", sub {$fs_window->destroy;});
if ($last_dir) {
$fs_window->set_filename($last_dir);
}
$fs_window->show;
return 1;
}
sub addAttachFile {
my ($widget,$fswin,$clist)=@_;
my (@selection);
@selection = $fswin->file_list->selection();
if (!@selection) {
my $file = $fswin->get_filename();
if (!-f $file) {
&main::err_dialog(_("Selected file $file couldn't be attached!\n"));
return;
} else {
AppendAttachedFile($clist,$file);
}
} else {
$last_dir = $fswin->selection_text->get();
$last_dir =~ s/(.*)\://;
foreach(@selection) {
my $file = $fswin->file_list->get_text($_,0);
if ($file) {
$file = "$last_dir/$file";
AppendAttachedFile($clist,$file);
}
}
}
$fswin->destroy();
return;
}
sub AppendAttachedFile
{
my ($clist,$filename) = @_;
my $error = 0;
open FILE, $filename or $error=1;
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size)=stat FILE;
close FILE or $error=1;
if ($error==0){
$size=$size/1024;
$clist->append(($filename,(sprintf("%8.2f",$size)."kb")));
my @tmp = split('/',$filename);
my $num=scalar(@tmp);
$tmp[$num-1] = "";
if ($tmp[0] eq " ") { $tmp[0] = ""; }
$last_dir = join('/',@tmp);
} else {
&main::wr_debug("unable to open $filename.");
}
return 1;
}
sub deleteAttachFile {
my ($widget,$list)=@_;
if (defined $list->selection() && $list->selection()>=0){
$list->remove($list->selection());
}
return 1;
}
1;
syntax highlighted by Code2HTML, v. 0.9.1