import: tcom-3.9
authorPat Thoyts <patthoyts@users.sourceforge.net>
Thu, 29 Jan 2009 22:17:50 +0000 (22:17 +0000)
committerPat Thoyts <patthoyts@users.sourceforge.net>
Thu, 29 Jan 2009 22:17:50 +0000 (22:17 +0000)
47 files changed:
CHANGES
README
doc/docbookx.dtd [deleted file]
doc/tcom.n.html
doc/tcom.n.xml
doc/xslt.tcl
lib/Banking/server.tcl
lib/TclScript/TclScript.dll
lib/TclScript/TclScript.itcl
lib/TclScript/TclScript.tlb
lib/TclScript/unregister.tcl [new file with mode: 0644]
lib/tcom/pkgIndex.tcl
lib/tcom/tcom.dll
lib/tcom/tcom.tcl
lib/tcom/tcominproc.dll
lib/tcom/tcomlocal.exe
samples/chart.tcl
samples/excel.tcl
src/Arguments.cpp
src/ComObject.cpp
src/ComObject.h
src/Extension.cpp
src/Extension.h
src/HandleSupport.cpp
src/HandleSupport.h
src/HashTable.h
src/Makefile
src/Reference.cpp
src/Reference.h
src/TclObject.cpp
src/TclScript.cpp
src/TclScript.dsp
src/TclScript.idl
src/bindCmd.cpp
src/buildNumber.h
src/comsupp.cpp [deleted file]
src/naCmd.cpp
src/nullCmd.cpp
src/objectCmd.cpp
src/refCmd.cpp
src/tcom.dsp
src/variantCmd.cpp [new file with mode: 0644]
src/version.h
tests/array.test [new file with mode: 0644]
tests/eval.test [new file with mode: 0644]
tests/foreach.test
tests/namedarg.test

diff --git a/CHANGES b/CHANGES
index 1ce6379c1b0a8c63fa4a53c22202215695a98acf..6edeffe7f36a239b70e86884e6340f31fe6b5907 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,19 @@
+Version 3.9
+- Fixed defect where eval may trigger premature destruction of handle internal
+  representation.
+- Fixed COM server handling of byref BSTR and VARIANT parameters.
+- Fixed invalid pointer error when Visual Studio automation object returns a
+  VARIANT of type VT_DISPATCH with pointer set to NULL.
+- Fixed incorrect type conversion when passing to SAFEARRAY(BYTE) parameter.
+- Fixed memory corruption in handling of [out] DECIMAL parameters.
+- Fixed Unicode encoding of ::tcom::ref getobject parameter.
+- If an error occurs while executing a ::tcom::bind event handler command 
+  then use the bgerror mechanism to report the error.
+- Added ::tcom::variant command which creates VARIANT values.
+- Added [::tcom::object null] command which returns a token representing a
+  null IUnknown pointer.
+- Added support for two-dimensional SAFEARRAY.
+
 Version 3.8
 - Fixed defect which prevented DISPATCH_PROPERTYPUTREF properties from being
   set.
diff --git a/README b/README
index e013838cdca5d0ff67b70603fef4648cd65b5d7b..6ff0ac0a7a7bd6a5dfe4cb8ab273b39494f30102 100644 (file)
--- a/README
+++ b/README
@@ -14,10 +14,10 @@ directory is C:\Tcl\lib, enter this command at the command prompt:
 
 TCL ACTIVE SCRIPT ENGINE
 
-This distribution includes an Active Script engine that's currently in a
-pre-alpha stage of development.  It implements just enough of the IActiveScript
-and IActiveScriptParse interfaces to enable Internet Explorer and Windows
-Script Host to run simple scripts.  It works with the ActiveTcl binary
-distribution from ActiveState.  To register the script engine (assuming the
-Tcl library directory is C:\Tcl\lib), change the current working directory to
+This distribution includes an experimental implementation of a Tcl Active
+Script engine.  It implements just enough of the IActiveScript and
+IActiveScriptParse interfaces to enable Internet Explorer and Windows Script
+Host to run simple scripts.  It works with the ActiveTcl binary distribution
+from ActiveState.  To register the script engine (assuming the Tcl library
+directory is C:\Tcl\lib), change the current working directory to
 C:\Tcl\lib\TclScript and run the register.tcl script.
diff --git a/doc/docbookx.dtd b/doc/docbookx.dtd
deleted file mode 100644 (file)
index e69de29..0000000
index 6913361358283c0f86b708ab4d8f599bb5b6d6fb..518d7627f35d9eff94accbcf51ee4ba12b75777b 100644 (file)
@@ -20,7 +20,7 @@
  <h2>Synopsis</h2>
   
    <span class="command">package require tcom</span>
-   <var>?<span class="option">3.8</span>?</var>
+   <var>?<span class="option">3.9</span>?</var>
    <br>
    <span class="command">::tcom::ref</span>
    <span class="command">createobject</span>
     </dt>
     <dd>
      <p>This command specifies a Tcl command that will be executed when
-     events are received from an object.  The
-     <var>command</var> will be called with additional
-     arguments: the event name and the event arguments.  By default, the event
-     interface is the default event source interface of the object's class.
-     Use the <var>eventIID</var> parameter to specify the IID
-     of another event interface.</p>
+     events are received from an object.  The <var>command</var>
+     will be called with additional arguments: the event name and the event
+     arguments.  By default, the event interface is the default event source
+     interface of the object's class.  Use the <var>eventIID</var>
+     parameter to specify the IID of another event interface.  If an error
+     occurs while executing the command then the bgerror mechanism is used to
+     report the error.</p>
     </dd>
    
    
index f5c20e47db3bcb7c2dcb19054e2a8586ec5cb4b2..4794bad1af2ac84269ead2b6e91e1e3eb8788300 100644 (file)
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
-<!-- $Id: tcom.n.xml,v 1.63 2002/04/12 23:44:50 cthuang Exp $ -->
+<!-- $Id: tcom.n.xml,v 1.65 2002/10/22 22:07:55 cthuang Exp $ -->
 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "docbookx.dtd">
 <refentry id="tcom">
  <docinfo>
-  <date>$Date: 2002/04/12 23:44:50 $</date>
-  <releaseinfo>$Revision: 1.63 $</releaseinfo>
+  <date>$Date: 2002/10/22 22:07:55 $</date>
+  <releaseinfo>$Revision: 1.65 $</releaseinfo>
  </docinfo>
  <refmeta>
   <refentrytitle>tcom</refentrytitle>
@@ -17,7 +17,7 @@
  <refsynopsisdiv>
   <cmdsynopsis>
    <command>package require tcom</command>
-   <arg><option>3.8</option></arg>
+   <arg><option>3.9</option></arg>
    <sbr/>
    <command>::tcom::ref</command>
    <command>createobject</command>
     </term>
     <listitem>
      <para>This command specifies a Tcl command that will be executed when
-     events are received from an object.  The
-     <parameter>command</parameter> will be called with additional
-     arguments: the event name and the event arguments.  By default, the event
-     interface is the default event source interface of the object's class.
-     Use the <parameter>eventIID</parameter> parameter to specify the IID
-     of another event interface.</para>
+     events are received from an object.  The <parameter>command</parameter>
+     will be called with additional arguments: the event name and the event
+     arguments.  By default, the event interface is the default event source
+     interface of the object's class.  Use the <parameter>eventIID</parameter>
+     parameter to specify the IID of another event interface.  If an error
+     occurs while executing the command then the bgerror mechanism is used to
+     report the error.</para>
     </listitem>
    </varlistentry>
    <varlistentry>
index 4df74fa4108997cc5a7c63c685d829ea7aed0a73..696998555a0c7042247afe4e47bbfa1fe2277bc8 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: xslt.tcl,v 1.1 2002/04/17 22:07:57 cthuang Exp $
+# $Id: xslt.tcl,v 1.2 2002/09/05 22:10:25 cthuang Exp $
 #
 # Run an XML document through an XSLT processor.
 
@@ -14,6 +14,7 @@ set domProgId "Msxml2.DOMDocument"
 set source [::tcom::ref createobject $domProgId]
 $source preserveWhiteSpace 1
 $source validateOnParse 0
