File Coverage

blib/lib/Mac/OSA/Simple.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Mac::OSA::Simple;
2              
3 3     3   81221 use strict;
  3         8  
  3         124  
4 3         329 use vars qw(
5             $VERSION $REVISION @ISA
6             @EXPORT @EXPORT_OK %EXPORT_TAGS
7             %ScriptComponents
8 3     3   16 );
  3         7  
9              
10 3     3   16 use Carp;
  3         12  
  3         349  
11 3     3   16 use Exporter;
  3         5  
  3         106  
12              
13 3     3   17 use File::Basename;
  3         5  
  3         434  
14 3     3   1423 use MacPerl ();
  0            
  0            
15             use Mac::AppleEvents::Simple ':all';
16             use Mac::Components;
17             use Mac::Memory;
18             use Mac::OSA 1.03;
19             use Mac::Processes;
20             use Mac::Resources 1.03;
21              
22             @ISA = qw(Exporter);
23             @EXPORT = qw(
24             frontier applescript osa_script
25             compile_frontier compile_applescript compile_osa_script
26             load_osa_script %ScriptComponents
27             );
28             @EXPORT_OK = @Mac::OSA::EXPORT;
29             %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]);
30              
31             $REVISION = '$Id: Simple.pm,v 1.8 2003/11/09 18:38:21 pudge Exp $';
32             $VERSION = '1.09';
33              
34             tie %ScriptComponents, 'Mac::OSA::Simple::Components';
35              
36             sub frontier { _doscript('LAND', $_[0]) }
37             sub applescript { _doscript('ascr', $_[0]) }
38             sub osa_script { _doscript(@_[0, 1]) }
39              
40             sub compile_frontier { _compile_script('LAND', $_[0]) }
41             sub compile_applescript { _compile_script('ascr', $_[0]) }
42             sub compile_osa_script { _compile_script(@_[0, 1]) }
43              
44             sub load_osa_script { _load_script(@_[0, 1, 2]) }
45              
46             sub execute {
47             my($self) = @_;
48             my $value = my $return = '';
49              
50             $value = OSAExecute($self->{COMP}, $self->{ID}, 0, 0)
51             or _mydie() && return;
52              
53             if ($value) {
54             $return = OSADisplay($self->{COMP}, $value, typeChar, 0)
55             or _mydie() && return;
56             OSADispose($self->{COMP}, $value);
57             }
58              
59             $self->{RETURN} = $return && $return->isa('AEDesc')
60             ? $return->get : 1;
61              
62             AEDisposeDesc($return) if $return;
63              
64             return $self->{RETURN};
65             }
66              
67             { my $target; # define only once
68             sub call {
69             my($self, $cid, $eid, $args, $mode) = @_;
70             $mode = kOSAModeNull unless defined $mode;
71              
72             $target ||= { typeProcessSerialNumber() => kCurrentProcess() };
73              
74             my $format;
75             if (ref($args) eq 'ARRAY') { # no record support yet
76             $format = '[';
77             $format .= join(', ', map { 'TEXT(@)' } 1 .. @$args);
78             $format .= ']';
79             } elsif (! ref($args)) {
80             $format = 'TEXT(@)';
81             $args = [ $args ];
82             } else {
83             carp "Only scalars and lists supported in call()";
84             }
85              
86             my $event = build_event($cid, $eid, $target, "'----':$format", @$args);
87              
88             $event->{REP} = OSADoEvent(
89             $self->{COMP}, $event->{EVT}, $self->{ID}, $mode
90             ) or _mydie() && return;
91              
92             return $event->get;
93             }
94             }
95              
96             sub dispose {
97             my($self) = @_;
98              
99             if ($self->{ID} && $self->{COMP}) {
100             OSADispose($self->{COMP}, $self->{ID});
101             delete $self->{ID};
102             delete $self->{COMP};
103             }
104              
105             if ($self->{SCRIPT}) {
106             AEDisposeDesc($self->{SCRIPT});
107             delete $self->{SCRIPT};
108             }
109              
110             return 1;
111             }
112              
113             sub save {
114             my($self, $file, $resid, $name) = @_;
115              
116             my $scpt = $self->compiled or _mydie() && return;
117             $self->{FILETYPE} ||= $^O eq 'MacOS' ? 'rsrc' : 'data';
118              
119             my $res;
120             if (($self->{FILETYPE} && $self->{FILETYPE} eq 'rsrc') || (!$self->{FILETYPE} && $^O eq 'MacOS')) {
121             $resid = defined($resid) ? $resid : ($self->{RESID} || 128);
122             $name = defined($name) ? $name : 'MacPerl Script';
123              
124             unless ($res = FSpOpenResFile($file, 0)) {
125             FSpCreateResFile($file, 'ToyS', 'osas', 0) or _mydie() && return;
126             $res = FSpOpenResFile($file, 0) or _mydie() && return;
127             }
128              
129             my $foo = Get1Resource(kOSAScriptResourceType, $resid);
130             if (defined $foo) {
131             RemoveResource($foo) or _mydie() && return;
132             }
133              
134             AddResource($scpt, kOSAScriptResourceType, $resid, $name)
135             or _mydie() && return;
136              
137             UpdateResFile($res) or _mydie() && return;
138             CloseResFile($res);
139              
140             } else {
141             local $\;
142             open my $fh, '>', $file;
143             print $fh $scpt->get;
144             close $fh;
145             MacPerl::SetFileInfo('ToyS', 'osas', $file);
146             }
147              
148             return 1;
149             }
150              
151             sub source {
152             my($self, $source, $text) = @_;
153            
154             $source = OSAGetSource($self->{COMP}, $self->{ID}, typeChar)
155             or _mydie() && return;
156              
157             $self->{SOURCE} = $source && $source->isa('AEDesc')
158             ? $source->get : '';
159              
160             AEDisposeDesc($source);
161              
162             $self->{SOURCE} =~ s/\015/\n/g unless $^O eq 'MacOS';
163             $self->{SOURCE};
164             }
165              
166             sub compiled {
167             my($self, $script) = @_;
168              
169             $script = OSAStore($self->{COMP}, $self->{ID},
170             typeOSAGenericStorage, 0)
171             or _mydie() && return;
172              
173             push @{$self->{AEDESC}}, $script;
174              
175             return $script->data;
176             }
177              
178             sub _doscript {
179             my($c, $text) = @_;
180              
181             my $self = _compile_script($c, $text) or _mydie() && return;
182             my $return = $self->execute;
183             _mydie() && return unless defined $return;
184             $self->dispose;
185              
186             return $return;
187             }
188              
189             sub _load_script {
190             my($scpt, $resid, $xtra) = @_;
191              
192             my $c = kOSAGenericScriptingComponentSubtype;
193             my $self = bless {
194             COMP => $ScriptComponents{$c},
195             TYPE => $c
196             }, __PACKAGE__;
197              
198             my $res;
199             if (!ref $scpt) {
200             # we used to support three-arg format; use third arg if supplied
201             $resid = defined($xtra) ? $xtra
202             : defined($resid) && $resid != 1 ? $resid
203             : 128;
204             my $file = $scpt;
205             undef $scpt;
206              
207             if ($^O eq 'MacOS') {
208             $res = FSpOpenResFile($file, 0) or _mydie() && return;
209             $scpt = Get1Resource(kOSAScriptResourceType, $resid)
210             or _mydie() && return;
211             } else {
212             $res = FSpOpenResFile($file, 0);
213             $scpt = Get1Resource(kOSAScriptResourceType, $resid) if $res;
214              
215             if (!$scpt) {
216             open my $fh, '<', $file or _mydie() && return;
217             $scpt = new Handle do {
218             local $/;
219             <$fh>;
220             };
221             }
222             }
223              
224             if ($res) {
225             $self->{FILETYPE} = 'rsrc';
226             $self->{RESID} = $resid;
227             } else {
228             $self->{FILETYPE} = 'data';
229             $self->{RESID} = undef;
230             }
231             }
232              
233             my $desc = AECreateDesc(typeOSAGenericStorage, $scpt->get)
234             or _mydie() && return;
235              
236             $self->{ID} = OSALoad($self->{COMP}, $desc, 0)
237             or _mydie() && return;
238              
239             AEDisposeDesc($desc) if $desc;
240             CloseResFile($res) if $res;
241              
242             return $self;
243             }
244              
245             sub _compile_script {
246             my($c, $text) = @_;
247              
248             my $comp = $ScriptComponents{$c} or return;
249              
250             my $self = bless {
251             COMP => $comp,
252             SOURCE => $text,
253             TYPE => $c
254             }, __PACKAGE__;
255              
256             return $self->_compile;
257             }
258              
259             sub _compile {
260             my($self) = @_;
261              
262             $self->{SCRIPT} = AECreateDesc(typeChar, $self->{SOURCE})
263             or _mydie() && return;
264              
265             $self->{ID} = OSACompile($self->{COMP}, $self->{SCRIPT}, kOSAModeCompileIntoContext)
266             or _mydie() && return;
267              
268             return $self;
269             }
270              
271             sub _mydie {
272             # maybe do something here some day
273             1;
274             }
275              
276             sub DESTROY {
277             my($self) = @_;
278              
279             if (exists($self->{ID}) || exists($self->{SCRIPT})) {
280             $self->dispose;
281             }
282              
283             if ($self->{AEDESC}) {
284             for (@{$self->{AEDESC}}) {
285             AEDisposeDesc($_) if $_;
286             }
287             }
288              
289             undef $self;
290             }
291              
292             END {
293             foreach my $comp (keys %ScriptComponents) {
294             CloseComponent($ScriptComponents{$comp});
295             }
296             }
297              
298             package Mac::OSA::Simple::Components;
299              
300             BEGIN {
301             use Carp;
302             use Tie::Hash ();
303             use Mac::Components;
304             use Mac::OSA;
305             use vars qw(@ISA);
306             @ISA = qw(Tie::StdHash);
307             }
308              
309             # { # if we don't do this, we fail if we fork ... weird
310             # my $x = 0;
311             # 1 while ($x = FindNextComponent($x, kOSAComponentType));
312             # }
313             #
314             # sub FETCH {
315             # my($self, $comp) = @_;
316             # if ($self->{pid}) {
317             # if ($self->{pid} != $$) {
318             # delete @{$self}{keys %$self};
319             # }
320             # } else {
321             # $self->{pid} = $$;
322             # }
323              
324             sub FETCH {
325             my($self, $comp) = @_;
326              
327             my $c = $comp;
328             if ($comp eq kOSAGenericScriptingComponentSubtype) {
329             $c = 0;
330             $c++ while exists $self->{$c}; # get unique key
331             }
332              
333             if (!$self->{$c}) {
334             my $comp = OpenDefaultComponent(kOSAComponentType, $comp)
335             or Mac::OSA::Simple::_mydie() && return;
336             $self->{$c} = $comp;
337             }
338             $self->{$c};
339             }
340              
341             package Mac::OSA::Simple; # odd "fix" for AutoSplit
342              
343             1;
344              
345             __END__