I have tested most of the routines here as completely as I could and 
have found no bugs.  However, I make no guarantees to the programmer 
that they are 100% error free.  Since I'm just poking things into 
the GEM control arrays, chances are if there are any bugs it's due to 
a typo and can be quite easily fixed.  Please contact me if you make 
any changes or find bugs.  GEM is very powerful, and can be 
dangerous as well.  Giving GEM a bad parameter can send your program 
off into memory never never land, never to return.  With C, this 
just causes the frustration of resetting and recompiling...with GFA 
however, it is easy to go long stretches without saving, only to 
watch it waste away in a second when you rub GEM the wrong way.  
So...save your work often.  I hope you find these routines useful 
and fun, as I think they take a lot of pain out of GEM programming.  
If you're so inclined, you can send lots of money to:
Paul Chinn
4995 Fern Place
Rohnert Park Ca. 94928
or lots of praise to Compuserve ID, 76157,55
Direct complaints to Atari corp.


GEM Bindings for GFA Basic. 1987 Paul Chinn
Release 1

     As most people are well aware, GFA basic is perhaps the most 
powerful basic ever created.  Not only that, but its performance 
rivals that of many compiled languages such as C or Pascal.  
Graphics, sound, I/O, GFA does everything...well maybe not 
_everything_.  GFA's weakest part, in my opinion, is its use of GEM.  
As implemented GFA is great for beginning GEM programmers.  What 
could be easier than OPENW 1 to pop open a window?  Well, with the 
simplicity you lose much of the power of GEM.  Under GFA
only four windows can be opened, and GFA maintains tight control 
over them, redirecting output to only the open window.  Use of 
resource files is limited to just menus and these are limited to 
text only.  As I mentioned, as is GFA's GEM is fine for beginners 
but is probably missing close to 90% of GEM functions, functions 
that are very desirable for advanced programming.  Fortunately, the 
programmers of GFA left their product amazingly open ended with 
hooks to all sorts of neat internal ST stuff...like GEM.        

I've taken advantage of these hooks, and created the set of 
subroutines you have here.  Now, right at your fingertips are all 
the GEM AES calls(except for appl_read,appl_write,and the play and 
record functions which are rarely used).  I've adopted the 'C' 
format for these calls, so GFA programmers can take advantage of the 
numerous tutorials about GEM in C.  Also, I myself, am a C 
programmer.  I have found GFA invaluable for testing out ideas and 
program mock-ups and now with these utilities, a GEM program can be 
translated virtually verbatim from basic to C(or vice versa). Not 
only that, but I can test out the AES and GEM in real time, from 
GFA's direct mode...something not previously possible.  The rest of 
this doc file will explain the use of these routines.  It is not 
intended as a tutorial on GEM but will outline each of the calls, 
and give some explanations for overcoming some of the 
dissimilarities between basic and C.

Using the routines:

To use the routines you have to include the following routines in 
each program:
fill_gcont()
fill_gint()
gem()
crack_add()
vs_clip()
Gem(),fill_gcont(), and fill_gint() are used by the routines and you 
need not worry about their use.  The other 2 will be explained 
later.  All these routines are at the end of the listing.

The rest of the routines are the actual GEM calls and you may 
include all of them in your program or only the ones you need.  I 
suggest that when you use my routines you don't mix in the GFA 
counterpart.  So if you use wind_open, keep away from GFA's openw.

The calls for the most part, follow their C counterparts exactly.
So the following call in C:
handle=wind_create(11,20,20,100,100);
would look like:
@wind_create(11,20,20,100,100)
in GFA.  As you can see, the transition is an easy one.  There are a 
few exceptions however.


Crossing the C to BASIC bridge:

Once difference between Basic and C is that unlike C, basic cannot 
return values from subroutines.  I solved this by creating the 
global variable ret.  So after a call, ret will contain the value 
normally returned by the C counterpart.  In the above example, ret 
would equal handle.

Another difference concerns passing variables.  In C the following 
is perfectly valid:
rsrc_load("Dummy.rsc");
In GFA, however, you will get an error because all my GEM routines 
take integers as parameters and unlike C, GFA does not convert 
types.(Note: in GFA integers are 4 bytes while in C they are only 
2...this will not usually be a problem).  The solution is again 
simple:
a$="DUMMY.RSC"
@rsrc_load(varptr(a$))
is the working basic equivalent.

Finally, if the C call is something like:
do_it(&x,&y,j);
the GFA call would be
@do_it(*x,*y,j)
The & in C and the * in basic tell the function to pass the 
_address_ of the variable so that its value may be changed by the 
function.  If this concept seems radically new to you, I suggest you 
brush up on variables and pointers before continuing.

There are some other differences that affect individual functions 
but they are minor and will be explained when needed.


And now the routines:
For explanation of the routines and their variables I suggest the 
abacus GEM book or Tim Oren's excellent series of tutorials on 
Compuserve.  The variable names shown here are the names used in the 
actual routines and because of the way GFA handles local and global 
variables you _MUST NOT_ use the same names for variables when 
calling my routines.

vs_clip(cx%,cy%,ch%,cw%,toggle%)
this call sets the clipping rectangle.  You specify the corner x and 
y and the width and height.  Clipping is turned on when toggle% is 1 
and off when toggle% is 0.  Turn off clipping only when you can be 
sure you won't write over the wrong part of the screen. This command 
must be used so that you don't draw over other windows or open ACCs.

*****AES initializing routines
Sets up your application.(I believe GFA takes care of this so they 
probably aren't needed)

@appl_init
@graf_handle(*hwchar%,*hhchar%,*hwbox%,*hhbox%)

*****AES window management

@wind_get(ghandle%,gfield%,*gw1%,*gw2%,*gw3%,*gw4%)
@wind_create(crkind%,crwx%,crwy%,crww%,crwh%)
@wind_open(ohandle%,owx%,owy%,oww%,owh%)
@wind_close(clhandle%)
@wind_delete(dhandle%)
@wind_set(shandle%,sfield%,sw1%,sw2%,sw3%,sw4%)
****>now's a good time to introduce the routine crack_add().  If you 
use wind_set to set the address of the text in the name or info 
lines of a window, you need to pass the lo and hi words in sw1% and 
sw2%.  This is how you do it:
     title$="My Window Title"
     title_add=varptr(title$)
     @crack_add(title_add)'crack_add returns 2 global variables: 
          hi% & lo%
     @wind_set(shandle%,2,lo%,hi%,0,0)

@wind_find(fmx%,fmy%)
@wind_update(ubegend%)
@wind_calc(ctype%,ckind%,cinx%,ciny%,cinw%,cinh%,*coutx%,*couty%,
           *coutw%,*couth%)

*****AES event handlers

@evnt_keybd
@evnt_button(bclicks%,bmask%,bstate%,*bmx%,*bmy%,*bbutton%,*bkstate%)
@evnt_mouse(moflags%,mox%,moy%,mowidth%,moheight%,*momx%,*momy,
            *mobutton%,*mokstate)
@evnt_timer(tlocount%,thicount%)
@evnt_mesag(mgpbuff%)
*****>buffer% has to be the address of a 16 byte buffer here's a how 
I like to do it:
     buffer$="0123456789abcdef"
     buffer%=varptr(buffer$)
     @evnt_mesag(buffer%)
Then you can read the buffer like this:
     val1%=dpeek(buffer%+offset)'offset must be a multiple of 2
@evnt_multi(mflags%,mbclicks%,mbmask%,mbstate%,mm1flags%,mm1x%,
            mm1y%,mm1width%,mm1height%,mm2flags%,mm2x%,mm2y%,
            mm2width%,mm2height%,mmgpbuff%,mtlocount%,mthicount%,
            *mmox%,*mmoy%,*mmobutton%,*mmokstate%,*mkreturn,
            *mbreturn%)'what a beast!!!!

*****File Selection Manager

@fsel_input(iinpath%,iinsel%,*iexbutton%)


****AES Object manager

@objc_draw(dtree%,drstartob%,drdepth%,drxclip%,dryclip%,drwclip%,
           drhclip%)
@objc_find(ftree%,fstartob%,fdepth%,fmx%,fmy%)
@objc_offset(oftree%,ofobject%,*ofxoff%,*ofyoff%)
@objc_edit(edtree%,edobject%,edchar%,edidx%,edkind%,*ednewidx%)
@objc_change(ctree%,cobject%,cresvd%,cxclip%,cyclip%,cwclip%,
             chclip%,cnewstate%,credraw%)

*****Dialog box manager

@rsrc_load(lpfname%)
@rsrc_free
@rsrc_gaddr(gtype%,gindex%,*gaddr%)
@rsrc_saddr(stype%,sindex%,saddr%)
@form_do(do_tree%,dostartob%)
@form_dial(diflag%,dilittx%,dilitty%,dilittw%,dilitth%,dix%,diy%,
           diw%,dih%)
@form_center(ctree%,*cx%,*cy%,*cw%,*ch%)
@form_alert(adefbttn%,astring%)
@form_error(enum%)


*****AES drop down menu manager

@menu_bar(btree%,bshow%)
@menu_icheck(ctree%,citem%,ccheck%)
@menu_enable(etree%,eitem%,eenable%)
@menu_tnormal(ntree%,ntittle%,nnormal%)
@menu_text(ttree%,titem%,ttext%)
@menu_register(rapid%,rpstring%)


*****AES graphic library

@graf_rubberbox(rx%,ry%,rminwidth%,rminheight%,*rlastwidth%,
                *rlastheight%)
@graf_dragbox(dwidth%,dheight%,dstartx%,dstarty%,dboundx%,dboundy%,
              dboundw%,dboundh%,*dfinishx%,*dfinishy%)
@grav_movebox(mwidth%,mheight%,msourcex%,msourcey%,mdestx%,mdesty%)
@graf_growbox(gstx%,gsty%,gstwidth%,gstheight%,gfinx%,ginfy%,
              gfinwidth%,gfinheight%)
@graf_shrinkbox(sfinx%,sfiny%,sfinwidth%,sfinheight%,sstx%,ssty%,
                sstwidth%,sstheight%)
@graf_watchbox(wptree%,wobject%,winstate%,woutstate%)
@graf_slidebox(slptree%,slparent%,slobject%,slvh%)
@graf_mouse(monumber%,mofaddr%)
@graf_mkstate(*mkmx%,*mkmy%,*mkmstate%,*mkkstate%)

