- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
189 lines
7.6 KiB
Plaintext
189 lines
7.6 KiB
Plaintext
AUTOMATING COLLECTIONS
|
|
|
|
Frequently an application organizes data and objects in
|
|
collections of various types, such as arrays, containers,
|
|
or linked lists, or it utilizes such capabilites inherent in
|
|
the operating platform. Collections generally expose an
|
|
iterator, a counter, a random-access function, and
|
|
optionally methods for managing the collection. Exposing
|
|
collections for automation generally involves three steps:
|
|
|
|
1. The collection is exposed as a property which returns
|
|
an object.
|
|
|
|
2. A C++ class is created, or enhanced, to support the
|
|
collection methods.
|
|
|
|
3. An iterator is defined to provide code to iterate
|
|
through the collection.
|
|
|
|
|
|
The iterator is internally exposed to the script controller
|
|
as a property having the reserved name "_NewEnum" which
|
|
returns an object supporting the IENUMVariant interface.
|
|
This interface contains methods to perform iteration. With
|
|
VisualBasic for Applications, the following syntax is used
|
|
for iteration:
|
|
|
|
For Each Thing In Owner.Bunch ("Thing" is an arbitrary
|
|
iterator name)
|
|
Thing.Member...... (can access methods and
|
|
properties)
|
|
Next Thing (loops through all items
|
|
in collection)
|
|
|
|
Note that the server can return any data type for items,
|
|
values or objects.
|
|
|
|
|
|
CREATING C++ CLASSES SPECIFICALLY FOR AUTOMATION
|
|
|
|
Frequently C++ classes do not already exist to encapsulate
|
|
items to be exposed for automation, such as collections,
|
|
simple structures, and system objects represented by
|
|
handles. The only C++ methods required are a constructor
|
|
and support methods for the exposed automation. Instances
|
|
of these classes are exposed as properties of their parent
|
|
classes and are constructed as the properties are retrieved
|
|
(as opposed to returning references to existing C++
|
|
instances). The constructor must accept a single argument
|
|
from the parent class: member data, result of an accessor
|
|
function, or the object's this pointer. The parent class
|
|
must supply an AUTOxxx macro that supplies this constructor
|
|
argument as a data member or function, and declares its
|
|
type with the templatized pointer class
|
|
TAutoObjectByVal<T>, where T is the new automated C++
|
|
class. TAutoObjectByVal<T> causes an instance of T to be
|
|
constructed that persists until all external references to
|
|
that instance are released (when the exposed object goes
|
|
out of scope in the automation controller). Examples of
|
|
the macros used within the DECLARE_AUTOCLASS and
|
|
DEFINE_AUTOCLASS sections are given below:
|
|
|
|
AUTODATARO(Documents, DocList, TAutoObjectByVal<TDocumentList>,)
|
|
// DocList is a TDocument*, head of a linked list of.
|
|
// type TDocument. TDocumentList is a new class, constructor:
|
|
// TDocumentList(TDocument*)
|
|
EXPOSE_PROPRO(Documents, TDocumentList, "Documents", "Doc Collection", 270)
|
|
|
|
AUTOTHIS(Views, TAutoObjectByVal<TViewList>,)
|
|
// TViewList is a new class, constructor: TView(TDocument* owner)
|
|
// In this case the parent's this pointer is passed to the constuctor
|
|
EXPOSE_PROPRO(Views, TViewList, "Views", "View Collection", 240)
|
|
|
|
AUTOFUNC0(Buttons, GetWindow(), TAutoObjectByVal<TCalcButtons>, )
|
|
// GetWindow() gets the window handle of the parent window of
|
|
// the buttons. TCalcButtons is a new class, constructor:
|
|
// TCalcButtons(HWND parent)
|
|
EXPOSE_PROPRO(Buttons, TCalcButtons, "Buttons", Button Collection", 170)
|
|
|
|
AUTODATARO(MyArray, Elem, TAutoObjectByVal<TMyArray>,)
|
|
// Elem is an array of shorts, defined as short Elem[COUNT]
|
|
// TMyArray is a new class, constructor: TMyArray(short* array)
|
|
EXPOSE_PROPRO(MyArray, TMyArray, "Array", "Array as collection", 110)
|
|
|
|
|
|
COLLECTION CLASSES
|
|
|
|
A C++ class must be defined to host the automation
|
|
declarations along with the supporting C++ methods. For
|
|
some collections, a C++ class might already exist. Otherwise
|
|
one must be defined to represent a collection object.
|
|
|
|
|
|
EXPOSING COLLECTION OBJECTS
|
|
|
|
EXPOSING ITERATORS
|
|
|
|
Iterators are defined for automation using the AUTOITERATOR
|
|
macro, which defines the iteration algorithm for the
|
|
enclosing collection class. No internal name is supplied,
|
|
as only one iterator may exist within a class. The macro
|
|
has five arguments, each representing a code fragment,
|
|
ordered as in a "for" loop.
|
|
|
|
1. Declaration of state variables, e.g. int Index
|
|
2. Loop initializer assigments, e.g. Index = 0
|
|
3. Loop entry test boolean expression, e.g. Index < This->Total
|
|
4. Loop iteration statements, e.g. Index++
|
|
5. Current element access expression, e.g. (This->Array)[Index]
|
|
|
|
Commas cannot be used unless inside parentheses. Semicolons
|
|
can be used to separate multiple statements, but cannot
|
|
be used to end a macro argument. In common with automated
|
|
methods, "This" is defined to be the "this" pointer of the
|
|
enclosing C++ class, in this case the collection itself.
|
|
|
|
The AUTOITERATOR macro generates a nested class definition.
|
|
For complex iterators, this class can be specified directly
|
|
in C++ as shown below:
|
|
|
|
class TIterator : public TAutoIterator {
|
|
public:
|
|
ThisClass* This;
|
|
/* declare state variables here as members */
|
|
void Init() {/* loop initialization function body */}
|
|
bool Test() {/* loop entry test function body */}
|
|
void Step() {/* loop iteration function body;}
|
|
void Return(TAutoVal& v) {/* current element return: v = expr */}
|
|
TIterator* Copy() {return new TIterator(*this);}
|
|
TIterator(ThisClass* obj, TServedObject& owner)
|
|
: This(obj), TAutoIterator(owner) {}
|
|
static TAutoIterator* Build(ObjectPtr obj, TServedObject& owner)
|
|
{ return new TIterator((ThisClass*)obj, owner); }
|
|
}; friend class TIterator;
|
|
|
|
Iterators are exposed as properties using the
|
|
EXPOSE_ITERATOR macro. Note that no internal or external
|
|
names are supplied (the external name is internally
|
|
hard-wired as "_NewEnum"). The automation type describes the
|
|
type of the items returned from the iterator, in the same
|
|
manner as a function return.
|
|
|
|
AUTOITERATOR(int Index, Index=0, Index<COUNT, Index++,
|
|
(This->Array)[Index])
|
|
// Array is a member array of shorts for which an iterator
|
|
// is defined. It will exposed as a "_NewEnum" property which
|
|
// returns an OLE enumerator.
|
|
EXPOSE_ITERATOR(TAutoShort, "Array Iterator", HC_ARRAY_ITERATOR)
|
|
|
|
In addition to exposing an iterator, a collection class by
|
|
convention exposes a "Count" method to return the number of
|
|
items in the collections, an "Index" method to randomly
|
|
access an element of the collection, and optionally,
|
|
methods to externally manage the collection, such as add and
|
|
delete.
|
|
|
|
____________________________________________________________
|
|
|
|
|
|
----example code from AutoCalc------
|
|
|
|
class TCalcButtons {
|
|
public:
|
|
TCalcButtons(HWND window) : HWnd(window) {}
|
|
short GetCount() { return IDC_LASTID - IDC_FIRSTID; }
|
|
HWND HWnd;
|
|
|
|
DECLARE_AUTOCLASS(TCalcButtons)
|
|
AUTOFUNC0 (Count, GetCount, short,)
|
|
AUTOITERATOR(int Id, Id = IDC_FIRSTID+1,
|
|
Id <= IDC_LASTID, Id++,
|
|
TAutoObjectByVal<TCalcButton>(::GetDlgItem(This->HWnd,Id)))
|
|
};
|
|
|
|
DEFINE_AUTOCLASS(TCalcButtons)
|
|
|
|
EXPOSE_PROPRO(Count, TAutoLong, "!Count","Button Count",
|
|
HC_TCALCBUTTONS_COUNT)
|
|
EXPOSE_ITERATOR(TCalcButton, "Button Iterator",
|
|
HC_TCALCBUTTONS_ITERATOR)
|
|
EXPOSE_METHOD_ID(0, Item, TCalcButton,"!Item",
|
|
"Button Collection Item", 0)
|
|
REQUIRED_ARG(TAutoShort, "!Index")
|
|
|
|
END_AUTOCLASS(TCalcButtons, "ButtonCollection",
|
|
"Button Collection", HC_TCALCBUTTONS)
|
|
|
|
|