From 36c28cb10c8d7c1d2e7172696d147a2450914715 Mon Sep 17 00:00:00 2001 From: Siep Kroonenberg Date: Fri, 17 May 2013 18:50:42 +0000 Subject: Added Win32::OLE class to tlperl git-svn-id: svn://tug.org/texlive/trunk@30525 c570f23f-e606-0410-a88d-b1316a301751 --- Master/tlpkg/tlperl/lib/Win32/OLE.pm | 968 +++++++++++++++++++++++ Master/tlpkg/tlperl/lib/Win32/OLE/Const.pm | 201 +++++ Master/tlpkg/tlperl/lib/Win32/OLE/Enum.pm | 95 +++ Master/tlpkg/tlperl/lib/Win32/OLE/Lite.pm | 224 ++++++ Master/tlpkg/tlperl/lib/Win32/OLE/NEWS.pod | 380 +++++++++ Master/tlpkg/tlperl/lib/Win32/OLE/NLS.pm | 968 +++++++++++++++++++++++ Master/tlpkg/tlperl/lib/Win32/OLE/TPJ.pod | 798 +++++++++++++++++++ Master/tlpkg/tlperl/lib/Win32/OLE/TypeInfo.pm | 389 +++++++++ Master/tlpkg/tlperl/lib/Win32/OLE/Variant.pm | 577 ++++++++++++++ Master/tlpkg/tlperl/lib/auto/Win32/OLE/.packlist | 12 + Master/tlpkg/tlperl/lib/auto/Win32/OLE/OLE.bs | 0 Master/tlpkg/tlperl/lib/auto/Win32/OLE/OLE.dll | Bin 0 -> 143872 bytes Master/tlpkg/tlperl/lib/perllocal.pod | 22 + 13 files changed, 4634 insertions(+) create mode 100644 Master/tlpkg/tlperl/lib/Win32/OLE.pm create mode 100644 Master/tlpkg/tlperl/lib/Win32/OLE/Const.pm create mode 100644 Master/tlpkg/tlperl/lib/Win32/OLE/Enum.pm create mode 100644 Master/tlpkg/tlperl/lib/Win32/OLE/Lite.pm create mode 100644 Master/tlpkg/tlperl/lib/Win32/OLE/NEWS.pod create mode 100644 Master/tlpkg/tlperl/lib/Win32/OLE/NLS.pm create mode 100644 Master/tlpkg/tlperl/lib/Win32/OLE/TPJ.pod create mode 100644 Master/tlpkg/tlperl/lib/Win32/OLE/TypeInfo.pm create mode 100644 Master/tlpkg/tlperl/lib/Win32/OLE/Variant.pm create mode 100644 Master/tlpkg/tlperl/lib/auto/Win32/OLE/.packlist create mode 100644 Master/tlpkg/tlperl/lib/auto/Win32/OLE/OLE.bs create mode 100644 Master/tlpkg/tlperl/lib/auto/Win32/OLE/OLE.dll diff --git a/Master/tlpkg/tlperl/lib/Win32/OLE.pm b/Master/tlpkg/tlperl/lib/Win32/OLE.pm new file mode 100644 index 00000000000..a447f1aaa18 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/Win32/OLE.pm @@ -0,0 +1,968 @@ +# The documentation is at the __END__ + +package Win32::OLE; + +use strict; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK @EXPORT_FAIL $AUTOLOAD + $CP $LCID $Warn $LastError $_NewEnum $_Unique); + +$VERSION = '0.1709'; + +use Carp; +use Exporter; +use DynaLoader; +@ISA = qw(Exporter DynaLoader); + +@EXPORT = qw(); +@EXPORT_OK = qw(in valof with HRESULT EVENTS OVERLOAD + CP_ACP CP_OEMCP CP_MACCP CP_UTF7 CP_UTF8 + DISPATCH_METHOD DISPATCH_PROPERTYGET + DISPATCH_PROPERTYPUT DISPATCH_PROPERTYPUTREF); +@EXPORT_FAIL = qw(EVENTS OVERLOAD); + +sub export_fail { + shift; + my @unknown; + while (@_) { + my $symbol = shift; + if ($symbol eq 'OVERLOAD') { + eval <<'OVERLOAD'; + use overload '""' => \&valof, + '0+' => \&valof, + fallback => 1; +OVERLOAD + } + elsif ($symbol eq 'EVENTS') { + Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE()); + } + else { + push @unknown, $symbol; + } + } + return @unknown; +} + +unless (defined &Dispatch) { + # Use regular DynaLoader if XS part is not yet initialized + bootstrap Win32::OLE; + require Win32::OLE::Lite; +} + +1; + +######################################################################## + +__END__ + +=head1 NAME + +Win32::OLE - OLE Automation extensions + +=head1 SYNOPSIS + + $ex = Win32::OLE->new('Excel.Application') or die "oops\n"; + $ex->Amethod("arg")->Bmethod->{'Property'} = "foo"; + $ex->Cmethod(undef,undef,$Arg3); + $ex->Dmethod($RequiredArg1, {NamedArg1 => $Value1, NamedArg2 => $Value2}); + + $wd = Win32::OLE->GetObject("D:\\Data\\Message.doc"); + $xl = Win32::OLE->GetActiveObject("Excel.Application"); + +=head1 DESCRIPTION + +This module provides an interface to OLE Automation from Perl. +OLE Automation brings VisualBasic like scripting capabilities and +offers powerful extensibility and the ability to control many Win32 +applications from Perl scripts. + +The Win32::OLE module uses the IDispatch interface exclusively. It is +not possible to access a custom OLE interface. OLE events and OCX's are +currently not supported. + +Actually, that's no longer strictly true. This module now contains +B level support for OLE events. This is largely untested and the +specific interface might still change in the future. + +=head2 Methods + +=over 8 + +=item Win32::OLE->new(PROGID[, DESTRUCTOR]) + +The new() class method starts a new instance of an OLE Automation object. +It returns a reference to this object or C if the creation failed. + +The PROGID argument must be either the OLE I or the I +of the required application. The optional DESTRUCTOR specifies a DESTROY-like +method. This can be either a CODE reference or a string containing an OLE +method name. It can be used to cleanly terminate OLE applications in case the +Perl program dies. + +To create an object via DCOM on a remote server you can use an array +reference in place of PROGID. The referenced array must contain the +machine name and the I or I. For example: + + my $obj = Win32::OLE->new(['my.machine.com', 'Program.Id']); + +If the PROGID is a I then Win32::OLE will try to resolve the +corresponding I locally. If the I is not registered +locally then the remote registry is queried. This will only succeed if +the local process has read access to the remote registry. The safest +(and fastest) method is to specify the C directly. + +=item Win32::OLE->EnumAllObjects([CALLBACK]) + +This class method returns the number Win32::OLE objects currently in +existance. It will call the optional CALLBACK function for each of +these objects: + + $Count = Win32::OLE->EnumAllObjects(sub { + my $Object = shift; + my $Class = Win32::OLE->QueryObjectType($Object); + printf "# Object=%s Class=%s\n", $Object, $Class; + }); + +The EnumAllObjects() method is primarily a debugging tool. It can be +used e.g. in an END block to check if all external connections have +been properly destroyed. + +=item Win32::OLE->FreeUnusedLibraries() + +The FreeUnusedLibraries() class method unloads all unused OLE +resources. These are the libraries of those classes of which all +existing objects have been destroyed. The unloading of object +libraries is really only important for long running processes that +might instantiate a huge number of B objects over time. + +Be aware that objects implemented in Visual Basic have a buggy +implementation of this functionality: They pretend to be unloadable +while they are actually still running their cleanup code. Unloading +the DLL at that moment typically produces an access violation. The +probability for this problem can be reduced by calling the +SpinMessageLoop() method and sleep()ing for a few seconds. + +=item Win32::OLE->GetActiveObject(CLASS[, DESTRUCTOR]) + +The GetActiveObject() class method returns an OLE reference to a +running instance of the specified OLE automation server. It returns +C if the server is not currently active. It will croak if +the class is not even registered. The optional DESTRUCTOR method takes +either a method name or a code reference. It is executed when the last +reference to this object goes away. It is generally considered C +to stop applications that you did not start yourself. + +=item Win32::OLE->GetObject(MONIKER[, DESTRUCTOR]) + +The GetObject() class method returns an OLE reference to the specified +object. The object is specified by a pathname optionally followed by +additional item subcomponent separated by exclamation marks '!'. The +optional DESTRUCTOR argument has the same semantics as the DESTRUCTOR in +new() or GetActiveObject(). + +=item Win32::OLE->Initialize([COINIT]) + +The Initialize() class method can be used to specify an alternative +apartment model for the Perl thread. It must be called B the +first OLE object is created. If the C module is +used then the call to the Initialize() method must be made from a BEGIN +block before the first C statement for the C +module. + +Valid values for COINIT are: + + Win32::OLE::COINIT_APARTMENTTHREADED - single threaded + Win32::OLE::COINIT_MULTITHREADED - the default + Win32::OLE::COINIT_OLEINITIALIZE - single threaded, additional OLE stuff + +COINIT_OLEINITIALIZE is sometimes needed when an OLE object uses +additional OLE compound document technologies not available from the +normal COM subsystem (for example MAPI.Session seems to require it). +Both COINIT_OLEINITIALIZE and COINIT_APARTMENTTHREADED create a hidden +top level window and a message queue for the Perl process. This may +create problems with other application, because Perl normally doesn't +process its message queue. This means programs using synchronous +communication between applications (such as DDE initiation), may hang +until Perl makes another OLE method call/property access or terminates. +This applies to InstallShield setups and many things started to shell +associations. Please try to utilize the CSpinMessageLoop> +and CUninitialize> methods if you can not use the default +COINIT_MULTITHREADED model. + +=item OBJECT->Invoke(METHOD[, ARGS]) + +The Invoke() object method is an alternate way to invoke OLE +methods. It is normally equivalent to C<$OBJECT->METHOD(@ARGS)>. This +function must be used if the METHOD name contains characters not valid +in a Perl variable name (like foreign language characters). It can +also be used to invoke the default method of an object even if the +default method has not been given a name in the type library. In this +case use or C<''> as the method name. To invoke an OLE objects +native Invoke() method (if such a thing exists), please use: + + $Object->Invoke('Invoke', @Args); + +=item Win32::OLE->LastError() + +The LastError() class method returns the last recorded OLE +error. This is a dual value like the C<$!> variable: in a numeric +context it returns the error number and in a string context it returns +the error message. The error number is a signed HRESULT value. Please +use the L function to convert an unsigned hexadecimal +constant to a signed HRESULT. + +The last OLE error is automatically reset by a successful OLE +call. The numeric value can also explicitly be set by a call (which will +discard the string value): + + Win32::OLE->LastError(0); + +=item OBJECT->LetProperty(NAME,ARGS,VALUE) + +In Win32::OLE property assignment using the hash syntax is equivalent +to the Visual Basic C syntax (I assignment): + + $Object->{Property} = $OtherObject; + +corresponds to this Visual Basic statement: + + Set Object.Property = OtherObject + +To get the I treatment of the Visual Basic C statement + + Object.Property = OtherObject + +you have to use the LetProperty() object method in Perl: + + $Object->LetProperty($Property, $OtherObject); + +LetProperty() also supports optional arguments for the property assignment. +See LSetProperty(NAME,ARGS,VALUE)> for details. + +=item Win32::OLE->MessageLoop() + +The MessageLoop() class method will run a standard Windows message +loop, dispatching messages until the QuitMessageLoop() class method is +called. It is used to wait for OLE events. + +=item Win32::OLE->Option(OPTION) + +The Option() class method can be used to inspect and modify +L. The single argument form retrieves the value of +an option: + + my $CP = Win32::OLE->Option('CP'); + +A single call can be used to set multiple options simultaneously: + + Win32::OLE->Option(CP => CP_ACP, Warn => 3); + +=item Win32::OLE->QueryObjectType(OBJECT) + +The QueryObjectType() class method returns a list of the type library +name and the objects class name. In a scalar context it returns the +class name only. It returns C when the type information is not +available. + +=item Win32::OLE->QuitMessageLoop() + +The QuitMessageLoop() class method posts a (user-level) "Quit" message +to the current threads message loop. QuitMessageLoop() is typically +called from an event handler. The MessageLoop() class method will +return when it receives this "Quit" method. + +=item OBJECT->SetProperty(NAME,ARGS,VALUE) + +The SetProperty() method allows to modify properties with arguments, +which is not supported by the hash syntax. The hash form + + $Object->{Property} = $Value; + +is equivalent to + + $Object->SetProperty('Property', $Value); + +Arguments must be specified between the property name and the new value: + + $Object->SetProperty('Property', @Args, $Value); + +It is not possible to use "named argument" syntax with this function +because the new value must be the last argument to SetProperty(). + +This method hides any native OLE object method called SetProperty(). +The native method will still be available through the Invoke() method: + + $Object->Invoke('SetProperty', @Args); + +=item Win32::OLE->SpinMessageLoop + +This class method retrieves all pending messages from the message queue +and dispatches them to their respective window procedures. Calling this +method is only necessary when not using the COINIT_MULTITHREADED model. +All OLE method calls and property accesses automatically process the +message queue. + +=item Win32::OLE->Uninitialize + +The Uninitialize() class method uninitializes the OLE subsystem. It +also destroys the hidden top level window created by OLE for single +threaded apartments. All OLE objects will become invalid after this call! +It is possible to call the Initialize() class method again with a different +apartment model after shutting down OLE with Uninitialize(). + +=item Win32::OLE->WithEvents(OBJECT[, HANDLER[, INTERFACE]]) + +This class method enables and disables the firing of events by the +specified OBJECT. If no HANDLER is specified, then events are +disconnected. For some objects Win32::OLE is not able to +automatically determine the correct event interface. In this case the +INTERFACE argument must contain either the COCLASS name of the OBJECT +or the name of the event DISPATCH interface. Please read the L +section below for detailed explanation of the Win32::OLE event +support. + +=back + +Whenever Perl does not find a method name in the Win32::OLE package it +is automatically used as the name of an OLE method and this method call +is dispatched to the OLE server. + +There is one special hack built into the module: If a method or property +name could not be resolved with the OLE object, then the default method +of the object is called with the method name as its first parameter. So + + my $Sheet = $Worksheets->Table1; +or + my $Sheet = $Worksheets->{Table1}; + +is resolved as + + my $Sheet = $Worksheet->Item('Table1'); + +provided that the $Worksheets object doesnot have a C method +or property. This hack has been introduced to call the default method +of collections which did not name the method in their type library. The +recommended way to call the "unnamed" default method is: + + my $Sheet = $Worksheets->Invoke('', 'Table1'); + +This special hack is disabled under C. + +=head2 Object methods and properties + +The object returned by the new() method can be used to invoke +methods or retrieve properties in the same fashion as described +in the documentation for the particular OLE class (eg. Microsoft +Excel documentation describes the object hierarchy along with the +properties and methods exposed for OLE access). + +Optional parameters on method calls can be omitted by using C +as a placeholder. A better way is to use named arguments, as the +order of optional parameters may change in later versions of the OLE +server application. Named parameters can be specified in a reference +to a hash as the last parameter to a method call. + +Properties can be retrieved or set using hash syntax, while methods +can be invoked with the usual perl method call syntax. The C +and C functions can be used to enumerate an object's properties. +Beware that a property is not always writable or even readable (sometimes +raising exceptions when read while being undefined). + +If a method or property returns an embedded OLE object, method +and property access can be chained as shown in the examples below. + +=head2 Functions + +The following functions are not exported by default. + +=over 8 + +=item HRESULT(ERROR) + +The HRESULT() function converts an unsigned number into a signed HRESULT +error value as used by OLE internally. This is necessary because Perl +treats all hexadecimal constants as unsigned. To check if the last OLE +function returned "Member not found" (0x80020003) you can write: + + if (Win32::OLE->LastError == HRESULT(0x80020003)) { + # your error recovery here + } + +=item in(COLLECTION) + +If COLLECTION is an OLE collection object then C +returns a list of all members of the collection. This is a shortcut +for CAll($COLLECTION)>. It is most commonly used in +a C loop: + + foreach my $value (in $collection) { + # do something with $value here + } + +=item valof(OBJECT) + +Normal assignment of Perl OLE objects creates just another reference +to the OLE object. The valof() function explictly dereferences the +object (through the default method) and returns the value of the object. + + my $RefOf = $Object; + my $ValOf = valof $Object; + $Object->{Value} = $NewValue; + +Now $ValOf still contains the old value wheras $RefOf would +resolve to the $NewValue because it is still a reference to +$Object. + +The valof() function can also be used to convert Win32::OLE::Variant +objects to Perl values. + +=item with(OBJECT, PROPERTYNAME => VALUE, ...) + +This function provides a concise way to set the values of multiple +properties of an object. It iterates over its arguments doing +C<$OBJECT->{PROPERTYNAME} = $VALUE> on each trailing pair. + +=back + +=head2 Overloading + +The Win32::OLE objects can be overloaded to automatically convert to +their values whenever they are used in a bool, numeric or string +context. This is not enabled by default. You have to request it +through the OVERLOAD pseudoexport: + + use Win32::OLE qw(in valof with OVERLOAD); + +You can still get the original string representation of an object +(C), e.g. for debugging, by using the +C method: + + print overload::StrVal($object), "\n"; + +Please note that C is a global setting. If any module enables +Win32::OLE overloading then it's active everywhere. + +=head2 Events + +The Win32::OLE module now contains B level event support. This +support is only available when Perl is running in a single threaded +apartment. This can most easily be assured by using the C +pseudo-import: + + use Win32::OLE qw(EVENTS); + +which implicitly does something like: + + use Win32::OLE; + Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE); + +The current interface to OLE events should be considered experimental +and is subject to change. It works as expected for normal OLE +applications, but OLE control events often don't seem to work yet. + +Events must be enabled explicitly for an OLE object through the +Win32::OLE->WithEvents() class method. The Win32::OLE module uses the +IProvideClassInfo2 interface to determine the default event source of +the object. If this interface is not supported, then the user must +specify the name of the event source explicitly in the WithEvents() +method call. It is also possible to specify the class name of the +object as the third parameter. In this case Win32::OLE will try to +look up the default source interface for this COCLASS. + +The HANDLER argument to Win32::OLE->WithEvents() can either be a CODE +reference or a package name. In the first case, all events will invoke +this particular function. The first two arguments to this function will +be the OBJECT itself and the name of the event. The remaining arguments +will be event specific. + + sub Event { + my ($Obj,$Event,@Args) = @_; + print "Event triggered: '$Event'\n"; + } + Win32::OLE->WithEvents($Obj, \&Event); + +Alternatively the HANDLER argument can specify a package name. When the +OBJECT fires an event, Win32::OLE will try to find a function of the same +name as the event in this package. This function will be called with the +OBJECT as the first argument followed again by the event specific parameters: + + package MyEvents; + sub EventName1 { + my ($Obj,@Args) = @_; + print "EventName1 event triggered\n"; + } + + package main; + Win32::OLE->WithEvents($Obj, 'MyEvents', 'IEventInterface'); + +If Win32::OLE doesn't find a function with the name of the event then nothing +happens. + +Event parameters passed I are handled specially. They are not +converted to the corresponding Perl datatype but passed as Win32::OLE::Variant +objects. You can assign a new value to these objects with the help of the +Put() method. This value will be passed back to the object when the event +function returns: + + package MyEvents; + sub BeforeClose { + my ($self,$Cancel) = @_; + $Cancel->Put(1) unless $MayClose; + } + +Direct assignment to $Cancel would have no effect on the original value and +would therefore not command the object to abort the closing action. + +=head2 Module Options + +The following module options can be accessed and modified with the +COption> class method. In earlier versions of the Win32::OLE +module these options were manipulated directly as class variables. This +practice is now deprecated. + +=over 8 + +=item CP + +This variable is used to determine the codepage used by all +translations between Perl strings and Unicode strings used by the OLE +interface. The default value is CP_ACP, which is the default ANSI +codepage. Other possible values are CP_OEMCP, CP_MACCP, CP_UTF7 and +CP_UTF8. These constants are not exported by default. + +=item LCID + +This variable controls the locale idnetifier used for all OLE calls. +It is set to LOCALE_NEUTRAL by default. Please check the +L module for other locale related information. + +=item Variant + +This options controls how method calls and property accessors return +values of type VT_CY and VT_DECIMAL are being returned. By default +VT_CY values are turned into strings and VT_DECIMAL values into +floating point numbers. If the C option is enabled, these +values are returned as Win32::OLE::Variant objects, just like VT_DATE +and VT_ERROR values. If the Win32::OLE::Variant module is also +loaded, then all values should still behave as before in string and in +numeric context. + +The only reason that the C behavior is not the default is that +this is an incompatible change that might break existing programs. + +=item Warn + +This variable determines the behavior of the Win32::OLE module when +an error happens. Valid values are: + + 0 Ignore error, return undef + 1 Carp::carp if $^W is set (-w option) + 2 always Carp::carp + 3 Carp::croak + +The error number and message (without Carp line/module info) are +available through the CLastError> class method. + +Alternatively the Warn option can be set to a CODE reference. E.g. + + Win32::OLE->Option(Warn => 3); + +is equivalent to + + Win32::OLE->Option(Warn => \&Carp::croak); + +This can even be used to emulate the VisualBasic C construct: + + Win32::OLE->Option(Warn => sub {goto CheckError}); + # ... your normal OLE code here ... + + CheckError: + # ... your error handling code here ... + +=item _NewEnum + +This option enables additional enumeration support for collection +objects. When the C<_NewEnum> option is set, all collections will +receive one additional property: C<_NewEnum>. The value of this +property will be a reference to an array containing all the elements +of the collection. This option can be useful when used in conjunction +with an automatic tree traversal program, like C or an +object tree browser. The value of this option should be either 1 +(enabled) or 0 (disabled, default). + + Win32::OLE->Option(_NewEnum => 1); + # ... + my @sheets = @{$Excel->Worksheets->{_NewEnum}}; + +In normal application code, this would be better written as: + + use Win32::OLE qw(in); + # ... + my @sheets = in $Excel->Worksheets; + +=item _Unique + +The C<_Unique> options guarantees that Win32::OLE will maintain a +one-to-one mapping between Win32::OLE objects and the native COM/OLE +objects. Without this option, you can query the same property twice +and get two different Win32::OLE objects for the same underlying COM +object. + +Using a unique proxy makes life easier for tree traversal algorithms +to recognize they already visited a particular node. This option +comes at a price: Win32::OLE has to maintain a global hash of all +outstanding objects and their corresponding proxies. Identity checks +on COM objects can also be expensive if the objects reside +out-of-process or even on a different computer. Therefore this option +is off by default unless the program is being run in the debugger. + +Unfortunately, this option doesn't always help. Some programs will +return new COM objects for even the same property when asked for it +multiple times (especially for collections). In this case, there is +nothing Win32::OLE can do to detect that these objects are in fact +identical (because they aren't at the COM level). + +The C<_Unique> option can be set to either 1 (enabled) or 0 (disabled, +default). + +=back + +=head1 EXAMPLES + +Here is a simple Microsoft Excel application. + + use Win32::OLE; + + # use existing instance if Excel is already running + eval {$ex = Win32::OLE->GetActiveObject('Excel.Application')}; + die "Excel not installed" if $@; + unless (defined $ex) { + $ex = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit;}) + or die "Oops, cannot start Excel"; + } + + # get a new workbook + $book = $ex->Workbooks->Add; + + # write to a particular cell + $sheet = $book->Worksheets(1); + $sheet->Cells(1,1)->{Value} = "foo"; + + # write a 2 rows by 3 columns range + $sheet->Range("A8:C9")->{Value} = [[ undef, 'Xyzzy', 'Plugh' ], + [ 42, 'Perl', 3.1415 ]]; + + # print "XyzzyPerl" + $array = $sheet->Range("A8:C9")->{Value}; + for (@$array) { + for (@$_) { + print defined($_) ? "$_|" : "|"; + } + print "\n"; + } + + # save and exit + $book->SaveAs( 'test.xls' ); + undef $book; + undef $ex; + +Please note the destructor specified on the Win32::OLE->new method. It ensures +that Excel will shutdown properly even if the Perl program dies. Otherwise +there could be a process leak if your application dies after having opened +an OLE instance of Excel. It is the responsibility of the module user to +make sure that all OLE objects are cleaned up properly! + +Here is an example of using Variant data types. + + use Win32::OLE; + use Win32::OLE::Variant; + $ex = Win32::OLE->new('Excel.Application', \&OleQuit) or die "oops\n"; + $ex->{Visible} = 1; + $ex->Workbooks->Add; + # should generate a warning under -w + $ovR8 = Variant(VT_R8, "3 is a good number"); + $ex->Range("A1")->{Value} = $ovR8; + $ex->Range("A2")->{Value} = Variant(VT_DATE, 'Jan 1,1970'); + + sub OleQuit { + my $self = shift; + $self->Quit; + } + +The above will put value "3" in cell A1 rather than the string +"3 is a good number". Cell A2 will contain the date. + +Similarly, to invoke a method with some binary data, you can +do the following: + + $obj->Method( Variant(VT_UI1, "foo\000b\001a\002r") ); + +Here is a wrapper class that basically delegates everything but +new() and DESTROY(). The wrapper class shown here is another way to +properly shut down connections if your application is liable to die +without proper cleanup. Your own wrappers will probably do something +more specific to the particular OLE object you may be dealing with, +like overriding the methods that you may wish to enhance with your +own. + + package Excel; + use Win32::OLE; + + sub new { + my $s = {}; + if ($s->{Ex} = Win32::OLE->new('Excel.Application')) { + return bless $s, shift; + } + return undef; + } + + sub DESTROY { + my $s = shift; + if (exists $s->{Ex}) { + print "# closing connection\n"; + $s->{Ex}->Quit; + return undef; + } + } + + sub AUTOLOAD { + my $s = shift; + $AUTOLOAD =~ s/^.*:://; + $s->{Ex}->$AUTOLOAD(@_); + } + + 1; + +The above module can be used just like Win32::OLE, except that +it takes care of closing connections in case of abnormal exits. +Note that the effect of this specific example can be easier accomplished +using the optional destructor argument of Win32::OLE::new: + + my $Excel = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit;}); + +Note that the delegation shown in the earlier example is not the same as +true subclassing with respect to further inheritance of method calls in your +specialized object. See L, L and L for details. +True subclassing (available by setting C<@ISA>) is also feasible, +as the following example demonstrates: + + # + # Add error reporting to Win32::OLE + # + + package Win32::OLE::Strict; + use Carp; + use Win32::OLE; + + use strict qw(vars); + use vars qw($AUTOLOAD @ISA); + @ISA = qw(Win32::OLE); + + sub AUTOLOAD { + my $obj = shift; + $AUTOLOAD =~ s/^.*:://; + my $meth = $AUTOLOAD; + $AUTOLOAD = "SUPER::" . $AUTOLOAD; + my $retval = $obj->$AUTOLOAD(@_); + unless (defined($retval) || $AUTOLOAD eq 'DESTROY') { + my $err = Win32::OLE::LastError(); + croak(sprintf("$meth returned OLE error 0x%08x",$err)) + if $err; + } + return $retval; + } + + 1; + +This package inherits the constructor new() from the Win32::OLE +package. It is important to note that you cannot later rebless a +Win32::OLE object as some information about the package is cached by +the object. Always invoke the new() constructor through the right +package! + +Here's how the above class will be used: + + use Win32::OLE::Strict; + my $Excel = Win32::OLE::Strict->new('Excel.Application', 'Quit'); + my $Books = $Excel->Workbooks; + $Books->UnknownMethod(42); + +In the sample above the call to UnknownMethod() will be caught with + + UnknownMethod returned OLE error 0x80020009 at test.pl line 5 + +because the Workbooks object inherits the class C from the +C<$Excel> object. + +=head1 NOTES + +=head2 Hints for Microsoft Office automation + +=over 8 + +=item Documentation + +The object model for the Office applications is defined in the Visual Basic +reference guides for the various applications. These are typically not +installed by default during the standard installation. They can be added +later by rerunning the setup program with the custom install option. + +=item Class, Method and Property names + +The names have been changed between different versions of Office. For +example C was a method in Office 95 and is a property in +Office97. Therefore it will not show up in the list of property names +C when querying an Office 95 object. + +The class names are not always identical to the method/property names +producing the object. E.g. the C method returns an object of +type C in Office 95 and C<_Workbook> in Office 97. + +=item Moniker (GetObject support) + +Office applications seem to implement file monikers only. For example +it seems to be impossible to retrieve a specific worksheet object through +C. Furthermore, in Excel 95 the moniker starts +a Worksheet object and in Excel 97 it returns a Workbook object. You can use +either the Win32::OLE::QueryObjectType class method or the $object->{Version} +property to write portable code. + +=item Enumeration of collection objects + +Enumerations seem to be incompletely implemented. Office 95 application don't +seem to support neither the Reset() nor the Clone() methods. The Clone() +method is still unimplemented in Office 97. A single walk through the +collection similar to Visual Basics C construct does work however. + +=item Localization + +Starting with Office 97 Microsoft has changed the localized class, method and +property names back into English. Note that string, date and currency +arguments are still subject to locale specific interpretation. Perl uses the +system default locale for all OLE transaction whereas Visual Basic uses a +type library specific locale. A Visual Basic script would use "R1C1" in string +arguments to specify relative references. A Perl script running on a German +language Windows would have to use "Z1S1". Set the LCID module option +to an English locale to write portable scripts. This variable should +not be changed after creating the OLE objects; some methods seem to randomly +fail if the locale is changed on the fly. + +=item SaveAs method in Word 97 doesn't work + +This is an known bug in Word 97. Search the MS knowledge base for Word / +Foxpro incompatibility. That problem applies to the Perl OLE interface as +well. A workaround is to use the WordBasic compatibility object. It doesn't +support all the options of the native method though. + + $Word->WordBasic->FileSaveAs($file); + +The problem seems to be fixed by applying the Office 97 Service Release 1. + +=item Randomly failing method calls + +It seems like modifying objects that are not selected/activated is sometimes +fragile. Most of these problems go away if the chart/sheet/document is +selected or activated before being manipulated (just like an interactive +user would automatically do it). + +=back + +=head2 Incompatibilities + +There are some incompatibilities with the version distributed by Activeware +(as of build 306). + +=over 8 + +=item 1 + +The package name has changed from "OLE" to "Win32::OLE". + +=item 2 + +All functions of the form "Win32::OLEFoo" are now "Win32::OLE::Foo", +though the old names are temporarily accomodated. Win32::OLECreateObject() +was changed to Win32::OLE::CreateObject(), and is now called +Win32::OLE::new() bowing to established convention for naming constructors. +The old names should be considered deprecated, and will be removed in the +next version. + +=item 3 + +Package "OLE::Variant" is now "Win32::OLE::Variant". + +=item 4 + +The Variant function is new, and is exported by default. So are +all the VT_XXX type constants. + +=item 5 + +The support for collection objects has been moved into the package +Win32::OLE::Enum. The C method is now used to enumerate +the properties of the object. + +=back + +=head2 Bugs and Limitations + +=over 8 + +=item * + +To invoke a native OLE method with the same name as one of the +Win32::OLE methods (C, C, C, C, +etc.), you have to use the C method: + + $Object->Invoke('Dispatch', @AdditionalArgs); + +The same is true for names exported by the Exporter or the Dynaloader +modules, e.g.: C, C, C, +C<_push_tags>, C, C, C, +C, C, +C, C, C, C, +C, C, C, +C, C and C. + +=back + +=head1 SEE ALSO + +The documentation for L, L, +L and L contains additional +information about OLE support for Perl on Win32. + +=head1 AUTHORS + +Originally put together by the kind people at Hip and Activeware. + +Gurusamy Sarathy subsequently fixed several +major bugs, memory leaks, and reliability problems, along with some +redesign of the code. + +Jan Dubois pitched in with yet more massive redesign, +added support for named parameters, and other significant enhancements. +He's been hacking on it ever since. + +Please send questions about problems with this module to the +Perl-Win32-Users mailinglist at ActiveState.com. The mailinglist charter +requests that you put an [OLE] tag somewhere on the subject line (for OLE +related questions only, of course). + +=head1 COPYRIGHT + + (c) 1995 Microsoft Corporation. All rights reserved. + Developed by ActiveWare Internet Corp., now known as + ActiveState Tool Corp., http://www.ActiveState.com + + Other modifications Copyright (c) 1997-2006 by Gurusamy Sarathy + and Jan Dubois + + You may distribute under the terms of either the GNU General Public + License or the Artistic License, as specified in the README file. + +=head1 VERSION + +Version 0.1709 17 April 2008 + +=cut diff --git a/Master/tlpkg/tlperl/lib/Win32/OLE/Const.pm b/Master/tlpkg/tlperl/lib/Win32/OLE/Const.pm new file mode 100644 index 00000000000..18456eebfe1 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/Win32/OLE/Const.pm @@ -0,0 +1,201 @@ +# The documentation is at the __END__ + +package Win32::OLE::Const; + +use strict; +use Carp; +use Win32::OLE; + +my $Typelibs; +sub _Typelib { + my ($clsid,$title,$version,$langid,$filename) = @_; + # Filenames might have a resource index appended to it. + $filename = $1 if $filename =~ /^(.*\.(?:dll|exe))(\\\d+)$/i; + # Ignore if it looks like a file but doesn't exist. + # We don't verify existance of monikers or filenames + # without a full pathname. + return unless -f $filename || $filename !~ /^\w:\\.*\.(exe|dll)$/; + push @$Typelibs, \@_; +} +unless (__PACKAGE__->_Typelibs("TypeLib")) { + warn("Cannot access HKEY_CLASSES_ROOT\\Typelib"); +} +# Enumerate 32bit type libraries on Win64 +__PACKAGE__->_Typelibs("Wow6432Node\\TypeLib"); + +sub import { + my ($self,$name,$major,$minor,$language,$codepage) = @_; + return unless defined($name) && $name !~ /^\s*$/; + $self->Load($name,$major,$minor,$language,$codepage,scalar caller); +} + +sub EnumTypeLibs { + my ($self,$callback) = @_; + foreach (@$Typelibs) { &$callback(@$_) } + return; +} + +sub Load { + my ($self,$name,$major,$minor,$language,$codepage,$caller) = @_; + + if (UNIVERSAL::isa($name,'Win32::OLE')) { + my $typelib = $name->GetTypeInfo->GetContainingTypeLib; + return _Constants($typelib, undef); + } + + undef $minor unless defined $major; + my $typelib = $self->LoadRegTypeLib($name,$major,$minor, + $language,$codepage); + return _Constants($typelib, $caller); +} + +sub LoadRegTypeLib { + my ($self,$name,$major,$minor,$language,$codepage) = @_; + undef $minor unless defined $major; + + unless (defined($name) && $name !~ /^\s*$/) { + carp "Win32::OLE::Const->Load: No or invalid type library name"; + return; + } + + my @found; + foreach my $Typelib (@$Typelibs) { + my ($clsid,$title,$version,$langid,$filename) = @$Typelib; + next unless $title =~ /^$name/; + next unless $version =~ /^([0-9a-fA-F]+)\.([0-9a-fA-F]+)$/; + my ($maj,$min) = (hex($1), hex($2)); + next if defined($major) && $maj != $major; + next if defined($minor) && $min < $minor; + next if defined($language) && $language != $langid; + push @found, [$clsid,$maj,$min,$langid,$filename]; + } + + unless (@found) { + carp "No type library matching \"$name\" found"; + return; + } + + @found = sort { + # Prefer greater version number + my $res = $b->[1] <=> $a->[1]; + $res = $b->[2] <=> $a->[2] if $res == 0; + # Prefer default language for equal version numbers + $res = -1 if $res == 0 && $a->[3] == 0; + $res = 1 if $res == 0 && $b->[3] == 0; + $res; + } @found; + + #printf "Loading %s\n", join(' ', @{$found[0]}); + return _LoadRegTypeLib(@{$found[0]},$codepage); +} + +1; + +__END__ + +=head1 NAME + +Win32::OLE::Const - Extract constant definitions from TypeLib + +=head1 SYNOPSIS + + use Win32::OLE::Const 'Microsoft Excel'; + printf "xlMarkerStyleDot = %d\n", xlMarkerStyleDot; + + my $wd = Win32::OLE::Const->Load("Microsoft Word 8\\.0 Object Library"); + foreach my $key (keys %$wd) { + printf "$key = %s\n", $wd->{$key}; + } + +=head1 DESCRIPTION + +This modules makes all constants from a registered OLE type library +available to the Perl program. The constant definitions can be +imported as functions, providing compile time name checking. +Alternatively the constants can be returned in a hash reference +which avoids defining lots of functions of unknown names. + +=head2 Functions/Methods + +=over 4 + +=item use Win32::OLE::Const + +The C statement can be used to directly import the constant names +and values into the users namespace. + + use Win32::OLE::Const (TYPELIB,MAJOR,MINOR,LANGUAGE); + +The TYPELIB argument specifies a regular expression for searching +through the registry for the type library. Note that this argument is +implicitly prefixed with C<^> to speed up matches in the most common +cases. Use a typelib name like ".*Excel" to match anywhere within the +description. TYPELIB is the only required argument. + +The MAJOR and MINOR arguments specify the requested version of +the type specification. If the MAJOR argument is used then only +typelibs with exactly this major version number will be matched. The +MINOR argument however specifies the minimum acceptable minor version. +MINOR is ignored if MAJOR is undefined. + +If the LANGUAGE argument is used then only typelibs with exactly this +language id will be matched. + +The module will select the typelib with the highest version number +satisfying the request. If no language id is specified then a the default +language (0) will be preferred over the others. + +Note that only constants with valid Perl variable names will be exported, +i.e. names matching this regexp: C. + +=item Win32::OLE::Const->Load + +The Win32::OLE::Const->Load method returns a reference to a hash of +constant definitions. + + my $const = Win32::OLE::Const->Load(TYPELIB,MAJOR,MINOR,LANGUAGE); + +The parameters are the same as for the C case. + +This method is generally preferrable when the typelib uses a non-english +language and the constant names contain locale specific characters not +allowed in Perl variable names. + +Another advantage is that all available constants can now be enumerated. + +The load method also accepts an OLE object as a parameter. In this case +the OLE object is queried about its containing type library and no registry +search is done at all. Interestingly this seems to be slower. + +=back + +=head1 EXAMPLES + +The first example imports all Excel constants names into the main namespace +and prints the value of xlMarkerStyleDot (-4118). + + use Win32::OLE::Const ('Microsoft Excel 8.0 Object Library'); + print "xlMarkerStyleDot = %d\n", xlMarkerStyleDot; + +The second example returns all Word constants in a hash ref. + + use Win32::OLE::Const; + my $wd = Win32::OLE::Const->Load("Microsoft Word 8.0 Object Library"); + foreach my $key (keys %$wd) { + printf "$key = %s\n", $wd->{$key}; + } + printf "wdGreen = %s\n", $wd->{wdGreen}; + +The last example uses an OLE object to specify the type library: + + use Win32::OLE; + use Win32::OLE::Const; + my $Excel = Win32::OLE->new('Excel.Application', 'Quit'); + my $xl = Win32::OLE::Const->Load($Excel); + + +=head1 AUTHORS/COPYRIGHT + +This module is part of the Win32::OLE distribution. + +=cut diff --git a/Master/tlpkg/tlperl/lib/Win32/OLE/Enum.pm b/Master/tlpkg/tlperl/lib/Win32/OLE/Enum.pm new file mode 100644 index 00000000000..6047d2c8274 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/Win32/OLE/Enum.pm @@ -0,0 +1,95 @@ +# The documentation is at the __END__ + +package Win32::OLE::Enum; +1; + +# everything is pure XS in Win32::OLE::Enum +# - new +# - DESTROY +# +# - All +# - Clone +# - Next +# - Reset +# - Skip + +__END__ + +=head1 NAME + +Win32::OLE::Enum - OLE Automation Collection Objects + +=head1 SYNOPSIS + + my $Sheets = $Excel->Workbooks(1)->Worksheets; + my $Enum = Win32::OLE::Enum->new($Sheets); + my @Sheets = $Enum->All; + + while (defined(my $Sheet = $Enum->Next)) { ... } + +=head1 DESCRIPTION + +This module provides an interface to OLE collection objects from +Perl. It defines an enumerator object closely mirroring the +functionality of the IEnumVARIANT interface. + +Please note that the Reset() method is not available in all implementations +of OLE collections (like Excel 7). In that case the Enum object is good +only for a single walk through of the collection. + +=head2 Functions/Methods + +=over 8 + +=item Win32::OLE::Enum->new($object) + +Creates an enumerator for $object, which must be a valid OLE collection +object. Note that correctly implemented collection objects must support +the C and C methods, so creating an enumerator is not always +necessary. + +=item $Enum->All() + +Returns a list of all objects in the collection. You have to call +$Enum->Reset() before the enumerator can be used again. The previous +position in the collection is lost. + +This method can also be called as a class method: + + my @list = Win32::OLE::Enum->All($Collection); + +=item $Enum->Clone() + +Returns a clone of the enumerator maintaining the current position within +the collection (if possible). Note that the C method is often not +implemented. Use $Enum->Clone() in an eval block to avoid dying if you +are not sure that Clone is supported. + +=item $Enum->Next( [$count] ) + +Returns the next element of the collection. In a list context the optional +$count argument specifies the number of objects to be returned. In a scalar +context only the last of at most $count retrieved objects is returned. The +default for $count is 1. + +=item $Enum->Reset() + +Resets the enumeration sequence to the beginning. There is no guarantee that +the exact same set of objects will be enumerated again (e.g. when enumerating +files in a directory). The methods return value indicates the success of the +operation. (Note that the Reset() method seems to be unimplemented in some +applications like Excel 7. Use it in an eval block to avoid dying.) + +=item $Enum->Skip( [$count] ) + +Skip the next $count elements of the enumeration. The default for $count is 1. +The functions returns TRUE if at least $count elements could be skipped. It +returns FALSE if not enough elements were left. + +=back + +=head1 AUTHORS/COPYRIGHT + +This module is part of the Win32::OLE distribution. + +=cut diff --git a/Master/tlpkg/tlperl/lib/Win32/OLE/Lite.pm b/Master/tlpkg/tlperl/lib/Win32/OLE/Lite.pm new file mode 100644 index 00000000000..66b5e50ac0e --- /dev/null +++ b/Master/tlpkg/tlperl/lib/Win32/OLE/Lite.pm @@ -0,0 +1,224 @@ +package Win32::OLE; + +sub _croak { require Carp; Carp::croak(@_) } + +unless (defined &Dispatch) { + DynaLoader::boot_DynaLoader('DynaLoader') + unless defined(&DynaLoader::dl_load_file); + my $file; + foreach my $dir (@INC) { + my $try = "$dir/auto/Win32/OLE/OLE.dll"; + last if $file = (-f $try && $try); + } + _croak("Can't locate loadable object for module Win32::OLE". + " in \@INC (\@INC contains: @INC)") + unless $file; # wording similar to error from 'require' + + my $libref = DynaLoader::dl_load_file($file, 0) or + _croak("Can't load '$file' for module Win32::OLE: ". + DynaLoader::dl_error()."\n"); + + my $boot_symbol_ref = DynaLoader::dl_find_symbol($libref, "boot_Win32__OLE") + or _croak("Can't find 'boot_Win32__OLE' symbol in $file\n"); + + my $xs = DynaLoader::dl_install_xsub("Win32::OLE::bootstrap", + $boot_symbol_ref, $file); + &$xs('Win32::OLE'); +} + +if (defined &DB::sub && !defined $_Unique) { + warn "Win32::OLE operating in debugging mode: _Unique => 1\n"; + $_Unique = 1; +} + +$Warn = 1; + +sub CP_ACP {0;} # ANSI codepage +sub CP_OEMCP {1;} # OEM codepage +sub CP_MACCP {2;} +sub CP_UTF7 {65000;} +sub CP_UTF8 {65001;} + +sub DISPATCH_METHOD {1;} +sub DISPATCH_PROPERTYGET {2;} +sub DISPATCH_PROPERTYPUT {4;} +sub DISPATCH_PROPERTYPUTREF {8;} + +sub COINIT_MULTITHREADED {0;} # Default +sub COINIT_APARTMENTTHREADED {2;} # Use single threaded apartment model + +# Bogus COINIT_* values to indicate special cases: +sub COINIT_OLEINITIALIZE {-1;} # Use OleInitialize instead of CoInitializeEx +sub COINIT_NO_INITIALIZE {-2;} # We are already initialized, just believe me + +sub HRESULT { + my $hr = shift; + $hr -= 2**32 if $hr & 0x80000000; + return $hr; +} + +# CreateObject is defined here only because it is documented in the +# "Learning Perl on Win32 Systems" Gecko book. Please use Win32::OLE->new(). +sub CreateObject { + if (ref($_[0]) && UNIVERSAL::isa($_[0],'Win32::OLE')) { + $AUTOLOAD = ref($_[0]) . '::CreateObject'; + goto &AUTOLOAD; + } + + # Hack to allow C<$obj = CreateObject Win32::OLE 'My.App';>. Although this + # is contrary to the Gecko, we just make it work since it doesn't hurt. + return Win32::OLE->new($_[1]) if $_[0] eq 'Win32::OLE'; + + # Gecko form: C<$success = Win32::OLE::CreateObject('My.App',$obj);> + $_[1] = Win32::OLE->new($_[0]); + return defined $_[1]; +} + +sub LastError { + unless (defined $_[0]) { + # Win32::OLE::LastError() will always return $Win32::OLE::LastError + return $LastError; + } + + if (ref($_[0]) && UNIVERSAL::isa($_[0],'Win32::OLE')) { + $AUTOLOAD = ref($_[0]) . '::LastError'; + goto &AUTOLOAD; + } + + #no strict 'refs'; + my $LastError = "$_[0]::LastError"; + $$LastError = $_[1] if defined $_[1]; + return $$LastError; +} + +my $Options = "^(?:CP|LCID|Warn|Variant|_NewEnum|_Unique)\$"; + +sub Option { + if (ref($_[0]) && UNIVERSAL::isa($_[0],'Win32::OLE')) { + $AUTOLOAD = ref($_[0]) . '::Option'; + goto &AUTOLOAD; + } + + my $class = shift; + + if (@_ == 1) { + my $option = shift; + return ${"${class}::$option"} if $option =~ /$Options/o; + _croak("Invalid $class option: $option"); + } + + while (@_) { + my ($option,$value) = splice @_, 0, 2; + _croak("Invalid $class option: $option") if $option !~ /$Options/o; + ${"${class}::$option"} = $value; + $class->_Unique() if $option eq "_Unique"; + } +} + +sub Invoke { + my ($self,$method,@args) = @_; + $self->Dispatch($method, my $retval, @args); + return $retval; +} + +sub LetProperty { + my ($self,$method,@args) = @_; + $self->Dispatch([DISPATCH_PROPERTYPUT, $method], my $retval, @args); + return $retval; +} + +sub SetProperty { + my ($self,$method,@args) = @_; + my $wFlags = DISPATCH_PROPERTYPUT; + if (@args) { + # If the value is an object then it will be set by reference! + my $value = $args[-1]; + if (UNIVERSAL::isa($value, 'Win32::OLE')) { + $wFlags = DISPATCH_PROPERTYPUTREF; + } + elsif (UNIVERSAL::isa($value,'Win32::OLE::Variant')) { + my $type = $value->Type & ~0xfff; # VT_TYPEMASK + # VT_DISPATCH and VT_UNKNOWN represent COM objects + $wFlags = DISPATCH_PROPERTYPUTREF if $type == 9 || $type == 13; + } + } + $self->Dispatch([$wFlags, $method], my $retval, @args); + return $retval; +} + +sub AUTOLOAD { + my $self = shift; + my $autoload = substr $AUTOLOAD, rindex($AUTOLOAD, ':')+1; + _croak("Cannot autoload class method \"$autoload\"") + unless ref($self) && UNIVERSAL::isa($self, 'Win32::OLE'); + my $success = $self->Dispatch($autoload, my $retval, @_); + unless (defined $success || ($^H & 0x200) != 0) { + # Retry default method if C + $self->Dispatch(undef, $retval, $autoload, @_); + } + return $retval; +} + +sub in { + my @res; + while (@_) { + my $this = shift; + if (UNIVERSAL::isa($this, 'Win32::OLE')) { + push @res, Win32::OLE::Enum->All($this); + } + elsif (ref($this) eq 'ARRAY') { + push @res, @$this; + } + else { + push @res, $this; + } + } + return @res; +} + +sub valof { + my $arg = shift; + if (UNIVERSAL::isa($arg, 'Win32::OLE')) { + require Win32::OLE::Variant; + my ($class) = overload::StrVal($arg) =~ /^([^=]+)=/; + #no strict 'refs'; + local $Win32::OLE::CP = ${"${class}::CP"}; + local $Win32::OLE::LCID = ${"${class}::LCID"}; + #use strict 'refs'; + # VT_EMPTY variant for return code + my $variant = Win32::OLE::Variant->new; + $arg->Dispatch(undef, $variant); + return $variant->Value; + } + $arg = $arg->Value if UNIVERSAL::can($arg, 'Value'); + return $arg; +} + +sub with { + my $object = shift; + while (@_) { + my $property = shift; + $object->{$property} = shift; + } +} + +######################################################################## + +package Win32::OLE::Tie; + +# Only retry default method under C +sub FETCH { + my ($self,$key) = @_; + if ($key eq "_NewEnum") { + (my $class = ref $self) =~ s/::Tie$//; + return [Win32::OLE::Enum->All($self)] if ${"${class}::_NewEnum"}; + } + $self->Fetch($key, !$Win32::OLE::Strict); +} + +sub STORE { + my ($self,$key,$value) = @_; + $self->Store($key, $value, !$Win32::OLE::Strict); +} + +1; diff --git a/Master/tlpkg/tlperl/lib/Win32/OLE/NEWS.pod b/Master/tlpkg/tlperl/lib/Win32/OLE/NEWS.pod new file mode 100644 index 00000000000..1de6b7ce0a5 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/Win32/OLE/NEWS.pod @@ -0,0 +1,380 @@ +=pod + +=head1 NAME + +Win32::OLE::NEWS - What's new in Win32::OLE + +This file contains a history of user visible changes to the +Win32::OLE::* modules. Only new features and major bug fixes that +might affect backwards compatibility are included. + +=head1 Version 0.18 + +=head2 VT_CY and VT_DECIMAL return values handled differently + +The new C option enables values of VT_CY or VT_DECIMAL type +to be returned as Win32::OLE::Variant objects instead of being +converted into strings and numbers respectively. This is similar to +the change in Win32::OLE version 0.12 to VT_DATE and VT_ERROR values. +The Win32::OLE::Variant module must be included to make sure that +VT_CY and VT_DECIMAL values behave as before in numeric or string +contexts. + +Because the new behavior is potentially incompatible, it must be +explicitly enabled: + + Win32::OLE->Option(Variant => 1); + + +=head1 Version 0.17 + +=head2 New nullstring() function in Win32::OLE::Variant + +The nullstring() function returns a VT_BSTR variant containing a NULL +string pointer. Note that this is not the same as a VT_BSTR variant +containing the empty string "". + +The nullstring() return value is equivalent to the Visual Basic +C constant. + + +=head1 Version 0.16 + +=head2 Improved Unicode support + +Passing Unicode strings to methods and properties as well as returning +Unicode strings back to Perl works now with both Perl 5.6 and 5.8. +Note that the Unicode support in 5.8 is much more complete than in 5.6 +or 5.6.1. + +C objects can now be passed to methods or assigned to +properties. + +You must enable Unicode support by switching Win32::OLE to the UTF8 +codepage: + + Win32::OLE->Option(CP => Win32::OLE::CP_UTF8()); + + +=head1 Version 0.13 + +=head2 New nothing() function in Win32::OLE::Variant + +The nothing() function returns an empty VT_DISPATCH variant. It can be +used to clear an object reference stored in a property + + use Win32::OLE::Variant qw(:DEFAULT nothing); + # ... + $object->{Property} = nothing; + +This has the same effect as the Visual Basic statement + + Set object.Property = Nothing + +=head2 New _NewEnum and _Unique options + +There are two new options available for the Win32::OLE->Option class +method: C<_NewEnum> provides the elements of a collection object +directly as the value of a C<_NewEnum> property. The C<_Unique> +option guarantees that Win32::OLE will not create multiple proxy +objects for the same underlying COM/OLE object. + +Both options are only really useful to tree traversal programs or +during debugging. + + +=head1 Version 0.12 + +=head2 Additional error handling functionality + +The Warn option can now be set to a CODE reference too. For example, + + Win32::OLE->Option(Warn => 3); + +could now be written as + + Win32::OLE->Option(Warn => \&Carp::croak); + +This can even be used to emulate the VisualBasic C construct: + + Win32::OLE->Option(Warn => sub {goto CheckError}); + # ... your normal OLE code here ... + + CheckError: + # ... your error handling code here ... + +=head2 Builtin event loop + +Processing OLE events required a polling loop before, e.g. + + my $Quit; + #... + until ($Quit) { + Win32::OLE->SpinMessageLoop; + Win32::Sleep(100); + } + package BrowserEvents; + sub OnQuit { $Quit = 1 } + +This is inefficient and a bit odd. This version of Win32::OLE now +supports a standard messageloop: + + Win32::OLE->MessageLoop(); + + package BrowserEvents; + sub OnQuit { Win32::OLE->QuitMessageLoop } + +=head2 Free unused OLE libraries + +Previous versions of Win32::OLE would call the CoFreeUnusedLibraries() +API whenever an OLE object was destroyed. This made sure that OLE +libraries would be unloaded as soon as they were no longer needed. +Unfortunately, objects implemented in Visual Basic tend to crash +during this call, as they pretend to be ready for unloading, when in +fact, they aren't. + +The unloading of object libraries is really only important for long +running processes that might instantiate a huge number of B +objects over time. Therefore this API is no longer called +automatically. The functionality is now available explicitly to those +who want or need it by calling a Win32::OLE class method: + + Win32::OLE->FreeUnusedLibraries(); + +=head2 The "Win32::OLE" article from "The Perl Journal #10" + +The article is Copyright 1998 by I. http://www.tpj.com + +It originally appeared in I # 10 and appears here +courtesy of Jon Orwant and I. The sample code from +the article is in the F file. + +=head2 VARIANT->Put() bug fixes + +The Put() method didn't work correctly for arrays of type VT_BSTR, +VT_DISPATH or VT_UNKNOWN. This has been fixed. + +=head2 Error message fixes + +Previous versions of Win32::OLE gave a wrong argument index for some +OLE error messages (the number was too large by 1). This should be +fixed now. + +=head2 VT_DATE and VT_ERROR return values handled differently + +Method calls and property accesses returning a VT_DATE or VT_ERROR +value would previously translate the value to string or integer +format. This has been changed to return a Win32::OLE::Variant object. +The return values will behave as before if the Win32::OLE::Variant +module is being used. This module overloads the conversion of +the objects to strings and numbers. + + +=head1 Version 0.11 (changes since 0.1008) + +=head2 new DHTML typelib browser + +The Win32::OLE distribution now contains a type library browser. It +is written in PerlScript, generating dynamic HTML. It requires +Internet Explorer 4.0 or later. You'll find it in +F. It should be available in the ActivePerl +HTML help under Win32::OLE::Browser. + +After selecting a library, type or member you can press F1 to call up +the corresponding help file at the appropriate location. + +=head2 VT_DECIMAL support + +The Win32::OLE::Variant module now supports VT_DECIMAL variants too. +They are not "officially" allowed in OLE Automation calls, but even +Microsoft's "ActiveX Data Objects" sometimes returns VT_DECIMAL +values. + +VT_DECIMAL variables are stored as 96-bit integers scaled by a +variable power of 10. The power of 10 scaling factor specifies the +number of digits to the right of the decimal point, and ranges from 0 +to 28. With a scale of 0 (no decimal places), the largest possible +value is +/-79,228,162,514,264,337,593,543,950,335. With a 28 decimal +places, the largest value is +/-7.9228162514264337593543950335 and the +smallest, non-zero value is +/-0.0000000000000000000000000001. + +=head1 Version 0.1008 + +=head2 new LetProperty() object method + +In Win32::OLE property assignment using the hash syntax is equivalent +to the Visual Basic C syntax (I assignment): + + $Object->{Property} = $OtherObject; + +corresponds to this Visual Basic statement: + + Set Object.Property = OtherObject + +To get the I treatment of the Visual Basic C statement + + Object.Property = OtherObject + +you have to use the LetProperty() object method in Perl: + + $Object->LetProperty($Property, $OtherObject); + +=head2 new HRESULT() function + +The HRESULT() function converts an unsigned number into a signed HRESULT +error value as used by OLE internally. This is necessary because Perl +treats all hexadecimal constants as unsigned. To check if the last OLE +function returned "Member not found" (0x80020003) you can write: + + if (Win32::OLE->LastError == HRESULT(0x80020003)) { + # your error recovery here + } + +=head1 Version 0.1007 (changes since 0.1005) + +=head2 OLE Event support + +This version of Win32::OLE contains B level support for OLE events. The +userinterface is still subject to change. There are ActiveX objects / controls +that don't fire events under the current implementation. + +Events are enabled for a specific object with the Win32::OLE->WithEvents() +class method: + + Win32::OLE->WithEvents(OBJECT, HANDLER, INTERFACE) + +Please read further documentation in Win32::OLE. + +=head2 GetObject() and GetActiveObject() now support optional DESTRUCTOR argument + +It is now possible to specify a DESTRUCTOR argument to the GetObject() and +GetActiveObject() class methods. They work identical to the new() DESTRUCTOR +argument. + +=head2 Remote object instantiation via DCOM + +This has actually been in Win32::OLE since 0.0608, but somehow never got +documented. You can provide an array reference in place of the usual PROGID +parameter to Win32::OLE->new(): + + OBJ = Win32::OLE->new([MACHINE, PRODID]); + +The array must contain two elements: the name of the MACHINE and the PROGID. +This will try to create the object on the remote MACHINE. + +=head2 Enumerate all Win32::OLE objects + +This class method returns the number Win32::OLE objects currently in +existance. It will call the optional CALLBACK function for each of +these objects: + + $Count = Win32::OLE->EnumAllObjects(sub { + my $Object = shift; + my $Class = Win32::OLE->QueryObjectType($Object); + printf "# Object=%s Class=%s\n", $Object, $Class; + }); + +The EnumAllObjects() method is primarily a debugging tool. It can be +used e.g. in an END block to check if all external connections have +been properly destroyed. + +=head2 The VARIANT->Put() method now returns the VARIANT object itself + +This allows chaining of Put() method calls to set multiple values in an +array variant: + + $Array->Put(0,0,$First_value)->Put(0,1,$Another_value); + +=head2 The VARIANT->Put(ARRAYREF) form allows assignment to a complete SAFEARRAY + +This allows automatic conversion from a list of lists to a SAFEARRAY. +You can now write: + + my $Array = Variant(VT_ARRAY|VT_R8, [1,2], 2); + $Array->Put([[1,2], [3,4]]); + +instead of the tedious: + + $Array->Put(1,0,1); + $Array->Put(1,1,2); + $Array->Put(2,0,3); + $Array->Put(2,1,4); + +=head2 New Variant formatting methods + +There are four new methods for formatting variant values: Currency(), Date(), +Number() and Time(). For example: + + my $v = Variant(VT_DATE, "April 1 99"); + print $v->Date(DATE_LONGDATE), "\n"; + print $v->Date("ddd',' MMM dd yy"), "\n"; + +will print: + + Thursday, April 01, 1999 + Thu, Apr 01 99 + +=head2 new Win32::OLE::NLS methods: SendSettingChange() and SetLocaleInfo() + +SendSettingChange() sends a WM_SETTINGCHANGE message to all top level windows. + +SetLocaleInfo() allows changing elements in the user override section of the +locale database. Unfortunately these changes are not automatically available +to further Variant formatting; you have to call SendSettingChange() first. + +=head2 Win32::OLE::Const now correctly treats version numbers as hex + +The minor and major version numbers of type libraries have been treated as +decimal. This was wrong. They are now correctly decoded as hex. + +=head2 more robust global destruction of Win32::OLE objects + +The final destruction of Win32::OLE objects has always been somewhat fragile. +The reason for this is that Perl doesn't honour reference counts during global +destruction but destroys objects in seemingly random order. This can lead +to leaked database connections or unterminated external objects. The only +solution was to make all objects lexical and hope that no object would be +trapped in a closure. Alternatively all objects could be explicitly set to +C, which doesn't work very well with exception handling. + +With version 0.1007 of Win32::OLE this problem should be gone: The module +keeps a list of active Win32::OLE objects. It uses an END block to destroy +all objects at program termination I the Perl's global destruction +starts. Objects still existing at program termination are now destroyed in +reverse order of creation. The effect is similar to explicitly calling +Win32::OLE->Uninitialize() just prior to termination. + +=head1 Version 0.1005 (changes since 0.1003) + +Win32::OLE 0.1005 has been release with ActivePerl build 509. It is also +included in the I Update. + +=head2 optional DESTRUCTOR for GetActiveObject() GetObject() class methods + +The GetActiveObject() and GetObject() class method now also support an +optional DESTRUCTOR parameter just like Win32::OLE->new(). The DESTRUCTOR +is executed when the last reference to this object goes away. It is +generally considered C to stop applications that you did not +start yourself. + +=head2 new Variant object method: $object->Copy() + +See L. + +=head2 new Win32::OLE->Option() class method + +The Option() class method can be used to inspect and modify +L. The single argument form retrieves +the value of an option: + + my $CP = Win32::OLE->Option('CP'); + +A single call can be used to set multiple options simultaneously: + + Win32::OLE->Option(CP => CP_ACP, Warn => 3); + +Currently the following options exist: CP, LCID and C. + +=cut diff --git a/Master/tlpkg/tlperl/lib/Win32/OLE/NLS.pm b/Master/tlpkg/tlperl/lib/Win32/OLE/NLS.pm new file mode 100644 index 00000000000..dc93f3b91c2 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/Win32/OLE/NLS.pm @@ -0,0 +1,968 @@ +# The documentation is at the __END__ + +package Win32::OLE::NLS; +require Win32::OLE; # Make sure the XS bootstrap has been called + +use strict; +use vars qw(@EXPORT @EXPORT_OK %EXPORT_TAGS @ISA); + +use Exporter; +@ISA = qw(Exporter); + +@EXPORT = qw( + CompareString + LCMapString + GetLocaleInfo + GetStringType + GetSystemDefaultLangID + GetSystemDefaultLCID + GetUserDefaultLangID + GetUserDefaultLCID + + MAKELANGID + PRIMARYLANGID + SUBLANGID + LANG_SYSTEM_DEFAULT + LANG_USER_DEFAULT + MAKELCID + LANGIDFROMLCID + LOCALE_SYSTEM_DEFAULT + LOCALE_USER_DEFAULT + ); + +@EXPORT_OK = qw(SetLocaleInfo SendSettingChange); + +%EXPORT_TAGS = +( + CT => [qw(CT_CTYPE1 CT_CTYPE2 CT_CTYPE3)], + C1 => [qw(C1_UPPER C1_LOWER C1_DIGIT C1_SPACE C1_PUNCT + C1_CNTRL C1_BLANK C1_XDIGIT C1_ALPHA)], + C2 => [qw(C2_LEFTTORIGHT C2_RIGHTTOLEFT C2_EUROPENUMBER + C2_EUROPESEPARATOR C2_EUROPETERMINATOR C2_ARABICNUMBER + C2_COMMONSEPARATOR C2_BLOCKSEPARATOR C2_SEGMENTSEPARATOR + C2_WHITESPACE C2_OTHERNEUTRAL C2_NOTAPPLICABLE)], + C3 => [qw(C3_NONSPACING C3_DIACRITIC C3_VOWELMARK C3_SYMBOL C3_KATAKANA + C3_HIRAGANA C3_HALFWIDTH C3_FULLWIDTH C3_IDEOGRAPH C3_KASHIDA + C3_ALPHA C3_NOTAPPLICABLE)], + NORM => [qw(NORM_IGNORECASE NORM_IGNORENONSPACE NORM_IGNORESYMBOLS + NORM_IGNOREWIDTH NORM_IGNOREKANATYPE NORM_IGNOREKASHIDA)], + LCMAP => [qw(LCMAP_LOWERCASE LCMAP_UPPERCASE LCMAP_SORTKEY LCMAP_HALFWIDTH + LCMAP_FULLWIDTH LCMAP_HIRAGANA LCMAP_KATAKANA)], + LANG => [qw(LANG_NEUTRAL LANG_ALBANIAN LANG_ARABIC LANG_BAHASA + LANG_BULGARIAN LANG_CATALAN LANG_CHINESE LANG_CZECH LANG_DANISH + LANG_DUTCH LANG_ENGLISH LANG_FINNISH LANG_FRENCH LANG_GERMAN + LANG_GREEK LANG_HEBREW LANG_HUNGARIAN LANG_ICELANDIC + LANG_ITALIAN LANG_JAPANESE LANG_KOREAN LANG_NORWEGIAN + LANG_POLISH LANG_PORTUGUESE LANG_RHAETO_ROMAN LANG_ROMANIAN + LANG_RUSSIAN LANG_SERBO_CROATIAN LANG_SLOVAK LANG_SPANISH + LANG_SWEDISH LANG_THAI LANG_TURKISH LANG_URDU)], + SUBLANG => [qw(SUBLANG_NEUTRAL SUBLANG_DEFAULT SUBLANG_SYS_DEFAULT + SUBLANG_CHINESE_SIMPLIFIED SUBLANG_CHINESE_TRADITIONAL + SUBLANG_DUTCH SUBLANG_DUTCH_BELGIAN SUBLANG_ENGLISH_US + SUBLANG_ENGLISH_UK SUBLANG_ENGLISH_AUS SUBLANG_ENGLISH_CAN + SUBLANG_ENGLISH_NZ SUBLANG_ENGLISH_EIRE SUBLANG_FRENCH + SUBLANG_FRENCH_BELGIAN SUBLANG_FRENCH_CANADIAN + SUBLANG_FRENCH_SWISS SUBLANG_GERMAN SUBLANG_GERMAN_SWISS + SUBLANG_GERMAN_AUSTRIAN SUBLANG_ITALIAN SUBLANG_ITALIAN_SWISS + SUBLANG_NORWEGIAN_BOKMAL SUBLANG_NORWEGIAN_NYNORSK + SUBLANG_PORTUGUESE SUBLANG_PORTUGUESE_BRAZILIAN + SUBLANG_SERBO_CROATIAN_CYRILLIC SUBLANG_SERBO_CROATIAN_LATIN + SUBLANG_SPANISH SUBLANG_SPANISH_MEXICAN + SUBLANG_SPANISH_MODERN)], + CTRY => [qw(CTRY_DEFAULT CTRY_AUSTRALIA CTRY_AUSTRIA CTRY_BELGIUM + CTRY_BRAZIL CTRY_CANADA CTRY_DENMARK CTRY_FINLAND CTRY_FRANCE + CTRY_GERMANY CTRY_ICELAND CTRY_IRELAND CTRY_ITALY CTRY_JAPAN + CTRY_MEXICO CTRY_NETHERLANDS CTRY_NEW_ZEALAND CTRY_NORWAY + CTRY_PORTUGAL CTRY_PRCHINA CTRY_SOUTH_KOREA CTRY_SPAIN + CTRY_SWEDEN CTRY_SWITZERLAND CTRY_TAIWAN CTRY_UNITED_KINGDOM + CTRY_UNITED_STATES)], + LOCALE => [qw(LOCALE_NOUSEROVERRIDE LOCALE_ILANGUAGE LOCALE_SLANGUAGE + LOCALE_SENGLANGUAGE LOCALE_SABBREVLANGNAME + LOCALE_SNATIVELANGNAME LOCALE_ICOUNTRY LOCALE_SCOUNTRY + LOCALE_SENGCOUNTRY LOCALE_SABBREVCTRYNAME LOCALE_SNATIVECTRYNAME + LOCALE_IDEFAULTLANGUAGE LOCALE_IDEFAULTCOUNTRY + LOCALE_IDEFAULTCODEPAGE LOCALE_IDEFAULTANSICODEPAGE LOCALE_SLIST + LOCALE_IMEASURE LOCALE_SDECIMAL LOCALE_STHOUSAND + LOCALE_SGROUPING LOCALE_IDIGITS LOCALE_ILZERO LOCALE_INEGNUMBER + LOCALE_SNATIVEDIGITS LOCALE_SCURRENCY LOCALE_SINTLSYMBOL + LOCALE_SMONDECIMALSEP LOCALE_SMONTHOUSANDSEP LOCALE_SMONGROUPING + LOCALE_ICURRDIGITS LOCALE_IINTLCURRDIGITS LOCALE_ICURRENCY + LOCALE_INEGCURR LOCALE_SDATE LOCALE_STIME LOCALE_SSHORTDATE + LOCALE_SLONGDATE LOCALE_STIMEFORMAT LOCALE_IDATE LOCALE_ILDATE + LOCALE_ITIME LOCALE_ITIMEMARKPOSN LOCALE_ICENTURY LOCALE_ITLZERO + LOCALE_IDAYLZERO LOCALE_IMONLZERO LOCALE_S1159 LOCALE_S2359 + LOCALE_ICALENDARTYPE LOCALE_IOPTIONALCALENDAR + LOCALE_IFIRSTDAYOFWEEK LOCALE_IFIRSTWEEKOFYEAR LOCALE_SDAYNAME1 + LOCALE_SDAYNAME2 LOCALE_SDAYNAME3 LOCALE_SDAYNAME4 + LOCALE_SDAYNAME5 LOCALE_SDAYNAME6 LOCALE_SDAYNAME7 + LOCALE_SABBREVDAYNAME1 LOCALE_SABBREVDAYNAME2 + LOCALE_SABBREVDAYNAME3 LOCALE_SABBREVDAYNAME4 + LOCALE_SABBREVDAYNAME5 LOCALE_SABBREVDAYNAME6 + LOCALE_SABBREVDAYNAME7 LOCALE_SMONTHNAME1 LOCALE_SMONTHNAME2 + LOCALE_SMONTHNAME3 LOCALE_SMONTHNAME4 LOCALE_SMONTHNAME5 + LOCALE_SMONTHNAME6 LOCALE_SMONTHNAME7 LOCALE_SMONTHNAME8 + LOCALE_SMONTHNAME9 LOCALE_SMONTHNAME10 LOCALE_SMONTHNAME11 + LOCALE_SMONTHNAME12 LOCALE_SMONTHNAME13 LOCALE_SABBREVMONTHNAME1 + LOCALE_SABBREVMONTHNAME2 LOCALE_SABBREVMONTHNAME3 + LOCALE_SABBREVMONTHNAME4 LOCALE_SABBREVMONTHNAME5 + LOCALE_SABBREVMONTHNAME6 LOCALE_SABBREVMONTHNAME7 + LOCALE_SABBREVMONTHNAME8 LOCALE_SABBREVMONTHNAME9 + LOCALE_SABBREVMONTHNAME10 LOCALE_SABBREVMONTHNAME11 + LOCALE_SABBREVMONTHNAME12 LOCALE_SABBREVMONTHNAME13 + LOCALE_SPOSITIVESIGN LOCALE_SNEGATIVESIGN LOCALE_IPOSSIGNPOSN + LOCALE_INEGSIGNPOSN LOCALE_IPOSSYMPRECEDES LOCALE_IPOSSEPBYSPACE + LOCALE_INEGSYMPRECEDES LOCALE_INEGSEPBYSPACE)], + TIME => [qw(TIME_NOMINUTESORSECONDS TIME_NOSECONDS TIME_NOTIMEMARKER + TIME_FORCE24HOURFORMAT)], + DATE => [qw(DATE_SHORTDATE DATE_LONGDATE DATE_USE_ALT_CALENDAR + DATE_YEARMONTH DATE_LTRREADING DATE_RTLREADING)], +); + +foreach my $tag (keys %EXPORT_TAGS) { + push @EXPORT_OK, @{$EXPORT_TAGS{$tag}}; +} + +# Character Type Flags +sub CT_CTYPE1 { 0x0001 } +sub CT_CTYPE2 { 0x0002 } +sub CT_CTYPE3 { 0x0004 } + +# Character Type 1 Bits +sub C1_UPPER { 0x0001 } +sub C1_LOWER { 0x0002 } +sub C1_DIGIT { 0x0004 } +sub C1_SPACE { 0x0008 } +sub C1_PUNCT { 0x0010 } +sub C1_CNTRL { 0x0020 } +sub C1_BLANK { 0x0040 } +sub C1_XDIGIT { 0x0080 } +sub C1_ALPHA { 0x0100 } + +# Character Type 2 Bits +sub C2_LEFTTORIGHT { 0x1 } +sub C2_RIGHTTOLEFT { 0x2 } +sub C2_EUROPENUMBER { 0x3 } +sub C2_EUROPESEPARATOR { 0x4 } +sub C2_EUROPETERMINATOR { 0x5 } +sub C2_ARABICNUMBER { 0x6 } +sub C2_COMMONSEPARATOR { 0x7 } +sub C2_BLOCKSEPARATOR { 0x8 } +sub C2_SEGMENTSEPARATOR { 0x9 } +sub C2_WHITESPACE { 0xA } +sub C2_OTHERNEUTRAL { 0xB } +sub C2_NOTAPPLICABLE { 0x0 } + +# Character Type 3 Bits +sub C3_NONSPACING { 0x0001 } +sub C3_DIACRITIC { 0x0002 } +sub C3_VOWELMARK { 0x0004 } +sub C3_SYMBOL { 0x0008 } +sub C3_KATAKANA { 0x0010 } +sub C3_HIRAGANA { 0x0020 } +sub C3_HALFWIDTH { 0x0040 } +sub C3_FULLWIDTH { 0x0080 } +sub C3_IDEOGRAPH { 0x0100 } +sub C3_KASHIDA { 0x0200 } +sub C3_ALPHA { 0x8000 } +sub C3_NOTAPPLICABLE { 0x0 } + +# String Flags +sub NORM_IGNORECASE { 0x0001 } +sub NORM_IGNORENONSPACE { 0x0002 } +sub NORM_IGNORESYMBOLS { 0x0004 } +sub NORM_IGNOREWIDTH { 0x0008 } +sub NORM_IGNOREKANATYPE { 0x0040 } +sub NORM_IGNOREKASHIDA { 0x40000} + +# Locale Dependent Mapping Flags +sub LCMAP_LOWERCASE { 0x0100 } +sub LCMAP_UPPERCASE { 0x0200 } +sub LCMAP_SORTKEY { 0x0400 } +sub LCMAP_HALFWIDTH { 0x0800 } +sub LCMAP_FULLWIDTH { 0x1000 } +sub LCMAP_HIRAGANA { 0x2000 } +sub LCMAP_KATAKANA { 0x4000 } + +# Primary Language Identifier +sub LANG_NEUTRAL { 0x00 } +sub LANG_ALBANIAN { 0x1c } +sub LANG_ARABIC { 0x01 } +sub LANG_BAHASA { 0x21 } +sub LANG_BULGARIAN { 0x02 } +sub LANG_CATALAN { 0x03 } +sub LANG_CHINESE { 0x04 } +sub LANG_CZECH { 0x05 } +sub LANG_DANISH { 0x06 } +sub LANG_DUTCH { 0x13 } +sub LANG_ENGLISH { 0x09 } +sub LANG_FINNISH { 0x0b } +sub LANG_FRENCH { 0x0c } +sub LANG_GERMAN { 0x07 } +sub LANG_GREEK { 0x08 } +sub LANG_HEBREW { 0x0d } +sub LANG_HUNGARIAN { 0x0e } +sub LANG_ICELANDIC { 0x0f } +sub LANG_ITALIAN { 0x10 } +sub LANG_JAPANESE { 0x11 } +sub LANG_KOREAN { 0x12 } +sub LANG_NORWEGIAN { 0x14 } +sub LANG_POLISH { 0x15 } +sub LANG_PORTUGUESE { 0x16 } +sub LANG_RHAETO_ROMAN { 0x17 } +sub LANG_ROMANIAN { 0x18 } +sub LANG_RUSSIAN { 0x19 } +sub LANG_SERBO_CROATIAN { 0x1a } +sub LANG_SLOVAK { 0x1b } +sub LANG_SPANISH { 0x0a } +sub LANG_SWEDISH { 0x1d } +sub LANG_THAI { 0x1e } +sub LANG_TURKISH { 0x1f } +sub LANG_URDU { 0x20 } + +# Sublanguage Identifier +sub SUBLANG_NEUTRAL { 0x00 } +sub SUBLANG_DEFAULT { 0x01 } +sub SUBLANG_SYS_DEFAULT { 0x02 } +sub SUBLANG_CHINESE_SIMPLIFIED { 0x02 } +sub SUBLANG_CHINESE_TRADITIONAL { 0x01 } +sub SUBLANG_DUTCH { 0x01 } +sub SUBLANG_DUTCH_BELGIAN { 0x02 } +sub SUBLANG_ENGLISH_US { 0x01 } +sub SUBLANG_ENGLISH_UK { 0x02 } +sub SUBLANG_ENGLISH_AUS { 0x03 } +sub SUBLANG_ENGLISH_CAN { 0x04 } +sub SUBLANG_ENGLISH_NZ { 0x05 } +sub SUBLANG_ENGLISH_EIRE { 0x06 } +sub SUBLANG_FRENCH { 0x01 } +sub SUBLANG_FRENCH_BELGIAN { 0x02 } +sub SUBLANG_FRENCH_CANADIAN { 0x03 } +sub SUBLANG_FRENCH_SWISS { 0x04 } +sub SUBLANG_GERMAN { 0x01 } +sub SUBLANG_GERMAN_SWISS { 0x02 } +sub SUBLANG_GERMAN_AUSTRIAN { 0x03 } +sub SUBLANG_ITALIAN { 0x01 } +sub SUBLANG_ITALIAN_SWISS { 0x02 } +sub SUBLANG_NORWEGIAN_BOKMAL { 0x01 } +sub SUBLANG_NORWEGIAN_NYNORSK { 0x02 } +sub SUBLANG_PORTUGUESE { 0x02 } +sub SUBLANG_PORTUGUESE_BRAZILIAN { 0x01 } +sub SUBLANG_SERBO_CROATIAN_CYRILLIC { 0x02 } +sub SUBLANG_SERBO_CROATIAN_LATIN { 0x01 } +sub SUBLANG_SPANISH { 0x01 } +sub SUBLANG_SPANISH_MEXICAN { 0x02 } +sub SUBLANG_SPANISH_MODERN { 0x03 } + +# Country codes +sub CTRY_DEFAULT { 0 } +sub CTRY_AUSTRALIA { 61 } +sub CTRY_AUSTRIA { 43 } +sub CTRY_BELGIUM { 32 } +sub CTRY_BRAZIL { 55 } +sub CTRY_CANADA { 2 } +sub CTRY_DENMARK { 45 } +sub CTRY_FINLAND { 358 } +sub CTRY_FRANCE { 33 } +sub CTRY_GERMANY { 49 } +sub CTRY_ICELAND { 354 } +sub CTRY_IRELAND { 353 } +sub CTRY_ITALY { 39 } +sub CTRY_JAPAN { 81 } +sub CTRY_MEXICO { 52 } +sub CTRY_NETHERLANDS { 31 } +sub CTRY_NEW_ZEALAND { 64 } +sub CTRY_NORWAY { 47 } +sub CTRY_PORTUGAL { 351 } +sub CTRY_PRCHINA { 86 } +sub CTRY_SOUTH_KOREA { 82 } +sub CTRY_SPAIN { 34 } +sub CTRY_SWEDEN { 46 } +sub CTRY_SWITZERLAND { 41 } +sub CTRY_TAIWAN { 886 } +sub CTRY_UNITED_KINGDOM { 44 } +sub CTRY_UNITED_STATES { 1 } + +# Locale Types +sub LOCALE_NOUSEROVERRIDE { 0x80000000 } +sub LOCALE_ILANGUAGE { 0x0001 } +sub LOCALE_SLANGUAGE { 0x0002 } +sub LOCALE_SENGLANGUAGE { 0x1001 } +sub LOCALE_SABBREVLANGNAME { 0x0003 } +sub LOCALE_SNATIVELANGNAME { 0x0004 } +sub LOCALE_ICOUNTRY { 0x0005 } +sub LOCALE_SCOUNTRY { 0x0006 } +sub LOCALE_SENGCOUNTRY { 0x1002 } +sub LOCALE_SABBREVCTRYNAME { 0x0007 } +sub LOCALE_SNATIVECTRYNAME { 0x0008 } +sub LOCALE_IDEFAULTLANGUAGE { 0x0009 } +sub LOCALE_IDEFAULTCOUNTRY { 0x000A } +sub LOCALE_IDEFAULTCODEPAGE { 0x000B } +sub LOCALE_IDEFAULTANSICODEPAGE { 0x1004 } +sub LOCALE_SLIST { 0x000C } +sub LOCALE_IMEASURE { 0x000D } +sub LOCALE_SDECIMAL { 0x000E } +sub LOCALE_STHOUSAND { 0x000F } +sub LOCALE_SGROUPING { 0x0010 } +sub LOCALE_IDIGITS { 0x0011 } +sub LOCALE_ILZERO { 0x0012 } +sub LOCALE_INEGNUMBER { 0x1010 } +sub LOCALE_SNATIVEDIGITS { 0x0013 } +sub LOCALE_SCURRENCY { 0x0014 } +sub LOCALE_SINTLSYMBOL { 0x0015 } +sub LOCALE_SMONDECIMALSEP { 0x0016 } +sub LOCALE_SMONTHOUSANDSEP { 0x0017 } +sub LOCALE_SMONGROUPING { 0x0018 } +sub LOCALE_ICURRDIGITS { 0x0019 } +sub LOCALE_IINTLCURRDIGITS { 0x001A } +sub LOCALE_ICURRENCY { 0x001B } +sub LOCALE_INEGCURR { 0x001C } +sub LOCALE_SDATE { 0x001D } +sub LOCALE_STIME { 0x001E } +sub LOCALE_SSHORTDATE { 0x001F } +sub LOCALE_SLONGDATE { 0x0020 } +sub LOCALE_STIMEFORMAT { 0x1003 } +sub LOCALE_IDATE { 0x0021 } +sub LOCALE_ILDATE { 0x0022 } +sub LOCALE_ITIME { 0x0023 } +sub LOCALE_ITIMEMARKPOSN { 0x1005 } +sub LOCALE_ICENTURY { 0x0024 } +sub LOCALE_ITLZERO { 0x0025 } +sub LOCALE_IDAYLZERO { 0x0026 } +sub LOCALE_IMONLZERO { 0x0027 } +sub LOCALE_S1159 { 0x0028 } +sub LOCALE_S2359 { 0x0029 } +sub LOCALE_ICALENDARTYPE { 0x1009 } +sub LOCALE_IOPTIONALCALENDAR { 0x100B } +sub LOCALE_IFIRSTDAYOFWEEK { 0x100C } +sub LOCALE_IFIRSTWEEKOFYEAR { 0x100D } +sub LOCALE_SDAYNAME1 { 0x002A } +sub LOCALE_SDAYNAME2 { 0x002B } +sub LOCALE_SDAYNAME3 { 0x002C } +sub LOCALE_SDAYNAME4 { 0x002D } +sub LOCALE_SDAYNAME5 { 0x002E } +sub LOCALE_SDAYNAME6 { 0x002F } +sub LOCALE_SDAYNAME7 { 0x0030 } +sub LOCALE_SABBREVDAYNAME1 { 0x0031 } +sub LOCALE_SABBREVDAYNAME2 { 0x0032 } +sub LOCALE_SABBREVDAYNAME3 { 0x0033 } +sub LOCALE_SABBREVDAYNAME4 { 0x0034 } +sub LOCALE_SABBREVDAYNAME5 { 0x0035 } +sub LOCALE_SABBREVDAYNAME6 { 0x0036 } +sub LOCALE_SABBREVDAYNAME7 { 0x0037 } +sub LOCALE_SMONTHNAME1 { 0x0038 } +sub LOCALE_SMONTHNAME2 { 0x0039 } +sub LOCALE_SMONTHNAME3 { 0x003A } +sub LOCALE_SMONTHNAME4 { 0x003B } +sub LOCALE_SMONTHNAME5 { 0x003C } +sub LOCALE_SMONTHNAME6 { 0x003D } +sub LOCALE_SMONTHNAME7 { 0x003E } +sub LOCALE_SMONTHNAME8 { 0x003F } +sub LOCALE_SMONTHNAME9 { 0x0040 } +sub LOCALE_SMONTHNAME10 { 0x0041 } +sub LOCALE_SMONTHNAME11 { 0x0042 } +sub LOCALE_SMONTHNAME12 { 0x0043 } +sub LOCALE_SMONTHNAME13 { 0x100E } +sub LOCALE_SABBREVMONTHNAME1 { 0x0044 } +sub LOCALE_SABBREVMONTHNAME2 { 0x0045 } +sub LOCALE_SABBREVMONTHNAME3 { 0x0046 } +sub LOCALE_SABBREVMONTHNAME4 { 0x0047 } +sub LOCALE_SABBREVMONTHNAME5 { 0x0048 } +sub LOCALE_SABBREVMONTHNAME6 { 0x0049 } +sub LOCALE_SABBREVMONTHNAME7 { 0x004A } +sub LOCALE_SABBREVMONTHNAME8 { 0x004B } +sub LOCALE_SABBREVMONTHNAME9 { 0x004C } +sub LOCALE_SABBREVMONTHNAME10 { 0x004D } +sub LOCALE_SABBREVMONTHNAME11 { 0x004E } +sub LOCALE_SABBREVMONTHNAME12 { 0x004F } +sub LOCALE_SABBREVMONTHNAME13 { 0x100F } +sub LOCALE_SPOSITIVESIGN { 0x0050 } +sub LOCALE_SNEGATIVESIGN { 0x0051 } +sub LOCALE_IPOSSIGNPOSN { 0x0052 } +sub LOCALE_INEGSIGNPOSN { 0x0053 } +sub LOCALE_IPOSSYMPRECEDES { 0x0054 } +sub LOCALE_IPOSSEPBYSPACE { 0x0055 } +sub LOCALE_INEGSYMPRECEDES { 0x0056 } +sub LOCALE_INEGSEPBYSPACE { 0x0057 } + +# GetTimeFormat Flags +sub TIME_NOMINUTESORSECONDS { 0x0001 } +sub TIME_NOSECONDS { 0x0002 } +sub TIME_NOTIMEMARKER { 0x0004 } +sub TIME_FORCE24HOURFORMAT { 0x0008 } + +# GetDateFormat Flags +sub DATE_SHORTDATE { 0x0001 } +sub DATE_LONGDATE { 0x0002 } +sub DATE_USE_ALT_CALENDAR { 0x0004 } +sub DATE_YEARMONTH { 0x0008 } +sub DATE_LTRREADING { 0x0010 } +sub DATE_RTLREADING { 0x0020 } + +# Language Identifier Functions +sub MAKELANGID { my ($p,$s) = @_; (($s & 0xffff) << 10) | ($p & 0xffff); } +sub PRIMARYLANGID { my $lgid = shift; $lgid & 0x3ff; } +sub SUBLANGID { my $lgid = shift; ($lgid >> 10) & 0x3f; } + +sub LANG_SYSTEM_DEFAULT { MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT); } +sub LANG_USER_DEFAULT { MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); } + +# Locale Identifier Functions +sub MAKELCID { my $lgid = shift; $lgid & 0xffff; } +sub LANGIDFROMLCID { my $lcid = shift; $lcid & 0xffff; } + +sub LOCALE_SYSTEM_DEFAULT { MAKELCID(LANG_SYSTEM_DEFAULT); } +sub LOCALE_USER_DEFAULT { MAKELCID(LANG_USER_DEFAULT); } + +1; + +__END__ + +=head1 NAME + +Win32::OLE::NLS - OLE National Language Support + +=head1 SYNOPSIS + + missing + +=head1 DESCRIPTION + +This module provides access to the national language support features +in the F. + +=head2 Functions + +=over 8 + +=item CompareString(LCID,FLAGS,STR1,STR2) + +Compare STR1 and STR2 in the LCID locale. FLAGS indicate the character +traits to be used or ignored when comparing the two strings. + + NORM_IGNORECASE Ignore case + NORM_IGNOREKANATYPE Ignore hiragana/katakana character differences + NORM_IGNORENONSPACE Ignore accents, diacritics, and vowel marks + NORM_IGNORESYMBOLS Ignore symbols + NORM_IGNOREWIDTH Ignore character width + +Possible return values are: + + 0 Function failed + 1 STR1 is less than STR2 + 2 STR1 is equal to STR2 + 3 STR1 is greater than STR2 + +Note that you can subtract 2 from the return code to get values +comparable to the C operator. + +=item LCMapString(LCID,FLAGS,STR) + +LCMapString translates STR using LCID dependent translation. +Flags contains a combination of the following options: + + LCMAP_LOWERCASE Lowercase + LCMAP_UPPERCASE Uppercase + LCMAP_HALFWIDTH Narrow characters + LCMAP_FULLWIDTH Wide characters + LCMAP_HIRAGANA Hiragana + LCMAP_KATAKANA Katakana + LCMAP_SORTKEY Character sort key + +The following normalization options can be combined with C: + + NORM_IGNORECASE Ignore case + NORM_IGNOREKANATYPE Ignore hiragana/katakana character differences + NORM_IGNORENONSPACE Ignore accents, diacritics, and vowel marks + NORM_IGNORESYMBOLS Ignore symbols + NORM_IGNOREWIDTH Ignore character width + +The return value is the translated string. + +=item GetLocaleInfo(LCID,LCTYPE) + +Retrieve locale setting LCTYPE from the locale specified by LCID. Use +LOCALE_NOUSEROVERRIDE | LCTYPE to always query the locale database. +Otherwise user changes to C through the windows control panel +take precedence when retrieving values for the system default locale. +See the documentation below for a list of valid LCTYPE values. + +The return value is the contents of the requested locale setting. + +=item GetStringType(LCID,TYPE,STR) + +Retrieve type information from locale LCID about each character in STR. +The requested TYPE can be one of the following 3 levels: + + CT_CTYPE1 ANSI C and POSIX type information + CT_CTYPE2 Text layout type information + CT_CTYPE3 Text processing type information + +The return value is a list of values, each of wich is a bitwise OR of +the applicable type bits from the corresponding table below: + + @ct = GetStringType(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, "String"); + +ANSI C and POSIX character type information: + + C1_UPPER Uppercase + C1_LOWER Lowercase + C1_DIGIT Decimal digits + C1_SPACE Space characters + C1_PUNCT Punctuation + C1_CNTRL Control characters + C1_BLANK Blank characters + C1_XDIGIT Hexadecimal digits + C1_ALPHA Any letter + +Text layout type information: + + C2_LEFTTORIGHT Left to right + C2_RIGHTTOLEFT Right to left + C2_EUROPENUMBER European number, European digit + C2_EUROPESEPARATOR European numeric separator + C2_EUROPETERMINATOR European numeric terminator + C2_ARABICNUMBER Arabic number + C2_COMMONSEPARATOR Common numeric separator + C2_BLOCKSEPARATOR Block separator + C2_SEGMENTSEPARATOR Segment separator + C2_WHITESPACE White space + C2_OTHERNEUTRAL Other neutrals + C2_NOTAPPLICABLE No implicit direction (e.g. ctrl codes) + +Text precessing type information: + + C3_NONSPACING Nonspacing mark + C3_DIACRITIC Diacritic nonspacing mark + C3_VOWELMARK Vowel nonspacing mark + C3_SYMBOL Symbol + C3_KATAKANA Katakana character + C3_HIRAGANA Hiragana character + C3_HALFWIDTH Narrow character + C3_FULLWIDTH Wide character + C3_IDEOGRAPH Ideograph + C3_ALPHA Any letter + C3_NOTAPPLICABLE Not applicable + + +=item GetSystemDefaultLangID() + +Returns the system default language identifier. + +=item GetSystemDefaultLCID() + +Returns the system default locale identifier. + +=item GetUserDefaultLangID() + +Returns the user default language identifier. + +=item GetUserDefaultLCID() + +Returns the user default locale identifier. + +=item SendSettingChange() + +Sends a WM_SETTINGCHANGE message to all top level windows. + +=item SetLocaleInfo(LCID, LCTYPE, LCDATA) + +Changes an item in the user override part of the locale setting LCID. +It doesn't change the system default database. The following LCTYPEs are +changeable: + + LOCALE_ICALENDARTYPE LOCALE_SDATE + LOCALE_ICURRDIGITS LOCALE_SDECIMAL + LOCALE_ICURRENCY LOCALE_SGROUPING + LOCALE_IDIGITS LOCALE_SLIST + LOCALE_IFIRSTDAYOFWEEK LOCALE_SLONGDATE + LOCALE_IFIRSTWEEKOFYEAR LOCALE_SMONDECIMALSEP + LOCALE_ILZERO LOCALE_SMONGROUPING + LOCALE_IMEASURE LOCALE_SMONTHOUSANDSEP + LOCALE_INEGCURR LOCALE_SNEGATIVESIGN + LOCALE_INEGNUMBER LOCALE_SPOSITIVESIGN + LOCALE_IPAPERSIZE LOCALE_SSHORTDATE + LOCALE_ITIME LOCALE_STHOUSAND + LOCALE_S1159 LOCALE_STIME + LOCALE_S2359 LOCALE_STIMEFORMAT + LOCALE_SCURRENCY LOCALE_SYEARMONTH + +You have to call SendSettingChange() to activate these changes for +subsequent Win32::OLE::Variant object formatting because the OLE +subsystem seems to cache locale information. + +=item MAKELANGID(LANG,SUBLANG) + +Creates a lnguage identifier from a primary language and a sublanguage. + +=item PRIMARYLANGID(LANGID) + +Retrieves the primary language from a language identifier. + +=item SUBLANGID(LANGID) + +Retrieves the sublanguage from a language identifier. + +=item MAKELCID(LANGID) + +Creates a locale identifies from a language identifier. + +=item LANGIDFROMLCID(LCID) + +Retrieves a language identifier from a locale identifier. + +=back + +=head2 Locale Types + +=over 8 + +=item LOCALE_ILANGUAGE + +The language identifier (in hex). + +=item LOCALE_SLANGUAGE + +The localized name of the language. + +=item LOCALE_SENGLANGUAGE + +The ISO Standard 639 English name of the language. + +=item LOCALE_SABBREVLANGNAME + +The three-letter abbreviated name of the language. The first two +letters are from the ISO Standard 639 language name abbreviation. The +third letter indicates the sublanguage type. + +=item LOCALE_SNATIVELANGNAME + +The native name of the language. + +=item LOCALE_ICOUNTRY + +The country code, which is based on international phone codes. + +=item LOCALE_SCOUNTRY + +The localized name of the country. + +=item LOCALE_SENGCOUNTRY + +The English name of the country. + +=item LOCALE_SABBREVCTRYNAME + +The ISO Standard 3166 abbreviated name of the country. + +=item LOCALE_SNATIVECTRYNAME + +The native name of the country. + +=item LOCALE_IDEFAULTLANGUAGE + +Language identifier for the principal language spoken in this +locale. + +=item LOCALE_IDEFAULTCOUNTRY + +Country code for the principal country in this locale. + +=item LOCALE_IDEFAULTANSICODEPAGE + +The ANSI code page associated with this locale. Format: 4 Unicode +decimal digits plus a Unicode null terminator. + +XXX This should be translated by GetLocaleInfo. XXX + +=item LOCALE_IDEFAULTCODEPAGE + +The OEM code page associated with the country. + +=item LOCALE_SLIST + +Characters used to separate list items (often a comma). + +=item LOCALE_IMEASURE + +Default measurement system: + + 0 metric system (S.I.) + 1 U.S. system + +=item LOCALE_SDECIMAL + +Characters used for the decimal separator (often a dot). + +=item LOCALE_STHOUSAND + +Characters used as the separator between groups of digits left of the decimal. + +=item LOCALE_SGROUPING + +Sizes for each group of digits to the left of the decimal. An explicit +size is required for each group. Sizes are separated by semicolons. If +the last value is 0, the preceding value is repeated. To group +thousands, specify 3;0. + +=item LOCALE_IDIGITS + +The number of fractional digits. + +=item LOCALE_ILZERO + +Whether to use leading zeros in decimal fields. A setting of 0 +means use no leading zeros; 1 means use leading zeros. + +=item LOCALE_SNATIVEDIGITS + +The ten characters that are the native equivalent of the ASCII 0-9. + +=item LOCALE_INEGNUMBER + +Negative number mode. + + 0 (1.1) + 1 -1.1 + 2 -1.1 + 3 1.1 + 4 1.1 + +=item LOCALE_SCURRENCY + +The string used as the local monetary symbol. + +=item LOCALE_SINTLSYMBOL + +Three characters of the International monetary symbol specified in ISO +4217, Codes for the Representation of Currencies and Funds, followed +by the character separating this string from the amount. + +=item LOCALE_SMONDECIMALSEP + +Characters used for the monetary decimal separators. + +=item LOCALE_SMONTHOUSANDSEP + +Characters used as monetary separator between groups of digits left of +the decimal. + +=item LOCALE_SMONGROUPING + +Sizes for each group of monetary digits to the left of the decimal. An +explicit size is needed for each group. Sizes are separated by +semicolons. If the last value is 0, the preceding value is +repeated. To group thousands, specify 3;0. + +=item LOCALE_ICURRDIGITS + +Number of fractional digits for the local monetary format. + +=item LOCALE_IINTLCURRDIGITS + +Number of fractional digits for the international monetary format. + +=item LOCALE_ICURRENCY + +Positive currency mode. + + 0 Prefix, no separation. + 1 Suffix, no separation. + 2 Prefix, 1-character separation. + 3 Suffix, 1-character separation. + +=item LOCALE_INEGCURR + +Negative currency mode. + + 0 ($1.1) + 1 -$1.1 + 2 $-1.1 + 3 $1.1- + 4 $(1.1$) + 5 -1.1$ + 6 1.1-$ + 7 1.1$- + 8 -1.1 $ (space before $) + 9 -$ 1.1 (space after $) + 10 1.1 $- (space before $) + +=item LOCALE_ICALENDARTYPE + +The type of calendar currently in use. + + 1 Gregorian (as in U.S.) + 2 Gregorian (always English strings) + 3 Era: Year of the Emperor (Japan) + 4 Era: Year of the Republic of China + 5 Tangun Era (Korea) + +=item LOCALE_IOPTIONALCALENDAR + +The additional calendar types available for this LCID. Can be a +null-separated list of all valid optional calendars. Value is +0 for "None available" or any of the LOCALE_ICALENDARTYPE settings. + +XXX null separated list should be translated by GetLocaleInfo XXX + +=item LOCALE_SDATE + +Characters used for the date separator. + +=item LOCALE_STIME + +Characters used for the time separator. + +=item LOCALE_STIMEFORMAT + +Time-formatting string. + +=item LOCALE_SSHORTDATE + +Short Date_Time formatting strings for this locale. + +=item LOCALE_SLONGDATE + +Long Date_Time formatting strings for this locale. + +=item LOCALE_IDATE + +Short Date format-ordering specifier. + + 0 Month - Day - Year + 1 Day - Month - Year + 2 Year - Month - Day + +=item LOCALE_ILDATE + +Long Date format ordering specifier. Value can be any of the valid +LOCALE_IDATE settings. + +=item LOCALE_ITIME + +Time format specifier. + + 0 AM/PM 12-hour format. + 1 24-hour format. + +=item LOCALE_ITIMEMARKPOSN + +Whether the time marker string (AM|PM) precedes or follows the time +string. + 0 Suffix (9:15 AM). + 1 Prefix (AM 9:15). + +=item LOCALE_ICENTURY + +Whether to use full 4-digit century. + + 0 Two digit. + 1 Full century. + +=item LOCALE_ITLZERO + +Whether to use leading zeros in time fields. + + 0 No leading zeros. + 1 Leading zeros for hours. + +=item LOCALE_IDAYLZERO + +Whether to use leading zeros in day fields. Values as for +LOCALE_ITLZERO. + +=item LOCALE_IMONLZERO + +Whether to use leading zeros in month fields. Values as for +LOCALE_ITLZERO. + +=item LOCALE_S1159 + +String for the AM designator. + +=item LOCALE_S2359 + +String for the PM designator. + +=item LOCALE_IFIRSTWEEKOFYEAR + +Specifies which week of the year is considered first. + + 0 Week containing 1/1 is the first week of the year. + 1 First full week following 1/1is the first week of the year. + 2 First week with at least 4 days is the first week of the year. + +=item LOCALE_IFIRSTDAYOFWEEK + +Specifies the day considered first in the week. Value "0" means +SDAYNAME1 and value "6" means SDAYNAME7. + +=item LOCALE_SDAYNAME1 .. LOCALE_SDAYNAME7 + +Long name for Monday .. Sunday. + +=item LOCALE_SABBREVDAYNAME1 .. LOCALE_SABBREVDAYNAME7 + +Abbreviated name for Monday .. Sunday. + +=item LOCALE_SMONTHNAME1 .. LOCALE_SMONTHNAME12 + +Long name for January .. December. + +=item LOCALE_SMONTHNAME13 + +Native name for 13th month, if it exists. + +=item LOCALE_SABBREVMONTHNAME1 .. LOCALE_SABBREVMONTHNAME12 + +Abbreviated name for January .. December. + +=item LOCALE_SABBREVMONTHNAME13 + +Native abbreviated name for 13th month, if it exists. + +=item LOCALE_SPOSITIVESIGN + +String value for the positive sign. + +=item LOCALE_SNEGATIVESIGN + +String value for the negative sign. + +=item LOCALE_IPOSSIGNPOSN + +Formatting index for positive values. + + 0 Parentheses surround the amount and the monetary symbol. + 1 The sign string precedes the amount and the monetary symbol. + 2 The sign string precedes the amount and the monetary symbol. + 3 The sign string precedes the amount and the monetary symbol. + 4 The sign string precedes the amount and the monetary symbol. + +=item LOCALE_INEGSIGNPOSN + +Formatting index for negative values. Values as for LOCALE_IPOSSIGNPOSN. + +=item LOCALE_IPOSSYMPRECEDES + +If the monetary symbol precedes, 1. If it succeeds a positive amount, 0. + +=item LOCALE_IPOSSEPBYSPACE + +If the monetary symbol is separated by a space from a positive amount, +1. Otherwise, 0. + +=item LOCALE_INEGSYMPRECEDES + +If the monetary symbol precedes, 1. If it succeeds a negative amount, 0. + +=item LOCALE_INEGSEPBYSPACE + +If the monetary symbol is separated by a space from a negative amount, +1. Otherwise, 0. + +=back + +=head1 AUTHORS/COPYRIGHT + +This module is part of the Win32::OLE distribution. + +=cut diff --git a/Master/tlpkg/tlperl/lib/Win32/OLE/TPJ.pod b/Master/tlpkg/tlperl/lib/Win32/OLE/TPJ.pod new file mode 100644 index 00000000000..e45770baa42 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/Win32/OLE/TPJ.pod @@ -0,0 +1,798 @@ +=pod + +=head1 NAME + +The Perl Journal #10 - Win32::OLE by Jan Dubois + +=head1 INTRODUCTION + +Suppose you're composing a document with Microsoft Word. You want to +include an Excel spreadsheet. You could save the spreadsheet in some +image format that Word can understand, and import it into your +document. But if the spreadsheet changes, your document will be out of +date. + +Microsoft's OLE (Object Linking and Embedding, pronounced "olay") lets +one program use objects from another. In the above scenario, the +spreadsheet is the object. As long as Excel makes that spreadsheet +available as an OLE object, and Word knows to treat it like one, your +document will always be current. + +You can control OLE objects from Perl with the Win32::OLE module, and +that's what this article is about. First, I'll show you how to "think +OLE," which mostly involves a lot of jargon. Next, I'll show you the +mechanics involved in using Win32::OLE. Then we'll go through a Perl +program that uses OLE to manipulate Microsoft Excel, Microsoft Access, +and Lotus Notes. Finally, I'll talk about Variants, an internal OLE +data type. + + +=head1 THE OLE MINDSET + +When an application makes an OLE object available for other +applications to use, that's called OLE I. The program +using the object is called the I, and the application +providing the object is called the I. OLE automation is guided +by the OLE Component Object Model (COM) which specifies how those +objects must behave if they are to be used by other processes and +machines. + +There are two different types of OLE automation servers. I +servers are implemented as dynamic link libraries (DLLs) and run in +the same process space as the controller. I servers +are more interesting; they are standalone executables that exist as +separate processes - possibly on a different computer. + +The Win32::OLE module lets your Perl program act as an OLE +controller. It allows Perl to be used in place of other languages like +Visual Basic or Java to control OLE objects. This makes all OLE +automation servers immediately available as Perl modules. + +Don't confuse ActiveState OLE with Win32::OLE. ActiveState OLE is +completely different, although future builds of ActiveState Perl (500 +and up) will work with Win32::OLE. + +Objects can expose OLE methods, properties, and events to the outside +world. Methods are functions that the controller can call to make the +object do something; properties describe the state of the object; and +events let the controller know about external events affecting the +object, such as the user clicking on a button. Since events involve +asynchronous communication with their objects, they require either +threads or an event loop. They are not yet supported by the Win32::OLE +module, and for the same reason ActiveX controls (OCXs) are currently +unsupported as well. + +=head1 WORKING WITH WIN32::OLE + +The Win32::OLE module doesn't let your Perl program create OLE +objects. What it does do is let your Perl program act like a remote +control for other applications-it lets your program be an OLE +controller. You can take an OLE object from another application +(Access, Notes, Excel, or anything else that speaks OLE) and invoke +its methods or manipulate its properties. + +=head2 THE FIRST STEP: CREATING AN OLE SERVER OBJECT + +First, we need to create a Perl object to represent the OLE +server. This is a weird idea; what it amounts to is that if we want to +control OLE objects produced by, say, Excel, we have to create a Perl +object that represents Excel. So even though our program is an OLE +controller, it'll contain objects that represent OLE servers. + +You can create a new OLE I with C<< Win32::OLE->new >>. +This takes a program ID (a human readable string like +C<'Speech.VoiceText'>) and returns a server object: + + my $server = Win32::OLE->new('Excel.Application', 'Quit'); + +Some server objects (particularly those for Microsoft Office +applications) don't automatically terminate when your program no +longer needs them. They need some kind of Quit method, and that's just +what our second argument is. It can be either a code reference or a +method name to be invoked when the object is destroyed. This lets you +ensure that objects will be properly cleaned up even when the Perl +program dies abnormally. + +To access a server object on a different computer, replace the first +argument with a reference to a list of the server name and program ID: + + my $server = Win32::OLE->new(['foo.bar.com', + 'Excel.Application']); + +(To get the requisite permissions, you'll need to configure your +security settings with F.) + +You can also directly attach your program to an already running OLE +server: + + my $server = Win32::OLE->GetActiveObject('Excel.Application'); + +This fails (returning C) if no server exists, or if the server +refuses the connection for some reason. It is also possible to use a +persistent object moniker (usually a filename) to start the associated +server and load the object into memory: + + my $doc = Win32::OLE->GetObject("MyDocument.Doc"); + +=head2 METHOD CALLS + +Once you've created one of these server objects, you need to call its +methods to make the OLE objects sing and dance. OLE methods are +invoked just like normal Perl object methods: + + $server->Foo(@Arguments); + +This is a Perl method call - but it also triggers an OLE method call +in the object. After your program executes this statement, the +C<$server> object will execute its Foo() method. The available methods +are typically documented in the application's I. + +B By default, all parameters are positional +(e.g. C) rather than named (e.g. +C<< foo(-name => "Yogi", -title => "Coach") >>). The required parameters +come first, followed by the optional parameters; if you need to +provide a dummy value for an optional parameter, use undef. + +Positional parameters get cumbersome if a method takes a lot of +them. You can use named arguments instead if you go to a little extra +trouble - when the last argument is a reference to a hash, the +key/value pairs of the hash are treated as named parameters: + + $server->Foo($Pos1, $Pos2, {Name1 => $Value1, + Name2 => $Value2}); + +B Sometimes OLE servers use +method and property names that are specific to a non-English +locale. That means they might have non-ASCII characters, which aren't +allowed in Perl variable names. In German, you might see C<Öffnen> used +instead of C. In these cases, you can use the Invoke() method: + + $server->Invoke('Öffnen', @Arguments); + +This is necessary because C<< $Server->Öffnen(@Arguments) >> is a syntax +error in current versions of Perl. + +=head2 PROPERTIES + +As I said earlier, objects can expose three things to the outside +world: methods, properties, and events. We've covered methods, and +Win32::OLE can't handle events. That leaves properties. But as it +turns out, properties and events are largely interchangeable. Most +methods have corresponding properties, and vice versa. + +An object's properties can be accessed with a hash reference: + + $server->{Bar} = $value; + $value = $server->{Bar}; + +This example sets and queries the value of the property named +C. You could also have called the object's Bar() method to +achieve the same effect: + + $value = $server->Bar; + +However, you can't write the first line as C<< $server->Bar = $value >>, +because you can't assign to the return value of a method call. In +Visual Basic, OLE automation distinguishes between assigning the name +of an object and assigning its value: + + Set Object = OtherObject + + Let Value = Object + +The C statement shown here makes C refer to the same object as +C. The C statement copies the value instead. (The value of +an OLE object is what you get when you call the object's default +method. + +In Perl, saying C<< $server1 = $server2 >> always creates another reference, +just like the C in Visual Basic. If you want to assign the value +instead, use the valof() function: + + my $value = valof $server; + +This is equivalent to + + my $value = $server->Invoke(''); + +=head2 SAMPLE APPLICATION + +Let's look at how all of this might be used. In Listing: 1 you'll see +F, a program that uses Win32::OLE for an almost-real world +application. + +The developer of this application, Mary Lynch, is a financial futures +broker. Every afternoon, she connects to the Chicago Board of Trade +(CBoT) web site at http://www.cbot.com and collects the time and sales +information for U.S. T-bond futures. She wants her program to create a +chart that depicts the data in 15-minute intervals, and then she wants +to record the data in a database for later analysis. Then she wants +her program to send mail to her clients. + +Mary's program will use Microsoft Access as a database, Microsoft +Excel to produce the chart, and Lotus Notes to send the mail. It will +all be controlled from a single Perl program using OLE automation. In +this section, we'll go through T-Bond. pl step by step so you can see +how Win32::OLE lets you control these applications. + +=head2 DOWNLOADING A WEB PAGE WITH LWP + +However, Mary first needs to amass the raw T-bond data by having her +Perl program automatically download and parse a web page. That's the +perfect job for LWP, the libwww-perl bundle available on the CPAN. LWP +has nothing to do with OLE. But this is a real-world application, and +it's just what Mary needs to download her data from the Chicago Board +of Trade. + + use LWP::Simple; + my $URL = 'http://www.cbot.com/mplex/quotes/tsfut'; + my $text = get("$URL/tsf$Contract.htm"); + +She could also have used the Win32::Internet module: + + use Win32::Internet; + my $URL = 'http://www.cbot.com/mplex/quotes/tsfut'; + my $text = $Win32::Internet->new->FetchURL("$URL/tsf$Contract.htm"); + +Mary wants to condense the ticker data into 15 minute bars. She's +interested only in lines that look like this: + + 03/12/1998 US 98Mar 12116 15:28:34 Open + +A regular expression can be used to determine whether a line looks +like this. If it does, the regex can split it up into individual +fields. The price quoted above, C<12116>, really means 121 16/32, and +needs to be converted to 121.5. The data is then condensed into 15 +minute intervals and only the first, last, highest, and lowest price +during each interval are kept. The time series is stored in the array +C<@Bars>. Each entry in C<@Bars> is a reference to a list of 5 elements: +Time, Open, High, Low, and Close. + + foreach (split "\n", $text) { + # 03/12/1998 US 98Mar 12116 15:28:34 Open + my ($Date,$Price,$Hour,$Min,$Sec,$Ind) = + m|^\s*(\d+/\d+/\d+) # " 03/12/1998" + \s+US\s+\S+\s+(\d+) # " US 98Mar 12116" + \s+(\d+):(\d+):(\d+) # " 12:42:40" + \s*(.*)$|x; # " Ask" + next unless defined $Date; + $Day = $Date; + + # Convert from fractional to decimal format + $Price = int($Price/100) + ($Price%100)/32; + + # Round up time to next multiple of 15 minutes + my $NewTime = int(($Sec+$Min*60+$Hour*3600)/900+1)*900; + unless (defined $Time && $NewTime == $Time) { + push @Bars, [$hhmm, $Open, $High, $Low, $Close] + if defined $Time; + $Open = $High = $Low = $Close = undef; + $Time = $NewTime; + my $Hour = int($Time/3600); + $hhmm = sprintf "%02d:%02d", $Hour, $Time/60-$Hour*60; + } + + # Update 15 minute bar values + $Close = $Price; + $Open = $Price unless defined $Open; + $High = $Price unless defined $High && $High > $Price; + $Low = $Price unless defined $Low && $Low > $Price; + } + + die "No data found" unless defined $Time; + push @Bars, [$hhmm, $Open, $High, $Low, $Close]; + +=head2 MICROSOFT ACCESS + +Now that Mary has her T-bond quotes, she's ready to use Win32::OLE to +store them into a Microsoft Access database. This has the advantage +that she can copy the database to her lap-top and work with it on her +long New York commute. She's able to create an Access database as +follows: + + use Win32::ODBC; + use Win32::OLE; + + # Include the constants for the Microsoft Access + # "Data Access Object". + + use Win32::OLE::Const 'Microsoft DAO'; + + my $DSN = 'T-Bonds'; + my $Driver = 'Microsoft Access Driver (*.mdb)'; + my $Desc = 'US T-Bond Quotes'; + my $Dir = 'i:\tmp\tpj'; + my $File = 'T-Bonds.mdb'; + my $Fullname = "$Dir\\$File"; + + # Remove old database and dataset name + unlink $Fullname if -f $Fullname; + Win32::ODBC::ConfigDSN(ODBC_REMOVE_DSN, $Driver, "DSN=$DSN") + if Win32::ODBC::DataSources($DSN); + + # Create new database + my $Access = Win32::OLE->new('Access.Application', 'Quit'); + my $Workspace = $Access->DBEngine->CreateWorkspace('', 'Admin', ''); + my $Database = $Workspace->CreateDatabase($Fullname, dbLangGeneral); + + # Add new database name + Win32::ODBC::ConfigDSN(ODBC_ADD_DSN, $Driver, + "DSN=$DSN", "Description=$Desc", "DBQ=$Fullname", + "DEFAULTDIR=$Dir", "UID=", "PWD="); + +This uses Win32::ODBC (described in TPJ #9) to remove and create +F. This lets Mary use the same script on her workstation +and on her laptop even when the database is stored in different +locations on each. The program also uses Win32::OLE to make Microsoft +Access create an empty database. + +Every OLE server has some constants that your Perl program will need +to use, made accessible by the Win32::OLE::Const module. For instance, +to grab the Excel constants, say C. + +In the above example, we imported the Data Access Object con-stants +just so we could use C. + +=head2 MICROSOFT EXCEL + +Now Mary uses Win32::OLE a second time, to have Microsoft Excel create +the chart shown below. + + Figure 1: T-Bond data generated by MicroSoft Excel via Win32::OLE + + # Start Excel and create new workbook with a single sheet + use Win32::OLE qw(in valof with); + use Win32::OLE::Const 'Microsoft Excel'; + use Win32::OLE::NLS qw(:DEFAULT :LANG :SUBLANG); + + my $lgid = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); + $Win32::OLE::LCID = MAKELCID($lgid); + + $Win32::OLE::Warn = 3; + +Here, Mary sets the locale to American English, which lets her do +things like use American date formats (e.g. C<"12-30-98"> rather than +C<"30-12-98">) in her program. It will continue to work even when she's +visiting one of her international customers and has to run this +program on their computers. + +The value of C<$Win32::OLE::Warn> determines what happens when an OLE +error occurs. If it's 0, the error is ignored. If it's 2, or if it's 1 +and the script is running under C<-w>, the Win32::OLE module invokes +C. If C<$Win32::OLE::Warn> is set to 3, C +is invoked and the program dies immediately. + +Now the data can be put into an Excel spreadsheet to produce the +chart. The following section of the program launches Excel and creates +a new workbook with a single worksheet. It puts the column titles +('Time', 'Open', 'High', 'Low', and 'Close') in a bold font on the +first row of the sheet. The first column displays the timestamp in +I format; the next four display prices. + + my $Excel = Win32::OLE->new('Excel.Application', 'Quit'); + $Excel->{SheetsInNewWorkbook} = 1; + my $Book = $Excel->Workbooks->Add; + my $Sheet = $Book->Worksheets(1); + $Sheet->{Name} = 'Candle'; + + # Insert column titles + my $Range = $Sheet->Range("A1:E1"); + $Range->{Value} = [qw(Time Open High Low Close)]; + $Range->Font->{Bold} = 1; + + $Sheet->Columns("A:A")->{NumberFormat} = "h:mm"; + # Open/High/Low/Close to be displayed in 32nds + $Sheet->Columns("B:E")->{NumberFormat} = "# ?/32"; + + # Add 15 minute data to spreadsheet + print "Add data\n"; + $Range = $Sheet->Range(sprintf "A2:E%d", 2+$#Bars); + $Range->{Value} = \@Bars; + +The last statement shows how to pass arrays to OLE objects. The +Win32::OLE module automatically translates each array reference to a +C, the internal OLE array data type. This translation first +determines the maximum nesting level used by the Perl array, and then +creates a C of the same dimension. The C<@Bars> array +already contains the data in the correct form for the spreadsheet: + + ([Time1, Open1, High1, Low1, Close1], + ... + [TimeN, OpenN, HighN, LowN, CloseN]) + +Now the table in the spreadsheet can be used to create a candle stick +chart from our bars. Excel automatically chooses the time axis labels +if they are selected before the chart is created: + + # Create candle stick chart as new object on worksheet + $Sheet->Range("A:E")->Select; + + my $Chart = $Book->Charts->Add; + $Chart->{ChartType} = xlStockOHLC; + $Chart->Location(xlLocationAsObject, $Sheet->{Name}); + # Excel bug: the old $Chart is now invalid! + $Chart = $Excel->ActiveChart; + +We can change the type of the chart from a separate sheet to a chart +object on the spreadsheet page with the C<< $Chart->Location >> +method. (This invalidates the chart object handle, which might be +considered a bug in Excel.) Fortunately, this new chart is still the +'active' chart, so an object handle to it can be reclaimed simply by +asking Excel. + +At this point, our chart still needs a title, the legend is +meaningless, and the axis has decimals instead of fractions. We can +fix those with the following code: + + # Add title, remove legend + with($Chart, HasLegend => 0, HasTitle => 1); + $Chart->ChartTitle->Characters->{Text} = "US T-Bond"; + + # Set up daily statistics + $Open = $Bars[0][1]; + $High = $Sheet->Evaluate("MAX(C:C)"); + $Low = $Sheet->Evaluate("MIN(D:D)"); + $Close = $Bars[$#Bars][4]; + +The with() function partially mimics the Visual Basic With statement, +but allows only property assignments. It's a convenient shortcut for +this: + + { # open new scope + my $Axis = $Chart->Axes(xlValue); + $Axis->{HasMajorGridlines} = 1; + $Axis->{HasMinorGridlines} = 1; + # etc ... + } + +The C<$High> and C<$Low> for the day are needed to determine the +minimum and maximum scaling levels. MIN and MAX are spreadsheet +functions, and aren't automatically available as methods. However, +Excel provides an Evaluate() method to calculate arbitrary spreadsheet +functions, so we can use that. + +We want the chart to show major gridlines at every fourth tick and +minor gridlines at every second tick. The minimum and maximum are +chosen to be whatever multiples of 1/16 we need to do that. + + # Change tickmark spacing from decimal to fractional + with($Chart->Axes(xlValue), + HasMajorGridlines => 1, + HasMinorGridlines => 1, + MajorUnit => 1/8, + MinorUnit => 1/16, + MinimumScale => int($Low*16)/16, + MaximumScale => int($High*16+1)/16 + ); + + # Fat candles with only 5% gaps + $Chart->ChartGroups(1)->{GapWidth} = 5; + + sub RGB { $_[0] | ($_[1] >> 8) | ($_[2] >> 16) } + + # White background with a solid border + + $Chart->PlotArea->Border->{LineStyle} = xlContinuous; + $Chart->PlotArea->Border->{Color} = RGB(0,0,0); + $Chart->PlotArea->Interior->{Color} = RGB(255,255,255); + + # Add 1 hour moving average of the Close series + my $MovAvg = $Chart->SeriesCollection(4)->Trendlines + ->Add({Type => xlMovingAvg, Period => 4}); + $MovAvg->Border->{Color} = RGB(255,0,0); + +Now the finished workbook can be saved to disk as +F. That file most likely still exists from when the +program ran yesterday, so we'll remove it. (Otherwise, Excel would pop +up a dialog with a warning, because the SaveAs() method doesn't like +to overwrite files.) + + + # Save workbook to file my $Filename = 'i:\tmp\tpj\data.xls'; + unlink $Filename if -f $Filename; + $Book->SaveAs($Filename); + $Book->Close; + +=head2 ACTIVEX DATA OBJECTS + +Mary stores the daily prices in her T-bonds database, keeping the data +for the different contracts in separate tables. After creating an ADO +(ActiveX Data Object) connection to the database, she tries to connect +a record set to the table for the current contract. If this fails, she +assumes that the table doesn't exists yet and tries to create it: + + use Win32::OLE::Const 'Microsoft ActiveX Data Objects'; + + my $Connection = Win32::OLE->new('ADODB.Connection'); + my $Recordset = Win32::OLE->new('ADODB.Recordset'); + $Connection->Open('T-Bonds'); + + # Open a record set for the table of this contract + { + local $Win32::OLE::Warn = 0; + $Recordset->Open($Contract, $Connection, adOpenKeyset, + adLockOptimistic, adCmdTable); + } + + # Create table and index if it doesn't exist yet + if (Win32::OLE->LastError) { + $Connection->Execute(<<"SQL"); + CREATE TABLE $Contract + ( + Day DATETIME, + Open DOUBLE, High DOUBLE, Low DOUBLE, Close DOUBLE + ) + SQL + $Connection->Execute(<<"SQL"); + CREATE INDEX $Contract + ON $Contract (Day) WITH PRIMARY + SQL + $Recordset->Open($Contract, $Connection, adOpenKeyset, + adLockOptimistic, adCmdTable); + } + +C<$Win32::OLE::Warn> is temporarily set to zero, so that if +C<$Recordset->Open> fails, the failure will be recorded silently without +terminating the program. CLastError> shows whether the Open +failed or not. C returns the OLE error code in a numeric +context and the OLE error message in a string context, just like +Perl's C<$!> variable. + +Now Mary can add today's data: + + # Add new record to table + use Win32::OLE::Variant; + $Win32::OLE::Variant::LCID = $Win32::OLE::LCID; + + my $Fields = [qw(Day Open High Low Close)]; + my $Values = [Variant(VT_DATE, $Day), + $Open, $High, $Low, $Close]; + +Mary uses the Win32::OLE::Variant module to store C<$Day> as a date +instead of a mere string. She wants to make sure that it's stored as +an American-style date, so in the third line shown here she sets the +locale ID of the Win32::OLE::Variant module to match the Win32::OLE +module. (C<$Win32::OLE::LCID> had been set earlier to English, since +that's what the Chicago Board of Trade uses.) + + { + local $Win32::OLE::Warn = 0; + $Recordset->AddNew($Fields, $Values); + } + + # Replace existing record + if (Win32::OLE->LastError) { + $Recordset->CancelUpdate; + $Recordset->Close; + $Recordset->Open(<<"SQL", $Connection, adOpenDynamic); + SELECT * FROM $Contract + WHERE Day = #$Day# + SQL + $Recordset->Update($Fields, $Values); + } + + $Recordset->Close; + $Connection->Close; + +The program expects to be able to add a new record to the table. It +fails if a record for this date already exists, because the Day field +is the primary index and therefore must be unique. If an error occurs, +the update operation started by AddNew() must first be cancelled with +C<< $Recordset->CancelUpdate >>; otherwise the record set won't close. + +=head2 LOTUS NOTES + +Now Mary can use Lotus Notes to mail updates to all her customers +interested in the T-bond data. (Lotus Notes doesn't provide its +constants in the OLE type library, so Mary had to determine them by +playing around with LotusScript.) The actual task is quite simple: A +Notes session must be started, the mail database must be opened and +the mail message must be created. The body of the message is created +as a rich text field, which lets her mix formatted text with object +attachments. + +In her program, Mary extracts the email addresses from her customer +database and sends separate message to each. Here, we've simplified it +somewhat. + + sub EMBED_ATTACHMENT {1454;} # from LotusScript + + my $Notes = Win32::OLE->new('Notes.NotesSession'); + my $Database = $Notes->GetDatabase('', ''); + $Database->OpenMail; + my $Document = $Database->CreateDocument; + + $Document->{Form} = 'Memo'; + $Document->{SendTo} = ['Jon Orwant >orwant@tpj.com>', + 'Jan Dubois >jan.dubois@ibm.net>']; + $Document->{Subject} = "US T-Bonds Chart for $Day"; + + my $Body = $Document->CreateRichtextItem('Body'); + $Body->AppendText(<<"EOT"); + I\'ve attached the latest US T-Bond data and chart for $Day. + The daily statistics were: + + \tOpen\t$Open + \tHigh\t$High + \tLow\t$Low + \tClose\t$Close + + Kind regards, + + Mary + EOT + + $Body->EmbedObject(EMBED_ATTACHMENT, '', $Filename); + + $Document->Send(0); + +=head1 VARIANTS + +In this final section, I'll talk about Variants, which are the data +types that you use to talk to OLE objects. We talked about this line +earlier: + + my $Values = [Variant(VT_DATE, $Day), + $Open, $High, $Low, $Close]; + +Here, the Variant() function creates a Variant object, of type C +and with the value C<$Day>. Variants are similar in many ways to Perl +scalars. Arguments to OLE methods are transparently converted from +their internal Perl representation to Variants and back again by the +Win32::OLE module. + +OLE automation uses a generic C data type to pass +parameters. This data type contains type information in addition to +the actual data value. Only the following data types are valid for OLE +automation: + + B + VT_EMPTY Not specified + VT_NULL Null + VT_I2 2 byte signed integer + VT_I4 4 byte signed integer + VT_R4 4 byte real + VT_R8 8 byte real + VT_CY Currency + VT_DATE Date + VT_BSTR Unicode string + VT_DISPATCH OLE automation interface + VT_ERROR Error + VT_BOOL Boolean + VT_VARIANT (only valid with VT_BYREF) + VT_UNKNOWN Generic COM interface + VT_UI1 Unsigned character + +The following two flags can also be used: + + VT_ARRAY Array of values + VT_BYREF Pass by reference (instead of by value) + +B The following conversions are +performed automatically whenever a Perl value must be translated into +a Variant: + + Perl value Variant + Integer values VT_I4 + Real values VT_R8 + Strings VT_BSTR + undef VT_ERROR (DISP_E_PARAMNOTFOUND) + Array reference VT_VARIANT | VT_ARRAY + Win32::OLE object VT_DISPATCH + Win32::OLE::Variant object Type of the Variant object + +What if your Perl value is a list of lists? Those can be irregularly +shaped in Perl; that is, the subsidiary lists needn't have the same +number of elements. In this case, the structure will be converted to a +"rectangular" C of Variants, with unused slots set to +C. Consider this Perl 2-D array: + + [ ["Perl" ], # one element + [1, 3.1215, undef] # three elements + ] + +This will be translated to a 2 by 3 C that looks like this: + + VT_BSTR("Perl") VT_EMPTY VT_EMPTY + VT_I4(1) VT_R8(3.1415) VT_ERROR(DISP_E_PARAMNOTFOUND) + +B Automatic conversion from Variants +to Perl values happens as follows: + + Variant Perl value + VT_BOOL, VT_ERROR Integer + VT_UI1, VT_I2, VT_I4 Integer + VT_R4, VT_R8 Float value + VT_BSTR String + VT_DISPATCH Win32::OLE object + +B This module provides access to the +Variant data type, which gives you more control over how these +arguments to OLE methods are encoded. (This is rarely necessary if you +have a good grasp of the default conversion rules.) A Variant object +can be created with the C<< Win32::OLE::Variant->new >> method or the +equivalent Variant() function: + + use Win32::OLE::Variant; + my $var1 = Win32::OLE::Variant->new(VT_DATE, 'Jan 1,1970'); + my $var2 = Variant(VT_BSTR, 'This is an Unicode string'); + +Several methods let you inspect and manipulate Variant objects: The +Type() and Value() methods return the variant type and value; the As() +method returns the value after converting it to a different variant +type; ChangeType() coerces the Variant into a different type; and +Unicode() returns the value of a Variant object as an object of the +Unicode::String class. + +These conversions are more interesting if they can be applied directly +to the return value of an OLE method call without first mutilating the +value with default conversions. This is possible with the following +trick: + + my $RetVal = Variant(VT_EMPTY, undef); + $Object->Dispatch($Method, $RetVal, @Arguments); + +Normally, you wouldn't call Dispatch() directly; it's executed +implicitly by either AUTOLOAD() or Invoke(). If Dispatch() realizes +that the return value is already a Win32::OLE::Variant object, the +return value is not translated into a Perl representation but rather +copied verbatim into the Variant object. + +Whenever a Win32::OLE::Variant object is used in a numeric or string +context it is automatically converted into the corresponding format. + + printf "Number: %f and String: %s\n", + $Var, $Var; + +This is equivalent to: + + printf "Number: %f and String: %s\n", + $Var->As(VT_R8), $Var->As(VT_BSTR); + +For methods that modify their arguments, you need to use the C +flag. This lets you create number and string Variants that can be +modified by OLE methods. Here, Corel's GetSize() method takes two +integers and stores the C and C dimensions in them: + + my $x = Variant( VT_I4 | VT_BYREF, 0); + my $y = Variant( VT_I4 | VT_BYREF, 0); + $Corel->GetSize($x, $y); + +C support for other Variant types might appear in future +releases of Win32::OLE. + +=head1 FURTHER INFORMATION + +=head2 DOCUMENTATION AND EXAMPLE CODE + +More information about the OLE modules can be found in the +documentation bundled with Win32::OLE. The distribution also contains +other code samples. + +The object model for Microsoft Office applications can be found in the +Visual Basic Reference for Microsoft Access, Excel, Word, or +PowerPoint. These help files are not installed by default, but they +can be added later by rerunning F and choosing I. The object model for Microsoft Outlook can be found on the +Microsoft Office Developer Forum at: +http://www.microsoft.com/OutlookDev/. + +Information about the LotusScript object model can be found at: +http://www.lotus.com/products/lotusscript.nsf. + +=head2 OLE AUTOMATION ON OTHER PLATFORMS + +Microsoft also makes OLE technology available for the Mac. DCOM is +already included in Windows NT 4.0 and can be downloaded for Windows +95. MVS and some Unix systems can use EntireX to get OLE +functionality; see +http://www.softwareag.com/corporat/solutions/entirex/entirex.htm. + +=head1 COPYRIGHT + +Copyright 1998 I. http://www.tpj.com + +This article originally appeared in I #10. It +appears courtesy of Jon Orwant and I. This document +may be distributed under the same terms as Perl itself. diff --git a/Master/tlpkg/tlperl/lib/Win32/OLE/TypeInfo.pm b/Master/tlpkg/tlperl/lib/Win32/OLE/TypeInfo.pm new file mode 100644 index 00000000000..d95399c1e29 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/Win32/OLE/TypeInfo.pm @@ -0,0 +1,389 @@ +# This module is still experimental and intentionally undocumented. +# If you don't know why it is here, then you should probably not use it. + +package Win32::OLE::TypeInfo; + +use strict; +use vars qw(@ISA @EXPORT @EXPORT_OK); +use vars qw(@VT %TYPEFLAGS @TYPEKIND %IMPLTYPEFLAGS %PARAMFLAGS + %FUNCFLAGS @CALLCONV @FUNCKIND %INVOKEKIND %VARFLAGS + %LIBFLAGS @SYSKIND); + +use Exporter; +@ISA = qw(Exporter); + +@EXPORT = qw( + VT_EMPTY VT_NULL VT_I2 VT_I4 VT_R4 VT_R8 VT_CY VT_DATE + VT_BSTR VT_DISPATCH VT_ERROR VT_BOOL VT_VARIANT VT_UNKNOWN + VT_DECIMAL VT_I1 VT_UI1 VT_UI2 VT_UI4 VT_I8 VT_UI8 VT_INT + VT_UINT VT_VOID VT_HRESULT VT_PTR VT_SAFEARRAY VT_CARRAY + VT_USERDEFINED VT_LPSTR VT_LPWSTR VT_FILETIME VT_BLOB + VT_STREAM VT_STORAGE VT_STREAMED_OBJECT VT_STORED_OBJECT + VT_BLOB_OBJECT VT_CF VT_CLSID VT_VECTOR VT_ARRAY VT_BYREF + VT_RESERVED VT_ILLEGAL VT_ILLEGALMASKED VT_TYPEMASK + + TYPEFLAG_FAPPOBJECT TYPEFLAG_FCANCREATE TYPEFLAG_FLICENSED + TYPEFLAG_FPREDECLID TYPEFLAG_FHIDDEN TYPEFLAG_FCONTROL + TYPEFLAG_FDUAL TYPEFLAG_FNONEXTENSIBLE TYPEFLAG_FOLEAUTOMATION + TYPEFLAG_FRESTRICTED TYPEFLAG_FAGGREGATABLE TYPEFLAG_FREPLACEABLE + TYPEFLAG_FDISPATCHABLE TYPEFLAG_FREVERSEBIND + + TKIND_ENUM TKIND_RECORD TKIND_MODULE TKIND_INTERFACE TKIND_DISPATCH + TKIND_COCLASS TKIND_ALIAS TKIND_UNION TKIND_MAX + + IMPLTYPEFLAG_FDEFAULT IMPLTYPEFLAG_FSOURCE IMPLTYPEFLAG_FRESTRICTED + IMPLTYPEFLAG_FDEFAULTVTABLE + + PARAMFLAG_NONE PARAMFLAG_FIN PARAMFLAG_FOUT PARAMFLAG_FLCID + PARAMFLAG_FRETVAL PARAMFLAG_FOPT PARAMFLAG_FHASDEFAULT + + FUNCFLAG_FRESTRICTED FUNCFLAG_FSOURCE FUNCFLAG_FBINDABLE + FUNCFLAG_FREQUESTEDIT FUNCFLAG_FDISPLAYBIND FUNCFLAG_FDEFAULTBIND + FUNCFLAG_FHIDDEN FUNCFLAG_FUSESGETLASTERROR FUNCFLAG_FDEFAULTCOLLELEM + FUNCFLAG_FUIDEFAULT FUNCFLAG_FNONBROWSABLE FUNCFLAG_FREPLACEABLE + FUNCFLAG_FIMMEDIATEBIND + + CC_FASTCALL CC_CDECL CC_MSCPASCAL CC_PASCAL CC_MACPASCAL CC_STDCALL + CC_FPFASTCALL CC_SYSCALL CC_MPWCDECL CC_MPWPASCAL CC_MAX + + INVOKE_FUNC INVOKE_PROPERTYGET INVOKE_PROPERTYPUT INVOKE_PROPERTYPUTREF + + VARFLAG_FREADONLY VARFLAG_FSOURCE VARFLAG_FBINDABLE VARFLAG_FREQUESTEDIT + VARFLAG_FDISPLAYBIND VARFLAG_FDEFAULTBIND VARFLAG_FHIDDEN VARFLAG_FRESTRICTED + VARFLAG_FDEFAULTCOLLELEM VARFLAG_FUIDEFAULT VARFLAG_FNONBROWSABLE + VARFLAG_FREPLACEABLE VARFLAG_FIMMEDIATEBIND + + LIBFLAG_FRESTRICTED LIBFLAG_FCONTROL LIBFLAG_FHIDDEN + SYS_WIN16 SYS_WIN32 SYS_MAC + + FUNC_VIRTUAL FUNC_PUREVIRTUAL FUNC_NONVIRTUAL FUNC_STATIC FUNC_DISPATCH + + @VT %TYPEFLAGS @TYPEKIND %IMPLTYPEFLAGS %PARAMFLAGS + %FUNCFLAGS @CALLCONV @FUNCKIND %INVOKEKIND %VARFLAGS %LIBFLAGS @SYSKIND +); + +# Lib Flags +# --------- + +sub LIBFLAG_FRESTRICTED () { 0x01; } +sub LIBFLAG_FCONTROL () { 0x02; } +sub LIBFLAG_FHIDDEN () { 0x04; } + +$LIBFLAGS{LIBFLAG_FRESTRICTED()} = LIBFLAG_FRESTRICTED; +$LIBFLAGS{LIBFLAG_FCONTROL()} = LIBFLAG_FCONTROL; +$LIBFLAGS{LIBFLAG_FHIDDEN()} = LIBFLAG_FHIDDEN; + +# Sys Kind +# -------- + +sub SYS_WIN16 () { 0; } +sub SYS_WIN32 () { SYS_WIN16() + 1; } +sub SYS_MAC () { SYS_WIN32() + 1; } + +$SYSKIND[SYS_WIN16] = 'SYS_WIN16'; +$SYSKIND[SYS_WIN32] = 'SYS_WIN32'; +$SYSKIND[SYS_MAC] = 'SYS_MAC'; + +# Type Flags +# ---------- + +sub TYPEFLAG_FAPPOBJECT () { 0x1; } +sub TYPEFLAG_FCANCREATE () { 0x2; } +sub TYPEFLAG_FLICENSED () { 0x4; } +sub TYPEFLAG_FPREDECLID () { 0x8; } +sub TYPEFLAG_FHIDDEN () { 0x10; } +sub TYPEFLAG_FCONTROL () { 0x20; } +sub TYPEFLAG_FDUAL () { 0x40; } +sub TYPEFLAG_FNONEXTENSIBLE () { 0x80; } +sub TYPEFLAG_FOLEAUTOMATION () { 0x100; } +sub TYPEFLAG_FRESTRICTED () { 0x200; } +sub TYPEFLAG_FAGGREGATABLE () { 0x400; } +sub TYPEFLAG_FREPLACEABLE () { 0x800; } +sub TYPEFLAG_FDISPATCHABLE () { 0x1000; } +sub TYPEFLAG_FREVERSEBIND () { 0x2000; } + +$TYPEFLAGS{TYPEFLAG_FAPPOBJECT()} = TYPEFLAG_FAPPOBJECT; +$TYPEFLAGS{TYPEFLAG_FCANCREATE()} = TYPEFLAG_FCANCREATE; +$TYPEFLAGS{TYPEFLAG_FLICENSED()} = TYPEFLAG_FLICENSED; +$TYPEFLAGS{TYPEFLAG_FPREDECLID()} = TYPEFLAG_FPREDECLID; +$TYPEFLAGS{TYPEFLAG_FHIDDEN()} = TYPEFLAG_FHIDDEN; +$TYPEFLAGS{TYPEFLAG_FCONTROL()} = TYPEFLAG_FCONTROL; +$TYPEFLAGS{TYPEFLAG_FDUAL()} = TYPEFLAG_FDUAL; +$TYPEFLAGS{TYPEFLAG_FNONEXTENSIBLE()} = TYPEFLAG_FNONEXTENSIBLE; +$TYPEFLAGS{TYPEFLAG_FOLEAUTOMATION()} = TYPEFLAG_FOLEAUTOMATION; +$TYPEFLAGS{TYPEFLAG_FRESTRICTED()} = TYPEFLAG_FRESTRICTED; +$TYPEFLAGS{TYPEFLAG_FAGGREGATABLE()} = TYPEFLAG_FAGGREGATABLE; +$TYPEFLAGS{TYPEFLAG_FREPLACEABLE()} = TYPEFLAG_FREPLACEABLE; +$TYPEFLAGS{TYPEFLAG_FDISPATCHABLE()} = TYPEFLAG_FDISPATCHABLE; +$TYPEFLAGS{TYPEFLAG_FREVERSEBIND()} = TYPEFLAG_FREVERSEBIND; + +# Type Kind +# --------- + +sub TKIND_ENUM () { 0; } +sub TKIND_RECORD () { TKIND_ENUM() + 1; } +sub TKIND_MODULE () { TKIND_RECORD() + 1; } +sub TKIND_INTERFACE () { TKIND_MODULE() + 1; } +sub TKIND_DISPATCH () { TKIND_INTERFACE() + 1; } +sub TKIND_COCLASS () { TKIND_DISPATCH() + 1; } +sub TKIND_ALIAS () { TKIND_COCLASS() + 1; } +sub TKIND_UNION () { TKIND_ALIAS() + 1; } +sub TKIND_MAX () { TKIND_UNION() + 1; } + +$TYPEKIND[TKIND_ENUM] = 'TKIND_ENUM'; +$TYPEKIND[TKIND_RECORD] = 'TKIND_RECORD'; +$TYPEKIND[TKIND_MODULE] = 'TKIND_MODULE'; +$TYPEKIND[TKIND_INTERFACE] = 'TKIND_INTERFACE'; +$TYPEKIND[TKIND_DISPATCH] = 'TKIND_DISPATCH'; +$TYPEKIND[TKIND_COCLASS] = 'TKIND_COCLASS'; +$TYPEKIND[TKIND_ALIAS] = 'TKIND_ALIAS'; +$TYPEKIND[TKIND_UNION] = 'TKIND_UNION'; + +# Implemented Type Flags +# ---------------------- + +sub IMPLTYPEFLAG_FDEFAULT () { 0x1; } +sub IMPLTYPEFLAG_FSOURCE () { 0x2; } +sub IMPLTYPEFLAG_FRESTRICTED () { 0x4; } +sub IMPLTYPEFLAG_FDEFAULTVTABLE () { 0x800; } + +$IMPLTYPEFLAGS{IMPLTYPEFLAG_FDEFAULT()} = IMPLTYPEFLAG_FDEFAULT; +$IMPLTYPEFLAGS{IMPLTYPEFLAG_FSOURCE()} = IMPLTYPEFLAG_FSOURCE; +$IMPLTYPEFLAGS{IMPLTYPEFLAG_FRESTRICTED()} = IMPLTYPEFLAG_FRESTRICTED; +$IMPLTYPEFLAGS{IMPLTYPEFLAG_FDEFAULTVTABLE()} = IMPLTYPEFLAG_FDEFAULTVTABLE; + +# Parameter Flags +# --------------- + +sub PARAMFLAG_NONE () { 0; } +sub PARAMFLAG_FIN () { 0x1; } +sub PARAMFLAG_FOUT () { 0x2; } +sub PARAMFLAG_FLCID () { 0x4; } +sub PARAMFLAG_FRETVAL () { 0x8; } +sub PARAMFLAG_FOPT () { 0x10; } +sub PARAMFLAG_FHASDEFAULT () { 0x20; } + +$PARAMFLAGS{PARAMFLAG_NONE()} = PARAMFLAG_NONE; +$PARAMFLAGS{PARAMFLAG_FIN()} = PARAMFLAG_FIN; +$PARAMFLAGS{PARAMFLAG_FOUT()} = PARAMFLAG_FOUT; +$PARAMFLAGS{PARAMFLAG_FLCID()} = PARAMFLAG_FLCID; +$PARAMFLAGS{PARAMFLAG_FRETVAL()} = PARAMFLAG_FRETVAL; +$PARAMFLAGS{PARAMFLAG_FOPT()} = PARAMFLAG_FOPT; +$PARAMFLAGS{PARAMFLAG_FHASDEFAULT()} = PARAMFLAG_FHASDEFAULT; + +# Function Flags +# -------------- + +sub FUNCFLAG_FRESTRICTED () { 0x1; } +sub FUNCFLAG_FSOURCE () { 0x2; } +sub FUNCFLAG_FBINDABLE () { 0x4; } +sub FUNCFLAG_FREQUESTEDIT () { 0x8; } +sub FUNCFLAG_FDISPLAYBIND () { 0x10; } +sub FUNCFLAG_FDEFAULTBIND () { 0x20; } +sub FUNCFLAG_FHIDDEN () { 0x40; } +sub FUNCFLAG_FUSESGETLASTERROR () { 0x80; } +sub FUNCFLAG_FDEFAULTCOLLELEM () { 0x100; } +sub FUNCFLAG_FUIDEFAULT () { 0x200; } +sub FUNCFLAG_FNONBROWSABLE () { 0x400; } +sub FUNCFLAG_FREPLACEABLE () { 0x800; } +sub FUNCFLAG_FIMMEDIATEBIND () { 0x1000; } + +$FUNCFLAGS{FUNCFLAG_FRESTRICTED()} = FUNCFLAG_FRESTRICTED; +$FUNCFLAGS{FUNCFLAG_FSOURCE()} = FUNCFLAG_FSOURCE; +$FUNCFLAGS{FUNCFLAG_FBINDABLE()} = FUNCFLAG_FBINDABLE; +$FUNCFLAGS{FUNCFLAG_FREQUESTEDIT()} = FUNCFLAG_FREQUESTEDIT; +$FUNCFLAGS{FUNCFLAG_FDISPLAYBIND()} = FUNCFLAG_FDISPLAYBIND; +$FUNCFLAGS{FUNCFLAG_FDEFAULTBIND()} = FUNCFLAG_FDEFAULTBIND; +$FUNCFLAGS{FUNCFLAG_FHIDDEN()} = FUNCFLAG_FHIDDEN; +$FUNCFLAGS{FUNCFLAG_FUSESGETLASTERROR()} = FUNCFLAG_FUSESGETLASTERROR; +$FUNCFLAGS{FUNCFLAG_FDEFAULTCOLLELEM()} = FUNCFLAG_FDEFAULTCOLLELEM; +$FUNCFLAGS{FUNCFLAG_FUIDEFAULT()} = FUNCFLAG_FUIDEFAULT; +$FUNCFLAGS{FUNCFLAG_FNONBROWSABLE()} = FUNCFLAG_FNONBROWSABLE; +$FUNCFLAGS{FUNCFLAG_FREPLACEABLE()} = FUNCFLAG_FREPLACEABLE; +$FUNCFLAGS{FUNCFLAG_FIMMEDIATEBIND()} = FUNCFLAG_FIMMEDIATEBIND; + +# Calling conventions +# ------------------- + +sub CC_FASTCALL () { 0; } +sub CC_CDECL () { 1; } +sub CC_MSCPASCAL () { CC_CDECL() + 1; } +sub CC_PASCAL () { CC_MSCPASCAL; } +sub CC_MACPASCAL () { CC_PASCAL() + 1; } +sub CC_STDCALL () { CC_MACPASCAL() + 1; } +sub CC_FPFASTCALL () { CC_STDCALL() + 1; } +sub CC_SYSCALL () { CC_FPFASTCALL() + 1; } +sub CC_MPWCDECL () { CC_SYSCALL() + 1; } +sub CC_MPWPASCAL () { CC_MPWCDECL() + 1; } +sub CC_MAX () { CC_MPWPASCAL() + 1; } + +$CALLCONV[CC_FASTCALL] = 'CC_FASTCALL'; +$CALLCONV[CC_CDECL] = 'CC_CDECL'; +$CALLCONV[CC_PASCAL] = 'CC_PASCAL'; +$CALLCONV[CC_MACPASCAL] = 'CC_MACPASCAL'; +$CALLCONV[CC_STDCALL] = 'CC_STDCALL'; +$CALLCONV[CC_FPFASTCALL] = 'CC_FPFASTCALL'; +$CALLCONV[CC_SYSCALL] = 'CC_SYSCALL'; +$CALLCONV[CC_MPWCDECL] = 'CC_MPWCDECL'; +$CALLCONV[CC_MPWPASCAL] = 'CC_MPWPASCAL'; + +# Function Kind +# ------------- + +sub FUNC_VIRTUAL () { 0; } +sub FUNC_PUREVIRTUAL () { FUNC_VIRTUAL() + 1; } +sub FUNC_NONVIRTUAL () { FUNC_PUREVIRTUAL() + 1; } +sub FUNC_STATIC () { FUNC_NONVIRTUAL() + 1; } +sub FUNC_DISPATCH () { FUNC_STATIC() + 1; } + +$FUNCKIND[FUNC_VIRTUAL] = 'FUNC_VIRTUAL'; +$FUNCKIND[FUNC_PUREVIRTUAL] = 'FUNC_PUREVIRTUAL'; +$FUNCKIND[FUNC_NONVIRTUAL] = 'FUNC_NONVIRTUAL'; +$FUNCKIND[FUNC_STATIC] = 'FUNC_STATIC'; +$FUNCKIND[FUNC_DISPATCH] = 'FUNC_DISPATCH'; + +# Invoke Kind +# ----------- + +sub INVOKE_FUNC () { 1; } +sub INVOKE_PROPERTYGET () { 2; } +sub INVOKE_PROPERTYPUT () { 4; } +sub INVOKE_PROPERTYPUTREF () { 8; } + +$INVOKEKIND{INVOKE_FUNC()} = INVOKE_FUNC; +$INVOKEKIND{INVOKE_PROPERTYGET()} = INVOKE_PROPERTYGET; +$INVOKEKIND{INVOKE_PROPERTYPUT()} = INVOKE_PROPERTYPUT; +$INVOKEKIND{INVOKE_PROPERTYPUTREF()} = INVOKE_PROPERTYPUTREF; + +# Variable Flags +# -------------- + +sub VARFLAG_FREADONLY () { 0x1; } +sub VARFLAG_FSOURCE () { 0x2; } +sub VARFLAG_FBINDABLE () { 0x4; } +sub VARFLAG_FREQUESTEDIT () { 0x8; } +sub VARFLAG_FDISPLAYBIND () { 0x10; } +sub VARFLAG_FDEFAULTBIND () { 0x20; } +sub VARFLAG_FHIDDEN () { 0x40; } +sub VARFLAG_FRESTRICTED () { 0x80; } +sub VARFLAG_FDEFAULTCOLLELEM () { 0x100; } +sub VARFLAG_FUIDEFAULT () { 0x200; } +sub VARFLAG_FNONBROWSABLE () { 0x400; } +sub VARFLAG_FREPLACEABLE () { 0x800; } +sub VARFLAG_FIMMEDIATEBIND () { 0x1000; } + +$VARFLAGS{VARFLAG_FREADONLY()} = VARFLAG_FREADONLY; +$VARFLAGS{VARFLAG_FSOURCE()} = VARFLAG_FSOURCE; +$VARFLAGS{VARFLAG_FBINDABLE()} = VARFLAG_FBINDABLE; +$VARFLAGS{VARFLAG_FREQUESTEDIT()} = VARFLAG_FREQUESTEDIT; +$VARFLAGS{VARFLAG_FDISPLAYBIND()} = VARFLAG_FDISPLAYBIND; +$VARFLAGS{VARFLAG_FDEFAULTBIND()} = VARFLAG_FDEFAULTBIND; +$VARFLAGS{VARFLAG_FHIDDEN()} = VARFLAG_FHIDDEN; +$VARFLAGS{VARFLAG_FRESTRICTED()} = VARFLAG_FRESTRICTED; +$VARFLAGS{VARFLAG_FDEFAULTCOLLELEM()} = VARFLAG_FDEFAULTCOLLELEM; +$VARFLAGS{VARFLAG_FUIDEFAULT()} = VARFLAG_FUIDEFAULT; +$VARFLAGS{VARFLAG_FNONBROWSABLE()} = VARFLAG_FNONBROWSABLE; +$VARFLAGS{VARFLAG_FREPLACEABLE()} = VARFLAG_FREPLACEABLE; +$VARFLAGS{VARFLAG_FIMMEDIATEBIND()} = VARFLAG_FIMMEDIATEBIND; + + +# Variant Types +# ------------- + +sub VT_EMPTY () { 0; } +sub VT_NULL () { 1; } +sub VT_I2 () { 2; } +sub VT_I4 () { 3; } +sub VT_R4 () { 4; } +sub VT_R8 () { 5; } +sub VT_CY () { 6; } +sub VT_DATE () { 7; } +sub VT_BSTR () { 8; } +sub VT_DISPATCH () { 9; } +sub VT_ERROR () { 10; } +sub VT_BOOL () { 11; } +sub VT_VARIANT () { 12; } +sub VT_UNKNOWN () { 13; } +sub VT_DECIMAL () { 14; } +sub VT_I1 () { 16; } +sub VT_UI1 () { 17; } +sub VT_UI2 () { 18; } +sub VT_UI4 () { 19; } +sub VT_I8 () { 20; } +sub VT_UI8 () { 21; } +sub VT_INT () { 22; } +sub VT_UINT () { 23; } +sub VT_VOID () { 24; } +sub VT_HRESULT () { 25; } +sub VT_PTR () { 26; } +sub VT_SAFEARRAY () { 27; } +sub VT_CARRAY () { 28; } +sub VT_USERDEFINED () { 29; } +sub VT_LPSTR () { 30; } +sub VT_LPWSTR () { 31; } +sub VT_FILETIME () { 64; } +sub VT_BLOB () { 65; } +sub VT_STREAM () { 66; } +sub VT_STORAGE () { 67; } +sub VT_STREAMED_OBJECT () { 68; } +sub VT_STORED_OBJECT () { 69; } +sub VT_BLOB_OBJECT () { 70; } +sub VT_CF () { 71; } +sub VT_CLSID () { 72; } +sub VT_VECTOR () { 0x1000; } +sub VT_ARRAY () { 0x2000; } +sub VT_BYREF () { 0x4000; } +sub VT_RESERVED () { 0x8000; } +sub VT_ILLEGAL () { 0xffff; } +sub VT_ILLEGALMASKED () { 0xfff; } +sub VT_TYPEMASK () { 0xfff; } + +$VT[VT_EMPTY] = 'VT_EMPTY'; +$VT[VT_NULL] = 'VT_NULL'; +$VT[VT_I2] = 'VT_I2'; +$VT[VT_I4] = 'VT_I4'; +$VT[VT_R4] = 'VT_R4'; +$VT[VT_R8] = 'VT_R8'; +$VT[VT_CY] = 'VT_CY'; +$VT[VT_DATE] = 'VT_DATE'; +$VT[VT_BSTR] = 'VT_BSTR'; +$VT[VT_DISPATCH] = 'VT_DISPATCH'; +$VT[VT_ERROR] = 'VT_ERROR'; +$VT[VT_BOOL] = 'VT_BOOL'; +$VT[VT_VARIANT] = 'VT_VARIANT'; +$VT[VT_UNKNOWN] = 'VT_UNKNOWN'; +$VT[VT_DECIMAL] = 'VT_DECIMAL'; +$VT[VT_I1] = 'VT_I1'; +$VT[VT_UI1] = 'VT_UI1'; +$VT[VT_UI2] = 'VT_UI2'; +$VT[VT_UI4] = 'VT_UI4'; +$VT[VT_I8] = 'VT_I8'; +$VT[VT_UI8] = 'VT_UI8'; +$VT[VT_INT] = 'VT_INT'; +$VT[VT_UINT] = 'VT_UINT'; +$VT[VT_VOID] = 'VT_VOID'; +$VT[VT_HRESULT] = 'VT_HRESULT'; +$VT[VT_PTR] = 'VT_PTR'; +$VT[VT_SAFEARRAY] = 'VT_SAFEARRAY'; +$VT[VT_CARRAY] = 'VT_CARRAY'; +$VT[VT_USERDEFINED] = 'VT_USERDEFINED'; +$VT[VT_LPSTR] = 'VT_LPSTR'; +$VT[VT_LPWSTR] = 'VT_LPWSTR'; +$VT[VT_FILETIME] = 'VT_FILETIME'; +$VT[VT_BLOB] = 'VT_BLOB'; +$VT[VT_STREAM] = 'VT_STREAM'; +$VT[VT_STORAGE] = 'VT_STORAGE'; +$VT[VT_STREAMED_OBJECT] = 'VT_STREAMED_OBJECT'; +$VT[VT_STORED_OBJECT] = 'VT_STORED_OBJECT'; +$VT[VT_BLOB_OBJECT] = 'VT_BLOB_OBJECT'; +$VT[VT_CF] = 'VT_CF'; +$VT[VT_CLSID] = 'VT_CLSID'; +$VT[VT_VECTOR] = 'VT_VECTOR'; +$VT[VT_ARRAY] = 'VT_ARRAY'; +$VT[VT_BYREF] = 'VT_BYREF'; +$VT[VT_RESERVED] = 'VT_RESERVED'; +$VT[VT_ILLEGAL] = 'VT_ILLEGAL'; +$VT[VT_ILLEGALMASKED] = 'VT_ILLEGALMASKED'; +$VT[VT_TYPEMASK] = 'VT_TYPEMASK'; + +1; diff --git a/Master/tlpkg/tlperl/lib/Win32/OLE/Variant.pm b/Master/tlpkg/tlperl/lib/Win32/OLE/Variant.pm new file mode 100644 index 00000000000..49e363da334 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/Win32/OLE/Variant.pm @@ -0,0 +1,577 @@ +# The documentation is at the __END__ + +package Win32::OLE::Variant; +require Win32::OLE; # Make sure the XS bootstrap has been called + +use strict; +use vars qw(@ISA @EXPORT @EXPORT_OK); + +use Exporter; +@ISA = qw(Exporter); + +@EXPORT = qw( + Variant + VT_EMPTY VT_NULL VT_I2 VT_I4 VT_R4 VT_R8 VT_CY VT_DATE VT_BSTR + VT_DISPATCH VT_ERROR VT_BOOL VT_VARIANT VT_UNKNOWN VT_DECIMAL VT_UI1 + VT_ARRAY VT_BYREF + ); + +@EXPORT_OK = qw(CP_ACP CP_OEMCP nothing nullstring); + +# Automation data types. +sub VT_EMPTY {0;} +sub VT_NULL {1;} +sub VT_I2 {2;} +sub VT_I4 {3;} +sub VT_R4 {4;} +sub VT_R8 {5;} +sub VT_CY {6;} +sub VT_DATE {7;} +sub VT_BSTR {8;} +sub VT_DISPATCH {9;} +sub VT_ERROR {10;} +sub VT_BOOL {11;} +sub VT_VARIANT {12;} +sub VT_UNKNOWN {13;} +sub VT_DECIMAL {14;} # Officially not allowed in VARIANTARGs +sub VT_UI1 {17;} + +sub VT_ARRAY {0x2000;} +sub VT_BYREF {0x4000;} + + +# For backward compatibility +sub CP_ACP {0;} # ANSI codepage +sub CP_OEMCP {1;} # OEM codepage + +use overload + # '+' => 'Add', '-' => 'Sub', '*' => 'Mul', '/' => 'Div', + '""' => sub {$_[0]->As(VT_BSTR)}, + '0+' => sub {$_[0]->As(VT_R8)}, + fallback => 1; + +sub Variant { + return Win32::OLE::Variant->new(@_); +} + +sub nothing { + return Win32::OLE::Variant->new(VT_DISPATCH); +} + +sub nullstring { + return Win32::OLE::Variant->new(VT_BSTR); +} + +1; + +__END__ + +=head1 NAME + +Win32::OLE::Variant - Create and modify OLE VARIANT variables + +=head1 SYNOPSIS + + use Win32::OLE::Variant; + my $var = Variant(VT_DATE, 'Jan 1,1970'); + $OleObject->{value} = $var; + $OleObject->Method($var); + + +=head1 DESCRIPTION + +The IDispatch interface used by the Perl OLE module uses a universal +argument type called VARIANT. This is basically an object containing +a data type and the actual data value. The data type is specified by +the VT_xxx constants. + +=head2 Functions + +=over 8 + +=item nothing() + +The nothing() function returns an empty VT_DISPATCH variant. It can be +used to clear an object reference stored in a property + + use Win32::OLE::Variant qw(:DEFAULT nothing); + # ... + $object->{Property} = nothing; + +This has the same effect as the Visual Basic statement + + Set object.Property = Nothing + +The nothing() function is B exported by default. + +=item nullstring() + +The nullstring() function returns a VT_BSTR variant with a NULL string +pointer. This is B the same as a VT_BSTR variant with an empty +string "". The nullstring() value is the same as the vbNullString +constant in Visual Basic. + +The nullstring() function is B exported by default. + +=item Variant(TYPE, DATA) + +This is just a function alias of the Cnew()> +method (see below). This function is exported by default. + +=back + +=head2 Methods + +=over 8 + +=item new(TYPE, DATA) + +This method returns a Win32::OLE::Variant object of the specified +TYPE that contains the given DATA. The Win32::OLE::Variant object +can be used to specify data types other than IV, NV or PV (which are +supported transparently). See L below for details. + +For VT_EMPTY and VT_NULL variants, the DATA argument may be omitted. +For all non-VT_ARRAY variants DATA specifies the initial value. + +To create a SAFEARRAY variant, you have to specify the VT_ARRAY flag in +addition to the variant base type of the array elemnts. In this cases +DATA must be a list specifying the dimensions of the array. Each element +can be either an element count (indices 0 to count-1) or an array +reference pointing to the lower and upper array bounds of this dimension: + + my $Array = Win32::OLE::Variant->new(VT_ARRAY|VT_R8, [1,2], 2); + +This creates a 2-dimensional SAFEARRAY of doubles with 4 elements: +(1,0), (1,1), (2,0) and (2,1). + +A special case is the the creation of one-dimensional VT_UI1 arrays with +a string DATA argument: + + my $String = Variant(VT_ARRAY|VT_UI1, "String"); + +This creates a 6 element character array initialized to "String". For +backward compatibility VT_UI1 with a string initializer automatically +implies VT_ARRAY. The next line is equivalent to the previous example: + + my $String = Variant(VT_UI1, "String"); + +If you really need a single character VT_UI1 variant, you have to create +it using a numeric intializer: + + my $Char = Variant(VT_UI1, ord('A')); + +=item As(TYPE) + +C converts the VARIANT to the new type before converting to a +Perl value. This take the current LCID setting into account. For +example a string might contain a ',' as the decimal point character. +Using C<$variant->As(VT_R8)> will correctly return the floating +point value. + +The underlying variant object is NOT changed by this method. + +=item ChangeType(TYPE) + +This method changes the type of the contained VARIANT in place. It +returns the object itself, not the converted value. + +=item Copy([DIM]) + +This method creates a copy of the object. If the original variant had +the VT_BYREF bit set then the new object will contain a copy of the +referenced data and not a reference to the same old data. The new +object will not have the VT_BYREF bit set. + + my $Var = Variant(VT_I4|VT_ARRAY|VT_BYREF, [1,5], 3); + my $Copy = $Var->Copy; + +The type of C<$Copy> is now VT_I4|VT_ARRAY and the value is a copy of +the other SAFEARRAY. Changes to elements of C<$Var> will not be reflected +in C<$Copy> and vice versa. + +The C method can also be used to extract a single element of a +VT_ARRAY | VT_VARIANT object. In this case the array indices must be +specified as a list DIM: + + my $Int = $Var->Copy(1, 2); + +C<$Int> is now a VT_I4 Variant object containing the value of element (1,2). + +=item Currency([FORMAT[, LCID]]) + +This method converts the VARIANT value into a formatted curency string. The +FORMAT can be either an integer constant or a hash reference. Valid constants +are 0 and LOCALE_NOUSEROVERRIDE. You get the value of LOCALE_NOUSEROVERRIDE +from the Win32::OLE::NLS module: + + use Win32::OLE::NLS qw(:LOCALE); + +LOCALE_NOUSEROVERRIDE tells the method to use the system default currency +format for the specified locale, disregarding any changes that might have +been made through the control panel application. + +The hash reference could contain the following keys: + + NumDigits number of fractional digits + LeadingZero whether to use leading zeroes in decimal fields + Grouping size of each group of digits to the left of the decimal + DecimalSep decimal separator string + ThousandSep thousand separator string + NegativeOrder see L + PositiveOrder see L + CurrencySymbol currency symbol string + +For example: + + use Win32::OLE::Variant; + use Win32::OLE::NLS qw(:DEFAULT :LANG :SUBLANG :DATE :TIME); + my $lcidGerman = MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_NEUTRAL)); + my $v = Variant(VT_CY, "-922337203685477.5808"); + print $v->Currency({CurrencySymbol => "Tuits"}, $lcidGerman), "\n"; + +will print: + + -922.337.203.685.477,58 Tuits + +=item Date([FORMAT[, LCID]]) + +Converts the VARIANT into a formatted date string. FORMAT can be either +one of the following integer constants or a format string: + + LOCALE_NOUSEROVERRIDE system default date format for this locale + DATE_SHORTDATE use the short date format (default) + DATE_LONGDATE use the long date format + DATE_YEARMONTH use the year/month format + DATE_USE_ALT_CALENDAR use the alternate calendar, if one exists + DATE_LTRREADING left-to-right reading order layout + DATE_RTLREADING right-to left reading order layout + +The constants are available from the Win32::OLE::NLS module: + + use Win32::OLE::NLS qw(:LOCALE :DATE); + +The following elements can be used to construct a date format string. +Characters must be specified exactly as given below (e.g. "dd" B "DD"). +Spaces can be inserted anywhere between formating codes, other verbatim +text should be included in single quotes. + + d day of month + dd day of month with leading zero for single-digit days + ddd day of week: three-letter abbreviation (LOCALE_SABBREVDAYNAME) + dddd day of week: full name (LOCALE_SDAYNAME) + M month + MM month with leading zero for single-digit months + MMM month: three-letter abbreviation (LOCALE_SABBREVMONTHNAME) + MMMM month: full name (LOCALE_SMONTHNAME) + y year as last two digits + yy year as last two digits with leading zero for years less than 10 + yyyy year represented by full four digits + gg period/era string + +For example: + + my $v = Variant(VT_DATE, "April 1 99"); + print $v->Date(DATE_LONGDATE), "\n"; + print $v->Date("ddd',' MMM dd yy"), "\n"; + +will print: + + Thursday, April 01, 1999 + Thu, Apr 01 99 + +=item Dim() + +Returns a list of array bounds for a VT_ARRAY variant. The list contains +an array reference for each dimension of the variant's SAFEARRAY. This +reference points to an array containing the lower and upper bounds for +this dimension. For example: + + my @Dim = $Var->Dim; + +Now C<@Dim> contains the following list: C<([1,5], [0,2])>. + +=item Get(DIM) + +For normal variants C returns the value of the variant, just like the +C method. For VT_ARRAY variants C retrieves the value of a single +array element. In this case C must be a list of array indices. E.g. + + my $Val = $Var->Get(2,0); + +As a special case for one dimensional VT_UI1|VT_ARRAY variants the C +method without arguments returns the character array as a Perl string. + + print $String->Get, "\n"; + +=item IsNothing() + +Tests if the object is an empty VT_DISPATCH variant. See also nothing(). + +=item IsNullString() + +Tests if the object is an empty VT_BSTR variant. See also nullstring(). + +=item LastError() + +The use of the CLastError()> method is deprecated. +Please use the CLastError()> class method instead. + +=item Number([FORMAT[, LCID]]) + +This method converts the VARIANT value into a formatted number string. The +FORMAT can be either an integer constant or a hash reference. Valid constants +are 0 and LOCALE_NOUSEROVERRIDE. You get the value of LOCALE_NOUSEROVERRIDE +from the Win32::OLE::NLS module: + + use Win32::OLE::NLS qw(:LOCALE); + +LOCALE_NOUSEROVERRIDE tells the method to use the system default number +format for the specified locale, disregarding any changes that might have +been made through the control panel application. + +The hash reference could contain the following keys: + + NumDigits number of fractional digits + LeadingZero whether to use leading zeroes in decimal fields + Grouping size of each group of digits to the left of the decimal + DecimalSep decimal separator string + ThousandSep thousand separator string + NegativeOrder see L + +=item Put(DIM, VALUE) + +The C method is used to assign a new value to a variant. The value will +be coerced into the current type of the variant. E.g.: + + my $Var = Variant(VT_I4, 42); + $Var->Put(3.1415); + +This changes the value of the variant to C<3> because the type is VT_I4. + +For VT_ARRAY type variants the indices for each dimension of the contained +SAFEARRAY must be specified in front of the new value: + + $Array->Put(1, 1, 2.7); + +It is also possible to assign values to *every* element of the SAFEARRAY at +once using a single Put() method call: + + $Array->Put([[1,2], [3,4]]); + +In this case the argument to Put() must be an array reference and the +dimensions of the Perl list-of-lists must match the dimensions of the +SAFEARRAY exactly. + +The are a few special cases for one-dimensional VT_UI1 arrays: The VALUE +can be specified as a string instead of a number. This will set the selected +character to the first character of the string or to '\0' if the string was +empty: + + my $String = Variant(VT_UI1|VT_ARRAY, "ABCDE"); + $String->Put(1, "123"); + $String->Put(3, ord('Z')); + $String->Put(4, ''); + +This will set the value of C<$String> to C<"A1CZ\0">. If the index is omitted +then the string is copied to the value completely. The string is truncated +if it is longer than the size of the VT_UI1 array. The result will be padded +with '\0's if the string is shorter: + + $String->Put("String"); + +Now C<$String> contains the value "Strin". + +C returns the Variant object itself so that multiple C calls can be +chained together: + + $Array->Put(0,0,$First_value)->Put(0,1,$Another_value); + +=item Time([FORMAT[, LCID]]) + +Converts the VARIANT into a formatted time string. FORMAT can be either +one of the following integer constants or a format string: + + LOCALE_NOUSEROVERRIDE system default time format for this locale + TIME_NOMINUTESORSECONDS don't use minutes or seconds + TIME_NOSECONDS don't use seconds + TIME_NOTIMEMARKER don't use a time marker + TIME_FORCE24HOURFORMAT always use a 24-hour time format + +The constants are available from the Win32::OLE::NLS module: + + use Win32::OLE::NLS qw(:LOCALE :TIME); + +The following elements can be used to construct a time format string. +Characters must be specified exactly as given below (e.g. "dd" B "DD"). +Spaces can be inserted anywhere between formating codes, other verbatim +text should be included in single quotes. + + h hours; 12-hour clock + hh hours with leading zero for single-digit hours; 12-hour clock + H hours; 24-hour clock + HH hours with leading zero for single-digit hours; 24-hour clock + m minutes + mm minutes with leading zero for single-digit minutes + s seconds + ss seconds with leading zero for single-digit seconds + t one character time marker string, such as A or P + tt multicharacter time marker string, such as AM or PM + +For example: + + my $v = Variant(VT_DATE, "April 1 99 2:23 pm"); + print $v->Time, "\n"; + print $v->Time(TIME_FORCE24HOURFORMAT|TIME_NOTIMEMARKER), "\n"; + print $v->Time("hh.mm.ss tt"), "\n"; + +will print: + + 2:23:00 PM + 14:23:00 + 02.23.00 PM + +=item Type() + +The C method returns the variant type of the contained VARIANT. + +=item Unicode() + +The C method returns a C object. This contains +the BSTR value of the variant in network byte order. If the variant is +not currently in VT_BSTR format then a VT_BSTR copy will be produced first. + +=item Value() + +The C method returns the value of the VARIANT as a Perl value. The +conversion is performed in the same manner as all return values of +Win32::OLE method calls are converted. + +=back + +=head2 Overloading + +The Win32::OLE::Variant package has overloaded the conversion to +string and number formats. Therefore variant objects can be used in +arithmetic and string operations without applying the C +method first. + +=head2 Class Variables + +The Win32::OLE::Variant class used to have its own set of class variables +like C<$CP>, C<$LCID> and C<$Warn>. In version 0.1003 and later of the +Win32::OLE module these variables have been eleminated. Now the settings +of Win32::OLE are used by the Win32::OLE::Variant module too. Please read +the documentation of the C class method. + + +=head2 Constants + +These constants are exported by default: + + VT_EMPTY + VT_NULL + VT_I2 + VT_I4 + VT_R4 + VT_R8 + VT_CY + VT_DATE + VT_BSTR + VT_DISPATCH + VT_ERROR + VT_BOOL + VT_VARIANT + VT_UNKNOWN + VT_DECIMAL + VT_UI1 + + VT_ARRAY + VT_BYREF + +VT_DECIMAL is not on the official list of allowable OLE Automation +datatypes. But even Microsoft ADO seems to sometimes return values +of Recordset fields in VT_DECIMAL format. + +=head2 Variants + +A Variant is a data type that is used to pass data between OLE +connections. + +The default behavior is to convert each perl scalar variable into +an OLE Variant according to the internal perl representation. +The following type correspondence holds: + + C type Perl type OLE type + ------ --------- -------- + int IV VT_I4 + double NV VT_R8 + char * PV VT_BSTR + void * ref to AV VT_ARRAY + ? undef VT_ERROR + ? Win32::OLE object VT_DISPATCH + +Note that VT_BSTR is a wide character or Unicode string. This presents a +problem if you want to pass in binary data as a parameter as 0x00 is +inserted between all the bytes in your data. The C method +provides a solution to this. With Variants the script writer can specify +the OLE variant type that the parameter should be converted to. Currently +supported types are: + + VT_UI1 unsigned char + VT_I2 signed int (2 bytes) + VT_I4 signed int (4 bytes) + VT_R4 float (4 bytes) + VT_R8 float (8 bytes) + VT_DATE OLE Date + VT_BSTR OLE String + VT_CY OLE Currency + VT_BOOL OLE Boolean + +When VT_DATE and VT_CY objects are created, the input parameter is treated +as a Perl string type, which is then converted to VT_BSTR, and finally to +VT_DATE of VT_CY using the C OLE API function. +See L for how these types can be used. + +=head2 Variant arrays + +A variant can not only contain a single value but also a multi-dimensional +array of values (called a SAFEARRAY). In this case the VT_ARRAY flag must +be added to the base variant type, e.g. C for an array of +integers. The VT_EMPTY and VT_NULL types are invalid for SAFEARRAYs. It +is possible to create an array of variants: C. In this +case each element of the array can have a different type (including VT_EMPTY +and VT_NULL). The elements of a VT_VARIANT SAFEARRAY cannot have either of the +VT_ARRAY or VT_BYREF flags set. + +The lower and upper bounds for each dimension can be specified separately. +They do not have to have all the same lower bound (unlike Perl's arrays). + +=head2 Variants by reference + +Some OLE servers expect parameters passed by reference so that they +can be changed in the method call. This allows methods to easily +return multiple values. There is preliminary support for this in +the Win32::OLE::Variant module: + + my $x = Variant(VT_I4|VT_BYREF, 0); + my $y = Variant(VT_I4|VT_BYREF, 0); + $Corel->GetSize($x, $y); + print "Size is $x by $y\n"; + +After the C method call C<$x> and C<$y> will be set to +the respective sizes. They will still be variants. In the print +statement the overloading converts them to string representation +automatically. + +VT_BYREF is now supported for all variant types (including SAFEARRAYs). +It can also be used to pass an OLE object by reference: + + my $Results = $App->CreateResultsObject; + $Object->Method(Variant(VT_DISPATCH|VT_BYREF, $Results)); + +=head1 AUTHORS/COPYRIGHT + +This module is part of the Win32::OLE distribution. + +=cut diff --git a/Master/tlpkg/tlperl/lib/auto/Win32/OLE/.packlist b/Master/tlpkg/tlperl/lib/auto/Win32/OLE/.packlist new file mode 100644 index 00000000000..40ef4381e84 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/auto/Win32/OLE/.packlist @@ -0,0 +1,12 @@ +C:\perl\site\lib\OLE.pm +C:\perl\site\lib\Win32\OLE.pm +C:\perl\site\lib\Win32\OLE\Const.pm +C:\perl\site\lib\Win32\OLE\Enum.pm +C:\perl\site\lib\Win32\OLE\Lite.pm +C:\perl\site\lib\Win32\OLE\NEWS.pod +C:\perl\site\lib\Win32\OLE\NLS.pm +C:\perl\site\lib\Win32\OLE\TPJ.pod +C:\perl\site\lib\Win32\OLE\TypeInfo.pm +C:\perl\site\lib\Win32\OLE\Variant.pm +C:\perl\site\lib\auto\Win32\OLE\OLE.bs +C:\perl\site\lib\auto\Win32\OLE\OLE.dll diff --git a/Master/tlpkg/tlperl/lib/auto/Win32/OLE/OLE.bs b/Master/tlpkg/tlperl/lib/auto/Win32/OLE/OLE.bs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Master/tlpkg/tlperl/lib/auto/Win32/OLE/OLE.dll b/Master/tlpkg/tlperl/lib/auto/Win32/OLE/OLE.dll new file mode 100644 index 00000000000..8140134685e Binary files /dev/null and b/Master/tlpkg/tlperl/lib/auto/Win32/OLE/OLE.dll differ diff --git a/Master/tlpkg/tlperl/lib/perllocal.pod b/Master/tlpkg/tlperl/lib/perllocal.pod index 8bc813cfc35..57a67a6b7f0 100644 --- a/Master/tlpkg/tlperl/lib/perllocal.pod +++ b/Master/tlpkg/tlperl/lib/perllocal.pod @@ -482,3 +482,25 @@ C =back +=head2 Tue Mar 5 22:14:06 2013: C L + +=over 4 + +=item * + +C + +=item * + +C + +=item * + +C + +=item * + +C + +=back + -- cgit v1.2.3