File Coverage

blib/lib/Tcl.pm
Criterion Covered Total %
statement 13 229 5.6
branch 0 84 0.0
condition 0 40 0.0
subroutine 5 28 17.8
pod n/a
total 18 381 4.7


line stmt bran cond sub pod time code
1             package Tcl;
2              
3             $Tcl::VERSION = '1.02';
4             $Tcl::STACK_TRACE = 1;
5              
6             =head1 NAME
7              
8             Tcl - Tcl extension module for Perl
9              
10             =head1 SYNOPSIS
11              
12             use Tcl;
13              
14             $interp = Tcl->new;
15             $interp->Eval('puts "Hello world"');
16              
17             =head1 DESCRIPTION
18              
19             The Tcl extension module gives access to the Tcl library with
20             functionality and interface similar to the C functions of Tcl.
21             In other words, you can
22              
23             =over
24              
25             =item *
26              
27             create Tcl interpreters
28              
29             The Tcl interpreters so created are Perl objects whose destructors
30             delete the interpreters cleanly when appropriate.
31              
32             =item *
33              
34             execute Tcl code in an interpreter
35              
36             The code can come from strings, files or Perl filehandles.
37              
38             =item *
39              
40             bind in new Tcl procedures
41              
42             The new procedures can be either C code (with addresses presumably
43             obtained using I and I) or Perl subroutines
44             (by name, reference or as anonymous subs). The (optional) deleteProc
45             callback in the latter case is another perl subroutine which is called
46             when the command is explicitly deleted by name or else when the
47             destructor for the interpreter object is explicitly or implicitly called.
48              
49             =item *
50              
51             Manipulate the result field of a Tcl interpreter
52              
53             =item *
54              
55             Set and get values of variables in a Tcl interpreter
56              
57             =item *
58              
59             Tie perl variables to variables in a Tcl interpreter
60              
61             The variables can be either scalars or hashes.
62              
63             =back
64              
65             =head2 Methods in class Tcl
66              
67             To create a new Tcl interpreter, use
68              
69             $interp = Tcl->new;
70              
71             The following methods and routines can then be used on the Perl object
72             returned (the object argument omitted in each case).
73              
74             =over
75              
76             =item $interp->Init ()
77              
78             Invoke I on the interpeter.
79              
80             =item $interp->Eval (STRING, FLAGS)
81              
82             Evaluate script STRING in the interpreter. If the script returns
83             successfully (TCL_OK) then the Perl return value corresponds to Tcl
84             interpreter's result otherwise a I exception is raised with the $@
85             variable corresponding to Tcl's interpreter result object. In each case,
86             I means that if the method is called in scalar context then
87             the string result is returned but if the method is called in list context
88             then the result is split as a Tcl list and returned as a Perl list.
89             The FLAGS field is optional and can be a bitwise OR of the constants
90             Tcl::EVAL_GLOBAL or Tcl::EVAL_DIRECT.
91              
92             =item $interp->GlobalEval (STRING)
93              
94             REMOVED. Evalulate script STRING at global level.
95             Call I(STRING, Tcl::EVAL_GLOBAL) instead.
96              
97             =item $interp->EvalFile (FILENAME)
98              
99             Evaluate the contents of the file with name FILENAME. Otherwise, the
100             same as I() above.
101              
102             =item $interp->EvalFileHandle (FILEHANDLE)
103              
104             Evaluate the contents of the Perl filehandle FILEHANDLE. Otherwise, the
105             same as I() above. Useful when using the filehandle DATA to tack
106             on a Tcl script following an __END__ token.
107              
108             =item $interp->call (PROC, ARG, ...)
109              
110             Looks up procedure PROC in the interpreter and invokes it using Tcl's eval
111             semantics that does command tracing and will use the ::unknown (AUTOLOAD)
112             mechanism. The arguments (ARG, ...) are not passed through the Tcl parser.
113             For example, spaces embedded in any ARG will not cause it to be split into
114             two Tcl arguments before being passed to PROC.
115              
116             Before invoking procedure PROC special processing is performed on ARG list:
117              
118             1. All subroutine references within ARG will be substituted with Tcl name
119             which is responsible to invoke this subroutine. This Tcl name will be
120             created using CreateCommand subroutine (see below).
121              
122             2. All references to scalars will be substituted with names of Tcl variables
123             transformed appropriately.
124              
125             These first two items allows to write and expect it to work properly such
126             code as:
127              
128             my $r = 'aaaa';
129             button(".d", -textvariable => \$r, -command=>sub {$r++});
130              
131             3. All references to hashes will be substituted with names of Tcl array
132             variables transformed appropriately.
133              
134             4. As a special case, there is a mechanism to deal with Tk's special event
135             variables (they are mentioned as '%x', '%y' and so on throughout Tcl).
136             When creating a subroutine reference that uses such variables, you must
137             declare the desired variables using Tcl::Ev as the first argument to the
138             subroutine. Example:
139              
140             sub textPaste {
141             my ($x,$y,$w) = @_;
142             widget($w)->insert("\@$x,$y", $interp->Eval('selection get'));
143             }
144             $widget->bind('<2>', [\&textPaste, Tcl::Ev('%x', '%y'), $widget] );
145              
146             =item $interp->return_ref (NAME)
147              
148             returns a reference corresponding to NAME, which was associated during
149             previously called C<< $interpnt->call(...) >> preprocessing. As a typical
150             example this could be variable associated with a widget.
151              
152             =item $interp->delete_ref (NAME)
153              
154             deletes and returns a reference corresponding to NAME, which was associated
155             during previously called C<< $interpnt->call(...) >> preprocessing.
156              
157             =item $interp->icall (PROC, ARG, ...)
158              
159             Looks up procedure PROC in the interpreter and invokes it using Tcl's eval
160             semantics that does command tracing and will use the ::unknown (AUTOLOAD)
161             mechanism. The arguments (ARG, ...) are not passed through the Tcl parser.
162             For example, spaces embedded in any ARG will not cause it to be split into
163             two Tcl arguments before being passed to PROC.
164              
165             This is the lower-level procedure that the 'call' method uses. Arguments
166             are converted efficiently from Perl SVs to Tcl_Objs. A Perl AV array
167             becomes a Tcl_ListObj, an SvIV becomes a Tcl_IntObj, etc. The reverse
168             conversion is done to the result.
169              
170             =item $interp->invoke (PROC, ARG, ...)
171              
172             Looks up procedure PROC in the interpreter and invokes it directly with
173             arguments (ARG, ...) without passing through the Tcl parser. For example,
174             spaces embedded in any ARG will not cause it to be split into two Tcl
175             arguments before being passed to PROC. This differs from icall/call in
176             that it directly invokes the command name without allowing for command
177             tracing or making use of Tcl's unknown (AUTOLOAD) mechanism. If the
178             command does not already exist in the interpreter, and error will be
179             thrown.
180              
181             Arguments are converted efficiently from Perl SVs to Tcl_Objs. A Perl AV
182             array becomes a Tcl_ListObj, an SvIV becomes a Tcl_IntObj, etc. The
183             reverse conversion is done to the result.
184              
185             =item Tcl::Ev (FIELD, ...)
186              
187             Used to declare %-substitution variables of interest to a subroutine
188             callback. FIELD is expected to be of the form "%#" where # is a single
189             character, and multiple fields may be specified. Returns a blessed object
190             that the 'call' method will recognize when it is passed as the first
191             argument to a subroutine in a callback. See description of 'call' method
192             for details.
193              
194             =item $interp->result ()
195              
196             Returns the current Tcl interpreter result. List v. scalar context is
197             handled as in I() above.
198              
199             =item $interp->CreateCommand (CMDNAME, CMDPROC, CLIENTDATA, DELETEPROC, FLAGS)
200              
201             Binds a new procedure named CMDNAME into the interpreter. The
202             CLIENTDATA and DELETEPROC arguments are optional. There are two cases:
203              
204             (1) CMDPROC is the address of a C function
205              
206             (presumably obtained using I and I. In this case
207             CLIENTDATA and DELETEPROC are taken to be raw data of the ClientData and
208             deleteProc field presumably obtained in a similar way.
209              
210             (2) CMDPROC is a Perl subroutine
211              
212             (either a sub name, a sub reference or an anonymous sub). In this case
213             CLIENTDATA can be any perl scalar (e.g. a ref to some other data) and
214             DELETEPROC must be a perl sub too. When CMDNAME is invoked in the Tcl
215             interpeter, the arguments passed to the Perl sub CMDPROC are
216              
217             (CLIENTDATA, INTERP, LIST)
218              
219             where INTERP is a Perl object for the Tcl interpreter which called out
220             and LIST is a Perl list of the arguments CMDNAME was called with.
221             If the 1-bit of FLAGS is set then the 3 first arguments on the call
222             to CMDPROC are suppressed.
223             As usual in Tcl, the first element of the list is CMDNAME itself.
224             When CMDNAME is deleted from the interpreter (either explicitly with
225             I or because the destructor for the interpeter object
226             is called), it is passed the single argument CLIENTDATA.
227              
228             =item $interp->DeleteCommand (CMDNAME)
229              
230             Deletes command CMDNAME from the interpreter. If the command was created
231             with a DELETEPROC (see I above), then it is invoked at
232             this point. When a Tcl interpreter object is destroyed either explicitly
233             or implicitly, an implicit I happens on all its currently
234             registered commands.
235              
236             =item $interp->SetResult (STRING)
237              
238             Sets Tcl interpreter result to STRING.
239              
240             =item $interp->AppendResult (LIST)
241              
242             Appends each element of LIST to Tcl's interpreter result object.
243              
244             =item $interp->AppendElement (STRING)
245              
246             Appends STRING to Tcl interpreter result object as an extra Tcl list element.
247              
248             =item $interp->ResetResult ()
249              
250             Resets Tcl interpreter result.
251              
252             =item $interp->SplitList (STRING)
253              
254             Splits STRING as a Tcl list. Returns a Perl list or the empty list if
255             there was an error (i.e. STRING was not a properly formed Tcl list).
256             In the latter case, the error message is left in Tcl's interpreter
257             result object.
258              
259             =item $interp->SetVar (VARNAME, VALUE, FLAGS)
260              
261             The FLAGS field is optional. Sets Tcl variable VARNAME in the
262             interpreter to VALUE. The FLAGS argument is the usual Tcl one and
263             can be a bitwise OR of the constants Tcl::GLOBAL_ONLY,
264             Tcl::LEAVE_ERR_MSG, Tcl::APPEND_VALUE, Tcl::LIST_ELEMENT.
265              
266             =item $interp->SetVar2 (VARNAME1, VARNAME2, VALUE, FLAGS)
267              
268             Sets the element VARNAME1(VARNAME2) of a Tcl array to VALUE. The optional
269             argument FLAGS behaves as in I above.
270              
271             =item $interp->GetVar (VARNAME, FLAGS)
272              
273             Returns the value of Tcl variable VARNAME. The optional argument FLAGS
274             behaves as in I above.
275              
276             =item $interp->GetVar2 (VARNAME1, VARNAME2, FLAGS)
277              
278             Returns the value of the element VARNAME1(VARNAME2) of a Tcl array.
279             The optional argument FLAGS behaves as in I above.
280              
281             =item $interp->UnsetVar (VARNAME, FLAGS)
282              
283             Unsets Tcl variable VARNAME. The optional argument FLAGS
284             behaves as in I above.
285              
286             =item $interp->UnsetVar2 (VARNAME1, VARNAME2, FLAGS)
287              
288             Unsets the element VARNAME1(VARNAME2) of a Tcl array.
289             The optional argument FLAGS behaves as in I above.
290              
291             =back
292              
293             =head2 Linking Perl and Tcl variables
294              
295             You can I a Perl variable (scalar or hash) into class Tcl::Var
296             so that changes to a Tcl variable automatically "change" the value
297             of the Perl variable. In fact, as usual with Perl tied variables,
298             its current value is just fetched from the Tcl variable when needed
299             and setting the Perl variable triggers the setting of the Tcl variable.
300              
301             To tie a Perl scalar I<$scalar> to the Tcl variable I in
302             interpreter I<$interp> with optional flags I<$flags> (see I
303             above), use
304              
305             tie $scalar, "Tcl::Var", $interp, "tclscalar", $flags;
306              
307             Omit the I<$flags> argument if not wanted.
308              
309             To tie a Perl hash I<%hash> to the Tcl array variable I in
310             interpreter I<$interp> with optional flags I<$flags>
311             (see I above), use
312              
313             tie %hash, "Tcl::Var", $interp, "array", $flags;
314              
315             Omit the I<$flags> argument if not wanted. Any alteration to Perl
316             variable I<$hash{"key"}> affects the Tcl variable I
317             and I.
318              
319             =head2 Accessing Perl from within Tcl
320              
321             After creation of Tcl interpreter, in addition to evaluation of Tcl/Tk
322             commands within Perl, other way round also instantiated. Within a special
323             namespace C< ::perl > following objects are created:
324              
325             ::perl::Eval
326              
327             So it is possible to use Perl objects from within Tcl.
328              
329             =head2 Moving Tcl/Tk around with Tcl.pm
330              
331             NOTE: explanations below is for developers managing Tcl/Tk installations
332             itself, users should skip this section.
333              
334             In order to create Tcl/Tk application with this module, you need to make
335             sure that Tcl/Tk is available within visibility of this module. There are
336             many ways to achieve this, varying on ease of starting things up and
337             providing flexible moveable archived files.
338              
339             Following list enumerates them, in order of increased possibility to change
340             location.
341              
342             =over
343              
344             =item *
345              
346             First method
347              
348             Install Tcl/Tk first, then install Perl module Tcl, so installed Tcl/Tk will
349             be used. This is most normal approach, and no care of Tcl/Tk distribution is
350             taken on Perl side (this is done on Tcl/Tk side)
351              
352             =item *
353              
354             Second method
355              
356             Copy installed Tcl/Tk binaries to some location, then install Perl module Tcl
357             with a special action to make Tcl.pm know of this location. This approach
358             makes sure that only chosen Tcl installation is used.
359              
360             =item *
361              
362             Third method
363              
364             During compiling Tcl Perl module, Tcl/Tk could be statically linked into
365             module's shared library and all other files zipped into a single archive, so
366             each file extracted when needed.
367              
368             To link Tcl/Tk binaries, prepare their libraries and then instruct Makefile.PL
369             to use these libraries in a link stage.
370             (TODO provide better detailed description)
371              
372             =back
373              
374             =cut
375              
376 11     11   35470 use strict;
  11         22  
  11         27776  
377              
378             our $DL_PATH;
379             unless (defined $DL_PATH) {
380             $DL_PATH = $ENV{PERL_TCL_DL_PATH} || $ENV{PERL_TCL_DLL} || "";
381             }
382              
383             unless ($DL_PATH) {
384             require Config;
385             for my $inc (@INC) {
386             my $tkkit = "$inc/auto/Tcl/tkkit.$Config::Config{so}";
387             if (-f $tkkit) {
388             $DL_PATH = $tkkit;
389             last;
390             }
391             }
392             }
393              
394              
395             my $path;
396             if ($^O eq 'darwin') {
397             # Darwin 7.9 (OS X 10.3) requires the path of the executable be prepended
398             # for #! scripts to operate properly (avoids RegisterProcess error).
399             require Config;
400             unless (grep { $_ eq $Config::Config{binexp} } split $Config::Config{path_sep}, $ENV{PATH}) {
401             $path = join $Config::Config{path_sep}, $Config::Config{binexp}, $ENV{PATH};
402             }
403             }
404              
405             require XSLoader;
406              
407             {
408             local $ENV{PATH} = $path if $path;
409             XSLoader::load('Tcl', $Tcl::VERSION);
410             }
411              
412             sub new {
413 0     0     my $int = _new(@_);
414 0           return $int;
415             }
416              
417             eval {
418             require "Tclaux.pm";
419             };
420              
421             END {
422 11     11   80 Tcl::_Finalize();
423             }
424              
425             #TODO make better wording here
426             # %anon_refs keeps track of anonymous subroutines that were created with
427             # "CreateCommand" method during process of transformation of arguments for
428             # "call" and other stuff such as scalar refs and so on.
429             # (TODO -- find out how to check for refcounting and proper releasing of
430             # resources)
431              
432             my %anon_refs;
433              
434             # %widget_refs is an array to hold refs that were created when working with
435             # widget the point is - it's not dangerous to delete more than needed, because
436             # those will be re-created at the very next time they needed.
437             # however when widget goes away, it is good to delete anything that comes
438             # into mind with that widget
439             my %widget_refs;
440             my $current_widget = '';
441 0     0     sub _current_refs_widget {$current_widget=shift}
442              
443             # Subroutine "call" preprocess the arguments for special cases
444             # and then calls "icall" (implemented in Tcl.xs), which invokes
445             # the command in Tcl.
446             sub call {
447 0     0     my $interp = shift;
448 0           my @args = @_;
449              
450             # Process arguments looking for special cases
451 0           for (my $argcnt=0; $argcnt<=$#args; $argcnt++) {
452 0           my $arg = $args[$argcnt];
453 0           my $ref = ref($arg);
454 0 0         next unless $ref;
455 0 0 0       if ($ref eq 'CODE') {
    0 0        
    0 0        
    0          
    0          
    0          
    0          
456             # We have been passed something like \&subroutine
457             # Create a proc in Tcl that invokes this subroutine (no args)
458 0           $args[$argcnt] = $interp->create_tcl_sub($arg);
459 0           $widget_refs{$current_widget}->{$args[$argcnt]}++;
460             }
461             elsif ($ref =~ /^Tcl::Tk::Widget\b/) {
462             # We have been passed a widget reference.
463             # Convert to its Tk pathname (eg, .top1.fr1.btn2)
464 0           $args[$argcnt] = $arg->path;
465 0 0         $current_widget = $args[$argcnt] if $argcnt==0;
466             }
467             elsif ($ref eq 'SCALAR') {
468             # We have been passed something like \$scalar
469             # Create a tied variable between Tcl and Perl.
470              
471             # stringify scalar ref, create in ::perl namespace on Tcl side
472             # This will be SCALAR(0xXXXXXX) - leave it to become part of a
473             # Tcl array.
474 0           my $nm = "::perl::$arg";
475             #$nm =~ s/\W/_/g; # remove () from stringified name
476 0 0         unless (exists $anon_refs{$nm}) {
477 0           $widget_refs{$current_widget}->{$nm}++;
478 0           $anon_refs{$nm} = $arg;
479 0           my $s = $$arg;
480 0           tie $$arg, 'Tcl::Var', $interp, $nm;
481 0 0         $s = '' unless defined $s;
482 0           $$arg = $s;
483             }
484 0           $args[$argcnt] = $nm; # ... and substitute its name
485             }
486             elsif ($ref eq 'HASH') {
487             # We have been passed something like \%hash
488             # Create a tied variable between Tcl and Perl.
489              
490             # stringify hash ref, create in ::perl namespace on Tcl side
491             # This will be HASH(0xXXXXXX) - leave it to become part of a
492             # Tcl array.
493 0           my $nm = $arg;
494 0           $nm =~ s/\W/_/g; # remove () from stringified name
495 0           $nm = "::perl::$nm";
496 0 0         unless (exists $anon_refs{$nm}) {
497 0           $widget_refs{$current_widget}->{$nm}++;
498 0           $anon_refs{$nm} = $arg;
499 0           my %s = %$arg;
500 0           tie %$arg, 'Tcl::Var', $interp, $nm;
501 0           %$arg = %s;
502             }
503 0           $args[$argcnt] = $nm; # ... and substitute its name
504             }
505             elsif ($ref eq 'ARRAY' && ref($arg->[0]) eq 'CODE') {
506             # We have been passed something like [\&subroutine, $arg1, ...]
507             # Create a proc in Tcl that invokes this subroutine with args
508 0           my $events;
509             # Look for Tcl::Ev objects as the first arg - these must be
510             # passed through for Tcl to evaluate. Used primarily for %-subs
511             # This could check for any arg ref being Tcl::Ev obj, but it
512             # currently doesn't.
513 0 0 0       if ($#$arg >= 1 && ref($arg->[1]) eq 'Tcl::Ev') {
514 0           $events = splice(@$arg, 1, 1);
515             }
516             $args[$argcnt] =
517             $interp->create_tcl_sub(sub {
518 0     0     $arg->[0]->(@_, @$arg[1..$#$arg]);
519 0           }, $events);
520             }
521             elsif ($ref eq 'ARRAY' && ref($arg->[0]) =~ /^Tcl::Tk::Widget\b/) {
522             # We have been passed [$Tcl_Tk_widget, 'method name', ...]
523             # Create a proc in Tcl that invokes said method with args
524 0           my $events;
525             # Look for Tcl::Ev objects as the first arg - these must be
526             # passed through for Tcl to evaluate. Used primarily for %-subs
527             # This could check for any arg ref being Tcl::Ev obj, but it
528             # currently doesn't.
529 0 0 0       if ($#$arg >= 1 && ref($arg->[1]) eq 'Tcl::Ev') {
530 0           $events = splice(@$arg, 1, 1);
531             }
532 0           my $wid = $arg->[0];
533 0           my $method_name = $arg->[1];
534             $args[$argcnt] =
535             $interp->create_tcl_sub(sub {
536 0     0     $wid->$method_name(@$arg[2..$#$arg]);
537 0           }, $events);
538             }
539             elsif (ref($arg) eq 'REF' and ref($$arg) eq 'SCALAR') {
540             # this is a very special shortcut: if we see construct like \\"xy"
541             # then place proper Tcl::Ev(...) for easier access
542 0           my $events = [map {"%$_"} split '', $$$arg];
  0            
543 0 0 0       if (ref($args[$argcnt+1]) eq 'ARRAY' &&
    0          
544             ref($args[$argcnt+1]->[0]) eq 'CODE') {
545 0           $arg = $args[$argcnt+1];
546             $args[$argcnt] =
547             $interp->create_tcl_sub(sub {
548 0     0     $arg->[0]->(@_, @$arg[1..$#$arg]);
549 0           }, $events);
550             }
551             elsif (ref($args[$argcnt+1]) eq 'CODE') {
552 0           $args[$argcnt] = $interp->create_tcl_sub($args[$argcnt+1],$events);
553             }
554             else {
555 0           warn "not CODE/ARRAY expected after description of event fields";
556             }
557 0           splice @args, $argcnt+1, 1;
558             }
559             }
560             # Done with special var processing. The only processing that icall
561             # will do with the args is efficient conversion of SV to Tcl_Obj.
562             # A SvIV will become a Tcl_IntObj, ARRAY refs will become Tcl_ListObjs,
563             # and so on. The return result from icall will do the opposite,
564             # converting a Tcl_Obj to an SV.
565 0 0         if (!$Tcl::STACK_TRACE) {
    0          
566 0           return $interp->icall(@args);
567             }
568             elsif (wantarray) {
569 0           my @res;
570 0           eval { @res = $interp->icall(@args); };
  0            
571 0 0         if ($@) {
572 0           require Carp;
573 0           Carp::confess ("Tcl error '$@' while invoking array result call:\n" .
574             "\t\"@args\"");
575             }
576 0           return @res;
577             } else {
578 0           my $res;
579 0           eval { $res = $interp->icall(@args); };
  0            
580 0 0         if ($@) {
581 0           require Carp;
582 0           Carp::confess ("Tcl error '$@' while invoking scalar result call:\n" .
583             "\t\"@args\"");
584             }
585 0           return $res;
586             }
587             }
588              
589             # wcall is simple wrapper to 'call' but it tries to search $res in %anon_hash
590             # This implementation is temporary
591             sub wcall {
592 0 0   0     if (wantarray) {
593 0           return call(@_);
594             } else {
595 0           my $res = call(@_);
596 0 0         if (exists $anon_refs{$res}) {
597 0           return $anon_refs{$res};
598             }
599 0           return $res;
600             }
601             }
602              
603             sub return_ref {
604 0     0     my $interp = shift;
605 0           my $rname = shift;
606 0           return $anon_refs{$rname};
607             }
608             sub delete_ref {
609 0     0     my $interp = shift;
610 0           my $rname = shift;
611 0           my $ref = delete $anon_refs{$rname};
612 0 0         if (ref($ref) eq 'CODE') {
613 0           $interp->DeleteCommand($rname);
614             }
615             else {
616 0           $interp->UnsetVar($rname); #TODO: will this delete variable in Tcl?
617 0           untie $$ref;
618             }
619 0           return $ref;
620             }
621             sub return_widget_refs {
622 0     0     my $interp = shift;
623 0           my $wpath = shift;
624 0           return keys %{$widget_refs{$wpath}};
  0            
625             }
626             sub delete_widget_refs {
627 0     0     my $interp = shift;
628 0           my $wpath = shift;
629 0           for (keys %{$widget_refs{$wpath}}) {
  0            
630             #print STDERR "del:$wpath($_)\n";
631 0           delete $widget_refs{$wpath}->{$_};
632 0           $interp->delete_ref($_);
633             }
634             }
635              
636             # create_tcl_sub will create TCL sub that will invoke perl anonymous sub
637             # If $events variable is specified then special processing will be
638             # performed to provide needed '%' variables.
639             # If $tclname is specified then procedure will have namely that name,
640             # otherwise it will have machine-readable name.
641             # Returns tcl script suitable for using in tcl events.
642             sub create_tcl_sub {
643 0     0     my ($interp,$sub,$events,$tclname) = @_;
644 0 0         unless ($tclname) {
645             # stringify sub, becomes "CODE(0x######)" in ::perl namespace
646 0           $tclname = "::perl::$sub";
647             }
648 0 0         unless (exists $anon_refs{$tclname}) {
649 0           $anon_refs{$tclname} = $sub;
650 0           $interp->CreateCommand($tclname, $sub, undef, undef, 1);
651             }
652 0 0         if ($events) {
653             # Add any %-substitutions to callback
654 0           $tclname = "$tclname " . join(' ', @{$events});
  0            
655             }
656 0           return $tclname;
657             }
658             sub Ev {
659 0     0     my @events = @_;
660 0           return bless \@events, "Tcl::Ev";
661             }
662              
663              
664             package Tcl::List;
665              
666 11         93 use overload '""' => \&as_string,
667 11     11   26787 fallback => 1;
  11         13928  
668              
669             package Tcl::Var;
670              
671             sub TIESCALAR {
672 0     0     my $class = shift;
673 0           my @objdata = @_;
674 0 0 0       unless (@_ == 2 || @_ == 3) {
675 0           require Carp;
676 0           Carp::croak('Usage: tie $s, Tcl::Var, $interp, $varname [, $flags]');
677             };
678 0           bless \@objdata, $class;
679             }
680              
681             sub TIEHASH {
682 0     0     my $class = shift;
683 0           my @objdata = @_;
684 0 0 0       unless (@_ == 2 || @_ == 3) {
685 0           require Carp;
686 0           Carp::croak('Usage: tie %hash, Tcl::Var, $interp, $varname [, $flags]');
687             }
688 0           bless \@objdata, $class;
689             }
690              
691             my %arraystates;
692             sub FIRSTKEY {
693 0     0     my $obj = shift;
694 0           die "STORE Usage: objdata @{$obj} $#{$obj}, not 2 or 3 (@_)"
  0            
  0            
695 0 0 0       unless @{$obj} == 2 || @{$obj} == 3;
  0            
696 0           my ($interp, $varname, $flags) = @$obj;
697 0           $arraystates{$varname} = $interp->invoke("array","startsearch",$varname);
698 0           my $r = $interp->invoke("array","nextelement",$varname,$arraystates{$varname});
699 0 0         if ($r eq '') {
700 0           delete $arraystates{$varname};
701 0           return undef;
702             }
703 0           return $r;
704             }
705             sub NEXTKEY {
706 0     0     my $obj = shift;
707 0           die "STORE Usage: objdata @{$obj} $#{$obj}, not 2 or 3 (@_)"
  0            
  0            
708 0 0 0       unless @{$obj} == 2 || @{$obj} == 3;
  0            
709 0           my ($interp, $varname, $flags) = @$obj;
710 0           my $r = $interp->invoke("array","nextelement",$varname,$arraystates{$varname});
711 0 0         if ($r eq '') {
712 0           delete $arraystates{$varname};
713 0           return undef;
714             }
715 0           return $r;
716             }
717             sub CLEAR {
718 0     0     my $obj = shift;
719 0           die "STORE Usage: objdata @{$obj} $#{$obj}, not 2 or 3 (@_)"
  0            
  0            
720 0 0 0       unless @{$obj} == 2 || @{$obj} == 3;
  0            
721 0           my ($interp, $varname, $flags) = @$obj;
722 0           $interp->invoke("array", "unset", "$varname");
723             #$interp->invoke("array", "set", "$varname", "");
724             }
725             sub DELETE {
726 0     0     my $obj = shift;
727 0 0 0       unless (@{$obj} == 2 || @{$obj} == 3) {
  0            
  0            
728 0           require Carp;
729 0           Carp::croak("STORE Usage: objdata @{$obj} $#{$obj}, not 2 or 3 (@_)");
  0            
  0            
730             }
731 0           my ($interp, $varname, $flags) = @{$obj};
  0            
732 0           my ($str1) = @_;
733 0           $interp->invoke("unset", "$varname($str1)"); # protect strings?
734             }
735              
736             sub UNTIE {
737 0     0     my $ref = shift;
738             #print STDERR "UNTIE:$ref(@_)\n";
739             }
740             sub DESTROY {
741 0     0     my $ref = shift;
742 0           delete $anon_refs{$ref->[1]};
743             }
744              
745             # This is the perl equiv to the C version, for reference
746             #
747             #sub STORE {
748             # my $obj = shift;
749             # croak "STORE Usage: objdata @{$obj} $#{$obj}, not 2 or 3 (@_)"
750             # unless @{$obj} == 2 || @{$obj} == 3;
751             # my ($interp, $varname, $flags) = @{$obj};
752             # my ($str1, $str2) = @_;
753             # if ($str2) {
754             # $interp->SetVar2($varname, $str1, $str2, $flags);
755             # } else {
756             # $interp->SetVar($varname, $str1, $flags || 0);
757             # }
758             #}
759             #
760             #sub FETCH {
761             # my $obj = shift;
762             # croak "FETCH Usage: objdata @{$obj} $#{$obj}, not 2 or 3 (@_)"
763             # unless @{$obj} == 2 || @{$obj} == 3;
764             # my ($interp, $varname, $flags) = @{$obj};
765             # my $key = shift;
766             # if ($key) {
767             # return $interp->GetVar2($varname, $key, $flags || 0);
768             # } else {
769             # return $interp->GetVar($varname, $flags || 0);
770             # }
771             #}
772              
773             package Tcl;
774              
775             =head1 Other Tcl interpreter methods
776              
777             =over 2
778              
779             =item export_to_tcl method
780              
781             An interpreter method, export_to_tcl, is used to expose a number of perl
782             subroutines and variables all at once into tcl/tk.
783              
784             B takes a hash as arguments, which represents named parameters,
785             with following allowed values:
786              
787             =over 4
788              
789             =item B => '...'
790              
791             tcl namespace, where commands and variables are to
792             be created, defaults to 'perl'. If '' is specified - then global
793             namespace is used. A possible '::' at end is stripped.
794              
795             =item B => { ... }
796              
797             anonymous hash of subs to be created in Tcl, in the form /tcl name/ => /code ref/
798              
799             =item B => { ... }
800              
801             anonymous hash of vars to be created in Tcl, in the form /tcl name/ => /code ref/
802              
803             =item B => '...'
804              
805             a name of Perl namespace, from where all existing subroutines will be searched
806             and Tcl command will be created for each of them.
807              
808             =item B => '...'
809              
810             a name of Perl namespace, from where all existing variables will be searched,
811             and each such variable will be tied to Tcl.
812              
813             =back
814              
815             An example:
816              
817             use strict;
818             use Tcl;
819            
820             my $int = new Tcl;
821            
822             $tcl::foo = 'qwerty';
823             $int->export_to_tcl(subs_from=>'tcl',vars_from=>'tcl');
824            
825             $int->Eval(<<'EOS');
826             package require Tk
827            
828             button .b1 -text {a fluffy button} -command perl::fluffy_sub
829             button .b2 -text {a foo button} -command perl::foo
830             entry .e -textvariable perl::foo
831             pack .b1 .b2 .e
832             focus .b2
833            
834             tkwait window .
835             EOS
836            
837             sub tcl::fluffy_sub {
838             print "Hi, I am a fluffy sub\n";
839             }
840             sub tcl::foo {
841             print "Hi, I am foo\n";
842             $tcl::foo++;
843             }
844              
845             =cut
846              
847             sub export_to_tcl {
848 0     0     my $int = shift;
849 0           my %args = @_;
850              
851             # name of Tcl package to hold tcl commands bound to perl subroutines
852 0 0         my $tcl_namespace = (exists $args{namespace} ? $args{namespace} : 'perl::');
853 0           $tcl_namespace=~s/(?:::)?$/::/;
854              
855             # a batch of perl subroutines which tcl counterparts should be created
856 0   0       my $subs = $args{subs} || {};
857              
858             # a batch of perl variables which tcl counterparts should be created
859 0   0       my $vars = $args{vars} || {};
860              
861             # TBD:
862             # only => \@list_of_names
863             # argument to be able to limit the names to export to Tcl.
864              
865 0 0         if (exists $args{subs_from}) {
866             # name of Perl package, which subroutines would be bound to tcl commands
867 0           my $subs_from = $args{subs_from};
868 0           $subs_from =~ s/::$//;
869 11     11   12112 no strict 'refs';
  11         25  
  11         1986  
870 0           for my $name (keys %{"$subs_from\::"}) {
  0            
871             #print STDERR "$name;\n";
872 0 0         if (defined &{"$subs_from\::$name"}) {
  0            
873 0 0         if (exists $subs->{$name}) {
874 0           next;
875             }
876             #print STDERR "binding sub '$name'\n";
877 0           $int->CreateCommand("$tcl_namespace$name", \&{"$subs_from\::$name"}, undef, undef, 1);
  0            
878             }
879             }
880             }
881 0 0         if (exists $args{vars_from}) {
882             # name of Perl package, which subroutines would be bound to tcl commands
883 0           my $vars_from = $args{vars_from};
884 0           $vars_from =~ s/::$//;
885 11     11   58 no strict 'refs';
  11         17  
  11         4641  
886 0           for my $name (keys %{"$vars_from\::"}) {
  0            
887             #print STDERR "$name;\n";
888 0 0         if (defined ${"$vars_from\::$name"}) {
  0            
889 0 0         if (exists $vars->{$name}) {
890 0           next;
891             }
892             #print STDERR "binding var '$name' in '$tcl_namespace'\n";
893 0           local $_ = ${"$vars_from\::$name"};
  0            
894 0           tie ${"$vars_from\::$name"}, 'Tcl::Var', $int, "$tcl_namespace$name";
  0            
895 0           ${"$vars_from\::$name"} = $_;
  0            
896             }
897 0           if (0) {
898             # array, hash - no need to do anything.
899             # (or should we?)
900             }
901             }
902             }
903              
904 0           for my $subname (keys %$subs) {
905             #print STDERR "binding2 sub '$subname'\n";
906 0           $int->CreateCommand("$tcl_namespace$subname",$subs->{$subname}, undef, undef, 1);
907             }
908              
909 0           for my $varname (keys %$vars) {
910             #print STDERR "binding2 var '$varname'\n";
911 0 0         unless (ref($vars->{$varname})) {
912 0           require 'Carp.pm';
913 0           Carp::croak("should pass var ref as variable bind parameter");
914             }
915 0           local $_ = ${$vars->{$varname}};
  0            
916 0           tie ${$vars->{$varname}}, 'Tcl::Var', $int, "$tcl_namespace$varname";
  0            
917 0           ${$vars->{$varname}} = $_;
  0            
918             }
919             }
920              
921             =item B
922              
923             extra convenience sub, binds to tcl all subs and vars from perl B namespace
924              
925             =back
926              
927             =cut
928              
929             sub export_tcl_namespace {
930 0     0     my $int = shift;
931 0           $int->export_to_tcl(subs_from=>'tcl', vars_from=>'tcl');
932             }
933              
934             =head1 AUTHORS
935              
936             Malcolm Beattie, mbeattie@sable.ox.ac.uk, 23 Oct 1994.
937             Vadim Konovalov, vkon@cpan.org, 19 May 2003.
938             Jeff Hobbs, jeff (a) activestate . com, 22 Mar 2004.
939             Gisle Aas, gisle (a) activestate . com, 14 Apr 2004.
940              
941             =head1 COPYRIGHT
942              
943             This program is free software; you can redistribute it and/or modify it under
944             the same terms as Perl itself.
945              
946             See http://www.perl.com/perl/misc/Artistic.html
947              
948             =cut
949              
950             1;
951