From e944f7eaa3aa55648cec04cd0e9623f4d8bd2cfd Mon Sep 17 00:00:00 2001 From: Pat Thoyts Date: Fri, 13 Jun 2008 17:22:40 +0100 Subject: [PATCH] optcl-3004 import --- GNU_Public_Licence.html | 525 +++++++++ ReadMe.txt | 19 + docs/default.html | 18 + docs/index.html | 24 + docs/loadedlibs.gif | Bin 0 -> 2809 bytes docs/optcl.art | Bin 0 -> 9032 bytes docs/optcl.gif | Bin 0 -> 81407 bytes docs/optcl.html | 100 ++ docs/optcl_large.gif | Bin 0 -> 7642 bytes docs/optcl_medium.gif | Bin 0 -> 3588 bytes docs/optcl_small.gif | Bin 0 -> 2362 bytes docs/optclobjects.html | 178 +++ docs/optcltypelibaccess.html | 293 +++++ docs/optcltypes.html | 112 ++ docs/refview.gif | Bin 0 -> 10112 bytes docs/viewlib1.gif | Bin 0 -> 13512 bytes docs/viewlib2.gif | Bin 0 -> 5736 bytes install/optcl80.dll | Bin 0 -> 204800 bytes install/optcl_Install.tcl | 88 ++ install/optclstubs.dll | Bin 0 -> 745539 bytes src/Container.cpp | 569 ++++++++++ src/Container.h | 90 ++ src/DispParams.cpp | 191 ++++ src/DispParams.h | 71 ++ src/EventBinding.cpp | 612 +++++++++++ src/EventBinding.h | 107 ++ src/ObjMap.cpp | 505 +++++++++ src/ObjMap.h | 79 ++ src/OptclBindPtr.cpp | 52 + src/OptclBindPtr.h | 127 +++ src/OptclObj.cpp | 1847 +++++++++++++++++++++++++++++++ src/OptclObj.h | 142 +++ src/OptclTypeAttr.cpp | 84 ++ src/OptclTypeAttr.h | 47 + src/StdAfx.cpp | 27 + src/StdAfx.h | 56 + src/conversion.txt | 51 + src/initonce.cpp | 26 + src/optcl.cpp | 671 ++++++++++++ src/optcl.dsp | 414 +++++++ src/optcl.h | 45 + src/resource.aps | Bin 0 -> 50364 bytes src/resource.h | 17 + src/resource.rc | 116 ++ src/tbase.h | 837 ++++++++++++++ src/test.tcl | 100 ++ src/typelib.cpp | 2008 ++++++++++++++++++++++++++++++++++ src/typelib.h | 81 ++ src/typelib.tcl | 622 +++++++++++ src/utility.cpp | 1045 ++++++++++++++++++ src/utility.h | 112 ++ tests/calendar.tcl | 54 + tests/pdf.tcl | 18 + tests/word.tcl | 45 + 54 files changed, 12225 insertions(+) create mode 100644 GNU_Public_Licence.html create mode 100644 ReadMe.txt create mode 100644 docs/default.html create mode 100644 docs/index.html create mode 100644 docs/loadedlibs.gif create mode 100644 docs/optcl.art create mode 100644 docs/optcl.gif create mode 100644 docs/optcl.html create mode 100644 docs/optcl_large.gif create mode 100644 docs/optcl_medium.gif create mode 100644 docs/optcl_small.gif create mode 100644 docs/optclobjects.html create mode 100644 docs/optcltypelibaccess.html create mode 100644 docs/optcltypes.html create mode 100644 docs/refview.gif create mode 100644 docs/viewlib1.gif create mode 100644 docs/viewlib2.gif create mode 100644 install/optcl80.dll create mode 100644 install/optcl_Install.tcl create mode 100644 install/optclstubs.dll create mode 100644 src/Container.cpp create mode 100644 src/Container.h create mode 100644 src/DispParams.cpp create mode 100644 src/DispParams.h create mode 100644 src/EventBinding.cpp create mode 100644 src/EventBinding.h create mode 100644 src/ObjMap.cpp create mode 100644 src/ObjMap.h create mode 100644 src/OptclBindPtr.cpp create mode 100644 src/OptclBindPtr.h create mode 100644 src/OptclObj.cpp create mode 100644 src/OptclObj.h create mode 100644 src/OptclTypeAttr.cpp create mode 100644 src/OptclTypeAttr.h create mode 100644 src/StdAfx.cpp create mode 100644 src/StdAfx.h create mode 100644 src/conversion.txt create mode 100644 src/initonce.cpp create mode 100644 src/optcl.cpp create mode 100644 src/optcl.dsp create mode 100644 src/optcl.h create mode 100644 src/resource.aps create mode 100644 src/resource.h create mode 100644 src/resource.rc create mode 100644 src/tbase.h create mode 100644 src/test.tcl create mode 100644 src/typelib.cpp create mode 100644 src/typelib.h create mode 100644 src/typelib.tcl create mode 100644 src/utility.cpp create mode 100644 src/utility.h create mode 100644 tests/calendar.tcl create mode 100644 tests/pdf.tcl create mode 100644 tests/word.tcl diff --git a/GNU_Public_Licence.html b/GNU_Public_Licence.html new file mode 100644 index 0000000..ee2d7f1 --- /dev/null +++ b/GNU_Public_Licence.html @@ -0,0 +1,525 @@ + + + +GNU General Public License - GNU Project - Free Software Foundation (FSF) + + + +

GNU General Public License

+ + +

+ +


+ +

+ +

Table of Contents

+ + +

+ +


+ +

+ + + +

GNU GENERAL PUBLIC LICENSE

+

+Version 2, June 1991 + +

+ +
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+ + + +

Preamble

+ +

+ The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + +

+

+ When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + +

+

+ To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + +

+

+ For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + +

+

+ We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +

+

+ Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +

+

+ Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +

+

+ The precise terms and conditions for copying, distribution and +modification follow. + +

+ + +

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

+ + +

+ +0. + This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". +

+ +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +

+ +1. + You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. +

+ +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. +

+ +2. + You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: +

+ +

+ +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. +

+ +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. +

+ +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +

+ +3. + You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + + + +

+ +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. +

+ +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. +

+ +4. + You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + +

+ +5. + You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +

+ +6. + Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + +

+ +7. + If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. +

+ +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. +

+ +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. +

+ +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +

+ +8. + If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + +

+ +9. + The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. +

+ +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +

+ + +10. + If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + + +

NO WARRANTY

+ +

+ +11. + BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +

+ +12. + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +

+ + +

END OF TERMS AND CONDITIONS

+ + + +

How to Apply These Terms to Your New Programs

+ +

+ If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +

+

+ To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + +

+ +
+one line to give the program's name and an idea of what it does.
+Copyright (C) yyyy  name of author
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ +

+Also add information on how to contact you by electronic and paper mail. + +

+

+If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + +

+ +
+Gnomovision version 69, Copyright (C) yyyy name of author
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
+type `show w'.  This is free software, and you are welcome
+to redistribute it under certain conditions; type `show c' 
+for details.
+
+ +

+The hypothetical commands `show w' and `show c' should show +the appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and +`show c'; they could even be mouse-clicks or menu items--whatever +suits your program. + +

+

+You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + +

+ +
+Yoyodyne, Inc., hereby disclaims all copyright
+interest in the program `Gnomovision'
+(which makes passes at compilers) written 
+by James Hacker.
+
+signature of Ty Coon, 1 April 1989
+Ty Coon, President of Vice
+
+ +

+This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + +


+ +Return to GNU's home page. +

+FSF & GNU inquiries & questions to +gnu@gnu.org. +Other ways to contact the FSF. +

+Comments on these web pages to +webmasters@www.gnu.org, +send other questions to +gnu@gnu.org. +

+Copyright notice above.
+Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111, USA +

+Updated: + +16 Feb 1998 tower + +


+ + diff --git a/ReadMe.txt b/ReadMe.txt new file mode 100644 index 0000000..310352f --- /dev/null +++ b/ReadMe.txt @@ -0,0 +1,19 @@ +OpTcl v3.0 build 04 +------------------- + +Licencing +--------- +Use of this software indicates an agreement to the GNU Public Licence under which, +this software is provided. + +Documentation +------------- +Please open the default.html file in the 'docs' directory for installation instructions +and documentation. + + + +I welcome any comments, suggestions and bug reports: +fuzz@sys.uea.ac.uk + + diff --git a/docs/default.html b/docs/default.html new file mode 100644 index 0000000..e4fb47d --- /dev/null +++ b/docs/default.html @@ -0,0 +1,18 @@ + + + + +OpTcl Documentation + + + + + + + <body> + </body> + + + diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..bc469d4 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,24 @@ + + + + +Index + + + + +

Index

+ +

About

+ +

Types

+ +

Type +Library Access

+ +

Objects

+ +

 

+ + diff --git a/docs/loadedlibs.gif b/docs/loadedlibs.gif new file mode 100644 index 0000000000000000000000000000000000000000..7cc3016e264ced84f77f9b6e73f187f29522e0ec GIT binary patch literal 2809 zcmeH{`9Bkk1IL%^k#ZG6M7iY-Icf=W%#mUV!-$z9m5ERyLXMm*nV379xeaZP_9%?C zg}LQE#*kYH>v^8n_s{q~@83SZzF)8R$I{xuz|e~d$OHTU{Ev75;CFm{d}n9p4lDWjk?Z*=;oFv@Il^^q*62#iT*p~*7=KyNl6ro<`}F7=@f z(OY55sn(Qq^Da0``dV13|0(!zo~LiZy|Jcw=Nzva1SuOvkV}m>H4ER`P|YZ{j1^E% zzPvn84lLwJGurjG0C1kV=<%hcZmugs&ZfY&wSIw`dnwR9D3{zzPa^UeXpQ;!AFBYN z?d`@wM;KKu%>~kKkH*GZkSmikV)OdMJ3;24P1A$H-jCTAJ?W&@ZDucV@7=4$ZRQ*& zG<{M-^3n2W<3skdH`0HS_P3dFC-mu)h_IcFIclMd`_ZqJwM-rT(%{ur-h}pY3!@LLu4c zxjy*?fc&^D4wj&@nCpY`UwjKQeJq~fj(V#Q=8S#0m>)Xi&wO{cC&Cl$18*HIjNwsT z!o-V#M_)ctz%CW1>a&(gGAsfdqb_(g4O+R-N>%KAng+$71tF|Tmm)04xdKxjfGtIE zqZDtlft$yj&^HZt84tk0<|;VS9&4qB%+8ZZhlsiPN<9VblSH0O{r}j-Aq=RwrU3hO1jUi;aUCeukaUB(+@+yw^P4 zA9Xh)D&TApnKuQYi5lTX z9x0Vh+M;$}jo%_@4X>gj!3(+HU+Fl`Z+|uULw)DEn4vr_mq#w)QuW%*@(#nnlD61y zDd-FDH}k{q4nf1ygpP5CWBz91tK$#4{$$)Y-{&DiNfYX#>`xL8 zOCe=)E=Jgr;;qntnRh*FIJ{|lKn|>tb#LWC%c;(0i1WU5)^ss8IRF~>CV6NE7tQx! zx$vxj+FaBY_r9lEE7-6QMNG?@PG(jc&%72MjB@yu{H=$H;3qOXf?=R6m%5a52N%RIDRye#s!D~Mi%T-B zYV_*spxjFnTvLxb)xh1pp(5glZ{e1Q3w_Yw!;;tYEugZ|%@B%B>4mSlS5CX*Gu-%Y z(HmPRVAm~(Q(T{1Vn^8tkF9Ks`TU&JvZ7VzrbC5pj;eEa&o!6QaI}c8vY$28!NW2` zFvv$eyqh{Z8XQhOS*{h=g!7Wz&b{nU@yJmzgtJ&7d7Rx-Iv`c6^TDAbPSQGOI*jx; zUl`RAQ>qdijm^DSVX-#WGxX<|o5|ctL6wS?BNxtuwJB(9uu0{5?t=!yR~15H-VVy& z-1*`;`AQy5behHP)0<*6)QcGdS7i854exsjDrO;ouzOIJGC8yH4=%px@ z6v#300}3mGE;#LOD=lec{gR;xW-V2LkWEdWavs$n?c9a zQlK}m5hshM6vC~wJ!+RPCSjJeln8+yu*R=_8i{oh8ojYPYQ;WXkYQP#KQwJf-}pdQ z=3@OBPmc55^XQ_O?d&(z{{D3l_RooY!mcL==dgzl=OZtf>SPi+ST1f4(c@-&HE{qa z3ecqh4cy$jY_GTt=uU3Oyf*YR%!sBU`C$*&VM* z7JTxNZl#mEroAMh9)8~=&UxWI;U)D5BanUeo0!Gz$Z%0vZyB`bnp4=*Nyzk*H*W14 z$$KwKo>m__4V{=}57%ioZg6xECk`Wi)Nxv@w*BNZSp#aDOo3^EdLte`RBb;nAJwI~ zs@>)5K*ew2Hj%(9c;V>gPeyI$Q^TXY>5?}I*T3_p<3Q7jN)iTUZEM+6;{(fBM2}`d zO-^0Dxq6^}A`~T*_9?YMJA3pB9EetQhtW_Ptv6u8jdznEw56Q zXwkO?Fq~;n;6Y}uEG{HfI1O&*m(j;Ozfydj|J~8@VzYC3Xqhw(WLNW+90hKw_F`G>T4BUm&g6Xo}gkz>%7X(t7Tvlu$aif(Gr) zSK)Kk_O@ug`UneFY)}8_2wc7)O~(QEIxCwig;3XE_q|g+E$69DSuK?o46+Fyb9KE# vWV+XeKRciX(wf_T(AJ}IqLYxyrldTJ_2&&y%53|V_A~U2gcLnl0KoWf{Tl=a literal 0 HcmV?d00001 diff --git a/docs/optcl.art b/docs/optcl.art new file mode 100644 index 0000000000000000000000000000000000000000..1a04f071da52cd5cb3d4095ced1c70669b10cb41 GIT binary patch literal 9032 zcmdUVby$>NxAxH8ACU*8|!cb-`WquX(0*eK1jhW0(GVE-H%7)HK|u$gBII{0 z0D$xlJH;QE62U=oWf9}nZ~i%gPlJN-%l;io6+n)Vs0d#P z1ip>HTnH?S-~bSRsJ}PIfv_XtjYPnpKSl?j15gZz0;~b9f8CORA%NgN1~(uHunW)x z)Bs2Tu7HWZW`_V70K0#Tzx@$qN38en@z3c0`~3gh3ljgm|G)LW`G4zw^Z(ZW=AQr* z0L*}Vz&*eMpc#PkAM1Mq-UD6%Xb>GWL}ZtX==Q&B|F2lc6M#GeNZA3H2Yf*EAK886 z89??Q*+FEN{w4pj|Novta*&?L>qg%A-AKD%=L5Mb@VwJ2$R0KoVNC>c2^ngKK>g-hF^rRU!Wzz!b>T76nL7zTR#%bB>CWW?G z@#kuPgDPIaqZO!h?{59Lx}Bj_4Br$we+Gw0RNS%JH#P-7w|GlHzx;Ntb;h#R#Q9F$ zMSdj>3@g+{xjU^6H9>_TL6t6Pl(>CKmoN-k0*LZjexwz}`pj~~Vyv3`#5RS8wq|AH zG0$qCMCO}`EJBUeL>atPCtD*aJr?t@sfV7uaq(jgqw~z71O$`o?oq)_w5yl?xmHDk zHm|dqEjthTtGhlDUOmbtncVigFn_u3+Pbj+U`fx!l`>1fZM9WI*lZ0GhRUD7yN0@ktANIDqu6m+GQ{~z0g_6cwzSOceoG)K=SIY9esD8MuOjldt z8)ea}DRGKTK$tN*PhSnqec#|b{)ijgXW1qbfq5Cq$3Cdgz=!4pv!%#A@Tv3rtBHPtB|8y`t~lw8pzd zh9S;Ny?(*t!t)Um0`v@W_}IhzSyVE~^Un=&)4PM?lVj71qVUypUUlVki|Cf;n}dy2dh zG90xf3TTgb(pG4#t3L+M%1k_WpGY*1x08LI$AealeTOjYP;`2DLJywJcQvGhfqtKa zVRic_#NhsfuaNH+twiRsO>6NVp@x~5&iI~tv8x`XzX8oX#&bQ0y z*uor9zI~D%9eeMj4X|TvV0SD{pD!Jx;5tiVW#m%!y+Gdbq8!wnouwm!pPT!$KvSQ$ zxPf&=DUx4nTY^yQi~Di4pAb*EwlaChWi)($8U!PTdG;xkSld4uXPfq>&(_U7d4U;z ze}?mH)c*Y=hCxS;HqwvNMc++@*Nd}Z%F}G@s8|DP;yE=Orlbir3#K`E-iZ%n$O4D! z&925q%@42^PR>h-rD2}&*X`$vjrYeajpFNc7K5QduDci^JjpK@2M+eFln0_@yOQ

{Frh(H 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 literal 0 HcmV?d00001 diff --git a/docs/optcl.gif b/docs/optcl.gif new file mode 100644 index 0000000000000000000000000000000000000000..19b96451fb2242ad581f977febb177ab31ca7e84 GIT binary patch literal 81407 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

nF$ZNC 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

jd@odDkDTT@}``(nl3Z0q%k#v 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 + + + + +OpTcl Documentation + + + + +


+version 3.0 build 04

+ +

Farzad +Pezeshkpour

+ +

August 1999

+ +

This software is freely distributed under the GNU Public +Licence. I've include this in this distribution as an HTML file.

+ +

Gosh! So much to document here, and so little time. This is a +preliminary, and rather informal document - a better version is +on its way!

+ +

The Distribution

+ +

The following is a description of the directory structure for +the distribution:

+ + + + + + + + + + + + + + + + + + +
installHolds the installer script and two versions of the + DLL - one for Tcl 8.0.5 (no stubs), and one with stubs + enabled, built for Tcl 8.2 libraries.
docsDocumentation.
srcThe source for OpTcl with Visual C++ v6.0 (sp3) + workspace.
testsA couple of test scripts using MS Word, and the + Calendar Control.
+ +

To install, run the install script optcl_install.tcl. +This will autodetect your version and location of your Tcl and +select the appropriate installation settings. The installer +copies the suitable DLL <tcl_lib>/../optcl/optcl.dll, and pkg_mkIndex +is applied to that directory.

+ +

The package can now be used by loaded using the command:

+ +
	package require optcl
+ +

Things To Do

+ +
    +
  • Distribute example files.
  • +
  • Implement array parameters.
  • +
  • Implement default parameter values.
  • +
  • Test out-flagged parameters (I haven't found a + server to do this, yet).
  • +
  • Implement in/out-flagged parameters for events.
  • +
  • Use Type Libraries on the type conversion of an event-handlers + result.
  • +
  • Test with DCOM. (does anyone have a setup that can do + this?)
  • +
  • Write an ActiveScripting engine interface.
  • +
  • In some cases perhaps, reconsider syntax.
  • +
+ +

Known Bugs/Limitations

+ +
    +
  • Not thread-safe.
  • +
  • Can't set parameters by their name, à la Visual Basic.
  • +
  • Microsoft Forms ActiveX objects can't be fully in-place + activated.
  • +
+ +

Credits

+ +

This work uses ideas developed by Jacob Levy in his Taxi +specification. I am very grateful for his helpful comments and +encouragement.

+ +

Copyright (c) 1999, Farzad Pezeshkpour

+ + diff --git a/docs/optcl_large.gif b/docs/optcl_large.gif new file mode 100644 index 0000000000000000000000000000000000000000..6c8621bc79921324d68218555040c4372cfd2acd GIT binary patch literal 7642 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 literal 0 HcmV?d00001 diff --git a/docs/optcl_medium.gif b/docs/optcl_medium.gif new file mode 100644 index 0000000000000000000000000000000000000000..b0e98a8651cfee21d25bc74bba3931b524f01935 GIT binary patch literal 3588 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 + + + +Optcl Objects + + + + +

+ +

Objects

+ +

The manipulation of objects in OpTcl is performed +with commands defined in the optcl namespace. The +following is the synopsis of this namespace.

+ +
+
optcl::new ?-start? + ?-window windowname? CLSID_ProgID_DocumentURL_HTML
+
optcl::lock + objid
+
optcl::unlock + objid ?objid ...?
+
optcl::isobject + objid
+
optcl::interface + objid ?new_interface_name?
+
optcl::class + objid
+
optcl::bind objid + eventname tcl_procedure
+
objid ?-with subobj? + methodname ?arg ...?
+
objid ?-with subobj? + : propname ?new_value?
+
objid ?-with subobj? + : propname(index?, index + ...?) ?new_value?
+
+ +

Description

+ +

optcl::new

+ +

The optcl::new command creates or attaches to +existing COM objects, returning a unique object identifier, if +successful. The -start flag is used to indicate that the call +should always create a new instance of the object. The -window +option creates with the COM object, a Tk widget that will attempt +to in-place activate the user interface of the object. Not all +COM objects provide a user interface, and not all objects with +user-interfaces will in-place activate.

+ +

The final parameter of the command is an identifier for the +COM class of the object. This can take four different forms: +CLSID, ProgID, document path or raw HTML. Currently, the latter +two only work with the -window option. A CLSID is a string +representation of a COM Globally Unique IDentifer (GUID for short). +CLSIDs uniquely identify the location of a COM class server +through the system registry. To successfully create an instance +of the COM class, the server must be correctly registered with +the system registery. An example of a CLSID is {8E27C92B-1264-101C-8A2F-040224009C02} +(the CLSID for the Calendar Control). In order to pass a CLSID +correctly to the optcl::new command, the CLSID +must be wrapped in an extra pair of braces. This will ensure that +the bracing surrounding the CLSID is not stripped by the Tcl +interpreter. For example, {{8E27C92B-1264-101C-8A2F-040224009C02}}. +A ProgID (programmatic identifier) is a human readable name that +performs the same job as a CLSID. For example, MSCAL.Calendar.7. +

+ +

Additionally, the command can take two further forms of +identifer. A URL to a document with a correctly registered +document server, or an inline HTML. Both these options are only +available currently with in-place activation only (-window option) +and require the installation of Internet Explorer 4.0 or above. +To use inline HTML, the source string must begin with the +characters "mshtml:".

+ +

Reference Management

+ +

At the time of writing, OpTcl cannot provide a robust +automatic handling of object lifetimes. So for now, the optcl::lock +and optcl::unlock commands provide explicit +means for respectively incrementing or decrementing the reference +count on an object. On creation, the reference count of an object +is one. If, the reference count of an object becomes zero, the +object is destroyed, together with its Tk container window, if +one exists. Furthermore, the destruction of a container window, +will immediately destroy its related object.

+ +

optcl::isobject

+ +

The optcl::isobject command returns true if +and only if its only parameter is an OpTcl object.

+ +

optcl::interface

+ +

The optcl::interface command performs the +role of querying the current interface name of an OpTcl object, +or setting it to a new interface type. COM objects are +polymorphic, in that they can (and often do) support multiple +interfaces. In OpTcl an interface name is a properly formed type, and hence can be +browsed with the Type Library +Access functionality of OpTcl. One can discover the supported +interfaces of an object by finding +and viewing details of its COM class. The initial +interface of an object, is its default interface.

+ +

optcl::class

+ +

The optcl::class command returns the class name of the object. +If no class name information is provided, the command returns +'???'.

+ +

optcl::bind

+ +

The optcl::bind command binds an event from +an object to a Tcl procedure name. The event can either be the +name of an event on the default interface, or the name of an +event on another event interface. The latter must take the form lib.eventinterface.event. +The Tcl procedure will be called with the first parameter being +the object identifier of the OpTcl object raising the event, +followed by the parameters of the event itself.

+ +

Object Command

+ +

The object identifer returned from optcl::new, +is also a Tcl command for the lifetime of the object. Using the +command, we can invoke the object's methods, and properties. As a +means to improving efficiency, both forms of member access can be +applied to a sub-object of the invoked +OpTcl object. Methods can be invoked on an object, by appending +to the object command (with a possible sub-object), the method +name and its parameters. +

+ +

Access to properties of an OpTcl object are differentiated +from method invocations by the placement of a : +prior the property name, with white space seperating it from the +name. For example to set the visible property of an +object to true, we would use the following syntax:

+ +
	$myobj : visible 1
+ +

And to retrieve it:

+ +
	$myobj : visible
+	==> 1
+ +

If the property is indexed, then its index can be specified +within matching braces as a comma-seperated list. For example:

+ +
	$myobj : grid(3,4) "foo"
+ +

Sub-Objects

+ +

COM objects often have deep hierarchies of objects, reachable +from the created object. In many cases it may be inefficient to +represent several of these objects within the hierarchy as OpTcl +objects, in order to access a single object. For this purpose, +the object command can take the -with option. This is a dot +seperated list of sub-objects that it has to traverse before +invoking the method or property. For example:

+ +
	$app -with documents(1) save
+	$xl -with workbooks(1).worksheets(sheet1).range(a1,b2) : value 15
+ +

Copyright (c) 1999, Farzad Pezeshkpour

+ + diff --git a/docs/optcltypelibaccess.html b/docs/optcltypelibaccess.html new file mode 100644 index 0000000..f83e0b8 --- /dev/null +++ b/docs/optcltypelibaccess.html @@ -0,0 +1,293 @@ + + + + +Type Library Access + + + + +

+ +

Type Library Access

+ +

OpTcl provides two means of accessing the type information +stored in a Type Library - graphical or command-line based, with +the graphical version being built on top of the command-line +commands.

+ +

Command Line Access of Type Libraries

+ +

The command line access to type libraries is +implemented with the typelib namespace. Here's its +synopsis:

+ +
+
typelib::alllibs
+
typelib::updatelibs
+
typelib::libdetail + fulllibname
+
typelib::load + fulllibname
+
typelib::unload + fulllibname
+
typelib::isloaded + fulllibname
+
typelib::loaded
+
typelib::types + libname
+
typelib::typeinfo + libname.type ?element?
+
 
+
+ +

Description

+ +

typelib::alllibs

+ +

The typelib::alllibs command returns a list +of registered libraries by their human readable names.

+ +

typelib::updatelibs

+ +

The typelib::updatelibs command update OpTcl's +internal list of registered libraries from the system registry.

+ +

typelib::libdetail

+ +

The typelib::libdetail command returns a list +of three elements - the unique identifier for the library, its +major version number, and its minor version number.

+ +

typelib::load

+ +

The typelib::load takes as its only parameter, +the human readable name of a registered Type Library. If +successful in loading the library, the command returns the +programmatic name for the library. Otherwise, the function +returns an error.

+ +

typelib::unload

+ +

The typelib::unload command takes as its only +parameter, the human readable library name of a registered Type +Library. If the library has been loaded, it is subsequently +unloaded.

+ +

typelib::isloaded

+ +

The typelib::isloaded command returns true if +and only if its only argument is the user readable name of a +library that is currently loaded.

+ +

typelib::loaded

+ +

The typelib::loaded command returns a list of +the currently loaded libraries, in terms of their programmatic +names.

+ +

typelib::types

+ +

The typelib::types command takes as its only +required parameter, a programmatic name for a loaded library. It +returns as its result a list of types defined in the library. +Each element of this list is composed of two elements: a type +category followed by the name of the +type. Types fall into one of the following categories.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryDescription
enumAn enumeration type.
structA record/structure type.
unionA union type. Currently OpTcl can't + manipulate these.
typedefAn alias to another type.
moduleGlobally declared functions (currently, + OpTcl cannot call these).
interfaceA collection of functions that implement + the objects methods, and its properties (get and set + functions). OpTcl cannot call these directly.
dispatchThe same as interface, except that OpTcl + can call these directly. Usually a dispatch interface + wraps an inherited interface type.
classA collection of interfaces (or + dispatches), broken into two categories: incoming and + outgoing. Incoming interfaces are those that are used to + invoke methods or access properties of an object, whilst + outgoing interfaces generate events from an object. In + each category, a class type can specify a default + interface. Each OpTcl object is associated with a maximum + of one class type.
+ +

typelib::typeinfo

+ +

The typelib::typeinfo command returns +information for either a type (in the form lib.type) or, +if provided as the last parameter, an element of a type. These +two forms are described as follows.

+ +
Type Information
+ +

The first form returns a list with four items. The first item +is the type's category. The second is a list of methods supported +by the type; the third is a list of properties for the type. The +last item is a list of fully formed +names of inherited types.

+ +
Element Information
+ +

Information of an element is stored in a list of three +elements: the category of the element (either method or property), +its signature, and documentation string (null, if not provided by +the library).

+ +

The format for an element's signature is based upon the +elements category. method elements return a signature +that is a list, with the first item being the return type of the +method, the second being the name of the method, and the +remaining elements being its parameters.

+ +

For a property element, the signature is a list with +the first element being the access flags to the property (a +combination of read or write), followed by the +properties type and its name. The remaining list elements are the +parameters required to access an +indexed property.

+ +

Parameters

+ +

A parameter description in OpTcl is a list with three required +members and one optional.

+ +

The first list element is a collection of flags describing the +direction of information flow for the parameter. This can either +be in, out, or both together. A parameter +flagged as in indicates that information flows from the +caller to the callee (by value call). A parameter flagged with out +indicates that information flows from the callee to the caller. +In the case of both flags being present, the information flow is +bi-directional (call by reference). It is important to note the +significance of this when operating with COM objects from OpTcl. +A parameter that is out or inout requires the +name of a Tcl variable to hold the value of the parameter. In the +case of inout the variable must exist prior to the +method call. Currently, OpTcl doesn't make full use of type +information for event handling. All parameters of an event are +passed to Tcl by-value only, for the time being.

+ +

The second list element is the correctly +formed type-name of the parameter. The third list element is +the parameters name. The final optional list element is either a +question mark, '?', indicating that the parameter is optional, or +some other value, denoting a default value. OpTcl currently does +not fill-in missing parameters with their default values.

+ +

Graphical Method for Accessing Type Libraries

+ +

For this OpTcl defines the tlview namespace. Here is +a synopsis of the commands defined within it:

+ +
+
tlview::refview + windowpath
+
tlview::loadedlibs + windowpath
+
tlview::viewlib + libname
+
tlview::viewtype + libname.typename
+
+ +

Description

+ +

tlview::refview

+ +

The tlview::refview command creates a +toplevel window that displays a list of system-registered +typelibraries. Here's a screen-shot:

+ +

+ +

In blue are the libraries currently loaded by OpTcl; the +others aren't loaded. The Refresh button updates the list. +Clicking on a library, either loads or unloads it, depending on +its currently status. At the bottom of the screen, a status bar +informs of result of the most recent operation.

+ +

tlview::loadedlibs

+ +

Once a library is loaded, it is referenced within OpTcl using +a programmatic identifier; in fact, this is true for any client +of COM's type-libraries - e.g. Visual Basic. The tlview::loadedlibs +command creates a toplevel window, hosting a list of currently +loaded libraries, in terms of their programmatic id. Heres's a +screen-shot:

+ +

+ +

tlview::viewlib

+ +

The list is automatically updated, every time the +window receives mouse focus. Here's where the fun begins. Each +element is mouse-sensitive - clicking on one creates a browser +window for that library. At any time, a type browser can be +opened using tlview::viewlib command. The system +ensures that there is only one browser per library. Here's a grab +of browser in action:

+ +

+ +

The left-hand pane contains a list of types +within the library. Clicking on any type displays its elements in +the right-hand pane. Elements in a typelibrary are organised in +terms of methods, properties and inherited types. The right-hand +pane sorts the elements into these basic groups. The lower pane +gives a description of the element last clicked. If the type +library provides any describing text for that element that is +also displayed. In the lower pane, if a non-primitive type is +used to describe either a property or an element of a method, +then that type will also be click-sensitive. For a more detailed +explanation please read the section on accessing elements of a +type.

+ +

tlview::viewtype

+ +

The tlview::viewtype command can +call-up a browser window to view the details of a specific type +in a Type Library.

+ +

Copyright (c) 1999, Farzad Pezeshkpour

+ + diff --git a/docs/optcltypes.html b/docs/optcltypes.html new file mode 100644 index 0000000..55bcdb6 --- /dev/null +++ b/docs/optcltypes.html @@ -0,0 +1,112 @@ + + + + +Types In Optcl + + + + +

+ +

Types

+ +

Type Libraries

+ +

In order to precisely describe the interface and (in some +cases!) the functionality of a COM object, COM defines a language +independant mechanism for describing types, called Type Libraries. +You can think of these as a machine readable superset of header +files. Using Type Libraries, the interfaces (more about these +later), methods, events and properties of an object can be +accurrately described.

+ +

Having this kind of information is very important as it can a) +allow for the accurate type conversion between Tcl objects and +COM types, and b) speed up an invocation on an object.

+ +

Optcl is now type library aware - at least in terms of reading them and being type +sensitive in its invocations. I hope a future version will be +able to write out Type Libraries.

+ +

In OpTcl, types are represented as a strings comprising of the +programmatic name for a type library and its contained typename, +joined using a dot. So for example, stdole.IFontDisp is +the IFontDisp type defined in the library called stdole. +

+ +

Primitive Types

+ +

The only exception to the formatting rule specified above are +primitive. These are always a single word with no '.' delimiter. +They are listed in the following table:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeDescriptionTypeDescription
charA single characterstringsingle byte string
ucharAn unsigned charactercarrayC-style array - not currently supported
short16 bit signed integerdecimal96-bit number
ushort16 bit unsigned integerfloat32 bit real number
long32 bit signed integerdouble64 bit real number
ulong32 bit unsigned integerdispatchScriptable interface to an object
boolbooleaninterfaceNon-scriptable interface to an object
dateDate type.currencyCurrency. Range: ±922337203685477.5807
anyA variant type.  
+ +

Copyright (c) 1999, Farzad Pezeshkpour

+ + diff --git a/docs/refview.gif b/docs/refview.gif new file mode 100644 index 0000000000000000000000000000000000000000..3522f14d1850649f9bce454b625bcc8ece2cf60c GIT binary patch literal 10112 zcmeI0RZ|;)qJ*Jnu~Hlg6n6^6-Q5Er1PQ^lxNC8j;!@n*-CBx!(FAw5;#Sgo&fI@- z=kDV^?#wr{yNb#RLc*r$$WF))NdK!aB&2_Se*eP4!g6x{_4fW79vgvo@DaeHYT5TX=G{p3X=1p9bQmvS?+=B(g!qTPo+v zwTe}AgJ?g7h{L0?o>ZKjE2X4UI2wk<~*`Qnjtz4obG z#+kCnBWllj&Kv#W(Q|4wf`4}UzG188s&zK)Po#8uqG4}Uf$DPls~GL?If9bxBqLCz z3R+KL4dxSh>fLSUs~v8q8&lowmzzIBu|I0`bhvC(y|YoD7HPaW{9UY?uhH9ecM5N| z-<c96UeC474nNUG{C&AOKP-nr1CIs`uQH%tk#{0D z^{yDSe|2r3!Edo1O~Up(juA2^8~RA?;V5lUJR1}I=Z8^ICP1My(liLNCt0031PYv$_<Z9CMNGKB$x-n)1-44BDC%cM!zp>@ASA3WAzw zyORn87xC6{8CuwLRc%SaI9tu9T01GT+MTY`+CjYUr}fdbDrZgA0^MiLTn;f`G{>;3wknL7>U|(!`#GfVA?OwMfpYkx@F6^Tp zw~lbGd_OET=T1yQJ7e2QRxGPu_=+4?gL-t|R*P7y*vi6R>y~M9ah{nE^J#w=mW|@P z@ptWI{?}cYWP?t|)AM2}bkpTGtYqcSDM|XLhltR(E)mb1!fH?*z4o@B2CJ(jO7VBH`YHeoVMtXtUN8xUK`k*fhF;ThC;jy-M4>`I{m%E$B?|6ojyNd zJDxy4)n3U{{g+(-^W>zewqhqCpspR=zW1@qUbFV8Q%$wL2% z{!72DDXi&l7UwKWzaHp1{pXnlrsP}2kg?BctNNBGNn?{%6q;FOlyfLvPpa(N^Vy0V zrugLy@^~u0HCFi!Fn&A@3sTQ#txzzwr$BxLEFP`cdod`VO&B>y)naU;`VwO(|(VZh_N`&+J=UwGshBA?EcGA(%or~g?zE|L- z&@4)GEq3WL^JWrma@BB+5t3t|3O>>j@f^)~6e+~;z|w|XxRha1*#6>UQzA_M^DV=I z;e+t;SmrZEnX&`hXI9(a&^hHw`AJqG52o^(>#<}gE))7k73E5-G^5G4>LBhm`Gl^! z+T|uPM>tklc=!-+tXZbBjvp8`dI^jF={8;;Ft?DQs9mb&g+8{!eQU#wMEdy6XC>K1Vv zpQ_T{MN1r?z={b>wRGChPNboy=S;ze0EhgpI09G9($dJuP303JP-B%?k+rA4dIs| zfO=HJXV64DeiWHIUvL;v2hg_%&|lF;b~NaHP)eBJMC>g3FmnH znE_z_*B;H&IC#1#y?t{3li+@d{Qeez-d3wDgit2j-wwg7h`v-G!cl;hQpJrX@=MW` zpl-{6Y(UFGR_x_zMt{!D`H11D&)g-2hfcN^`@?UC|J zQ`?8lWzW(lG7^7;Xk-;(4Np zR$ov2?u(y0bQ14@!J@0^+=9FF=jVvV^}9kz>Ww?RJby3i%}jH_*dR&q?RWn+W^M&1 zlp(*%g#D`y;`rurE#`T<0Eu+@g!lCbP1n%VfQR}?(`1fMu0l}%CH1(zG1m?kv!>f5 z&+Cq#Fs`Kw(&qT{!vHhS`hN&s!oQ^gZc-U`zV2>OAUEj|XLPta9iKa^uDn=#K=i>^ zuX6vJFm0mD;BwTUNOaqJkQ+{h%-*dOHj8c3uwny=JFb#@ReA^ui*qKr%ir=~J{H-n zk-+;sH;X0N7a|QFS?d^gF3D8pNOu=3a3F#R7)KO}d=o;n|9K54zcJ#(3l2?mwTA_V zd!q+UJ>)dNIS8LcgN)Qin)X)8mNm<9?IH_uY|~48{4PLH%3ftlpd4Fvf2@#&2~PEP%B= z`E63a@2nD+7ZZp1O>akyuO6XDZ@=M~ zf3x3@e?Bt#>rI_=W$;M$?O@-Sk;m|TrwMka31d?d<#H0WG97^r^rLVxgK{#~u?%fi zGFxZz?xG1tG<4b$LHwB<@|)P?H)G0sPzs7d%9e)-PbEa4Ge!I<`93^B&L>qVD|IJR zPh~k(<0&;ToX%Jv4XB?6@=4Q33fDg(yOg%n?j&G(Pss5;-EEePU)q93!NTT=$fh$L z{FLsjOpg0RuFhn_DMxXblu?{Sf&?RR1emd!nh98$i&>?|12UyS>F%bPv7MPB>6zBc z=83{tlAx?4@{CO7G`BGe)V36@GK(ZeOB-o3HrmWAVPcu>^zzQ^nlV!>=g;-Rdb}>5 zjmJ{8e7<))r3P5pL`Owq$l7y)qkG9?6)~6@mD~rHqop!(=)B{Wuih{8TRZIA8o;R* z^%bX&siqO5Qr%g(8{~Ypci+~8bImJa1o?GHTNPc>`CJ(k0Itq%Ezz6Dw5!V*>&H^P zGjttzC<}Oa}Lxw{#9RKwI?4b8D-AsgW6bIvixY|Bj=F-K~+b zzrKy3C&9F$qA1#ziJ~(o(svELX9&dc2;`pECL#VBc55R!8uKIv7(RB1U;3=Y5{_n9 z6#7^gpsXqCUYNyF92XUoavxQfp10VNe^c&q19KxhDuziH1s(vFSha!KYEr)WhR>y; zzr2n>P9B2PgI4}`5&rg}WsRW%!`4E@urk=Zu(*pLV%OIRi^^%2veB&^$X3=&?=e&C ziKrbBhq!szVsJ(nctA14-Cz}~^WxD4B1Z>~4$LBf?O(R(y$$NI0BaVJ1>`wf(bJiIoaQmyG7#(%r9MWz?(>JmL z8HfU;gJ>z zh9*iZo0*dauwihKcd-6y>ke&M|Gn4dun>gTdn>(aCEdHH$$Q9}zoV$i=s{==u>zq|{xfu>=Cx zyk=*++`pImV)dL`iKdB^*Te`H(|xg6^>VOx3gi`>Vi&$OckpfYX-51Kdax?@bnBUK zEO%*^wDXN(FpTRYtT^TMENZVr399&>?O{nTZaN~EE83IZ)tNZaS!*YG*X;{46dn<+ z4*Jlw4XUXv7o78}tU~dE3JL~3SN6Q{6~zeU*jM$0d}*!nL9qLmg;p2ydNxz|M@05l z(n}KOv`4?M?o%mmP;7tE5wN`xih1$*5zB$9*4r#I06VQJWF9Eg{>8Z_=9}_s(bKfQRfhHd3#r+0Lv%$j%f#% znBYh&9yQ4ymT-v<|9WZ?jI9@_uK&T>n4uJ`9H)Wq#~2Vdf_QBoQCVv+ifU$GY@}En z<|fFG?P>go9dUU~=bbuAVKdAoI`T>$lG>sA<~f*)Wkj5d=7(z2t)hN(4mI5NnlMbmDgT&xdAboA#LWeDZu@9{xkck!NL*ryenXLnue zHW#{^S{Jy2mT0kxP}t7x5GXEeyfPxS$39)H{uL{SZ)NQBLw-X^tXEHLH9RI?t^i+Y zq$#R^MR2m|Wh5W&dapKVVlaxX(irtcQL{QvpF$_zsQFvZ=Z~Ue8-D}(I7%MnN{)M` zt>YqEg?=|PH5dASEr}aT6pN+coXIwtc^4l{Tw5f`j`$i49HP1zzcB*AIU;pMCuF}z zs*AS1zl${2bq#Qz@M)j<+fyn_Mc+21BYv@b0zqH`GouZ*aek-I z4ojc)$3D(|C8G+DU@VC^ro0`#yq(?Aoh5I*w@*9tcw6j;yZqF9{DHeCB@J}cB~*EP zDt&uu8+#gvJuMCVb#3A|pZ9e>;VZE28T9QFrzc@45Ca_XNyqlX(GE;C@Xa@%#v4%F zPD5LbgOJ68j=O`W)`P!{hu`04*UBFvoDq5`hpEePnHcfMPQ5*IcLpwH32aV7Ek>xRFosIXMO>Ue`BhG$PpU+90 zFBqRM1)h&zBoEht+b$A4kIy5}j-)%!2TITP0>LrVsVRL&vOX!Nj>mBt-^9sNE;Wwh z11}DBRUQ+-YmAn{(I<#c$D&V{)f&fDb%#FGCz74yF9~4Oy)Ar6D!brwBIp&#*DJF8 zD~cailrvYy6jwAKsRlOwFhCL4(B*8F{A;!!*ARtlj(^wOA8!n;4zQ#%aIUfhzf$=7 zT(ivH1XX6*S7z5Oo5w|G3((&3>5h8qMNd%-ycYB529tk252Y$?P?=k_&I0^V4$bb_z^0@|TT7H0}ay2`$JonXS?T zkqLt@??arj*g%i+l9|#6X4AoB2{VtT`J~@A?_HozYW=q!o$-FGMnQEC%+PGTkLgV5 zcVWWjrC*<;m9xq(%`EE8B5j|eD(__kUcS{orhk30CcoRMB=M+!(yS-f{-|Hv`C#@$ zqL=tmlK3*7c%8Ya=Y^Ot6uG>fkbGT$KEWjj81=t{K(A|?uN#}Dr3+U(l88Mh;@~Ud zDDm8A0#1Am7YrCn3 z1__5=CKa5tBOgb|Y`j)6yE76)Ei7=RbiJ$ajRZMWY?+`~HkC_#e~3==vhaaz`cfhZC`8nbGpK<)q9* zndJv!Zry%FmV6=;WaW0bGABz0!LfX(l59E>6V}<>2FRtcjg40#6x91(9{$cND(I)n z-dM`l1j=Xrp$#_Oxv~paFQqKHVsj^-<}&v`4Z_ASeJZ*?dHd1zf&nI5eh*jM?0itoxI@f7T1qJI(C7m`^WqMA~x+ODiJ_iQ<85;%u$^%Ctls#@KD zDEOTEFYQp0`q3UpvF%GZWGOdyxw$`lPT`d94m@*F>UN!UQT!bR zbX8``;M10UF0-psW~**#YGLM;yY6G}zP+C4Zpv{|eb>)-qsG@vpd-N(dOh=_qi(`U zLBtI~P$f6mX79`*B%jKy&IMZlj4zG1@OBYm$IT8As!wW&qRxEy(?&$7OY~Fq)uLrc zO4|maPz5p$qYaAmYk*mp7H!)1Tb)dAK!%JPU(SXdQj#f7j|M;|s zJFnd9WA%bOamF2Adq%3IOOM|EZM-hIxFt8(v`{P=Xx>?>sw8nmr?*BM=|BkaTt(A? zIQzJJ8T)31wS#?57rmhO7q8X8Kok-(Ri{ED7&9`#C#m2!1SAD@VdOE7g%QNlb~_O` z_$Ekbd{BE4?_Sz zCc9Defy)-j=AOd)g&zf;EVG#LvI@U5_mS^M7FrpY#(&K7waaxe&O9yh(hxbT@GA4R zXkG*%S)y!^&|H*fQ2RONvw14nmAf50@#JHp#aI+|J3jyET|6+fj=W5VpSFGEA$J^{ z@Fcq)dGEA*KKTyne>FXkzP2+cDhRnPb_<4*&VcC|QyH+{Jdp?Q1&y)3+aHnM_4)BC` z3PbX7_K!V8UBpCt+`aRD`@g`>qZ!h#h!>d3*SjapAQV07h z34dAbVvWKYUUK5Y*6`Z!C@_!}_d6&}mL1Z2K*gX?u|%yn++w`VY6n znd;k6mSQ5as!;m5sY0O8u<|;VrrJUQF6-#9Brza1WxL3r2Q2v^w_3*cFV@FHr3?{? zgM^nCbJ~5<(M24dpa_e-&4NcI7V4U$6dW=XRv+cS|BR>}ij1&ZcVa3KKKtHvu~At? zHE9}qJYX-2DLjhBVhAf9>zbji24w(q?2lAp5e@MooW&&1C6XKAYThb@R`NEj2~y{e z$AO%xM*k^>NuwlYprf6RQF(`wy)=VW74 zT(X-V1Ncg$Zz!(g(s}l6HND?guik3diF}_`_nM(!Jx?HQL{=hpUGZCA$%z3jR+Wpm|bYK>LqmBU6E@IEv5I@bxR15em;1m;Ycz9BnsWTf%uw7QcbXV5jz z!+dR>fG0QOxgM|ATw~r@7P$<1g(1T5}Ozua%1P!N~hYqt5}SkoNf$xb}trNS{Q5W-mMxhpl6TA;5yiTm^vJY zp0V;S{_OPejbPT|V+*5bLvHuV@qC2u90gOZb3b~Y(yHD9p~7`V>Kfpx?W_ru)G%lz zo?);n$ko}VR~>!FB{pmTKfh{ahz$5L8$`N1!4%h&^?F7}?APtM!+>gEsbP`c9HBI} z^Y)Uj7+T1a>V+l9j$LU4j+o8dud-T3UQP0)# zuul3__GjQCL+<$~1?K`A&*kPsVSrl)obphVG(UR3b%wgn*a!9aqf^Jd#(m=HTKZ~tf%iTG z72~jn>Qhmeo6+T(zxUW|oij9saF4}F*nJc4i_DVp`o9ZNl0?jF(hG=gyrl5Ne1)qY z0rje@_}`fW50AMZYK|phky&*FSL$58@twHx>j`A$+tQD~JB6<_bKf`ay?@vi@{9zu zwX186Xj0`KH+IoBOO)5%7-ql!_q@CxsA_7E65-D!T9V`R1gu(raLw7h0<^01e9d{< zAA7m^*y7llk$>hJ`MAkdU+z{X`Ka*#9VX46(O39(_3NywxnjsMk-am1qQ~e>k2rb7 zn>8`i81ZF7@p_^5X~!Te{vN`;oxAQPyWnbmBL#SUJ)%5QtsODlhn=bM9L{} zG8c8WXF5P3xcr%N(frfIo^}sA(VwvMYE>wBN0K^K?1`|u;k2N9UThzwkFH0ornrBQ zxA=0R?~h;474{FHvUEx{;#cql2~|&Dx1Y%4Y8mTo7n;Q{Mx7q;isXH>3_-sPNlrWW zxLAl`-|0(IYd7QGP;$M$`NqtmW*2cC9oi`?=ob(HU!O)Bs3C! z%QkFkKB#&!Ks+ey@MRGEqTr0fht9Ej@SOcu3$H94 zWp~7Px%ao-#-a)x2vL&S0qMHtZW>^r?w+(jkIemqye_2-ot-@UV4HVphs{~awoaG3 z{sg)x!=AzoveF>CY@*qCH&U-iivY+?WkyvIOHQ%Y=u_R9 z%D{liThs}dpIjUVwm?qDuMcHvsYN7V($x&ZVwB7+d-6UD%z-ud2EcZ}pnM6ASa(iz zNb`t6f8SPYTK=snP_58cr)RLF9i>O9D^5fxNo5=#vk<9>!u^-QUSB`osC~3#q}nie zP%P#JFeI4|=|iQ5<1<_nugLwGIwt+P^;r z{bhUjG>)2O^}~w&CY3%kPL&U;TQpDl^2JuQh_jpGpu8`UVwjj;#X&kMxqD;=S}A}QZB~x%_eY2}lY=&MfHvX! z4Cxf&HyPR--Fh7|F@R-V`_s8L*Xta1?i|Xx7ApVTn>%c7bsc_)j(|9Tbt?HjXZAc> zQ>0c$v{y%LN=JNMN8(&Z@>NF)7br~yl;H#_84!x6=`c=c)&iRZ0)R^KK;>K@s=SU$ zFHmg?sP3Vy+Pi=#!C_bjD!(p_VJ@nk164}jePYxBgadWgwLzsoVD5rm_#D_lSD<#0 zxmQ;?S66vaSA$>IXi66qtZSMJgvJ9+9JGz8K->@zlLJUe9i+zzLd9LY5?gwk2C_ca zw%L!R(8YBihJB`j*}lf9y)L!jgYZ4#!lbmlYJqO&pijDbUutLB;%EJ9=iVXqu>;cp z>ZMDHx_ad%dR3UP&;Xb>zm{XE9!skptu8nKO^@XbEUXvIJ_QVR&P0ewka}UUXv<;Yurzi3MH{fdIyfbK(T7u?`5a6gzRaJt%s;gJpHKb!DwmrM}r1j!$zvr#@glTI{+Gu zVJpP2O&70uUEf{Yurt@N>vguS*05*FuvhnY_qySaSHmCiI6tY3eo+}Euo(@i8+C~r z4c*PQQ|Y^M!Z9865(A799oCpEjV9M;J@;YWt+O)_c<2zwi*r3X@LVqy4H7;Cn+||Y zodc!l*5v@x{=J9yauvb2HKdc%u%zYh4YsF?9%_B>ab)t$LBT z53yJW&e=SSYMLTQvAJToQoqrDd*XpP9Fb-)7Q+apPY(fRp+ZNb!9l&w;;;i_4*$18 zDz8btvd=BULRL@|Qf7`8r*=`~XZTDe_qyGpxPRpITe#)>BWX-P{t7p{)!72+IC7N^ z_vuF4RXB-)f-8e%;6)GKrm(|hyN7gQ)wFNxYB6Z_o!y zdP%N(<#G$LAu4I~N+=C%vU%9SrQVi547WU05WX)1l{0}8VU{O(B4SZMlgFuX6m1cq zseXNP%g;~_sc6dha!LKY5X46tYIo-RvTw0pYY2ZQeJPD1jZz3Kqw&JI&E7QGrz5gT z!Q(G4%FuIVJV>umxN;I+XQ>ABf%79M>3z6{m!&M zFORi1v?=VX@7VkU<;=ljL1en(4d*>&1Pz^KBcBll(O1Qv7 zF?}{$M`hwNuFVpAyZljO>`?_2s%Tm;4g=k-XlnuK=5L6}T9!oOx>{z$zk>cQXf2{T z)Hn%r^FW7u(gHYF^nu;Y_U>j50z2ObYM$%tw@G<+zrS^tt=|=1G6O%)Ix;OKb8lCk z{PJUKJ^KB}LAWne@ACF6Hn7{hBqeFv7o4CeUU+=>ea5x8e$mPPx+e~`4P1`w{QkFe zLwpMc#P48xqM|nOQtaYZEl|Tt0d?ISqY)LI7;b&{J&12r37qlPGh=<)j;rW$oVqya z+5ojW|NGcQCWU^yKYd+#>x?n$ij}Li;&XD2Qu_7KWW!ablVsDFMl?n~#yk4}u|DU? ze;<<0+|mL5AWYjsltmH!SBM&1^~JnW6h#cD<0cS|Py!Z}a*%l8CX$(T56x>$9G6)l z0(!T&zfEf`2+^o=`q@c1N=?W^cgtz^BE5a*=~agu=n!7%c5v3THpE~(p}qu54eN0_ z%>Bw9Ymi$+w0b5$5zFN$wUvLkLErp$yvAC#i-sU&OwOiI!^$4v+aqx+KMVJl(4V$3A!B(7`Wh1un2XEaD50F zp&@h#*nNs9W7wIk$|Y=C?Gp%H+!+m9C7e;~fPR11ARYHD6iGb+X=ZGjg3Wy{2A}rN z_;)|gf6{-{jZbUY@uX9b9*i8>4r%OY=o`G}VN;#)r`n~&4KI~q>O}Qh5xXYxKqn7h z@z18t5U+DBn&^c9cp_*WjleEHVkv3D{?L^q&)X_mu{7N=Y)?0{oFxiA1O3_>svm_Y zd}fb%_}yJX3&C$qn}_&W3K#t&C2b4YfZ1#fCMPZbFbE0NOQbk_4JHV3K`+6?G$$)( z?_0!U#Y;BU;YN>}`-SbiU!5r!USbbMdpModuf5FN)Lm1$+8XWG>v978?4S;=HPGV9LkPOeT+?G@8N?VURz*3oDP3!i{ZLK?~^6$We24I-4)_RM@ zlHr1Jq;#hE{T(PGi@Nrw$1UZei`t5=S+cMiD<_~EIJ*Xr3=Gu`_mqJi$xG841!O!5 z-ND-!%8M8Z@MpI6MZ`F7Gq1pHtu)#3RJ*!NZXFA^w$BCBxECvJgAH3d*1Da5(JjWR z-vn4$M4a5)a<^~oSG&%{YJC?cckbv3I(9(p-U7rs0L7TDi)m-Sr^;RE?NhInYpj%gppbx_#tHKdB<_Y%nITbMd)NIlb1e$5O;kn^keW_hIMTO(^h3TeR z7bz;AJ({j$KzoNp1ATeJ07TnN#82BPLA?--?ATuIWn*QAzooVM(kW?7r}R^6+o;Nw zYwp|DnQCjtstFEUgA7N2-MA?^JmIjm9M^M=faMh#o}UpCS1OZo5q0r(5lk27bK*qz zN5V}+l1sqvJ+t{Dm$Ds16x2d`BM-WWgFvBAygz_1sD0Wf&c*W4M-CHBo;Cf9kkQ5rMrSZ%^BW5;T74ZupkH!T!5-RqV<{>NN~I z9e-;4OwP_lV~ryHCpTaW;K_i!1FrEF9Vb)qgwxKSbN8lY0aR&BcAW^!zRdVR?+QM5 zpUJDeF68dq%?o#*>&?EdbV48M7{meuz_#aHON}q?IYj}6nh+|dWh?j9kmsuAbY2*^ z)ALMt^#d3OyGdhoTXBR;ijVBPxYuLFKzMTK4FpFnPIBnihYHbl0LH=1JAV~#k@f)e zvGd=@O;XT{QZvl`=D&pD2c}KJ@xJL6;wM^O;8VKH1Fz=aa9}WR;J8dM?3$);xNPOI zA+sznLE8v(j6L;{w2jB%?(}Qwa)_EG|5$TK2(7Bzl2&Y_9_E=|L#7=>+i&YW1jkBE zkSBObJM2X}Sj1AqLNXK;C6qim7>-9x;!Nr~%?S2^GcHmR8CN(uQocLO?{Y|U);&a> zE}S%*L+MDtUB)QNLu@kA0hur2hjb)5uAMn8*>fvUmN48=*3WV6>mXgAi+gBimcsL zD3#%;Fxrr7-eB4LP@HVZejG=%!AKM>JuKU3%V-I2-55ZdNc5QfL$Nlihu?3cXu)Om z*pg6BnZOQPxrS$5vgPoSGJ{&%$Qmupu>rAq&&a+fovyZ6L`Lr3RtG98O=Ep|VJkhG zG3nv#pngWNK|zr=+h|Jt1T+Qp^D&v?1N9aG!2+*u281eU`h1Y=q)`ilgf_dJ6&*MU zrH&@0o^YM2Bc%ozrJ8h@%5X)5PfC~oot_~b=@3PPJw+oO9aE18XU3Qje*G?iRE+S1 zdMiEECWB2Htwly5C`#(_7&IySK1GHxZR{@fF5F;zETQos$Y?3nXf2lISUK7~nD@m- z@FA90KUNhbLe(csd0inuL5spJhCk-3{#vviAfwGXiH=czbcBoPIZk*jJ*>@e-ZrGq zTdhx@`%S^YsyxhOEH+9Z#3~|9p*`bYdIo2CmQh&NzKp7Sc^d1O`fy|t_>jk}%)uUz z>TsX=0+&+7o80zWDFcw)DWlV;om>~LgAkn4aFmlRWEgB`7YG(e_WAibmZd8MWNQw; zE{pORVwJT6md9{>eNgTI$A+zChpwd}YW?&t`Dy8vJM;;lBNV4jmIn+5g$r>F3v*lP zE$X@PI|@lR3dvu62o23Y+ZWLK7SLCiN$D0b`xddr7MRHi*_?j2v7zK%AmO&RM58Va z&njkZC=#D2GP*66+9-N{p)r3VgT7G6j?hYP{8k@vXHxvFDqKRDNqr=k1RcVsuGgw- z#7F95MEPNLDOB2&7Q(z@Q#O)n<;`oYVQqHKZ}V8f*)RGX71qWxrXCi@g_+yR)5;Gu z&yu*z_%Q$)Ozi;iv6H8Z5B1G3kz+e&NDJ;L3ohj>wJJNyu|;Qo8tN^~H-J^~952Bo{8^Xio1Hc;Om# zIHPr%`kN!X4uV8?I2j*5%#Y$F{dN>uFD?Rg}f zb$*?dxt+~%ot>4P#gpv}MV_{;G=bdTBu~6}CyKfF{ipl8+z5VWqILf`^~QPYih)LX z$1!w!$#=&`b+bN_aB(*UMHK^{s1M#cMN>T;{&Xi0_#_E*U&R>@z0p}A5}Bti8&TcuZA%dZi^eUX{>#u1rfayMo@bRM&@Xa@Bt#3VT!_ z0R4x5bo|6JGR~?O+g#Sf7C~7-UV%3H@YDCaHf3gI(s511gnNEQH5Vm%864aKl6m48MzfvtEBP%Ynfxl zGjJf#w%us0Y;;e|Xp>#IouD0E0%*!%&S5ztih1cOEi&VEvCe)e!*yQygOPD*L{E79 z-Alh+c=l41?*k#9g3QpzSWfklRdPMpy=#G?3}oOqMF%fo4w+O$$;?B^jrx?tF&(V< zDWBk3gDW6CQf~2ATd36wXqPBN)3!>X%2#cW#4EA@ zbAqaSaZqtt{0ymaO#pKqD06FUo*^ffC~P^?ee>jf4GKkP(qrD1CmRAXuBUIW4{S{} zye_9VOf9fR!PE9Wvnr^TEXOK>#4s#R?WXfORM(BOqne^no8vFKKvxKcaWCsuhC5$M z*9^V&ZmOmcYc|t1c9w*TN?)c#!tLxMVqK~BR>+v<#1`>XnTA381U++eQ`_A!n$}DS zv_k7c+iMt!xs(|Cc;Tt#)msj}0``XD{eSjge=ikP$FOWG8%#|{`y}u=+K{MfEP!** z$`j|Ox0Q{j#m*p555)4aOo$6wR1!?mj)Y<1b0eXAD>Y_s|F zPrNWPfKDN=)OpTThpwP;18v`M+VTd@spFiozW z0cTz*%_k;TUn!#4T{hk)BfwlV)F_gEx+DiIWmQbM-6wcFOmimgg)v2#CqR}#XDS$w zTPLQ3nc?GKk@kkN;4Z7lZe#matX-r7 zc~&0o`6lQphAIDn)>_VE&qU$y(hYj8Z+I=09SomzYmR!2J9BFzd(BC~L_fQs5^=pZ zrA6bkOntn`S!0j8y~WLb|A``xnK-lfB>3S#FazOQ!~h>t&ZZ^v^WV`o7|fy>Ix4|Sl$ zV3W0OHWgQA&J-u5mP8%o;Abo$rLyqnXf@@!`<(dR3oOc);`I%?Ux(Ia4sPs~lg8<$ zDn?Y-pa^nDhW2E6I4}GNc);8}o{rw2e0a}Wd7GSlAHMplqZa*_HT}`; zdZH%YbZzqhBk{;Nca$P^3U{}&`|7rPoC)!7@A}t{-Z!qkAc9Db-3L<7xCWkqSi2jxP)4QYEq_?2s|6GWldZB}|Y3j+9odNiQ7bn~sBi zBg!vvI@`3%&2pFH3A&g0n(T8u_dLRIt$ zuD4SSzn){*FVqf}LDOZE=uLhWSS7>U94v2SmD#P;Tg~D}6Nj8nQ}EercRuhq?)67J zLArdJ$6>ooKHKbUwGSK^wbILPZ@7h2pp}0;-PzvPschp&8Z{=h@{HK*uC@7!^)8ii zbnIMH^WJfsWSQVL;=B6KALbtprvw}_Z=D3fXKhYNB!Z>t*6Di@_8#~bHj(M z2mrY%-KsBR6uFSU0ES|j`LS(&*3^N&@vKa8Jy%Mue21dpuF6c4w0Bd;j+;rX)XiHB zlZ8vhsQ}&!DDR!BNTd7W2*>JD<+ND)R)v@pT7Z+fG>#5$%W~D=-MlDO2JeC>Fz;Sd zk!zV(3+7G{M|Bp-Ep-?caO|$7twy$}siWo5tfTK`e5(a^;z^WU))WD(8av;4teWZ! zs;s4kPcJX&r6pu&fzv%a*KN!))XFaH$)=Vt03|NN-^3>Q*UXUb_yMZrwg62U_OD?{ml=V(g@muBGc^mHF+$K~26=%z(Oej2I^Lh@K~y72c`S zpx_9KwMGO3Z*325Nyi#nUu#ImZ?!5b&g?kO3LxXK4iAb0S5?E~I8O zYFXg+PR1wfJIm)vGyR-8Y$`Xj#Q#jbHg~)|zB%{F8<_{gp$K&S82Tiye{zu*C(<%n z*uno}g5^||W=f!;OmL*#Ue#el8NSkSqy@8^Ye=!x-(v;LyslEkx%#%AncIL6sujfsy6e7Fknbeh*5=ffKVYHT17(NOz^qMJgmXXDl1 z#k5v5LJct5rJ5OK$}>!QFB3l=UfT=Ea-^QEQ4y14RdGt=vskT6vV;1kS?fLNLk4a8e!wpJFVN+O`fk zKF(B4kZ!a4e=|rv+p2xlZOn)NX3g_=eAZVSCwtOE)f6j*W1)7cX`ZQfN5GT zPKm9o2zZ*{FMZzq_Y~n2yBU-iAP>3KDa9dCuvw{l!HT=B(jSB5$dUU(WJFs@MCRGB zs{2w_j}so?hE~B$`k#d+Ta5%?ZTauoYD^opDZ+{~Njr+#Ooj|;Fg}{5McRLOFYP3} zP?xeIA4*Lhz?ATc+C`|^Wu_`XJriN=Txy*fw-TVZWJg_BG;N;a05pM(ioqo;8(4(Q4&e2ZA&rmAV zB?*s&HC+A8aBW1lrLo$Q-lk+d=u*D5jcvgRm|?W@ir?0I>G&f-$#@^1pna6g$t~kz z>qsuEeYT{=JPYDcA6vL;@AudZS94}{}BT3Z~jg!*pJfV9QM>{jv}Jpjonfk{L#dKe(f~? zZg6y4kNfXGOR$&n#5wx%!2tV@_Yg}DL7WEU`Y z`61z$?*UiJWkxNn(^~&H-;MS0Jqtuve_XS)A@GmGF*Cg2z~@rV%ZN zeOl{>N5wV+dd{#>e=FWbgMMuK+Vo?f$rCk^bCc_Jj^lA9FoIVSk8z|;blFutR<=44& z=mUtt`1n1)BV}0Sw(ZaRfV;D>?`ooZjh+}J{3xJrJy{(@@AAcqN zJoM{*J0u8t84n7)`$O?@q4)J5G!*!|yWZ77Ci*XcF{oqyALUHk-0aQ2R@@2f!@J&p zmANqft;3(XnZ@F*@>552%nxi?-YI zKgCL3miG@+7Oj+{MFPHXEzz-A1~alsnZikad6yPo3M0-?%aU@k~!d_IA(^my`U8DKPaZgdZ8G~|eQ$3^Q$2cpTYMe_}ipw=r2nS8|F!C0Y>~@e}~r zVO+&wkmw!&FQouNkwDuY`IRCw_FR~oF8$kBQP~~s(O|qlCO^kgVGm2bYzo8^E>SQv z{s}TvJJqjE;_)Pr^ zR>AL5==C3q-cs1-jW0a{C>h7czk{|Ra=GY5<>{*RqEoH5lGpx98Isg5f+{8V0G>RB z-TT5eUU}82e5Lf6Bjx<_p{dHQaZgt1LHGWxdqpTjEjFB3NV1O!d-|b&2+$>|XgP5v zI``5K!NPm^v)@K-6nrW}EuQgWV^G)92im=E*~;9xbO@{Kvx}b0~^h9S*Zy zypkO>vq*@VHOdno;nLy>lKl`Zr0OxWpNmUF8dF?aYkd=t@WCr()lAX3U-z?uwCT9R zqp&8^rL+J_4~0^!F{+0-*-HR#IzYNvZrnlPO$Jmor6>RzN|RZv8Pb&ch*Pv0GCxuw zV3q!=qBMjsyDN$s`+IWWed3)~d5&sPvjl*zquH;lWr4T2L8>fdvZ!#RAXK8w{7|Gc ztivRhZ?HURX)>m@J%3uJlg2e-MYsB(py_dp>Gm=2DVF|2XN4s}@6=n5#YBbmc$5a( zJiY6$-d8~7nUEi#GK)gCfH|=0*gSK1Bq<*udEBJbHZ?c*qKfIUhE1%mJ*_=^0G~}g zb9qVGaRIHGQUg!>bE*Ma#B!p?9NM;eRx@cT-ncuTrXL9pZS*#=&c)eTif*gC1@Acp8@Y-YnNS^I zKG9|t*){FuPZhqb4h<+m5nmjh-ef)A#GoHRQZ2vT>akBDEWzPx>npIsk)_8&blMPW(-A`j0fq#(_mp(YX*$xy89P*g8!HJ0^yI5EC2P6cCUm7{n|7u|_=&7N8=o`xKn34~^J4{d z_e54UxHAvMN|z~+48@>_?R6GXJ29dwdLdOt8&l@_I&#vU-^=TCzgT|?spVjLWJ_LW#ONUdWAfcldHXxZj`qX4mbwa{ zB*0>Y%WD4YSbtkhz-gHe$pW2iUcAL>2iH{1%53vV3*9f89MMpQ+1_wp2G24L}bQ>2iiuN+wL73$6Uok_nbu(*us=2lEsSpS7Ig0u7OBE9V_5ewPvJRwsPQla&WS^9rO>rT^adB$>TW!jAN~?L#FO!sjlN- zBut&IV*|TZRLyCVu3@pekTy4(=j{BQR(T4>DdU< z*4a$VDL)X&>Im8Wh~eXG3~B$@70JmJn6lZxCtg!oHT{C!Rt?kHIq`G=SIfq6%Dx%W zOLTo3c&u?X7HM@%HKGFTIenJPdB8L^CjZZ0pbVV@^c`y^)q_iP()X)R-)Alv0+x;) zjmeQt78q|R`FHkp46tU7H$+baFqXOUb3fS}!MWauAKU05o}$|5NdNs|>IiIcuwX%Q zHdmP>cLqvy8{b(vY^q+ZuMG)$7|$g@H_RjYgH~+btUr^SuAcKptk;OZV z9iAgoHYK@IyC%HLt6MX30$_ePuY{xT7#2xLdE7y6 zZ1V02?2nv5D3-mpR%VYJ*B-X=X9~4@-+C>7961fJts(zAGBMM$BS=iPw);u`lt=h9 zry7k=2gYQ6e3Uy7Z#7oVy7q>$?+zO;I@_EGjyi1+KIPzF%wqo6fAEUx(=z*0j_H#N z10-G7yN3Qyhv7^&=`YR95Z95_xYNx}_l?o6R)^hVG>T&;KDh7kyf@P^b@d|b>+=%+ zMTYasu-vHqEF|``OXm&%A<4^p_nvR&=`-rn-q^)Zpj~gKU8*T0i`{WW+`DKOSdi#l z*rO>Lq)(PKZU)-Dh7wZ>oMdh7_v1PjASV`m1!o~S&dd3DB0J{FdAU+trc+$z@V{m2 z<=gx_I!Ahms(G_hL+R49?cRM0J9`WB^ipbhlNEQ#W|i#!a|?{}qDjzp7Pyb20y`Y0+DBQv!=s+H{~lWNA2!Q9Trgc9Fat*)ub9oC zU!i_|URSf%(7x8dbEKf2e}T6QCEkEVS8ctvPKL-DM zM*jYUgn|NxjEW$U{9n=(m5Nq*><1-G6y_JX@UgmY!x6*+u8_08G-Jus1QHVFx3r3B zh%m`A1%0%^u+%m)dCzs`BT+&eJ6((^40HMT&itZ`TsHHeiagX9=V|myVQgBOCPK@{ zFqw2_)Y0YcOwjp!ehm6$1Kn@yjp9LpRzM!+tv1(F)GozkI=D)sZxg>o1gQ5~zincA zh@>;_4TKXAYTC0bhTKVa7w^P#sPcst3%XP3_qK1qYFVZoOkFmBDHCK2_ z6fbms2Hk^0L{|?^l7tE##R^_|)27xuJQpXcK=mngQ50KYGIR`m=#=#A+v&1Qd|&9Y zzr_mC=UDv&|F=Gb`$3S4Qb4$vZI>^^0P@)IVaWeJ@pAmrQB$Wl{YT~zLrBIKU&f*s z<_^Z<1mRcP-0UwMnnfJlLcxVPlAoCVfP7z>%JLP@8A_rJg>BQbh&LEaiz8o|tLi6E z%PXr~^(%gHfP866%kqcLt#W6CS?h;;h^u^<5dF$(oQhDtyN4FJn>N-E`?0mGGc$vg zPPgqVt-LP{je>!?ELAPw3LvDN#CMaqZ6fvp;ui8KTpfJ*+QHuYfhke}cg^mn*En4P zJ!fgYu|DS*#LyGw=!3%*wpXW8bM67f>FAEK7-t_(87Ui}s(*0N@m7SOV8S4>8$WP}X1_@y#i$-M4Z8Su2>eE|~K^?U1n+*C$& z5?Bct6?@p4HN?=$PZ0U9K`Bb&Hce?pfkG!az@3r587+=2`C{kE+*dub)$WSeE-9L)ibu*lG<#%pEL|6;)B6AYGPljSsh&`|; zsam*iyN;cA!VMgC2Lq8FyKhZGoC6=gU#rF6$Sx8;;-j93NR&a-;=LoB85}(|2ZzJ{ zZ@vNrFxWp#u8U3H14|@6a^ix}{mnmaY}k*>tNamh3$EGA`hg~&>B?!yQKCGX2B&Mn zNRG&+RLcgw$tq|u5}S{p&=0`2%!Ml$Q9(4L2gyRuBT>^*KDm`N{uurtCwoM7CVVDM z%k82e?!JNXhoP3HX4XT^;ouaLkeAh!%S-2dKjD>rq&LMS-kOz$c(!bWx4|XB$$^G+ zmvK}u5<^y&St9keY*g&FJ}H1UMqXE&cJsMDIZ~9C8V8VtRid8!2#uXEg0X->A>0#b z11RWX6{LU|8`ARMe^U?%)usvFYW`hM@}I-TX|Noo%;4=~LDWu-?z+v`<{E?HwG%JE zmB`9NpyLc6Tf{CC;m)&w|2+GOv%(+d_4 zQ%=P?CUrt{75A9Ily62W_k5{5^&wg3p+HW}P`9S0xmtT$3F$Mj22Fc&jb}+2 z=hY~C7_`SShG(tvZR-Z)zZXWpFqy0n116_e|T}Z=BIVl zmBxuV4a)|iN{h5#hOKVSIOVeca-*D&qqRKCX0Nro5WUWSX{W}G?E>to`g&D=YnCmv z{-!p%_Di9t%B^GS@wQ>vD~%kMZSc>rcJ2svU5$w~6}b$-rH>l3DkV+GEuORh#-*jZ zFIm1X!+#F~h#D8#&Wn>w7Y!YUJ>a(v+Wep9gzBUnVFN#kS8RRCM>adFZBVhAF~xS|Uck$KMF#WhuM}!H)Jzb{_}W~@lp^i}y|^uxAVbSF+{k8>mU@3grOuyQvw`$l zp-P*>k~kf6ASuu(di9wsk70B<>J}-DiabEecOkQex0ItAtnB8y=mjq!0RtoQe*koO BPl^Bl literal 0 HcmV?d00001 diff --git a/docs/viewlib2.gif b/docs/viewlib2.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc7ddd4a7b09463f9c5bb9d5a2168e5b52208881 GIT binary patch literal 5736 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 TpxNR86?D*AJBEh`0Lc6YpxJYi literal 0 HcmV?d00001 diff --git a/install/optcl80.dll b/install/optcl80.dll new file mode 100644 index 0000000000000000000000000000000000000000..a45c51a768b58a4dc147d5d790f684f14e33e5d2 GIT binary patch literal 204800 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

uVMh4a5|;O&0It~II}lb(!p<<~vWG?G`7DuQ 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 z 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%0A0SNsnd;{4?qSCg**8HViAW?mdEg((k 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 f3P=T{0#X5~fK)&#AQg}bNCl(8;G0Ncv literal 0 HcmV?d00001 diff --git a/install/optcl_Install.tcl b/install/optcl_Install.tcl new file mode 100644 index 0000000..0b04ace --- /dev/null +++ b/install/optcl_Install.tcl @@ -0,0 +1,88 @@ + +# OpTcl Installer +# Author: Fuzz +# fuzz@sys.uea.ac.uk + +package require registry + +set piccy ../docs/optcl_medium.gif + +set installfolder [file join [info library] .. optcl] +set installname optcl.dll + +puts "Install dir: $installfolder" +set version [info tclversion] + +if {$version < 8.0} { + tk_messageBox -message "Sorry, but OpTcl needs Tcl version 8.0.5" -type ok + exit +} elseif {$version < 8.1} { + set dll optcl80.dll +} elseif {$version < 9.0} { + set dll optclstubs.dll +} else { + tk_messageBox -message "Sorry, but OpTcl was compiled for Tcl major-version 8" -type ok +} + +image create photo optclim -file $piccy + +proc updategui {} { + global installfolder installname + if [file exists [file join $installfolder $installname]] { + .uninstall config -state normal + .install config -text "Re-install for Tcl[info tclversion]" + } else { + .uninstall config -state disabled + .install config -text "Install for Tcl[info tclversion]" + } +} + +proc install {} { + global installfolder installname dll + set answer [tk_messageBox -title {} -message "Okay to install $dll in $installfolder\nand register as OpTcl package?" -icon question -type yesno] + + switch $answer { + no {} + yes { + set bad [catch { + file mkdir $installfolder + file copy -force $dll [file join $installfolder $installname] + pkg_mkIndex -direct $installfolder + } err] + if {$bad} { + tk_messageBox -type ok -message "Error: $err" -icon error + } else { + tk_messageBox -type ok -message "OpTcl successfully installed." -icon info + } + exit + } + } +} + +proc uninstall {} { + global installfolder installname + set reply [tk_messageBox -type yesno -message "Delete package OpTcl located at $installfolder?" -icon question] + if {[string compare $reply yes] != 0} return + file delete [file join $installfolder $installname] [file join $installfolder pkgIndex.tcl] $installfolder + updategui +} + +wm title . "OpTcl Installer - F2 for console" +bind . {console show} +bind . {exit} + +label .im -image optclim -relief flat -bd 0 +button .install -text Install... -command install -width 16 -height 1 -bd 2 -font {arial 8 bold} +button .uninstall -text Uninstall -command uninstall -width 16 -height 1 -bd 2 -font {arial 8 bold} +button .quit -text Quit -command exit -bd 2 -font {arial 8 bold} -width 5 -height 1 + +grid .im -column 0 -row 0 -rowspan 2 -padx 2 -pady 2 +grid .install -column 1 -row 0 -padx 2 -pady 2 -sticky nsew +grid .uninstall -column 2 -row 0 -padx 2 -pady 2 -sticky nsew +grid .quit -column 1 -row 1 -columnspan 2 -padx 2 -pady 2 -sticky nsew + + +wm resizable . 0 0 +updategui +raise . +focus -force . diff --git a/install/optclstubs.dll b/install/optclstubs.dll new file mode 100644 index 0000000000000000000000000000000000000000..516434b01076ebc7afea0f1189e12aa5a1d10100 GIT binary patch literal 745539 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 z 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�AinKfh{y_GycE&orrHTEN2| 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 F{1>?L{^$Sz literal 0 HcmV?d00001 diff --git a/src/Container.cpp b/src/Container.cpp new file mode 100644 index 0000000..b9de8d5 --- /dev/null +++ b/src/Container.cpp @@ -0,0 +1,569 @@ +/* + *------------------------------------------------------------------------------ + * container.cpp + * Implementation of the CContainer class, providing functionality for + * a Tk activex container widget. + * 1999-01-26 created + * 1999-08-25 modified for use in Optcl + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + + + +#include "stdafx.h" +#include "tbase.h" +#include "optcl.h" +#include "utility.h" +#include "Container.h" +#include "optclobj.h" + + + +const char * CContainer::m_propname = "container"; + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +/* + *------------------------------------------------------------------------- + * CContainer::CContainer() -- + * Constructor + * Result: + * None + * Side effects: + * Members set to default values - initial height and width information + * stored here. + *------------------------------------------------------------------------- + */ +CContainer::CContainer(OptclObj *parent) : +m_tkWindow(NULL), +m_widgetCmd(NULL), +m_pInterp(NULL), +m_height(200), +m_width(200), +m_windowproc(NULL), +m_bDestroyPending(false), +m_optclobj(parent) +{ + ASSERT (parent != NULL); +} + +/* + *------------------------------------------------------------------------- + * CContainer::~CContainer() -- + * Destructor + * Result: + * None + * Side effects: + * Tk window is requested to be destroyed. + * COM resources release (except for the control container which is release + * when the Tk window is actually destroyed. + *------------------------------------------------------------------------- + */ + +CContainer::~CContainer() +{ + // close down the references to the object + m_bDestroyPending = true; + m_pUnk.Release(); + m_pObj.Release(); + m_pSite.Release(); + m_pInPlaceObj.Release(); + m_pOleWnd.Release(); + m_pUnkHost.Release(); + + if (m_widgetCmd != NULL) { + if (!Tcl_InterpDeleted(m_pInterp)) + Tcl_DeleteCommandFromToken (m_pInterp, m_widgetCmd); + m_widgetCmd = NULL; + } + + if (m_tkWindow != NULL) + { + // remove the subclass + SetWindowLong (m_hTkWnd, GWL_WNDPROC, (LONG)m_windowproc); + RemoveProp (m_hTkWnd, m_propname); + Tk_DestroyWindow (m_tkWindow); + m_tkWindow = NULL; + } + +} + +/* + *------------------------------------------------------------------------- + * CContainer::ContainerEventProc -- + * Called by Tk to process events + * Result: + * None + * Side effects: + * Lifetime and size of widget affected - focus model needs working on! + *------------------------------------------------------------------------- + */ +void CContainer::ContainerEventProc (ClientData cd, XEvent *pEvent) +{ + CContainer *pContainer = (CContainer *)cd; + SIZEL s, hm; + RECT r; + + switch (pEvent->type) + { + case Expose: + // Nothing required as the AxAtl window + // should receive its own exposure event + break; + case FocusIn: + if (pContainer->m_pSite) + pContainer->m_pSite->OnFocus(TRUE); + /* + hControl = ::GetWindow (pContainer->m_hTkWnd, GW_CHILD); + if (hControl) + ::SetFocus(hControl); + */ + + break; + case ConfigureNotify: + s.cx = Tk_Width(pContainer->m_tkWindow); + s.cy = Tk_Height(pContainer->m_tkWindow); + r.left = r.top = 0; + r.right = s.cx; + r.bottom = s.cy; + + + AtlPixelToHiMetric(&s, &hm); + if (pContainer->m_pObj) + pContainer->m_pObj->SetExtent(DVASPECT_CONTENT, &hm); + if (pContainer->m_pInPlaceObj) + pContainer->m_pInPlaceObj->SetObjectRects (&r, &r); + + break; + case DestroyNotify: + if (!pContainer->m_bDestroyPending) { + Tcl_EventuallyFree(cd, DeleteContainer); + pContainer->m_tkWindow = NULL; + } + break; + + + default: + break; + } + +} + +/* + *------------------------------------------------------------------------- + * CContainer::DeleteContainer -- + * Called by ContainerEventProc, when the Tk_Window is about to be + * destroyed by scripting. + * Result: + * None + * Side effects: + * Memory deallocated + *------------------------------------------------------------------------- + */ +void CContainer::DeleteContainer (char *pObject) +{ + CContainer *pContainer = (CContainer*)pObject; + pContainer->m_optclobj->ContainerWantsToDie(); +} + + + +/* + *------------------------------------------------------------------------- + * CContainer::Create -- + * Called by the related object in order to create the window. + * tkParent in a parent of the window to be created. The string + * pointed to by 'id' is the clsid/progid/documentpath of this object. + * + * Result: + * NULL iff failed to be created (pInterp will store descriptive result) + * + * Side effects: + * Depends on object being created. + *------------------------------------------------------------------------- + */ +IUnknown * CContainer::Create (Tcl_Interp *pInterp, Tk_Window tkParent, + const char * widgetpath, const char *id) +{ + m_pInterp = pInterp; + char *path; + if (TCL_ERROR == CreateTkWindow (tkParent, (char*)widgetpath)) + return NULL; + + path = Tk_PathName(m_tkWindow); + + Tcl_VarEval (pInterp, "winfo id ", path, (char*)NULL); + + int iParent; + Tcl_GetIntFromObj (pInterp, Tcl_GetObjResult (pInterp), &iParent); + m_hTkWnd = (HWND) iParent; + SetProp (m_hTkWnd, m_propname, (HANDLE)this); + + if (!CreateControl(pInterp, id)) + return NULL; + + InitFromObject (); + + + // subclass this window (once again, since ATL has already hooked it), in order + // to correctly handle mouse messages and destruction + m_windowproc = SetWindowLong (m_hTkWnd, GWL_WNDPROC, (LONG)WidgetSubclassProc); + + // Set up the height and width accordingly + Tk_GeometryRequest (m_tkWindow, m_width, m_height); + + + m_widgetCmd = Tcl_CreateObjCommand (m_pInterp, path, WidgetCmd, + (ClientData)this, NULL); + + Tcl_SetResult (m_pInterp, path, TCL_STATIC); + return m_pUnk; +} + + + + +/* + *------------------------------------------------------------------------- + * CContainer::WidgetCmd -- + * Static class method that is called by Tcl when invoking the widget + * command. + * Result: + * TCL_OK if command execute ok; else TCL_ERROR + * Side effects: + * Dependant on the subcommand + *------------------------------------------------------------------------- + */ +int CContainer::WidgetCmd ( ClientData cd, Tcl_Interp *pInterp, int objc, + Tcl_Obj *CONST objv[] ) +{ + if (objc < 2) { + Tcl_AppendResult (pInterp, "wrong # args: should be \"", + Tcl_GetStringFromObj (objv[0], NULL), " option ?arg arg ...?\"", (char*)NULL); + return TCL_ERROR; + } + char *szCommand = Tcl_GetStringFromObj(objv[1], NULL); + int nLength = strlen(szCommand); + CContainer *pWidget = (CContainer*)cd; + + if (strncmp (szCommand, "configure", nLength) == 0) { + switch (objc) { + case 2: + return pWidget->ConfigInfo (pInterp); + break; + case 3: + return pWidget->ConfigInfo (pInterp, Tcl_GetStringFromObj(objv[2], NULL)); + break; + default: + return pWidget->ConfigInfo (pInterp, objc - 2, objv + 2); + break; + } + } + + if (strncmp (szCommand, "cget", nLength) == 0) { + if (objc == 3) { + return pWidget->ConfigInfo (pInterp, Tcl_GetStringFromObj(objv[2], NULL)); + } else { + Tcl_AppendResult (pInterp, "wrong # args: should be \"", + Tcl_GetStringFromObj (objv[0], NULL), " cget arg\"", (char*)NULL); + return TCL_ERROR; + } + } + + Tcl_AppendResult (pInterp, "urecognised command: ", szCommand, (char*)NULL); + return TCL_ERROR; +} + +/* + *------------------------------------------------------------------------- + * CContainer::ConfigInfo (Tcl_Interp *pInterp) -- + * Overloaded method that returns the value of all configuration options + * for the widget + * Result: + * TCL_OK + * Side effects: + * New Tcl result + *------------------------------------------------------------------------- + */ +int CContainer::ConfigInfo (Tcl_Interp *pInterp) +{ + Tcl_DString dstring; + Tcl_DStringInit(&dstring); + + Tcl_ResetResult(pInterp); + ConfigInfo (pInterp, "-width"); + Tcl_DStringAppendElement(&dstring, Tcl_GetStringResult (pInterp)); + + Tcl_ResetResult(pInterp); + ConfigInfo (pInterp, "-height"); + Tcl_DStringAppendElement(&dstring, Tcl_GetStringResult (pInterp)); + + Tcl_SetResult(pInterp, dstring.string, TCL_VOLATILE); + Tcl_DStringFree(&dstring); + return TCL_OK; +} + +/* + *------------------------------------------------------------------------- + * CContainer::ConfigInfo (Tcl_Interp *pInterp, char *pProperty) -- + * Overloaded method that provides the value of a given configuration + * option. + * Result: + * TCL_OK iff configuration option exists; else TCL_ERROR + * Side effects: + * New Tcl result. + *------------------------------------------------------------------------- + */ +int CContainer::ConfigInfo (Tcl_Interp *pInterp, char *pProperty) +{ + bool bFound = false; + if (strcmp(pProperty, "-width")==0) { + bFound = true; + Tcl_SetObjResult (pInterp, Tcl_NewIntObj (m_width)); + } + + else if (strcmp(pProperty, "-height")==0) { + bFound = true; + Tcl_SetObjResult (pInterp, Tcl_NewIntObj (m_height)); + } + + else if (strcmp(pProperty, "-takefocus")==0) { + bFound = true; + Tcl_SetObjResult (pInterp, Tcl_NewBooleanObj(1)); + } + + if (!bFound) { + Tcl_ResetResult (pInterp); + Tcl_AppendResult (pInterp, "unknown option \"", pProperty, (char*)NULL); + return TCL_ERROR; + } + return TCL_OK; +} + +/* + *------------------------------------------------------------------------- + * CContainer::ConfigInfo (Tcl_Interp *pInterp, int objc, Tcl_Obj *CONST pArgs[]) -- + * Overloaded method; used to set the value of a number of options + * Result: + * TCL_OK iff all specified options are set ok; else TCL_ERROR + * Side effects: + * Change in options may have an effect on the size and viewing of the + * widget + *------------------------------------------------------------------------- + */ +int CContainer::ConfigInfo (Tcl_Interp *pInterp, int objc, Tcl_Obj *CONST pArgs[]) +{ + if (objc % 2 == 0) + { + bool bChanged = false; + for (int i = 0; i < objc; i += 2) { + if (SetProperty (pInterp, pArgs[i], pArgs[i+1], bChanged) != TCL_OK) + return TCL_ERROR; + } + if (bChanged) + { + Tk_GeometryRequest(m_tkWindow, m_width, m_height); + } + return TCL_OK; + } + else // # of values != # of options + { + char *szLast = Tcl_GetStringFromObj(pArgs[objc-1], NULL); + Tcl_ResetResult(pInterp); + Tcl_AppendResult (pInterp, "unknown option \"", szLast, "\"", (char*)NULL); + return TCL_ERROR; + } +} + +/* + *------------------------------------------------------------------------- + * CContainer::SetProperty -- + * Sets a single option with a new value. + * Result: + * TCL_OK iff option set ok; else TCL_ERROR + * Side effects: + * Size and other viewing factors may change for widget + *------------------------------------------------------------------------- + */ +int CContainer::SetProperty (Tcl_Interp *pInterp, Tcl_Obj *pProperty, Tcl_Obj *pValue, bool &bChanged) +{ + char *szProperty = Tcl_GetStringFromObj (pProperty, NULL); + int value; + + if (strcmp(szProperty, "-width")==0) { + if (Tcl_GetIntFromObj (pInterp, pValue, &value) == TCL_ERROR) + return TCL_ERROR; + m_width = abs(value); + bChanged = true; + } + + else if (strcmp(szProperty, "-height")==0) { + if (Tcl_GetIntFromObj (pInterp, pValue, &value) == TCL_ERROR) + return TCL_ERROR; + m_height = abs(value); + bChanged = true; + } + + else { + Tcl_ResetResult (pInterp); + Tcl_AppendResult (pInterp, "unknown option \"", szProperty, (char*)NULL); + return TCL_ERROR; + } + + return TCL_OK; +} + +/* + *------------------------------------------------------------------------- + * CContainer::WidgetSubclassProc -- + * This is used to subclass the main window to handle proper forwarding + * of mouse capture, release of the control container, and the release of + * OLE resources. + * Result: + * The return of the subclassed window procedure + * Side effects: + * Mouse capture affected - COM interfaces destroyed, OLE uninitialised by one + *------------------------------------------------------------------------- + */ +LRESULT CALLBACK CContainer::WidgetSubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + CContainer *pContainer = (CContainer*) GetProp (hwnd, m_propname); + if (pContainer == NULL) return 0; + WORD fwEvent = LOWORD (wParam); + WORD idChild = HIWORD (wParam); + HWND hCurrentFocus = GetFocus(); + + switch (uMsg) { + case WM_MOUSEACTIVATE: + return MA_ACTIVATE; + break; + + case WM_NCCREATE: + pContainer->m_pHost.Release(); + break; + } + + return CallWindowProc ((WNDPROC)(pContainer->m_windowproc), hwnd, uMsg, wParam, lParam); +} + + +/* + *------------------------------------------------------------------------- + * CContainer::InitFromObject -- + * Initialises interface pointers to the underlying control, and site + * Result: + * None + * Side effects: + * COM memory allocation of vtables etc. + *------------------------------------------------------------------------- + */ +void CContainer::InitFromObject () +{ + AtlAxGetControl(m_hTkWnd, &m_pUnk); + m_pObj = m_pUnk; + m_pInPlaceObj = m_pUnk; + m_pOleWnd = m_pUnk; + m_pSite = m_pUnkHost; +} + + +/* + *------------------------------------------------------------------------- + * CContainer::CreateTkWindow -- + * Called by the Create member function to create the Tk window + * Result: + * returns TCL_OK iff window created + * Side effects: + * + *------------------------------------------------------------------------- + */ +int CContainer::CreateTkWindow(Tk_Window tkParent, char *path) +{ + // create the window, specifying that it is a child + m_tkWindow = Tk_CreateWindowFromPath(m_pInterp, tkParent, path, NULL); + if (m_tkWindow == NULL) + return TCL_ERROR; + + Tk_SetClass(m_tkWindow, "Container"); + m_tkDisplay = Tk_Display(m_tkWindow); + + Tk_CreateEventHandler (m_tkWindow, + StructureNotifyMask | + ExposureMask | + FocusChangeMask, + ContainerEventProc, (ClientData)this); + + Tk_MakeWindowExist(m_tkWindow); + return TCL_OK; +} + + + +/* + *------------------------------------------------------------------------- + * CContainer::CreateControl -- + * Using Atl, creates the control. Ensures that the children of the + * control can be navigated with the keyboard. + * + * Result: + * true iff succeeded. pInterp will hold a description of the error. + * + * Side effects: + * Depends on the object being created + *------------------------------------------------------------------------- + */ +bool CContainer::CreateControl (Tcl_Interp *pInterp, const char *id) +{ + USES_CONVERSION; + HRESULT hr = E_FAIL; + HWND hWndChild; + LPOLESTR oleid = A2OLE(id); + + hr = AtlAxCreateControl (oleid, m_hTkWnd, NULL, &m_pUnkHost); + if (FAILED(hr)) + goto error; + + m_pHost = m_pUnkHost; + + if (m_pHost == NULL) { + hr = E_NOINTERFACE; + goto error; + } + + + // check for control parent style if control has a window + hWndChild = ::GetWindow(m_hTkWnd, GW_CHILD); + if(hWndChild != NULL) + { + if(::GetWindowLong(hWndChild, GWL_EXSTYLE) & WS_EX_CONTROLPARENT) + { + DWORD dwExStyle = ::GetWindowLong(m_hTkWnd, GWL_EXSTYLE); + dwExStyle |= WS_EX_CONTROLPARENT; + ::SetWindowLong(m_hTkWnd, GWL_EXSTYLE, dwExStyle); + } + } + return true; +error: + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_STATIC); + return false; +} + + + diff --git a/src/Container.h b/src/Container.h new file mode 100644 index 0000000..85fda55 --- /dev/null +++ b/src/Container.h @@ -0,0 +1,90 @@ +/* + *------------------------------------------------------------------------------ + * container.cpp + * Declaration of the CContainer class, providing functionality for + * a Tk activex container widget. + * 1999-01-26 created + * 1999-08-25 modified for use in Optcl + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#if !defined(AFX_CONTAINER_H__C07038C0_9445_11D2_86E7_0000B482A708__INCLUDED_) +#define AFX_CONTAINER_H__C07038C0_9445_11D2_86E7_0000B482A708__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +class OptclObj; + + +class CContainer +{ +public: // constructors + CContainer(OptclObj *pObj); + virtual ~CContainer(); + +public: // non-static methods + IUnknown * Create (Tcl_Interp *pInterp, Tk_Window tkParent, const char * path, const char *id); + +public: // static methods + static void ContainerEventProc (ClientData cd, XEvent *pEvent); + static void DeleteContainer (char *pObject); + static LRESULT CALLBACK WidgetSubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +protected: // static methods + static int WidgetCmd (ClientData cd, Tcl_Interp *pInterp, int objc, Tcl_Obj *CONST objv[]); + +protected: // non-static methods + int ConfigInfo (Tcl_Interp *pInterp); + int ConfigInfo (Tcl_Interp *pInterp, char *pProperty); + int ConfigInfo (Tcl_Interp *pInterp, int objc, Tcl_Obj *CONST pArgs[]); + int SetProperty (Tcl_Interp *pInterp, Tcl_Obj *pProperty, Tcl_Obj *pValue, bool &bChanged); + bool CreateControl (Tcl_Interp *pInterp, const char *id); + void InitFromObject (); + int CreateTkWindow(Tk_Window tkParent, char *path); + +protected: // members variables + Tk_Window m_tkWindow; + Tcl_Interp * m_pInterp; + Display * m_tkDisplay; + Tcl_Command m_widgetCmd; + HWND m_hTkWnd; + DWORD m_height; + DWORD m_width; + LONG m_windowproc; + bool m_bDestroyPending; + OptclObj * m_optclobj; + + // Com pointers + CComPtr m_pUnk; // pointer to the contained object + CComPtr m_pUnkHost; // pointer to the host IUnknown + + // QI ptrs that have the IDD-templatised versions + CComQIPtr m_pObj; + CComQIPtr m_pInPlaceObj; + CComQIPtr m_pOleWnd; + CComQIPtr m_pSite; + CComQIPtr m_pHost; // pointer to the host (client site) object +protected: // static member variables + + static const char * m_propname; +}; + +#endif // !defined(AFX_CONTAINER_H__C07038C0_9445_11D2_86E7_0000B482A708__INCLUDED_) diff --git a/src/DispParams.cpp b/src/DispParams.cpp new file mode 100644 index 0000000..8573c8c --- /dev/null +++ b/src/DispParams.cpp @@ -0,0 +1,191 @@ +/* + *------------------------------------------------------------------------------ + * dispparams.cpp + * Implementation of the DispParams class, a wrapper for the DISPPARAMS + * Automation type. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#include "stdafx.h" +#include "tbase.h" +#include "optcl.h" +#include "DispParams.h" +#include "utility.h" + + + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +/* + *------------------------------------------------------------------------- + * DispParams::DispParams -- + * Constructor - nulls out everything. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +DispParams::DispParams() +{ + rgvarg = NULL; + rgdispidNamedArgs = NULL; + cArgs = 0; + cNamedArgs = 0; +} + +/* + *------------------------------------------------------------------------- + * DispParams::~DispParams -- + * Destructor - releases internal data. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +DispParams::~DispParams() +{ + Release(); +} + +/* + *------------------------------------------------------------------------- + * DispParams::Release -- + * Releases all allocated variants. Nulls out the DISPPARAMS structure. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void DispParams::Release () +{ + // start releasing the variants + for (UINT i = 0; i < cArgs; i++) + { + ASSERT (rgvarg != NULL); + OptclVariantClear (rgvarg+i); + } + + delete_ptr (rgvarg); + delete_ptr (rgdispidNamedArgs); + cArgs = 0; + cNamedArgs = 0; +} + + + +/* + *------------------------------------------------------------------------- + * DispParams::Args -- + * Sets up the number of arguments, both name and unnamed. + * + * Result: + * None. + * + * Side effects: + * Allocates enough memory for the dispatch id's of the named arguments. + * + *------------------------------------------------------------------------- + */ +void DispParams::Args (UINT args, UINT named) +{ + UINT i; + + Release(); + if (args > 0) + { + rgvarg = new VARIANTARG[args]; + for (i = 0; i < args; i++) + VariantInit(rgvarg+i); + cArgs = args; + } + + if (named > 0) + { + rgdispidNamedArgs = new DISPID[named]; + for (i = 0; i < named; i++) + rgdispidNamedArgs[i] = DISPID_UNKNOWN; + cNamedArgs = named; + } +} + +/* + *------------------------------------------------------------------------- + * DispParams::SetDISPID -- + * Sets the dispatch id of a named arguments. The argument is accessed using + * the index 'named'. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void DispParams::SetDISPID (UINT named, DISPID id) +{ + ASSERT (named < cNamedArgs); + rgdispidNamedArgs[named] = id; +} + + +/* + *------------------------------------------------------------------------- + * DispParams::operator[] -- + * operator to get direct access to an argument at a certain index. + * + * Result: + * A reference to the argument. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +VARIANTARG &DispParams::operator[] (UINT arg) +{ + ASSERT (arg < cArgs); + return rgvarg[arg]; +} + + + + +/* + *------------------------------------------------------------------------- + * DispParams::Set -- + * + * Result: + * + * Side effects: + * + *------------------------------------------------------------------------- + */ +void DispParams::Set (UINT index, VARIANT * pv) +{ + ASSERT (pv != NULL); + ASSERT (index < cArgs); + + V_VARIANTREF(rgvarg + index) = pv; + V_VT(rgvarg + index) = VT_VARIANT|VT_BYREF; +} diff --git a/src/DispParams.h b/src/DispParams.h new file mode 100644 index 0000000..0827cbc --- /dev/null +++ b/src/DispParams.h @@ -0,0 +1,71 @@ +/* + *------------------------------------------------------------------------------ + * dispparams.h + * Declaration of the DispParams class, a wrapper for the DISPPARAMS + * Automation type. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#if !defined(AFX_DISPPARAMS_H__BF3EF6CA_73B0_11D4_8004_0040055861F2__INCLUDED_) +#define AFX_DISPPARAMS_H__BF3EF6CA_73B0_11D4_8004_0040055861F2__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + + +class DispParams : public DISPPARAMS +{ +public: + DispParams(); + virtual ~DispParams(); + + void Release (); + void Args (UINT args, UINT named = 0); + void SetDISPID (UINT named, DISPID id); + VARIANTARG &operator[] (UINT arg); + + + /* + *------------------------------------------------------------------------- + * Set -- + * Template function that sets the value of a variant at index 'index' + * to a template-type value. This works because the type T should have + * an appropriate casting operator to fit those of VC6's _variant_t + * Result: + * None. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ + template void Set (UINT index, T value) + { + _variant_t t; + VARIANTARG *pref = &(operator[](index)); + t.Attach (*pref); + t = value; + *pref = t.Detach(); + } + + void Set (UINT index, VARIANT * pv); +}; + +#endif // !defined(AFX_DISPPARAMS_H__BF3EF6CA_73B0_11D4_8004_0040055861F2__INCLUDED_) + diff --git a/src/EventBinding.cpp b/src/EventBinding.cpp new file mode 100644 index 0000000..d8a12bd --- /dev/null +++ b/src/EventBinding.cpp @@ -0,0 +1,612 @@ +/* + *------------------------------------------------------------------------------ + * eventbinding.cpp + * Declares classes used for implementing OpTcl's event binding. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#include "stdafx.h" +#include "tbase.h" +#include "EventBinding.h" +#include "optcl.h" +#include "utility.h" +#include "objmap.h" +#include "typelib.h" +#include "optclbindptr.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +/* + *------------------------------------------------------------------------- + * EventNotFound -- + * Writes a standard error message to the interpreter, indicating + * that an event was not found. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void EventNotFound (Tcl_Interp *pInterp, const char * event) +{ + Tcl_SetResult (pInterp, "event not found: ", TCL_STATIC); + Tcl_AppendResult (pInterp, (char*) event, NULL); +} + + +/* + *------------------------------------------------------------------------- + * EventBindings::EventBindings -- + * Constructor - caches the parameters, and attempts to bind to ITypeComp + * interface. If not found, throw an HRESULT. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +EventBindings::EventBindings(OptclObj *pObj, REFGUID guid, ITypeInfo *pInfo) +: m_ref(0), m_bindings(0), m_cookie(0) +{ + ASSERT (pInfo!= NULL); + ASSERT (pObj != NULL); + + HRESULT hr; + + m_pti = pInfo; + m_optclobj = pObj; + m_guid = guid; + + hr = m_pti->GetTypeComp(&m_ptc); + CHECKHR(hr); + ASSERT (m_ptc != NULL); +} + + +/* + *------------------------------------------------------------------------- + * EventBindings::~EventBindings -- + * Destructor - ensures that any event bindings within this object + * are deleted. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +EventBindings::~EventBindings() +{ + DeleteTbl(); +} + + + +/* + *------------------------------------------------------------------------- + * EventBindings::DeleteTbl -- + * Iterates through the command table, and deletes each object + * before finally deleting the hash table. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void EventBindings::DeleteTbl() +{ + DispCmdTbl::iterator i; + TObjPtr p; + + for (i = m_cmdtbl.begin(); i != m_cmdtbl.end(); i++) + { + BindingProps *p = *i; + ASSERT (p != NULL); + delete p; + } + m_cmdtbl.deltbl(); + m_bindings = 0; +} + + + + +// IUnknown Entries +/* + *------------------------------------------------------------------------- + * EventBindings::QueryInterface -- + * Implements the IUnknown member. Successfull iff riid is for IUnknown, + * IDispatch, or the event interface that we're implementing. + * + * Result: + * Standard COM result. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +HRESULT STDMETHODCALLTYPE EventBindings::QueryInterface(REFIID riid, void ** ppvObject) +{ + HRESULT hr = S_OK; + if (riid == IID_IUnknown) + *ppvObject = (IUnknown*)this; + else if (riid == IID_IDispatch || riid == m_guid) + *ppvObject = (IDispatch*)this; + else + hr = E_NOINTERFACE; + if (SUCCEEDED(hr)) + AddRef(); + + return hr; +} + + + + + +/* + *------------------------------------------------------------------------- + * EventBindings::AddRef -- + * Implements the IUnknown member. + * Result: + * Standard AddRef result. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +ULONG STDMETHODCALLTYPE EventBindings::AddRef( void) +{ + return InterlockedIncrement (&m_ref); +} + + + + + +/* + *------------------------------------------------------------------------- + * EventBindings::Release -- + * Implements the IUnknown member. In fact, this never deletes this object + * That responsibility is always with the optcl object. I am not sure + * if this approach is a good one. So beware! :o + * + * Result: + * Standard Release result. + * Side effects: + * None, what so ever. + *------------------------------------------------------------------------- + */ +ULONG STDMETHODCALLTYPE EventBindings::Release( void) +{ + // a dummy function + if (InterlockedDecrement (&m_ref) <= 0) + m_ref = 0; + return m_ref; +} + + + + + +// IDispatch Entries +/* + *------------------------------------------------------------------------- + * EventBindings::GetTypeInfoCount -- + * Implements the IDispatch member. 1 if we did get a type info. The + * check isn't necessary at all, but I've put it there just as a reminder. + * Result: + * S_OK always. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +HRESULT STDMETHODCALLTYPE EventBindings::GetTypeInfoCount(UINT *pctinfo) +{ + ASSERT (m_pti != NULL); + *pctinfo = (m_pti!=NULL)?1:0; + return S_OK; +} + + + + + + +/* + *------------------------------------------------------------------------- + * EventBindings::GetTypeInfo -- + * Implements the IDispatch member. Standard stuff. + * Result: + * Standard GetTypeInfo result. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +HRESULT STDMETHODCALLTYPE +EventBindings::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo ** ppTInfo) +{ + ASSERT (lcid == LOCALE_SYSTEM_DEFAULT); + HRESULT hr = S_OK; + if (iTInfo != 0 || m_pti == NULL || ppTInfo == NULL) + hr = DISP_E_BADINDEX; + else { + (*ppTInfo) = m_pti; + (*ppTInfo)->AddRef(); + } + return hr; +} + + + + + +/* + *------------------------------------------------------------------------- + * EventBindings::GetIDsOfNames -- + * Standard IDispatch member. Passes on the responsiblity to the type + * library. + * Result: + * Standard com result. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +HRESULT STDMETHODCALLTYPE +EventBindings::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, + UINT cNames, LCID lcid, DISPID *rgDispId) +{ + HRESULT hr = S_OK; + if (m_pti == NULL) + hr = DISP_E_UNKNOWNNAME; + if (lcid != LOCALE_SYSTEM_DEFAULT) + hr = DISP_E_UNKNOWNLCID; + else + hr = DispGetIDsOfNames (m_pti, rgszNames, cNames, rgDispId); + return hr; +} + + + + + +/* + *------------------------------------------------------------------------- + * EventBindings::Invoke -- + * Called by the event source when an event is raised. Attempts to + * find event in the event table. If not bound yet, simply returns, + * otherwise, asks the binding to be evaluated. + * Result: + * S_OK iff succeeded. If error and an exception info struct is available, + * then it is filled out. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +HRESULT STDMETHODCALLTYPE +EventBindings::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, + WORD wFlags, DISPPARAMS *pDispParams, LPVARIANT pVarResult, + LPEXCEPINFO pExcepInfo, UINT *puArgErr) +{ + if (pDispParams == NULL) + return E_FAIL; + + // look up the dispatch id in our table. + BindingProps *bp = NULL; + + + + if (m_cmdtbl.find((DISPID*)dispIdMember, &bp) != NULL) + { + ASSERT (bp != NULL); + int res = bp->Eval(m_optclobj, pDispParams, pVarResult, pExcepInfo); + if (res == TCL_ERROR) { + if (pExcepInfo == NULL) + return E_FAIL; + else + return DISP_E_EXCEPTION; + } + } + return S_OK; +} + + + +/* + *------------------------------------------------------------------------- + * EventBindings::Name2Dispid -- + * Binds a string name to a dispatch id in the implemented event interface. + * + * Result: + * true iff successful. pInterp will contain the error string if not. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool EventBindings::Name2Dispid (Tcl_Interp *pInterp, const char * name, DISPID &dispid) +{ + ASSERT (pInterp != NULL && name != NULL && m_ptc != NULL); + + USES_CONVERSION; + LPOLESTR olename; + HRESULT hr; + OptclBindPtr obp; + bool bOk = false; + + olename = A2OLE (name); + + try { + hr = m_ptc->Bind (olename, LHashValOfName(LOCALE_SYSTEM_DEFAULT, olename), + INVOKE_FUNC, &obp.m_pti, &obp.m_dk, &obp.m_bp); + CHECKHR(hr); + + if (obp.m_dk == DESCKIND_FUNCDESC) { + ASSERT (obp.m_bp.lpfuncdesc != NULL); + dispid = obp.m_bp.lpfuncdesc->memid; + bOk = true; + } else + EventNotFound(pInterp, name); + } + catch (HRESULT hr) { + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + } + + return bOk; +} + +/* + *------------------------------------------------------------------------- + * EventBindings::TotalBindings -- + * Returns the total number of even bindings in this collection. + * Result: + * The count. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +ULONG EventBindings::TotalBindings () +{ + return m_bindings; +} + + +/* + *------------------------------------------------------------------------- + * EventBindings::SetBinding -- + * Attempts to bind an event, give by name, to a tcl command (a tcl object) + * + * Result: + * true iff successful. Else, error string in interpreter. + * Side effects: + * Changes the count of the number of bindings. + *------------------------------------------------------------------------- + */ +bool EventBindings::SetBinding (Tcl_Interp *pInterp, const char * name, Tcl_Obj *pCommand) +{ + ASSERT (pInterp != NULL && name != NULL && pCommand != NULL); + + DISPID dispid; + + if (!Name2Dispid (pInterp, name, dispid)) + return false; + + BindingProps *pbp = NULL; + if (!m_cmdtbl.find ((DISPID*)(dispid), &pbp)) { + pbp = new BindingProps (pInterp, pCommand); + m_cmdtbl.set ((DISPID*)(dispid), pbp); + m_bindings++; + } else { + ASSERT (pbp != NULL); + pbp->m_pInterp = pInterp; + pbp->m_pScript = pCommand; + } + return true; +} + + + +/* + *------------------------------------------------------------------------- + * EventBindings::GetBinding -- + * Returns within the interpreter the tcl command bound to an event. + * Result: + * true iff successful. Else, error string in interpreter. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool EventBindings::GetBinding (Tcl_Interp *pInterp, const char * name) +{ + ASSERT (pInterp != NULL && name != NULL); + DISPID dispid; + + if (!Name2Dispid (pInterp, name, dispid)) + return false; + + + BindingProps *pbp = NULL; + if (m_cmdtbl.find ((DISPID*)(dispid), &pbp)) { + ASSERT (pbp != NULL); + Tcl_SetObjResult (pInterp, pbp->m_pScript); + } + return true; +} + + +/* + *------------------------------------------------------------------------- + * EventBindings::DeleteBinding -- + * Removes an event binding. + * Result: + * false iff 'name' is not the name of an existing event. + * Side effects: + * Changes the count of the number of bindings. + *------------------------------------------------------------------------- + */ +bool EventBindings::DeleteBinding (Tcl_Interp *pInterp, const char * name) +{ + ASSERT (pInterp != NULL && name != NULL); + DISPID dispid; + + if (!Name2Dispid (pInterp, name, dispid)) + return false; + BindingProps *pbp = NULL; + if (m_cmdtbl.find ((DISPID*)(dispid), &pbp)) { + ASSERT (pbp != NULL); + delete pbp; + m_cmdtbl.delete_entry ((DISPID*)(dispid)); + m_bindings--; + } + return true; +} + + +/* + *------------------------------------------------------------------------- + * BindingProps::Eval -- + * The guts of the event handler. Pulls out the parameters (in reverse order) + * and invokes that on the registered tcl handler. Note that the command + * line will look like: + * handler objid ?arg ...? + * where objid is the optcl identifier of the activex object that created + * the event. + * + * Result: + * Standard Tcl Result. + * + * Side effects: + * Depends on the tcl handler. + *------------------------------------------------------------------------- + */ +int BindingProps::Eval (OptclObj *pObj, DISPPARAMS *pDispParams, LPVARIANT pVarResult, + LPEXCEPINFO pExcepInfo) +{ + ASSERT (m_pInterp != NULL && m_pScript.isnotnull()); + ASSERT (pDispParams != NULL); + ASSERT (pObj != NULL); + + OptclObj ** ppObjs = NULL; + + TObjPtr cmd; + UINT count; + int result = TCL_ERROR; + + cmd.copy(m_pScript); + cmd.lappend ((const char*)(*pObj)); // cast to a string + + ASSERT (pDispParams->cNamedArgs == 0); + + // potentially all the parameters could result in an object, so + // allocate an array and set it all to nulls. + if (pDispParams->cArgs > 0) { + ppObjs = (OptclObj**)calloc(pDispParams->cArgs, sizeof (OptclObj*)); + if (ppObjs == NULL) { + Tcl_SetResult (m_pInterp, "failed to allocate memory", TCL_STATIC); + Tcl_BackgroundError (m_pInterp); + return TCL_ERROR; + } + } + + // temporarily increase the reference count on the object + // this way, if the event handler unlocks the objects, a possible + // destruction doesn't occur until this event has been handled + g_objmap.Lock (pObj); + + try { + // convert the dispatch parameters into Tcl arguments + for (count = 0; count < pDispParams->cArgs; count++) + { + TObjPtr param; + if (!var2obj(m_pInterp, pDispParams->rgvarg[pDispParams->cArgs - count - 1], param, ppObjs+count)) + break; + cmd.lappend(param, m_pInterp); + } + } + + // the error will already be stored in the interpreter + catch (char *) { + } + + + // if we managed to convert all the parameters, invoke the function + if (count == pDispParams->cArgs) + result = Tcl_GlobalEvalObj (m_pInterp, cmd); + + + + // deallocate the objects + for (count = 0; count < pDispParams->cArgs; count++) + { + if (ppObjs[count] != NULL) + g_objmap.Unlock (ppObjs[count]); + } + + // release the object pointers + if (ppObjs != NULL) + free (ppObjs); + + if (result == TCL_ERROR) + { + // do we have a exception storage + if (pExcepInfo != NULL) + { + // fill it in + _bstr_t src(Tcl_GetStringResult(m_pInterp)); + _bstr_t name("OpTcl"); + pExcepInfo->wCode = 1001; + pExcepInfo->wReserved = 0; + pExcepInfo->bstrSource = name.copy(); + pExcepInfo->bstrDescription = src.copy(); + pExcepInfo->bstrHelpFile = NULL; + pExcepInfo->pvReserved = NULL; + pExcepInfo->pfnDeferredFillIn = NULL; + } + Tcl_BackgroundError (m_pInterp); + } + else + { + // get the Tcl result and store it in the result variant + // currently we are limited to the basic types, until + // I get the time to pull the typelib stuff to this point + if (pVarResult != NULL) + { + TObjPtr pres(Tcl_GetObjResult (m_pInterp), false); + VariantInit(pVarResult); + obj2var (pres, *pVarResult); + } + } + + // finally unlock the object + g_objmap.Unlock (pObj); + return result; +} + + + + + + + + + + diff --git a/src/EventBinding.h b/src/EventBinding.h new file mode 100644 index 0000000..ec8d400 --- /dev/null +++ b/src/EventBinding.h @@ -0,0 +1,107 @@ +/* + *------------------------------------------------------------------------------ + * eventbinding.h + * Declares classes used for implementing OpTcl's event binding. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#if !defined(AFX_EVENTBINDING_H__818C3160_57FC_11D3_86E8_0000B482A708__INCLUDED_) +#define AFX_EVENTBINDING_H__818C3160_57FC_11D3_86E8_0000B482A708__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +struct BindingProps; +class OptclObj; + + +typedef THash DispCmdTbl; + + + +struct BindingProps +{ + TObjPtr m_pScript; + Tcl_Interp * m_pInterp; + + BindingProps (Tcl_Interp *pInterp, Tcl_Obj * pScript) + { + ASSERT (pInterp != NULL && pScript != NULL); + m_pInterp = pInterp; + m_pScript = pScript; + } + + int Eval (OptclObj *pObj, DISPPARAMS *pDispParams, LPVARIANT pVarResult, + LPEXCEPINFO pExcepInfo); +}; + + + +class EventBindings : public IDispatch +{ +public: + friend OptclObj; + + EventBindings(OptclObj *pObj, REFGUID guid, ITypeInfo *pInfo); + virtual ~EventBindings(); + + + bool SetBinding (Tcl_Interp *pInterp, const char * name, Tcl_Obj *pCommand); + bool GetBinding (Tcl_Interp *pInterp, const char * name); + bool DeleteBinding (Tcl_Interp *pInterp, const char * name); + + ULONG TotalBindings (); + + // IUnknown Entries + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void ** ppvObject); + ULONG STDMETHODCALLTYPE AddRef( void); + ULONG STDMETHODCALLTYPE Release( void); + + // IDispatch Entries + HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo); + + HRESULT STDMETHODCALLTYPE + GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo ** ppTInfo); + + HRESULT STDMETHODCALLTYPE + GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, + UINT cNames, LCID lcid, DISPID *rgDispId); + + HRESULT STDMETHODCALLTYPE + Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, + WORD wFlags, DISPPARAMS *pDispParams, LPVARIANT pVarResult, + LPEXCEPINFO pExcepInfo, UINT *puArgErr); + +protected: + void DeleteTbl(); + bool Name2Dispid (Tcl_Interp *pInterp, const char * name, DISPID &dispid); + +protected: + LONG m_ref; // COM reference count for this event binding + ULONG m_bindings; // total number of bindings in this event object + CComPtr m_pti; // the type information that we are going to be binding + CComPtr m_ptc; // fast access to members + DispCmdTbl m_cmdtbl; // mapping of dispatch ids to Tcl commands + OptclObj * m_optclobj; // the parent object of this binding + DWORD m_cookie; // cookie used for event advise + GUID m_guid; // the id for the event interface +}; + +#endif // !defined(AFX_EVENTBINDING_H__818C3160_57FC_11D3_86E8_0000B482A708__INCLUDED_) diff --git a/src/ObjMap.cpp b/src/ObjMap.cpp new file mode 100644 index 0000000..1e9fd53 --- /dev/null +++ b/src/ObjMap.cpp @@ -0,0 +1,505 @@ +/* + *------------------------------------------------------------------------------ + * objmap.cpp + * Implementation of the object table. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ +#include "stdafx.h" +#include "tbase.h" +#include "optcl.h" +#include "utility.h" +#include "objmap.h" + + + + +// globals + +// the one and only object map for this extension +// this class uses a Tcl hash table - this usually wouldn't be +// safe, except that this hash table is initialised (courtsey of THash<>) +// only on first uses (lazy). So it should be okay. Not sure how +// this will behave in a multithreaded application + +ObjMap g_objmap; + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +ObjMap::ObjMap() : m_destructpending(false) +{ + +} + +ObjMap::~ObjMap() +{ + +} + + +/* + *------------------------------------------------------------------------- + * ObjMap::DeleteAll -- + * Deletes all objects in the system. + * Result: + * None. + * Side effects: + * Deletes all object commands from respective interpreters + *------------------------------------------------------------------------- + */ +void ObjMap::DeleteAll () +{ + ObjNameMap::iterator i; + for (i = m_namemap.begin(); i != m_namemap.end(); i++) { + OptclObj *pobj = *i; + ASSERT (pobj != NULL); + DeleteCommand (pobj); + delete pobj; + } + m_namemap.deltbl(); + m_unkmap.deltbl(); +} + + + + +/* + *------------------------------------------------------------------------- + * ObjMap::Create -- + * Creates an object for a particular interpreter. The type of the object + * is identified by a string representing either a CLSID or ProgId. It would + * be neat if it also could be the name of a file on the local system or + * at some URL. More on this later.... + * If the object already exists in the object table, then we return that + * object. In fact, this is a limitation of the system, as objects that have + * been registered in one interpreter cannot be accessed from another + * interpreter. + * + * Result: + * A non-null pointer to the underlying Optcl object representation, + * iff successful. + * + * Side effects: + * Creates also the Tcl command used to invoke this object. + * + *------------------------------------------------------------------------- + */ +OptclObj * ObjMap::Create (Tcl_Interp *pInterp, const char * id, const char * path, bool start) +{ + ASSERT (id != NULL); + OptclObj *pObj = NULL, + *ptmp = NULL; + + pObj = new OptclObj (); + if (!pObj->Create(pInterp, id, path, start)) { + delete pObj; + return NULL; + } + + IUnknown **u = (IUnknown**)(IUnknown*)(*pObj); + if (m_unkmap.find(u, &ptmp) != NULL) { + ASSERT (ptmp != NULL); + delete pObj; + ++ptmp->m_refcount; + return ptmp; + } + + m_unkmap.set (u, pObj); + m_namemap.set (*pObj, pObj); // implicit const char * cast + pObj->m_refcount = 1; + CreateCommand (pObj); + return pObj; +} + + +/* + *------------------------------------------------------------------------- + * ObjMap::Add -- + * Given an IUnknown pointer, this function ensures that the object table + * has a representation for it. If one cannot be found, then a new + * representation is created, and the object command is created in the + * specified interpreter. + * + * Result: + * Non-null pointer to the internal representation iff successful. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +OptclObj * ObjMap::Add (Tcl_Interp *pInterp, LPUNKNOWN punk) +{ + ASSERT (punk != NULL); + CComPtr t_unk; + HRESULT hr; + OptclObj *pObj = NULL; + + // get the objects pure IUnknown interface (punk can + // point to any interface + + hr = punk->QueryInterface (IID_IUnknown, (void**)(&t_unk)); + CHECKHR(hr); + IUnknown ** u = (IUnknown **)(IUnknown*)t_unk; + + if (m_unkmap.find(u, &pObj) == NULL) { + pObj = new OptclObj(); + if (!pObj->Attach(pInterp, punk)) + { + delete pObj; + pObj = NULL; + } + m_namemap.set(*pObj, pObj); + m_unkmap.set(u, pObj); + pObj->m_refcount = 1; + CreateCommand (pObj); + } else { + ++pObj->m_refcount; + } + + ASSERT (pObj != NULL); + return pObj; +} + + + +/* + *------------------------------------------------------------------------- + * ObjMap::Find -- + * Given and IUnknown pointer, this function attempts to bind to an + * existing representation within the object table. + * + * Result: + * A non-null pointer to the required Optcl object, iff successful. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ +OptclObj *ObjMap::Find (LPUNKNOWN punk) +{ + ASSERT (punk != NULL); + CComPtr t_unk; + HRESULT hr; + OptclObj *pObj = NULL; + + // get the objects pure IUnknown interface (punk can + // point to any interface + + hr = punk->QueryInterface (IID_IUnknown, (void**)(&t_unk)); + CHECKHR(hr); + IUnknown **u = (IUnknown**)(IUnknown*)(t_unk); + m_unkmap.find (u, &pObj); + return pObj; +} + + + +/* + *------------------------------------------------------------------------- + * ObjMap::Find -- + * Finds an existing optcl object keyed on its name. + * + * Result: + * A non-null pointer to the required Optcl object, iff successful. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ +OptclObj *ObjMap::Find (const char *name) +{ + ASSERT (name != NULL); + OptclObj *pObj = NULL; + m_namemap.find (name, &pObj); + return pObj; +} + + + + + +/* + *------------------------------------------------------------------------- + * ObjMap::DeleteCommand -- + * Ensures that the object command associated with a valid Optcl object + * is quietly removed. + * + * Result: + * None. + * + * Side effects: + * po->m_cmdtoken is set to NULL. + *------------------------------------------------------------------------- + */ +void ObjMap::DeleteCommand (OptclObj *po) +{ + ASSERT (po != NULL); + + if (po->m_cmdtoken == NULL) + return; + + + CONST84 char * cmdname = Tcl_GetCommandName (po->m_pInterp, po->m_cmdtoken); + if (cmdname == NULL) + return; + Tcl_CmdInfo cmdinf; + + if (Tcl_GetCommandInfo (po->m_pInterp, cmdname, &cmdinf) == 0) + return; + + // modify the command info of this command so that the callback is now disabled + cmdinf.deleteProc = NULL; + cmdinf.deleteData = NULL; + + Tcl_SetCommandInfo (po->m_pInterp, cmdname, &cmdinf); + Tcl_DeleteCommand (po->m_pInterp, cmdname); + po->m_cmdtoken = NULL; +} + + +/* + *------------------------------------------------------------------------- + * ObjMap::Delete -- + * Deletes an Optcl object, ensuring the removal of its object command, + * and its entries in the object table. + * + * Result: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ +void ObjMap::Delete (OptclObj *pObj) +{ + ASSERT (pObj != NULL); + + // first ensure that we delete the objects command + DeleteCommand(pObj); + m_namemap.delete_entry (*pObj); + m_unkmap.delete_entry ((IUnknown**)(IUnknown*)(*pObj)); + delete pObj; +} + + + +/* + *------------------------------------------------------------------------- + * ObjMap::Delete -- + * Deletes an optcl object keyed on its name. Ensures the removal of the + * object command, as well as its reference in the object table. + * + * Result: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ +void ObjMap::Delete (const char * name) +{ + ASSERT (name != NULL); + OptclObj *pObj = NULL; + + if (m_namemap.find (name, &pObj) == NULL) + return; + ASSERT (pObj != NULL); + ASSERT (strcmp(name, *pObj) == 0); + Delete (pObj); +} + + + +/* + *------------------------------------------------------------------------- + * ObjMap::Lock -- + * Increments the reference count on an optcl object. + * + * Result: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ +void ObjMap::Lock (OptclObj *po) +{ + ASSERT (po != NULL); + ++po->m_refcount; +} + + +/* + *------------------------------------------------------------------------- + * ObjMap::Unlock -- + * Decrements the reference count on an optcl object. If zero, the object + * is deleted. These functions could do with thread safety in the future. + * + * Result: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ +void ObjMap::Unlock(OptclObj *po) +{ + ASSERT (po != NULL); + if (--po->m_refcount == 0) + Delete (po); +} + + + + +/* + *------------------------------------------------------------------------- + * ObjMap::Lock -- + * Increments the reference count on an optcl object, keyed on its name + * + * Result: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ +bool ObjMap::Lock (const char *name) +{ + ASSERT (name != NULL); + OptclObj *pObj = NULL; + if (m_namemap.find (name, &pObj) == NULL) + return false; + Lock (pObj); + return true; +} + + + + + + +/* + *------------------------------------------------------------------------- + * ObjMap::Unlock -- + * Decrements the reference count of an optcl object, keyed on its name. + * If zero, the object is deleted. + * + * Result: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ +bool ObjMap::Unlock(const char *name) +{ + ASSERT (name != NULL); + OptclObj *pObj = NULL; + if (m_namemap.find (name, &pObj) == NULL) + return false; + Unlock(pObj); + return true; +} + + + +/* + *------------------------------------------------------------------------- + * ObjMap::CreateCommand -- + * Creates the command that is to be associated with an optcl object. + * The command is created within the interpreter referenced by the object. + * The command token is stored within the object. + * + * Result: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ +void ObjMap::CreateCommand(OptclObj * pObj) +{ + ASSERT (pObj != NULL); + pObj->m_cmdtoken = + Tcl_CreateObjCommand (pObj->m_pInterp, (char*)(const char*)(*pObj), + ObjMap::OnCmd, (ClientData)pObj, ObjMap::OnCmdDelete); +} + + +/* + *------------------------------------------------------------------------- + * ObjMap::OnCmd -- + * Function called from tcl whenever an optcl object command is invoked. + * The ClientData is the pointer to the object. + * + * Result: + * Std Tcl results. + * + * Side effects: + * Anything, depending on the invocation + * + *------------------------------------------------------------------------- + */ +TCL_CMDEF(ObjMap::OnCmd) +{ + OptclObj *po = (OptclObj*)cd; // cast the client data to the underlying + // object + ASSERT (po != NULL); + return (po->InvokeCmd (pInterp, objc-1, objv+1))?TCL_OK:TCL_ERROR; +} + + +/* + *------------------------------------------------------------------------- + * ObjMap::OnCmdDelete -- + * Called when (and only when) a script deletes an object command. The + * referenced optcl object is also destroyed. + * + * Result: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ +void ObjMap::OnCmdDelete (ClientData cd) +{ + OptclObj *po = (OptclObj*) cd; + ASSERT (po != NULL); + g_objmap.Delete(po); +} + + + + + diff --git a/src/ObjMap.h b/src/ObjMap.h new file mode 100644 index 0000000..ce1a58c --- /dev/null +++ b/src/ObjMap.h @@ -0,0 +1,79 @@ +/* + *------------------------------------------------------------------------------ + * objmap.h + * Definition of the object table. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#if !defined(AFX_OBJMAP_H__8A11BC00_616B_11D4_8004_0040055861F2__INCLUDED_) +#define AFX_OBJMAP_H__8A11BC00_616B_11D4_8004_0040055861F2__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "optcl.h" +#include "OptclObj.h" + +typedef THash ObjNameMap; +typedef THash ObjUnkMap; + +class ObjMap { + friend OptclObj; +protected: + ObjNameMap m_namemap; + ObjUnkMap m_unkmap; + bool m_destructpending; + +public: // constructor / destructor + ObjMap (); + virtual ~ObjMap (); + + OptclObj * Create (Tcl_Interp *pInterp, const char * id, const char * path, bool start); + OptclObj * Add (Tcl_Interp *pInterp, LPUNKNOWN punk); + OptclObj * Find (LPUNKNOWN punk); + OptclObj * Find (const char *name); + + void Delete (const char * name); + void DeleteAll (); + + bool Lock (const char *name); + bool Unlock(const char *name); + + void Lock (OptclObj *); + void Unlock(OptclObj *); + + +public: // statics + static TCL_CMDEF(OnCmd); + static void OnCmdDelete (ClientData cd); + +protected: + void Delete (OptclObj *); + void CreateCommand (OptclObj *); + void DeleteCommand (OptclObj *); + +}; + + +// Global Variable Declaration!!! + +extern ObjMap g_objmap; // once object map per application + +#endif // !defined(AFX_OBJMAP_H__8A11BC00_616B_11D4_8004_0040055861F2__INCLUDED_) diff --git a/src/OptclBindPtr.cpp b/src/OptclBindPtr.cpp new file mode 100644 index 0000000..c6557f6 --- /dev/null +++ b/src/OptclBindPtr.cpp @@ -0,0 +1,52 @@ +/* + *------------------------------------------------------------------------------ + * optclbindptr.cpp + * Implements the class used wrapping a BINDPTR, DESCKIND and ITypeInfo + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#include "stdafx.h" +#include "typelib.h" +#include "OptclBindPtr.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +OptclBindPtr::OptclBindPtr() +{ + m_bp.lpfuncdesc = NULL; + m_dk = DESCKIND_NONE; +} + +OptclBindPtr::~OptclBindPtr() +{ + ReleaseBindPtr(); +} + + +void OptclBindPtr::ReleaseBindPtr () +{ + ::ReleaseBindPtr(m_pti, m_dk, m_bp); + m_dk = DESCKIND_NONE; +} + + + + diff --git a/src/OptclBindPtr.h b/src/OptclBindPtr.h new file mode 100644 index 0000000..da93d28 --- /dev/null +++ b/src/OptclBindPtr.h @@ -0,0 +1,127 @@ +/* + *------------------------------------------------------------------------------ + * optclbindptr.h + * Defines the class used wrapping a BINDPTR, DESCKIND and ITypeInfo + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */#if !defined(AFX_OPTCLBINDPTR_H__2682D1C3_5EDC_11D3_86E8_0000B482A708__INCLUDED_) +#define AFX_OPTCLBINDPTR_H__2682D1C3_5EDC_11D3_86E8_0000B482A708__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +// wrapper class for a BINDPTR, DESCKIND, and ITypeInfo +class OptclBindPtr +{ +public: + BINDPTR m_bp; + DESCKIND m_dk; + CComPtr m_pti; + +public: + OptclBindPtr(); + virtual ~OptclBindPtr(); + void ReleaseBindPtr (); + + // inline functions + MEMBERID OptclBindPtr::memid () + { + ASSERT (m_bp.lpfuncdesc != NULL); + + switch (m_dk) { + case DESCKIND_FUNCDESC: + return m_bp.lpfuncdesc->memid; + + case DESCKIND_IMPLICITAPPOBJ: + case DESCKIND_VARDESC: + return m_bp.lpvardesc->memid; + default: + ASSERT (FALSE); + return DISPID_UNKNOWN; + } + } + + + short OptclBindPtr::cParams() + { + ASSERT (m_bp.lpfuncdesc != NULL); + switch (m_dk) { + case DESCKIND_FUNCDESC: + return m_bp.lpfuncdesc->cParams; + case DESCKIND_IMPLICITAPPOBJ: + case DESCKIND_VARDESC: + return 1; + default: + ASSERT (FALSE); + return 0; + } + } + + short OptclBindPtr::cParamsOpt() + { + ASSERT (m_bp.lpfuncdesc != NULL); + switch (m_dk) { + case DESCKIND_FUNCDESC: + return m_bp.lpfuncdesc->cParamsOpt; + case DESCKIND_IMPLICITAPPOBJ: + case DESCKIND_VARDESC: + return 1; + default: + ASSERT (FALSE); + return 0; + } + } + + ELEMDESC * OptclBindPtr::param(short param) + { + ASSERT (m_bp.lpfuncdesc != NULL); + ASSERT (param < cParams()); + + switch (m_dk) { + case DESCKIND_FUNCDESC: + return (m_bp.lpfuncdesc->lprgelemdescParam + param); + case DESCKIND_IMPLICITAPPOBJ: + case DESCKIND_VARDESC: + return (&m_bp.lpvardesc->elemdescVar); + default: + ASSERT (FALSE); + return 0; + } + + } + + ELEMDESC * OptclBindPtr::result() + { + ASSERT (m_bp.lpfuncdesc != NULL); + + switch (m_dk) { + case DESCKIND_FUNCDESC: + return (&m_bp.lpfuncdesc->elemdescFunc); + case DESCKIND_IMPLICITAPPOBJ: + case DESCKIND_VARDESC: + return (&m_bp.lpvardesc->elemdescVar); + default: + ASSERT (FALSE); + return 0; + } + } +}; + +#endif // !defined(AFX_OPTCLBINDPTR_H__2682D1C3_5EDC_11D3_86E8_0000B482A708__INCLUDED_) diff --git a/src/OptclObj.cpp b/src/OptclObj.cpp new file mode 100644 index 0000000..b2c74f6 --- /dev/null +++ b/src/OptclObj.cpp @@ -0,0 +1,1847 @@ +/* + *------------------------------------------------------------------------------ + * optclobj.cpp + * Implements the functionality for the internal representation of + * an optcl object. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#include "stdafx.h" +#include +#include "tbase.h" +#include "utility.h" +#include "optcl.h" +#include "OptclObj.h" +#include "typelib.h" +#include "ObjMap.h" +#include "dispparams.h" +#include "eventbinding.h" +#include "optclbindptr.h" +#include "optcltypeattr.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +OptclObj::OptclObj () +: m_refcount(0), m_cmdtoken(NULL), m_pta(NULL), +m_destroypending(false), m_container(this) +{ +} + +bool OptclObj::Create (Tcl_Interp *pInterp, const char *strid, + const char * windowpath, bool start) +{ + m_pInterp = pInterp; + + USES_CONVERSION; + ASSERT (strid != NULL); + + if (windowpath == NULL) { + LPOLESTR lpolestrid = A2OLE(strid); + CLSID clsid; + HRESULT hr; + + // convert strid to CLSID + hr = CLSIDFromString (lpolestrid, &clsid); + if (FAILED (hr)) + hr = CLSIDFromProgID (lpolestrid, &clsid); + CHECKHR_TCL(hr, pInterp, false); + + if (!start) + hr = GetActiveObject(clsid, NULL, &m_punk); + if (start || FAILED(hr)) + hr = CoCreateInstance (clsid, NULL, CLSCTX_SERVER, IID_IUnknown, (void**)&m_punk); + CHECKHR_TCL(hr, pInterp, false); + + } + else { + m_punk = m_container.Create(pInterp, Tk_MainWindow(pInterp), windowpath, strid); + if (m_punk == NULL) + return false; + } + try { + CreateName (m_punk); + InitialiseClassInfo(m_punk); + InitialisePointers (m_punk); + } + catch (HRESULT hr) { + CHECKHR_TCL(hr, pInterp, false); + } + return true; +} + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::Attach -- + * Connects this object to an existing interface + * Result: + * true iff successful + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool OptclObj::Attach (Tcl_Interp *pInterp, LPUNKNOWN punk) +{ + ASSERT (m_punk == NULL); + ASSERT (punk != NULL); + + m_pInterp = pInterp; + try { + CreateName (punk); + InitialiseUnknown(punk); + InitialiseClassInfo(m_punk); + InitialisePointers (m_punk); + } + catch (HRESULT hr) { + m_punk = NULL; + CHECKHR_TCL(hr, pInterp, false); + } + return true; +} + + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::~OptclObj -- + * Destructor + * Result: + * + * Side effects: + * + *------------------------------------------------------------------------- + */ +OptclObj::~OptclObj() +{ + m_destroypending = true; + ReleaseBindingTable(); + ReleaseTypeAttr(); +} + + + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::CreateName -- + * Creates the string representation for this object - a unique name is + * created from the object's IUnknown pointer. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void OptclObj::CreateName (LPUNKNOWN punk) +{ + ASSERT (punk != NULL); + char str[10]; + sprintf (str, "%x", punk); + m_name = "optcl0x"; + m_name += str; +} + + + + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::InitialiseClassInfo -- + * Attempts to find the typeinfo for this object's coclass. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void OptclObj::InitialiseClassInfo (LPUNKNOWN punk) +{ + CComQIPtr pcli; + + // try to pull out the coclass information + pcli = punk; // implicit query interface + if (pcli != NULL) + pcli->GetClassInfo (&m_pti_class); +} + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::InitialiseUnknown -- + * Initialises the OptclObj's 'true' IUnknown pointer. + * + * Result: + * None. + * + * Side effects: + * Throws HRESULT on error. + *------------------------------------------------------------------------- + */ +void OptclObj::InitialiseUnknown (LPUNKNOWN punk) +{ + ASSERT (punk != NULL); + HRESULT hr; + + hr = punk->QueryInterface (IID_IUnknown, (void**)(&m_punk)); + CHECKHR(hr); +} + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::InitialisePointersFromCoClass -- + * Called when we have the coclass information for this object. The + * function identifies the default interface and binds to it. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +HRESULT OptclObj::InitialisePointersFromCoClass() +{ + ASSERT (m_pti_class != NULL); + TYPEATTR *pta = NULL; + HRESULT hr; + + // retrieve the type attribute + hr = m_pti_class->GetTypeAttr (&pta); + CHECKHR(hr); + + // store the number of implemented interfaces + WORD impcount = pta->cImplTypes; + m_pti_class->ReleaseTypeAttr (pta); pta = NULL; + + // iterate through the type looking for the default interface + for (WORD i = 0; i < impcount; i++) + { + INT flags; + hr = m_pti_class->GetImplTypeFlags (i, &flags); + if (FAILED (hr)) + return hr; + if (flags == IMPLTYPEFLAG_FDEFAULT) + break; + } + + // if not found return an error + if (i == impcount) + return E_FAIL; + + // we found the interface - now to get its iid... + // first retrieve the type info; + + CComPtr reftype; + CComPtr reftypelib; + + HREFTYPE href; + + hr = m_pti_class->GetRefTypeOfImplType (i, &href); + if (FAILED(hr)) + return hr; + + hr = m_pti_class->GetRefTypeInfo (href, &reftype); + if (FAILED(hr)) + return hr; + + // now set the interface from typeinfo + return SetInterfaceFromType (reftype); +} + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::GetTypeAttr -- + * Retrieves the type attribute for the type of this object's current + * interface. + * Result: + * Standard HRESULT. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +HRESULT OptclObj::GetTypeAttr() +{ + ASSERT (m_pta == NULL); + ASSERT (m_pti != NULL); + return m_pti->GetTypeAttr(&m_pta); +} + + +/* + *------------------------------------------------------------------------- + * OptclObj::ReleaseTypeAttr -- + * Releases the current type attribute, and sets it to NULL. + * Result: + * None. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void OptclObj::ReleaseTypeAttr() +{ + if (m_pti != NULL && m_pta != NULL) { + m_pti->ReleaseTypeAttr(m_pta); + m_pta = NULL; + } +} + + +/* + *------------------------------------------------------------------------- + * OptclObj::SetInterfaceFromType -- + * Queries for the interface described in the typeinfo. The interface, + * if found, becomes the current interface. + * + * Result: + * HRESULT giving success code. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +HRESULT OptclObj::SetInterfaceFromType (ITypeInfo *reftype) +{ + HRESULT hr; + CComPtr reftypelib; + UINT libindex; + TYPEATTR *pta; + + hr = reftype->GetContainingTypeLib(&reftypelib, &libindex); + if (FAILED(hr)) + return hr; + + hr = reftype->GetTypeAttr (&pta); + if (FAILED(hr)) + return hr; + + if (pta->typekind != TKIND_DISPATCH) { + reftype->ReleaseTypeAttr (pta); + return E_NOINTERFACE; + } + + GUID guid = pta->guid; + reftype->ReleaseTypeAttr (pta); + + hr = m_punk->QueryInterface(guid, (void**)(&m_pcurrent)); + if (FAILED(hr)) + return hr; + + + // nice! now we cache the result of all our hard work + ReleaseTypeAttr (); + m_pti = reftype; + m_ptl = reftypelib; + m_ptc = NULL; + m_pti->GetTypeComp (&m_ptc); + // now that we got the interface ok, retrieve the type attributes again + return GetTypeAttr(); +} + + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::InitialisePointers -- + * Called to initialise this objects interface pointers + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void OptclObj::InitialisePointers (LPUNKNOWN punk, ITypeLib *plib, ITypeInfo *pinfo) +{ + HRESULT hr; + ASSERT (punk != NULL); + CComQIPtr pdisp; + + ASSERT ((plib!=NULL && pinfo!=NULL) || (plib==NULL && pinfo==NULL)); + + if (plib != NULL && pinfo != NULL) { + m_pcurrent = punk; + m_ptl = plib; + m_pti = pinfo; + m_ptc = NULL; + m_pti->GetTypeComp (&m_ptc); + GetTypeAttr(); + } + + // else, if we have the coclass information, try building on its default + // interface + else if (m_pti_class == NULL || FAILED(InitialisePointersFromCoClass())) { + // failed to build using coclass information + // Query Interface cast to a dispatch interface + m_pcurrent = punk; + try { + if (m_pcurrent == NULL) + throw (HRESULT(0)); + // get the type information and library. + hr = m_pcurrent->GetTypeInfo (0, LOCALE_SYSTEM_DEFAULT, &m_pti); + CHECKHR(hr); + UINT index; + hr = m_pti->GetContainingTypeLib(&m_ptl, &index); + CHECKHR(hr); + m_ptc = NULL; + m_pti->GetTypeComp (&m_ptc); + GetTypeAttr(); + } + + + catch (HRESULT) { + // there isn't a interface that we can use + ReleaseTypeAttr(); + m_pcurrent.Release(); + m_pti = NULL; + m_ptl = NULL; + m_ptc = NULL; + return; + } + } + // inform the typelibrary browser system of the library + g_libs.EnsureCached (m_ptl); +} + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::operator LPUNKNOWN -- + * Gives the 'true' IUnknown pointer for this object. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +OptclObj::operator LPUNKNOWN() +{ + return m_punk; +} + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::operator const char * -- + * Gives the string representation for this object. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +OptclObj::operator const char * () +{ + return m_name.c_str(); +} + + + +/* + *------------------------------------------------------------------------- + * void OptclObj::CoClassName -- + * Returns the class name in the tcl object smart ptr or ??? if unknown. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void OptclObj::CoClassName (TObjPtr &pObj) +{ + pObj.create(); + if (m_pti_class == NULL) + pObj = "???"; + else + TypeLib_GetName (NULL, m_pti_class, pObj); +} + + +/* + *------------------------------------------------------------------------- + * OptclObj::InterfaceName -- + * Returns the name of this objects current interface. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void OptclObj::InterfaceName (TObjPtr &pObj) +{ + pObj.create(); + if (m_pti == NULL) + pObj = "???"; + else + TypeLib_GetName (NULL, m_pti, pObj); +} + + + +/* + *------------------------------------------------------------------------- + * OptclObj::SetInterfaceName -- + * Sets the current interface to that named by pObj. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void OptclObj::SetInterfaceName (TObjPtr &pObj) +{ + ASSERT (pObj.isnotnull()); + TypeLib *ptl; + CComPtr pti; + CComPtr punk; + TYPEATTR ta, *pta = NULL; + HRESULT hr; + + TypeLib_ResolveName (pObj, &ptl, &pti); + // we need to insert some alias type resolution here. + + hr = pti->GetTypeAttr (&pta); + CHECKHR(hr); + ta = *pta; + pti->ReleaseTypeAttr (pta); + + + if (ta.typekind != TKIND_INTERFACE && + ta.typekind != TKIND_DISPATCH) + throw ("type does not resolve to an interface"); + + + hr = m_punk->QueryInterface (ta.guid, (void**)(&punk)); + CHECKHR(hr); + InitialisePointers (punk, ptl->m_ptl, pti); +} + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::InvokeCmd -- + * Called by the object map as a result of invoking the object command + * on this object. Format of the command is as follows + * + * obj : ?-with subprop? prop ?value? ?prop value? ... + * obj method ?arg? ... + * + * Result: + * true iff successful. Error string in interpreter. + * + * Side effects: + * Depends on the parameters. + *------------------------------------------------------------------------- + */ +bool OptclObj::InvokeCmd (Tcl_Interp *pInterp, int objc, Tcl_Obj *CONST objv[]) +{ + ASSERT (pInterp != NULL); + CComPtr pdisp; + CComPtr ptc; + CComPtr pti; + TObjPtr name; + + int invkind = DISPATCH_METHOD; + + char * msg = + "\n\tobj : ?-with subprop? prop ?value? ?prop value? ..." + "\n\tobj method ?arg? ..."; + + if (objc == 0) { + Tcl_WrongNumArgs (pInterp, 0, NULL, msg); + return TCL_ERROR; + } + + if (CheckInterface (pInterp) == false) + return TCL_ERROR; + + + + // parse for a -with flag + name.attach(objv[0]); + if (strncmp (name, "-with", strlen(name)) == 0) + { + // check that we have enough parameters + if (objc < 3) { + Tcl_WrongNumArgs (pInterp, 0, NULL, msg); + return false; + } + + name.attach(objv[1]); + if (!ResolvePropertyObject (pInterp, name, &pdisp, &pti, &ptc)) + return false; + objc -= 2; + objv += 2; + } + else { + pdisp = m_pcurrent; + ptc = m_ptc; + pti = m_pti; + } + + // check the first argument for a ':' + char * str = Tcl_GetStringFromObj (objv[0], NULL); + ASSERT (str != NULL); + + if (*str == ':') { + objc--; + objv++; + + if (objc == 1) + return GetProp (pInterp, objv[0], pdisp, pti, ptc); + else { + if (objc % 2 != 0) { + Tcl_SetResult (pInterp, "property set requires pairs of parameters", TCL_STATIC); + return false; + } + return SetProp (pInterp, objc/2, objv, pdisp, pti, ptc); + } + } + + if (ptc == NULL) + return InvokeNoTypeInf (pInterp, invkind, objc, objv, pdisp); + else + return InvokeWithTypeInf (pInterp, invkind, objc, objv, pdisp, pti, ptc); +} + + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::CheckInterface -- + * Checks for current interface being valid. + * Result: + * Currently, returns true iff an interface exists. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool OptclObj::CheckInterface (Tcl_Interp *pInterp) +{ + if (m_pcurrent == NULL) { + Tcl_SetResult (pInterp, "no interface available", TCL_STATIC); + return false; + } + + /* -- not needed now that we are only working with dispatch interfaces + + if (m_pta != NULL) { + if (m_pta->typekind == TKIND_INTERFACE && ((m_pta->wTypeFlags&TYPEFLAG_FDUAL)==0)) + { + Tcl_SetResult (pInterp, "interface is a pure vtable - optcl can't call these ... yet!", TCL_STATIC); + return false; + } + } + */ + return true; +} + + +/* + *------------------------------------------------------------------------- + * OptclObj::BuildParamsWithBindPtr -- + * Builds the dispatch parameters using the values found in a bindptr + * object. + * + * Result: + * true iff successful - else error string in interpreter. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool OptclObj::BuildParamsWithBindPtr (Tcl_Interp *pInterp, int objc, Tcl_Obj *CONST objv[], + OptclBindPtr & bp, DispParams & dp) +{ + ASSERT (pInterp != NULL && objv != NULL); + bool con_ok = true; + TObjPtr obj; + + + // check for the last parameter being the return value and take + // this into account when checking parameter counts + int params = bp.cParams (); + if (params > 0 && bp.param(params - 1)->paramdesc.wParamFlags & PARAMFLAG_FRETVAL) + --params; + + if (objc <= params && + objc >= (params - bp.cParamsOpt())) + { + // set up the dispatch arguments - must be in reverse order + dp.Args (objc); + for (int count = objc-1; count >= 0 && con_ok; count--) + { + con_ok = false; + ELEMDESC *pdesc = bp.param(count); + ASSERT (pdesc != NULL); + // cases for parameters : [in] - value + // [inout] - reference (variable must exist) + // [out] - reference (variable doesn have to exist) + + // is it an in* type + if ((pdesc->paramdesc.wParamFlags & PARAMFLAG_FIN) || (pdesc->paramdesc.wParamFlags == PARAMFLAG_NONE)) { + // is it [inout]? + if (pdesc->paramdesc.wParamFlags & PARAMFLAG_FOUT) { + obj.attach(Tcl_ObjGetVar2 (pInterp, objv[count], NULL, TCL_LEAVE_ERR_MSG)); + if (obj.isnull()) + return false; + } + else // just [in] + obj.attach(objv[count]); + + con_ok = obj2var_ti(pInterp, obj, dp[objc - count - 1], bp.m_pti, &(pdesc->tdesc)); + } + + else if (pdesc->paramdesc.wParamFlags & PARAMFLAG_FOUT) + { // a pure out flag - we'll set up the type of the parameter correctly, but fill it with a null + con_ok = obj2var_ti(pInterp, TObjPtr(NULL), dp[objc - count - 1], bp.m_pti, &(pdesc->tdesc)); + } + + else { + // unknown parameter type + ASSERT(false); + } + } + } + else + { + Tcl_SetResult (pInterp, "wrong # args", TCL_STATIC); + con_ok = false; + } + + return con_ok; +} + + + +/* + *------------------------------------------------------------------------- + * OptclObj::RetrieveOutParams -- + * Scans the parameter types in a bind pointer and pulls out those that + * are either out or in/out, and sets the appropriate Tcl variable to + * their value. + * + * Result: + * true iff successful. Else, error string in interpreter. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool OptclObj::RetrieveOutParams (Tcl_Interp *pInterp, int objc, Tcl_Obj *CONST objv[], + OptclBindPtr & bp, DispParams & dp) + +{ + TObjPtr presult; + bool bok = true; + // now loop through the parameters again, pulling out the [*out] values + for (int count = objc - 1; bok && count >= 0; count--) + { + ELEMDESC *pdesc = bp.param(count); + ASSERT (pdesc != NULL); + // is it an out parameter? + if (pdesc->paramdesc.wParamFlags & PARAMFLAG_FOUT) + { + // convert the value back to a tcl object + bok = (!var2obj (pInterp, dp[objc - count - 1], presult) || + Tcl_ObjSetVar2 (pInterp, objv[count], NULL, + presult, TCL_LEAVE_ERR_MSG) == NULL); + + } + } + return bok; +} + + + + + + +bool OptclObj::InvokeWithTypeInfVariant (Tcl_Interp *pInterp, long invokekind, + int objc, Tcl_Obj *CONST objv[], + IDispatch *pDisp, ITypeInfo *pti, ITypeComp *pCmp, VARIANT &varResult) +{ + USES_CONVERSION; + DispParams dp; + LPOLESTR olename; + + + DISPID dispid; + HRESULT hr; + EXCEPINFO ei; + UINT ea = 0; + + bool bOk = false; + TObjPtr obj; + TObjPtr presult; + static DISPID propput = DISPID_PROPERTYPUT; + OptclBindPtr obp; + OptclTypeAttr ota; + + ASSERT (objc >= 1); + ASSERT (pDisp != NULL); + ASSERT (pti != NULL); + ASSERT (varResult.vt == VT_EMPTY); + ota = pti; + + ASSERT (ota->typekind == TKIND_DISPATCH || (ota->wTypeFlags & TYPEFLAG_FDUAL)); + + try { + olename = A2OLE(Tcl_GetStringFromObj (objv[0], NULL)); + hr = pCmp->Bind (olename, LHashValOfName(LOCALE_SYSTEM_DEFAULT, olename), + invokekind, &obp.m_pti, &obp.m_dk, &obp.m_bp); + CHECKHR(hr); + + if (obp.m_dk == DESCKIND_NONE) { + Tcl_SetResult (pInterp, "member not found: ", TCL_STATIC); + Tcl_AppendResult (pInterp, (char*)obj, NULL); + } else { + dispid = obp.memid(); + // check the number of parameters + + objc--; // count of parameters provided + objv++; // the parameters + if (!BuildParamsWithBindPtr (pInterp, objc, objv, obp, dp)) + return false; + + if (invokekind == DISPATCH_PROPERTYPUT) { + dp.cNamedArgs = 1; + dp.rgdispidNamedArgs = &propput; + } + + // can't invoke through the typelibrary for local objects + //hr = pti->Invoke(pDisp, dispid, invokekind, &dp, &varResult, &ei, &ea); + hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, invokekind, + &dp, &varResult, &ei, &ea); + + if (invokekind == DISPATCH_PROPERTYPUT) { + dp.rgdispidNamedArgs = NULL; + } + + // error check + if (hr == DISP_E_EXCEPTION) + Tcl_SetResult (pInterp, ExceptInfo2Str (&ei), TCL_DYNAMIC); + + else if (hr == DISP_E_TYPEMISMATCH) { + TDString td("type mismatch in parameter #"); + td << (long)(ea); + Tcl_SetResult (pInterp, td, TCL_VOLATILE); + } + else + CHECKHR_TCL(hr, pInterp, false); + if (FAILED(hr)) + return false; + + if (!RetrieveOutParams (pInterp, objc, objv, obp, dp)) + return false; + bOk = true; + } + } + catch (HRESULT hr) + { + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + } + return bOk; +} + + + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::InvokeWithTypeInf -- + * Performs a method invocation, given a dispatch interface and a + * ITypeComp interface for typing. + * + * Result: + * true iff successful. Error string in interpreter. + * Side effects: + * Depends on the method being invoked. + *------------------------------------------------------------------------- + */ +bool OptclObj::InvokeWithTypeInf (Tcl_Interp *pInterp, long invokekind, + int objc, Tcl_Obj *CONST objv[], + IDispatch *pDisp, ITypeInfo *pti, ITypeComp *pCmp) +{ + VARIANT varResult; + VariantInit(&varResult); + TObjPtr presult; + + bool bok; + bok = InvokeWithTypeInfVariant (pInterp, invokekind, objc, objv, pDisp, pti, pCmp, varResult); + + // set the result of the operation to the return value of the function + if (bok && (bok = var2obj(pInterp, varResult, presult))) + Tcl_SetObjResult (pInterp, presult); + VariantClear(&varResult); + return bok; +} + + + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::InvokeNoTypeInf -- + * Performs a member invocation without any type information on an + * IDispatch interface. + * + * Result: + * true iff successful. Else, error string in interpreter. + * Side effects: + * Depends on the methods being invoked. + *------------------------------------------------------------------------- + */ + +bool OptclObj::InvokeNoTypeInf( Tcl_Interp *pInterp, long invokekind, + int objc, Tcl_Obj *CONST objv[], + IDispatch *pDisp) +{ + VARIANT var; + VariantInit (&var); + TObjPtr presult; + bool bok; + + if (bok = InvokeNoTypeInfVariant (pInterp, invokekind, objc, objv, pDisp, var)) { + if (bok = var2obj(pInterp, var, presult)) + Tcl_SetObjResult (pInterp, presult); + VariantClear(&var); + } + + return bok; +} + + + +/* + *------------------------------------------------------------------------- + * OptclObj::InvokeNoTypeInfVariant -- + * The same as InvokeNoTypeInf, but instead of placing the result in + * the interpreter, returns within a variant. + * Result: + * true iff successful. Else, error string in interpreter + * Side effects: + * Depends on member being invoked + *------------------------------------------------------------------------- + */ +bool OptclObj::InvokeNoTypeInfVariant ( Tcl_Interp *pInterp, long invokekind, + int objc, Tcl_Obj *CONST objv[], + IDispatch *pDisp, VARIANT &varResult) +{ + ASSERT (varResult.vt == VT_EMPTY); + + DispParams dp; + DISPID dispid; + HRESULT hr; + TObjPtr obj; + EXCEPINFO ei; + UINT ea = 0; + bool bOk = false; + + ASSERT (objc >= 1); + ASSERT (pDisp != NULL); + + obj.attach(objv[0]); + dispid = Name2ID(pDisp, obj); + if (dispid == DISPID_UNKNOWN) { + Tcl_SetResult (pInterp, "member not found: ", TCL_STATIC); + Tcl_AppendResult (pInterp, obj, NULL); + } else { + objc--; // count of parameters + // set up the dispatch arguments - must be in reverse order + dp.Args (objc); + for (int i = objc-1; i >= 0; i--) + { + obj.attach(objv[i+1]); + obj2var(obj, dp[i]); + } + + hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, invokekind, + &dp, &varResult, &ei, &ea); + if (hr == DISP_E_EXCEPTION) + Tcl_SetResult (pInterp, ExceptInfo2Str (&ei), TCL_DYNAMIC); + else if (hr == DISP_E_TYPEMISMATCH) { + TDString td("type mismatch in parameter #"); + td << (long)(ea); + Tcl_SetResult (pInterp, td, TCL_VOLATILE); + } + else if (FAILED(hr)) + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + else { + } + } + + return bOk; +} + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::GetProp -- + * Called to get the value of a property (a property can be indexed) + * If type information is provided, then it will be used in the invocation + * Result: + * true iff ok. Else, error string in interpreter + * Side effects: + * Depends on the property and its value. + *------------------------------------------------------------------------- + */ +bool OptclObj::GetProp (Tcl_Interp *pInterp, Tcl_Obj *name, + IDispatch *pdisp, ITypeInfo *pti, ITypeComp *ptc) +{ + ASSERT (pInterp != NULL && name != NULL && pdisp != NULL); + TObjPtr params; + bool bok; + + if (bok = SplitBrackets (pInterp, name, params)) { + int length = params.llength(); + ASSERT (length >= 1); + Tcl_Obj ** pplist = (Tcl_Obj **)malloc(sizeof(Tcl_Obj*) * length); + if (pplist == NULL) { + Tcl_SetResult (pInterp, "out of memory", TCL_STATIC); + return false; + } + + for (int p = 0; p < length; p++) + pplist[p] = params.lindex(p); + + if (pti != NULL) { + ASSERT (ptc != NULL); + bok = InvokeWithTypeInf(pInterp, DISPATCH_PROPERTYGET, length, pplist, pdisp, pti, ptc); + } + else { + bok = InvokeNoTypeInf (pInterp, DISPATCH_PROPERTYGET, length, pplist, pdisp); + } + + free(pplist); + } + return bok; +} + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::GetIndexedVariant -- + * Called to get the value of a property or the return type of method, with + * bracket indexing. + * If type information is provided, then it will be used in the invocation + * Result: + * true iff ok. Else, error string in interpreter + * Side effects: + * Depends on the property and its value. + *------------------------------------------------------------------------- + */ +bool OptclObj::GetIndexedVariant (Tcl_Interp *pInterp, Tcl_Obj *name, + IDispatch *pdisp, ITypeInfo *pti, ITypeComp *ptc, VARIANT &varResult) +{ + ASSERT (pInterp != NULL && name != NULL && pdisp != NULL); + ASSERT (varResult.vt == VT_EMPTY); + + TObjPtr params; + TObjPtr presult; + bool bok; + static const int invkind = DISPATCH_PROPERTYGET|DISPATCH_METHOD; + if (bok = SplitBrackets (pInterp, name, params)) { + int length = params.llength(); + ASSERT (length >= 1); + Tcl_Obj ** pplist = (Tcl_Obj **)malloc(sizeof(Tcl_Obj*) * length); + if (pplist == NULL) { + Tcl_SetResult (pInterp, "out of memory", TCL_STATIC); + return false; + } + + for (int p = 0; p < length; p++) + pplist[p] = params.lindex(p); + + if (pti != NULL) { + ASSERT (ptc != NULL); + bok = InvokeWithTypeInfVariant (pInterp, invkind, length, pplist, pdisp, pti, ptc, varResult); + } + else { + bok = InvokeNoTypeInfVariant (pInterp, invkind, length, pplist, pdisp, varResult); + } + free(pplist); + } + return bok; +} + +bool OptclObj::SetProp (Tcl_Interp *pInterp, + int paircount, Tcl_Obj * CONST namevalues[], + IDispatch *pdisp, ITypeInfo *pti, ITypeComp *ptc) +{ + bool bok = true; + ASSERT (pInterp != NULL && paircount > 0 && namevalues != NULL && pdisp != NULL); + for (int i = 0; bok && i < paircount; i++) + { + TObjPtr params; + if (bok = SplitBrackets (pInterp, namevalues[0], params)) { + params.lappend(namevalues[1]); + int length = params.llength(); + ASSERT (length >= 1); + Tcl_Obj ** pplist = (Tcl_Obj **)malloc(sizeof(Tcl_Obj*) * length); + if (pplist == NULL) { + Tcl_SetResult (pInterp, "out of memory", TCL_STATIC); + return false; + } + + + for (int p = 0; p < length; p++) + pplist[p] = params.lindex(p); + + if (pti != NULL) { + ASSERT (ptc != NULL); + bok = InvokeWithTypeInf(pInterp, DISPATCH_PROPERTYPUT, length, pplist, pdisp, pti, ptc); + } + else { + bok = InvokeNoTypeInf (pInterp, DISPATCH_PROPERTYPUT, length, pplist, pdisp); + } + namevalues += 2; + free(pplist); + } + } + if (bok) + Tcl_ResetResult (pInterp); + return true; +} + + + + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::GetPropVariantDispatch -- + * Retrieves the value of property as a variant, relative to a dispatch + * interface. + * + * Result: + * true iff successful. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool OptclObj::GetPropVariantDispatch (Tcl_Interp *pInterp, const char*name, + IDispatch* pcurrent, VARIANT &varResult) + +{ + USES_CONVERSION; + + ASSERT (pcurrent != NULL && pInterp != NULL); + + DISPID dispid; + HRESULT hr; + DISPPARAMS dispparamsNoArgs; SETNOPARAMS (dispparamsNoArgs); + EXCEPINFO ei; + bool bOk = false; + + dispid = Name2ID (pcurrent, name); + if (dispid == DISPID_UNKNOWN) { + Tcl_SetResult (pInterp, "property not found: ", TCL_STATIC); + Tcl_AppendResult (pInterp, name, NULL); + return false; + } + + hr = pcurrent->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, + &dispparamsNoArgs, &varResult, &ei, NULL); + if (hr == DISP_E_EXCEPTION) + Tcl_SetResult (pInterp, ExceptInfo2Str (&ei), TCL_DYNAMIC); + else if (FAILED(hr)) + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + else + bOk = true; + + return bOk; +} + + + + + + + + + + +/* + *------------------------------------------------------------------------- + * ResolvePropertyObject -- + * Resolves a property list of objects in the dot format + * e.g. application.documents(1).pages(2) + * Result: + * true iff successful to bind the ppunk parameter to a valid + * Side effects: + * + *------------------------------------------------------------------------- + */ +bool OptclObj::ResolvePropertyObject (Tcl_Interp *pInterp, const char *sname, + IDispatch **ppdisp, ITypeInfo **ppinfo, ITypeComp **ppcmp /* = NULL*/) +{ + USES_CONVERSION; + ASSERT (pInterp != NULL && ppdisp != NULL && sname != NULL); + // copy the string onto the stack + char * szname; + char * seps = "."; + char * szprop = NULL; + _variant_t varobj; + VARIANT varResult; + + HRESULT hr; + + TObjPtr pcmd; + TObjPtr plist; + TObjPtr pokstring; + + szname = (char*)_alloca (strlen (sname) + 1); + strcpy (szname, sname); + szprop = strtok(szname, seps); + CComQIPtr current; + CComPtr pti; + CComPtr pcmp; + + UINT typecount = 0; + + current = m_pcurrent; + pti = m_pti; + pcmp = m_ptc; + + pcmd.create(); + + VariantInit (&varResult); + + try { + while (szprop != NULL) + { + TObjPtr prop(szprop); + + VariantClear(&varResult); + if (!GetIndexedVariant (pInterp, prop, current, pti, pcmp, varResult)) + break; + + // check that it's an object + if (varResult.vt != VT_DISPATCH && varResult.vt != VT_UNKNOWN) + { + Tcl_SetResult (pInterp, "'", TCL_STATIC); + Tcl_AppendResult (pInterp, szprop, "' is not an object", NULL); + break; + } + + else + { + current = varResult.punkVal; + if (current == NULL) + { + Tcl_SetResult (pInterp, "'", TCL_STATIC); + Tcl_AppendResult (pInterp, szprop, "' is not a dispatchable object", NULL); + break; + } + typecount = 0; + pti = NULL; + pcmp = NULL; + + current->GetTypeInfoCount (&typecount); + if (typecount > 0) { + hr = current->GetTypeInfo (0, LOCALE_SYSTEM_DEFAULT, &pti); + if (SUCCEEDED(hr)) { + g_libs.EnsureCached (pti); + } + pti->GetTypeComp(&pcmp); + } + } + + // get the next property + szprop = strtok(NULL, seps); + } + + *ppinfo = pti.Detach(); + *ppcmp = pcmp.Detach(); + *ppdisp = current.Detach (); + } + + catch (HRESULT hr) + { + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + } + + catch (char * error) + { + Tcl_SetResult (pInterp, error, TCL_STATIC); + } + VariantClear(&varResult); + return (szprop == NULL); +} + + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::GetBinding -- + * Retrieves the current binding, if any for a properly formed event. + * Event is in the form of either + * 'event_name' on default interface + * 'lib.type.event_name' + * + * Result: + * true iff successful. Error in interpreter. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool OptclObj::GetBinding (Tcl_Interp *pInterp, char *pname) +{ + ASSERT (pInterp != NULL && pname != NULL); + + EventBindings * pbinding = NULL; + GUID guid; + CComPtr + pti; + int ne; + TObjPtr name(pname); + TObjPtr sr; + + + // split the name + sr.create(); + if (!SplitObject(pInterp, name, ".", &sr)) + return false; + + ne = sr.llength(); + if (ne <= 0) + return false; + + // check for a split on strings ending with a token + if ((*(char*)(sr.lindex(ne - 1))) == '\0') { + if (--ne <= 0) + return false; + } + + if (ne != 1 && ne != 3) { + Tcl_SetResult (pInterp, "wrong event format: should be either 'eventname' or 'lib.type.eventname'", TCL_STATIC); + return NULL; + } + + if (ne == 1 && !FindDefaultEventInterface(pInterp, &pti, &guid)) + return false; + else if (ne == 3 && FindEventInterface (pInterp, sr.lindex(0), sr.lindex(1), &pti, &guid)) + return false; + + if (m_bindings.find(&guid, &pbinding) == NULL) { + Tcl_ResetResult (pInterp); + return true; + } + else + return pbinding->GetBinding (pInterp, name); +} + + + +/* + *------------------------------------------------------------------------- + * OptclObj::SetBinding -- + * Sets an event binding for the event pointed by 'pname' to the tcl command + * stored in 'pcmd'. + * Result: + * true iff successful. Else error in interpreter. + * Side effects: + * Any earlier binding for this event will be removed. + *------------------------------------------------------------------------- + */ +bool OptclObj::SetBinding (Tcl_Interp *pInterp, char *pname, Tcl_Obj *pcmd) +{ + ASSERT (pInterp != NULL && pname != NULL && pcmd != NULL); + ASSERT (m_punk != NULL); + + TObjPtr name(pname); + TObjPtr cmd(pcmd, false); + + TObjPtr sr; // split result + int ne; // name elements + GUID guid; // id of the event interface + HRESULT hr; + + CComPtr + pti; // typeinfo for the event interface + + EventBindings * // the bindings for this interface + pbinding = NULL; + + + // split the name + sr.create(); + if (!SplitObject(pInterp, name, ".", &sr)) + return false; + + ne = sr.llength(); + if (ne <= 0) + return false; + + // check for a split on strings ending with a token + if ((*(char*)(sr.lindex(ne - 1))) == '\0') { + if (--ne <= 0) + return false; + } + + if (ne != 1 && ne != 3) { + Tcl_SetResult (pInterp, "wrong event format: should be either 'eventname' or 'lib.type.eventname'", TCL_STATIC); + return NULL; + } + + if (ne == 1 && !FindDefaultEventInterface(pInterp, &pti, &guid)) + return false; + else if (ne == 3 && !FindEventInterface (pInterp, sr.lindex(0), sr.lindex(1), &pti, &guid)) + return false; + + + if (m_bindings.find(&guid, &pbinding) == NULL) + { + pbinding = new EventBindings (this, guid, pti); + // initiate the advise + hr = m_punk.Advise((IUnknown*)(pbinding), guid, &(pbinding->m_cookie)); + if (FAILED(hr)) { + delete pbinding; + Tcl_SetResult (pInterp, HRESULT2Str (hr), TCL_DYNAMIC); + return false; + } + m_bindings.set(&guid, pbinding); + } + + // deleting a single event binding + if ((*(char*)cmd) == '\0') { + if (!pbinding->DeleteBinding (pInterp, sr.lindex(ne==1?0:2))) + return false; + // total number of bindings for this interface is now zero? + if (pbinding->TotalBindings() == 0) { + // unadvise - CComPtr doesn't have this!! + CComQIPtr pcpc; + CComPtr pcp; + pcpc = m_punk; + ASSERT (pcpc != NULL); + pcpc->FindConnectionPoint (guid, &pcp); + ASSERT (pcp != NULL); + pcp->Unadvise (pbinding->m_cookie); + m_bindings.delete_entry(&guid); + delete pbinding; + } + } + else if (!pbinding->SetBinding (pInterp, sr.lindex(ne==1?0:2), pcmd)) + return false; + + return true; +} + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::FindDefaultEventInterface -- + * Retrieves the default event interface for this object. + * Result: + * true iff successful. Else, error string in interpreter. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool OptclObj::FindDefaultEventInterface (Tcl_Interp *pInterp, ITypeInfo **ppinfo, GUID *pguid) +{ + ASSERT (pInterp != NULL && ppinfo != NULL && pguid != NULL); + ASSERT (m_punk != NULL); + + bool bOk = false; + TYPEATTR * pattr = NULL; + HRESULT hr; + USHORT impltypes; + CComPtr peti; + + + if (m_pti_class == NULL) + Tcl_SetResult (pInterp, "class-less object doesn't have a default event interface", TCL_STATIC); + else + { + hr = m_pti_class->GetTypeAttr (&pattr); + CHECKHR_TCL(hr, pInterp, false); + impltypes = pattr->cImplTypes; + m_pti_class->ReleaseTypeAttr(pattr); pattr = NULL; + + for (USHORT i = 0; i < impltypes; i++) + { + INT flags; + HREFTYPE href; + if (SUCCEEDED(m_pti_class->GetImplTypeFlags (i, &flags)) + && (flags & IMPLTYPEFLAG_FDEFAULT) // default interface and .. + && (flags & IMPLTYPEFLAG_FSOURCE) // an event source + && SUCCEEDED(m_pti_class->GetRefTypeOfImplType(i, &href)) + && SUCCEEDED(m_pti_class->GetRefTypeInfo (href, &peti))) + { + i = impltypes; // quits this loop + // while we're here, we'll make sure that this type is cached + g_libs.EnsureCached(peti); + } + } + + if (peti != NULL) + { + hr = peti->GetTypeAttr (&pattr); + CHECKHR_TCL(hr, pInterp, false); + *pguid = pattr->guid; + peti->ReleaseTypeAttr(pattr); pattr = NULL; + *ppinfo = peti; + (*ppinfo)->AddRef(); + bOk = true; + } + } + return bOk; +} + + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::FindEventInterface -- + * Called to find an event type info and guid given library and type of + * event interface. + * + * Result: + * true iff successful. Else, error string in interpreter. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool OptclObj::FindEventInterface (Tcl_Interp *pInterp, const char * lib, const char *type, + ITypeInfo **ppinfo, GUID * pguid) +{ + + ASSERT (pInterp != NULL && lib != NULL && type != NULL && ppinfo != NULL); + ASSERT (pguid != NULL); + ASSERT (m_punk != NULL); + + USES_CONVERSION; + CComPtr peti; + CComPtr petl; + + bool bOk = false; + TYPEATTR * pattr = NULL; + BSTR bType = NULL; + BSTR bLib = NULL; + HRESULT hr; + UINT dummy; + + + if (m_pti_class == NULL) { + // we don't have any class information + // try going through the typelibraries + try { + TypeLib_ResolveName (lib, type, NULL, &peti); + if (peti == NULL) + Tcl_SetResult (pInterp, "binding through typelib for class-less object failed", TCL_STATIC); + } + + catch (char *err) { + Tcl_SetResult (pInterp, err, TCL_VOLATILE); + } + + catch (HRESULT hr) { + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + } + } + + else + { + // we do have class information + // this will ensure that even if the type library for the event + // interface is not loaded (yes, it can be different to that of the + // object that's using it, it will still be found. + + // convert the event interface name to a bstring + bType = A2BSTR(type); + bLib = A2BSTR(lib); + // get the number of implemented types + hr = m_pti_class->GetTypeAttr (&pattr); + CHECKHR_TCL(hr, pInterp, false); // beware, conditional return here + USHORT types = pattr->cImplTypes; + m_pti_class->ReleaseTypeAttr (pattr); pattr = NULL; + + // loop throught the implemented types + for (USHORT intf = 0; intf < types; intf++) + { + INT flags; + HREFTYPE href; + CComBSTR btypename, + blibname; + + // if we the implementation flags is an event source and + // the name of the referenced type is the same + if (SUCCEEDED(m_pti_class->GetImplTypeFlags (intf, &flags)) + && (flags&IMPLTYPEFLAG_FSOURCE) + && SUCCEEDED(m_pti_class->GetRefTypeOfImplType (intf, &href)) + && SUCCEEDED(m_pti_class->GetRefTypeInfo (href, &peti)) + && SUCCEEDED(peti->GetContainingTypeLib(&petl, &dummy)) + && SUCCEEDED(peti->GetDocumentation(MEMBERID_NIL, &btypename, NULL, NULL, NULL)) + && SUCCEEDED(petl->GetDocumentation(-1, &blibname, NULL, NULL, NULL))) + { + if ((btypename == bType) && (blibname == bLib)) { + intf = types; // quits this loop + // while we're at it, lets make sure that this typelibrary is + // registered. + g_libs.EnsureCached(petl); + } + } + else { + peti = NULL; + petl = NULL; + } + btypename.Empty(); + blibname.Empty(); + } + + if (peti == NULL) + Tcl_SetResult (pInterp, "couldn't find event interface", TCL_STATIC); + } + + if (peti != NULL) { + // if we've got a typeinfo, find the GUID + hr = peti->GetTypeAttr (&pattr); + CHECKHR_TCL (hr, pInterp, false); + *pguid = pattr->guid; + peti->ReleaseTypeAttr(pattr); pattr = NULL; + *ppinfo = peti; + (*ppinfo)->AddRef(); + bOk = true; + } + return bOk; +} + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::ReleaseBindingTable -- + * Releases the bindings withing the event bindings hash table. + * It's probably very important that this isn't called within the + * evaluation of an event. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void OptclObj::ReleaseBindingTable() +{ + CComQIPtr pcpc; + EventBindings * pbinding; + CComPtr pcp; + + + pcpc = m_punk; + if (pcpc == NULL) + return; + + EventBindingsTbl::iterator i; + for (i = m_bindings.begin(); i != m_bindings.end(); i++) + { + pbinding = *i; + pcpc->FindConnectionPoint (*(i.key()), &pcp); + if (pcp != NULL) { + pcp->Unadvise(pbinding->m_cookie); + pcp = NULL; + } + else { + // this case occurs when the com object has been destroyed + // before this object is destroyed + } + delete pbinding; + } +} + + + + +/* + *------------------------------------------------------------------------- + * OptclObj::GetState -- + * This is some prelim code for persistence support - yanked out of the + * old container code - more soon! + * + * Result: + * + * Side effects: + * + *------------------------------------------------------------------------- + */ +bool OptclObj::GetState (Tcl_Interp *pInterp) +{ + ASSERT (pInterp != NULL); + USES_CONVERSION; + + CComPtr pStream; + CComQIPtr pPS; + CComQIPtr pPSI; + + HGLOBAL hMem; // handle to memory + LPVOID pMem; // pointer to memory + HRESULT hr; + DWORD dwSize; // size of memory used + TObjPtr pObjs[2]; // objects to automanage the tcl_obj lifetimes + Tcl_Obj * pResult; // pointers used to create the result list + CLSID clsid; + LPOLESTR lpOleStr; + + + pPS = m_punk; + pPSI = m_punk; + if (!pPS && !pPSI) { + Tcl_SetResult (pInterp, "object does not support stream persistance model", TCL_STATIC); + return false; + } + + hMem = GlobalAlloc (GHND, 0); + if (hMem == NULL) { + Tcl_SetResult (pInterp, "unable to initialise global memory", TCL_STATIC); + return false; + } + + hr = CreateStreamOnHGlobal (hMem, TRUE, &pStream); + if (FAILED(hr)) { + GlobalFree (hMem); + Tcl_SetResult (pInterp, "unable to create a stream on global memory", TCL_STATIC); + return false; + } + + if (pPS) + hr = pPS->Save (pStream, TRUE); + else + hr = pPSI->Save(pStream, TRUE); + + + if (FAILED(hr)) { + if (hr == STG_E_CANTSAVE) + Tcl_SetResult (pInterp, "failed to save object", TCL_STATIC); + else if (hr == STG_E_MEDIUMFULL) + Tcl_SetResult (pInterp, "failed to aquire enough memory", TCL_STATIC); + return false; + } + dwSize = GlobalSize(hMem); + pMem = GlobalLock (hMem); + + ATLASSERT (pMem); + pObjs[1] = Tcl_NewStringObj ((char*)pMem, dwSize); + GlobalUnlock (hMem); + + // now get the clsid + if (pPS) + hr = pPS->GetClassID (&clsid); + else + hr = pPSI->GetClassID (&clsid); + + if (FAILED(hr)) + { + Tcl_SetResult (pInterp, "failed to retrieve the clsid", TCL_STATIC); + return false; + } + + hr = StringFromCLSID (clsid, &lpOleStr); + if (FAILED(hr)) { + Tcl_SetResult (pInterp, "failed to convert clsid to a string", TCL_STATIC); + return false; + } + pObjs[0] = Tcl_NewStringObj (OLE2A(lpOleStr), -1); + pResult = Tcl_NewListObj (0, NULL); + Tcl_ListObjAppendElement (NULL, pResult, pObjs[0]); + Tcl_ListObjAppendElement (NULL, pResult, pObjs[1]); + Tcl_SetObjResult (pInterp, pResult); + return true; +} + + +/* + *------------------------------------------------------------------------- + * OptclObj::ContainerWantsToDie -- + * Called by the Tk widget container, when it is about to be destroyed. + * If we are not currently destroying this object, then instigate it. + * + * Result: + * None. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void OptclObj::ContainerWantsToDie () +{ + if (!m_destroypending) + g_objmap.Delete(this); +} + + diff --git a/src/OptclObj.h b/src/OptclObj.h new file mode 100644 index 0000000..5d296f0 --- /dev/null +++ b/src/OptclObj.h @@ -0,0 +1,142 @@ +/* + *------------------------------------------------------------------------------ + * optclobj.cpp + * Declares the functionality for the internal representation of + * an optcl object. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#if !defined(AFX_OPTCLOBJ_H__8A11BC04_616B_11D4_8004_0040055861F2__INCLUDED_) +#define AFX_OPTCLOBJ_H__8A11BC04_616B_11D4_8004_0040055861F2__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// forward declarations of used classes +#include "container.h" +#include + +class ObjMap; +class EventBindings; +class OptclBindPtr; +class DispParams; + +typedef THash EventBindingsTbl; + + +class OptclObj { +friend ObjMap; +friend CContainer; + + +public: + OptclObj (); + virtual ~OptclObj (); + + bool Create (Tcl_Interp *pInterp, const char *strid, const char *windowpath, bool start); + bool Attach (Tcl_Interp *pInterp, LPUNKNOWN punk); + + operator LPUNKNOWN(); + operator const char * (); + + void CoClassName (TObjPtr &pObj); + void InterfaceName (TObjPtr &pObj); + void SetInterfaceName (TObjPtr &pObj); + + bool InvokeCmd (Tcl_Interp *pInterp, int objc, Tcl_Obj *CONST objv[]); + + bool OptclObj::ResolvePropertyObject (Tcl_Interp *pInterp, const char *sname, + IDispatch **ppdisp, ITypeInfo **ppinfo, ITypeComp **ppcmp); + + bool GetBinding (Tcl_Interp *pInterp, char *name); + bool SetBinding (Tcl_Interp *pInterp, char *name, Tcl_Obj *command); + + bool GetState (Tcl_Interp *pInterp); + + + +protected: // methods + void CreateName (LPUNKNOWN punk); + void InitialiseUnknown (LPUNKNOWN punk); + void InitialiseClassInfo (LPUNKNOWN punk); + void InitialisePointers (LPUNKNOWN punk, ITypeLib *pLib = NULL, ITypeInfo *pinfo = NULL); + void CreateCommand(); + HRESULT InitialisePointersFromCoClass (); + HRESULT SetInterfaceFromType (ITypeInfo *pinfo); + HRESULT GetTypeAttr(); + void ReleaseTypeAttr(); + void ReleaseBindingTable(); + + + + bool BuildParamsWithBindPtr (Tcl_Interp *pInterp, int objc, Tcl_Obj *CONST objv[], + OptclBindPtr & bp, DispParams & dp); + bool RetrieveOutParams (Tcl_Interp *pInterp, int objc, Tcl_Obj *CONST objv[], + OptclBindPtr & bp, DispParams & dp); + + bool InvokeNoTypeInfVariant (Tcl_Interp *pInterp, long ik, int objc, Tcl_Obj *CONST objv[], + IDispatch *pDisp, VARIANT &varResult); + bool InvokeNoTypeInf (Tcl_Interp *pInterp, long ik, int objc, Tcl_Obj *CONST objv[], + IDispatch *pDisp); + + bool InvokeWithTypeInfVariant (Tcl_Interp *pInterp, long invokekind, + int objc, Tcl_Obj *CONST objv[], + IDispatch *pDisp, ITypeInfo *pti, ITypeComp *pCmp, VARIANT &varResult); + bool InvokeWithTypeInf (Tcl_Interp *pInterp, long ik, int objc, Tcl_Obj *CONST objv[], + IDispatch *pDisp, ITypeInfo *pti, ITypeComp *pcmp); + + bool CheckInterface (Tcl_Interp *pInterp); + + bool SetProp (Tcl_Interp *pInterp, int paircount, Tcl_Obj * CONST namevalues[], + IDispatch *pdisp, ITypeInfo *pti, ITypeComp *ptc); + + bool GetProp (Tcl_Interp *pInterp, Tcl_Obj *name, IDispatch *pDisp, ITypeInfo *pti, ITypeComp *ptc); + bool GetIndexedVariant (Tcl_Interp *pInterp, Tcl_Obj *name, + IDispatch *pdisp, ITypeInfo *pti, ITypeComp *ptc, VARIANT &varResult); + + bool GetPropVariantDispatch (Tcl_Interp *pInterp, const char*name, + IDispatch * pcurrent, VARIANT &varResult); + + bool FindEventInterface (Tcl_Interp *pInterp, const char * lib, const char * type, + ITypeInfo **ppinfo, GUID * pguid); + + bool FindDefaultEventInterface (Tcl_Interp *pInterp, ITypeInfo **ppinfo, GUID *pguid); + + void ContainerWantsToDie (); +protected: // properties + CComQIPtr m_pcurrent; // Current interface + CComPtr m_punk; // the 'true' IUnknown; reference purposes only + CComPtr m_ptl; // the type library for this object + CComPtr m_pti; // the type interface for the current interface + CComPtr m_ptc; // the type info's compiler interface + CComPtr m_pti_class;// the type interface for the this coclass + TYPEATTR * m_pta; // the type attribute for the current typeinfo + + std::string m_name; + unsigned long m_refcount; // reference count of this optcl object + Tcl_Interp * m_pInterp; // interpreter that created this object + Tcl_Command m_cmdtoken; // command token of the tcl command within the above interpreter + EventBindingsTbl m_bindings; // bindings for event interfaces of this object + CContainer m_container;// container + bool m_destroypending; // true during a final delete operation +}; + + +#endif // !defined(AFX_OPTCLOBJ_H__8A11BC04_616B_11D4_8004_0040055861F2__INCLUDED_) diff --git a/src/OptclTypeAttr.cpp b/src/OptclTypeAttr.cpp new file mode 100644 index 0000000..452b04b --- /dev/null +++ b/src/OptclTypeAttr.cpp @@ -0,0 +1,84 @@ +/* + *------------------------------------------------------------------------------ + * optcltypeattr.cpp + * Implementation of the OptclTypeAttr class, a wrapper for the TYPEATTR + * pointer type. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#include "stdafx.h" +#include "tbase.h" +#include "optcl.h" +#include "utility.h" +#include "OptclTypeAttr.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +OptclTypeAttr::OptclTypeAttr() : m_pattr(NULL) +{ + +} + +OptclTypeAttr::~OptclTypeAttr() +{ + ReleaseTypeAttr(); +} + + +HRESULT OptclTypeAttr::GetTypeAttr () +{ + HRESULT hr = S_OK; + // only get if we haven't already + if (m_pattr == NULL) { + ASSERT (m_pti != NULL); + hr = m_pti->GetTypeAttr (&m_pattr); + } + return hr; +} + + +void OptclTypeAttr::ReleaseTypeAttr () +{ + if (m_pattr != NULL) + { + ASSERT (m_pti != NULL); + m_pti->ReleaseTypeAttr(m_pattr);; + m_pattr = NULL; + } +} + + +OptclTypeAttr & OptclTypeAttr::operator= (ITypeInfo *pti) +{ + ReleaseTypeAttr(); + m_pti = pti; + if (m_pti != NULL) + GetTypeAttr(); + return *this; +} + + +TYPEATTR * OptclTypeAttr::operator -> () +{ + ASSERT (m_pattr != NULL); + return m_pattr; +} + diff --git a/src/OptclTypeAttr.h b/src/OptclTypeAttr.h new file mode 100644 index 0000000..5ed6917 --- /dev/null +++ b/src/OptclTypeAttr.h @@ -0,0 +1,47 @@ +/* + *------------------------------------------------------------------------------ + * optcltypeattr.h + * Definition of the OptclTypeAttr class, a wrapper for the TYPEATTR + * pointer type. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#if !defined(AFX_OPTCLTYPEATTR_H__5826EED2_5FA7_11D3_86E8_0000B482A708__INCLUDED_) +#define AFX_OPTCLTYPEATTR_H__5826EED2_5FA7_11D3_86E8_0000B482A708__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class OptclTypeAttr +{ +public: + CComPtr m_pti; + TYPEATTR * m_pattr; + +public: + OptclTypeAttr(); + virtual ~OptclTypeAttr(); + HRESULT GetTypeAttr (); + void ReleaseTypeAttr (); + OptclTypeAttr & operator= (ITypeInfo *pti); + TYPEATTR * operator -> (); +}; + +#endif // !defined(AFX_OPTCLTYPEATTR_H__5826EED2_5FA7_11D3_86E8_0000B482A708__INCLUDED_) diff --git a/src/StdAfx.cpp b/src/StdAfx.cpp new file mode 100644 index 0000000..4f7f50b --- /dev/null +++ b/src/StdAfx.cpp @@ -0,0 +1,27 @@ +/* + *------------------------------------------------------------------------------ + * stdafx.cpp + * source file that includes just the standard includes + * optcl.pch will be the pre-compiled header + * stdafx.obj will contain the pre-compiled type information + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + + +#include "stdafx.h" diff --git a/src/StdAfx.h b/src/StdAfx.h new file mode 100644 index 0000000..93fcdcf --- /dev/null +++ b/src/StdAfx.h @@ -0,0 +1,56 @@ +/* + *------------------------------------------------------------------------------ + * stdafx.cpp + * include file for standard system include files, or project specific + * include files that are used frequently, but are changed infrequently + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__1363E007_C12C_11D2_8003_0040055861F2__INCLUDED_) +#define AFX_STDAFX_H__1363E007_C12C_11D2_8003_0040055861F2__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +// Insert your headers here +//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include +extern CComModule _Module; +#include +#include +#include + +#include +#include +#include +#include + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__1363E007_C12C_11D2_8003_0040055861F2__INCLUDED_) diff --git a/src/conversion.txt b/src/conversion.txt new file mode 100644 index 0000000..5027cfd --- /dev/null +++ b/src/conversion.txt @@ -0,0 +1,51 @@ +Conversion + VT_EMPTY = 0, // 0 + VT_VOID = 24, // 0 + VT_NULL = 1, // 0 + + + VT_VARIANT = 12, // VARIANT * - decode by reference + + VT_ERROR = 10, // short + VT_I2 = 2, // short + VT_UI1 = 17, // short + + VT_I4 = 3, // long + VT_UI2 = 18, // long + VT_INT = 22, // long + + VT_R4 = 4, // float + VT_R8 = 5, // real + + VT_BOOL = 11, // boolean + + VT_UNKNOWN = 13, // object + VT_DISPATCH = 9, // object + + VT_I1 = 16, // char + + + *** VT_DECIMAL = 14, // can't - string? no + *** VT_CARRAY = 28, // ? + + + VT_CY = 6, // string + VT_DATE = 7, // string + VT_BSTR = 8, // string + + VT_UI4 = 19, // string + VT_I8 = 20, // string + VT_UI8 = 21, // string + VT_UINT = 23, // string + + VT_HRESULT = 25, // HRESULT2Str + VT_SAFEARRAY = 27, // tcl list + VT_USERDEFINED = 29, // type info require + VT_RECORD = 36, // tcl list? - creating might be a bit hard + VT_VECTOR = 0x1000, // tcl list? + VT_ARRAY = 0x2000, // tcl list + VT_BYREF = 0x4000, // pointer to value - eek + + +convert an object to a variant using type k +template f (VARIANT *p \ No newline at end of file diff --git a/src/initonce.cpp b/src/initonce.cpp new file mode 100644 index 0000000..f473480 --- /dev/null +++ b/src/initonce.cpp @@ -0,0 +1,26 @@ +/* + *------------------------------------------------------------------------------ + * initonce.cpp + * This file is used to correctly perform the one-time initialisation + * of standard GUIDs. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#include +#include diff --git a/src/optcl.cpp b/src/optcl.cpp new file mode 100644 index 0000000..d2fa2e1 --- /dev/null +++ b/src/optcl.cpp @@ -0,0 +1,671 @@ +/* + *------------------------------------------------------------------------------ + * optcl.cpp + * Tcl gateway functions are placed here. De/Initialisation + * of the object map occurs here, together with registration of many of + * optcl's commands. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + + +#include "stdafx.h" +#include "tbase.h" +#include "utility.h" +#include "optcl.h" +#include "resource.h" +#include "optclobj.h" +#include "objmap.h" +#include "dispparams.h" +#include "typelib.h" + +//---------------------------------------------------------------- +HINSTANCE ghDll = NULL; +CComModule _Module; +CComPtr g_pmalloc; + +//---------------------------------------------------------------- + +// Function declarations +void Optcl_Exit (ClientData); + + +TCL_CMDEF(OptclNewCmd); +TCL_CMDEF(OptclLockCmd); +TCL_CMDEF(OptclUnlockCmd); +TCL_CMDEF(OptclClassCmd); +TCL_CMDEF(OptclInterfaceCmd); +TCL_CMDEF(OptclBindCmd); +TCL_CMDEF(OptclIsObjectCmd); +TCL_CMDEF(OptclInvokeLibFunction); + + +//---------------------------------------------------------------- + +/* + *------------------------------------------------------------------------- + * DllMain -- + * Windows entry point - ensures that ATL's ax containement are + * initialised. + * + * Result: + * TRUE. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ +#ifdef _DEBUG + int tmpFlag; +#endif // _DEBUG + + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + ghDll = hinstDLL; + _Module.Init (NULL, (HINSTANCE)hinstDLL); + AtlAxWinInit(); + + #ifdef _DEBUG + // memory leak detection - only in the debug build + tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); + tmpFlag |= _CRTDBG_LEAK_CHECK_DF; + _CrtSetDbgFlag( tmpFlag ); + #endif // _DEBUG + break; + case DLL_PROCESS_DETACH: + _Module.Term(); + break; + } + + return TRUE; +} + + +/* + *------------------------------------------------------------------------- + * Optcl_Exit -- + * Called by Tcl pending exit. Removes all optcl objects. Uninits OLE. + * Result: + * None. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void Optcl_Exit (ClientData) +{ + // remove all the elements of the table + g_objmap.DeleteAll (); + g_pmalloc.Release(); + OleUninitialize(); +} + + + +/* + *------------------------------------------------------------------------- + * OptclNewCmd -- + * Implements the optcl::new command. Format of this command currently is: + * ?-start? ?-window path? ProgIdOrClsidOrDocument + * For the time being, documents require the -window option to be used + * as this code relies on ATL containement to locate the document server. + * This constraint is not ensured by this code. + * This can easily be implemented for documents that are not to be contained. + * + * Result: + * Standard Tcl result. + * Side effects: + * Depends on parameters. + *------------------------------------------------------------------------- + */ +TCL_CMDEF(OptclNewCmd) +{ + OptclObj *pObj = NULL; + TObjPtr id; + Tcl_Obj ** old = (Tcl_Obj**)objv; + + char *path = NULL; + bool start = false; + static const char * err = "?-start? ?-window path? ProgIdOrClsidOrDocument"; + static const char * errcreate = "error in creating object"; + + if (objc < 2 || objc > 5) { + Tcl_WrongNumArgs (pInterp, 1, objv, (char*)err); + return TCL_ERROR; + } + + // do we have flags? + // process each one + while (objc >= 3) + { + TObjPtr element; + element.attach(objv[1]); + int len = strlen(element); + if (strncmp (element, "-start", len) == 0) { + start = true; + } + else if (strncmp (element, "-window", len) == 0) { + if (--objc <= 0) { + Tcl_SetResult (pInterp, "expected path after -window", TCL_STATIC); + return TCL_ERROR; + } + objv++; + element.attach(objv[1]); + path = (char*)element; + } + else { + Tcl_SetResult (pInterp, "unknown flag: ", TCL_STATIC); + Tcl_AppendResult (pInterp, (char*)element, NULL); + return TCL_ERROR; + } + if (--objc <= 0) { + Tcl_WrongNumArgs (pInterp, 1, old, (char*) err); + return TCL_ERROR; + } + objv++; + } + + id.attach (objv[1]); + + try { + // try creating the object + pObj = g_objmap.Create (pInterp, id, path, start); + if (pObj == NULL) + Tcl_SetResult (pInterp, (char*)errcreate, TCL_STATIC); + } + + catch (HRESULT hr) { + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + } + + catch (char *err) { + Tcl_SetResult (pInterp, err, TCL_VOLATILE); + } + + catch (...) + { + Tcl_SetResult (pInterp, (char*)errcreate, TCL_STATIC); + } + + if (pObj != NULL) { + Tcl_SetResult (pInterp, (char*)(const char*)(*pObj), TCL_VOLATILE); + return TCL_OK; + } + else + return TCL_ERROR; +} + + + + + + +/* + *------------------------------------------------------------------------- + * OptclLockCmd -- + * Implements the optcl::lock command. + * Result: + * Standard Tcl result + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +TCL_CMDEF(OptclLockCmd) +{ + if (objc != 2) { + Tcl_WrongNumArgs (pInterp, 1, objv, "object"); + return TCL_ERROR; + } + TObjPtr name; + name.attach(objv[1]); + if (!g_objmap.Lock(name)) { + return ObjectNotFound(pInterp, name); + } + return TCL_OK; +} + + + + + +/* + *------------------------------------------------------------------------- + * OptclUnlockCmd -- + * Implements the optcl::unlock command. + * + * Result: + * Standard Tcl result. + * + * Side effects: + * If the reference count of the object hits zero, then the object will be + * deleted, together with its Tcl command and its container window, if it + * exists. + *------------------------------------------------------------------------- + */ +TCL_CMDEF(OptclUnlockCmd) +{ + if (objc < 2) { + Tcl_WrongNumArgs (pInterp, 1, objv, "object ..."); + return TCL_ERROR; + } + + TObjPtr name; + for (int i = 1; i < objc; i++) { + name.attach(objv[1]); + g_objmap.Unlock(name); + } + return TCL_OK; +} + + + +/* + *------------------------------------------------------------------------- + * OptclInvokeLibFunction -- + * Wild and useless attempt at calling ITypeInfo declared static DLL + * functions. Sigh! + * Result: + * + * Side effects: + * + *------------------------------------------------------------------------- + */ +TCL_CMDEF(OptclInvokeLibFunction) +{ + USES_CONVERSION; + DispParams dp; + LPOLESTR olename; + TObjPtr name, + presult; + CComPtr pinfo; + CComPtr pti; + CComPtr pcmp; + HRESULT hr; + DESCKIND dk; dk = DESCKIND_NONE; + BINDPTR bp; bp.lpfuncdesc = NULL; + DISPID dispid; + EXCEPINFO ei; + UINT ea = 0; + VARIANT varResult; + bool bOk = false; + VOID * pFunc = NULL; + + if (objc < 3) { + Tcl_WrongNumArgs (pInterp, 1, objv, "typename function args..."); + return TCL_ERROR; + } + + try { + // attempt to resolve the type + name.attach(objv[1]); + TypeLib_ResolveName (name, NULL, &pinfo); + + hr = pinfo->GetTypeComp (&pcmp); + CHECKHR_TCL(hr, pInterp, TCL_ERROR); + + name.attach(objv[2]); + olename = A2OLE(name); + hr = pcmp->Bind (olename, LHashValOfName(LOCALE_SYSTEM_DEFAULT, olename), + INVOKE_FUNC, &pti, &dk, &bp); + + CHECKHR(hr); + if (dk != DESCKIND_FUNCDESC || bp.lpfuncdesc->funckind != FUNC_STATIC) { + Tcl_SetResult (pInterp, "static method not found: ", TCL_STATIC); + Tcl_AppendResult (pInterp, (char*)name, NULL); + } else { + ASSERT (bp.lpfuncdesc != NULL); + dispid = bp.lpfuncdesc->memid; + hr = pinfo->AddressOfMember (dispid, INVOKE_FUNC, &pFunc); + CHECKHR_TCL(hr, pInterp, TCL_ERROR); + int params = objc - 3; + + // check for the last parameter being the return value and take + // this into account when checking parameter counts + int reqparams = bp.lpfuncdesc->cParams; + if (reqparams > 0 && bp.lpfuncdesc->lprgelemdescParam[reqparams - 1].paramdesc.wParamFlags & PARAMFLAG_FRETVAL) + --reqparams; + + + if (params <= reqparams && + params >= (reqparams -bp.lpfuncdesc->cParamsOpt)) + { + VariantInit (&varResult); + + // set up the dispatch arguments - must be in reverse order + dp.Args (params); + for (int i = params-1; i >= 0; i--) + { + bool con_ok; + LPVARIANT pv; + + name.attach(objv[i+3]); + // are we dealing with referenced parameter? + if (bp.lpfuncdesc->lprgelemdescParam[i].tdesc.vt == VT_PTR) { + ASSERT (bp.lpfuncdesc->lprgelemdescParam[i].tdesc.lptdesc != NULL); + + // allocate a variant to store the *value* + pv = new VARIANT; + VariantInit (pv); + con_ok = obj2var_ti(pInterp, name, *pv, pti, &(bp.lpfuncdesc->lprgelemdescParam[i].tdesc)); + // we'll now set it as a reference for the dispatch parameters array + // on destruction, the array will take care of clearing the variant + dp.Set(params - i - 1, pv); + } + + else + con_ok = obj2var_ti(pInterp, name, dp[params - i - 1], pti, &(bp.lpfuncdesc->lprgelemdescParam[i].tdesc)); + + + if (!con_ok) + { + ReleaseBindPtr (pti, dk, bp); + return false; // error in type conversion + } + } + hr = pinfo->Invoke (pFunc, dispid, DISPATCH_METHOD, &dp, &varResult, &ei, &ea); + //hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, + // &dp, &varResult, &ei, &ea); + + if (hr == DISP_E_EXCEPTION) + Tcl_SetResult (pInterp, ExceptInfo2Str (&ei), TCL_DYNAMIC); + else if (hr == DISP_E_TYPEMISMATCH) { + TDString td("type mismatch in parameter #"); + td << (long)(ea); + Tcl_SetResult (pInterp, td, TCL_VOLATILE); + } + else + CHECKHR_TCL(hr, pInterp, TCL_ERROR); + if (FAILED(hr)) + return TCL_ERROR; + if (bOk = var2obj(pInterp, varResult, presult)) + Tcl_SetObjResult (pInterp, presult); + VariantClear(&varResult); + } + else + { + Tcl_SetResult (pInterp, "wrong # args", TCL_STATIC); + } + } + } + + catch (HRESULT hr) { + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + } + return bOk?TCL_OK:TCL_ERROR; +} + +/* + *------------------------------------------------------------------------- + * OptclClassCmd -- + * Implements the optcl::class command. + * + * Result: + * Standard Tcl result + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +TCL_CMDEF(OptclClassCmd) +{ + if (objc != 2) { + Tcl_WrongNumArgs (pInterp, 1, objv, "object"); + return TCL_ERROR; + } + OptclObj *pObj = NULL; + TObjPtr name; + TObjPtr classname; + + name.attach (objv[1]); + pObj = g_objmap.Find (name); + if (pObj == NULL) + return ObjectNotFound (pInterp, name); + try { + pObj->CoClassName(classname); + } + + catch (HRESULT hr) { + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + return TCL_ERROR; + } + Tcl_SetObjResult (pInterp, classname); + return TCL_OK; +} + + + + +/* + *------------------------------------------------------------------------- + * OptclInterfaceCmd -- + * Implements the optcl::interface command. Will either retrieve the + * current active interface or set it: + * optcl::interface objid ?newinterface? + * + * The new interface must be a proper typename. i.e. lib.type + * Result: + * Standard Tcl result. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +TCL_CMDEF(OptclInterfaceCmd) +{ + if (objc != 2 && objc != 3) { + Tcl_WrongNumArgs (pInterp, 1, objv, "object ?interface?"); + return TCL_ERROR; + } + + OptclObj *pObj = NULL; + TObjPtr name; + TObjPtr intfname; + + name.attach (objv[1]); + pObj = g_objmap.Find (name); + if (pObj == NULL) + return ObjectNotFound (pInterp, name); + try { + if (objc == 2) // get the current interface name + pObj->InterfaceName(intfname); + else // we are setting the interface + { + intfname.attach(objv[2]); + pObj->SetInterfaceName(intfname); + } + } + + catch (HRESULT hr) { + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + return TCL_ERROR; + } + catch (char *error) { + Tcl_SetResult (pInterp, error, TCL_VOLATILE); + return TCL_ERROR; + } + + Tcl_SetObjResult (pInterp, intfname); + return TCL_OK; +} + + + + +/* + *------------------------------------------------------------------------- + * OptclBindCmd -- + * Implements the optcl::bind command. This enables the setting, unsetting + * and retrieving of a binding to an objects event, either on its default + * interface (in which case the interface type is not required) or on + * a non-default event interface. e.g. + * optcl::bind $obj NewDoc OnNewDocTclhandler + * optcl::bind $obj NewDoc ==> OnNewDocTclhandler + * optcl::bind $obj ICustomInterface.Foo FooHandler + * + * The tcl command is then called when the specified event is fired. + * The parameter list of the event is prepended with the identifier + * object that fired event. If a parameter of an event is an object, + * it's lifetime is only within the duration of the execution of the + * tcl handler. To allow for the object to persist after the handler has + * completed, the tcl script must call optcl::lock on the object. + * + * Result: + * Standard Tcl result. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +TCL_CMDEF(OptclBindCmd) +{ + if (objc != 3 && objc != 4) + { + Tcl_WrongNumArgs (pInterp, 1, objv, "object event_name ?tcl_command?"); + return TCL_ERROR; + } + + OptclObj *pObj = NULL; + TObjPtr name; + TObjPtr value; + bool bOk = false; + + name.attach (objv[1]); + pObj = g_objmap.Find (name); + if (pObj == NULL) + return ObjectNotFound (pInterp, name); + + name.attach(objv[2]); // the event name + if (objc == 3) // get the current binding (if any) for an event + bOk = pObj->GetBinding (pInterp, name); + else // we are setting the interface + { + value.attach(objv[3]); + if (bOk = pObj->SetBinding(pInterp, name, value)) + Tcl_SetObjResult (pInterp, value); + } + return (bOk?TCL_OK:TCL_ERROR); +} + + + +/* + *------------------------------------------------------------------------- + * OptclIsObjectCmd -- + * Returns a boolean in the interpreter - true iff the only parameter + * for this command is an object. + * + * Result: + * TCL_OK always for the correct number of parameters. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +TCL_CMDEF(OptclIsObjectCmd) +{ + if (objc != 2) { + Tcl_WrongNumArgs (pInterp, 1, objv, "object"); + return TCL_ERROR; + } + TObjPtr name(objv[1], false); + TObjPtr found(false, false); + if (g_objmap.Find (name)) + { + found = true; + } + Tcl_SetObjResult (pInterp, found); + return TCL_OK; +} + + +/* + *------------------------------------------------------------------------- + * Optcl_Init -- + * Tcl's first entry point. Initialises ole, sets up the exit handler, + * invokes the startup script (stored in a windows resource) and setsup + * the optcl namespace. Finally, it initialises the type library system. + * + * Result: + * Standard Tcl result. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +int Optcl_Init (Tcl_Interp *pInterp) +{ + Tcl_CmdInfo *pinfo = NULL; + +#ifdef USE_TCL_STUBS +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 1) + // initialise the Tcl stubs - failure is very bad + if (Tcl_InitStubs (pInterp, "8.0", 0) == NULL) + return TCL_ERROR; + + // if Tk is loaded then initialise the Tk stubs + if (Tcl_Eval (pInterp, "package present Tk") != TCL_ERROR) { + // initialise the Tk stubs - failure + if (Tk_InitStubs (pInterp, "8.0", 0) == NULL) + return TCL_ERROR; + } +#else +#error Wrong Tcl version for Stubs +#endif // (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 1) +#endif // USE_TCL_STUBS + + HRESULT hr; + OleInitialize(NULL); + hr = CoGetMalloc(1, &g_pmalloc); + CHECKHR_TCL(hr, pInterp, TCL_ERROR); + + Tcl_CreateExitHandler (Optcl_Exit, NULL); + HRSRC hrsrc = FindResource (ghDll, MAKEINTRESOURCE(IDR_TYPELIB), _T("TCL_SCRIPT")); + if (hrsrc == NULL) { + Tcl_SetResult (pInterp, "failed to locate internal script", TCL_STATIC); + return TCL_ERROR; + } + HGLOBAL hscript = LoadResource (ghDll, hrsrc); + if (hscript == NULL) { + Tcl_SetResult (pInterp, "failed to load internal script", TCL_STATIC); + return TCL_ERROR; + } + + ASSERT (hscript != NULL); + char *szscript = (char*)LockResource (hscript); + + ASSERT (szscript != NULL); + if (Tcl_GlobalEval (pInterp, szscript) == TCL_ERROR) + return TCL_ERROR; + + Tcl_CreateObjCommand (pInterp, "optcl::new", OptclNewCmd, NULL, NULL); + Tcl_CreateObjCommand (pInterp, "optcl::lock", OptclLockCmd, NULL, NULL); + Tcl_CreateObjCommand (pInterp, "optcl::unlock", OptclUnlockCmd, NULL, NULL); + Tcl_CreateObjCommand (pInterp, "optcl::class", OptclClassCmd, NULL, NULL); + Tcl_CreateObjCommand (pInterp, "optcl::interface", OptclInterfaceCmd, NULL, NULL); + Tcl_CreateObjCommand (pInterp, "optcl::bind", OptclBindCmd, NULL, NULL); + Tcl_CreateObjCommand (pInterp, "optcl::module", OptclInvokeLibFunction, NULL, NULL); + Tcl_CreateObjCommand (pInterp, "optcl::isobject", OptclIsObjectCmd, NULL, NULL); + + + /// TESTS /// + Tcl_CreateObjCommand (pInterp, "optcl::vartest", Obj2VarTest, NULL, NULL); + + return TypeLib_Init(pInterp); +} + diff --git a/src/optcl.dsp b/src/optcl.dsp new file mode 100644 index 0000000..c4407bd --- /dev/null +++ b/src/optcl.dsp @@ -0,0 +1,414 @@ +# Microsoft Developer Studio Project File - Name="optcl" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=optcl - Win32 Debug_NoStubs +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "optcl.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "optcl.mak" CFG="optcl - Win32 Debug_NoStubs" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "optcl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "optcl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "optcl - Win32 Release_NoStubs" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "optcl - Win32 Debug_NoStubs" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "optcl - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# 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 "OPTCL_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "c:\progra~1\tcl\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPTCL_EXPORTS" /D "USE_TCL_STUBS" /D "USE_TK_STUBS" /FR /Yu"stdafx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib tclstub82.lib tkstub82.lib /nologo /dll /machine:I386 /out:"../install/optclstubs.dll" /libpath:"c:\progra~1\tcl\lib" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "optcl___Win32_Debug" +# PROP BASE Intermediate_Dir "optcl___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# 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 "OPTCL_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /Gi /GX /ZI /Od /I "c:\progra~1\tcl\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPTCL_EXPORTS" /D "USE_TCL_STUBS" /D "USE_TK_STUBS" /FR /Yu"stdafx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib tclstub84.lib tkstub84.lib /nologo /dll /debug /machine:I386 /out:"../install/optclstubs.dll" /pdbtype:sept /libpath:"c:\progra~1\tcl\lib" + +!ELSEIF "$(CFG)" == "optcl - Win32 Release_NoStubs" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "optcl___Win32_Release_NoStubs" +# PROP BASE Intermediate_Dir "optcl___Win32_Release_NoStubs" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release_NoStubs" +# PROP Intermediate_Dir "Release_NoStubs" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "c:\progra~1\tcl\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPTCL_EXPORTS" /D "USE_TCL_STUBS" /D "USE_TK_STUBS" /FR /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "c:\progra~1\tcl\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPTCL_EXPORTS" /FR /Yu"stdafx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib tclstub82.lib tkstub82.lib /nologo /dll /machine:I386 /libpath:"c:\progra~1\tcl\lib" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib tcl80.lib tk80.lib /nologo /dll /machine:I386 /out:"../install/optcl80.dll" /libpath:"c:\progra~1\tcl\lib" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug_NoStubs" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "optcl___Win32_Debug_NoStubs" +# PROP BASE Intermediate_Dir "optcl___Win32_Debug_NoStubs" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_NoStubs" +# PROP Intermediate_Dir "Debug_NoStubs" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /Gi /GX /ZI /Od /I "c:\progra~1\tcl\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPTCL_EXPORTS" /D "USE_TCL_STUBS" /D "USE_TK_STUBS" /FR /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /Gi /GX /ZI /Od /I "c:\progra~1\tcl\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OPTCL_EXPORTS" /FR /Yu"stdafx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib tclstub82.lib tkstub82.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\progra~1\tcl\lib" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib tcl80.lib tk80.lib /nologo /dll /debug /machine:I386 /out:"../install/optcl80.dll" /pdbtype:sept /libpath:"c:\progra~1\tcl\lib" + +!ENDIF + +# Begin Target + +# Name "optcl - Win32 Release" +# Name "optcl - Win32 Debug" +# Name "optcl - Win32 Release_NoStubs" +# Name "optcl - Win32 Debug_NoStubs" +# Begin Group "Source" + +# PROP Default_Filter "cpp" +# Begin Source File + +SOURCE=.\Container.cpp + +!IF "$(CFG)" == "optcl - Win32 Release" + +# ADD CPP /Yu"StdAfx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug" + +!ELSEIF "$(CFG)" == "optcl - Win32 Release_NoStubs" + +# ADD BASE CPP /Yu"StdAfx.h" +# ADD CPP /Yu"StdAfx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug_NoStubs" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\DispParams.cpp + +!IF "$(CFG)" == "optcl - Win32 Release" + +# ADD CPP /Yu"stdafx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug" + +# ADD CPP /Yu"StdAfx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Release_NoStubs" + +# ADD BASE CPP /Yu"stdafx.h" +# ADD CPP /Yu"stdafx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug_NoStubs" + +# ADD BASE CPP /Yu"StdAfx.h" +# ADD CPP /Yu"StdAfx.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\EventBinding.cpp + +!IF "$(CFG)" == "optcl - Win32 Release" + +# ADD CPP /Yu"stdafx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug" + +!ELSEIF "$(CFG)" == "optcl - Win32 Release_NoStubs" + +# ADD BASE CPP /Yu"stdafx.h" +# ADD CPP /Yu"stdafx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug_NoStubs" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\initonce.cpp +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=.\ObjMap.cpp + +!IF "$(CFG)" == "optcl - Win32 Release" + +# ADD CPP /Yu"stdafx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug" + +# ADD CPP /Yu"StdAfx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Release_NoStubs" + +# ADD BASE CPP /Yu"stdafx.h" +# ADD CPP /Yu"stdafx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug_NoStubs" + +# ADD BASE CPP /Yu"StdAfx.h" +# ADD CPP /Yu"StdAfx.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\optcl.cpp + +!IF "$(CFG)" == "optcl - Win32 Release" + +# ADD CPP /Yu"stdafx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug" + +# ADD CPP /Yu"StdAfx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Release_NoStubs" + +# ADD BASE CPP /Yu"stdafx.h" +# ADD CPP /Yu"stdafx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug_NoStubs" + +# ADD BASE CPP /Yu"StdAfx.h" +# ADD CPP /Yu"StdAfx.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\OptclBindPtr.cpp +# End Source File +# Begin Source File + +SOURCE=.\OptclObj.cpp + +!IF "$(CFG)" == "optcl - Win32 Release" + +# ADD CPP /Yu"stdafx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug" + +# ADD CPP /Yu"StdAfx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Release_NoStubs" + +# ADD BASE CPP /Yu"stdafx.h" +# ADD CPP /Yu"stdafx.h" + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug_NoStubs" + +# ADD BASE CPP /Yu"StdAfx.h" +# ADD CPP /Yu"StdAfx.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\OptclTypeAttr.cpp +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\typelib.cpp +# ADD CPP /Yu"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\utility.cpp +# ADD CPP /Yu"StdAfx.h" +# End Source File +# End Group +# Begin Group "Header" + +# PROP Default_Filter "h" +# Begin Source File + +SOURCE=.\Container.h +# End Source File +# Begin Source File + +SOURCE=.\DispParams.h +# End Source File +# Begin Source File + +SOURCE=.\EventBinding.h +# End Source File +# Begin Source File + +SOURCE=.\ObjMap.h +# End Source File +# Begin Source File + +SOURCE=.\optcl.h +# End Source File +# Begin Source File + +SOURCE=.\OptclBindPtr.h +# End Source File +# Begin Source File + +SOURCE=.\OptclObj.h +# End Source File +# Begin Source File + +SOURCE=.\OptclTypeAttr.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=.\tbase.h +# End Source File +# Begin Source File + +SOURCE=.\typelib.h +# End Source File +# Begin Source File + +SOURCE=.\utility.h +# End Source File +# End Group +# Begin Group "Resource" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\typelib.tcl +# End Source File +# End Group +# Begin Source File + +SOURCE=.\test.tcl + +!IF "$(CFG)" == "optcl - Win32 Release" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "optcl - Win32 Release_NoStubs" + +# PROP BASE Exclude_From_Build 1 +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "optcl - Win32 Debug_NoStubs" + +# PROP BASE Exclude_From_Build 1 +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# End Target +# End Project diff --git a/src/optcl.h b/src/optcl.h new file mode 100644 index 0000000..7e21c66 --- /dev/null +++ b/src/optcl.h @@ -0,0 +1,45 @@ +/* + *------------------------------------------------------------------------------ + * optcl.cpp + * Declares the OpTcl's main entry points. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + +#ifndef _OPTCL_H_B229D2A0_616A_11d4_8004_0040055861F2 +#define _OPTCL_H_B229D2A0_616A_11d4_8004_0040055861F2 + + + +// debugging symbols +#ifdef _DEBUG +#define _ATL_DEBUG_INTERFACES +#define _ATL_DEBUG_REFCOUNT +#define _ATL_DEBUG_QI +#endif + + + +extern "C" DLLEXPORT int Optcl_Init (Tcl_Interp *pInterp); +extern "C" DLLEXPORT BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); +int TypeLib_Init (Tcl_Interp *pInterp); + + +extern CComPtr g_pmalloc; + +#endif// _OPTCL_H_B229D2A0_616A_11d4_8004_0040055861F2 \ No newline at end of file diff --git a/src/resource.aps b/src/resource.aps new file mode 100644 index 0000000000000000000000000000000000000000..28c86bbdf75aa430c38699f694c1c75fd8320e97 GIT binary patch literal 50364 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 literal 0 HcmV?d00001 diff --git a/src/resource.h b/src/resource.h new file mode 100644 index 0000000..d253af9 --- /dev/null +++ b/src/resource.h @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// +#define IDR_TCL_SCRIPT1 101 +#define IDR_TYPELIB 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/resource.rc b/src/resource.rc new file mode 100644 index 0000000..52e366d --- /dev/null +++ b/src/resource.rc @@ -0,0 +1,116 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// TCL_SCRIPT +// + +IDR_TYPELIB TCL_SCRIPT DISCARDABLE "typelib.tcl" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x29L +#else + FILEFLAGS 0x28L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "Comments", "Requires Tcl/Tk major version 8, minor version >= 1\0" + VALUE "CompanyName", "University of East Anglia\0" + VALUE "FileDescription", "A Tcl extension for manipulating COM objects.\0" + VALUE "FileVersion", "3,0,0,2\0" + VALUE "InternalName", "optcl\0" + VALUE "LegalCopyright", "Copyright © 1999\0" + VALUE "LegalTrademarks", "-\0" + VALUE "OriginalFilename", "optcl.dll\0" + VALUE "PrivateBuild", "-\0" + VALUE "ProductName", "OpTcl\0" + VALUE "ProductVersion", "3,0,0,2\0" + VALUE "SpecialBuild", "-\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1200 + END +END + +#endif // !_MAC + +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/tbase.h b/src/tbase.h new file mode 100644 index 0000000..8dba129 --- /dev/null +++ b/src/tbase.h @@ -0,0 +1,837 @@ +/* + *------------------------------------------------------------------------------ + * tbase.h + * C++ Wrapper classes for common Tcl types. + * + * Updated: 1999.03.08 - Removed a few bugs from TObjPtr + * Updated: 1999.07.11 - Added isnull and isnotnull to TObjPtr + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + + +#ifndef _3CC705E0_BA28_11d2_8003_0040055861F2_ +#define _3CC705E0_BA28_11d2_8003_0040055861F2_ + + +#include +#include +#include + + +#ifndef ASSERT +# ifdef _DEBUG +# include +# define ASSERT(x) _ASSERTE(x) +# else +# define ASSERT(x) +# endif +#endif + + + + +class TObjPtr +{ +protected: + Tcl_Obj *m_po; + bool m_ba; +public: + TObjPtr() : m_po(NULL), m_ba(true) + { + } + + TObjPtr (int i, Tcl_Obj *const objs[], bool bauto = true) : m_po (NULL), m_ba(bauto) + { + ASSERT (i >= 0 && (i == 0 || objs!=NULL)); + m_po = Tcl_NewListObj (i, objs); + if (m_ba) + incr(); + } + + TObjPtr(Tcl_Obj *ptr, bool bauto =true) : m_po(ptr), m_ba(bauto) + { + if (m_ba) + incr(); + } + + TObjPtr(const TObjPtr &src, bool bauto=false) : m_po(NULL), m_ba(bauto) + { + copy (src, bauto); + } + + TObjPtr(const char *string, bool bauto=true) : m_po(NULL), m_ba(bauto) + { + m_po = Tcl_NewStringObj ((char*)string, -1); + if (m_po==NULL) + throw ("failed to create string object"); + if (m_ba) + incr(); + } + + TObjPtr(const long l, bool bauto=true) : m_po(NULL), m_ba(bauto) + { + m_po = Tcl_NewLongObj (l); + if (m_po==NULL) + throw ("failed to create long tcl object"); + if (m_ba) + incr(); + } + + + TObjPtr(const int i, bool bauto=true) : m_po(NULL), m_ba(bauto) + { + m_po = Tcl_NewIntObj (i); + if (m_po==NULL) + throw ("failed to create int tcl object"); + if (m_ba) + incr(); + } + + TObjPtr(const bool b, bool bauto=true) : m_po(NULL), m_ba(bauto) + { + m_po = Tcl_NewBooleanObj (b); + if (m_po==NULL) + throw ("failed to create long tcl object"); + if (m_ba) + incr(); + } + + TObjPtr(const double d, bool bauto=true) : m_po(NULL), m_ba(bauto) + { + m_po = Tcl_NewDoubleObj (d); + if (m_po==NULL) + throw ("failed to create double object"); + if (m_ba) + incr(); + } + + + virtual ~TObjPtr() + { + if (m_ba!=NULL && m_po != NULL) { + if (m_po->refCount == 0) + incr(); + decr(); + } + m_po = NULL; + } + + Tcl_Obj* create (bool bauto=true) + { + if (m_ba!=NULL && m_po != NULL) { + if (m_po->refCount == 0) + incr(); + decr(); + } + m_ba = bauto; + m_po = Tcl_NewObj (); + if (m_ba) + incr(); + return m_po; + } + + + void incr() + { + if (m_po) + Tcl_IncrRefCount(m_po); + } + + void decr() + { + if (m_po) + Tcl_DecrRefCount(m_po); + } + + bool isnull () + { + return (m_po == NULL); + } + + bool isnotnull() + { + return (m_po != NULL); + } + + void attach (Tcl_Obj *ptr, bool bauto=false) + { + if (m_ba) + decr(); + m_po = ptr; + m_ba = bauto; + } + + Tcl_Obj *detach () + { + Tcl_Obj *p = m_po; + m_po = NULL; + return p; + } + + void copy (const Tcl_Obj *src, bool bauto = true) + { + ASSERT (src!=NULL); + if (m_ba) + decr(); + + m_po = Tcl_DuplicateObj((Tcl_Obj*)src); + ASSERT (m_po); + m_ba = bauto; + if (m_ba) + incr(); + } + + int llength (Tcl_Interp *pInterp = NULL) + { + ASSERT (m_po!=NULL); + int length; + if (TCL_OK != Tcl_ListObjLength (pInterp, m_po, &length)) { + if (pInterp != NULL) + throw (Tcl_GetStringResult (pInterp)); + else + throw ("failed to get length of list"); + } + return length; + } + + + TObjPtr lindex (int index, Tcl_Interp *pInterp = NULL) + { + ASSERT (m_po); + Tcl_Obj *pObj = NULL; + if (TCL_OK != Tcl_ListObjIndex (pInterp, m_po, index, &pObj)) { + if (pInterp != NULL) + throw (Tcl_GetStringResult (pInterp)); + else + throw ("failed to get list item"); + } + return TObjPtr(pObj, false); + } + + + TObjPtr& lappend (TObjPtr &pObj, Tcl_Interp *pInterp = NULL) + { + return lappend ((Tcl_Obj*)pObj, pInterp); + } + + TObjPtr& lappend (Tcl_Obj *pObj, Tcl_Interp *pInterp = NULL) + { + ASSERT (pObj!=NULL && m_po!=NULL); + if (TCL_OK != Tcl_ListObjAppendElement (pInterp, m_po, pObj)) { + if (pInterp != NULL) + throw (Tcl_GetStringResult (pInterp)); + else + throw ("failed to add element to list"); + } + return *this; + } + + TObjPtr& lappend(const char *string, Tcl_Interp *pInterp = NULL) + { + ASSERT (string!=NULL && m_po != NULL); + return lappend (TObjPtr(string), pInterp); + } + + TObjPtr& lappend(const int i, Tcl_Interp *pInterp = NULL) + { + ASSERT (m_po != NULL); + return lappend (TObjPtr(i), pInterp); + } + + TObjPtr& lappend(const long l, Tcl_Interp *pInterp = NULL) + { + ASSERT (m_po != NULL); + return lappend (TObjPtr (l), pInterp); + } + + TObjPtr& lappend(const double d, Tcl_Interp *pInterp = NULL) + { + ASSERT (m_po != NULL); + return lappend (TObjPtr (d), pInterp); + } + + TObjPtr& lappend(const bool b, Tcl_Interp *pInterp = NULL) + { + ASSERT (m_po != NULL); + return lappend (TObjPtr (b), pInterp); + } + + + operator int() + { + ASSERT (m_po != NULL); + int n; + if (TCL_OK != Tcl_GetIntFromObj (NULL, m_po, &n)) + // perform a cast + n = (int) double (*this); + return n; + } + + + operator long() + { + long n; + ASSERT (m_po != NULL); + if (TCL_OK != Tcl_GetLongFromObj (NULL, m_po, &n)) + // perform a cast + n = (long) double (*this); + return n; + } + + + operator bool() + { + int b; + ASSERT (m_po != NULL); + if (TCL_OK != Tcl_GetBooleanFromObj (NULL, m_po, &b)) + throw ("failed to convert object to bool"); + return (b!=0); + } + + operator double () + { + double d; + ASSERT (m_po != NULL); + if (TCL_OK != Tcl_GetDoubleFromObj (NULL, m_po, &d)) + throw ("failed to convert object to double"); + return d; + } + + operator char*() const + { + if (m_po == NULL) return NULL; + return Tcl_GetStringFromObj(m_po, NULL); + } + + operator Tcl_Obj*() const + { + return m_po; + } + + + TObjPtr &operator= (Tcl_Obj *ptr) + { + attach(ptr, true); // automatically sets reference management + if (m_po != NULL) + incr(); + return *this; + } + + TObjPtr &operator= (const char *string) + { + ASSERT(string!=NULL && m_po != NULL); + Tcl_SetStringObj (m_po, (char*)string, -1); + return *this; + } + + TObjPtr &operator= (const long l) + { + ASSERT (m_po != NULL); + Tcl_SetLongObj (m_po, l); + return *this; + } + + TObjPtr &operator= (const int i) + { + ASSERT (m_po != NULL); + Tcl_SetIntObj (m_po, i); + return *this; + } + + TObjPtr &operator= (const bool b) + { + ASSERT (m_po != NULL); + Tcl_SetBooleanObj (m_po, b?1:0); + return *this; + } + + TObjPtr &operator= (const double d) + { + ASSERT (m_po != NULL); + Tcl_SetDoubleObj (m_po, d); + return *this; + } + + + bool operator== (Tcl_Obj *ptr) + { + return (ptr == m_po); + } + + + TObjPtr &operator+= (const char *string) + { + ASSERT (string && m_po); + Tcl_AppendToObj(m_po, (char*)string, -1); + return *this; + } + + TObjPtr& operator+= (Tcl_Obj *pObj) + { + ASSERT (m_po != NULL); + return lappend (pObj); + } + + TObjPtr &operator+= (TObjPtr &pObj) + { + ASSERT (m_po != NULL); + return lappend (pObj); + } + + TObjPtr &operator+= (int i) + { + ASSERT (m_po != NULL); + (*this) = int(*this) + i; + return *this; + } + + TObjPtr &operator+= (long l) + { + ASSERT (m_po != NULL); + (*this) = long(*this) + l; + return *this; + } + + + TObjPtr &operator+= (double d) + { + ASSERT (m_po != NULL); + (*this) = double(*this) + d; + return *this; + } + + TObjPtr &operator-= (Tcl_Obj *pObj) + { + ASSERT (m_po != NULL && pObj != NULL); + Tcl_Obj ** objv; + int objc; + char *sObj = Tcl_GetStringFromObj (pObj, NULL), + *sTemp; + + if (sObj == NULL) + return *this; + + Tcl_ListObjGetElements (NULL, m_po, &objc, &objv); + for (int i = 0; i < objc; i++) + { + if (objv[i] != NULL) { + sTemp = Tcl_GetStringFromObj (objv[i], NULL); + if (sTemp != NULL && strcmp (sObj, sTemp) == 0) + Tcl_ListObjReplace ( NULL, m_po, i, 1, 0, NULL); + } + } + return *this; + } + + TObjPtr &operator-= (TObjPtr &obj) + { + return operator-=((Tcl_Obj*)obj); + } + + TObjPtr &operator-= (int i) + { + return operator=(int(*this) - i); + } + + TObjPtr &operator-= (long l) + { + return operator=(long(*this) - l); + } + + TObjPtr &operator-= (double d) + { + return operator=(double(*this) - d); + } + + TObjPtr &operator *= (double d) + { + return operator=(double(*this) * d); + } + + TObjPtr &operator *= (int i) + { + return operator=(int(*this) * i); + } + + TObjPtr &operator *= (long l) + { + return operator=(long(*this) * l); + } + + + TObjPtr &operator /= (double d) + { + return operator=(double(*this) / d); + } + + TObjPtr &operator /= (int i) + { + return operator=(int(*this) / i); + } + + TObjPtr &operator /= (long l) + { + return operator=(long(*this) / l); + } + + Tcl_Obj **operator &() + { + return &m_po; + } + + + Tcl_Obj *operator ->() const + { + return m_po; + } + + bool operator!= (Tcl_Obj *p) + { + return (m_po != p); + } + +}; + + + + + + + +template +class THashIterator +{ +protected: + Tcl_HashTable *m_pt; + Tcl_HashEntry *m_pe; + Tcl_HashSearch m_s; + +public: + THashIterator () : m_pt(NULL), + m_pe(NULL) + {} + + THashIterator (Tcl_HashTable *pTable) : + m_pt(pTable) + { + ASSERT (m_pt!=NULL); + m_pe = Tcl_FirstHashEntry (m_pt, &m_s); + } + + THashIterator (THashIterator &src) + { + *this = src; + } + + virtual ~THashIterator () + {} + + V operator * () + { + if (m_pe == NULL) + throw ("null hash iterator"); + return (V)Tcl_GetHashValue (m_pe); + } + + THashIterator &operator ++ () + { + if (m_pe != NULL) + m_pe = Tcl_NextHashEntry (&m_s); + return *this; + } + + + THashIterator &operator ++ (int) + { + if (m_pe != NULL) + m_pe = Tcl_NextHashEntry (&m_s); + return *this; + } + + operator Tcl_HashEntry* () + { + return m_pe; + } + + bool operator!= (Tcl_HashEntry *pEntry) + { + return m_pe != pEntry; + } + + bool operator== (Tcl_HashEntry *pEntry) + { + return m_pe == pEntry; + } + + K* key () { + ASSERT (m_pt != NULL); + if (m_pe == NULL) + throw ("null hash iterator"); + return (K*)Tcl_GetHashKey (m_pt, m_pe); + } + + THashIterator &operator = (THashIterator &i) + { + m_pt = i.m_pt; + m_pe = i.m_pe; + m_s = i.m_s; + return *this; + } +}; + + + + +template +class THash +{ +public: + typedef THashIterator iterator; +protected: + int m_keytype; + bool m_bCreated; + Tcl_HashTable m_tbl; +public: + THash (): + m_keytype(Size), + m_bCreated(false) + { + } + + ~THash () + { + deltbl(); + } + + + + iterator begin () + { + createtbl(); + iterator i(&m_tbl); + return i; + } + + iterator end () + { + createtbl(); + iterator i; + return i; + } + + + Tcl_HashEntry *find (const K *key, V *value = NULL) + { + Tcl_HashEntry *p = NULL; + createtbl(); + + p = Tcl_FindHashEntry (&m_tbl, (char*)key); + if (value != NULL && p!=NULL) + *value = (V)Tcl_GetHashValue (p); + return p; + } + + + bool delete_entry (const K *key) + { + Tcl_HashEntry *p = find (key); + if (p!=NULL) + Tcl_DeleteHashEntry (p); + return (p!=NULL); + } + + + Tcl_HashEntry * create_entry (const K *key, int *created = NULL) + { + ASSERT (key != NULL); + createtbl(); + + int c; + Tcl_HashEntry *p; + + if (created == NULL) + p = Tcl_CreateHashEntry (&m_tbl, (char*)key, &c); + else + p = Tcl_CreateHashEntry (&m_tbl, (char*)key, created); + return p; + } + + Tcl_HashEntry * set (const K *key, const V &value) + { + ASSERT (key != NULL); + createtbl(); + + Tcl_HashEntry *p = create_entry (key); + if (p!=NULL) + Tcl_SetHashValue (p, (ClientData)value); + return p; + } + + K *key (const Tcl_HashEntry *p) + { + ASSERT (p!=NULL); + if (!m_bCreated) return NULL; + return (K*)Tcl_GetHashKey (&m_tbl, p); + } + + operator Tcl_HashTable*() + { + return &m_tbl; + } + + void deltbl () + { + if (m_bCreated) { + Tcl_DeleteHashTable (&m_tbl); + m_bCreated = false; + } + } + + void createtbl () + { + if (!m_bCreated) { + Tcl_InitHashTable (&m_tbl, m_keytype); + m_bCreated = true; + } + } + +}; + + + +class TDString { +protected: + Tcl_DString ds; +public: + TDString () + { + Tcl_DStringInit(&ds); + } + + TDString (const char *init) + { + Tcl_DStringInit(&ds); + append(init); + } + + ~TDString () + { + Tcl_DStringFree(&ds); + } + + TDString& set (const char *string = "") + { + ASSERT (string != NULL); + Tcl_DStringFree (&ds); + Tcl_DStringInit(&ds); + append(string); + return *this; + } + + char *append (const char *string, int length = -1) + { + ASSERT (string != NULL); + return Tcl_DStringAppend (&ds, (char*)string, length); + } + + TDString& operator<< (const char *string) + { + ASSERT (string!=NULL); + append(string); + return *this; + } + + TDString& operator<< (const long val) + { + TObjPtr p(val); + append((char*)p); + return *this; + } + + TDString& operator<< (const int val) + { + TObjPtr p(val); + append((char*)p); + return *this; + } + + TDString& operator<< (const double fval) + { + TObjPtr d(fval); + append((char*)d); + return *this; + } + + operator const char*() + { + return value(); + } + + // type unsafe, as the string still belongs to this object + operator char*() + { + return (char*)(value()); + } + + TDString& operator= (TDString & src) + { + set (src.value()); + return *this; + } + + char *append_element(char *string) + { + ASSERT (string != NULL); + return Tcl_DStringAppendElement (&ds, (char*)string); + } + + void start_sublist () + { + Tcl_DStringStartSublist (&ds); + } + + void end_sublist () + { + Tcl_DStringEndSublist (&ds); + } + + int length () + { + return Tcl_DStringLength (&ds); + } + + const char *value () + { + return Tcl_DStringValue (&ds); + } + + void set_result (Tcl_Interp *pInterp) + { + Tcl_DStringResult (pInterp, &ds); + } + + void get_result (Tcl_Interp *pInterp) + { + Tcl_DStringGetResult (pInterp, &ds); + } +}; + + + +#endif // _3CC705E0_BA28_11d2_8003_0040055861F2_ diff --git a/src/test.tcl b/src/test.tcl new file mode 100644 index 0000000..86b8d60 --- /dev/null +++ b/src/test.tcl @@ -0,0 +1,100 @@ +console show +load optcl + + + +proc ie_test {} { + global ie + set ie [optcl::new -window .ie {{8856F961-340A-11D0-A96B-00C04FD705A2}}] + pack .ie + $ie navigate www.wired.com +} + +proc vrml_test {} { + global vrml + set vrml [optcl::new -window .vrml {{4B6E3013-6E45-11D0-9309-0020AFE05CC8}}] + pack .vrml +} + +proc tree_test {} { + global tv + set tv [optcl::new -window .tv {{C74190B6-8589-11D1-B16A-00C0F0283628}}] + pack .tv + set n1 [$tv -with nodes add] + $n1 : text "Node 1" key "1 Node" + optcl::unlock $n1 + set n2 [$tv -with nodes add "1 Node" 4 "2 Node" "Node 2"] + $n2 : text "Node 2.5" + optcl::unlock $n2 +} + +proc dp_test {} { + global dp + destroy .date + set dp [optcl::new -window .date MSComCtl2.DTPicker] + .date config -width 100 -height 20 + pack .date + tlview::viewtype [optcl::class $dp] +} + +proc cal_test {} { + global cal + destroy .cal + set cal [optcl::new -window .cal MSCAL.Calendar] + pack .cal +} + + +proc pb_test {} { + global pb mousedown + + proc PBMouseDown {obj args} { + global mousedown + set mousedown $obj + } + + proc PBMouseUp {args} { + global mousedown + set mousedown {} + } + + proc PBMouseMove {obj button shift x y} { + global mousedown + if {$mousedown == {}} return + if {[string compare $mousedown $obj]==0} { + $obj : value $x + } + } + destroy .pb + set pb [optcl::new -window .pb MSComctlLib.ProgCtrl] + pack .pb + .pb config -width 100 -height 10 + optcl::bind $pb MouseDown PBMouseDown + optcl::bind $pb MouseUp PBMouseUp + optcl::bind $pb MouseMove PBMouseMove +} + + + + +proc word_test {} { + global word + + set word [optcl::new word.application] + $word : visible 1 +} + + +proc tl_test {} { + typelib::load {Microsoft Shell Controls And Automation (Ver 1.0)} + tlview::refview .r + tlview::loadedlibs .l +} + + + +proc cosmo_test {} { + global co + set co [optcl::new -window .co SGI.CosmoPlayer.2] + pack .co +} diff --git a/src/typelib.cpp b/src/typelib.cpp new file mode 100644 index 0000000..4e2ec52 --- /dev/null +++ b/src/typelib.cpp @@ -0,0 +1,2008 @@ +/* + *------------------------------------------------------------------------------ + * typelib.cpp + * Implements access to typelibraries. Currently this only includes + * browsing facilities. In the future, this may contain typelib building + * functionality. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + + + +#include "stdafx.h" +#include "tbase.h" +#include "utility.h" +#include "optcl.h" +#include "typelib.h" +#include "objmap.h" +#include "optclbindptr.h" + + +//---------------------------------------------------------------- +// \/\/\/\/\/\ Declarations /\/\/\/\/\/\/ + + +void TypeLib_Exit (ClientData); +const char *TYPEKIND2Str (TYPEKIND tkind); +void FUNCDESC2Obj (ITypeInfo *pti, FUNCDESC *pfd, TObjPtr &fdesc); +void VARDESC2Obj (ITypeInfo *pti, VARDESC *pdesc, TObjPtr &presult); +bool TYPEDESC2Obj (ITypeInfo *pti, TYPEDESC *pdesc, TObjPtr &pobj); + +void VariantToObj (VARIANT *pvar, TObjPtr &obj); + +inline void ReleaseTypeAttr (ITypeInfo *pti, TYPEATTR *&pta); + +void Guid2LibName (GUID &guid, TObjPtr &plibname); + +void TypeLib_GetImplTypes (ITypeInfo *pti, TObjPtr &inherited); +void TypeLib_ProcessFunctions (ITypeInfo *pti, TObjPtr &methods, TObjPtr &properties); +void TypeLib_ProcessVariables (ITypeInfo *pti, TObjPtr &properties); +void TypeLib_GetVariable (ITypeInfo *pti, UINT index, TObjPtr &properties); + +HRESULT BindTypeInfo (ITypeComp *, const char *, ITypeInfo **); + +TCL_CMDEF(TypeLib_LoadedLibs); +TCL_CMDEF(TypeLib_LoadLib); +TCL_CMDEF(TypeLib_UnloadLib); +TCL_CMDEF(TypeLib_IsLibLoaded); +TCL_CMDEF(TypeLib_TypesInLib); +TCL_CMDEF(TypeLib_TypeInfo); + + +//// TEST CODE //// +TCL_CMDEF(TypeLib_ResolveConstantTest); + +//---------------------------------------------------------------- +// \/\/\/\/\/\/ Globals \/\/\/\/\/\/\/ + +// this class uses a Tcl hash table - this usually wouldn't be +// safe, except that this hash table is initialised (courtsey of THash<>) +// only on first uses (lazy). So it should be okay. Not sure how +// this will behave in a multithreaded application + +TypeLibsTbl g_libs; + +//---------------------------------------------------------------- +// Implementation for TypeLibsTbl class + +TypeLibsTbl::TypeLibsTbl () : THash () +{ + +} + + +TypeLibsTbl::~TypeLibsTbl () +{ + DeleteAll(); +} + +void TypeLibsTbl::DeleteAll () +{ + for (iterator i = begin(); i != end(); i++) + { + ASSERT ((*i) != NULL); + delete (*i); + } + deltbl(); +} + + +ITypeLib * TypeLibsTbl::LoadLib (Tcl_Interp *pInterp, const char *fullname) +{ + USES_CONVERSION; + CComPtr pLib; + CComPtr pComp; + + TObjPtr cmd, // used to build up a command string + result, // attaches to the result of the above commands' execution + progname; // the programmatic name of the library + GUID guid; + int maj, min; + HRESULT hr; + + Tcl_HashEntry *pEntry = NULL; + TypeLib *ptl; + + if (m_loadedlibs.find(fullname, &pEntry) != NULL) { + ASSERT (pEntry != NULL); + ptl = (TypeLib *)Tcl_GetHashValue (pEntry); + ASSERT (ptl != NULL); + Tcl_SetResult (pInterp, Tcl_GetHashKey (&m_tbl, pEntry), TCL_VOLATILE); + pLib = ptl->m_ptl; + ASSERT (pLib != NULL); + return pLib; + } + + + try { + // get the guid, max and min version numbers + cmd.create(); + cmd = "typelib::libdetail"; + cmd.lappend (fullname); + if (Tcl_GlobalEvalObj (pInterp, cmd) == TCL_ERROR) return NULL; + result.attach(Tcl_GetObjResult(pInterp), false); + if (result.llength() != 3) + throw ("expected three elements in the library description"); + + maj = result.lindex (1); + min = result.lindex (2); + hr = CLSIDFromString (A2OLE(result.lindex(0)), &guid); + if (FAILED(hr)) + throw ("failed to convert identifier"); + + // load the library + hr = LoadRegTypeLib (guid, maj, min, LOCALE_SYSTEM_DEFAULT, &pLib); + CHECKHR(hr); + if (pLib == NULL) + throw ("failed to bind to a type library"); + + // get the programmatic name of the library + TypeLib_GetName (pLib, NULL, progname); + + hr = pLib->GetTypeComp(&pComp); + if (FAILED(hr)) + throw ("failed to get the compiler interface for library"); + + Cache (progname, fullname, pLib, pComp); + Tcl_SetResult (pInterp, (char*)(const char*)progname, TCL_VOLATILE); + } + + catch (char *error) { + Tcl_SetResult (pInterp, error, TCL_VOLATILE); + } + catch (HRESULT hr) { + Tcl_SetResult (pInterp, (char*)HRESULT2Str(hr), TCL_DYNAMIC); + } + + return pLib; +} + + + + +/* + *------------------------------------------------------------------------- + * TypeLibsTbl::Cache -- + * Called in order to cache a library. + * Pre: The library does *not* exist in the cache + * + * Result: + * A standard OLE HRESULT + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +TypeLib* TypeLibsTbl::Cache (const char *szname, const char *szfullname, ITypeLib *ptl, ITypeComp *ptc) +{ + ASSERT(szname != NULL && szfullname != NULL); + ASSERT (ptl != NULL && ptc != NULL); + TypeLib *pLib = NULL; + Tcl_HashEntry *pEntry = NULL; + + pLib = new TypeLib (ptl, ptc); + pEntry = set(szname, pLib); + ASSERT (pEntry != NULL); + + m_loadedlibs.set (szfullname, pEntry); + return pLib; +} + + +bool TypeLibsTbl::IsLibLoaded (const char *fullname) +{ + ASSERT (fullname != NULL); + return (m_loadedlibs.find (fullname) != NULL); +} + +/* + *------------------------------------------------------------------------- + * TypeLibsTbl::UnloadLib -- + * Given the fullname of a library, the routine unloads it, if it is + * loaded. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void TypeLibsTbl::UnloadLib (Tcl_Interp *pInterp, const char *fullname) +{ + Tcl_HashEntry *pEntry = NULL; + TypeLib *ptl = NULL; + + if (!m_loadedlibs.find (fullname, &pEntry)) + return; + + ASSERT (pEntry != NULL); + ptl = (TypeLib*)Tcl_GetHashValue (pEntry); + ASSERT (ptl != NULL); + delete ptl; + m_loadedlibs.delete_entry(fullname); + Tcl_DeleteHashEntry (pEntry); +} + + + + +/* + *------------------------------------------------------------------------- + * TypeLibsTbl::EnsureCached -- + * Given a typelibrary, the routine ensures that it is stored in the cache. + * + * Result: + * A pointer to the caches TypeLib object. + * + * Side effects: + * Throws HRESULT. + *------------------------------------------------------------------------- + */ +TypeLib *TypeLibsTbl::EnsureCached (ITypeLib *ptl) +{ + USES_CONVERSION; + + ASSERT (ptl != NULL); + TDString verfullname; + TypeLib *pLib = NULL; + TLIBATTR *pattr = NULL; + HRESULT hr; + BSTR name = NULL, + fullname = NULL; + char *szname, *szfullname; + Tcl_HashEntry *pEntry = NULL; + CComPtr ptc; + + // get the libraries different names + hr = ptl->GetDocumentation(-1, &name, &fullname, NULL, NULL); + CHECKHR(hr); + szname = W2A(name); + szfullname = W2A(fullname); + FreeBSTR(name); + FreeBSTR(fullname); + if (find(szname, &pLib)) + return pLib; // cached already + + // build the fullname+version string + hr = ptl->GetLibAttr(&pattr); + CHECKHR(hr); + verfullname.set (szfullname) << " (Ver " << short(pattr->wMajorVerNum) << "." << + short(pattr->wMinorVerNum) << ")"; + ptl->ReleaseTLibAttr (pattr); pattr = NULL; + + // get the compiler interface + hr = ptl->GetTypeComp (&ptc); + CHECKHR(hr); + // now cache the lot + pLib = Cache (szname, verfullname, ptl, ptc); + return pLib; +} + + +/* + *------------------------------------------------------------------------- + * TypeLibsTbl::EnsureCached -- + * Sames as EnsureChached(ITypeLib *), but uses a type info. + * + * Result: + * Non NULL iff successful - result points to the cached TypeLib structure. + * + * Side effects: + * Throws HRESULT. + *------------------------------------------------------------------------- + */ +TypeLib *TypeLibsTbl::EnsureCached (ITypeInfo *pInfo) +{ + ASSERT (pInfo != NULL); + CComPtr pLib; + UINT tmp; + HRESULT hr; + hr = pInfo->GetContainingTypeLib(&pLib, &tmp); + CHECKHR(hr); + return EnsureCached (pLib); +} + + + + + + + +// ------------------- TypeLib initialisation and shutdown routines ------------------------- +int TypeLib_Init (Tcl_Interp *pInterp) +{ + OleInitialize(NULL); + Tcl_CreateExitHandler (TypeLib_Exit, NULL); + Tcl_CreateObjCommand (pInterp, "typelib::loaded", TypeLib_LoadedLibs, NULL, NULL); + Tcl_CreateObjCommand (pInterp, "typelib::load", TypeLib_LoadLib, NULL, NULL); + Tcl_CreateObjCommand (pInterp, "typelib::unload", TypeLib_UnloadLib, NULL, NULL); + Tcl_CreateObjCommand (pInterp, "typelib::types", TypeLib_TypesInLib, NULL, NULL); + Tcl_CreateObjCommand (pInterp, "typelib::typeinfo", TypeLib_TypeInfo, NULL, NULL); + Tcl_CreateObjCommand (pInterp, "typelib::isloaded", TypeLib_IsLibLoaded, NULL, NULL); + + //// TESTS //// + Tcl_CreateObjCommand (pInterp, "typelib::resolveconst", TypeLib_ResolveConstantTest, NULL, NULL); + + return TCL_OK; +} + + + +void TypeLib_Exit (ClientData) +{ + g_libs.DeleteAll (); + OleUninitialize(); +} +// ------------------------------------------------------------------------------------------ + + + + +/* + *------------------------------------------------------------------------- + * ReleaseTypeAttr -- + * Release at type attribute from the specified type info. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +inline void ReleaseTypeAttr (ITypeInfo *pti, TYPEATTR *&pta) +{ + ASSERT (pti != NULL); + if (pta != NULL) { + pti->ReleaseTypeAttr(pta); + pta = NULL; + } +} + + + + +/* + *------------------------------------------------------------------------- + * ReleaseBindPtr -- + * Releases a bind ptr (if not null), according to its type description. + * Sets the value of the pointer to null. + * + * Result: + * None + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void ReleaseBindPtr (ITypeInfo *pti, DESCKIND dk, BINDPTR &ptr) +{ + if (ptr.lpfuncdesc != NULL) { + switch (dk) { + case DESCKIND_FUNCDESC: + ASSERT (pti != NULL); + pti->ReleaseFuncDesc (ptr.lpfuncdesc); + ptr.lpfuncdesc = NULL; + break; + case DESCKIND_IMPLICITAPPOBJ: // same as a vardesc + case DESCKIND_VARDESC: + ASSERT (pti != NULL); + pti->ReleaseVarDesc (ptr.lpvardesc); + ptr.lpvardesc = NULL; + break; + case DESCKIND_TYPECOMP: + ptr.lptcomp->Release(); + ptr.lptcomp = NULL; + break; + } + } +} + + + +const char *TYPEKIND2Str (TYPEKIND tkind) +{ + switch (tkind) + { + case TKIND_ENUM: + return "enum"; + case TKIND_RECORD: + return "struct"; + case TKIND_MODULE: + return "module"; + case TKIND_INTERFACE: + return "interface"; + case TKIND_DISPATCH: + return "dispatch"; + case TKIND_COCLASS: + return "class"; + case TKIND_ALIAS: + return "typedef"; + case TKIND_UNION: + return "union"; + default: + return "???"; + } +} + + + + + + +const char *VARTYPE2Str (VARTYPE vt) +{ + vt = vt & ~VT_ARRAY & ~VT_BYREF; + switch (vt) { + case VT_EMPTY: + case VT_NULL: + return "_null_"; + case VT_I1: + return "char"; + case VT_UI1: + return "uchar"; + case VT_I2: + return "short"; + case VT_UI2: + return "ushort"; + case VT_INT: + case VT_I4: + case VT_ERROR: + return "long"; + case VT_UI4: + case VT_UINT: + return "ulong"; + case VT_I8: + return "super_long"; + case VT_UI8: + return "usuper_long"; + case VT_R4: + return "float"; + case VT_R8: + return "double"; + case VT_CY: + return "currency"; + case VT_DATE: + return "date"; + case VT_BSTR: + return "string"; + case VT_DISPATCH: + return "dispatch"; + case VT_BOOL: + return "bool"; + case VT_VARIANT: + return "any"; + case VT_UNKNOWN: + return "interface"; + case VT_DECIMAL: + return "decimal"; + case VT_VOID: + return "void"; + case VT_HRESULT: + return "scode"; + case VT_LPSTR: + case VT_LPWSTR: + return "string"; + case VT_CARRAY: + return "carray"; + default: + return "???"; + } +} + + + + + +/* + *------------------------------------------------------------------------- + * TYPEDESC2Obj -- + * + * Result: + * + * Side effects: + * + *------------------------------------------------------------------------- + */ +bool TYPEDESC2Obj (ITypeInfo *pti, TYPEDESC *pdesc, TObjPtr &pobj) +{ + USES_CONVERSION; + ASSERT (pdesc != NULL && pti != NULL); + bool array = ((pdesc->vt & VT_ARRAY) != 0); + pdesc->vt = pdesc->vt & ~VT_ARRAY; + HRESULT hr; + + if (pdesc->vt == VT_USERDEFINED) { + // resolve the referenced type + CComPtr prefti; + TYPEATTR *pta = NULL; + WORD flags; + hr = pti->GetRefTypeInfo (pdesc->hreftype, &prefti); + CHECKHR(hr); + hr = prefti->GetTypeAttr (&pta); + CHECKHR(hr); + flags = pta->wTypeFlags; + + ReleaseTypeAttr (prefti, pta); + if ((flags & TYPEFLAG_FRESTRICTED)) { + pobj.create(); + pobj = "!!!"; // unaccessable type + return false; + } + g_libs.EnsureCached(prefti); + TypeLib_GetName (NULL, prefti, pobj); + } else if ((pdesc->vt == VT_SAFEARRAY) || (pdesc->vt == VT_PTR)) { + if (!TYPEDESC2Obj (pti, pdesc->lptdesc, pobj)) + return false; + ASSERT (pobj.isnotnull()); + if (pdesc->vt == VT_SAFEARRAY) + pobj += " []"; + } else { + pobj.create(); + pobj = VARTYPE2Str(pdesc->vt); + } + + return true; +} + + + + + +/* + *------------------------------------------------------------------------- + * TypeLib_GetName -- + * Converts a library or type to a name stored in a Tcl_Obj. If pLib + * is not NULL and pInfo is, then the name is the name of the library. + * Otherwise, pInfo must be non-null (pLib can always be derived from pInfo) + * The result is stored in pname. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void TypeLib_GetName (ITypeLib *pLib, ITypeInfo *pInfo, TObjPtr &pname) +{ + ASSERT (pLib!=NULL || pInfo!=NULL); + + USES_CONVERSION; + BSTR progname = NULL, + typname = NULL; + HRESULT hr; + + UINT tmp; + bool bLibcreate = false; + + // ensure we have a library to work with + if (pLib == NULL) { + hr = pInfo->GetContainingTypeLib(&pLib, &tmp); + CHECKHR(hr); + bLibcreate = true; + } + // get the library programmatic name + hr = pLib->GetDocumentation (-1, &progname, NULL, NULL, NULL); + CHECKHR(hr); + + if (pInfo == NULL) { + pname.create(); + pname = W2A(progname); + } else { + hr = pInfo->GetDocumentation(MEMBERID_NIL, &typname, NULL, NULL, NULL); + CHECKHR(hr); + TDString str; + str.set(W2A(progname)) << "." << W2A(typname); + pname.create(); + pname = str; + } + + FreeBSTR(progname); + FreeBSTR(typname); + if (bLibcreate) + pLib->Release(); +} + + + + + +/* + *------------------------------------------------------------------------- + * BindTypeInfo -- + * Given a type compiling interface (ptc) and a typename (szTypeName), + * resolves to a ITypeInfo interface (stored in ppti). + * + * Result: + * Returns a standard OLE HRESULT. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +HRESULT BindTypeInfo (ITypeComp *ptc, const char *szTypeName, ITypeInfo **ppti) +{ + USES_CONVERSION; + LPOLESTR oleTypename = NULL; + UINT hash; + ASSERT (ptc != NULL && ppti != NULL); + CComPtr ptemp; + oleTypename = A2OLE(szTypeName); + hash = LHashValOfName(LOCALE_SYSTEM_DEFAULT, oleTypename); + return ptc->BindType (oleTypename, hash, ppti, &ptemp); +} + + + + + + +/* + *------------------------------------------------------------------------- + * FUNCDESC2Obj -- + * + * Result: + * + * Side effects: + * + *------------------------------------------------------------------------- + */ +void FUNCDESC2Obj (ITypeInfo *pti, FUNCDESC *pfd, TObjPtr &fdesc) +{ + ASSERT (pfd != NULL && pti != NULL); + ASSERT (!(pfd->wFuncFlags & FUNCFLAG_FRESTRICTED)); + USES_CONVERSION; + BSTR * fnames = NULL; + char * szfname = NULL; + HRESULT hr; + UINT totalread = 0; + UINT total = 0; + TObjPtr type; + TObjPtr flags; + TObjPtr param; + TObjPtr optionparam; + + fdesc.create(); + + try { + // get the names + total = pfd->cParams + 1; + fnames = new BSTR[total]; + hr = pti->GetNames(pfd->memid, fnames, total, &totalread); + CHECKHR(hr); + if (totalread != total) + throw ("couldn't retrieve all the parameter names"); + + + + TYPEDESC2Obj(pti, &(pfd->elemdescFunc.tdesc), type); + fdesc.lappend (type); // return type + fdesc.lappend (W2A(fnames[0])); // the function name + + + // now build up the parameters + for (SHORT index = 0; index < pfd->cParams; index++) + { + ELEMDESC *pdesc = pfd->lprgelemdescParam + index; + flags.create(); + if ((pdesc->paramdesc.wParamFlags & PARAMFLAG_FIN) || + (pdesc->paramdesc.wParamFlags == PARAMFLAG_NONE)) + flags.lappend("in"); + if (pdesc->paramdesc.wParamFlags & PARAMFLAG_FOUT) + flags.lappend("out"); + if (pdesc->paramdesc.wParamFlags & PARAMFLAG_FRETVAL) + flags.lappend("retval"); + + // type of parameter + TYPEDESC2Obj(pti, &(pdesc->tdesc), type); + + // setup the result + param.create(); + param.lappend(flags).lappend(type).lappend(W2A(fnames[index+1])); + + + // is it optional and does it have a default value + if ((pdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) + && (pdesc->paramdesc.wParamFlags & PARAMFLAG_FOPT)) { + VariantToObj (&(pdesc->paramdesc.pparamdescex->varDefaultValue), optionparam); + param.lappend(optionparam); + } + else + if ((pfd->cParams - index)<=pfd->cParamsOpt) + param.lappend ("?"); + + fdesc.lappend(param); + } + + + FreeBSTRArray (fnames, totalread); + delete fnames; + } + + catch (char *error) { + FreeBSTRArray (fnames, totalread); + delete fnames; + throw (error); + } + + catch (HRESULT hr) { + FreeBSTRArray (fnames, totalread); + delete fnames; + throw (hr); + } +} + + + +/* + *------------------------------------------------------------------------- + * VARDESC2Obj -- + * + * Result: + * + * Side effects: + * + *------------------------------------------------------------------------- + */ +void VARDESC2Obj (ITypeInfo *pti, VARDESC *pdesc, TObjPtr &presult) +{ + ASSERT (pti != NULL && pdesc != NULL); + + USES_CONVERSION; + HRESULT hr; + BSTR name = NULL; + char * szname = NULL; + TObjPtr tdesc; // stores the description of the type + TObjPtr tflags;// read write flags for this variable + + hr = pti->GetDocumentation(pdesc->memid, &name, NULL, NULL, NULL); + CHECKHR(hr); + szname = W2A (name); + FreeBSTR (name); + + TYPEDESC2Obj (pti, &(pdesc->elemdescVar.tdesc), tdesc); + tflags.create(); + if (pdesc->wVarFlags & VARFLAG_FREADONLY) + tflags = "read"; + else + tflags = "read write"; + + presult.create(); + presult.lappend (tflags).lappend(tdesc).lappend(szname); + if (pdesc->varkind == VAR_CONST) { // its a constant + TObjPtr cnst; + VariantToObj (pdesc->lpvarValue, cnst); + presult.lappend (cnst); + } +} + + +void VariantToObj (VARIANT *pvar, TObjPtr &obj) +{ + ASSERT (pvar != NULL); + + USES_CONVERSION; + + VARTYPE vt = pvar->vt; + CComVariant var; + HRESULT hr; + + vt = vt & ~VT_BYREF; + obj.create(); + + if (vt == VT_UNKNOWN || vt == VT_DISPATCH) + obj = "object"; + else if ((vt & VT_ARRAY) == VT_ARRAY) + obj = "array"; + else { + hr = var.Copy (pvar); + CHECKHR(hr); + var.ChangeType(VT_BSTR); + ASSERT (var.bstrVal != NULL); + obj = W2A (var.bstrVal); + } +} + + + +/* + *------------------------------------------------------------------------- + * ImplFlags2Obj -- + * + * Converts implementation flags to a tcl object. + * + * Result: + * None. + * + * Side effects: + * Uses TObjPtr functions, and hence throws (char *) in case of any errors. + *------------------------------------------------------------------------- + */ +void ImplFlags2Obj (UINT implflags, TObjPtr &flags) +{ + flags.create(); + if (implflags & IMPLTYPEFLAG_FDEFAULT) + flags.lappend("default"); + if (implflags & IMPLTYPEFLAG_FSOURCE) + flags.lappend("source"); +} + + + + +/* + *------------------------------------------------------------------------- + * TypeLib_DescOfRefType -- + * + * Called to describe a referenced type from another type. If bclassinfo + * is true, the function prepends additional flags to describe the role of + * the referenced type to the class type. + * + * Result: + * return true iff successful. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool TypeLib_DescOfRefType (ITypeInfo *pti, UINT index, TObjPtr &desc, bool bclassinf) +{ + ASSERT (pti != NULL); + + HRESULT hr; + TObjPtr name; + TObjPtr flags; + CComPtr ptmp; + HREFTYPE href; + INT implflags; + TYPEATTR * pta = NULL; + WORD typeflags; + + hr = pti->GetRefTypeOfImplType (index , &href); + CHECKHR(hr); + + hr = pti->GetRefTypeInfo (href, &ptmp); + CHECKHR(hr); + + g_libs.EnsureCached(ptmp); + hr = pti->GetImplTypeFlags(index, &implflags); + CHECKHR(hr); + + hr = ptmp->GetTypeAttr (&pta); + CHECKHR(hr); + typeflags = pta->wTypeFlags; + ReleaseTypeAttr(pti, pta); + + if ((typeflags & TYPEFLAG_FRESTRICTED) || + (implflags & IMPLTYPEFLAG_FRESTRICTED)) + return false; + + + TypeLib_GetName (NULL, ptmp, name); + if (bclassinf) { + ImplFlags2Obj (implflags, flags); + } else { + flags.create(); + } + + desc.create(); + desc.lappend(flags).lappend(name); + return true; +} + + + + + +/* + *------------------------------------------------------------------------- + * TypeLib_GetImplTypes -- + * Compiles a list of inherited interfaces from a type information pointer. + * + * Result: + * None. + * + * Side effects: + * throws char * and HRESULT. + *------------------------------------------------------------------------- + */ +void TypeLib_GetImplTypes (ITypeInfo *pti, TObjPtr &inherited) +{ + ASSERT (pti!=NULL && inherited.isnotnull()); + + HRESULT hr; + TYPEATTR * pattr = NULL; + WORD count; // total number of references + TObjPtr desc; + TYPEKIND tkind; + + + hr = pti->GetTypeAttr (&pattr); + CHECKHR(hr); + + count = pattr->cImplTypes; + tkind = pattr->typekind; + ReleaseTypeAttr (pti, pattr); + + for (WORD index = 0; index < count; index++) + { + if (TypeLib_DescOfRefType (pti, index, desc, (tkind == TKIND_COCLASS))) + inherited.lappend(desc); + } +} + + + + + + + +/* + *------------------------------------------------------------------------- + * TypeLib_GetVariable -- + * Gets the description for a variable (VARDESC) property, based on an + * index. + * + * Result: + * None. + * + * Side effects: + * Throws HRESULT and char *. + *------------------------------------------------------------------------- + */ +void TypeLib_GetVariable (ITypeInfo *pti, UINT index, TObjPtr &properties) +{ + USES_CONVERSION; + + ASSERT (pti != NULL && properties.isnotnull()); + VARDESC * pDesc; + HRESULT hr; + BSTR name = NULL; + char * szName = NULL; + + try { + hr = pti->GetVarDesc(index, &pDesc); + CHECKHR(hr); + + ASSERT (pDesc != NULL); + + if (!(pDesc->wVarFlags & VARFLAG_FHIDDEN)) // not a hidden variable + { + hr = pti->GetDocumentation(pDesc->memid, &name, NULL, NULL, NULL); + CHECKHR(hr); + + szName = W2A(name); + FreeBSTR(name); + properties.lappend(szName); + } + pti->ReleaseVarDesc(pDesc); + } + + catch (HRESULT hr) { + if (pDesc != NULL) { + pti->ReleaseVarDesc(pDesc); + pDesc = NULL; + } + throw (hr); + } + + catch (char *error) { + if (pDesc != NULL) { + pti->ReleaseVarDesc(pDesc); + pDesc = NULL; + } + throw (error); + } +} + + + + + + + +/* + *------------------------------------------------------------------------- + * TypeLib_ProcessVariables -- + * Appends to a tcl list object, a the set of VARDESC defined properties. + * + * Result: + * None. + * + * Side effects: + * Uses functions that throw HRESULT and char * + *------------------------------------------------------------------------- + */ +void TypeLib_ProcessVariables (ITypeInfo *pti, TObjPtr &properties) +{ + ASSERT (pti != NULL && properties.isnotnull()); + TYPEATTR *pattr = NULL; + HRESULT hr; + UINT count; + + hr = pti->GetTypeAttr(&pattr); + CHECKHR(hr); + count = pattr->cVars; + ReleaseTypeAttr (pti, pattr); + + for (UINT index = 0; index < count; index++) { + TypeLib_GetVariable (pti, index, properties); + } +} + + + + +/* + *------------------------------------------------------------------------- + * TypeLib_ProcessFunctions -- + * Scans the functions within the type and separates them into two lists: + * Methods functions, and property functions. Read/Write access to + * properties are not determined here. + * + * Result: + * None. + * + * Side effects: + * Can throw HRESULT and char *. + *------------------------------------------------------------------------- + */ +void TypeLib_ProcessFunctions (ITypeInfo *pti, TObjPtr &methods, TObjPtr &properties) +{ + USES_CONVERSION; + ASSERT (pti != NULL && properties.isnotnull() && methods.isnotnull()); + + HRESULT hr; + TYPEATTR * pattr = NULL; + WORD count; + FUNCDESC * pfd = NULL; + BSTR name; + char * szname; + THash proptbl; + + hr = pti->GetTypeAttr (&pattr); + CHECKHR(hr); + + count = pattr->cFuncs; + ReleaseTypeAttr (pti, pattr); + + + try { + for (WORD index = 0; index < count; index++) + { + hr = pti->GetFuncDesc (index, &pfd); + CHECKHR(hr); + // if the function shouldn't be shown, skip this iteration + if ((pfd->wFuncFlags & FUNCFLAG_FRESTRICTED)) { + pti->ReleaseFuncDesc (pfd); pfd = NULL; + continue; + } + + hr = pti->GetDocumentation(pfd->memid, &name, NULL, NULL, NULL); + CHECKHR(hr); + + szname = W2A (name); + FreeBSTR (name); + if (pfd->invkind == INVOKE_FUNC) { + methods.lappend(szname); + } else { + proptbl.set(szname, 0); + } + pti->ReleaseFuncDesc (pfd); pfd = NULL; + } + // now process the properties + for (THash::iterator e = proptbl.begin(); e != proptbl.end(); e++) + properties.lappend(e.key()); + } + + catch (char *error) { + if (pfd != NULL) { + pti->ReleaseFuncDesc (pfd); pfd = NULL; + } + throw (error); + } + catch (HRESULT hr) { + if (pfd != NULL) { + pti->ReleaseFuncDesc (pfd); pfd = NULL; + } + throw (hr); + } +} + + + + + + +/* + *------------------------------------------------------------------------- + * TypeLib_DescribeTypeInfo -- + * Describe the type info in terms of the types kind, its methods, + * properties and inherited types. + * + * Result: + * Std Tcl return. + * + * Side effects: + * Can throw either HRESULT and char *. These probably can be removed + * and returned directly in the interpreter. I've left them to be + * picked up by the calling procedure, as that has its own exception + * handling code. + *------------------------------------------------------------------------- + */ +int TypeLib_DescribeTypeInfo (Tcl_Interp *pInterp, ITypeInfo *pti) +{ + int cmdresult = TCL_ERROR; + USES_CONVERSION; + + ASSERT (pti != NULL && pInterp != NULL); + TYPEATTR *pta = NULL; + HRESULT hr; + TObjPtr presult, + inherited, + methods, + properties; + BSTR bdoc = NULL; + + hr = pti->GetTypeAttr(&pta); + CHECKHR(hr); + + try { + if (pta->typekind == TKIND_ALIAS) { + presult.create (); + presult.lappend("typedef").lappend("").lappend(""); + + //TypeLib_GetImplTypes (pti, inherited); + TYPEDESC2Obj (pti, &(pta->tdescAlias), inherited); + presult.lappend (inherited); + cmdresult = TCL_OK; + } + + else { + inherited.create(); + methods.create(); + properties.create(); + TypeLib_GetImplTypes (pti, inherited); + TypeLib_ProcessFunctions (pti, methods, properties); + TypeLib_ProcessVariables (pti, properties); + + presult.create(); + switch (pta->typekind) + { + case TKIND_ENUM: + presult = "enum"; break; + case TKIND_RECORD: + presult = "struct"; break; + case TKIND_MODULE: + presult = "module"; break; + case TKIND_INTERFACE: + presult = "interface"; break; + case TKIND_DISPATCH: + presult = "dispatch"; break; + case TKIND_COCLASS: + presult = "class"; break; + case TKIND_UNION: + presult = "union"; break; + default: + presult = "???"; break; + } + + presult.lappend(methods).lappend(properties).lappend(inherited); + cmdresult = TCL_OK; + } + ReleaseTypeAttr (pti, pta); + } + catch (HRESULT hr) { + ReleaseTypeAttr (pti, pta); + throw (hr); + } + catch (char *error) { + ReleaseTypeAttr (pti, pta); + throw (error); + } + + if (cmdresult == TCL_OK) { + if (SUCCEEDED(pti->GetDocumentation (MEMBERID_NIL, NULL, &bdoc, NULL, NULL)) && bdoc != NULL) + { + presult.lappend (OLE2A(bdoc)); + SysFreeString (bdoc); + } + else + presult.lappend (""); + + Tcl_SetObjResult (pInterp, presult); + } + + return cmdresult; +} + + + + +/* + *------------------------------------------------------------------------- + * DescPropertyFuncDesc -- + * Helper function to provides a description in a tcl object, + * of a accessor based property. The property name, hash, typeinfo, + * compiler interface, funcdesc are already provided. The function evaluates + * the read/write priviliges, and type of the property, before building the + * resultant list. + * + * Result: + * None. + * + * Side effects: + * throws HRESULT or char* + *------------------------------------------------------------------------- + */ +void DescPropertyFuncDesc (BSTR name, ULONG hash, ITypeInfo *pti, + ITypeComp *pcmp, FUNCDESC *pfd, TObjPtr &pdesc) +{ + ASSERT (pti != NULL && pcmp != NULL); + + USES_CONVERSION; + + bool bRead = false, + bWrite = false; + BSTR * fnames = NULL; + char * szname = NULL; + OptclBindPtr obp; + HRESULT hr; + + UINT totalread = 0; + UINT total = 0; + TObjPtr fdesc, param, type, optionparam, flags; + + try { + // find out read/write access of this property + bWrite = (pfd->invkind==INVOKE_PROPERTYPUT || + pfd->invkind==INVOKE_PROPERTYPUTREF); + + // assertion: due to the order of computation, + // if bWrite is TRUE, then bRead will be false + bRead = !bWrite; + + if (!bWrite) { + hr = pcmp->Bind (name, hash, INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF, + &obp.m_pti, &obp.m_dk, &obp.m_bp); + bWrite = SUCCEEDED(hr) && (obp.m_bp.lpfuncdesc->invkind==INVOKE_PROPERTYPUT || + obp.m_bp.lpfuncdesc->invkind==INVOKE_PROPERTYPUTREF); + } + + total = pfd->cParams + 1; + fnames = new BSTR[total]; + hr = pti->GetNames(pfd->memid, fnames, total, &totalread); + CHECKHR(hr); + if (totalread != total) + throw ("couldn't retrieve all the parameter names"); + + pdesc.create(); + flags.create(); + if (bRead) + flags.lappend ("read"); + if (bWrite) + flags.lappend ("write"); + if (bRead) { // its a propertyget - use the return value of the function as the type + TYPEDESC2Obj (pti, &(pfd->elemdescFunc.tdesc), type); + } else { // its a propertyput only - use the first parameter + TYPEDESC2Obj (pti, &(pfd->lprgelemdescParam->tdesc), type); + } + pdesc.lappend(flags).lappend(type).lappend(W2A(fnames[0])); + + + // now build up the parameters + for (SHORT index = 0; index < pfd->cParams; index++) + { + ELEMDESC *elemdesc = pfd->lprgelemdescParam + index; + + flags.create(); + if (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FIN) + flags.lappend("in"); + if (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FOUT) + flags.lappend("out"); + if (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FRETVAL) + flags.lappend("retval"); + + // type of parameter + TYPEDESC2Obj(pti, &(elemdesc->tdesc), type); + + // setup the result + param.create(); + param.lappend(flags).lappend(type).lappend(W2A(fnames[index+1])); + + // is it optional and does it have a default value + if ((elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) + && (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FOPT)) { + VariantToObj (&(elemdesc->paramdesc.pparamdescex->varDefaultValue), optionparam); + param.lappend(optionparam); + } + else + if ((pfd->cParams - index)<=pfd->cParamsOpt) + param.lappend ("?"); + + pdesc.lappend(param); + } + + FreeBSTRArray (fnames, totalread); + delete fnames; + } + catch (char *error) { + FreeBSTRArray (fnames, totalread); + delete fnames; + throw (error); + } + + catch (HRESULT hr) { + FreeBSTRArray (fnames, totalread); + delete fnames; + throw (hr); + } +} + + + + + +/* + *------------------------------------------------------------------------- + * TypeLib_DescribeTypeInfoElement -- + * Called to describe an element of a type information pointer. Identifies + * it's role (currently only property or method), and retrieves a + * description. + * + * Result: + * Std Tcl result. + * + * Side effects: + * Throws HRESULT and char *. + *------------------------------------------------------------------------- + */ +int TypeLib_DescribeTypeInfoElement (Tcl_Interp *pInterp, ITypeInfo *pti, + const char *elem) +{ + ASSERT (pInterp != NULL && pti != NULL && elem != NULL); + + USES_CONVERSION; + + int cmdresult = TCL_ERROR; + HRESULT hr; + OptclBindPtr bp; + ULONG hash; + LPOLESTR name = A2OLE(elem); + CComPtr pcmp; + TObjPtr presult, + pdesc; + BSTR bdoc; + + try { + hr = pti->GetTypeComp (&pcmp); + CHECKHR(hr); + + hash = LHashValOfName (LOCALE_SYSTEM_DEFAULT, name); + hr = pcmp->Bind (name, hash, INVOKE_FUNC | INVOKE_PROPERTYGET, &bp.m_pti, &bp.m_dk, &bp.m_bp); + if (FAILED(hr) || (bp.m_dk == DESCKIND_NONE)) { + bp.ReleaseBindPtr(); + hr = pcmp->Bind (name, hash, INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF, &bp.m_pti, &bp.m_dk, &bp.m_bp); + } + + CHECKHR(hr); + + + cmdresult = TCL_OK; + switch (bp.m_dk) { + case DESCKIND_FUNCDESC: + // check access restrictions on the function + if (bp.m_bp.lpfuncdesc->wFuncFlags & FUNCFLAG_FRESTRICTED) { + Tcl_SetResult(pInterp, "you aren't allowed to view: '", TCL_STATIC); + Tcl_AppendResult (pInterp, (char*)elem, "'", NULL); + cmdresult = TCL_ERROR; + } else { + presult.create(); + if (bp.m_bp.lpfuncdesc->invkind == INVOKE_FUNC) {// its a standard function + FUNCDESC2Obj (bp.m_pti, bp.m_bp.lpfuncdesc, pdesc); + presult.lappend ("method").lappend(pdesc); + } + else {// its an implicit variable with accessor function + DescPropertyFuncDesc(name, hash, bp.m_pti, pcmp, bp.m_bp.lpfuncdesc, pdesc); + presult.lappend ("property").lappend(pdesc); + } + } + break; + + case DESCKIND_VARDESC: + if ((bp.m_bp.lpvardesc->wVarFlags & VARFLAG_FRESTRICTED)) { + Tcl_SetResult (pInterp, "you aren't allowed to view: '", TCL_STATIC); + Tcl_AppendResult (pInterp, (char*)elem, "'", NULL); + cmdresult = TCL_ERROR; + } else { + VARDESC2Obj (bp.m_pti, bp.m_bp.lpvardesc, pdesc); + presult.create(); + presult.lappend ("property").lappend(pdesc); + } + break; + + case DESCKIND_TYPECOMP: // don't know how to handle these ones at the moment + Tcl_SetResult (pInterp, "typecomp", TCL_STATIC); + break; + + case DESCKIND_IMPLICITAPPOBJ: // don't know how to handle these ones at the moment + Tcl_SetResult (pInterp, "appobj", TCL_STATIC); + break; + + case DESCKIND_NONE: + default: + Tcl_SetResult (pInterp, "can't find a description for '", TCL_STATIC); + Tcl_AppendResult (pInterp, (char*)elem, "'", NULL); + cmdresult = TCL_ERROR; + } + } + catch (HRESULT hr) { + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + cmdresult = TCL_ERROR; + } + catch (char *err) { + Tcl_SetResult (pInterp, err, TCL_VOLATILE); + cmdresult = TCL_ERROR; + } + + // get the documentation string + + if (cmdresult == TCL_OK && (bp.m_dk == DESCKIND_FUNCDESC || bp.m_dk == DESCKIND_VARDESC)) { + if (SUCCEEDED( + bp.m_pti->GetDocumentation (bp.m_dk==DESCKIND_FUNCDESC?bp.m_bp.lpfuncdesc->memid:bp.m_bp.lpvardesc->memid, + NULL, &bdoc, NULL, NULL)) && bdoc != NULL) + { + presult.lappend(OLE2A(bdoc)); + SysFreeString (bdoc); + } + else + { + presult.lappend (""); + } + Tcl_SetObjResult (pInterp, presult); + } + + return cmdresult; +} + + + + + +/* + *------------------------------------------------------------------------- + * TypeLib_LoadedLibs -- + * Lists the currently loaded libraries + * Result: + * TCL_OK iff ok. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +TCL_CMDEF(TypeLib_LoadedLibs) +{ + if (objc != 1) { + Tcl_WrongNumArgs (pInterp, 1, objv, ""); + return TCL_ERROR; + } + TObjPtr presult; + presult.create(false); + try { + for (TypeLibsTbl::iterator i = g_libs.begin();i != g_libs.end(); i++) + presult.lappend(i.key(), pInterp); + } + catch (char *error) { + Tcl_SetResult (pInterp, error, TCL_VOLATILE); + return TCL_ERROR; + } + Tcl_SetObjResult (pInterp, presult); + return TCL_OK; +} + + + +/* + *------------------------------------------------------------------------- + * TypeLib_LoadLib -- + * Ensures that a given library is loaded. A library is described in terms + * of its full human-readable name. + * + * Result: + * TCL_OK iff successful. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +TCL_CMDEF(TypeLib_LoadLib) +{ + if (objc != 2) { + Tcl_WrongNumArgs (pInterp, 1, objv, "full_libname"); + return TCL_ERROR; + } + TObjPtr libname; + libname.attach(objv[1], false); + if (g_libs.LoadLib (pInterp, libname) != NULL) + return TCL_OK; + else + return TCL_ERROR; +} + + + +/* + *------------------------------------------------------------------------- + * TypeLib_UnloadLib -- + * Unloads a loaded library, specified in its human readable description. + * Perhaps this could be extended to take multiple arguments. + * + * Result: + * Always TCL_OK + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +TCL_CMDEF(TypeLib_UnloadLib) +{ + if (objc != 2) { + Tcl_WrongNumArgs (pInterp, 1, objv, "full_libname"); + return TCL_ERROR; + } + TObjPtr libname; + libname.attach(objv[1], false); + g_libs.UnloadLib (pInterp, libname); + return TCL_OK; +} + +/* + *------------------------------------------------------------------------- + * TypeLib_IsLibLoaded -- + * Returns true in the interpreter if the library (specifed in the first + * parameter) is correct. + * Result: + * TCL_OK iff # of params ok + * Side effects: + * None + *------------------------------------------------------------------------- + */ +TCL_CMDEF(TypeLib_IsLibLoaded) +{ + if (objc != 2) { + Tcl_WrongNumArgs (pInterp, 1, objv, "fullname_library"); + return TCL_ERROR; + } + TObjPtr name; + TObjPtr value; + value.create(false); + name.attach(objv[1]); + value = g_libs.IsLibLoaded(name); + Tcl_SetObjResult (pInterp, value); + return TCL_OK; +} + +/* + *------------------------------------------------------------------------- + * TypeLib_TypesInLib -- + * Returns a list in the interpreter holding the name and typekind of each + * type described in the library referenced by the first parameter to this + * command. + * Result: + * Std Tcl return results. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +TCL_CMDEF (TypeLib_TypesInLib) +{ + USES_CONVERSION; + + if (objc != 2) { + Tcl_WrongNumArgs (pInterp, 1, objv, "programmatic_libname"); + return TCL_ERROR; + } + + + TypeLib *ptl = NULL; + TObjPtr name, typedesc, types, tname; + HRESULT hr; + TYPEKIND tkind; + CComPtr pti; + int retresult = TCL_ERROR; + TYPEATTR *pta = NULL; + ULONG flags; + + + + types.create(); + name.attach(objv[1]); + if (!g_libs.find(name, &ptl)) { + Tcl_SetResult (pInterp, "can't find library name: ", TCL_STATIC); + Tcl_AppendResult (pInterp, (char*)name, NULL); + return TCL_ERROR; + } + + ASSERT (ptl != NULL && ptl->m_ptl != NULL); + UINT count = ptl->m_ptl->GetTypeInfoCount(); + try { + for (UINT index = 0; index < count; index++) { + + + // get the type of the typeinfo + hr = ptl->m_ptl->GetTypeInfoType (index, &tkind); + CHECKHR(hr); + + // get the next typeifo + pti = NULL; // free the last typeinfo + hr = ptl->m_ptl->GetTypeInfo (index, &pti); + CHECKHR(hr); + + ASSERT (pti != NULL); + + // check whether this is a restricted type + hr = pti->GetTypeAttr (&pta); + CHECKHR(hr); + flags = pta->wTypeFlags; + ReleaseTypeAttr(pti, pta); + + if (flags & TYPEFLAG_FRESTRICTED) + continue; // it is so skip the rest of this iteration + TypeLib_GetName(ptl->m_ptl, pti, tname); + + typedesc.create(); + typedesc.lappend (TYPEKIND2Str(tkind)).lappend(tname); + types.lappend (typedesc); + } + Tcl_SetObjResult (pInterp, types); + retresult = TCL_OK; + } + + catch (char *error) { + Tcl_SetResult (pInterp, error, TCL_VOLATILE); + } + catch (HRESULT hr) { + Tcl_SetResult (pInterp, (char*)HRESULT2Str(hr), TCL_DYNAMIC); + } + + return retresult; +} + + + + + + + + + +/* + *------------------------------------------------------------------------- + * TypeLib_TypeInfo -- + * Implements the typelib::typeinfo command. + * + * Result: + * Std Tcl result. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +TCL_CMDEF(TypeLib_TypeInfo) +{ + USES_CONVERSION; + if (objc != 2 && objc != 3) { + Tcl_WrongNumArgs (pInterp, 1, objv, "typename ?type_element_name?"); + return TCL_ERROR; + } + + TObjPtr tname; + TypeLib *ptl = NULL; + BSTR bsTypename = NULL; + + CComPtr pti; + CComPtr ptc; + int cmdresult = TCL_ERROR; + + try { + tname.attach(objv[1]); + TypeLib_ResolveName (tname, &ptl, &pti); + + + if (objc == 2) { // describing the entire type + cmdresult = TypeLib_DescribeTypeInfo (pInterp, pti); + } else { // describing a single element within the type + TObjPtr item; + item.attach (objv[2]); + cmdresult = TypeLib_DescribeTypeInfoElement (pInterp, pti, item); + } + } + + catch (char *error) { + if (error != NULL) + Tcl_SetResult (pInterp, error, TCL_VOLATILE); + } + + catch (HRESULT hr) { + Tcl_SetResult (pInterp, (char*)HRESULT2Str(hr), TCL_DYNAMIC); + } + + return cmdresult; +} + + +/* + *------------------------------------------------------------------------- + * TypeLib_ResolveName -- + * Resolves a library name and type name to a typeinfo. + * if pptl is not NULL then the TypeLib structure for this type is provided + * as the result, also. + * May throw an HRESULT or char*. + * + * Result: + * None. + * Side effects: + * + *------------------------------------------------------------------------- + */ +void TypeLib_ResolveName (const char * lib, const char * type, + TypeLib **pptl, ITypeInfo **ppinfo) +{ + ASSERT (lib != NULL && type != NULL && ppinfo != NULL); + HRESULT hr; + + TypeLib * ptl = NULL; + + // bind to the library + if (g_libs.find (lib, &ptl) == NULL) + throw ("failed to bind to library"); + + ASSERT (ptl != NULL && ptl->m_ptl != NULL); + if (ptl->m_ptc == NULL) + throw("library doesn't provide a compiling interface"); + if (pptl != NULL) + *pptl = ptl; + + // find the type info if required + if (ppinfo != NULL && type != NULL) { + hr = BindTypeInfo(ptl->m_ptc, type, ppinfo); + CHECKHR(hr); + if (*ppinfo == NULL) + throw ("failed to bind to type"); + } +} + + +/* + *------------------------------------------------------------------------- + * TypeLib_ResolveName -- + * Resolves a fully formed type name (ie lib.type) to its type info. + * if pptl is not NULL then the TypeLib structure for this type is provided + * as the result, also. + * Throws HRESULT or (char*) in case of error. Apologies for this error style - + * I know that its predominant in this file - I was simply experimenting :) + * + * Result: + * None. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void TypeLib_ResolveName (const char *name, TypeLib **pptl, ITypeInfo **ppinfo) +{ + ASSERT (name != NULL); + char * lib = NULL, + * type = NULL; + char * copy = new char [strlen (name) + 1]; + strcpy (copy, name); + + try { + lib = strtok (copy, "."); + type = strtok (NULL, "."); + if (type == NULL && ppinfo != NULL) + throw ("string is not properly formatted"); + TypeLib_ResolveName (lib, type, pptl, ppinfo); + delete_ptr (copy); + } + + catch (HRESULT hr) { + delete_ptr (copy); + throw (hr); + } + + catch (char * error) { + delete_ptr (copy); + throw (error); + } +} + + + + +/* + *------------------------------------------------------------------------- + * TypeLib_ResolveConstant -- + * + * Result: + * + * Side effects: + * + *------------------------------------------------------------------------- + */ +bool TypeLib_ResolveConstant (Tcl_Interp *pInterp, ITypeInfo *pti, + const char *member, TObjPtr &pObj) +{ + ASSERT (pInterp != NULL && pti != NULL && member != NULL); + + USES_CONVERSION; + CComPtr ptc; + CComPtr ptmpti; + DESCKIND dk; + BINDPTR bp; bp.lpvardesc = NULL; + HRESULT hr; + LPOLESTR cnst = A2OLE (member); + +#ifdef _DEBUG + // *** TypeInfo must be an enumeration + TYPEATTR * pattr; + hr = pti->GetTypeAttr (&pattr); + CHECKHR(hr); + ASSERT (pattr->typekind == TKIND_ENUM); + pti->ReleaseTypeAttr (pattr); +#endif + + + try { + hr = pti->GetTypeComp (&ptc); + CHECKHR(hr); + + hr = ptc->Bind (cnst, LHashValOfName (LOCALE_SYSTEM_DEFAULT, cnst), + DISPATCH_PROPERTYGET, &ptmpti, &dk, &bp); + CHECKHR(hr); + if (dk == DESCKIND_NONE) + throw ("can't find constant"); + ASSERT (dk == DESCKIND_VARDESC || dk == DESCKIND_IMPLICITAPPOBJ); + + if (bp.lpvardesc->varkind != VAR_CONST) + throw ("member is not a constant"); + ASSERT (bp.lpvardesc->lpvarValue != NULL); + if (bp.lpvardesc->lpvarValue == NULL) + throw ("constant didn't have a associated value!"); + var2obj (pInterp, *(bp.lpvardesc->lpvarValue), pObj); + pti->ReleaseVarDesc (bp.lpvardesc); + return true; + } + + catch (char *e) { + if (bp.lpvardesc != NULL) + pti->ReleaseVarDesc (bp.lpvardesc); + + Tcl_SetResult (pInterp, (char*)member, TCL_VOLATILE); + Tcl_AppendResult (pInterp, ": ", e, NULL); + } + + catch (HRESULT hr) { + if (bp.lpvardesc != NULL) + pti->ReleaseVarDesc (bp.lpvardesc); + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + } + return false; +} + + + + + +/* + *------------------------------------------------------------------------- + * TypeLib_ResolveConstant -- + * Attempts to resolve the name of a constant to its value, to be stored + * in pObj. An optional type info constrains the binding. + * Result: + * true iff successful. Else error in interpreter. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool TypeLib_ResolveConstant (Tcl_Interp *pInterp, char *szname, + TObjPtr &pObj, ITypeInfo *pTypeInfo /* = NULL */) +{ + ASSERT (pInterp != NULL && szname != NULL); + + const char *token = "."; + char *name; + char *szfirst; + TypeLib * ptl; + CComPtr pti; + + try { + if (pTypeInfo == NULL) + { + // we'll use the stack for our allocation - saves on clean-up code + name = (char*)alloca (strlen(szname) + 1); + if (name == NULL) throw (HRESULT(E_OUTOFMEMORY)); + + strcpy (name, szname); + SplitTypedString (name, &szfirst); + if (szfirst == NULL) + throw ("badly formed constant"); + + // at this point, name points to the name of the type, and + // szfirst points to the name of the constant + + // retrieve the typelibrary, info and compiler interfaces + TypeLib_ResolveName (name, &ptl, &pti); + return TypeLib_ResolveConstant (pInterp, pti, szfirst, pObj); + } else { + return TypeLib_ResolveConstant (pInterp, pTypeInfo, szname, pObj); + } + + + } + + catch (char *e) { + Tcl_SetResult (pInterp, szname, TCL_VOLATILE); + Tcl_AppendResult (pInterp, ": ", e, NULL); + } + + catch (HRESULT hr) { + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + } + + return false; +} + + + +///// TEST CODE ///// + + +TCL_CMDEF(TypeLib_ResolveConstantTest) +{ + if (objc != 2 && objc != 3) + { + Tcl_WrongNumArgs (pInterp, 1, objv, "lib.type.member or lib.type member"); + return TCL_ERROR; + } + + TObjPtr result; + TObjPtr p1; + TObjPtr p2; + bool bOk; + + if (objc == 2) { + p1.attach(objv[1]); + bOk = TypeLib_ResolveConstant(pInterp, p1, result, NULL); + } else { + CComPtr pti; + TypeLib * ptl; + + p1.attach(objv[1]); + p2.attach(objv[2]); + + TypeLib_ResolveName (p1, &ptl, &pti); + bOk = TypeLib_ResolveConstant (pInterp, p2, result, pti); + } + if (bOk) { + Tcl_SetObjResult (pInterp, result); + return TCL_OK; + } else + return TCL_ERROR; +} + diff --git a/src/typelib.h b/src/typelib.h new file mode 100644 index 0000000..907709a --- /dev/null +++ b/src/typelib.h @@ -0,0 +1,81 @@ +/* + *------------------------------------------------------------------------------ + * typelib.h + * Declares a collection of function for accessing typelibraries. + * Currently this only includes browsing facilities. + * In the future, this may contain typelib building functionality. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + + +#ifndef _TYPELIB_H_62518A80_624A_11d4_8004_0040055861F2 +#define _TYPELIB_H_62518A80_624A_11d4_8004_0040055861F2 + +#include "tbase.h" + +// TypeLib provides the structure that holds the main pointer to the library ITypeLib +// interface, together with its compiler interface +struct TypeLib { + CComPtr m_ptl; + CComPtr m_ptc; + + TypeLib (ITypeLib *ptl, ITypeComp *ptc) { + m_ptl = ptl; + m_ptc = ptc; + } +}; + + + +// TypeLibsTbl - a hash table mapping library programmatic name to a TypeLib structure +// Internally it also holds a mapping from the a libraries human readable name to +// the same structure +class TypeLibsTbl : public THash +{ +public: + TypeLibsTbl (); + virtual ~TypeLibsTbl (); + void DeleteAll (); + ITypeLib* LoadLib (Tcl_Interp *pInterp, const char *fullname); + void UnloadLib (Tcl_Interp *pInterp, const char *fullname); + bool IsLibLoaded (const char *fullname); + TypeLib* EnsureCached (ITypeLib *pLib); + TypeLib* EnsureCached (ITypeInfo *pInfo); +protected: // methods + TypeLib* Cache (const char *szname, const char *szfullname, ITypeLib *ptl, ITypeComp *ptc); + +protected: // properties + THash m_loadedlibs; // by name +}; + +// globals +extern TypeLibsTbl g_libs; + + +void TypeLib_GetName (ITypeLib *, ITypeInfo *, TObjPtr &pname); +void TypeLib_ResolveName (const char *name, TypeLib **pptl, ITypeInfo **ppinfo); +void TypeLib_ResolveName (const char * lib, const char * type, TypeLib **pptl, ITypeInfo **ppinfo); +void ReleaseBindPtr (ITypeInfo *pti, DESCKIND dk, BINDPTR &ptr); +bool TypeLib_ResolveConstant (Tcl_Interp *pInterp, char *fullformatname, + TObjPtr &pObj, ITypeInfo *pInfo = NULL); +bool TypeLib_ResolveConstant (Tcl_Interp *pInterp, ITypeInfo *pti, + const char *member, TObjPtr &pObj); + + +#endif // _TYPELIB_H_62518A80_624A_11d4_8004_0040055861F2 \ No newline at end of file diff --git a/src/typelib.tcl b/src/typelib.tcl new file mode 100644 index 0000000..ac19136 --- /dev/null +++ b/src/typelib.tcl @@ -0,0 +1,622 @@ +package require registry +package provide optcl 3.0 + +namespace eval typelib { + variable syslibs + variable syslibguids + array set syslibs {} + array set syslibguids {} + + + # ----------------------------------------------------------------------------- + + # updatelibs -- called to enumerate and store the system libraries + proc updatelibs {} { + + variable syslibs; + catch {unset syslibs} + array set syslibs {} + + + set root {HKEY_CLASSES_ROOT\TypeLib} + foreach id [registry keys $root] { + catch { + foreach v [registry keys $root\\$id] { + scan $v "%d.%d" maj min; + if [catch { + set flags [registry get $root\\$id\\$v\\FLAGS {}]; + }] { set flags 0;} + + # check for restricted or hidden libraries + if {[expr ($flags & 1) || ($flags & 4)]} { + continue; + } + + set name "[registry get $root\\$id\\$v {}] (Ver $maj.$min)" + set syslibs($name) [list $id $maj $min] + } + } + } + } + + # ----------------------------------------------------------------------------- + + # categories -- returns the component categories + proc categories {} { + + set alldata {} + set k "HKEY_CLASSES_ROOT\\Component Categories" + set cats [registry keys $k] + + foreach cat $cats { + set values [registry values $k\\$cat] + set data {} + foreach value $values { + lappend data [registry get $k\\$cat $value] + } + lappend alldata $data + } + + return $alldata + } + + + + + # ----------------------------------------------------------------------------- + + # libdetail -- returns a the id, maj and min version number + # in a list if it exists, else throws an error + proc libdetail {name} { + variable syslibs + + if {[array names syslibs $name] == {}} { + error "could not find the library '$name'" + } + + return [lindex [array get syslibs $name] 1] + } + + + #------------------------------------------------------------------------------ + + # alllibs -- returns all the registered libraries by name + proc alllibs {} { + variable syslibs + return [array names syslibs] + } + + proc defaultinterface {classtype} { + set desc [typelib::typeinfo $classtype] + if {[llength $desc] != 3} { + error "$classtype is not a class" + } + set implintf [lindex $desc 2] + foreach intf $implintf { + if {[lsearch -exact [lindex $intf 0] default] >= 0} { + return [lindex $intf 1] + } + } + error "object doesn't have a default interface" + } + + #------------------------------------------------------------------------------ + updatelibs + +} + + + + + +if {[info commands tk] != {}} { + namespace eval tlview { + catch {font delete tlviewertext} + catch {font delete tlviewerhigh} + catch {font delete tlviewerbold} + font create tlviewertext -family Arial -size 9 -weight normal + font create tlviewerhigh -family Arial -size 9 -weight bold + font create tlviewerbold -family Arial -size 9 -weight bold + + variable bgcolor white + variable textcolor black + variable highlightcolor blue + variable selectcolor red + variable labelcolor red + + array set viewedtypes {} + + #------------------------------------------------------------------------------ + proc scrltxt {w {sb {x y}}} { + variable bgcolor; + frame $w -bd 2 -relief sunken; + + text $w.t -bg $bgcolor -bd 0 -relief flat -cursor arrow -width 40 -height 20 + grid $w.t -column 0 -row 0 -sticky nsew; + + if {[lsearch $sb x] >= 0} { + scrollbar $w.x -orient horizontal -command [list $w.t xview] + $w.t config -xscrollcommand [list $w.x set] -wrap none + grid $w.x -column 0 -row 1 -sticky ew; + } + if {[lsearch $sb y] >= 0} { + scrollbar $w.y -orient vertical -command [list $w.t yview] + $w.t config -yscrollcommand [list $w.y set] + grid $w.y -column 1 -row 0 -sticky ns; + } + + grid columnconfigure $w 0 -weight 1; + grid rowconfigure $w 0 -weight 1; + } + + + #------------------------------------------------------------------------------ + proc cl_list {w} { + variable bgcolor + frame $w -bd 2 -relief sunken + canvas $w.c -yscrollcommand "$w.v set" -xscrollcommand "$w.h set" -bd 0 -relief flat -cursor arrow -bg $bgcolor -highlightthickness 0 + scrollbar $w.h -orient horizontal -command "$w.c xview" + scrollbar $w.v -orient vertical -command "$w.c yview" + + grid $w.c -column 0 -row 0 -sticky news + grid $w.h -column 0 -row 1 -sticky ew + grid $w.v -column 1 -row 0 -sticky ns + grid columnconfigure $w 0 -weight 1 + grid rowconfigure $w 0 -weight 1 + bind $w.c <1> { focus %W } + bind $w.c { %W yview scroll -1 pages} + bind $w.c { %W yview scroll 1 pages} + return $w + } + + + + proc cl_list_update {w} { + variable ::typelib::syslibs + variable bgcolor + + if {![winfo exists $w]} { + error "expected to find a TypeLib list widget: $w" + } + + set c $w.c + $c delete all + + foreach tl [lsort [array names ::typelib::syslibs]] { + cl_list_addlib $w $tl + } + } + + + + proc cl_list_addlib {w tl} { + variable bgcolor + + set c $w.c + set bbox [$c bbox entry] + if {$bbox == {}} {set bbox {0 0 10 10}} + set bottom [lindex $bbox 3] + set bottom [expr int($bottom) + 3] + set tag [$c create text 10 $bottom -anchor nw -fill black -font tlviewertext -justify left -text $tl -tags entry] + $c bind $tag <1> [namespace code "cl_list_press $w $tag"] + cl_list_updatetag $w $tag + + set bbox [$c bbox entry] + set sr [list 0 0 [lindex $bbox 2] [expr $bottom + 20]] + $c config -scrollregion $sr + } + + + proc cl_list_updatetag {w tag} { + variable textcolor + variable highlightcolor + + set c $w.c + set tl [$c itemcget $tag -text] + + if {![typelib::isloaded $tl]} { + $c itemconfig $tag -fill $textcolor -font tlviewertext + } else { + $c itemconfig $tag -fill $highlightcolor -font tlviewerhigh + } + } + + + proc cl_list_press {w tag} { + set c $w.c + set tl [$c itemcget $tag -text] + set parent [winfo parent $w] + + if {![typelib::isloaded $tl]} { + # loading typelib + if {[catch {typelib::load $tl} progname]} { + puts $progname + $parent.error config -text [string trim $progname] + } else { + puts "loaded $progname" + $parent.error config -text "loaded $progname" + loadedlibs_updateall + } + } else { + typelib::unload $tl + puts "unloaded $tl" + $parent.error config -text "unloaded $tl" + loadedlibs_updateall + } + + cl_list_updatetag $w $tag + } + + + + proc refview {w} { + toplevel $w + wm title $w "Referenced Type Libraries" + bind $w "destroy $w" + bind $w "$w.close invoke" + bind $w "$w.refresh config -relief sunken; update; $w.refresh invoke; $w.refresh config -relief raised" + button $w.close -text Close -width 7 -command "destroy $w" -underline 0 + button $w.refresh -text Refresh -width 7 -command [namespace code "cl_list_update $w.list"] -underline 0 + label $w.error -bd 1 -relief sunken + + grid [cl_list $w.list] -column 0 -row 0 -columnspan 2 -sticky nsew + grid $w.close -column 0 -row 1 -padx 5 -pady 5 + grid $w.refresh -column 1 -row 1 -padx 5 -pady 5 + grid $w.error -column 0 -row 2 -columnspan 2 -sticky nsew + + grid columnconfig $w 0 -weight 1 + grid columnconfig $w 1 -weight 1 + grid rowconfig $w 0 -weight 1 + + cl_list_update $w.list + return $w + } + + + + #------------------------------------------------------------------------------ + + proc loadedlibs_updateall {} { + foreach w [winfo child .] { + if {[string compare [winfo class $w] TLLoadedTypeLibs] == 0} { + loadedlibs_update $w + } + } + } + + proc loadedlibs_update {w} { + variable bgcolor + variable textcolor + variable highlightcolor + + $w.l.t config -state normal + $w.l.t delete 1.0 end + foreach lib [lsort [typelib::loaded]] { + $w.l.t tag configure tag$lib -foreground $highlightcolor -font tlviewertext -underline 0 + $w.l.t insert end "$lib\n" tag$lib + $w.l.t tag bind tag$lib <1> [namespace code "viewlib $lib"] + $w.l.t tag bind tag$lib "$w.l.t config -cursor hand2; $w.l.t tag config tag$lib -underline 1" + $w.l.t tag bind tag$lib "$w.l.t config -cursor arrow; $w.l.t tag config tag$lib -underline 0" + } + $w.l.t config -state disabled + } + + proc loadedlibs {w} { + toplevel $w -class TLLoadedTypeLibs + + wm title $w "Loaded Libraries" + scrltxt $w.l + + grid $w.l -column 0 -row 0 -sticky nsew + grid columnconfig $w 0 -weight 1 + grid rowconfig $w 0 -weight 1 + loadedlibs_update $w + bind $w [namespace code "loadedlibs_update $w"] + } + + #------------------------------------------------------------------------------ + proc viewlib_onenter {txt tag} { + $txt config -cursor hand2 + $txt tag config $tag -underline 1 + } + + proc viewlib_onleave {txt tag} { + $txt config -cursor arrow + $txt tag config $tag -underline 0 + } + + proc viewlib_unselect {txt lib} { + variable viewedtypes + variable textcolor + if {[array name viewedtypes $lib] != {}} { + set type $viewedtypes($lib) + $txt tag config tag$type -foreground $textcolor -font tlviewertext + set viewedtypes($lib) {} + } + } + + + + proc viewlib_select {fulltype } { + variable viewedtypes + variable highlightcolor + + puts $fulltype + set sp [split $fulltype .] + if {[llength $sp] != 2} { + return + } + + set lib [lindex $sp 0] + set type [lindex $sp 1] + + set w [viewlib $lib] + set txt $w.types.t + + viewlib_unselect $txt $lib + $txt tag config tag$type -foreground $highlightcolor -font tlviewerhigh + + $txt see [lindex [$txt tag ranges tag$type] 0] + set viewedtypes($lib) $type + viewlib_readelems $w $lib $type; + } + + + proc viewlib_selectelem {w fulltype element} { + variable viewedtypes + variable highlightcolor + + puts "$fulltype $element" + set sp [split $fulltype .] + set lib [lindex $sp 0] + set type [lindex $sp 1] + + set txt $w.elems.t + + viewlib_unselect $txt $fulltype + $txt tag config tag$element -foreground $highlightcolor -font tlviewerhigh + $txt see [lindex [$txt tag ranges tag$element] 0] + set viewedtypes($fulltype) $element + viewlib_readdesc $w $lib $type $element + } + + ### + # creates a list of types in some library + proc viewlib_readtypes {w lib} { + variable textcolor + set txt $w.types.t + + $txt config -state normal + $txt del 1.0 end + + foreach tdesc [lsort [typelib::types $lib]] { + $txt insert end "[lindex $tdesc 0]\t" + set full [lindex $tdesc 1] + set type [lindex [split $full .] 1] + $txt tag configure tag$type -foreground $textcolor -font tlviewertext -underline 0 + $txt insert end "$type\n" tag$type + $txt tag bind tag$type <1> [namespace code " + viewlib_select $full; + "] + + $txt tag bind tag$type [namespace code "viewlib_onenter $txt tag$type"] + $txt tag bind tag$type [namespace code "viewlib_onleave $txt tag$type"] + } + $txt config -state disabled + } + + + proc viewlib_writetype {txt fulltype} { + variable highlightcolor + if {[llength [split $fulltype .]] > 1} { + $txt tag configure tag$fulltype -foreground $highlightcolor -font tlviewertext -underline 0 + $txt tag bind tag$fulltype [namespace code "viewlib_onenter $txt tag$fulltype"] + $txt tag bind tag$fulltype [namespace code "viewlib_onleave $txt tag$fulltype"] + $txt tag bind tag$fulltype <1> [namespace code "viewlib_select $fulltype"] + $txt insert end "$fulltype" tag$fulltype + } else { + $txt insert end "$fulltype" + } + } + + + ### + # displays the elements for a type of some library + proc viewlib_readelems {w lib type} { + variable labelcolor + variable textcolor + variable highlightcolor + + set txt $w.elems.t + $txt config -state normal + $txt del 1.0 end + set elems [typelib::typeinfo $lib.$type] + loadedlibs_updateall + + $txt tag configure label -font tlviewerhigh -underline 1 -foreground $labelcolor + + if {[string compare "typedef" [lindex $elems 0]] == 0} { + # --- we are working with a typedef + set t [lindex $elems 3] + $txt insert end "Typedef\n\t" label + viewlib_writetype $txt $t + } else { + if {[llength [lindex $elems 1]] != 0} { + $txt insert end "Methods\n" label + } + + foreach method [lsort [lindex $elems 1]] { + $txt tag configure tag$method -foreground $textcolor -font tlviewertext -underline 0 + $txt tag bind tag$method [namespace code "viewlib_onenter $txt tag$method"] + $txt tag bind tag$method [namespace code "viewlib_onleave $txt tag$method"] + $txt tag bind tag$method <1> [namespace code "viewlib_selectelem $w $lib.$type $method"] + $txt insert end "\t$method\n" tag$method + } + + if {[llength [lindex $elems 2]] != 0} { + $txt insert end "Properties\n" label + } + + foreach prop [lsort [lindex $elems 2]] { + $txt tag configure tag$prop -foreground $textcolor -font tlviewertext -underline 0 + $txt tag bind tag$prop [namespace code "viewlib_onenter $txt tag$prop"] + $txt tag bind tag$prop [namespace code "viewlib_onleave $txt tag$prop"] + $txt tag bind tag$prop <1> [namespace code "viewlib_selectelem $w $lib.$type $prop"] + $txt insert end "\t$prop\n" tag$prop + } + + if {[llength [lindex $elems 3]] != 0} { + $txt insert end "Inherited Types\n" label + } + + foreach impl [lsort -index 1 [lindex $elems 3]] { + # implemented interfaces + set t [lindex $impl 1] + set flags [lindex $impl 0] + if {[lsearch -exact $flags default] != -1} { + $txt insert end "*" + } + + if {[lsearch -exac $flags source] != -1} { + $txt insert end "event" + } + $txt insert end "\t" + + $txt tag configure itag$t -foreground $highlightcolor -font tlviewertext -underline 0 + $txt tag bind itag$t [namespace code "viewlib_onenter $txt itag$t"] + $txt tag bind itag$t [namespace code "viewlib_onleave $txt itag$t"] + $txt tag bind itag$t <1> [namespace code "viewlib_select $t"] + + $txt insert end "$t\n" itag$t + } + } + $txt config -state disabled + viewlib_settypedoc $w [lindex $elems 4] + } + + + proc viewlib_settypedoc {w doc} { + set txt $w.desc.t + $txt config -state normal + $txt delete 1.0 end + $txt insert end $doc + $txt config -state disabled + } + + + ### + # retrieves the description for an element + proc viewlib_readdesc {w lib type elem} { + variable labelcolor + + set txt $w.desc.t + $txt config -state normal + $txt delete 1.0 end + + $txt tag configure label -font tlviewerhigh -underline 1 -foreground $labelcolor + $txt tag configure element -font tlviewerbold + $txt tag bind element [namespace code "viewlib_onenter $txt element"] + $txt tag bind element [namespace code "viewlib_onleave $txt element"] + + $txt tag bind element <1> [namespace code "viewlib_select $lib.$type; viewlib_selectelem $w $lib.$type $elem"] + + set desc [typelib::typeinfo $lib.$type $elem] + set kind [lindex $desc 0] + switch $kind { + property { + $txt insert end "Property" label + $txt insert end "\t[lindex $desc 2]\n" + + set p [lindex $desc 1] + # insert the flags + $txt insert end "[lindex $p 0]\t" + viewlib_writetype $txt [lindex $p 1] + $txt insert end " " + $txt insert end "[lindex $p 2]" element + + set params [lrange $p 3 end] + + foreach param $params { + $txt insert end "\n\t" + + if {[llength $param] == 3} { + $txt insert end "[lindex $param 0]\t" + set param [lrange $param 1 end] + } + viewlib_writetype $txt [lindex $param 0] + $txt insert end " [lrange $param 1 end]" + } + } + + method { + set m [lindex $desc 1] + $txt insert end "Method" label + $txt insert end "\t[lindex $desc 2]\n" + viewlib_writetype $txt [lindex $m 0] + $txt insert end " " + $txt insert end "[lindex $m 1]" element + set params [lrange $m 2 end] + + foreach param $params { + $txt insert end "\n\t" + + if {[llength $param] == 3} { + $txt insert end "[lindex $param 0]\t" + set param [lrange $param 1 end] + } + viewlib_writetype $txt [lindex $param 0] + $txt insert end " [lrange $param 1 end]" + } + } + } + + puts [lindex $desc 1] + $txt config -state disabled + } + + + #### + # Creates a viewer for library + proc viewlib {lib} { + set w ._tlview$lib + if [winfo exists $w] { + raise $w + return $w + } + toplevel $w -class tlview_$lib + wm title $w "Type Library: $lib" + + label $w.tl -text Types; + label $w.el -text Elements; + label $w.dl -text Description; + + scrltxt $w.types; + scrltxt $w.elems + scrltxt $w.desc y + $w.desc.t config -height 5 + $w.desc.t config -state disabled + $w.elems.t config -state disabled + $w.types.t config -state disabled + + grid $w.tl -column 0 -row 0 -sticky nw + grid $w.types -column 0 -row 1 -sticky news -padx 2 -pady 2 + grid $w.el -column 1 -row 0 -sticky nw + grid $w.elems -column 1 -row 1 -sticky news -padx 2 -pady 2 + grid $w.dl -column 0 -row 2 -sticky nw + grid $w.desc -column 0 -row 3 -columnspan 2 -sticky news -padx 2 -pady 2 + + grid columnconfigure $w 0 -weight 1 + grid columnconfigure $w 1 -weight 1 + grid rowconfigure $w 1 -weight 1 + #grid rowconfigure $w 3 -weight 1 + + viewlib_readtypes $w $lib + return $w + } + + + proc viewtype {fullname} { + viewlib_select $fullname + } + } +} \ No newline at end of file diff --git a/src/utility.cpp b/src/utility.cpp new file mode 100644 index 0000000..ea4bba6 --- /dev/null +++ b/src/utility.cpp @@ -0,0 +1,1045 @@ +/* + *------------------------------------------------------------------------------ + * utility.cpp + * Implements a collection of often used, general purpose functions. + * I've also placed the variant/Tcl_Obj conversion functions here. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ + + +#include "stdafx.h" +#include "tbase.h" +#include "utility.h" +#include "optcl.h" +#include "objmap.h" +#include "typelib.h" +#include "optclobj.h" +#include "optcltypeattr.h" + +#ifdef _DEBUG +/* + *------------------------------------------------------------------------- + * OptclTrace -- + * Performs a debugging service similar to printf. Works only under debug. + * #defined to TRACE(formatstring, ....) + * Result: + * None. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void OptclTrace(LPCTSTR lpszFormat, ...) +{ + va_list args; + va_start(args, lpszFormat); + + int nBuf; + TCHAR szBuffer[512]; + + nBuf = _vsntprintf(szBuffer, _countof(szBuffer), lpszFormat, args); + + // was there an error? was the expanded string too long? + ASSERT(nBuf >= 0); + + OutputDebugString (szBuffer); + va_end(args); +} +#endif //_DEBUG + + +/* + *------------------------------------------------------------------------- + * HRESULT2Str -- + * Converts an HRESULT to a Tcl allocated string. + * + * Result: + * The string if not null. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +char * HRESULT2Str (HRESULT hr) +{ + + USES_CONVERSION; + + LPTSTR szMessage; + char *message; + char *tclmessage; + + if (HRESULT_FACILITY(hr) == FACILITY_WINDOWS) + hr = HRESULT_CODE(hr); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + hr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language + (LPTSTR)&szMessage, + 0, + NULL ); + + // conversion to char * if unicode + message = T2A (szMessage); + tclmessage = Tcl_Alloc(strlen(message)+1); + strcpy(tclmessage, message); + for (char *i = tclmessage; *i != 0; i++) + if (*i == '\r') *i = ' '; + LocalFree(szMessage); + return tclmessage; +} + + + + +/* + *------------------------------------------------------------------------- + * FreeBSTR -- + * If not NULL, releases the BSTR and sets it to NULL. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void FreeBSTR (BSTR &bstr) +{ + if (bstr != NULL) { + SysFreeString (bstr); + bstr = NULL; + } +} + + +/* + *------------------------------------------------------------------------- + * FreeBSTRArray -- + * Releases an array of BSTR and sets them to NULL, if not already. + * + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void FreeBSTRArray (BSTR * bstr, UINT count) +{ + if (bstr == NULL) return; + for (UINT index = 0; index < count; index++) + { + FreeBSTR (bstr[index]); + } +} + + + +/* + *------------------------------------------------------------------------- + * ExceptInfo2Str -- + * Converts an EXCEPINFO structure to a Tcl allocated string. + * + * Result: + * The string if not null. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +char * ExceptInfo2Str (EXCEPINFO *pe) +{ + USES_CONVERSION; + + ASSERT (pe != NULL); + char * str = NULL; + HRESULT hr; + + char* stderror = "unknown error"; + + if (pe->bstrDescription == NULL) { + if (pe->pfnDeferredFillIn != NULL) { + hr = (pe->pfnDeferredFillIn)(pe); + if (FAILED (hr) || pe->bstrDescription==NULL) + return HRESULT2Str(hr); + } + else + { + str = Tcl_Alloc (strlen(stderror)+1); + strcpy (str, stderror); + return str; + } + } + + TDString s; + s.set("error - "); + + if (pe->bstrSource != NULL) + s << "source: \"" << W2A(pe->bstrSource) << "\" "; + s << "description: \"" << W2A(pe->bstrDescription) << "\""; + str = Tcl_Alloc(s.length () + 1); + strcpy (str, s); + return str; +} + + + +/* + *------------------------------------------------------------------------- + * Name2ID -- + * Converts a name of a dispatch member to an id. + * Result: + * Either DISPID_UNKNOWN if failed or the dispid. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +DISPID Name2ID (IDispatch *pdisp, const char *name) +{ + USES_CONVERSION; + ASSERT (pdisp != NULL && name != NULL); + LPOLESTR olestr = A2OLE ((char*)name); + DISPID dispid = DISPID_UNKNOWN; + + pdisp->GetIDsOfNames (IID_NULL, &olestr, 1, LOCALE_SYSTEM_DEFAULT, &dispid); + return dispid; +} + + +/* + *------------------------------------------------------------------------- + * Name2ID -- + * Converts a name (OLE string) of a dispatch member to an id. + * Result: + * Either DISPID_UNKNOWN if failed or the dispid. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +DISPID Name2ID (IDispatch *pdisp, const LPOLESTR olename) +{ + DISPID dispid = DISPID_UNKNOWN; + pdisp->GetIDsOfNames (IID_NULL, (LPOLESTR*)&olename, 1, LOCALE_SYSTEM_DEFAULT, &dispid); + return dispid; +} + + + +void OptclVariantClear (VARIANT *pvar) +{ + ASSERT (pvar != NULL); + if ((pvar->vt & VT_BYREF) || pvar->vt == VT_VARIANT) { + switch (pvar->vt & (~VT_BYREF)) { + case VT_VARIANT: + OptclVariantClear (pvar->pvarVal); + g_pmalloc->Free (pvar->pvarVal); + break; + case VT_ERROR: + case VT_I2: + case VT_UI1: + g_pmalloc->Free (pvar->piVal); + break; + // long + case VT_HRESULT: + case VT_I4: + case VT_UI2: + case VT_INT: + g_pmalloc->Free (pvar->plVal); + break; + // float + case VT_R4: + g_pmalloc->Free (pvar->pfltVal); + break; + + // double + case VT_R8: + g_pmalloc->Free (pvar->pdblVal); + break; + + // boolean + case VT_BOOL: + g_pmalloc->Free (pvar->pboolVal); + break; + // object + case VT_UNKNOWN: + case VT_DISPATCH: + if (pvar->ppunkVal != NULL) { + (*(pvar->ppunkVal))->Release(); + g_pmalloc->Free (pvar->ppunkVal); + } + break; + case VT_CY: + g_pmalloc->Free (pvar->pcyVal); + break; + case VT_DATE: + g_pmalloc->Free (pvar->pdate); + break; + case VT_BSTR: + if (pvar->pbstrVal != NULL) { + SysFreeString (*(pvar->pbstrVal)); + g_pmalloc->Free (pvar->pbstrVal); + } + break; + case VT_RECORD: + case VT_VECTOR: + case VT_ARRAY: + case VT_SAFEARRAY: + ASSERT (FALSE); // case not handled yet + break; + + default: + ASSERT (FALSE); // unknown type + } + } + else + VariantClear (pvar); +} + + + + +bool var2obj_byref (Tcl_Interp *pInterp, VARIANT &var, TObjPtr &presult, OptclObj **ppObj) +{ + ASSERT (var.ppunkVal != NULL); + + USES_CONVERSION; + + bool bOk = false; + BSTR bstr = NULL; + HRESULT hr = S_OK; + OptclObj * pObj = NULL; + + + presult.create(); + if (var.ppunkVal == NULL) { + presult = 0; + return true; + } + try { + switch (var.vt & ~VT_BYREF) + { + case VT_DISPATCH: + case VT_UNKNOWN: + if (*var.ppunkVal != NULL) { + pObj = g_objmap.Add (pInterp, *var.ppunkVal); + presult = (const char*)(*pObj); // cast to char* + if (ppObj != NULL) + *ppObj = pObj; + } + else + presult = 0; + break; + case VT_BOOL: + presult = (bool)(*var.pboolVal != 0); + break; + + case VT_ERROR: + case VT_I2: + presult = *var.piVal; + break; + + case VT_HRESULT: + case VT_I4: + case VT_UI2: + case VT_INT: + presult = *var.plVal; + break; + case VT_R4: + presult = (double)(*var.pfltVal); + break; + case VT_R8: + presult = (double)(*var.pdblVal); + break; + case VT_BSTR: + presult = OLE2A(*var.pbstrVal); + break; + case VT_CY: + hr = VarBstrFromCy (*var.pcyVal, LOCALE_SYSTEM_DEFAULT, NULL, &bstr); + CHECKHR_TCL(hr, pInterp, false); + break; + case VT_DATE: + hr = VarBstrFromDate (*var.pdblVal, LOCALE_SYSTEM_DEFAULT, NULL, &bstr); + CHECKHR_TCL(hr, pInterp, false); + break; + case VT_VARIANT: + if (var.pvarVal == NULL) { + Tcl_SetResult (pInterp, "pointer to null", TCL_STATIC); + bOk = false; + } else { + bOk = var2obj (pInterp, *var.pvarVal, presult, ppObj); + } + break; + default: + presult = "?unhandledtype?"; + } + bOk = true; + if (bstr != NULL) { + presult = OLE2A(bstr); + SysFreeString (bstr); bstr = NULL; + } + } + catch (char *err) { + Tcl_SetResult (pInterp, err, TCL_VOLATILE); + } + return bOk; +} + + +/* + *------------------------------------------------------------------------- + * var2obj -- + * Converts a variant to a Tcl_Obj without type information. + * Result: + * true iff successful, else interpreter holds error string. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool var2obj (Tcl_Interp *pInterp, VARIANT &var, TObjPtr &presult, OptclObj **ppObj /* = NULL*/) +{ + USES_CONVERSION; + + ASSERT (pInterp != NULL); + ASSERT (ppObj == NULL || *ppObj == NULL); + + + OptclObj * pObj = NULL; + _variant_t comvar; + HRESULT hr = S_OK; + _bstr_t name; + bool bOk = false; + + + if ((var.vt & VT_ARRAY) || (var.vt & VT_VECTOR)) { + Tcl_SetResult (pInterp, "can't handle arrays or vectors for now", TCL_STATIC); + return false; + } + + if (var.vt == VT_VARIANT) { + ASSERT (var.pvarVal != NULL); + return var2obj (pInterp, *(var.pvarVal), presult, ppObj); + } + + if (var.vt & VT_BYREF) + return var2obj_byref (pInterp, var, presult, ppObj); + + presult.create(); + + try { + switch (var.vt) + { + case VT_DISPATCH: + case VT_UNKNOWN: + if (var.punkVal != NULL) { + pObj = g_objmap.Add (pInterp, var.punkVal); + presult = (const char*)(*pObj); // cast to char* + if (ppObj != NULL) + *ppObj = pObj; + } + else + presult = 0; + break; + case VT_BOOL: + presult = (bool)(var.boolVal != 0); + break; + case VT_I2: + presult = var.iVal; + break; + case VT_I4: + presult = var.lVal; + break; + case VT_R4: + presult = (double)(var.fltVal); + break; + case VT_R8: + presult = (double)(var.dblVal); + break; + default: // standard string conversion required + comvar = var; + name = comvar; + presult = (char*)name; + } + bOk = true; + } + + catch (HRESULT hr) { + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + } + catch (_com_error ce) { + Tcl_SetResult (pInterp, T2A((TCHAR*)ce.ErrorMessage()), TCL_VOLATILE); + } + catch (char *err) { + Tcl_SetResult (pInterp, err, TCL_VOLATILE); + } + + return bOk; +} + + + + + + + +/* + *------------------------------------------------------------------------- + * obj2var_ti -- + * converts a Tcl_Obj to a variant using type information. + * + * Result: + * true iff successful, else interpreter holds error string. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +// nb - pInfo is the context for pdesc +bool obj2var_ti (Tcl_Interp *pInterp, TObjPtr &obj, VARIANT &var, + ITypeInfo *pInfo, TYPEDESC *pdesc) +{ + ASSERT ((pInfo == NULL && pdesc == NULL) || (pInfo != NULL && pdesc != NULL)); + ASSERT (pInterp != NULL); + + OptclTypeAttr ota; + CComPtr pcurrent; + CComPtr ptmpunk; + HRESULT hr; + TObjPtr ptmp; + bool bOk = false; + OptclObj * pOptclObj = NULL; + long lValue; + + // if no type description has been provided, do a simple conversion + if (pdesc == NULL) { + obj2var (obj, var); + bOk = true; + } + + // a simple type + else if (pdesc->vt != VT_USERDEFINED && pdesc->vt != VT_SAFEARRAY) { + if (pdesc->vt != VT_PTR) + return obj2var_vt (pInterp, obj, var, pdesc->vt); + else { + ASSERT (pdesc->lptdesc->vt != VT_PTR && + pdesc->lptdesc->vt != VT_USERDEFINED && + pdesc->lptdesc->vt != VT_SAFEARRAY); + + if (pdesc->lptdesc->vt == VT_PTR || + pdesc->lptdesc->vt == VT_USERDEFINED || + pdesc->lptdesc->vt == VT_SAFEARRAY) + { + Tcl_SetResult (pInterp, "can't convert - optcl doesn't support level of de-referencing", TCL_STATIC); + return false; + } + return obj2var_vt_byref (pInterp, obj, var, pdesc->lptdesc->vt); + } + } + + // arrays - should be easy to do - not enough time right now... + else if (pdesc->vt == VT_SAFEARRAY) { + // wont do arrays for now. + Tcl_SetResult (pInterp, "optcl doesn't currently handle array types", TCL_STATIC); + } + + else { + // type information provided and it refers to a user defined type + // resolve the initial type + + hr = pInfo->GetRefTypeInfo (pdesc->hreftype, &ota.m_pti); + CHECKHR(hr); + g_libs.EnsureCached (ota.m_pti); + hr = ota.GetTypeAttr(); + CHECKHR(hr); + ASSERT (ota.m_pattr != NULL); + pcurrent = pInfo; + + while (ota->typekind == TKIND_ALIAS && + ota->tdescAlias.vt == VT_USERDEFINED) + { + HREFTYPE href = ota->tdescAlias.hreftype; + pcurrent = ota.m_pti; + ota = NULL; // release the type attribute and type info + pcurrent->GetRefTypeInfo (href, &ota.m_pti); + hr = ota.GetTypeAttr(); + CHECKHR(hr); + } + + // we've now climbed back up the alias chain and have one of the following: + // enum, record, module, interface, dispatch, coclass, union or alias to a basic type + // The following we can't (currently) do anything useful with: record, union, module. + + if (ota.m_pattr->typekind == TKIND_ALIAS) + return obj2var_ti (pInterp, obj, var, pcurrent, &(ota->tdescAlias)); + + + TYPEKIND tk = ota->typekind; // the metaclass + GUID intfguid = ota->guid; + + + switch (tk) + { + case TKIND_ENUM: + if (bOk = (Tcl_GetLongFromObj (NULL, obj, &lValue) == TCL_OK)) + obj2var(obj, var); + else if (bOk = TypeLib_ResolveConstant (pInterp, obj, ptmp, ota.m_pti)) + obj2var (ptmp, var); + break; + + case TKIND_DISPATCH: + case TKIND_INTERFACE: + // both these case require an object with the correct interface + pOptclObj = g_objmap.Find (obj); + if (pOptclObj != NULL) { + ptmpunk = (IUnknown*)(*pOptclObj); + ASSERT (ptmpunk != NULL); + hr = ptmpunk->QueryInterface (intfguid, (void**)&(var.punkVal)); + CHECKHR(hr); + V_VT(&var) = VT_UNKNOWN; + bOk = true; + } else + ObjectNotFound (pInterp, obj); + break; + + case TKIND_COCLASS: + pOptclObj = g_objmap.Find (obj); + if (pOptclObj != NULL) { + var.punkVal = (IUnknown*)(*pOptclObj); + var.punkVal->AddRef(); + V_VT(&var) = VT_UNKNOWN; + bOk = true; + } else + ObjectNotFound (pInterp, obj); + break; + + case TKIND_ALIAS: + ASSERT (FALSE); // should be hanlded above. + break; + + // can't handle these types + case TKIND_MODULE: + case TKIND_RECORD: + case TKIND_UNION: + obj2var (obj, var); + bOk = true; + break; + + default: + break; + } + } + + return bOk; +} + + + + + + + +/* + *------------------------------------------------------------------------- + * obj2var -- + * Converts a Tcl object to a variant without type information. + * If the Tcl object is null, then sets the value to zero. + * Result: + * None. + * + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void obj2var (TObjPtr &obj, VARIANT &var) +{ + _variant_t v; + ASSERT (var.vt == VT_EMPTY); + try { + if (obj.isnull()) { + var.lVal = 0; + var.vt = VT_I4; + } else { + + if (Tcl_GetLongFromObj (NULL, obj, &V_I4(&var)) == TCL_OK) + V_VT(&var) = VT_I4; + + else if (Tcl_GetDoubleFromObj (NULL, obj, &V_R8(&var)) == TCL_OK) + V_VT(&var) = VT_R8; + + else { + v.Attach (var); + v = (char*)(obj); + var = v.Detach(); + } + + #if _DEBUG + if (obj->typePtr != NULL) { + TRACE ("%s\n", obj->typePtr->name); + } + #endif // _DEBUG + } + } + + catch (_com_error ce) { + throw (HRESULT(ce.Error())); + } +} + + +static char memerr[] = "out of memory"; + +#define CHECKMEM_TCL(x, interp, action) if ((x) == NULL) { \ + Tcl_SetResult (interp, memerr, TCL_STATIC); \ + action; \ +} + +bool obj2var_vt_byref (Tcl_Interp *pInterp, TObjPtr &obj, VARIANT &var, VARTYPE vt) +{ + USES_CONVERSION; + + ASSERT ((vt & VT_BYREF) == 0); // we know that this is a BYREF variant - we don't want it in the vt + OptclObj * pOptclObj = NULL; + bool bok = true; + IUnknown * pUnk= NULL; + VARIANT temp; + + + if (vt == VT_VARIANT) { + var.pvarVal = (VARIANT*)g_pmalloc->Alloc (sizeof(VARIANT)); + CHECKMEM_TCL(var.pvarVal, pInterp, return false); + VariantInit (var.pvarVal); + if (!obj2var_vt (pInterp, obj, *var.pvarVal, vt)) { + g_pmalloc->Free(var.pvarVal); + var.pvarVal = NULL; + return false; + } + var.vt = vt | VT_BYREF; + return true; + } + + + VariantInit(&temp); + // perform the conversion into a temporary variant + if (!obj2var_vt (pInterp, obj, temp, vt)) + return false; + + + switch (temp.vt) { + // short + case VT_ERROR: + case VT_I2: + case VT_UI1: + var.piVal = (short*)g_pmalloc->Alloc (sizeof(short)); + CHECKMEM_TCL(var.pvarVal, pInterp, bok = false); + if (bok) *var.piVal = temp.iVal; + break; + + // long + case VT_HRESULT: + case VT_I4: + case VT_UI2: + case VT_INT: + var.plVal = (long*)g_pmalloc->Alloc (sizeof(long)); + CHECKMEM_TCL(var.plVal, pInterp, bok = false); + if (bok) *var.plVal = temp.lVal; + break; + + // float + case VT_R4: + var.pfltVal = (float*)g_pmalloc->Alloc(sizeof(float)); + CHECKMEM_TCL(var.pfltVal, pInterp, bok = false); + if (bok) *var.pfltVal = temp.fltVal; + break; + + // double + case VT_R8: + var.pdblVal = (double*)g_pmalloc->Alloc(sizeof(double)); + CHECKMEM_TCL(var.pdblVal, pInterp, bok = false); + if (bok) *var.pdblVal = temp.dblVal; + break; + + // boolean + case VT_BOOL: + var.pboolVal = (VARIANT_BOOL*)g_pmalloc->Alloc(sizeof(VARIANT_BOOL)); + CHECKMEM_TCL(var.pboolVal, pInterp, bok = false); + if (bok) *var.pboolVal = temp.boolVal; + break; + + // object + case VT_UNKNOWN: + case VT_DISPATCH: + // now allocate the memory + var.ppunkVal = (LPUNKNOWN*)g_pmalloc->Alloc(sizeof (LPUNKNOWN)); + CHECKMEM_TCL(var.ppunkVal, pInterp, bok = false); + if (bok) { + *var.ppunkVal = temp.punkVal; + if (*var.ppunkVal != NULL) + (*var.ppunkVal)->AddRef(); + } + break; + + case VT_CY: + var.pcyVal = (CY*)g_pmalloc->Alloc(sizeof(CY)); + CHECKMEM_TCL(var.pcyVal, pInterp, bok = false); + if (bok) *var.pcyVal = temp.cyVal; + break; + case VT_DATE: + var.pdate = (DATE*)g_pmalloc->Alloc(sizeof(DATE)); + CHECKMEM_TCL(var.pdate, pInterp, bok = false); + if (bok) *var.pdate = temp.date; + break; + case VT_BSTR: + var.pbstrVal = (BSTR*)g_pmalloc->Alloc(sizeof(BSTR)); + CHECKMEM_TCL(var.pdate, pInterp, bok = false); + if (bok) { + *var.pbstrVal = SysAllocStringLen (temp.bstrVal, SysStringLen(temp.bstrVal)); + if (*var.pbstrVal == NULL) { + g_pmalloc->Free (var.pbstrVal); var.pbstrVal = NULL; + Tcl_SetResult (pInterp, memerr, TCL_STATIC); + bok = false; + } + } + + break; + case VT_RECORD: + case VT_VECTOR: + case VT_ARRAY: + case VT_SAFEARRAY: + ASSERT (FALSE); // case not handled yet + break; + + default: + ASSERT (FALSE); // should never get here. + } + + var.vt = temp.vt | VT_BYREF; + VariantClear(&temp); + return bok; +} + + +/* + *------------------------------------------------------------------------- + * obj2var_vt -- + * Converts a Tcl object to a variant of a certain type. + * Result: + * None. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool obj2var_vt (Tcl_Interp *pInterp, TObjPtr &obj, VARIANT &var, VARTYPE vt) +{ + ASSERT ((vt & VT_BYREF) == 0); // house rules: no by-reference variants here! + + OptclObj *pOptclObj = NULL; + IUnknown * ptmpunk = NULL; + bool bOk = true; + HRESULT hr; + + switch (vt) + { + case VT_DISPATCH: + case VT_UNKNOWN: + V_VT(&var) = vt; + if (obj.isnull()) + var.punkVal = NULL; + else { + // attempt to cast from an optcl object + pOptclObj = g_objmap.Find (obj); + + + if (pOptclObj != NULL) { // found it? + ptmpunk = (IUnknown*)(*pOptclObj); // pull out the IUnknown pointer + ASSERT (ptmpunk != NULL); + if (vt == VT_DISPATCH) { // query to IDispatch iff required + hr = ptmpunk->QueryInterface (IID_IDispatch, (VOID**)&ptmpunk); + CHECKHR_TCL(hr, pInterp, false); + } + else + ptmpunk->AddRef(); // if not IDispatch, make sure we incr the refcount + var.punkVal = ptmpunk; + } + else { + ObjectNotFound (pInterp, obj); + bOk = false; + } + } + break; + default: + obj2var (obj, var); + if (vt != VT_VARIANT) { + HRESULT hr = VariantChangeType (&var, &var, NULL, vt); + if (FAILED (hr)) { + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + bOk = false; + } + } + break; + } + return bOk; +} + + + +/* + *------------------------------------------------------------------------- + * ObjectNotFound -- + * Standard error message when an optcl object is not found. + * Result: + * TCL_ERROR always. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +int ObjectNotFound (Tcl_Interp *pInterp, const char *name) +{ + Tcl_SetResult (pInterp, "could not find object '", TCL_STATIC); + Tcl_AppendResult (pInterp, (char*)name, "'", NULL); + return TCL_ERROR; +} + + + +/* + *------------------------------------------------------------------------- + * SplitTypedString -- + * If pstr is of the format "a.b.c" then it is modified such that + * pstr == "a.b" and *ppsecond = "c" + * Otherwise, pstr will point to the original string and *ppsecond will + * be NULL. + * Result: + * None. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +void SplitTypedString (char *pstr, char ** ppsecond) +{ + const char * token = "."; + ASSERT (pstr != NULL && ppsecond != NULL); + + char *p = pstr; + while (*p != '.' && *p != '\0') p++; + if (*p == '\0') { + *ppsecond = NULL; + return; + } + + pstr = strtok (pstr, token); + pstr[strlen(pstr)] = '.'; + + for (short i = 0; i < 2; i++) + { + *ppsecond = strtok (NULL, token); + if (*ppsecond == NULL) + break; + } +} + + + +/* + *------------------------------------------------------------------------- + * SplitObject -- + * Splits a string held within a Tcl object (pObj) into its constituent + * objects (ppResult), using a collection tokens. + * + * Result: + * true iff successful. Else, error string in interpreter. + * Side effects: + * None. + *------------------------------------------------------------------------- + */ +bool SplitObject (Tcl_Interp *pInterp, Tcl_Obj *pObj, + const char * tokens, Tcl_Obj **ppResult) +{ + ASSERT (pInterp != NULL && pObj != NULL && tokens != NULL && ppResult != NULL); + TObjPtr cmd; + cmd.create(); + cmd = "split"; + cmd.lappend (pObj); + cmd.lappend(tokens); + if (Tcl_EvalObj (pInterp, cmd) == TCL_ERROR) + return false; + *ppResult = Tcl_GetObjResult (pInterp); + Tcl_IncrRefCount (*ppResult); + return true; +} + + +bool SplitBrackets (Tcl_Interp *pInterp, Tcl_Obj *pObj, + TObjPtr & result) +{ + ASSERT (pInterp != NULL && pObj != NULL); + TObjPtr pcmd ("regexp -nocase {^([^\\(\\)])+(\\([^\\(\\)]+\\))?$} "); + pcmd.lappend(pObj); + + if (Tcl_EvalObj (pInterp, pcmd) == TCL_ERROR) + return false; + + CONST84 char * okstr = Tcl_GetStringResult (pInterp); + if (okstr[0] == '0') { + Tcl_SetResult (pInterp, "property format is incorrect: ", TCL_STATIC); + Tcl_AppendResult (pInterp, Tcl_GetStringFromObj(pObj, NULL), NULL); + return false; + } + + pcmd = "split"; + pcmd.lappend (pObj).lappend("(),"); + if (Tcl_EvalObj (pInterp, pcmd) == TCL_ERROR) + return false; + result.copy(Tcl_GetObjResult (pInterp)); + + // the last element will be a null string + char *str = Tcl_GetStringFromObj (pObj, NULL); + if (str[strlen (str) - 1] == ')') + Tcl_ListObjReplace (NULL, result, result.llength() - 1, 1, 0, NULL); + return true; +} + +/// Tests +TCL_CMDEF (Obj2VarTest) +{ + if (objc < 2) { + Tcl_WrongNumArgs(pInterp, 1, objv, "value"); + return TCL_ERROR; + } + + VARIANT var; + VARIANT * pvar; + HRESULT hr; + + pvar = (VARIANT*)CoTaskMemAlloc(sizeof(VARIANT)); + + VariantInit(pvar); + var.vt = VT_VARIANT; + var.pvarVal = pvar; + + TObjPtr ptr(objv[1], false); + + obj2var (ptr, *pvar); + CoTaskMemFree((LPVOID)pvar); + hr = VariantClear(&var); + Tcl_SetResult (pInterp, HRESULT2Str(hr), TCL_DYNAMIC); + return FAILED(hr)?TCL_ERROR:TCL_OK; +} + + diff --git a/src/utility.h b/src/utility.h new file mode 100644 index 0000000..510c692 --- /dev/null +++ b/src/utility.h @@ -0,0 +1,112 @@ +/* + *------------------------------------------------------------------------------ + * utility.cpp + * Declares a collection of often used, general purpose functions. + * I've also placed the variant/Tcl_Obj conversion functions here. + * + * Copyright (C) 1999 Farzad Pezeshkpour, University of East Anglia + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *------------------------------------------------------------------------------ + */ +#ifndef UTILITY_418A3400_56FC_11d3_86E8_0000B482A708 +#define UTILITY_418A3400_56FC_11d3_86E8_0000B482A708 + + +#ifndef ASSERT +# ifdef _DEBUG +# include +# define ASSERT(x) _ASSERTE(x) +# else +# define ASSERT(x) +# endif +#endif + + + +// TRACE functionality - works like printf, only in debug mode +// - output to the debug console +#ifdef _DEBUG +# define TRACE OptclTrace +void OptclTrace(LPCTSTR lpszFormat, ...); +#else +# define TRACE +#endif + +#define TCL_CMDEF(fname) int fname (ClientData cd, Tcl_Interp *pInterp, int objc, Tcl_Obj *CONST objv[]) +#define CHECKHR(hr) if (FAILED(hr)) throw(hr) +#define CHECKHR_TCL(hr, i, v) if (FAILED(hr)) {Tcl_SetResult (i, HRESULT2Str(hr), TCL_DYNAMIC); return v;} + +#define SETDISPPARAMS(dp, numArgs, pvArgs, numNamed, pNamed) \ + {\ + (dp).cArgs=numArgs;\ + (dp).rgvarg=pvArgs;\ + (dp).cNamedArgs=numNamed;\ + (dp).rgdispidNamedArgs=pNamed;\ + } + +#define SETNOPARAMS(dp) SETDISPPARAMS(dp, 0, NULL, 0, NULL) + +#define _countof(x) (sizeof(x)/sizeof(x[0])) + + +template void delete_ptr (T* &ptr) +{ + if (ptr != NULL) { + delete ptr; + ptr = NULL; + } +} + + +template T* delete_array (T *&ptr) { + if (ptr != NULL) { + delete []ptr; + ptr = NULL; + } + return ptr; +} + + + +class OptclObj; + +bool var2obj (Tcl_Interp *pInterp, VARIANT &var, TObjPtr &presult, OptclObj **ppObj = NULL); +bool obj2var_ti (Tcl_Interp *pInterp, TObjPtr &obj, VARIANT &var, ITypeInfo *pInfo, TYPEDESC *pdesc); +bool obj2var_vt (Tcl_Interp *pInterp, TObjPtr &obj, VARIANT &var, VARTYPE vt); +bool obj2var_vt_byref (Tcl_Interp *pInterp, TObjPtr &obj, VARIANT &var, VARTYPE vt); +void obj2var (TObjPtr &obj, VARIANT &var); + + +void OptclVariantClear (VARIANT *pvar); + + +char * HRESULT2Str (HRESULT hr); +void FreeBSTR (BSTR &bstr); +void FreeBSTRArray (BSTR * bstr, UINT count); +char * ExceptInfo2Str (EXCEPINFO *pe); +DISPID Name2ID (IDispatch *, const LPOLESTR name); +DISPID Name2ID (IDispatch *, const char *name); +int ObjectNotFound (Tcl_Interp *pInterp, const char *name); +void SplitTypedString (char *pstr, char ** ppsecond); +bool SplitObject (Tcl_Interp *pInterp, Tcl_Obj *pObj, + const char * tokens, Tcl_Obj **ppResult); +bool SplitBrackets (Tcl_Interp *pInterp, Tcl_Obj *pObj, + TObjPtr & result); + +/// TESTS +TCL_CMDEF (Obj2VarTest); + +#endif // UTILITY_418A3400_56FC_11d3_86E8_0000B482A708 \ No newline at end of file diff --git a/tests/calendar.tcl b/tests/calendar.tcl new file mode 100644 index 0000000..2ee371b --- /dev/null +++ b/tests/calendar.tcl @@ -0,0 +1,54 @@ +##################################################### +# This file demonstrates the Calendar control being +# integrated within a Tk widget, and bound to a +# an event handler +##################################################### + + +# in case we want to do some debugging +bind . {console show} + + +# optcl load happens here +package require optcl + + +## +# called when an AfterUpdate event is raised. +# the first parameter is the object that raised +# the event +proc onupdate {obj} { + global currentdate + set currentdate [$obj : value] +} + + + +# main script------ + + +# create a status bar to show the current date +label .cd -bd 1 -relief sunken -textvariable currentdate +pack .cd -side bottom -fill x + +# create the calendar object +set cal [optcl::new -window .cal MSCAL.Calendar] +.cal config -width 300 -height 300 +pack .cal + +# bind to the calendar AfterUpdate event +# routing it to the tcl procedure onupdate +# +optcl::bind $cal AfterUpdate onupdate + + +# get the current value +set currentdate [$cal : value] + + +# make a button to view the type information of +# the calendar +button .b -text TypeInfo -command {tlview::viewtype [optcl::class $cal]} +pack .b -side bottom -anchor se + + diff --git a/tests/pdf.tcl b/tests/pdf.tcl new file mode 100644 index 0000000..9304dca --- /dev/null +++ b/tests/pdf.tcl @@ -0,0 +1,18 @@ + + +package require optcl +bind . {console show} + +wm title . {PDF Document in Tk} +set pdf [optcl::new -window .pdf {d:/program files/adobe/acrobat3/acrobat.pdf}] +.pdf config -width 500 -height 300 +pack .pdf -fill both -expand 1 + +# to view the type information for the control +pack [button .b -text "View TypeLibrary for IE container" -command { + tlview::viewtype [ optcl::class $pdf ] + } ] -side bottom + +# can't execute these until the document has loaded... +#set doc [$pdf : document] +#tlview::viewtype [ optcl::class $doc ] diff --git a/tests/word.tcl b/tests/word.tcl new file mode 100644 index 0000000..5f06fdb --- /dev/null +++ b/tests/word.tcl @@ -0,0 +1,45 @@ +################################################################ +# This file demonstrates the automation MS Word +################################################################ + + +# for debuggin +bind . {console show} + +#load optcl +package require optcl + + + +# with this procedure, closing the document closes wish +proc onclose {obj} { + # if the document is closing then exit + # but we can't call exit here as we are processing an event + # so set up a timer on this + after 500 {exit} +} + +set word [optcl::new word.application] +$word : visible 1 + +# create a new doc +set doc [$word -with documents add] + +# bind to its close event of the document +optcl::bind $doc Close onclose + + +# gui + +button .st -text "Set Text" -command {$doc -with content : text [.f.t get 1.0 end]; $doc : saved 1} +pack .st + +frame .f -bd 1 -relief sunken +pack .f -side top -fill both -expand 1 +scrollbar .f.ys -orient vertical -command {.f.t yview} +pack .f.ys -side right -fill y +text .f.t -yscrollcommand {.f.ys set} -bd 0 -relief flat +pack .f.t -fill both -expand 1 + +.f.t insert end "Please type your text here and press 'Set Text'" + -- 2.23.0