ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Mozilla-Plugin/Plugin.pm
Revision: 1.6
Committed: Sun Feb 25 12:04:43 2001 UTC (23 years, 4 months ago) by root
Branch: MAIN
Changes since 1.5: +24 -15 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 Mozilla::Plugin - embed perl into mozilla/netscape.
4
5 =head1 SYNOPSIS
6
7 use Mozilla::Plugin;
8
9 =head1 DESCRIPTION
10
11 sorry...
12
13 =over 4
14
15 =cut
16
17 package Mozilla::Plugin;
18
19 use base Exporter;
20 use Storable;
21 #use XSLoader;
22
23 $VERSION = 0.01;
24 @EXPORT = qw();
25
26 #XSLoader::load __PACKAGE__, $VERSION;
27 use Data::Dumper;#d#
28
29 my $interface; # Mozilla::Plugin::xxx (design weakness)
30
31 my $data;
32
33 sub BIAS() { -2000000000 } # ugliest hack ever seen
34
35 sub snd_cmd($) {
36 $data = pack "NN", 0, ord($_[0]);
37 }
38
39 sub snd_ptr($) {
40 $data .= $_[0];
41 }
42
43 sub snd_u32($) {
44 $data .= pack "N", $_[0];
45 }
46
47 sub snd_i32($) {
48 $data .= pack "N", $_[0] - BIAS;
49 }
50
51 sub snd_blk($) {
52 $data .= pack "NA*", length($_[0]), $_[0];
53 }
54
55 sub snd_snd() {
56 substr ($data, 0, 4) = pack "N", length $data;
57 length ($data) == syswrite FD, $data;
58 }
59
60 sub snd_dyn($) {
61 length ($_[0]) == syswrite FD, $_[0];
62 }
63
64 sub rcv_cmd() {
65 my $buf;
66 4 == sysread FD, $buf, 4 or exit;
67 my $len = unpack "N", $buf;
68 $len -= 4;
69 $len == sysread FD, $buf, $len or die;
70
71 $data = substr $buf, 4;
72
73 substr $buf, 3, 1;
74 }
75
76 sub rcv_ptr() {
77 my $ptr = substr $data, 0, 8;
78 $data = substr $data, 8;
79 $ptr;
80 }
81
82 sub rcv_u32() {
83 my $u32 = unpack "N", $data;
84 $data = substr $data, 4;
85 $u32;
86 }
87
88 sub rcv_i32() {
89 my $i32 = BIAS + unpack "N", $data;
90 $data = substr $data, 4;
91 $i32;
92 }
93
94 sub rcv_blk() {
95 my $len = unpack "N", $data;
96 my $str = substr $data, 4, $len;
97 $data = substr $data, 4 + $len;
98 $str;
99 }
100
101 =item my $fh = server_fh
102
103 The design of this module is event-based. When the plug-in starts (there
104 is always just one interpreter) it spawns one perl interpreter which
105 will immediately go into a even loop. If you want to use your own event
106 loop (e.g. using the Gtk or Event modules) you need to register a file
107 input handler on the filehandle returned by C<server_fh> that calls
108 C<server_event> whenever there is input pending on C<server_fh>. This will
109 ensure proper operation of the plug-in.
110
111 =item server_event
112
113 Call this function whenever there is data available on the C<server_fh>. This function
114 might not return.
115
116 Due to this design (flaw?), sharing of different toolkits using this
117 plug-in is difficult at best. Spawning a new perl interpreter for every
118 plug-in is also not very viable, so in the future one might be able to
119 specify a group on the embed statement (i.e. EMBED GROUP="gtk+").
120
121 =cut
122
123 sub server_fh() { \*FD }
124
125 sub server_event() {
126 my $cmd = rcv_cmd;
127
128 warn "cmd<$cmd>\n";#d#
129
130 if ($cmd eq "I") {
131 rcv_u32 == 1 or die "protocol version mismatch\n";
132 ($IFACE, $OSNAME, $OSVERS) = (rcv_blk, rcv_blk, rcv_blk);
133
134 } elsif ($cmd eq "+") {
135 my ($objid, $type, $mode, $save, $argc)
136 = (rcv_ptr, rcv_blk, rcv_u32, rcv_blk, rcv_u32);
137 my %args;
138 while ($argc--) {
139 my ($argn, $argv) = (rcv_blk, rcv_blk);
140 $args{$argn} = $argv;
141 }
142
143 warn "new obj $objid\n";#d#
144 $_OBJ{$objid} = $interface->new(
145 objid => $objid,
146 type => $type,
147 mode => $mode,
148 save => $save,
149 args => \%args,
150 );
151
152 } elsif ($cmd eq "-") {
153 my $objid = rcv_ptr;
154 my $save = (delete $_OBJ{$objid})->save;
155 snd_cmd "-";
156 snd_u32 length $save;
157 snd_snd and snd_dyn $save;
158
159 } elsif ($cmd eq "W") {
160 my $objid = rcv_ptr;
161 my %args = (
162 window => rcv_ptr,
163 x => rcv_i32,
164 y => rcv_i32,
165 w => rcv_i32,
166 h => rcv_i32,
167 );
168 if ($IFACE eq "UNIX") {
169 $args{window} = unpack "xxxxN", $args{window};
170 $args{ws_type} = rcv_i32;
171 $args{ws_depth} = rcv_u32;
172 }
173
174 $_OBJ{$objid}->set_window(\%args);
175
176 } else {
177 die "unknown command '$cmd' received";
178 }
179 }
180
181 sub mainloop {
182 server_event while 1;
183 }
184
185 sub init {
186 $interface = shift;
187
188 open FD, "+<&=$_[0]"; binmode FD;
189
190 $interface->mainloop;
191 }
192
193 sub new {
194 my $class = shift;
195 my $self = bless { @_ }, $class;
196 $self->{save} = $self->{save} ne ""
197 ? Storable::thaw $self->{save}
198 : {};
199 warn "new: ".Dumper($self);
200 $self;
201 }
202
203 sub set_window {
204 my $self = shift;
205 my $new = shift;
206 print "window set calling with $new->{window}, $new->{w}, $new->{h} ($self->{window}\n";#d#
207 if ($self->{window}) {
208 if ($self->{window}{window} ne $new->{window}) {
209 $self->window_delete($self->{window});
210 } elsif ($self->{window}{w} != $new->{w}
211 or $self->{window}{h} != $new->{h}) {
212 $self->window_resize($new->{window}, $new->{w}, $new->{h});
213 }
214 $self->{window} = $new;
215 }
216
217 unless ($self->{window}) {
218 $self->{window} = $new;
219 print "window new calling with $new->{window}, $new->{w}, $new->{h}\n";#d#
220 $self->window_new($new->{window}, $new->{w}, $new->{h});
221 }
222 warn "set_window: ".Dumper($self);
223 }
224
225 sub window_new {}
226 sub window_resize {}
227
228 sub window_delete {
229 my $self = shift;
230 delete $self->{window};
231 }
232
233 sub save {
234 my $self = shift;
235 $self->set_window(undef);
236 Storable::nfreeze $self->{save};
237 }
238
239 sub DESTROY {
240 warn "DESTROY";
241 }
242
243 1;
244
245 =back
246
247 =head1 BUGS
248
249 =head1 SEE ALSO
250
251 L<PApp>.
252
253 =head1 AUTHOR
254
255 Marc Lehmann <pcg@goof.com>
256 http://www.goof.com/pcg/marc/
257
258 =cut
259