=head1 NAME Mozilla::Plugin - embed perl into mozilla/netscape. =head1 SYNOPSIS use Mozilla::Plugin; =head1 DESCRIPTION sorry... =over 4 =cut package Mozilla::Plugin; use base Exporter; #use XSLoader; $VERSION = 0.12; @EXPORT = qw(); warn "in module [@ARGV]";#d# #XSLoader::load __PACKAGE__, $VERSION; use Data::Dumper; my $data; sub snd_cmd($) { $data = pack "NN", 0, ord($_[0]); } sub snd_i32($) { $data .= pack "N", $_[0]; } sub snd_blk($) { $data .= pack "NA*", length($_[0]), $_[0]; } sub snd_snd($) { substr ($data, 0, 4) = pack "N", length $data; length ($data) == syswrite $_[0], $data; } sub snd_dyn { length ($_[1]) == syswrite $_[0], $_[1]; } sub rcv_cmd { my $buf; 4 == sysread $_[0], $buf, 4 or exit; my $len = unpack "N", $buf; $len -= 4; $len == sysread $_[0], $buf, $len or die; $data = substr $buf, 4; substr $buf, 3, 1; } sub rcv_i32() { my $i32 = unpack "N", $data; $data = substr $data, 4; $i32; } sub rcv_blk() { my $len = unpack "N", $data; my $str = substr $data, 4, $len; $data = substr $data, 4 + $len; $str; } =item my $fh = server_fh The design of this module is event-based. When the plug-in starts (there is always just one interpreter) it spawns one perl interpreter which will immediately go into a even loop. If you want to use your own event loop (e.g. using the Gtk or Event modules) you need to register a file input handler on the filehandle returned by C that calls C whenever there is input pending on C. This will ensure proper operation of the plug-in. =item server_event Call this function whenever there is data available on the C. This function might not return. Due to this design (flaw?), sharing of different toolkits using this plug-in is difficult at best. Spawning a new perl interpreter for every plug-in is also not very viable, so in the future one might be able to specify a group on the embed statement (i.e. EMBED GROUP="gtk+"). =cut sub server_fh() { $FD1 } sub server_event() { my $cmd = rcv_cmd $FD1; if ($cmd eq "I") { rcv_i32 == 1 or die "protocol version mismatch\n"; ($IFACE, $OSNAME, $OSVERS) = (rcv_blk, rcv_blk, rcv_blk); } elsif ($cmd eq "+") { my ($objid, $type, $mode, $save, $argc) = (rcv_i32, rcv_blk, rcv_i32, rcv_blk, rcv_i32); my %args; while ($argc--) { my ($argn, $argv) = (rcv_blk, rcv_blk); $args{$argn} = $argv; } $_OBJ{$objid} = new Mozilla::Plugin type => $type, mode => $mode, save => $save, args => \%args; } elsif ($cmd eq "-") { my $objid = rcv_i32; snd_cmd "-"; my $save = (delete $_OBJ{$objid})->save; snd_i32 length $save; snd_dyn $FD1, $save; } else { die "unknown command '$cmd' received"; } } sub mainloop { server_event while 1; } sub _main { $LIBDIR = shift @ARGV; $IN_MOZILLA = 1; (shift @ARGV) =~ /^(\d+),(\d+)$/ or die "init arg error"; my ($fd1, $fd2) = ($1, $2); open $FD1, "+<&=$fd1"; binmode $FD1; open $FD2, "+<&=$fd2"; binmode $FD2; mainloop; } sub new { my $class = shift; bless { @_ }, $class; } sub set_window { warn "set_window: ".Dumper(\@_); } sub save { warn "save: ".Dumper(\@_); "[save]"; } sub DESTROY { warn "DESTROY"; } 1; =back =head1 BUGS =head1 SEE ALSO L. =head1 AUTHOR Marc Lehmann http://www.goof.com/pcg/marc/ =cut