home *** CD-ROM | disk | FTP | other *** search
-
- **************************************************************************
- *
- * GEMXTEND.DOC - Descriptions of extensions made to GEM bindings since
- * the original TOS 1.0 release.
- *
- * 09/02/91 - v1.7
- * Added new function vgd_detect() to detect GDOS.
- *
- * 07/18/91 - v1.6 (Has it really been a year since the last release?)
- * Added new VDI function vdicall(), which allows you to
- * "roll your own" binding to a VDI function that's not
- * directly supported in vdifast.a. This ought to please
- * all the GDOS-using folks. This is documented at the
- * very end of this doc file.
- *
- * 06/29/90 - v1.5
- * Added function v_gchar() to output a single text char.
- *
- * 05/26/90 - v1.4
- * Included documentation on the new calling standard,
- * and the bindings that currently support it:
- * evnx_multi()
- * frmx_center()
- * winx_get()
- * winx_calc()
- *
- * 09/06/89 - v1.3
- * This document is new with this release, and contains
- * revisions through TOS 1.4.
- **************************************************************************
-
- This document is divided into two sections. Section 1 documents the
- changes and additions Atari has made to the GEM routines in TOS. Section 2
- documents alternate calling standards to the existing functions. These
- alternate bindings provide more efficient ways to call AES functions.
-
-
- **************************************************************************
- *
- * Section 1 - Changes Atari has made to GEM/TOS.
- *
- **************************************************************************
-
- This section describes extensions Atari has made to TOS/GEM since the
- original TOS 1.0 operating system. When Atari adds new VDI/AES functions,
- appropriate bindings will be created and documented here. Note that some
- of the functions listed here have been available since TOS 1.0, but Atari
- neglected to document them. The title bar for each function lists the
- first TOS version that supported the function. Other functions have
- backwards compatibility built into the GEMFAST binding so that they will
- work correctly on all TOS versions (these are noted in the title bars too).
-
- *--------------------------------------------------------------------------
- * About TOS 1.4...
- *--------------------------------------------------------------------------
-
- The TOS 1.4 pre-release notes contain documentation for the following:
-
- form_error form_alert shel_write shel_get shel_put
- fsel_exinput wind_new
-
- Of these, the form_error/alert and shel_???? docs seem to be just a
- clarification of the docs without any functional changes.
-
- The wind_new and fsel_exinput functions are new with TOS 1.4.
-
- ;-------------------------------------------------------------------------
- ; wind_new TOS 1.4
- ;-------------------------------------------------------------------------
-
- void wind_new();
-
- The 'wind_new' function is for doing a major cleanup after a GEM
- application. It closes & deletes all windows, flushes all the windows'
- buffers (of redraw msgs, I presume), clears the wind_update flag, and
- restores ownership of the mouse to the system (END_MCTRL I presume). The
- documentation is not clear on whether this function should be used by
- an application that wants to shut down everything quickly, or whether it
- is intended for a shell's use in cleaning up after an application exits.
- I tend to suspect the latter, and I think this function was developed
- because shell writers all begged Atari to provide something that could
- clean up after an application the way the desktop does.
-
- ;-------------------------------------------------------------------------
- ; fsel_exinput TOS 1.4 (binding compatible with 1.0 and up)
- ;-------------------------------------------------------------------------
-
- Full 1.4 emulation...
-
- status = fsel_exinput(in_path, in_sel, &exitbtn, prompt_text);
-
- (status and exitbtn are 16-bit ints, others are char *).
-
- This routine is functionally equivelent to fsel_input, except that it
- also allows you to specify a prompt string of up to 30 characters to be
- displayed along with the file selector. While the function is new with
- TOS 1.4, the AESFAST bindings support it in all versions via a routine
- which checks the AES version number and simulates the actions of
- fsel_exinput by using fsel_input and objc_draw. If running under
- TOS 1.4, the system will display your prompt text in place of the words
- 'FILE SELECTOR' inside the fsel box. If running under pre-TOS 1.4, the
- simulation routines place the prompt text in a box which appears
- between the menu bar and the fsel box.
-
- Other TOS 1.4 changes to the fsel routines that this routine supports
- via simulation when running on pre-TOS 1.4 systems...
-
- - The file selector now allows you to edit the pathname and hit RETURN
- without exiting the dialog. If you edit the filename and hit <CR>,
- you will exit as if you clicked on OK.
- - If the initial pathname has a leading '\', it will be appended to the
- end of the current default drive and path, and the entire resulting
- string will be returned if the user exits via OK or <CR>.
- - The current default drive and path are preserved, and the contents
- of the current DTA are preserved. Only the default path on the
- default drive is saved with the simulation software. If the user
- changes devices during file selection, the default path on all devices
- may be changed except for the device that was the default when
- fsel_exinput was called.
-
- The executable code for the fsel_exinput binding is big -- about 800
- bytes. Also, it uses about 350 bytes of stack space during the call.
- Still, having a prompted file selector that works correctly on all
- machines will lend a touch of class to your application (IMHO).
-
- Note that all of the above fsel ehancements which are supported by the
- simulation on pre-TOS 1.4 systems are supported ONLY if you call
- fsel_exinput; if you call fsel_input on a pre-1.4 system the default
- path et. al. will behave as they always have. (Hint: USE exinput).
-
- ;-------------------------------------------------------------------------
- ; fsel_smallexinput TOS 1.4 (binding compatible with 1.0 and up)
- ;-------------------------------------------------------------------------
-
- Prompting emulation only...
-
- This function has calling parameters identical to fsel_exinput() (see
- above), but it's behavior (return values, etc) is identical to that of
- fsel_input() (the original). This function will call the real 'exinput'
- routine if on TOS 1.4, but if on an earlier version it emulates only the
- prompting of 'exinput', it does not save the path or DTA, or handle <CR>
- correctly, or any of the other nice TOS 1.4 features. On the other hand,
- it's only half as big as the full emulator for fsel_exinput(), so it's
- handy for accessories and other small-memory applications. (It will add
- about 450 bytes to your program, as opposed to 800).
-
- I'd like to recommend that you do not code calls to fsel_smallexinput()
- directly in your program. Instead, just code fsel_exinput(), and at the
- top of your C source, code:
-
- #define fsel_exinput fsel_smallexinput
-
- and let the C compiler handle the rest for you. This ought to keep your
- code compatible many years into the future...
-
- ;-------------------------------------------------------------------------
- ; fsel_14input TOS 1.4 (binding compatible with 1.0 and up)
- ;-------------------------------------------------------------------------
-
- No emulation.
-
- This function has calling parameters identical to fsel_exinput() (see
- above). However, it makes no attempt to emulate any of the 1.4 exinput
- features. Basically, if running on TOS 1.4, fsel_exinput is called. If
- running on a pre-1.4 system, the prompt string is thrown away, and the
- normal file selector is called. This binding is very small compared to
- other (emulation mode) exinput bindings.
-
- Again, it is best to access this function through a #define statement:
-
- #define fsel_exinput fsel_14input
-
- | This function was added with v1.4.
-
- ;-------------------------------------------------------------------------
- ; shel_get / shel_put TOS 1.0
- ;-------------------------------------------------------------------------
-
- status = shel_get(char *bufadr, int buflen)
- status = shel_put(char *bufadr, int buflen)
-
- These functions read and write the desktop's internal buffer
- which holds a copy of the DESKTOP.INF file. The buffer holds
- an exact image of the file, in plain ASCII text. If 'status'
- is returned as zero, an error occurred. The Atari docs say that
- the buffer should never exceed 1024 bytes, but I've been told
- that it *can* in fact exceed this length.
-
- ;-------------------------------------------------------------------------
- ; form_keybd TOS 1.0
- ;-------------------------------------------------------------------------
-
- keyret = form_keybd(tree, object, nxtobject, thechar, &nxtobject, &thechar);
-
- (All values are 16-bit words, except 'tree', which is OBJECT *).
-
- The form_keybd routine acts as a filter on character input.
- When it recognizes a control character, it processes
- it and zeroes the keyboard word. Other chararacters can be
- passed on to objc_edit to be inserted in the editable object.
- If the routine returns a zero, a default object is selected (<CR>).
- (Hints: If 'nxtobject' is not equal to 'object' after this call,
- form_keybd() has detected a TAB or ARROW key to move to the next
- edit field, so call objc_edit(..., EDEND) for the current field,
- as long as nxtobject is non-zero. If 'thechar' comes back non-zero,
- pass it to objc_edit(..., EDCHAR). If this doesn't make sense, get
- the Tim Oren articles and make your own interpretations.)
-
- ;-------------------------------------------------------------------------
- ; form_button TOS 1.0
- ;-------------------------------------------------------------------------
-
- btnret = form_button(tree, object, clicks, &nxtobject);
-
- (All values are 16-bit words, except 'tree', which is OBJECT *).
-
- I can't tell you as much about this one. This routine handles an
- already-occurred mouse button event. It handles changing the
- selected object into reverse video. It (presumably) handles radio
- buttons. 'object' is the index of the object the mouse is over, so
- I presume have have to call objc_find() first to get this. 'nxtobject'
- is the new selected object index. If the routine returns a zero,
- a default or exit object was selected.
-
-
- **************************************************************************
- *
- * Section 2 - An alternate calling standard, and supporting bindings...
- *
- **************************************************************************
-
- BACKGROUND
-
- The calling standard for AES functions defined and documented by DRI was
- defined for ease of use in C programming, but it does not lend itself to
- particularly efficient code generation. For example, the wind_get() call
- can be used to return many different types of values, so DRI defined the
- function as taking pointers to 4 separate output fields. However, one of
- most common functions for wind_get() is to return information about window
- rectangles; the values are returned in typical GRECT order.
-
- In the old days, a call of this type was often coded as:
-
- wind_get(wi_handle, WF_CURRXYWH, &x, &y, &w, &h);
-
- As GEM coding techniques have become more sophisticated, people have found
- that it makes more sense to keep xywh values in GRECT structures instead of
- in discrete variables. This leads to the rather cumbersome construct:
-
- wind_get(wi_handle, WF_CURRXYWH,
- &windrect.g_x, &windrect.g_y,
- &windrect.g_w, &windrect.g_h);
-
- When ideally, one would prefer to code:
-
- wind_get(wi_handle, WF_CURRXYWH, &windrect);
-
- This makes a huge difference in runtime performance. When the binding for
- the original wind_get() routine is called, it has no idea whether discrete
- (possibly discontiguous) addresses are passed, so it must build a temporary
- output array on the stack in which the AES can pass return values. Upon
- return from the AES, the binding must copy each of the four return values
- back to the caller's memory, using the 4 individual pointers specified.
- Using the alternate calling standard, the binding can simply pass the AES
- the GRECT pointer specified in the call, and the AES can place the returned
- values directly into the caller's memory, avoiding intermediate arrays.
- Also, the C compiler only has to stack one address when setting up the call.
-
- STANDARDS
-
- Because it is not possible to have one function name to handle both types
- of calling standards, I have choosen to implement the alternate bindings
- using similar names, with an 'x' to indicate it is one of the extended
- bindings. Thus, wind_get() would be called when discrete addresses are
- passed, and winx_get() would be called when a single pointer is passed.
-
- There will be a certain amount of schizophrenia in the alternate binding
- standards. Some functions (such as evnx_multi) will take all input and
- output values in a single consolidated structure. Others will pass
- discrete input values, but take the return values in a structure, or
- vice versa. I will try to use common sense when making such decisions;
- what I want to avoid is the VDI mess. With VDI calls, you have to load
- *everything* into an array, even when it doesn't seem to make sense to
- do so. I think VDI coding is very tedious for this reason, and I'm going
- to try to avoid that with the alternate AES bindings.
-
- As an aside: I've heard rumours that Tim Oren defined an entire alternate
- calling structure for the AES under the name GEMX. Unfortunately, I can't
- find out anything about it except that it 'may exist'. Therefore, nothing
- in my alternate calling standards are going to correspond to his, except
- by accident. If anybody has more info on GEMX, I'd love to learn about it.
-
- IMPLEMENTATION
-
- I had planned to write the entire set of alternate bindings and release
- them as GemFast v2.0. I've been planning that for months, and it isn't
- working out. Therefore, beginning with v1.4, I'm releasing things as I
- go. As of 1.4, there are only a couple of these extended bindings
- available.
-
- The C-source version of the AESFAST utilities (GEMFUTxx.ARC) contains
- versions of the extended AES routines (evnx_multi, et. al.), to provide
- code compatibility. The C versions of these functions do not provide the
- speed of the assemblerized versions in AESFAST.A, but they also do not add
- more than a few bytes to the size of your program.
-
- X-STRUCTURES
-
- Where custom data structures are needed by an alternate binding, the
- structures will be documented with the binding(s) that use them. All such
- structures are defined in the GEMFAST.H header file.
-
- ;-------------------------------------------------------------------------
- ; evnx_multi - Alternate for evnt_multi.
- ;-------------------------------------------------------------------------
-
- int evnx_multi(XMULTI *xm);
-
- This binding takes a single parm, a pointer to an XMULTI structure. It
- returns an integer, which is a bit mask of events which occurred (the
- same value returned by evnt_multi). This mask is also returned in
- the mwhich element of the XMULTI structure.
-
- All of the values normally passed to evnt_multi are included in the
- XMULTI structure. All of the output values are returned in the XMULTI
- structure, including messages in the message buffer, which is the 1st
- eight words of the XMULTI structure.
-
- The XMULTI structure is defined as follows:
-
- typedef struct xmulti {
- int msgbuf[8]; /* Message buffer */
- int mflags; /* Mask of events to wait for */
- int mbclicks, /* Button clicks to wait for */
- mbmask, /* Which buttons to wait for */
- mbstate; /* Button state to wait for */
- int mm1flags; /* M1 rect: wait for in/out flag*/
- GRECT mm1rect; /* M1 rect: xywh coordinates */
- int mm2flags; /* M2 rect: wait for in/out flag*/
- GRECT mm2rect; /* M2 rect: xywh coordinates */
- int mtlocount, /* Timer count low value */
- mthicount; /* Timer count high value */
- int mwhich, /* Mask of events that occurred */
- mmox, /* Mouse x at time of event */
- mmoy, /* Mouse y at time of event */
- mmobutton, /* Mouse buttons at event */
- mmokstate, /* Keystate at event */
- mkreturn, /* Key pressed at event */
- mbreturn; /* Times buttons was clicked */
- } XMULTI;
-
- It is most efficient to code the XMULTI structure as a local variable
- of the function that uses it, although it can be defined as a global
- or static variable. A simple, typical multi-handler might look like:
-
- multi()
- {
- XMULTI xm;
- int events
-
- /*
- * set up static portions of xm structure...
- */
-
- xm.mflags = MU_TIMER | MU_MESAG | MU_BUTTON;
-
- xm.tlocount = 1000; /* 1 second */
- xm.thicount = 0; /* timer value */
-
- xm.mbclicks = 1; /* wait for single */
- xm.mbmask = 1; /* click of left */
- xm.mbstate = 1; /* button */
-
- while (1) {
-
- events = evnx_multi(&xm);
-
- if (events & MU_BUTTON) {
- handle_button(xm.mox, xm.moy);
- }
-
- if (events & MU_TIMER) {
- handle_timeout();
- }
-
- if (events & MU_MESAG) {
- switch(xm.msgbuf[0]) {
- case WM_REDRAW:
- do_redraw(xm.msgbuf[3], &xm.msgbuf[4]);
- break;
- case MN_SELECTED:
- do_menuitem(xm.msgbuf[3], xm.msgbuf[4]);
- break;
- /* etc */
- } /* end switch */
- } /* end if (MU_MESAG) */
- } /* end while(1) */
- } /* end multi() function */
-
- As can be seen in the example, this can be much more efficient than
- the usual call to evnt_multi, because it is not necessary to stack
- 50-some bytes of info on each loop iteration. Also, the binding for
- envx_multi is *much* smaller and faster than the one for evnt_multi.
-
- ;-------------------------------------------------------------------------
- ; winx_get - Alternate for wind_get
- ;-------------------------------------------------------------------------
-
- int winx_get(int whandle, int wfield, GRECT *outrect);
-
- This binding takes the same 2 input parms as wind_get; the window
- handle, and a value indicating the window info to be returned. For
- output, it takes a pointer to a GRECT structure. The return value is
- the same as for wind_get() (0 indicates error).
-
- Note that the pointer to the output doesn't *have* to be a GRECT
- pointer, it is more specifically a pointer to 4 contiguous words of
- storage which will hold the return values. The only wind_get()
- functions which return more than a single value all return GRECT type
- output, however.
-
- If winx_get() is called with a wfield value that implies just one
- return value (WF_TOP, for example), you must be aware that EIGHT BYTES
- OF MEMORY WILL BE MODIFIED at the location pointed to by the output
- pointer. (All but the first 2 bytes will be garbage, of course).
-
- Usage example:
-
- GRECT currect;
-
- winx_get(wi_handle, WF_CURRXYWH, &currect);
-
- ;-------------------------------------------------------------------------
- ; winx_calc - Alternate for wind_calc
- ;-------------------------------------------------------------------------
-
- int winx_calc(int type, kind, in_x, in_y, in_w, in_h, GRECT *outrect);
-
- This binding takes all the same input values as wind_calc, but returns
- the output in a GRECT structure. Note that although the input xywh
- values are listed as discrete in the definition above, your compiler
- will accept the name of a GRECT as the third parameter, and will
- stack the four values from the rectangle as discrete parms.
-
- The following example might be used to create a window around an
- object tree...
-
- int wi_kind = MOVER | FULLER | CLOSER;
- GRECT workrect;
- GRECT fullrect;
-
- frmx_center(tree, &workrect);
- winx_calc(WC_BORDER, wi_kind, workrect, &fullrect);
- wi_handle = wind_create(wi_kind, fullrect);
- if (wi_handle >= 0)
- wind_open(wi_handle, fullrect);
-
- ;-------------------------------------------------------------------------
- ; frmx_center - Alternate for form_center
- ;-------------------------------------------------------------------------
-
- int frmx_center(OBJECT *ptree, GRECT *outrect);
-
- This binding takes a pointer to an object tree (as form_center does),
- and a pointer to a GRECT where the output xywh values will be returned.
- The return value from the function is always 1, as for form_center.
-
- Example:
-
- GRECT treerect;
-
- frmx_center(ptree, &treerect);
- objc_draw(ptree, R_TREE, MAX_DEPTH, treerect);
-
- ;-------------------------------------------------------------------------
- ; v_gchar - Output a single character via a fast call to v_gtext
- ;-------------------------------------------------------------------------
-
- void v_gchar(int vdi_handle, int x, int y, char outchar);
-
- This function generates a fast call to v_gtext to output a single
- character. It is about half the size of the regular v_gtext binding,
- and will execute **much** faster. It is useful for things like
- telecomm programs that must do character-at-a-time output to a window.
-
- | This function is new with v1.5.
-
- ;-------------------------------------------------------------------------
- ; vdicall - Issue a call to VDI with the specified control/intin/etc.
- ;-------------------------------------------------------------------------
-
- int vdicall(control, intin, ptsin, intout, ptsout);
-
- Each of the parameters is a pointer to an array of 16-bit ints.
-
- This function allows you to call VDI functions not directly supported
- by the vdifast bindings library. Within your program, you set up
- arrays containing the parameters for the function, and then pass
- pointers to those arrays to this routine. It will combine the
- pointers into a VDI parameter block, and issue the VDI trap.
-
- This routine always returns a 16-bit integer which is the contents
- of intout[0].
-
- You must always supply a non-NULL pointer for control, and the values
- in control must contain everything VDI needs to process the call.
- (IE, opcode, sub-opcode if needed, intin count, ptsin count, and
- extend control info such as the FDB pointers for a blit, if needed).
- You never need to supply the intout or ptsout count values in the
- control array: VDI will fill those in (and will ignore anything you
- put there anyway.)
-
- The other array pointers may be NULL if they are not needed for a
- given VDI call (ie, if there are no ptsin parms for the call, just
- code NULL for the ptsin pointer). The intout array is handled a
- little strangely: if you supply a NULL intout pointer, the vdicall()
- routine allocates a 256-byte intout array on the stack for you. It
- will return the value from intout[0] as the function return value,
- and discard the rest of the intout array. This is mainly to provide
- ease-of-use in coding custom bindings which only need a single-word
- return value (ie, success/failure).
-
- As an example, suppose the vro_cpyfm() binding was not supported.
- You could write a macro to implement it, as follows:
-
- #define vro_cpyfm(handle,op,xycoords,srcfdb,dstfdb) \
- { \
- int control[11] = {109, 4, 0, 1, 0, 0}; \
- int temp = op; \
- control[6] = handle; \
- *(long*)(&control[7]) = (long)srcfdb; \
- *(long*)(&control[9]) = (long)dstfdb; \
- vdicall(control, &temp, xycoords, NULL, NULL); \
- }
-
- (NOTE: If you are using Sozobon C, the control and temp variables
- in this example would have to be declared as 'static' to avoid a
- bug in the compiler (at least, as of v1.3) that causes bombs when
- you initialize an auto-class variable declared in a local block.)
-
- There are, of course, other ways to implement functions besides
- coding them as macros -- you can, for example, build your own
- library of C functions which serve as bindings. (In fact, I rather
- hope someone will code up a set of GDOS bindings in this way, and
- that such bindings eventually find their way back to me. Then I
- could re-do them in assembler and make them part of GemFast. I
- just don't have any docs on GDOS.)
-
- As an assist to anyone undertaking their own bindings, the following
- is the code that implements this function:
-
- _vdicall:
- .cargs #8,.control.l,.intin.l,.ptsin.l,.intout.l,.ptsout.l
- link a6,#-256 ; nice big intout, 'just in case'.
- move.l a3,-(sp) ; save this, we use it for intout.
- move.l .intout(a6),a3 ; get caller-supplied intout ptr.
- move.l a3,d0 ; test it for NULLness, if it's
- bne.s .no_local_intout ; not NULL, continue, else set
- lea -256(a6),a3 ; up a pointer to our local intout
- clr.w (a3) ; array, and blast local intout[0].
- .no_local_intout:
- move.l .ptsout(a6),-(sp) ; build vdipb on the stack...
- move.l a3,-(sp)
- move.l .ptsin(a6),-(sp)
- move.l .intin(a6),-(sp)
- move.l .control(a6),-(sp)
- move.l sp,d1 ; load pointer to vdipb
- moveq.l #$73,d0 ; load vdi function code
- trap #2 ; do it.
- move.w (a3),d0 ; return intout[0] in d0.
- move.l (sp)+,a3
- unlk a6
- rts
-
- | This function is new with v1.6.
-
- ;-------------------------------------------------------------------------
- ; vgd_detect - Detect presence of GDOS on the machine.
- ;-------------------------------------------------------------------------
-
- int vgd_detect()
-
- Returns zero if GDOS not present or non-zero if it is present. Works
- by calling trap #2 with -2 in D0 register, then testing for -2 still
- in the register after the trap.
-
- | This functions is new with v1.7.
-
- **************************************************************************
- * END OF GEMXTEND DOC
- **************************************************************************
-
-