+$source resolveExternals 0
 set sourceUrl [lindex $argv 0]
 if {![$source load $sourceUrl]} {
     set parseError [$source parseError]
index 520e669a005271907aa8e88eb136b9201f1db9be..f31894fa26f851f52c5b239c9d13094b883e404b 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: server.tcl,v 1.3 2002/06/29 15:34:52 cthuang Exp $
+# $Id: server.tcl,v 1.4 2003/03/07 00:03:00 cthuang Exp $
 package provide Banking 1.0
 
 package require tcom
@@ -34,7 +34,6 @@ proc bankImpl {method args} {
     switch -- $method {
        CreateAccount {
            set balance 0
-           set name ""
            return [::tcom::object create ::Banking::Account accountImpl]
        }
        
index 81409ac4f4f83e66ee0260c452e1e9a4eb353060..a214bbdf208352a703b0ee5e6bc1a97aa84df932 100644 (file)
Binary files a/lib/TclScript/TclScript.dll and b/lib/TclScript/TclScript.dll differ
index 40c93a3b0bdaf3863bf65b0a747d69bc578c764e..1d6f28776de083d13a365c5acff774155c4c6a2d 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: TclScript.itcl,v 1.2 2002/04/20 06:11:32 cthuang Exp $
+# $Id: TclScript.itcl,v 1.6 2003/11/08 17:38:09 cthuang Exp $
 
 package require Itcl
 namespace import itcl::*
@@ -8,6 +8,7 @@ package require tcom
 
 class Engine {
     # common HRESULT values
+    common S_FALSE     0x00000001
     common E_NOTIMPL   0x80004001
     common E_FAIL      0x80004005
 
@@ -39,7 +40,7 @@ class Engine {
     common SCRIPTITEM_NOCODE           0x400
 
     # true if logging to debug output enabled
-    variable logDebugOn_ 1
+    common logDebugOn_ 1
 
     # SCRIPTSTATE
     variable scriptState_
@@ -51,7 +52,7 @@ class Engine {
     variable slave_
 
     # code to execute
-    variable code_ {}
+    public variable code_ {}
 
     # list of names of items which have global members
     variable globalMemberItems_ {}
@@ -103,12 +104,14 @@ class Engine {
        }
 
        # Fall back to original unknown.
-       eval unknown $args
+       if {![$slave_ issafe]} {
+           $slave_ eval ::TclScriptEngine::oldUnknown $args
+       }
     }
 
     method log {msg} {
        if {$logDebugOn_} {
-           ::TclScriptEngine::outputdebug $msg
+           ::tcom::outputdebug "$this $msg"
        }
     }
 
@@ -144,9 +147,15 @@ class Engine {
     }
 
     method changeScriptState {newState} {
+       log "changeScriptState $scriptStateDesc($scriptState_) $scriptStateDesc($newState)"
+
        set scriptState_ $newState
        if {[info exists scriptSite_]} {
-           $scriptSite_ OnStateChange $newState
+           if {[catch {
+               $scriptSite_ OnStateChange $newState
+           }]} {
+               log $::errorInfo
+           }
        }
 
        switch -- $newState \
@@ -156,7 +165,7 @@ class Engine {
            }
     }
 
-    method sink {sourceName eventName} {
+    method sink {sourceName eventName args} {
        if {[info exists eventCode_($sourceName,$eventName)]} {
            $slave_ eval $eventCode_($sourceName,$eventName)
        }
@@ -171,10 +180,7 @@ class Engine {
                set source [::TclScriptEngine::getnameditem \
                    $scriptSite_ $itemName $subItemName]
 
-               set sinkProcName ::${sourceName}_sink
-               proc $sinkProcName {eventName args} \
-                   "$this sink $sourceName \$eventName"
-               ::tcom::bind $source $sinkProcName
+               ::tcom::bind $source "$this sink $sourceName"
 
                set connectedSources_($sourceName) $source
            }
@@ -183,7 +189,7 @@ class Engine {
 
     method disconnectFromSources {} {
        foreach {sourceName source} [array get connectedSources_] {
-           ::tcom::unbind $source
+           ::tcom::bind $source {}
            unset connectedSources_($sourceName)
        }
     }
@@ -261,12 +267,11 @@ class Engine {
 
        set unknown [::TclScriptEngine::getnameditem $scriptSite_ $name]
 
-       if {($flags & $SCRIPTITEM_GLOBALMEMBERS) != 0} {
+       if {$flags & $SCRIPTITEM_GLOBALMEMBERS} {
            lappend globalMemberItems_ $name
        }
 
-       if {($flags & $SCRIPTITEM_ISVISIBLE) != 0} {
-           log "IActiveScript::AddNamedItem createItemCommand"
+       if {$flags & $SCRIPTITEM_ISVISIBLE} {
            createItemCommand $name $unknown
        }
     }
@@ -279,8 +284,16 @@ class Engine {
     method GetScriptDispatch {itemName ppDispatch} {
        log "IActiveScript::GetScriptDispatch $itemName"
        upvar $ppDispatch pDispatch 
+
+       if {[string length $itemName] == 0} {
+           set pDispatch [::tcom::object create ::TclScript::Dispatch \
+               [namespace current]::$this]
+           return
+       }
+
        set pDispatch 0
-       errorNotImpl
+       set messageText "Not implemented"
+       error $messageText {} [list COM $S_FALSE $messageText]
     }
 
     method GetCurrentScriptThreadID {pScriptThreadId} {
@@ -310,8 +323,13 @@ class Engine {
     method Clone {ppScript} {
        log "IActiveScript::Clone"
        upvar $ppScript pScript
-       set pScript 0
-       errorNotImpl
+
+       set engine [Engine #auto]
+       $engine configure -code_ $code_
+       $engine InitNew
+
+       set pScript [::tcom::object create ::TclScript::Engine \
+           [namespace current]::$engine {delete object}]
     }
 
     # IActiveScriptParse implementation
@@ -323,6 +341,7 @@ class Engine {
            set slave_ [interp create -safe]
        } else {
            set slave_ [interp create]
+           $slave_ eval rename unknown ::TclScriptEngine::oldUnknown
        }
        $slave_ alias unknown $this resolveUnknownCommand
 
index af2393780a5addb48e573eca772d1be0fbe7bd1c..871d6948fe5881441fcda6f68b479efcd2c9e3e1 100644 (file)
Binary files a/lib/TclScript/TclScript.tlb and b/lib/TclScript/TclScript.tlb differ
diff --git a/lib/TclScript/unregister.tcl b/lib/TclScript/unregister.tcl
new file mode 100644 (file)
index 0000000..906114a
--- /dev/null
@@ -0,0 +1,13 @@
+# $Id: unregister.tcl,v 1.1 2003/03/20 00:12:14 cthuang Exp $
+#
+# This script unregisters the Tcl Active Scripting engine.
+
+package require registry
+package require tcom
+
+    set typeLibFile "TclScript.tlb"
+    ::tcom::server unregister $typeLibFile
+
+    registry delete "HKEY_CLASSES_ROOT\\TclScript"
+    registry delete "HKEY_CLASSES_ROOT\\.tcls"
+    registry delete "HKEY_CLASSES_ROOT\\TclScriptFile"
index bbfa7142120b877c705328846e6b5a8c9bf43e3b..aa90f9b76cf8dece99ee177dc2acd944ef71ecbf 100644 (file)
@@ -1,3 +1,3 @@
-# $Id: pkgIndex.tcl,v 1.15 2002/02/26 23:10:47 cthuang Exp $
-package ifneeded tcom 3.8 \
+# $Id: pkgIndex.tcl,v 1.16 2003/04/17 03:17:30 cthuang Exp $
+package ifneeded tcom 3.9 \
 [list load [file join $dir tcom.dll]]\n[list source [file join $dir tcom.tcl]]
index c54312196401c5da058ce644432fc3d6ec2e7312..3c689014ddfd00653020fc68756ed29647402cb1 100644 (file)
Binary files a/lib/tcom/tcom.dll and b/lib/tcom/tcom.dll differ
index 2044e33266960832567dfd2a14567ea21fdd1d7d..58eaab4b4ff5b58c243bb4fe2a2d5173a8632c2d 100644 (file)
@@ -1,6 +1,11 @@
-# $Id: tcom.tcl,v 1.14 2002/03/30 16:24:11 cthuang Exp $
+# $Id: tcom.tcl,v 1.17 2003/04/02 22:46:51 cthuang Exp $
 
 namespace eval ::tcom {
+    # Tear down all event connections to the object.
+    proc unbind {handle} {
+       ::tcom::bind $handle {}
+    }
+
     # Look for the file in the directories in the package load path.
     # Return the full path of the file.
     proc search_auto_path {fileSpec} {
@@ -44,6 +49,7 @@ namespace eval ::tcom {
        set key "HKEY_CLASSES_ROOT\\$verIndependentProgId"
        registry set $key "" "$className Class"
        registry set "$key\\CLSID" "" $clsid
+       registry set "$key\\CurVer" "" $progId
 
        set key "HKEY_CLASSES_ROOT\\CLSID\\$clsid"
        registry set $key "" "$className Class"
@@ -55,7 +61,6 @@ namespace eval ::tcom {
        if {$inproc} {
            set key "HKEY_CLASSES_ROOT\\CLSID\\$clsid\\InprocServer32"
            registry set $key "" $dllPath
-           registry set $key "ThreadingModel" "Apartment"
        }
 
        if {$local} {
index ddedbfe09a9d270954d78f074c6024f948e743a1..519a611acaa08c35c3f9e36d74fe1d3801426287 100644 (file)
Binary files a/lib/tcom/tcominproc.dll and b/lib/tcom/tcominproc.dll differ
index f71826876875e4a554f8baa1f37ec917ad40f354..42df14c8aee3a98b6b9f5aa2ac3eec29334d10f7 100644 (file)
Binary files a/lib/tcom/tcomlocal.exe and b/lib/tcom/tcomlocal.exe differ
index cb34c0916b266a93ec7f77cedacfe494ce98b823..fbfd15f6ee91ae04e0497acdab3101338a5402c7 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: chart.tcl,v 1.1 2001/08/18 00:35:52 cthuang Exp $
+# $Id: chart.tcl,v 1.5 2004/02/26 18:07:38 cthuang Exp $
 #
 # This example controls Excel.  It performs the following steps.
 #       - Start Excel application.
@@ -16,28 +16,16 @@ set workbook [$workbooks Add]
 set worksheets [$workbook Worksheets]
 set worksheet [$worksheets Item [expr 1]]
 
-set cells [$worksheet Cells]
-$cells Item 1 A "North"
-$cells Item 1 B "South"
-$cells Item 1 C "East"
-$cells Item 1 D "West"
-$cells Item 2 A 5.2
-$cells Item 2 B 10.0
-$cells Item 2 C 8.0
-$cells Item 2 D 20.0
+set data [list \
+    [list "North" "South" "East" "West"] \
+    [list 5.2 10.0 8.0 20.0] \
+]
 set sourceRange [$worksheet Range "A1" "D2"]
+$sourceRange Value $data
 
 set charts [$workbook Charts]
 set chart [$charts Add]
-$chart ChartWizard \
-    $sourceRange \
-    [expr -4102] \
-    [expr 7] \
-    [expr 1] \
-    [expr 1] \
-    [expr 0] \
-    0 \
-    "Sales Percentages"
+$chart ChartWizard $sourceRange 5 [::tcom::na] 1 1 0 0 "Sales Percentages"
 
 # Prevent Excel from prompting to save the document on close.
 $workbook Saved 1
index 4bc303175bbd906b88a0d0ae6c489ce525c40ded..b00459e540c0cd8b112ebd7bbb52a30bb9f24b4e 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: excel.tcl,v 1.9 2001/06/30 18:42:58 cthuang Exp $
+# $Id: excel.tcl,v 1.10 2002/09/27 22:11:03 cthuang Exp $
 #
 # This example controls Excel.  It performs the following steps.
 #       - Start Excel application.
@@ -13,6 +13,7 @@ package require tcom
 
 proc dumpInterface {obj} {
     set interface [::tcom::info interface $obj]
+    puts "interface [$interface name]"
 
     set properties [$interface properties]
     foreach property $properties {
index 4ed82a7d9beb56c823a785551928da4f035897db..b92e4a71bfad4e76d7170396e1112664f2be92ee 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: Arguments.cpp,v 1.33 2002/07/09 04:10:08 cthuang Exp $
+// $Id: Arguments.cpp,v 1.35 2003/03/15 01:32:09 cthuang Exp $
 #include "Arguments.h"
 #include "Extension.h"
 #include "TclObject.h"
@@ -45,7 +45,11 @@ TypedArguments::initArgument (
         // For out parameters, set a pointer to where the out value
         // will be stored.
 
-        if (vt == VT_USERDEFINED) {
+        if (vt == VT_INT) {
+            // IDispatch::Invoke returns DISP_E_TYPEMISMATCH on
+            // VT_INT | VT_BYREF parameters.
+            vt = VT_I4;
+        } else if (vt == VT_USERDEFINED) {
             // Assume user defined types derive from IUnknown.
             vt = VT_UNKNOWN;
         }
@@ -57,7 +61,7 @@ TypedArguments::initArgument (
             m_args[argIndex].vt = VT_BYREF | vt;
         }
 
-        if (vt == VT_VARIANT) {
+        if (vt == VT_VARIANT || vt == VT_DECIMAL) {
             // Set a pointer to out variant.
             m_args[argIndex].byref = &m_outValues[argIndex];
         } else {
index e0fc18777e01f004658290e1f22433d0a51be453..beb4e9b350581caa2f35079ce3572bbb873fdf4a 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: ComObject.cpp,v 1.37 2002/05/31 04:03:06 cthuang Exp $
+// $Id: ComObject.cpp,v 1.41 2003/04/04 23:55:04 cthuang Exp $
 #pragma warning(disable: 4786)
 #include "ComObject.h"
 #include <stdexcept>
@@ -16,14 +16,17 @@ static const char setPrefix[] = "_set_";
 ComObject::ComObject (const Class::Interfaces &interfaces,
                       Tcl_Interp *interp,
                       TclObject servant,
-                      TclObject destructor):
+                      TclObject destructor,
+                      bool isSink):
     m_refCount(0),
     m_defaultInterface(*(interfaces.front())),
     m_interp(interp),
     m_servant(servant),
     m_destructor(destructor),
     m_supportErrorInfo(*this),
-    m_pDispatch(0)
+    m_pDispatch(0),
+    m_registeredActiveObject(false),
+    m_isSink(isSink)
 {
 //    Tcl_Preserve(reinterpret_cast<ClientData>(m_interp));
     ComModule::instance().lock();
@@ -86,16 +89,18 @@ ComObject::newInstance (
     const Interface &defaultInterface,
     Tcl_Interp *interp,
     TclObject servant,
-    TclObject destructor)
+    TclObject destructor,
+    bool isSink)
 {
     Class::Interfaces interfaces;
     interfaces.push_back(&defaultInterface);
 
     return new ComObject(
-       interfaces,
-       interp,
-       servant,
-       destructor);
+        interfaces,
+        interp,
+        servant,
+        destructor,
+        isSink);
 }
 
 ComObject *
@@ -105,12 +110,12 @@ ComObject::newInstance (
     TclObject servant,
     TclObject destructor)
 {
-    ComObject *pComObject = new ComObject(
-       interfaces,
-       interp,
-       servant,
-       destructor);
-    return pComObject;
+    return new ComObject(
+        interfaces,
+        interp,
+        servant,
+        destructor,
+        false);
 }
 
 int
@@ -190,9 +195,9 @@ HRESULT
 ComObject::queryInterface (REFIID iid, void **ppvObj)
 {
     if (IsEqualIID(iid, IID_IUnknown)) {
-       *ppvObj = m_pDefaultAdapter;
+        *ppvObj = m_pDefaultAdapter;
         addRef();
-       return S_OK;
+        return S_OK;
     }
 
     if (IsEqualIID(iid, IID_IDispatch)) {
@@ -200,15 +205,15 @@ ComObject::queryInterface (REFIID iid, void **ppvObj)
         if (m_pDispatch == 0) {
             m_pDispatch = new InterfaceAdapter(*this, m_defaultInterface, true);
         }
-       *ppvObj = m_pDispatch;
+        *ppvObj = m_pDispatch;
         addRef();
-       return S_OK;
+        return S_OK;
     }
 
     if (IsEqualIID(iid, IID_ISupportErrorInfo)) {
-       *ppvObj = &m_supportErrorInfo;
+        *ppvObj = &m_supportErrorInfo;
         addRef();
-       return S_OK;
+        return S_OK;
     }
 
     InterfaceAdapter *pAdapter = m_iidToAdapterMap.find(iid);
@@ -220,9 +225,9 @@ ComObject::queryInterface (REFIID iid, void **ppvObj)
     }
 
     if (pAdapter != 0) {
-       *ppvObj = pAdapter;
+        *ppvObj = pAdapter;
         addRef();
-       return S_OK;
+        return S_OK;
     }
 
     *ppvObj = 0;
@@ -241,7 +246,7 @@ ComObject::release ()
 {
     InterlockedDecrement(&m_refCount);
     if (m_refCount == 0) {
-       delete this;
+        delete this;
         return 0;
     }
     return m_refCount;
@@ -447,13 +452,22 @@ ComObject::invoke (InterfaceAdapter *pAdapter,
         // Execute the Tcl script.
         TclObject result;
         int completionCode = eval(script, &result);
-        if (completionCode != TCL_OK) {
-            fillExcepInfo(
-                pExcepInfo,
-                hresultFromErrorCode(),
-                m_servant.c_str(),
-                result.c_str());
-            return DISP_E_EXCEPTION;
+        if (completionCode == TCL_OK) {
+            hresult = S_OK;
+        } else {
+            if (m_isSink) {
+                Tcl_BackgroundError(m_interp);
+            }
+
+            hresult = hresultFromErrorCode();
+            if (FAILED(hresult)) {
+                fillExcepInfo(
+                    pExcepInfo,
+                    hresult,
+                    m_servant.c_str(),
+                    result.c_str());
+                hresult = DISP_E_EXCEPTION;
+            }
         }
 
         // Copy values to out arguments.
@@ -482,8 +496,6 @@ ComObject::invoke (InterfaceAdapter *pAdapter,
             // from methods.
             result.toVariant(pReturnValue, pMethod->type(), m_interp, true);
         }
-
-        hresult = S_OK;
     }
     catch (_com_error &e) {
         fillExcepInfo(pExcepInfo, e.Error(), m_servant.c_str(), 0);
@@ -549,19 +561,29 @@ convertNativeToTclObject (va_list pArg,
         {
 #if TCL_MINOR_VERSION >= 2
             // Uses Unicode function introduced in Tcl 8.2.
-            Tcl_UniChar *pUnicode = va_arg(pArg, Tcl_UniChar *);
+            Tcl_UniChar *pUnicode = byRef ?
+                *va_arg(pArg, Tcl_UniChar **) : va_arg(pArg, Tcl_UniChar *);
             if (pUnicode != 0) {
                 tclObject = Tcl_NewUnicodeObj(pUnicode, -1);
             } else {
                 tclObject = Tcl_NewObj();
             }
 #else
-            _bstr_t str(va_arg(pArg, wchar_t *));
+            wchar_t *pUnicode = byRef ?
+                *va_arg(pArg, wchar_t **) : va_arg(pArg, wchar_t *);
+            _bstr_t str(pUnicode);
             tclObject = Tcl_NewStringObj(str, -1);
 #endif
         }
         break;
 
+    case VT_VARIANT:
+        tclObject = TclObject(
+            byRef ? va_arg(pArg, VARIANT *) : &va_arg(pArg, VARIANT),
+            type,
+            interp);
+        break;
+
     default:
         tclObject = Tcl_NewLongObj(
             byRef ? *va_arg(pArg, int *) : va_arg(pArg, int));
@@ -711,6 +733,10 @@ nextArgument (va_list pArg, const Type &type)
         va_arg(pArg, BSTR);
         break;
 
+    case VT_VARIANT:
+        va_arg(pArg, VARIANT);
+        break;
+
     default:
         va_arg(pArg, int);
     }
@@ -752,10 +778,10 @@ setErrorInfo (const char *source, const char *description)
 void __cdecl
 invokeComObjectFunction (volatile HRESULT hresult,
                          volatile DWORD pArgEnd,
-                        DWORD /*ebp*/,
-                        DWORD funcIndex,
-                        DWORD /*retAddr*/,
-                        InterfaceAdapter *pAdapter,
+                         DWORD /*ebp*/,
+                         DWORD funcIndex,
+                         DWORD /*retAddr*/,
+                         InterfaceAdapter *pAdapter,
                          ...)
 {
     // Get the method description for method being invoked.
@@ -812,7 +838,9 @@ invokeComObjectFunction (volatile HRESULT hresult,
         hresult = S_OK;
     } else {
         hresult = object.hresultFromErrorCode();
-        setErrorInfo(object.m_servant.c_str(), result.c_str());
+        if (FAILED(hresult)) {
+            setErrorInfo(object.m_servant.c_str(), result.c_str());
+        }
     }
 
     // Copy values to out arguments.
index 1d71c0a8f0d485014830bd2e75493a1530d82525..3868e2f8ffbf659ce93588d0bfb71b6e0789df3d 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: ComObject.h,v 1.14 2002/04/13 03:53:56 cthuang Exp $
+// $Id: ComObject.h,v 1.15 2002/10/22 22:07:55 cthuang Exp $
 #ifndef COMOBJECT_H
 #define COMOBJECT_H
 
@@ -67,12 +67,16 @@ class TCOM_API ComObject
     // true if object registered in running object table
     bool m_registeredActiveObject;
 
+    // true if object is an event sink
+    bool m_isSink;
+
     // Do not allow others to create or copy instances of this class.
     ComObject(
         const Class::Interfaces &interfaces,
         Tcl_Interp *interp,
         TclObject servant,
-        TclObject destructor);
+        TclObject destructor,
+        bool isSink);
     ComObject(const ComObject &);       // not implemented
     void operator=(const ComObject &);  // not implemented
 
@@ -91,7 +95,8 @@ public:
         const Interface &defaultInterface,
         Tcl_Interp *interp,
         TclObject servant,
-        TclObject destructor);
+        TclObject destructor,
+        bool isSink = false);
     static ComObject *newInstance(
         const Class::Interfaces &interfaces,
         Tcl_Interp *interp,
index ab53fba87866358240585bba3f73362dc0e46dc0..85d4abe2a7a3863ca356fb2436a580591fee9900 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: Extension.cpp,v 1.1 2002/06/29 15:40:32 cthuang Exp $
+// $Id: Extension.cpp,v 1.3 2003/04/02 22:46:51 cthuang Exp $
 #pragma warning(disable: 4786)
 #include "Extension.h"
 #include "ComModule.h"
@@ -35,6 +35,8 @@ Extension::Extension (Tcl_Interp *interp):
         interp, PACKAGE_NAMESPACE "null", nullCmd, 0, 0);
     Tcl_CreateObjCommand(
         interp, PACKAGE_NAMESPACE "object", objectCmd, this, 0);
+    Tcl_CreateObjCommand(
+        interp, PACKAGE_NAMESPACE "outputdebug", outputdebugCmd, this, 0);
     Tcl_CreateObjCommand(
         interp, PACKAGE_NAMESPACE "property", propertyCmd, 0, 0);
     Tcl_CreateObjCommand(
@@ -46,7 +48,7 @@ Extension::Extension (Tcl_Interp *interp):
     Tcl_CreateObjCommand(
         interp, PACKAGE_NAMESPACE "typeof", typeofCmd, 0, 0);
     Tcl_CreateObjCommand(
-        interp, PACKAGE_NAMESPACE "unbind", unbindCmd, 0, 0);
+        interp, PACKAGE_NAMESPACE "variant", variantCmd, 0, 0);
 
     Tcl_CallWhenDeleted(interp, interpDeleteProc, this);
     Tcl_CreateExitHandler(exitProc, this);
@@ -97,3 +99,30 @@ Extension::typeofCmd (
     Tcl_SetResult(interp, name, TCL_STATIC);
     return TCL_OK;
 }
+
+// This Tcl command outputs a string to the debug stream.
+
+int
+Extension::outputdebugCmd (
+    ClientData,
+    Tcl_Interp *interp,
+    int objc,
+    Tcl_Obj *CONST objv[])
+{
+    if (objc != 2) {
+       Tcl_WrongNumArgs(interp, 1, objv, "message");
+       return TCL_ERROR;
+    }
+
+    Tcl_Obj *pMessage = objv[1];
+    Tcl_Obj *pWithNewLine =
+        Tcl_IsShared(pMessage) ? Tcl_DuplicateObj(pMessage) : pMessage;
+
+    Tcl_AppendToObj(pWithNewLine, "\n", 1);
+    OutputDebugString(Tcl_GetStringFromObj(pWithNewLine, 0));
+
+    if (Tcl_IsShared(pMessage)) {
+        Tcl_DecrRefCount(pWithNewLine);
+    }
+    return TCL_OK;
+}
index de47b6c6c08649e538f9526dcf1d2b5f7ae2cdae..7eb71165d36cbd50fb02fa6c5a57d90f9e025a39 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: Extension.h,v 1.1 2002/06/29 15:40:32 cthuang Exp $
+// $Id: Extension.h,v 1.5 2003/04/02 22:46:51 cthuang Exp $
 #ifndef EXTENSION_H
 #define EXTENSION_H
 
@@ -47,12 +47,13 @@ class TCOM_API Extension
     static int naCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
     static int nullCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
     static int objectCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
+    static int outputdebugCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
     static int propertyCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
     static int refCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
     static int shortPathNameCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
     static int typelibCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
     static int typeofCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
-    static int unbindCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
+    static int variantCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []);
 
     // not implemented
     Extension(const Extension &);
@@ -84,10 +85,17 @@ public:
     static Tcl_ObjType naType;
     static Tcl_ObjType nullType;
     static Tcl_ObjType unknownPointerType;
+    static Tcl_ObjType variantType;
 
     // Create a Tcl value representing a missing optional argument.
     static Tcl_Obj *newNaObj();
 
+    // Create a Tcl value representing a SQL-style null.
+    static Tcl_Obj *newNullObj();
+
+    // Create a Tcl value representing a VARIANT.
+    static Tcl_Obj *newVariantObj(_variant_t *pVar);
+
     // Set the Tcl result to a description of the COM error and return TCL_ERROR.
     static int setComErrorResult(
         Tcl_Interp *interp, _com_error &e, const char *file, int line);
index 2795dcfe422824a96a94e1edb2bd86f869455d31..d4d75dff6c15c2fb9332b73c16e3a7cf479bd4e1 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: HandleSupport.cpp,v 1.15 2002/05/31 04:03:06 cthuang Exp $
+// $Id: HandleSupport.cpp,v 1.19 2003/07/17 22:33:31 cthuang Exp $
 #include "HandleSupport.h"
 #include <sstream>
 #include "ThreadLocalStorage.h"
@@ -20,13 +20,16 @@ InternalRep::InternalRep (
         objClientData,
         0);
 
-    HandleNameToRepMap::instance(interp)->insert(handleName.c_str(), this);
+    m_pNameEntry = HandleNameToRepMap::instance(interp)->insert(
+        handleName.c_str(), this);
 }
 
 InternalRep::~InternalRep ()
 {
-    HandleNameToRepMap::instance(m_interp)->erase(name().c_str());
-    Tcl_DeleteCommandFromToken(m_interp, m_command);
+    HandleNameToRepMap::erase(m_pNameEntry);
+    if (!Tcl_InterpDeleted(m_interp)) {
+        Tcl_DeleteCommandFromToken(m_interp, m_command);
+    }
 }
 
 std::string
@@ -58,7 +61,7 @@ InternalRep::decrHandleCount ()
 
 class ObjToRepMap
 {
-    Tcl_HashTable m_hashTable;
+    Tcl_HashTable m_objMap;
 
     static ThreadLocalStorage<ObjToRepMap> ms_tls;
 
@@ -89,7 +92,7 @@ ObjToRepMap::exitProc (ClientData clientData)
 
 ObjToRepMap::ObjToRepMap ()
 {
-    Tcl_InitHashTable(&m_hashTable, TCL_ONE_WORD_KEYS);
+    Tcl_InitHashTable(&m_objMap, TCL_ONE_WORD_KEYS);
 
 #ifdef TCL_THREADS
     Tcl_CreateThreadExitHandler(exitProc, this);
@@ -100,7 +103,7 @@ ObjToRepMap::ObjToRepMap ()
 
 ObjToRepMap::~ObjToRepMap ()
 {
-    Tcl_DeleteHashTable(&m_hashTable);
+    Tcl_DeleteHashTable(&m_objMap);
 }
 
 ObjToRepMap &
@@ -114,7 +117,7 @@ ObjToRepMap::insert (Tcl_Obj *pObj, InternalRep *pRep)
 {
     int isNew;
     Tcl_HashEntry *pEntry = Tcl_CreateHashEntry(
-        &m_hashTable, reinterpret_cast<char *>(pObj), &isNew);
+        &m_objMap, reinterpret_cast<char *>(pObj), &isNew);
     Tcl_SetHashValue(pEntry, pRep);
 }
 
@@ -122,7 +125,7 @@ InternalRep *
 ObjToRepMap::find (Tcl_Obj *pObj)
 {
     Tcl_HashEntry *pEntry = Tcl_FindHashEntry(
-        &m_hashTable, reinterpret_cast<char *>(pObj));
+        &m_objMap, reinterpret_cast<char *>(pObj));
     if (pEntry == 0) {
         return 0;
     }
@@ -133,7 +136,7 @@ void
 ObjToRepMap::erase (Tcl_Obj *pObj)
 {
     Tcl_HashEntry *pEntry = Tcl_FindHashEntry(
-        &m_hashTable, reinterpret_cast<char *>(pObj));
+        &m_objMap, reinterpret_cast<char *>(pObj));
     if (pEntry != 0) {
         Tcl_DeleteHashEntry(pEntry);
     }
@@ -176,8 +179,9 @@ CmdNameType::freeInternalRep (Tcl_Obj *pObj)
 {
     if (pObj->refCount == 0) {
         InternalRep *pRep = ObjToRepMap::instance().find(pObj);
-        if (pRep != 0 && pRep->decrHandleCount() == 0) {
+        if (pRep != 0) {
             ObjToRepMap::instance().erase(pObj);
+            pRep->decrHandleCount();
         }
     }
 
@@ -236,6 +240,8 @@ static char ASSOC_KEY[] = "tcomHandles";
 HandleNameToRepMap::HandleNameToRepMap (Tcl_Interp *interp):
     m_interp(interp)
 {
+    Tcl_InitHashTable(&m_handleMap, TCL_STRING_KEYS);
+
     Tcl_SetAssocData(interp, ASSOC_KEY, deleteInterpProc, this);
     Tcl_CreateExitHandler(exitProc, this);
 }
@@ -243,7 +249,15 @@ HandleNameToRepMap::HandleNameToRepMap (Tcl_Interp *interp):
 HandleNameToRepMap::~HandleNameToRepMap ()
 {
     // Clean up any left over objects.
-    clear();
+    Tcl_HashSearch search;
+    Tcl_HashEntry *pEntry = Tcl_FirstHashEntry(&m_handleMap, &search);
+    while (pEntry != 0) {
+        Tcl_HashEntry *pNext = Tcl_NextHashEntry(&search);
+        delete static_cast<InternalRep *>(Tcl_GetHashValue(pEntry));
+        pEntry = pNext;
+    }
+
+    Tcl_DeleteHashTable(&m_handleMap);
 }
 
 void
@@ -268,9 +282,30 @@ HandleNameToRepMap::instance (Tcl_Interp *interp)
         Tcl_GetAssocData(interp, ASSOC_KEY, 0));
 }
 
+Tcl_HashEntry *
+HandleNameToRepMap::insert (const char *handleStr, InternalRep *pRep)
+{
+    int isNew;
+    Tcl_HashEntry *pEntry = Tcl_CreateHashEntry(
+        &m_handleMap, const_cast<char *>(handleStr), &isNew);
+    Tcl_SetHashValue(pEntry, static_cast<ClientData>(pRep));
+    return pEntry;
+}
+
+InternalRep *
+HandleNameToRepMap::find (Tcl_Obj *pHandle) const
+{
+    char *key = Tcl_GetStringFromObj(pHandle, 0);
+    Tcl_HashEntry *pEntry = Tcl_FindHashEntry(
+        const_cast<Tcl_HashTable *>(&m_handleMap), key);
+    if (pEntry == 0) {
+        return 0;
+    }
+    return static_cast<InternalRep *>(Tcl_GetHashValue(pEntry));
+}
+
 void
-HandleNameToRepMap::clear ()
+HandleNameToRepMap::erase (Tcl_HashEntry *pNameEntry)
 {
-    m_map.forEach(Delete());
-    m_map.clear();
+    Tcl_DeleteHashEntry(pNameEntry);
 }
index 51ad6c0d7c2da043c61154cdf52d4829ce49d1ae..d96a1fb2c1f90b01dcf581d0e9bfdf22c0d8acd2 100644 (file)
@@ -1,11 +1,10 @@
-// $Id: HandleSupport.h,v 1.27 2002/04/17 21:43:07 cthuang Exp $
+// $Id: HandleSupport.h,v 1.29 2003/07/17 22:33:31 cthuang Exp $
 #ifndef HANDLESUPPORT_H
 #define HANDLESUPPORT_H
 
 #include <tcl.h>
 #include <string>
 #include "tcomApi.h"
-#include "HashTable.h"
 #include "Singleton.h"
 
 // This class represents an association from a handle to an application object.
@@ -17,6 +16,7 @@ protected:
     Tcl_Interp *m_interp;
     Tcl_Command m_command;
     ClientData m_clientData;
+    Tcl_HashEntry *m_pNameEntry;
 
     // number of Tcl_Obj instances that are handles to this object
     long m_handleCount;
@@ -94,16 +94,16 @@ public:
     Tcl_Obj *newObj(Tcl_Interp *interp, InternalRep *pRep);
 };
 
-// Maps handle name to internal representation.  There's an instance of this
-// class associated with each Tcl interpreter that loads the extension.
+// Maps string representation of handle to internal representation.  There's an
+// instance of this class associated with each Tcl interpreter that loads the
+// extension.
 
 class TCOM_API HandleNameToRepMap
 {
     Tcl_Interp *m_interp;
 
     // handle string representation to internal representation map
-    typedef StringHashTable<InternalRep *> Map;
-    Map m_map;
+    Tcl_HashTable m_handleMap;
 
     static void deleteInterpProc(ClientData clientData, Tcl_Interp *interp);
     static void exitProc(ClientData clientData);
@@ -117,19 +117,13 @@ public:
     static HandleNameToRepMap *instance(Tcl_Interp *interp);
     
     // Insert handle to object mapping.
-    void insert (const char *handleStr, InternalRep *pRep)
-    { m_map.insert(handleStr, pRep); }
+    Tcl_HashEntry *insert(const char *handleStr, InternalRep *pRep);
 
     // Get the object represented by the handle.
-    InternalRep *find (Tcl_Obj *pHandle) const
-    { return m_map.find(Tcl_GetStringFromObj(pHandle, 0)); }
+    InternalRep *find(Tcl_Obj *pHandle) const;
 
     // Remove handle to object mapping.
-    void erase (const char *handleStr)
-    { m_map.erase(handleStr); }
-
-    // Clean all handles.
-    void clear();
+    static void erase(Tcl_HashEntry *pNameEntry);
 };
 
 // This class provides functions to map handles to objects of a specific
@@ -150,10 +144,6 @@ public:
     // ownership of the application object and is responsible for deleting it.
     Tcl_Obj *newObj(Tcl_Interp *interp, AppType *pAppObject);
 
-    // Get count of matching elements.
-    size_t count (Tcl_Interp *interp, Tcl_Obj *pHandle) const
-    { return HandleNameToRepMap::instance(interp)->count(pHandle); }
-
     // Get the application object represented by the handle.  If the handle
     // is invalid, return 0.
     AppType *find(Tcl_Interp *interp, Tcl_Obj *pHandle) const;
index 8b1d3d3e47093b8eb9b836874001d62e89af2553..120b02906e8dcab8dbc89276489ad5c2ba30c0df 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: HashTable.h,v 1.21 2002/04/13 03:53:56 cthuang Exp $
+// $Id: HashTable.h,v 1.22 2003/07/17 22:33:31 cthuang Exp $
 #ifndef HASHTABLE_H
 #define HASHTABLE_H
 
@@ -118,6 +118,7 @@ HashTable<K,D>::erase (const K &key)
     }
 }
 
+#if 0
 // This class wraps a Tcl hash table that uses null-terminated strings as keys.
 // The mapped type is assumed to be a pointer type.
 
@@ -172,5 +173,6 @@ StringHashTable<D>::erase (const char *key)
         Tcl_DeleteHashEntry(pEntry);
     }
 }
+#endif
 
 #endif
index 9ce33e08196027c2b7dcaef5aa34e177ebaaadb3..9c9c30960605c487909fefcaace7982296632b9b 100644 (file)
@@ -1,21 +1,27 @@
-# $Id: Makefile,v 1.10 2002/05/31 04:03:06 cthuang Exp $
+# $Id: Makefile,v 1.12 2003/07/24 22:46:35 cthuang Exp $
 
 debug:
        tclsh &&|
 set libDir [file join [info library] "../tcom"]
+file copy -force ../lib/tcom/pkgIndex.tcl $libDir
+file copy -force ../lib/tcom/tcom.tcl $libDir
 file copy -force Debug/tcom.dll $libDir
 file copy -force dllserver_Debug/tcominproc.dll $libDir
 file copy -force exeserver_Debug/tcomlocal.exe $libDir
 set libDir [file join [info library] "../TclScript"]
 file copy -force TclScript_Debug/TclScript.dll $libDir
+file copy -force TclScript_Debug/TclScript.tlb $libDir
 |
 
 release:
        tclsh &&|
 set libDir [file join [info library] "../tcom"]
+file copy -force ../lib/tcom/pkgIndex.tcl $libDir
+file copy -force ../lib/tcom/tcom.tcl $libDir
 file copy -force Release/tcom.dll $libDir
 file copy -force dllserver_Release/tcominproc.dll $libDir
 file copy -force exeserver_Release/tcomlocal.exe $libDir
 set libDir [file join [info library] "../TclScript"]
 file copy -force TclScript_Release/TclScript.dll $libDir
+file copy -force TclScript_Release/TclScript.tlb $libDir
 |
index 49e9a7929a90b30aaca6a2e0f76ccf759b42fdba..9a7f44835c1de5045caae45bdce31f1072ebb3b5 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: Reference.cpp,v 1.69 2002/06/28 00:53:46 cthuang Exp $
+// $Id: Reference.cpp,v 1.73 2003/11/06 15:29:01 cthuang Exp $
 #pragma warning(disable: 4786)
 #include <string.h>
 #include "ComObject.h"
@@ -35,7 +35,8 @@ Reference::Connection::Connection (Tcl_Interp *interp,
         eventInterfaceDesc,
         interp,
         servant,
-        "");
+        "",
+        true);
 
     // Connect to connection point.
     hr = m_pConnectionPoint->Advise(pComObject->unknown(), &m_adviseCookie);
@@ -159,6 +160,21 @@ Reference::operator== (const Reference &rhs) const
     return result;
 }
 
+static void
+throwDispatchException (EXCEPINFO &excepInfo)
+{
+    // Clean up exception information strings.
+    _bstr_t source(excepInfo.bstrSource, false);
+    _bstr_t description(excepInfo.bstrDescription, false);
+    _bstr_t helpFile(excepInfo.bstrHelpFile, false);
+
+    HRESULT hr = excepInfo.scode;
+    if (hr == 0) {
+        hr = _com_error::WCodeToHRESULT(excepInfo.wCode);
+    }
+    throw DispatchException(hr, description);
+}
+
 HRESULT
 Reference::invokeDispatch (
     MEMBERID memberid,
@@ -214,16 +230,7 @@ Reference::invokeDispatch (
         &argErr);
 
     if (hr == DISP_E_EXCEPTION) {
-        // Clean up exception information strings.
-        _bstr_t source(excepInfo.bstrSource, false);
-        _bstr_t description(excepInfo.bstrDescription, false);
-        _bstr_t helpFile(excepInfo.bstrHelpFile, false);
-
-        hr = excepInfo.scode;
-        if (hr == 0) {
-            hr = _com_error::WCodeToHRESULT(excepInfo.wCode);
-        }
-        throw DispatchException(hr, description);
+        throwDispatchException(excepInfo);
     }
 
     return hr;
@@ -254,6 +261,10 @@ Reference::invoke (MEMBERID memberid,
         if (SUCCEEDED(hr)) {
             return hr;
         }
+
+        if (hr == DISP_E_EXCEPTION) {
+            throwDispatchException(excepInfo);
+        }
     }
 
     return invokeDispatch(memberid, dispatchFlags, arguments, pResult);
@@ -518,11 +529,11 @@ Reference::getActiveObject (const char *progId)
 }
 
 Reference *
-Reference::getObject (const char *displayName)
+Reference::getObject (const wchar_t *displayName)
 {
     IUnknown *pUnknown;
     HRESULT hr = CoGetObject(
-        _bstr_t(displayName),
+        displayName,
         NULL,
         IID_IUnknown,
         reinterpret_cast<void **>(&pUnknown));
index 5c423d5ea4766b229a3c42a959d1177178f6c19d..fc4693111631a52cd0028ffeaa6e0a1f3646f833 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: Reference.h,v 1.41 2002/06/12 02:14:08 cthuang Exp $
+// $Id: Reference.h,v 1.42 2003/11/06 15:29:01 cthuang Exp $
 #ifndef REFERENCE_H
 #define REFERENCE_H
 
@@ -132,7 +132,7 @@ public:
     static Reference *getActiveObject(const char *progId);
 
     // Get an object using CoGetObject and construct a reference.
-    static Reference *getObject(const char *displayName);
+    static Reference *getObject(const wchar_t *displayName);
 
     // Get raw interface pointer.
     IUnknown *unknown () const
index dc164f79ba82e660cd8c48821a8d23aefed0d773..8c24d8a611f41393d37e894e1085900302ba2142 100644 (file)
@@ -1,5 +1,6 @@
-// $Id: TclObject.cpp,v 1.29 2002/05/31 04:03:06 cthuang Exp $
+// $Id: TclObject.cpp,v 1.35 2003/05/12 23:30:43 cthuang Exp $
 #include "TclObject.h"
+#include <vector>
 #ifdef WIN32
 #include "Extension.h"
 #include "Reference.h"
@@ -152,112 +153,161 @@ TclObject::lappend (Tcl_Obj *pElement)
 }
 
 #ifdef WIN32
+// Convert SAFEARRAY to a Tcl value.
 
-TclObject::TclObject (VARIANT *pSrc, const Type &type, Tcl_Interp *interp)
+static Tcl_Obj *
+convertFromSafeArray (
+    SAFEARRAY *psa,
+    VARTYPE vt,
+    unsigned dim,
+    long *pIndices,
+    const Type &type,
+    Tcl_Interp *interp)
 {
     HRESULT hr;
 
-    if (V_VT(pSrc) & VT_ARRAY) {
-        // We can handle only one-dimensional arrays.
-        SAFEARRAY *psa = V_ARRAY(pSrc);
-        if (SafeArrayGetDim(psa) != 1) {
-            _com_issue_error(E_INVALIDARG);
+    // Get index range.
+    long lowerBound;
+    hr = SafeArrayGetLBound(psa, dim, &lowerBound);
+    if (FAILED(hr)) {
+        _com_issue_error(hr);
+    }
+
+    long upperBound;
+    hr = SafeArrayGetUBound(psa, dim, &upperBound);
+    if (FAILED(hr)) {
+        _com_issue_error(hr);
+    }
+
+    Tcl_Obj *pResult;
+    if (dim < SafeArrayGetDim(psa)) {
+        // Create list of list for multi-dimensional array.
+        pResult = Tcl_NewListObj(0, 0);
+        for (long i = lowerBound; i <= upperBound; ++i) {
+            pIndices[dim - 1] = i;
+            Tcl_Obj *pElement =
+                convertFromSafeArray(psa, vt, dim + 1, pIndices, type, interp);
+            Tcl_ListObjAppendElement(interp, pResult, pElement);
         }
+        return pResult;
+    }
 
-        // Get index range.
-        long lowerBound;
-        hr = SafeArrayGetLBound(psa, 1, &lowerBound);
+    if (vt == VT_UI1 && SafeArrayGetDim(psa) == 1) {
+        unsigned char *pData;
+        hr = SafeArrayAccessData(psa, reinterpret_cast<void **>(&pData));
         if (FAILED(hr)) {
             _com_issue_error(hr);
         }
 
-        long upperBound;
-        hr = SafeArrayGetUBound(psa, 1, &upperBound);
+        long length = upperBound - lowerBound + 1;
+        pResult =
+#if TCL_MINOR_VERSION >= 1
+            // Convert array of bytes to Tcl byte array.
+            Tcl_NewByteArrayObj(pData, length);
+#else
+            // Convert array of bytes to Tcl string.
+            Tcl_NewStringObj(reinterpret_cast<char *>(pData), length);
+#endif
+
+        hr = SafeArrayUnaccessData(psa);
         if (FAILED(hr)) {
             _com_issue_error(hr);
         }
 
-        // Get element type.
-        VARTYPE vt = V_VT(pSrc) & VT_TYPEMASK;
+    } else {
+        // Create list of Tcl values.
+        pResult = Tcl_NewListObj(0, 0);
+        for (long i = lowerBound; i <= upperBound; ++i) {
+            _variant_t elementVar;
+
+            pIndices[dim - 1] = i;
+            if (vt == VT_VARIANT) {
+                hr = SafeArrayGetElement(psa, pIndices, &elementVar);
+            } else {
+                // I hope the element can be contained in a VARIANT.
+                V_VT(&elementVar) = vt;
+                hr = SafeArrayGetElement(psa, pIndices, &elementVar.punkVal);
+            }
+            if (FAILED(hr)) {
+                _com_issue_error(hr);
+            }
 
-        switch (vt) {
-        case VT_UNKNOWN:
-        case VT_DISPATCH:
-            // Convert array of IUnknown to Tcl list of interface pointer
-            // handles.
-            {
-                IUnknown **pData;
-                hr = SafeArrayAccessData(
-                    psa, reinterpret_cast<void **>(&pData));
-                if (FAILED(hr)) {
-                    _com_issue_error(hr);
-                }
+            TclObject element(&elementVar, type, interp);
+            Tcl_ListObjAppendElement(interp, pResult, element);
+        }
+    }
 
-                m_pObj = Tcl_NewListObj(0, 0);
-                for (long i = lowerBound; i <= upperBound; ++i) {
-                    Tcl_Obj *pElement =
-                        Extension::referenceHandles.newObj(
-                            interp, Reference::newReference(pData[i]));
-                    Tcl_ListObjAppendElement(interp, m_pObj, pElement);
-                }
+    return pResult;
+}
 
-                hr = SafeArrayUnaccessData(psa);
-                if (FAILED(hr)) {
-                    _com_issue_error(hr);
-                }
-            }
-            break;
+// Fill SAFEARRAY from Tcl list.
 
-        case VT_UI1:
-            {
-                unsigned char *pData;
-                hr = SafeArrayAccessData(
-                    psa, reinterpret_cast<void **>(&pData));
-                if (FAILED(hr)) {
-                    _com_issue_error(hr);
-                }
+static void
+fillSafeArray (
+    Tcl_Obj *pList,
+    SAFEARRAY *psa,
+    unsigned dim,
+    long *pIndices,
+    Tcl_Interp *interp,
+    bool addRef)
+{
+    HRESULT hr;
 
-                long length = upperBound - lowerBound + 1;
-                m_pObj =
-#if TCL_MINOR_VERSION >= 1
-                    // Convert array of bytes to Tcl byte array.
-                    Tcl_NewByteArrayObj(pData, length);
-#else
-                    // Convert array of bytes to Tcl string.
-                    Tcl_NewStringObj(reinterpret_cast<char *>(pData), length);
-#endif
+    // Get index range.
+    long lowerBound;
+    hr = SafeArrayGetLBound(psa, dim, &lowerBound);
+    if (FAILED(hr)) {
+        _com_issue_error(hr);
+    }
 
-                hr = SafeArrayUnaccessData(psa);
-                if (FAILED(hr)) {
-                    _com_issue_error(hr);
-                }
-            }
-            break;
+    long upperBound;
+    hr = SafeArrayGetUBound(psa, dim, &upperBound);
+    if (FAILED(hr)) {
+        _com_issue_error(hr);
+    }
 
-        default:
-            // Convert array of other types to Tcl list of objects.
-            {
-                m_pObj = Tcl_NewListObj(0, 0);
-                for (long i = lowerBound; i <= upperBound; ++i) {
-                    _variant_t elementVar;
-
-                    if (vt == VT_VARIANT) {
-                        hr = SafeArrayGetElement(psa, &i, &elementVar);
-                    } else {
-                        // I hope the element can be contained in a VARIANT.
-                        V_VT(&elementVar) = vt;
-                        hr = SafeArrayGetElement(
-                            psa, &i, &elementVar.punkVal);
-                    }
-                    if (FAILED(hr)) {
-                        _com_issue_error(hr);
-                    }
+    int numElements;
+    Tcl_Obj **pElements;
+    if (Tcl_ListObjGetElements(interp, pList, &numElements, &pElements)
+        != TCL_OK) {
+        _com_issue_error(E_INVALIDARG);
+    }
 
-                    TclObject element(&elementVar, type, interp);
-                    Tcl_ListObjAppendElement(interp, m_pObj, element);
-                }
+    unsigned dim1 = dim - 1;
+    if (dim < SafeArrayGetDim(psa)) {
+        // Create list of list for multi-dimensional array.
+        for (int i = 0; i < numElements; ++i) {
+            pIndices[dim1] = i;
+            fillSafeArray(pElements[i], psa, dim + 1, pIndices, interp, addRef);
+        }
+
+    } else {
+        for (int i = 0; i < numElements; ++i) {
+            TclObject element(pElements[i]); 
+            _variant_t elementVar;
+            element.toVariant(&elementVar, Type::variant(), interp, addRef);
+
+            pIndices[dim1] = i;
+            hr = SafeArrayPutElement(psa, pIndices, &elementVar);
+            if (FAILED(hr)) {
+                _com_issue_error(hr);
             }
         }
+    }
+}
+
+TclObject::TclObject (VARIANT *pSrc, const Type &type, Tcl_Interp *interp)
+{
+    if (V_VT(pSrc) & VT_ARRAY) {
+        SAFEARRAY *psa = V_ARRAY(pSrc);
+        VARTYPE vt = V_VT(pSrc) & VT_TYPEMASK;
+        unsigned numDimensions = SafeArrayGetDim(psa);
+        std::vector<long> indices(numDimensions);
+        m_pObj = convertFromSafeArray(
+            psa, vt, 1, &indices[0], type, interp);
+
+    } else if (vtMissing == pSrc) {
+        m_pObj = Extension::newNaObj();
 
     } else {
         switch (V_VT(pSrc)) {
@@ -292,7 +342,9 @@ TclObject::TclObject (VARIANT *pSrc, const Type &type, Tcl_Interp *interp)
             break;
 
         case VT_DISPATCH:
-            {
+            if (V_DISPATCH(pSrc) == 0) {
+                m_pObj = Tcl_NewObj();
+            } else {
                 const Interface *pInterface =
                     InterfaceManager::instance().find(type.iid());
                 m_pObj = Extension::referenceHandles.newObj(
@@ -302,7 +354,9 @@ TclObject::TclObject (VARIANT *pSrc, const Type &type, Tcl_Interp *interp)
             break;
 
         case VT_UNKNOWN:
-            {
+            if (V_UNKNOWN(pSrc) == 0) {
+                m_pObj = Tcl_NewObj();
+            } else {
                 const Interface *pInterface =
                     InterfaceManager::instance().find(type.iid());
                 m_pObj = Extension::referenceHandles.newObj(
@@ -312,7 +366,7 @@ TclObject::TclObject (VARIANT *pSrc, const Type &type, Tcl_Interp *interp)
             break;
 
         case VT_NULL:
-            m_pObj = Tcl_NewObj();
+            m_pObj = Extension::newNullObj();
             break;
 
         case VT_LPSTR:
@@ -366,6 +420,39 @@ TclObject::getBSTR () const
 #endif
 }
 
+#if TCL_MINOR_VERSION >= 1
+// Convert Tcl byte array to SAFEARRAY of bytes.
+
+static SAFEARRAY *
+newByteSafeArray (Tcl_Obj *pObj)
+{
+    int length;
+    unsigned char *pSrc = Tcl_GetByteArrayFromObj(pObj, &length);
+
+    SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, length);
+    if (psa == 0) {
+        _com_issue_error(E_OUTOFMEMORY);
+    }
+
+    unsigned char *pDest;
+    HRESULT hr;
+    hr = SafeArrayAccessData(
+        psa, reinterpret_cast<void **>(&pDest));
+    if (FAILED(hr)) {
+        _com_issue_error(hr);
+    }
+
+    memcpy(pDest, pSrc, length);
+
+    hr = SafeArrayUnaccessData(psa);
+    if (FAILED(hr)) {
+        _com_issue_error(hr);
+    }
+
+    return psa;
+}
+#endif
+
 void
 TclObject::toVariant (VARIANT *pDest,
                       const Type &type,
@@ -397,7 +484,7 @@ TclObject::toVariant (VARIANT *pDest,
         // Convert to interface pointer.
         IUnknown *pUnknown = static_cast<IUnknown *>(
             m_pObj->internalRep.otherValuePtr);
-        if (addRef) {
+        if (addRef && pUnknown != 0) {
             // Must increment reference count of interface pointers returned
             // from methods.
             pUnknown->AddRef();
@@ -406,66 +493,71 @@ TclObject::toVariant (VARIANT *pDest,
         V_UNKNOWN(pDest) = pUnknown;
 
     } else if (vt == VT_SAFEARRAY) {
-        // Convert Tcl list to SAFEARRAY.
-        int numElements;
-        Tcl_Obj **pElements;
-        if (Tcl_ListObjGetElements(interp, m_pObj, &numElements, &pElements)
-          != TCL_OK) {
-            _com_issue_error(E_INVALIDARG);
-        }
-
+        SAFEARRAY *psa;
         const Type &elementType = type.elementType();
-        SAFEARRAY *psa =
-            SafeArrayCreateVector(elementType.vartype(), 0, numElements);
-        if (psa == 0) {
-            _com_issue_error(E_OUTOFMEMORY);
-        }
 
-        void *pData;
-        HRESULT hr;
-        hr = SafeArrayAccessData(psa, &pData);
-        if (FAILED(hr)) {
-            _com_issue_error(hr);
-        }
+        if (elementType.vartype() == VT_UI1) {
+            psa = newByteSafeArray(m_pObj);
+        } else {
+            // Convert Tcl list to SAFEARRAY.
+            int numElements;
+            Tcl_Obj **pElements;
+            if (Tcl_ListObjGetElements(interp, m_pObj, &numElements, &pElements)
+              != TCL_OK) {
+                _com_issue_error(E_INVALIDARG);
+            }
 
-        for (int i = 0; i < numElements; ++i) {
-            TclObject value(pElements[i]);
-
-            switch (elementType.vartype()) {
-            case VT_BOOL:
-                static_cast<VARIANT_BOOL *>(pData)[i] =
-                    value.getBool() ? VARIANT_TRUE : VARIANT_FALSE;
-                break;
-
-            case VT_R4:
-                static_cast<float *>(pData)[i] =
-                    static_cast<float>(value.getDouble());
-                break;
-
-            case VT_R8:
-                static_cast<double *>(pData)[i] = value.getDouble();
-                break;
-
-            case VT_BSTR:
-                static_cast<BSTR *>(pData)[i] = value.getBSTR();
-                break;
-
-            case VT_VARIANT:
-                {
-                    VARIANT *pDest = static_cast<VARIANT *>(pData) + i;
-                    VariantInit(pDest);
-                    value.toVariant(pDest, elementType, interp);
-                }
-                break;
+            psa = SafeArrayCreateVector(elementType.vartype(), 0, numElements);
+            if (psa == 0) {
+                _com_issue_error(E_OUTOFMEMORY);
+            }
 
-            default:
-                static_cast<int *>(pData)[i] = value.getLong();
+            void *pData;
+            HRESULT hr;
+            hr = SafeArrayAccessData(psa, &pData);
+            if (FAILED(hr)) {
+                _com_issue_error(hr);
             }
-        }
 
-        hr = SafeArrayUnaccessData(psa);
-        if (FAILED(hr)) {
-            _com_issue_error(hr);
+            for (int i = 0; i < numElements; ++i) {
+                TclObject value(pElements[i]);
+
+                switch (elementType.vartype()) {
+                case VT_BOOL:
+                    static_cast<VARIANT_BOOL *>(pData)[i] =
+                        value.getBool() ? VARIANT_TRUE : VARIANT_FALSE;
+                    break;
+
+                case VT_R4:
+                    static_cast<float *>(pData)[i] =
+                        static_cast<float>(value.getDouble());
+                    break;
+
+                case VT_R8:
+                    static_cast<double *>(pData)[i] = value.getDouble();
+                    break;
+
+                case VT_BSTR:
+                    static_cast<BSTR *>(pData)[i] = value.getBSTR();
+                    break;
+
+                case VT_VARIANT:
+                    {
+                        VARIANT *pDest = static_cast<VARIANT *>(pData) + i;
+                        VariantInit(pDest);
+                        value.toVariant(pDest, elementType, interp);
+                    }
+                    break;
+
+                default:
+                    static_cast<int *>(pData)[i] = value.getLong();
+                }
+            }
+
+            hr = SafeArrayUnaccessData(psa);
+            if (FAILED(hr)) {
+                _com_issue_error(hr);
+            }
         }
 
         V_VT(pDest) = VT_ARRAY | elementType.vartype();
@@ -480,60 +572,41 @@ TclObject::toVariant (VARIANT *pDest,
             _com_issue_error(E_INVALIDARG);
         }
 
-        SAFEARRAY *psa = SafeArrayCreateVector(VT_VARIANT, 0, numElements);
-        if (psa == 0) {
-            _com_issue_error(E_OUTOFMEMORY);
-        }
+        SAFEARRAYBOUND bounds[2];
+        bounds[0].cElements = numElements;
+        bounds[0].lLbound = 0;
 
-        VARIANT *pData;
-        HRESULT hr;
-        hr = SafeArrayAccessData(psa, reinterpret_cast<void **>(&pData));
-        if (FAILED(hr)) {
-            _com_issue_error(hr);
-        }
+        unsigned numDimensions;
 
-        for (int i = 0; i < numElements; ++i) {
-            TclObject value(pElements[i]);
-            VariantInit(&pData[i]);
-            value.toVariant(&pData[i], Type::variant(), interp, addRef);
-        }
+        // Check if the first element of the list is a list.
+        if (numElements > 0 && pElements[0]->typePtr == TclTypes::listType()) {
+            int colSize;
+            Tcl_Obj **pCol;
+            if (Tcl_ListObjGetElements(interp, pElements[0], &colSize, &pCol)
+             != TCL_OK) {
+                _com_issue_error(E_INVALIDARG);
+            }
 
-        hr = SafeArrayUnaccessData(psa);
-        if (FAILED(hr)) {
-            _com_issue_error(hr);
+            bounds[1].cElements = colSize;
+            bounds[1].lLbound = 0;
+            numDimensions = 2;
+        } else {
+            numDimensions = 1;
         }
 
+        SAFEARRAY *psa = SafeArrayCreate(VT_VARIANT, numDimensions, bounds);
+        std::vector<long> indices(numDimensions);
+        fillSafeArray(m_pObj, psa, 1, &indices[0], interp, addRef);
+
         V_VT(pDest) = VT_ARRAY | VT_VARIANT;
         V_ARRAY(pDest) = psa;
 
 #if TCL_MINOR_VERSION >= 1
     } else if (m_pObj->typePtr == TclTypes::byteArrayType()) {
-        // Convert Tcl byte array to array of bytes.
-        int length;
-        unsigned char *pBytes = Tcl_GetByteArrayFromObj(m_pObj, &length);
-
-        SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, length);
-        if (psa == 0) {
-            _com_issue_error(E_OUTOFMEMORY);
-        }
-
-        unsigned char *pDestData;
-        HRESULT hr;
-        hr = SafeArrayAccessData(
-            psa, reinterpret_cast<void **>(&pDestData));
-        if (FAILED(hr)) {
-            _com_issue_error(hr);
-        }
-
-        memcpy(pDestData, pBytes, length);
-
-        hr = SafeArrayUnaccessData(psa);
-        if (FAILED(hr)) {
-            _com_issue_error(hr);
-        }
+        // Convert Tcl byte array to SAFEARRAY of bytes.
 
         V_VT(pDest) = VT_ARRAY | VT_UI1;
-        V_ARRAY(pDest) = psa;
+        V_ARRAY(pDest) = newByteSafeArray(m_pObj);
 #endif
 
     } else if (m_pObj->typePtr == &Extension::naType) {
@@ -543,6 +616,11 @@ TclObject::toVariant (VARIANT *pDest,
     } else if (m_pObj->typePtr == &Extension::nullType) {
         V_VT(pDest) = VT_NULL;
 
+    } else if (m_pObj->typePtr == &Extension::variantType) {
+        VariantCopy(
+            pDest,
+            static_cast<_variant_t *>(m_pObj->internalRep.otherValuePtr));
+
     } else if (m_pObj->typePtr == TclTypes::intType()) {
         long value;
         if (Tcl_GetLongFromObj(interp, m_pObj, &value) != TCL_OK) {
@@ -584,26 +662,19 @@ TclObject::toVariant (VARIANT *pDest,
         V_BOOL(pDest) = getBool() ? VARIANT_TRUE : VARIANT_FALSE;
 
     } else {
-#if TCL_MINOR_VERSION >= 2
-        // Uses Unicode function introduced in Tcl 8.2.
-        const wchar_t *pStringRep =
-           reinterpret_cast<const wchar_t *>(Tcl_GetUnicode(m_pObj));
-#else
-        const char *pStringRep = Tcl_GetStringFromObj(m_pObj, 0);
-#endif
-        _variant_t var(pStringRep);
+        V_VT(pDest) = VT_BSTR;
+        V_BSTR(pDest) = getBSTR();
 
         // If trying to convert from a string to a date,
         // we need to convert to a double (VT_R8) first.
         if (vt == VT_DATE) {
-            var.ChangeType(VT_R8);
+            VariantChangeType(pDest, pDest, 0, VT_R8);
         }
 
         // Try to convert from a string representation.
         if (vt != VT_VARIANT && vt != VT_USERDEFINED && vt != VT_LPWSTR) {
-            var.ChangeType(vt);
+            VariantChangeType(pDest, pDest, 0, vt);
         }
-        VariantCopy(pDest, &var);
     }
 }
 
index 71954c6926930a743fb7c6b41c85a712358e4653..df521430a340d6a41432c8566e6930daaa2304c9 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: TclScript.cpp,v 1.10 2002/07/14 18:42:57 cthuang Exp $
+// $Id: TclScript.cpp,v 1.12 2003/04/02 22:46:51 cthuang Exp $
 #include "ActiveScriptError.h"
 #include "Reference.h"
 #include "TypeInfo.h"
@@ -9,29 +9,6 @@
 #define ENGINE_PACKAGE_NAME "TclScript"
 #define ENGINE_PACKAGE_VERSION "1.0"
 
-static int
-outputdebugCmd (
-    ClientData,
-    Tcl_Interp *interp,
-    int objc,
-    Tcl_Obj *CONST objv[])
-{
-    if (objc != 2) {
-       Tcl_WrongNumArgs(interp, 1, objv, "message");
-       return TCL_ERROR;
-    }
-
-    Tcl_Obj *pMessage = objv[1];
-    if (Tcl_IsShared(pMessage)) {
-        pMessage = Tcl_DuplicateObj(pMessage);
-    }
-    Tcl_IncrRefCount(pMessage);
-    Tcl_AppendToObj(pMessage, "\n", 1);
-    OutputDebugString(Tcl_GetStringFromObj(pMessage, 0));
-    Tcl_DecrRefCount(pMessage);
-    return TCL_OK;
-}
-
 static int
 getnameditemCmd (
     ClientData,
@@ -206,8 +183,6 @@ Tclscript_Init (Tcl_Interp *interp)
     }
 #endif
 
-    Tcl_CreateObjCommand(
-        interp, NAMESPACE "outputdebug", outputdebugCmd, 0, 0);
     Tcl_CreateObjCommand(
         interp, NAMESPACE "getnameditem", getnameditemCmd, 0, 0);
     Tcl_CreateObjCommand(
index 12f542d18022777811e18885b4a9a1ef962baef4..ec02430e8168bab91d0f7d4eed157cd8460e7f69 100644 (file)
@@ -43,7 +43,7 @@ RSC=rc.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DLLSERVER_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /Zi /Od /I "\tcl\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DLLSERVER_EXPORTS" /D "TCL_THREADS" /D "USE_TCL_STUBS" /D "USE_NON_CONST" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /Zi /Od /I "\tcl\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TCL_THREADS" /D "USE_TCL_STUBS" /D "USE_NON_CONST" /YX /FD /c
 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD MTL /nologo /D "NDEBUG" /win32
 # SUBTRACT MTL /mktyplib203
@@ -70,7 +70,7 @@ LINK32=link.exe
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DLLSERVER_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "\tcl\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DLLSERVER_EXPORTS" /D "TCL_THREADS" /D "USE_TCL_STUBS" /D "USE_NON_CONST" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "\tcl\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TCL_THREADS" /D "USE_TCL_STUBS" /D "USE_NON_CONST" /YX /FD /GZ /c
 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD MTL /nologo /D "_DEBUG" /win32
 # SUBTRACT MTL /mktyplib203
index 1dbdf314d2897790e63681165d124ca3566fc760..2ea365a87fe0150db313c6c0fea6702c1d869878 100644 (file)
@@ -24,4 +24,13 @@ library TclScript
                 interface IActiveScriptParse;
                 interface IObjectSafety;
         };
+
+        [
+                uuid(0A0059C5-E0B0-11D2-942A-00C04F7040AE),
+                helpstring("Dispatch Class")
+        ]
+        coclass Dispatch
+        {
+                [default] interface IDispatch;
+        };
 };
index a336015d663235f059dd5b2907c0b4ad82a3d393..7b0c253a04c556a631bbe838cc41bf1361e9ff5e 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: bindCmd.cpp,v 1.52 2002/04/13 03:53:56 cthuang Exp $
+// $Id: bindCmd.cpp,v 1.53 2003/04/02 22:46:51 cthuang Exp $
 #pragma warning(disable: 4786)
 #include "Extension.h"
 #include "Reference.h"
@@ -175,7 +175,7 @@ Extension::bindCmd (
     Tcl_Obj *CONST objv[])
 {
     if (objc < 3 || objc > 4) {
-       Tcl_WrongNumArgs(interp, 1, objv, "object sinkCommand ?eventIID?");
+       Tcl_WrongNumArgs(interp, 1, objv, "handle sinkCommand ?eventIID?");
        return TCL_ERROR;
     }
 
@@ -187,6 +187,19 @@ Extension::bindCmd (
         return TCL_ERROR;
     }
 
+    int servantLength;
+    Tcl_GetStringFromObj(objv[2], &servantLength);
+    if (servantLength == 0) {
+        try {
+            // Tear down all event connections to the object.
+            pReference->unadvise();
+        }
+        catch (_com_error &e) {
+            return setComErrorResult(interp, e, __FILE__, __LINE__);
+        }
+        return TCL_OK;
+    }
+
     TclObject servant(objv[2]);
 
     char *eventIIDStr = (objc < 4) ? 0 : Tcl_GetStringFromObj(objv[3], 0);
@@ -205,34 +218,3 @@ Extension::bindCmd (
     }
     return TCL_OK;
 }
-
-// This Tcl command tears down all event connections to the object.
-
-int
-Extension::unbindCmd (
-    ClientData,
-    Tcl_Interp *interp,
-    int objc,
-    Tcl_Obj *CONST objv[])
-{
-    if (objc != 2) {
-        Tcl_WrongNumArgs(interp, 1, objv, "object");
-        return TCL_ERROR;
-    }
-
-    Reference *pReference = referenceHandles.find(interp, objv[1]);
-    if (pReference == 0) {
-        const char *arg = Tcl_GetStringFromObj(objv[1], 0);
-        Tcl_AppendResult(
-            interp, "invalid interface pointer handle ", arg, NULL);
-        return TCL_ERROR;
-    }
-
-    try {
-        pReference->unadvise();
-    }
-    catch (_com_error &e) {
-        return setComErrorResult(interp, e, __FILE__, __LINE__);
-    }
-    return TCL_OK;
-}
index dd59692acf5f975bb062c2304a6c0f2885a08bcf..7fe11cc39a8fdb8f42ddd39202a294a85b21e89c 100644 (file)
@@ -1 +1 @@
-#define BUILD_NUMBER 13
+#define BUILD_NUMBER 28
diff --git a/src/comsupp.cpp b/src/comsupp.cpp
deleted file mode 100644 (file)
index a4128f5..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// $Id: comsupp.cpp,v 1.2 2001/07/12 04:09:58 cthuang Exp $
-//
-// These functions are defined in comsupp.lib but Borland C++ does not include
-// that library in its distribution, so we implement them here when compiling
-// with Borland C++.
-#include <stdlib.h>
-#include <string.h>
-#include <comdef.h>
-#include <comutil.h>
-
-// This value represents a missing optional parameter.
-_variant_t vtMissing(DISP_E_PARAMNOTFOUND, VT_ERROR);
-
-// COM error handling routine
-
-void __stdcall
-_com_issue_error (HRESULT hr) throw(_com_error)
-{
-    throw _com_error(hr);
-}
-
-namespace _com_util {
-
-// Convert char * to BSTR
-
-BSTR __stdcall
-ConvertStringToBSTR (const char* pSrc) throw(_com_error)
-{
-    if (pSrc == 0) {
-       return SysAllocString(0);
-    }
-
-    // Guess the number of wide characters needed.
-    size_t destLen = strlen(pSrc) + 1;
-    wchar_t *pDest = new wchar_t[destLen];
-    mbstowcs(pDest, pSrc, destLen);
-    BSTR result = SysAllocString(pDest);
-    delete[] pDest;
-    return result;
-}
-
-// Convert BSTR to char *
-
-char* __stdcall
-ConvertBSTRToString (BSTR pSrc) throw(_com_error)
-{
-    if (pSrc == 0) {
-        char *pDest = new char[1];
-       *pDest = '\0';
-        return pDest;
-    }
-
-    // Guess the number of bytes needed.
-    size_t destLen = wcslen(pSrc) * 3 + 1;
-    char *pDest = new char[destLen];
-    wcstombs(pDest, pSrc, destLen);
-    return pDest;
-}
-
-} //namespace
index 2b6f4d158d8a5db84a0ffe8caf1dd80c29dfdc8e..8cc47b04b89c4db76b117e9aacf390b70768fd69 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: naCmd.cpp,v 1.6 2002/04/27 18:15:24 cthuang Exp $
+// $Id: naCmd.cpp,v 1.7 2003/03/07 00:17:30 cthuang Exp $
 #include "Extension.h"
 #include <string.h>
 
@@ -34,7 +34,7 @@ Tcl_ObjType Extension::naType = {
     naSetFromAny
 };
 
-// Create an NA object.
+// Create a Tcl value representing a missing optional argument.
 
 Tcl_Obj *
 Extension::newNaObj ()
@@ -45,7 +45,7 @@ Extension::newNaObj ()
     return pObj;
 }
 
-// This Tcl command returns an object used to represent a missing optional
+// This Tcl command returns a Tcl value representing a missing optional
 // argument.
 
 int
index 91fc3aa6482b289c27d1b305a7ea3cf57ba47633..28e669e3fddc50226b998c55c500c1f71ef31e1c 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: nullCmd.cpp,v 1.9 2002/04/27 18:15:24 cthuang Exp $
+// $Id: nullCmd.cpp,v 1.10 2003/03/07 00:17:30 cthuang Exp $
 #include "Extension.h"
 #include <string.h>
 
@@ -34,8 +34,19 @@ Tcl_ObjType Extension::nullType = {
     nullSetFromAny
 };
 
-// This Tcl command returns a null object which be used to pass a null pointer
-// argument.
+// Create a Tcl value representing a null value in SQL operations.
+
+Tcl_Obj *
+Extension::newNullObj ()
+{
+    Tcl_Obj *pObj = Tcl_NewObj();
+    Tcl_InvalidateStringRep(pObj);
+    pObj->typePtr = &nullType;
+    return pObj;
+}
+
+// This Tcl command returns a Tcl value representing a null value in SQL
+// operations.
 
 int
 Extension::nullCmd (
@@ -49,10 +60,6 @@ Extension::nullCmd (
        return TCL_ERROR;
     }
 
-    Tcl_Obj *pObj = Tcl_NewObj();
-    Tcl_InvalidateStringRep(pObj);
-    pObj->typePtr = &nullType;
-
-    Tcl_SetObjResult(interp, pObj);
+    Tcl_SetObjResult(interp, newNullObj());
     return TCL_OK;
 }
index 9f2c01083f1c295465d47fb6405c583e278f279f..5dc95603f81318e6755af9e1cde41c128b705633 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: objectCmd.cpp,v 1.30 2002/04/27 18:15:24 cthuang Exp $
+// $Id: objectCmd.cpp,v 1.31 2003/03/07 00:24:04 cthuang Exp $
 #pragma warning(disable: 4786)
 #include "Extension.h"
 #include <sstream>
@@ -140,6 +140,16 @@ findInterface (Tcl_Interp *interp, Tcl_Obj *pName)
     return pInterface;
 }
 
+static Tcl_Obj *
+newUnknownPointer (IUnknown *pUnknown)
+{
+    Tcl_Obj *pObj = Tcl_NewObj();
+    Tcl_InvalidateStringRep(pObj);
+    pObj->typePtr = &Extension::unknownPointerType;
+    pObj->internalRep.otherValuePtr = pUnknown;
+    return pObj;
+}
+
 // This Tcl command creates a COM object.
 
 static int
@@ -234,12 +244,7 @@ objectCreateCmd (
                 destructor);
         }
 
-        Tcl_Obj *pObj = Tcl_NewObj();
-        Tcl_InvalidateStringRep(pObj);
-        pObj->typePtr = &Extension::unknownPointerType;
-        pObj->internalRep.otherValuePtr = pComObject->unknown();
-
-        Tcl_SetObjResult(interp, pObj);
+        Tcl_SetObjResult(interp, newUnknownPointer(pComObject->unknown()));
     }
     catch (_com_error &e) {
         return Extension::setComErrorResult(interp, e, __FILE__, __LINE__);
@@ -247,6 +252,27 @@ objectCreateCmd (
     return TCL_OK;
 }
 
+// This Tcl command creates a null IUnknown pointer.
+
+static int
+objectNullCmd (
+    Tcl_Interp *interp,
+    int objc,
+    Tcl_Obj *CONST objv[])
+{
+    if (objc != 2) {
+       Tcl_WrongNumArgs(
+            interp,
+            2,
+            objv,
+            NULL);
+       return TCL_ERROR;
+    }
+
+    Tcl_SetObjResult(interp, newUnknownPointer(0));
+    return TCL_OK;
+}
+
 // This Tcl command provides operations for creating COM objects.
 
 int
@@ -266,10 +292,10 @@ Extension::objectCmd (
     pExtension->initializeCom();
 
     static char *options[] = {
-       "create", "registerfactory", NULL
+       "create", "null", "registerfactory", NULL
     };
     enum SubCommandEnum {
-        CREATE, REGISTER_FACTORY
+        CREATE, OBJECT_NULL, REGISTER_FACTORY
     };
 
     int index;
@@ -281,6 +307,8 @@ Extension::objectCmd (
     switch (index) {
     case CREATE:
         return objectCreateCmd(interp, objc, objv);
+    case OBJECT_NULL:
+        return objectNullCmd(interp, objc, objv);
     case REGISTER_FACTORY:
         return objectRegisterFactoryCmd(interp, objc, objv);
     }
index 6b4e641e90dd602b67f272e67ed1e2cb57bc2916..eac808da2f2345ce7069caeeda8c6c2cf8989cc0 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: refCmd.cpp,v 1.43 2002/06/12 02:14:08 cthuang Exp $
+// $Id: refCmd.cpp,v 1.46 2003/11/06 15:29:01 cthuang Exp $
 #pragma warning(disable: 4786)
 #include "Extension.h"
 #include <sstream>
@@ -17,9 +17,10 @@ static bool
 getErrorInfo (Reference *pReference, IErrorInfo **ppErrorInfo)
 {
     const Interface *pInterface = pReference->interfaceDesc();
-    if (pInterface == 0) {
-        return false;
-    }
+
+    // The .NET Framework uses GUID_NULL to identify the interface which
+    // raised the error.
+    const IID &iid = (pInterface == 0) ? GUID_NULL : pInterface->iid();
 
     ISupportErrorInfoPtr pSupportErrorInfo;
     HRESULT hr = pReference->unknown()->QueryInterface(
@@ -28,8 +29,7 @@ getErrorInfo (Reference *pReference, IErrorInfo **ppErrorInfo)
         return false;
     }
 
-    if (pSupportErrorInfo->InterfaceSupportsErrorInfo(pInterface->iid())
-     != S_OK) {
+    if (pSupportErrorInfo->InterfaceSupportsErrorInfo(iid) != S_OK) {
         return false;
     }
 
@@ -90,18 +90,17 @@ Extension::setComErrorResult (
 
 #if TCL_MINOR_VERSION >= 2
     // Uses Unicode functions introduced in Tcl 8.2.
-    wchar_t *pMessage = 0;
-    FormatMessageW(
+    wchar_t *pMessage;
+    DWORD nLen = FormatMessageW(
         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
         NULL,
         e.Error(),
-        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+        0,
         reinterpret_cast<LPWSTR>(&pMessage),
         0,
         NULL);
 
-    if (pMessage != 0) {
-        int nLen = wcslen(pMessage);
+    if (nLen > 0) {
         if (nLen > 1 && pMessage[nLen - 1] == '\n') {
             --nLen;
             if (nLen > 1 && pMessage[nLen - 1] == '\r') {
@@ -477,7 +476,11 @@ getObjectCmd (
        return TCL_ERROR;
     }
 
-    char *monikerName = Tcl_GetStringFromObj(objv[2], 0);
+#if TCL_MINOR_VERSION >= 2
+    const wchar_t *monikerName = Tcl_GetUnicode(objv[2]);
+#else
+    _bstr_t monikerName(Tcl_GetStringFromObj(objv[2], 0));
+#endif
 
     try {
         Reference *pReference = Reference::getObject(monikerName);
index 167275941de1fa79d5b5fa2e0f95f748f9a3b54b..b05665d1204a62f06a8a7140d323d8a94a4ddfc7 100644 (file)
@@ -260,6 +260,10 @@ SOURCE=.\typelibCmd.cpp
 
 SOURCE=.\Uuid.cpp
 # End Source File
+# Begin Source File
+
+SOURCE=.\variantCmd.cpp
+# End Source File
 # End Group
 # Begin Group "Header Files"
 
diff --git a/src/variantCmd.cpp b/src/variantCmd.cpp
new file mode 100644 (file)
index 0000000..51e5214
--- /dev/null
@@ -0,0 +1,151 @@
+// $Id: variantCmd.cpp,v 1.1 2003/05/29 03:33:08 cthuang Exp $
+#include "Extension.h"
+#include <string.h>
+
+static void
+variantFreeInternalRep (Tcl_Obj *pObj)
+{
+    delete static_cast<_variant_t *>(pObj->internalRep.otherValuePtr);
+}
+
+static void
+variantDuplicateInternalRep (Tcl_Obj *pSrc, Tcl_Obj *pDup)
+{
+    pDup->typePtr = &Extension::variantType;
+    pDup->internalRep.otherValuePtr = new _variant_t(
+        static_cast<_variant_t *>(pSrc->internalRep.otherValuePtr));
+}
+
+static void
+variantUpdateString (Tcl_Obj *pObj)
+{
+    try {
+        _bstr_t bstr(
+            static_cast<_variant_t *>(pObj->internalRep.otherValuePtr));
+        const char *stringRep = bstr;
+        pObj->length = strlen(stringRep);
+        pObj->bytes = Tcl_Alloc(pObj->length + 1);
+        strcpy(pObj->bytes, stringRep);
+    }
+    catch (_com_error &) {
+        pObj->length = 0;
+        pObj->bytes = Tcl_Alloc(1);
+        pObj->bytes[0] = '\0';
+    }
+}
+
+static int
+variantSetFromAny (Tcl_Interp *interp, Tcl_Obj *pObj)
+{
+    const char *stringRep = Tcl_GetStringFromObj(pObj, 0);
+
+    Tcl_ObjType *pOldType = pObj->typePtr;
+    if (pOldType != NULL && pOldType->freeIntRepProc != NULL) {
+       pOldType->freeIntRepProc(pObj);
+    }
+
+    pObj->typePtr = &Extension::variantType;
+    pObj->internalRep.otherValuePtr = new _variant_t(stringRep);
+    return TCL_OK;
+}
+
+Tcl_ObjType Extension::variantType = {
+    PACKAGE_NAMESPACE "VARIANT",
+    variantFreeInternalRep,
+    variantDuplicateInternalRep,
+    variantUpdateString,
+    variantSetFromAny
+};
+
+// Create a Tcl value representing a VARIANT.
+
+Tcl_Obj *
+Extension::newVariantObj (_variant_t *pVar)
+{
+    Tcl_Obj *pObj = Tcl_NewObj();
+    Tcl_InvalidateStringRep(pObj);
+    pObj->typePtr = &variantType;
+    pObj->internalRep.otherValuePtr = pVar;
+    return pObj;
+}
+
+// This Tcl command returns a Tcl value representing a VARIANT.
+
+int
+Extension::variantCmd (
+    ClientData,
+    Tcl_Interp *interp,
+    int objc,
+    Tcl_Obj *CONST objv[])
+{
+    if (objc < 2 || objc > 3) {
+       Tcl_WrongNumArgs(interp, 1, objv, "type ?value?");
+       return TCL_ERROR;
+    }
+
+    static char *types[] = {
+        "empty",
+        "null",
+        "i2",
+        "i4",
+        "r4",
+        "r8",
+        "cy",
+        "date",
+        "bstr",
+        "dispatch",
+        "error",
+        "bool",
+        "variant",
+        "unknown",
+        "decimal",
+        "record",
+        "i1",
+        "ui1",
+        "ui2",
+        "ui4",
+        "i8",   // VT_I8 and VT_UI8 actually are not valid VARIANT types.
+        "ui8",
+        "int",
+        "uint",
+        NULL
+    };
+
+    int vt;
+    if (Tcl_GetIndexFromObj(NULL, objv[1], types, "type", 0, &vt) != TCL_OK) {
+        if (Tcl_GetIntFromObj(interp, objv[1], &vt) != TCL_OK) {
+            return TCL_ERROR;
+        }
+    }
+
+    _variant_t *pVar = new _variant_t;
+    switch (vt) {
+    case VT_DISPATCH:
+        V_VT(pVar) = vt;
+        V_DISPATCH(pVar) = 0;
+        break;
+
+    case VT_UNKNOWN:
+        V_VT(pVar) = vt;
+        V_UNKNOWN(pVar) = 0;
+        break;
+    }
+
+    try {
+        if (objc == 3) {
+            *pVar = Tcl_GetStringFromObj(objv[2], 0);
+        }
+
+        if (vt == VT_DATE) {
+            pVar->ChangeType(VT_R8);
+        }
+
+        pVar->ChangeType(vt);
+    }
+    catch (_com_error &e) {
+        return setComErrorResult(interp, e, __FILE__, __LINE__);
+    }
+
+    Tcl_SetObjResult(interp, newVariantObj(pVar));
+    return TCL_OK;
+}
index 090cd68dbde82f8128a377d973d8c9422c2d8461..5e9876031f973dcad178f4bd16b3db0dd1778c15 100644 (file)
@@ -1,9 +1,9 @@
-// $Id: version.h,v 1.3 2002/04/27 18:15:24 cthuang Exp $
+// $Id: version.h,v 1.4 2002/10/01 21:51:32 cthuang Exp $
 #ifndef VERSION_H
 #define VERSION_H
 
 #define PACKAGE_MAJOR_VERSION 3
-#define PACKAGE_MINOR_VERSION 8
+#define PACKAGE_MINOR_VERSION 9
 
 #define MAKE_VERSION_STRING0(MAJOR,MINOR) #MAJOR "." #MINOR
 #define MAKE_VERSION_STRING(MAJOR,MINOR) MAKE_VERSION_STRING0(MAJOR,MINOR)
diff --git a/tests/array.test b/tests/array.test
new file mode 100644 (file)
index 0000000..8a8f49b
--- /dev/null
@@ -0,0 +1,53 @@
+# $Id: array.test,v 1.1 2003/05/12 23:31:03 cthuang Exp $
+#
+# This file contains tests for the passing arrays
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+    package require tcltest
+    namespace import -force ::tcltest::*
+}
+
+test array-1.1 {one-dimensional array} {
+    package require tcom
+
+    set application [::tcom::ref createobject "Excel.Application"]
+    $application Visible 1
+
+    set workbooks [$application Workbooks]
+    set workbook [$workbooks Add]
+    set worksheets [$workbook Worksheets]
+    set worksheet [$worksheets Item [expr 1]]
+
+    set range [$worksheet Range "A1" "C1"]
+    $range Value [list 1 2 3]
+    set value [$range Value]
+
+    $workbook Saved 1
+    $application Quit
+
+    set value
+} {{1.0 2.0 3.0}}
+
+test array-1.2 {two-dimensional array} {
+    package require tcom
+
+    set application [::tcom::ref createobject "Excel.Application"]
+    $application Visible 1
+
+    set workbooks [$application Workbooks]
+    set workbook [$workbooks Add]
+    set worksheets [$workbook Worksheets]
+    set worksheet [$worksheets Item [expr 1]]
+
+    set range [$worksheet Range "A1" "C2"]
+    $range Value [list [list 1 2 3] [list 4 5 6]]
+    set value [$range Value]
+
+    $workbook Saved 1
+    $application Quit
+
+    set value
+} {{1.0 2.0 3.0} {4.0 5.0 6.0}}
+
+::tcltest::cleanupTests
+return
diff --git a/tests/eval.test b/tests/eval.test
new file mode 100644 (file)
index 0000000..e55972b
--- /dev/null
@@ -0,0 +1,35 @@
+# $Id: eval.test,v 1.2 2003/04/02 22:57:35 cthuang Exp $
+#
+# This file contains tests the robustness of handles under eval.
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+    package require tcltest
+    namespace import -force ::tcltest::*
+}
+
+test eval-1.1 {eval} {
+    package require tcom
+
+    for {set i 1} {$i <= 9} {incr i} {
+       proc testEval$i {} {
+       }
+    }
+
+    proc testEval {n} {
+       set application [::tcom::ref createobject "Excel.Application"]
+       eval $application Visible 0
+
+       for {set i 1} {$i <= $n} {incr i} {
+           eval testEval$i
+       }
+
+       $application Visible 0
+    }
+
+    for {set i 1} {$i <= 9} {incr i} {
+       testEval $i
+    }
+} {}
+
+::tcltest::cleanupTests
+return
index 55ea329c8b33d9cface99a5c106295a7e164e54c..f2935bf19b37ef4505fddbf1701f29a548d590b6 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: foreach.test,v 1.1 2002/03/16 04:53:17 cthuang Exp $
+# $Id: foreach.test,v 1.2 2003/03/07 00:01:40 cthuang Exp $
 #
 # This file contains tests for the ::tcom::foreach command.
 
@@ -26,17 +26,17 @@ test foreach-1.1 {::tcom::foreach} {
        }
     }
 
-    set cellCount 0
+    set addresses {}
     set range [$worksheet Range "A1:C3"]
     ::tcom::foreach cell $range {
-       incr cellCount
+       lappend addresses [$cell Address]
     }
 
     $workbook Saved 1
     $application Quit
 
-    set cellCount
-} {9}
+    set addresses
+} {{$A$1} {$B$1} {$C$1} {$A$2} {$B$2} {$C$2} {$A$3} {$B$3} {$C$3}}
 
 ::tcltest::cleanupTests
 return
index 6b461d6dcdcf8090313aa421b0abbea7bf238ed2..21f718fcdd9a19f0786d496a07e7d4630dbea8a7 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: namedarg.test,v 1.1 2002/06/21 02:38:50 cthuang Exp $
+# $Id: namedarg.test,v 1.2 2003/04/02 22:57:35 cthuang Exp $
 #
 # This file contains tests invoking methods through IDispatch with named
 # arguments.
@@ -34,7 +34,7 @@ test namedarg-1.1 {named arguments, ChartWizard} {
     set chart [$charts Add]
     $chart -namedarg ChartWizard \
        Source $sourceRange \
-       Gallery [expr -4102] \
+       Gallery [expr 5] \
        PlotBy [expr 1] \
        CategoryLabels [expr 1] \
        SeriesLabels [expr 0] \