+
+sub send_dx_spot
+{
+ my $self = shift;
+ my $line = shift;
+ my @dxchan = DXChannel::get_all();
+ my $dxchan;
+ my $pc11;
+
+ # send it if it isn't the except list and isn't isolated and still has a hop count
+ # taking into account filtering and so on
+ foreach $dxchan (@dxchan) {
+ next if $dxchan == $main::me;
+ next if $dxchan == $self && $self->is_node;
+ if ($line =~ /PC61/ && !($dxchan->is_spider || $dxchan->is_user)) {
+ unless ($pc11) {
+ my @f = split /\^/, $line;
+ $pc11 = join '^', 'PC11', @f[1..7,9];
+ }
+ $dxchan->dx_spot($pc11, $self->{isolate}, @_, $self->{call});
+ } else {
+ $dxchan->dx_spot($line, $self->{isolate}, @_, $self->{call});
+ }
+ }
+}
+
+sub dx_spot
+{
+ my $self = shift;
+ my $line = shift;
+ my $isolate = shift;
+ my ($filter, $hops);
+
+ if ($self->{spotsfilter}) {
+ ($filter, $hops) = $self->{spotsfilter}->it(@_);
+ return unless $filter;
+ }
+ send_prot_line($self, $filter, $hops, $isolate, $line);
+}
+
+sub send_prot_line
+{
+ my ($self, $filter, $hops, $isolate, $line) = @_;
+ my $routeit;
+
+
+ if ($hops) {
+ $routeit = $line;
+ $routeit =~ s/\^H\d+\^\~$/\^H$hops\^\~/;
+ } else {
+ $routeit = adjust_hops($self, $line); # adjust its hop count by node name
+ return unless $routeit;
+ }
+ if ($filter) {
+ $self->send($routeit);
+ } else {
+ $self->send($routeit) unless $self->{isolate} || $isolate;
+ }
+}
+
+
+sub send_wwv_spot
+{
+ my $self = shift;
+ my $line = shift;
+ my @dxchan = DXChannel::get_all();
+ my $dxchan;
+ my @dxcc = ((Prefix::cty_data($_[6]))[0..2], (Prefix::cty_data($_[7]))[0..2]);
+
+ # send it if it isn't the except list and isn't isolated and still has a hop count
+ # taking into account filtering and so on
+ foreach $dxchan (@dxchan) {
+ next if $dxchan == $main::me;
+ next if $dxchan == $self && $self->is_node;
+ my $routeit;
+ my ($filter, $hops);
+
+ $dxchan->wwv($line, $self->{isolate}, @_, $self->{call}, @dxcc);
+ }
+}
+
+sub wwv
+{
+ my $self = shift;
+ my $line = shift;
+ my $isolate = shift;
+ my ($filter, $hops);
+
+ if ($self->{wwvfilter}) {
+ ($filter, $hops) = $self->{wwvfilter}->it(@_[7..$#_]);
+ return unless $filter;
+ }
+ send_prot_line($self, $filter, $hops, $isolate, $line)
+}
+
+sub send_wcy_spot
+{
+ my $self = shift;
+ my $line = shift;
+ my @dxchan = DXChannel::get_all();
+ my $dxchan;
+ my @dxcc = ((Prefix::cty_data($_[10]))[0..2], (Prefix::cty_data($_[11]))[0..2]);
+
+ # send it if it isn't the except list and isn't isolated and still has a hop count
+ # taking into account filtering and so on
+ foreach $dxchan (@dxchan) {
+ next if $dxchan == $main::me;
+ next if $dxchan == $self;
+
+ $dxchan->wcy($line, $self->{isolate}, @_, $self->{call}, @dxcc);
+ }
+}
+
+sub wcy
+{
+ my $self = shift;
+ my $line = shift;
+ my $isolate = shift;
+ my ($filter, $hops);
+
+ if ($self->{wcyfilter}) {
+ ($filter, $hops) = $self->{wcyfilter}->it(@_);
+ return unless $filter;
+ }
+ send_prot_line($self, $filter, $hops, $isolate, $line) if $self->is_clx || $self->is_spider || $self->is_dxnet;
+}
+
+# send an announce
+sub send_announce
+{
+ my $self = shift;
+ my $from_pc9x = shift;
+ my $line = shift;
+ my @dxchan = DXChannel::get_all();
+ my $dxchan;
+ my $target = $_[6];
+ my $to = 'To ';
+ my $text = unpad($_[2]);
+ my $from = $_[0];
+
+ if ($_[3] eq '*') { # sysops
+ $target = "SYSOP";
+ } elsif ($_[3] gt ' ') { # speciality list handling
+ my ($name) = split /\./, $_[3];
+ $target = "$name"; # put the rest in later (if bothered)
+ }
+
+ if ($_[5] eq '1') {
+ $target = "WX";
+ $to = '';
+ }
+ $target = "ALL" if !$target;
+
+
+ # obtain country codes etc
+ my @a = Prefix::cty_data($from);
+ my @b = Prefix::cty_data($_[4]);
+ if ($self->{inannfilter}) {
+ my ($filter, $hops) =
+ $self->{inannfilter}->it(@_, $self->{call},
+ @a[0..2],
+ @b[0..2], $a[3], $b[3]);
+ unless ($filter) {
+ dbg("PCPROT: Rejected by input announce filter") if isdbg('chanerr');
+ return;
+ }
+ }
+
+ # the sysop ('*') thing is an attempt to minimise the damage caused by non-updated PC93 generators
+ if (AnnTalk::dup($from, $target, $_[2]) || ($_[3] eq '*' && AnnTalk::dup($from, 'ALL', $_[2]))) {
+ my $dxchan = DXChannel::get($from);
+ if ($self == $main::me && $dxchan && $dxchan->is_user) {
+ if ($dxchan->priv < 5) {
+ $dxchan->send($dxchan->msg('dup'));
+ return;
+ }
+ } else {
+ dbg("PCPROT: Duplicate Announce ignored") if isdbg('chanerr');
+ return;
+ }
+ }
+
+ Log('ann', $target, $from, $text);
+
+ # send it if it isn't the except list and isn't isolated and still has a hop count
+ # taking into account filtering and so on
+ foreach $dxchan (@dxchan) {
+ next if $dxchan == $main::me;
+ next if $dxchan == $self && $self->is_node;
+ next if $from_pc9x && $dxchan->{do_pc9x};
+ next if $target eq 'LOCAL' && $dxchan->is_node;
+ $dxchan->announce($line, $self->{isolate}, $to, $target, $text, @_, $self->{call},
+ @a[0..2], @b[0..2]);
+ }
+}
+
+my $msgid = int rand(1000);
+
+sub nextchatmsgid
+{
+ $msgid++;
+ $msgid = 1 if $msgid > 999;
+ return $msgid;
+}
+
+# send a chat line
+sub send_chat
+{
+ my $self = shift;
+ my $from_pc9x = shift;
+ my $line = shift;
+ my @dxchan = DXChannel::get_all();
+ my $dxchan;
+ my $target = $_[3];
+ my $text = unpad($_[2]);
+ my $ak1a_line;
+ my $from = $_[0];
+
+ # munge the group and recast the line if required
+ if ($target =~ s/\.LST$//) {
+ $ak1a_line = $line;
+ }
+
+ # obtain country codes etc
+ my @a = Prefix::cty_data($from);
+ my @b = Prefix::cty_data($_[4]);
+ if ($self->{inannfilter}) {
+ my ($filter, $hops) =
+ $self->{inannfilter}->it(@_, $self->{call},
+ @a[0..2],
+ @b[0..2], $a[3], $b[3]);
+ unless ($filter) {
+ dbg("PCPROT: Rejected by input announce filter") if isdbg('chanerr');
+ return;
+ }
+ }
+
+ if (AnnTalk::dup($from, $target, $_[2], $main::systime + $chatdupeage)) {
+ my $dxchan = DXChannel::get($from);
+ if ($self == $main::me && $dxchan && $dxchan->is_user) {
+ if ($dxchan->priv < 5) {
+ $dxchan->send($dxchan->msg('dup'));
+ return;
+ }
+ } else {
+ dbg("PCPROT: Duplicate Announce ignored") if isdbg('chanerr');
+ return;
+ }
+ }
+
+
+ Log('chat', $target, $from, $text);
+
+ # send it if it isn't the except list and isn't isolated and still has a hop count
+ # taking into account filtering and so on
+ foreach $dxchan (@dxchan) {
+ if ($dxchan->is_node) {
+ next if $dxchan == $main::me;
+ next if $dxchan == $self;
+ next if $from_pc9x && $dxchan->do_pc9x;
+ next unless $dxchan->is_spider && $dxchan->do_pc9x;
+ next if $target eq 'LOCAL';
+ }
+
+ $dxchan->chat($line, $self->{isolate}, $target, $_[1],
+ $text, @_, $self->{call}, @a[0..2], @b[0..2]);
+ }
+}
+
+sub announce
+{
+ my $self = shift;
+ my $line = shift;
+ my $isolate = shift;
+ my $to = shift;
+ my $target = shift;
+ my $text = shift;
+ my ($filter, $hops);
+
+ if ($self->{annfilter}) {
+ ($filter, $hops) = $self->{annfilter}->it(@_);
+ return unless $filter;
+ }
+ send_prot_line($self, $filter, $hops, $isolate, $line) unless $_[1] eq $main::mycall;
+}
+
+sub chat
+{
+ my $self = shift;
+ my $line = shift;
+ my $isolate = shift;
+ my $to = shift;
+ my $target = shift;
+ my $text = shift;
+ my ($filter, $hops);
+
+ if ($self->{annfilter}) {
+ ($filter, $hops) = $self->{annfilter}->it(@_);
+ return unless $filter;
+ }
+ if (($self->is_spider || $self->is_ak1a) && $_[1] ne $main::mycall) {
+ send_prot_line($self, $filter, $hops, $isolate, $line);
+ }
+}
+
+