# $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 = ; $/ = "\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 () { $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 = ; 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 (){ $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 = ; 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;$tmpappend((@$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;