Windoid XCMD
Volume Number: 6
Issue Number: 12
Column Tag: XCMD Corner
Windoids and HyperCard 2.0 
By Donald Koscheka, MacTutor Contributing Editor
If you’ve been writing XCMDs for some time now, you might be a little concerned
over how much work is involved in porting your xcmds to Hypercard 2.0. For the
most part, this is a trivial process and you need not modify any of your code to support
Hypercard 2.0. You will need to recompile with the new xcmd libraries though as the
callback engine has been completely re-written to allow for a larger number of
callbacks (some 75 as opposed to the 30 or so in HC1.0; the number is a little vague
because I found a few callbacks in the library that are not documented anywhere).
For those of you using Think “C”, you will need to convert the XCMD library,
“HyperXLib.o” to a Think “C” library. I got this file in MPW format and ran the
“oConv” utility on it to convert it to something that Think can use. I then built a
library from this. There is one small catch, the Library entry points are all
uppercase. You will need to modify your calls to uppercase. For example, PasToZero
becomes PASTOZERO. Of course, you might just wait until someone comes along with a
more convenient library than the one that is currently distributed.
As I said, your xcmd should work “for the most part”. Certain xcmds will not
work very well under Hypercard 2.0 or they will work but their behaviour will be
such that you won’t recognize them (kind of like my 2 year old when she skips her
nap).
The reason for this is that Hypercard 2.0 implements a completely new external
window schema which offers a tremendous benefit to the xcmd writer but which also
requires that you rethink your windowing strategy. The benefit of making your xcmds
HC2.0 “windoid” friendly is tremendous -- windoids that function in the HC windoid
layer will be able to communicate directly with Hypercard and use the Hypercard
callbacks. In effect, you get a multiple-window Hypercard stack.
Windoids don’t come for free in Hypercard 2.0 and that’s good. In effect, Apple is
leaving it up to each developer to decide what to do with external windows. The only
rules that you must obey are those that will allow your windows to function within the
external windows layer. This way, your windows will work correctly with other
xcmds that also create external windows. Hypercard keeps track of which windows are
owned by which xcmds, and it passes window events to each external windoid
appropriately.
Windoids.c
Listing 1, “Windoids.c” is an external window xcmd skeleton. It incorporates
two new functions of HC 2.0 xcmds: (1) it handles the “?” and “!” queries from the
user and (2) it responds to windoid events. The former was covered last month is
quite straightforward. We will look at the windoid events in greater detail in this and
future columns.
Take a look at the entry point in Listing 1. Note that the first thing we do is check
the number of parameters being passed to us by Hypercard. If the parameter count is
less than zero (specifically, -1), then we are being passed an external windoid event
for a window that we created earlier. If there is only one parameter and it’s “?” or
“!” then return the appropriate information about the xcmd back to the caller. In the
case of the “?”, you should return usage information. In the case of the “!” you should
return a note about who created the xcmd and what it does. This is also a good place to
put your copyright notice.
If the parameter count is greater than or equal to zero, then you treat the
parameters as ordinary xcmd parameters. However, if the parameter count is less
than zero, then you decode the parameter block in an entirely different manner. In
this case, the first parameter, params[0] (“C”) or params[1] (Pascal), contains a
POINTER to an xcmd event record. This record contains the following fields:
/* 1 */
struct XWEventInfo {
EventRecord event;
WindowPtr eventWindow;
long eventParams[9];
Handle eventResult;
}XWEventInfo, *XWEventInfoPtr;
The eventrecord is identical to the event manager event record. The windowPtr is
a pointer to the windoid that should get this event. The event parameters and event
result have other meanings that we will no doubt explore in the future but which are
not required for the code in Listing 1.
In the listing, we call HandleHCEvent with the xcmd parameter block if
paramcount is less than zero, otherwise we move to HandleHCmessage which should
treat the parameter block like an ordinary xcmd activation. After a little thought this
mechanism begs a question -- if we are responding to events in HandleHCEvent, why do
we pass the entire parameter block rather than just the xwindow event record? This
question gives rise to yet another question -- if that’s the case, why isn’t the
parameter block just declared thusly: