ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Mozilla-Plugin/Plugin.pm
Revision: 1.7
Committed: Sun Feb 25 13:29:41 2001 UTC (23 years, 2 months ago) by root
Branch: MAIN
Changes since 1.6: +1 -4 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 $_OBJ{$objid} = $interface->new(
144 objid => $objid,
145 type => $type,
146 mode => $mode,
147 save => $save,
148 args => \%args,
149 );
150
151 } elsif ($cmd eq "-") {
152 my $objid = rcv_ptr;
153 my $save = (delete $_OBJ{$objid})->save;
154 snd_cmd "-";
155 snd_u32 length $save;
156 snd_snd and snd_dyn $save;
157
158 } elsif ($cmd eq "W") {
159 my $objid = rcv_ptr;
160 my %args = (
161 window => rcv_ptr,
162 x => rcv_i32,
163 y => rcv_i32,
164 w => rcv_i32,
165 h => rcv_i32,
166 );
167 if ($IFACE eq "UNIX") {
168 $args{window} = unpack "xxxxN", $args{window};
169 $args{ws_type} = rcv_i32;
170 $args{ws_depth} = rcv_u32;
171 }
172
173 $_OBJ{$objid}->set_window(\%args);
174
175 } else {
176 die "unknown command '$cmd' received";
177 }
178 }
179
180 sub mainloop {
181 server_event while 1;
182 }
183
184 sub init {
185 $interface = shift;
186
187 open FD, "+<&=$_[0]"; binmode FD;
188
189 $interface->mainloop;
190 }
191
192 sub new {
193 my $class = shift;
194 my $self = bless { @_ }, $class;
195 $self->{save} = $self->{save} ne ""
196 ? Storable::thaw $self->{save}
197 : {};
198 $self;
199 }
200
201 sub set_window {
202 my $self = shift;
203 my $new = shift;
204 print "window set calling with $new->{window}, $new->{w}, $new->{h} ($self->{window}\n";#d#
205 if ($self->{window}) {
206 if ($self->{window}{window} ne $new->{window}) {
207 $self->window_delete($self->{window});
208 } elsif ($self->{window}{w} != $new->{w}
209 or $self->{window}{h} != $new->{h}) {
210 $self->window_resize($new->{window}, $new->{w}, $new->{h});
211 }
212 $self->{window} = $new;
213 }
214
215 unless ($self->{window}) {
216 $self->{window} = $new;
217 print "window new calling with $new->{window}, $new->{w}, $new->{h}\n";#d#
218 $self->window_new($new->{window}, $new->{w}, $new->{h});
219 }
220 }
221
222 sub window_new {}
223 sub window_resize {}
224
225 sub window_delete {
226 my $self = shift;
227 delete $self->{window};
228 }
229
230 sub save {
231 my $self = shift;
232 $self->set_window(undef);
233 Storable::nfreeze $self->{save};
234 }
235
236 sub DESTROY {
237 #warn "DESTROY";#d#
238 }
239
240 1;
241
242 =back
243
244 =head1 BUGS
245
246 =head1 SEE ALSO
247
248 L<PApp>.
249
250 =head1 AUTHOR
251
252 Marc Lehmann <pcg@goof.com>
253 http://www.goof.com/pcg/marc/
254
255 =cut
256