[net.micro.atari16] ProGEM Parts 10-12

bammi@cwruecmp.UUCP (Jwahar R. Bammi) (05/03/86)

Here are the next three articles in Tim Orens Professional Gem
seminar. I am also including the updated proff header file that
includes all the parts (tut.prf).
					enjoy,

#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	tut.prf
#	wind10.prf
#	wind11.prf
#	wind12.prf
#	apndx9.prf
# This archive created: Sat May  3 01:36:35 1986
# By:	Jwahar R. Bammi ()
export PATH; PATH=/bin:$PATH
echo shar: extracting "'tut.prf'" '(1190 characters)'
if test -f 'tut.prf'
then
	echo shar: over-writing existing file "'tut.prf'"
fi
sed 's/^X//' << \SHAR_EOF > 'tut.prf'
X.!****************************************************************************
X.! 
X.! ANTIC PUBLISHING INC., COPYRIGHT 1985.  REPRINTED BY PERMISSION.
X.!
X.! ** Professional GEM ** by Tim Oren
X.!
X.! Proff File by ST enthusiasts at
X.! Case Western Reserve University
X.! Cleveland, Ohio
X.! uucp : decvax!cwruecmp!bammi
X.! csnet: bammi@case
X.! arpa : bammi%case@csnet-relay
X.! compuserve: 71515,155
X.!
X.!****************************************************************************
X.!
X.!			Begin Tutorial
X.!
X.!***************************************************************************
X.!
X.!
X.so macros.prf
X.so wind1.prf
X.so wind2.prf
X.so wind3.prf
X.so wind4.prf
X.so wind5.prf
X.so wind6.prf
X.so wind7.prf
X.so wind8.prf
X.so wind10.prf
X.so wind11.prf
X.so wind12.prf
X.!
X.! Add any further Parts Above
X.!
X.cl 0 APPENDICES
X.so apndx1.prf
X.so apndx2.prf
X.so apndx3.prf
X.so apndx4.prf
X.so apndx5.prf
X.so apndx6.prf
X.so apndx7.prf
X.so apndx8.prf
X.so apndx9.prf
X.!
X.! Add any further Appendicies Above
X.!
X.so toc.prf
X.!
X.!
X.!****************************************************************************
X.!
X.!			End Tutorial
X.!
X.!***************************************************************************
SHAR_EOF
if test 1190 -ne "`wc -c 'tut.prf'`"
then
	echo shar: error transmitting "'tut.prf'" '(should have been 1190 characters)'
fi
echo shar: extracting "'wind10.prf'" '(13162 characters)'
if test -f 'wind10.prf'
then
	echo shar: over-writing existing file "'wind10.prf'"
fi
sed 's/^X//' << \SHAR_EOF > 'wind10.prf'
X.!****************************************************************************
X.! 
X.! ANTIC PUBLISHING INC., COPYRIGHT 1985.  REPRINTED BY PERMISSION.
X.!
X.! ** Professional GEM ** by Tim Oren
X.!
X.! Proff File by ST enthusiasts at
X.! Case Western Reserve University
X.! Cleveland, Ohio
X.! uucp : decvax!cwruecmp!bammi
X.! csnet: bammi@case
X.! arpa : bammi%case@csnet-relay
X.! compuserve: 71515,155
X.!
X.!****************************************************************************
X.!
X.!
X.!****************************************************************************
X.!
X.!			Begin Part 10
X.!
X.!****************************************************************************
X.!
X.PART X VDI Graphics: Text Output
X.PP
XThis  issue of ST PRO GEM concludes the two column series  on
XVDI  with a look at simple VDI  text output,  and ways to optimize
Xits  speed.   There is also a Feedback section.   You may find the
Xassociated  download  file under the name GMCL10.C in DL3  of  the
XATARI16 SIG (PCS-58).
X.PP
XTo  keep  the size of this first discussion  of  text  within
Xreason, I am going to restrict it to use of the mono-spaced system
Xfont   in  its  default  size  and  orientation.    Discussion  of
Xalternate and proportionally spaced fonts,  baseline rotation, and
Xcharacter scaling will become a later article in this series.
X.SH DEFINITIONS
XThis  article  makes use of  some  terminology
Xwhich may be unfamiliar if you have not used digital typefaces.  A
Xmono-spaced  font  is  one in which  each  character  occupies  an
Xidentically  wide  space on the screen.   A proportional font  has
Xcharacters  which occupy different widths.   For instance,  an 'l'
Xwould probably be narrower than a 'w'.
X.PP
XText may be "justified" right,  left,  or center.  This means
Xthat  the right character,  left character,  or center position of
Xthe  text  string is constrained to a given location.   In  common
Xusage,  a  page  of text is "ragged right" if its lines  are  left
Xjustified only.   The text page is "fully justified",  "justified"
Xor  (ambiguously)  "right justified" if BOTH the  left  and  right
Xcharacters are contrained to fixed columns.  Full justification is
Xproduced  by  inserting extra blank characters in the  case  of  a
Xmono-spaced font,  or by adding extra pixel columns in the case of
Xproportional output.
X.PP
XA  text character (in a monospaced font) is written inside  a
Xstandard sized cell or box.  Vertically, the cell extends from the
X"top  line" down to the "bottom line".   If there are one or  more
Xblank  lines at the top or bottom,  they are called "leading"  and
Xare  used  to separate lines of text.   The characters  themselves
Xalways  fall between the "ascent line",  which is the highest line
Xreached by characters such as 'd' and 'l', and the "descent line",
Xwhich  is the lowest line in characters like 'q' and  'g'.   Other
Xlocations  of  interest are the "half line",  which is the top  of
Xcharacters  like  'a' or 'n',  and the "base line",  which is  the
Xbottom of characters which do not have descenders.
X.PP
XBefore  plunging into the Attribute Functions for  text,  you
Xshould  note  that  the  writing  mode  (vswr_mode)  and  clipping
Xrectangle  (vs_clip) attributes discussed in the last column  (#9)
Xalso  pertain  to  text.   Since much of the  discussion  of  text
Xoptimization  will  center on these attributes,  you may  want  to
Xreview them.
X.SH TEXT ATTRIBUTES
XThe writing color for graphics text is set
Xwith the command:
X.FB vst_color()
X          vst_color(vdi_handle, color);
X.FE
XVdi_handle  is  always the handle returned from  graf_handle()  at
Xapplication startup.  Color is a word value between 0 and 15 which
Xdesignates  the  output  color index.   As discussed  in  previous
Xcolumns,  the  actual  color  which appears is  dependent  on  the
Xcurrent  palette  settings.   In  applications such  as  word  and
Xoutline  processors  it  is important that  characters  and  their
Xbackground  provide  good contrast to avoid eyestrain.   In  these
Xsituations,  you  may  want to use the setPalette and/or  setColor
XXBIOS  functions  to  force the palette to a  known  state  before
Xstarting the application.
X.PP
XYou  can choose a variety of special output effects for  your
Xtext with the call:
X.FB vst_effects()
Xvst_effects(vdi_handle, effects);
X.FE
XEffects is a single flag word,  with the bits having the following
Xsignificance:
X.BO
X0 - Thicken
X.EO
X.BO
X1 - Lighten
X.EO
X.BO
X2 - Skew
X.EO
X.BO
X3 - Underline
X.EO
X.BO
X4 - Outline
X.EO
X.BO
X5 - Shadow
X.EO
X.PP
XIn each case,  turning the bit on selects the effect.   Otherwise,
Xthe  effect  is  off.   Any  number of  multiple  effects  may  be
Xselected, but the result may not always be pleasing or legible.
X.PP
XThe  "thicken"  effect widens the character  strokes  by  one
Xpixel,   resulting  in  the  appearance  of  boldface  type.   The
X"lighten" effect superimposes a half-tone dither on the character.
XThis mode is useful for indicating non-selectable text items,  but
Xis not legible enough for other purposes.
X.PP
XThe  skew effect shifts the rows of the character the  right,
Xwith  the greatest displacement at the top.   This results in  the
Xappearance of italic text.   You should be aware that the VDI does
Xnot  compensate for this effect.   This means that a skewed italic
Xcharacter which is immediately followed by a normal blank will  be
Xoverstruck,  and  part of the top of the character will disappear.
XLikewise,  a  skewed character written to the left of an  existing
Xnormal  character will overstrike part of it.   There is a related
Xbug  in  the VDI clipping logic which may cause some  parts  of  a
Xskewed  character not to be redrawn if they fall at the edge of  a
Xclipping  rectangle,  even  though  they should  fall  within  the
Xregion.
X.PP
XThe  outline  effect  produces output which is  a  one  pixel
X"halo" around the normal character.  The shadow effect attempts to
Xcreate  a  "drop  shadow" to the side  of  the  character.   These
Xeffects  should be used very sparingly with default  sized  fonts.
XThey often result in illegible output.
X.PP
XWhen  graphics text is written,  a screen coordinate must  be
Xspecified  for  the output.   The relationship of the text to  the
Xscreen point is determined by the call:
X.FB bst_alignment()
X          vst_alignment(vdi_handle, hin, vin, &hout, &vout);
X.FE
XHin  and  vin are each words,  with values specifying the  desired
Xhorizontal  and vertical alignment,  respectively.   Hout and vout
Xreceive the actual values set by the VDI.  If they differ from the
Xrequested values, an error has occurred.
X.PP
XHin may be set to zero for left justification, one for center
Xjustification,  or  two  for right justification.   The coordinate
Xgiven when text is written becomes the "anchor point" as described
Xin the definitions above.  The default justification is left.
X.PP
XVin determines what reference line of the text is  positioned
Xat the output coordinate.  The selection values are:
X.bp
X.BO
X0 - baseline (default)
X.EO
X.BO
X1 - half line
X.EO
X.BO
X2 - ascent line
X.EO
X.BO
X3 - bottom line
X.EO
X.BO
X4 - descent line
X.EO
X.BO
X5 - top line
X.EO
X.PP
XA  common combination of alignments is left (0) and top  line
X(5).   This  mode guarantees that all text output will lie to  the
Xright and below the output coordinate.   This corresponds with the
XAES object and GRECT coordinate systems.
X.PP
XFinally, the call to do the actual output is:
X.FB v_gtext()
Xv_gtext(vdi_handle, x, y, string);
X.FE
XX  and y define the screen coordinate to be used as the  alignment
Xpoint.   String  is  a pointer to a null terminated string,  which
Xmust  be total eighty characters or less,  exclusive of the  null.
XThis limit is imposed by the size of the intin[] array in the  VDI
Xbinding.   Be  warned  that  it  is NOT checked  in  the  standard
Xbinding!  Exceeding it may cause memory to be overwritten.
X.PP
XOne Inquire Function is useful with text output.  The call
X.FB vqt_attributes()
Xvqt_attributes(vdi_handle, attrib);
X.FE
Xreads  back the current attribute settings into the 10 word  array
Xattrib[].   The  main  items  of interest  are  attrib[6]  through
Xattrib[9],  which contain the width and height of characters,  and
Xthe  width and height of the character cell in the  current  font.
XYou  should  rely  on this function to  obtain  size  information,
Xrather  than using the output of the graf_handle()  function.   On
Xthe ST, graf_handle() always returns sizes for the monochrome mode
Xsystem font, which will be incorrect in the color screen modes.
X.PP
XAttrib[1] will contain the current graphics text color as set
Xby  vst_color().   Attrib[3]  and [4] contain the  horizontal  and
Xvertical alignment settings, respectively.  Attrib[5] contains the
Xcurrent writing mode, as set by vswr_mode().
X.SH OPTIMIZATION
XThe most common complaint about using bit maps
Xfor character output is lack of speed.  This section suggests ways
Xto  speed  things up.   By adopting all of these methods,  you can
Xrealize an improvement of two to three times in speed.
X.SH BYTE ALIGNMENT
XSince writing graphic text is essentially a
Xbit-blit operation,  characters which have "fringes",  that is, do
Xnot  align  evenly with byte boundaries,  will suffer  performance
Xpenalities.  The default system fonts in all resolutions of the ST
Xare  a  multiple of eight pixels wide,  so the problem reduces  to
Xassuring  that  each characters starts at a byte boundary  in  the
Xscreen bit map.  This will be true if the horizontal pixel address
Xof the left edge of the character is evenly divisible by eight.
X.PP
XObviously,  byte  alignment  is easiest to enforce  when  the
Xhorizontal justification is right or left.  Doing so with centered
Xtext is possible, but requires adding padding blanks to odd length
Xstrings.
X.PP
XWhen  writing  text within windows,  it is helpful to  assure
Xthat the edges of the window working area are byte aligned.  There
Xis  a section of code in the download which shows a technique  for
Xconverting  a  user requested window position and/or size  to  its
Xworking   dimensions,   byte-aligning  the  width  and  horizontal
Xposition, and computing the adjusted external window coordinates.
X.SH WRITING MODE
XThe fastest text output mode is replace.  All
Xother modes require reading in the target raster area and  merging
Xit  with  the  new information.   You may find that you  must  use
Xtransparent or reverse transparent mode,  for instance,  to use or
Xpreserve an underlying background color other than white.  In this
Xcase,  you  can  still  do  some optimization by  filling  in  the
Xbackground color for the entire string with a v_bar() call, rather
Xthan doing it one character cell at a time.
X.SH CLIPPING
XVDI  output  always  proceeds  faster  when  the
Xclipping rectangle is turned off, and text output is no exception.
XRemember  that  you  may only do this if you are  drawing  into  a
Xdialog box,  or into the interior of a window which you know is on
Xtop.   (You  can  use  the WM_TOPPED and  WM_NEWTOP  messages  for
Xkeeping track of the top window, or use the WF_TOP wind_get() call
Xto  find the current top.)  In both of these cases,  you will know
Xthe  width  of the drawing area,  and you can truncate the  output
Xstring to fit exactly, rather than setting the clipping rectangle.
XFor this to work,  you must have used the byte alignment technique
Xto  assure  that the width of the writing area is  a  multiple  of
Xeight.
X.SH BINDINGS
XThe  normal binding for v_gtext() is inefficient.
XIt copies the string which you supply character-by-character  into
Xintin[] before it calls the VDI itself.  In many cases, it will be
Xmore  efficient for your application to place characters  directly
Xinto  intin[] and make the VDI trap call directly.   To give you a
Xstart,  the  code  for  the standard v_gtext()  binding  has  been
Xincluded in the download.  When setting up intin[], be sure not to
Xload  more  than  80 characters,  or you will probably  crash  the
Xsystem!
X.SH MOVING TEXT
XWhen performing text editing on the screen, you
Xshould  avoid rewriting the string under edit  whenever  possible.
XIt is always more efficient to use the raster operations to move a
Xstring  to  the right or left,  assuming that you have obeyed  the
Xbyte  alignment rule.    If you are deleting characters,  blit the
Xunchanged part of the screen to the left,  and overstrike the last
Xcharacter  in the string with a blank.   If inserting  characters,
Xblit  the  trailing  portion of the string  to  the  right  before
Xwriting in the new character.
X.SH THAT'S IT FOR NOW
XThis concludes the two article series on
Xsimple  VDI output.   Future columns may explore more complex  VDI
Xtopics such as proportional text.  If there is something you would
Xlike  to  see,  please  use the Online Feedback to  let  me  know!
XMeanwhile,  the next column will give out the locations of some of
Xthe  "hooks" and "trapdoors" built into the AES object  structure,
Xincluding  how  to set up user-defined AES drawing  objects.
X.!
X.!
X.!*****************************************************************************
X.!*									      *
X.!*				End Part 10				      *
X.!*									      *
X.!*****************************************************************************
SHAR_EOF
if test 13162 -ne "`wc -c 'wind10.prf'`"
then
	echo shar: error transmitting "'wind10.prf'" '(should have been 13162 characters)'
fi
echo shar: extracting "'wind11.prf'" '(21298 characters)'
if test -f 'wind11.prf'
then
	echo shar: over-writing existing file "'wind11.prf'"
fi
sed 's/^X//' << \SHAR_EOF > 'wind11.prf'
X.!****************************************************************************
X.! 
X.! ANTIC PUBLISHING INC., COPYRIGHT 1985.  REPRINTED BY PERMISSION.
X.!
X.! ** Professional GEM ** by Tim Oren
X.!
X.! Proff File by ST enthusiasts at
X.! Case Western Reserve University
X.! Cleveland, Ohio
X.! uucp : decvax!cwruecmp!bammi
X.! csnet: bammi@case
X.! arpa : bammi%case@csnet-relay
X.! compuserve: 71515,155
X.!
X.!****************************************************************************
X.!
X.!
X.!****************************************************************************
X.!
X.!			Begin Part 11
X.!
X.!****************************************************************************
X.!
X.PART XI GEM Hooks and Hacks
X.PP
XWelcome  to  the  eleventh episode of ST PRO  GEM,  which  is
Xdevoted to exploring some of the little documented,  but powerful,
Xfeatures  of GEM.   Like the authors of most complex systems,  the
XGEM  programmers left behind a set of "hooks",  powerful  features
Xwhich would aid them in enhancing the system later.  I am going to
Xlay  out  a number of these methods which have served me  well  in
Xmaking  creative use of the AES.   You will find that most of them
Xconcern  the object and form libraries,  since I was most involved
Xin those parts of GEM.  There are probably many more useful tricks
Xwaiting  to be found in other parts of GEM,  so if you happen onto
Xone, please let me know in the Feedback!  Before you begin,be sure
Xto  pick up the download for this column:  GMCL11.C in DL3 of PCS-
X57.
X.SH POWERFUL   OBJECTS
XThe  first  four tricks all involve  augmenting  standard  AES
Xobjects.   This is a powerful technique for two  reasons.   First,
Xyou  can  take  advantage  of the  regular  AES  object  and  form
Xlibraries  to draw and handle most of your objects,  so that  your
Xprogram need only process the exceptions.  Second, you can use the
XRCS  to  copy  the  special  objects  into  multiple  dialogs   or
Xresources.   These  four tricks are Extended Object  Types,  User-
Xdefined Objects,  TOUCHEXIT,  and INDIRECT.  Let's look at each of
Xthem in turn.
X.SH EXTENDED OBJECT TYPES
XIf you look at the AES Object Library documentation,  you will
Xnotice that the values for the OB_TYPE field in an object are  all
X32 or less.   This means that a number of bits are unused in  this
Xfield.   In fact,  the AES completely ignores the top byte of  the
XOB_TYPE field.   In addition, the RCS ignores the top byte, but it
Xalso  preserves  its value when an object  is  read,  written,  or
Xcopied.
X.PP
XThis  gives  you one byte per object to use as you  see  fit.
XSince  the  processing of an object or dialog is (so far)  in  the
Xhands of the AES,  the best uses of Extended Types are in flagging
Xmethods for initializing an object or handling its value when  the
Xdialog  completes.
X.PP
XFor  example,  you  might  have  several  dialogs  containing
Xeditable numeric fields.   The Extended Type of each numeric field
Xcould be set to the index of the corresponding value in an  array.
XThen your application's dialog initialization code could scan  the
Xobject  tree  for  such objects,  pick up  the  appropriate  value
Xfrom the array and convert it to ASCII,  storing the result in the
Xresource's  string  area.   When the dialog was finished,  another
Xpass could be made to reconvert the ASCII to binary and store away
Xthe results in the array.   (Note that the map_tree() utility from
Xcolumn #5 will scan an entire resource tree.)
X.PP
XAnother  application  is  to assign  uniform  codes  to  exit
Xbuttons  in  dialogs.   If you give every "OK" button an  Extended
XType  of one,  and every "Cancel" button an Extended Type of  two,
Xthen  you  needn't  worry about naming every  exit  object.   Just
Xexamine  the Extended Type of the object returned by form_do,  and
Xproceed accordingly.
X.PP
XThe catch, of course, is that you have to find a way to enter
Xthe  Extended  Type code in the first place.   Version 1.0 of  the
XRCS, as shipped with the Atari developer's kit, makes no provision
Xfor this.  So you have your choice of two methods for creating the
Xfirst  object with each Extended Type code.
X.PP
XFirst,  you can dump out a C source of a resource, insert the
Xnew type code by hand,  and regenerate the resource with STCREATE.
XAlternately,  you could carefully modify the binary resource using
XSID.   You will probably want to reread the AES object manual,  ST
XPRO GEM #4 and #5,  and use the C source as a guide when doing so.
XIn both cases, you should make things easy on yourself by creating
Xa  one  dialog resource with only a single object other  than  the
Xroot.   Version  2.0  of  the RCS will let you directly  enter  an
XExtended Type, but it has not yet been released for the ST by DRI.
X.PP
XOnce  you have created a prototype extended object by  either
Xmethod, you can use the RCS to propogate it.  The safest way is to
Xuse the MERGE option to add the modified tree to the resource  you
Xare building.  Then copy the prototype object via the clipboard to
Xyour dialog(s), deleting the extra tree when you are done.  If you
Xare  using several different extended objects,  you can use  MERGE
Xand clipboard copies to get them all into one tree which will then
Xbecome your own object library.
X.PP
XThe  second way of using RCS is easier,  but more  dangerous.
XIf you want to try the following technique,  BACK UP YOUR RCS DISK
XFIRST!   Put  simply,  the RCS does not care what is in its dialog
Xpartbox. It will make copies of anything that it finds there! This
Xgives you the option of using the RCS on ITS OWN RESOURCE in order
Xto add your customized objects to the partbox.
X.PP
XTo do this, open RCS.RSC from the RCS.  Since there is no DEF
Xfile,  you will get a collection of question mark icons.   Use the
XNAME option to make TREE5 into a DIALOG.    Open it,  and you will
Xsee the dialog partbox.
X.PP
XNow you can use the MERGE technique described above to insert
Xyour  customized  objects.   Then SAVE the modified resource,  and
Xrerun the RCS.  Your new objects should now appear in the partbox.
XIf  you added several,  you may have to stretch the partbox to see
Xthem  all.   You can now make copies of the new objects just  like
Xany other part.  (Note: DO NOT modify the alert or menu partboxes,
Xyou will probably crash the RCS.)
X.SH USER-DEFINED  OBJECTS
XThe one type of object which was not discussed in the  earlier
Xarticles  on  AES objects was G_USERDEF,  the  programmer  defined
Xobject.   This  is  the  hook  for  creating  objects  with  other
Xappearances  beyond those provided by the standard  AES.   By  the
Xway, you should note that the G_PROGDEF and APPLBLK mnemonics used
Xin  the  AES documents are incorrect;  the actual  names  as  used
Xdefined OBDEFS.H are G_USERDEF and USERBLK.
X.PP
XThe  RCS does not support the creation of G_USERDEF  objects,
Xsince  it  has  no idea how they will be drawn  by  your  program.
XInstead,  you  must insert a dummy object into your resource where
Xyou  want  the  G_USERDEF  to appear,  and  patch  it  after  your
Xapplication performs its resource load.
X.PP
XYou   must  replace  the  object's  existing   OB_TYPE   with
XG_USERDEF,  though you may still use the upper byte as an Extended
XType.   You  must  also  change the OB_SPEC field to be  a  32-bit
Xpointer  to  a USERBLK structure.   An USERBLK is simply two  LONG
X(32-bit)  fields.   The  first is the address of the drawing  code
Xassociated  with  the  user  defined object.   The  second  is  an
Xarbitrary 32-bit value assigned to the object by your application.
X.PP
XYou can designate objects for conversion to G_USERDEFs in the
Xnormal fashion by assigning them names which are referenced one by
Xone in your initialization code.   You can also combine two tricks
Xby using the Extended Type field as a designator for objects to be
Xconverted to G_USERDEF.  Each tree can then be scanned for objects
Xto  be converted.   There is a short code segment in the  download
Xwhich demonstrates this technique.
X.PP
XMy  usual  convention  is to define new  drawing  objects  as
Xvariants  of  existing objects,  using the Extended Type field  to
Xdesignate the particular variation.   Thus an Extended Type of one
Xmight designate a G_BUTTON with rounded corners,  while a value of
Xtwo  could  flag  a G_STRING of boldface text.   When  using  this
Xtechnique,  the  RCS can be used to build a rough facsimile of the
Xdialog  by inserting the basic object type as  placeholders.   The
Xexisting  OB_SPEC  information can then be copied  to  the  second
Xposition in the USERBLK when the object is initialized.
X.PP
XOne final note before moving on:  There is no reason that the
XUSERBLK  cannot be extended beyond two fields.   You might want to
Xadd  extra words to store more information related to drawing  the
Xobject, such as its original type.
X.PP
XThe  AES will call your drawing code whenever  the  G_USERDEF
Xneeds  to be drawn.   This occurs when you make an objc_draw  call
Xfor its tree,  or when an objc_change occurs for that object.   If
Xyour user-defined object is in a menu drop-drop, then your drawing
Xcode will be called any time the user exposes that menu.
X.PP
XBefore  getting  into the details of the AES  to  application
Xcalling  sequence,  some  warnings are in order.   First,  remember
Xthat your drawing code will execute in the AES' context, using its
Xstack.   Therefore,  be careful not to overuse the stack with deep
Xrecursion, long parameter lists, or large dynamic arrays.  Second,
Xthe  AES  is NOT re-entrant,  so you may not make ANY calls to  it
Xfrom within a G_USERDEF procedure.   You may,  of course, call the
XVDI.   Finally,  realize  that drawing code associated with a menu
Xobject may be called by the AES at any time.   Exercise great care
Xin  sharing  data  space between such code and  the  rest  of  the
Xapplication!
X.PP
XWhen your drawing code is called by the AES, the stack is set
Xup  as if a normal procedure call had occured.   There will be one
Xparameter  on the stack:  a 32-bit pointer to a PARMBLK structure.
XThis structure lies in the AES' data space, so do not write beyond
Xits end!
X.PP
XThe  PARMBLK contains 15 words.   The first two are the  long
Xaddress of the object tree being drawn,  and the third word is the
Xnumber of the G_USERDEF object.   You may need these values if the
Xsame  drawing  code is used for more than one object  at  a  time.
XWords  four  and five contain the previous  and  current  OB_STATE
Xvalues of the object.  If these values are different, your drawing
Xcode  is  being  called in response  to  an  objc_change  request.
XOtherwise, the active AES call is an objc_draw.
X.PP
XWords six through nine contain the object's rectangle on  the
Xscreen.   Remember  that  you cannot call objc_offset  within  the
Xdrawing code,  so you will need these values!  The next four words
Xcontain the clipping rectangle specified in the active objc_change
Xor objc_draw call.   You should set the VDI clip rectangle to this
Xvalue before doing any output to the screen.
X.PP
XThe last two words in the PARMBLK contain a copy of the extra
X32-bit parameter from the object's USERBLK.   If you have followed
Xthe  method of copying an OB_SPEC into this location,  these words
Xwill be your pointer to a string, or BITBLK, or whatever.
X.PP
XWhen  your drawing routine is done,  it should return a  zero
Xvalue  to  the AES.   This is a "magic" value;  anything else will
Xstop the drawing operation.
X.PP
XThe download contains a sample drawing routine which  defines
Xone extended drawing object,  a rounded rectangle button.  You can
Xuse  this procedure as a starting point for your own User  Defined
Xobjects.
X.SH PUT  ANYTHING YOU WANT ON THE DESKTOP!
XIn  ST  PRO GEM #2,  I described the use  of  the  WF_NEWDESK
Xwind_set  call to substitute your own object tree for  the  normal
Xgreen  desktop background.   If the tree you supply contains  User
XDefined  objects,  you can draw whatever you want on the  desktop!
XSome  of the things you might try are free hand drawings  imported
Xin  metafile  format from EasyDraw,  or whole  screen  bit  images
Xgenerated by Degas.   If you do the latter, you will have to store
Xthe entire image off screen and blit parts of it to the display as
Xrequested.
X.PP
XIn  any case,  remember that your desktop drawing code can be
Xcalled any time that a window is moved,  so exercise the same care
Xas with a menu drawer.   Also, be aware that making the WF_NEWDESK
Xcall  does  not force an immediate redraw of the desktop.   To  do
Xthat, do a form_dial(3) call for the entire desktop rectangle.
X.SH THE TOUCHEXIT FLAG
XThe  TOUCHEXIT attribute is an alternative to  the  more  usual
XEXIT.   When the TOUCHEXIT bit is set in an object's OB_FLAG word,
Xthe form_do routine will exit immediately when the mouse button is
Xpressed  with  the  cursor  over  the  object.    Your  code   can
Ximmediately take control of the mouse and display, without waiting
Xfor the release of the button.  This method is used for generating
Xeffects such as slider bars within otherwise normal dialogs.
X.PP
XThe  easiest  way to code a TOUCHEXIT handler is to  place  a
Xloop  around the form_do call.   If the object number returned  is
XTOUCHEXIT,  then the animation procedure is called,  followed by a
Xresumption   of  the  form_do  (WITHOUT  recalling  form_dial   or
Xobjc_draw!).   If the object returned is a normal EXIT, the dialog
Xis  complete and control flows to the cleanup code.
X.PP
XThere is one idiosyncrasy of TOUCHEXIT which should be noted.
XWhen the AES "notices" that the mouse button has been pressed over
Xa TOUCHEXIT,  it immediately retests the button state.   If it has
Xalready  been  released,  it  waits to see if  a  double click  is
Xperformed.  If so, the object number returned by form_do will have
Xits  high  bit set.   If you don't care about double clicks,  your
Xcode should mask off this flag.   However, you may want to use the
Xdouble click to denote some enhanced action.  For example, the GEM
Xfile selector uses a double click on one of the file name  objects
Xto indicate a selection plus immediate exit.
X.SH THE INDIRECT FLAG
XIf the INDIRECT bit is set in an object's OB_STATE  word,  the
XAES interprets the 32-bit OB_SPEC field as a pointer to the memory
Xlocation  in which the ACTUAL OB_SPEC is to be found.   Like  User
XDefined objects,  this capability is not supported by the RCS,  so
Xyou  have to set up the INDIRECT bit and alter the OB_SPEC at  run
Xtime.
X.PP
XThe value of INDIRECT is that you can use it to associate  an
XAES  object with other data or code.   The general technique is to
Xset  up  a table with a spare 32-bit location  at  its  beginning.
XThen,  when initializing the application's resource,  you move the
Xtrue  OB_SPEC  into  this location,  set the  INDIRECT  flag,  and
Xreplace the OB_SPEC field with a pointer to the table.  The object
Xbehaves normally during drawing and form handling. However, if you
Xreceive  its  number  from  form_do  or  objc_find,  you  have  an
Ximmediate  pointer to the associated table,  without having to  go
Xthrough a lookup procedure.
X.PP
XThis  technique works well in programs like the GEM  Desktop.
XEach  G_ICON object is set up with INDIRECT.   Its OB_SPEC goes to
Xthe  beginning of a data area defining the associated  file.   The
Xblank  location at the beginning of file table is filled  up  with
Xthe former OB_SPEC, which points to a ICONBLK.
X.PP
XYou  can also combine INDIRECT with TOUCHEXIT  when  creating
Xobjects  that  must change when they are clicked by a  user.   For
Xinstance,  a  color  selection  box  might be linked  to  a  table
Xcontaining  the various OB_SPEC values through which  the  program
Xwill cycle.   Each time the user clicked on the box, the TOUCHEXIT
Xroutine would advance the table pointer,  copy the next value into
Xthe  dummy OB_SPEC location at the front of the table,  and redraw
Xthe object in its new appearance.
X.PP
XA  programmer  who wanted to follow a  truly  object-oriented
X"Smalltalkish" approach could use the INDIRECT method to bind  AES
Xdrawing  object to tables of associated procedures  or  "methods".
XFor instance, one procedure could be flagged for use when the user
Xclicked  on the object,  one when the object was dragged,  one for
Xdouble-click,  and  so on.   If the table structure was capable of
Xindicating  that  the true method was stored in another  table,  a
Xrudimentary form of class inheritance could be obtained.
X.SH INSTANT CO-ROUTINES
XWe turn to the AES event and message system for  this  trick.
XWhile   some  languages  like  Modula  2  provide  a  method   for
Ximplementing  co-routines,  there  is  no such  capability  in  C.
XHowever,  we  can  effectively  fake it by  using  the  AES  event
Xlibrary.
X.PP
XAs  already  seen in an earlier column,  an  application  can
Xwrite a message to its own event queue using the appl_write  call.
XUsually, this is a redraw message, but there is nothing to prevent
Xyou from using this facility to send messages from one routine  in
Xyour program to another.  To set up co-routines using this method,
Xthey  would  be  coded  as separate  procedures  called  from  the
Xapplication's main event loop.
X.PP
XWhen  one  of the co-routines wanted to call  the  other,  it
Xwould  post  a message containing the request and  any  associated
Xparameters into the application's queue and then return.  The main
Xloop  would find the message and make the appropriate call to  the
Xsecond co-routine.  It it was necessary to then re-enter the first
Xco-routine  at  the  calling point,  the  original  message  could
Xcontain an imbedded reply message to be sent back when the request
Xwas  complete.   A  simple switch structure could then be used  to
Xresume at the appropriate point.
X.PP
XThere  are two potential problems in using this method.   The
Xfirst is the limited capacity of the application event queue.  The
Xqueue  contains  eight entries.    While the AES  economizes  this
Xspace  by  merging redraws and multiple events,  it  cannot  merge
Xmessages.   Because  of this limit,  you must be extremely careful
Xwhen  one  message received has the potential to generate  two  or
Xmore  messages sent.   Unless this situation is carefully managed,
Xyou  can get a sort of "cancer" which will overflow the queue  and
Xprobably crash your application.
X.PP
XThe second danger involves race conditions.   Message sent by
Xthe  application  are posted to the end of the  queue.   If  other
Xevents  have occurred,  such as mouse clicks or keyboard  presses,
Xthey will be seen and processed ahead of the application generated
Xmessage.   This  implies  that you cannot use this method  if  the
Xprogram must complete its action before a new user generated event
Xcan be processed.
X.SH THAT'S  ALL  FOR NOW
XHopefully these hints will keep you profitably occupied for  a
Xwhile.   ST PRO GEM number twelve will return to the topic of user
Xinterfaces.   Reaction  to the first article on this  subject  was
Xmostly  positive,  but a lot of folks wanted to see real  code  as
Xwell.   In response to your feedback,  there will also be code for
Ximplemented  your  own "mouse sensitive" objects  which  highlight
Xwhen the cursor touches them.   This will be presented as part  of
Xan alternate form manager.
X.SH UPDATE: ATARI ST
XI  have  recently gotten more  information  on  some  topics
Xmentioned in earlier articles.   These notes will bring you up  to
Xdate:
X.PP
XA number of developers reported that they were unable to get
Xthe  self-redraw  technique described in ST PRO GEM  #2  to  work.
XThis is usually due to a bug in the appl_init binding in Alcyon C.
XThe  value  returned from the function,  which would  normally  be
Xassigned  to gl_apid,  is coming back as garbage.   To work around
Xthe problem,  declare EXTERN WORD gl_apid;  in your program and DO
XNOT  assign the value from appl_init.   The binding WILL make  the
Xassignment.  A tip of the hat to Russ Wetmore for this report.
X.PP
XThe   last  column  mentioned  that  turning  off  the   clip
Xrectangle  while drawing graphics text will speed things  up.   It
Xturns  out that the VDI will also run at the non-clipped speed  if
Xthe  ENTIRE  string  to  be written is  within  the  current  clip
Xrectangle.  To compound the problem, there is a one-off bug in the
Xdetection  algorithm  for  the right  edge.   That  is,  the  clip
Xrectangle  has to be one pixel BEYOND the right edge of  the  text
Xfor the fast write to work.
X.PP
XThe Feedback in ST PRO GEM #10 mentioned that there are known
Xbugs  in  the  Alcyon C floating point  library.   In  fact,  this
Xlibrary  has been replaced with a new,  debugged version in recent
Xshipments  of the Toolkit.   If you need to use floating point and
Xhave  run into this bug,  you should be able to get an update from
XAtari.   Also,  check  the  Atari  Developer's SIG (PCS-57) for  a
Xpossible download.
X.PP
XIn addition, it turns out there is an undocumented feature in
XAlcyon  C  which allows you to imbed assembly code  in-line.   Try
Xusing:
X.FB asm()
Xasm(".....");
X.FE
Xwhere the dots are replaced with an assembly instruction.  You get
Xone instruction per asm(),  one asm() per line.  Thanks to Leonard
XTramiel for both of the above tidbits.
X.!
X.!
X.!*****************************************************************************
X.!*									      *
X.!*				End Part 11				      *
X.!*									      *
X.!*****************************************************************************
SHAR_EOF
if test 21298 -ne "`wc -c 'wind11.prf'`"
then
	echo shar: error transmitting "'wind11.prf'" '(should have been 21298 characters)'
fi
echo shar: extracting "'wind12.prf'" '(18067 characters)'
if test -f 'wind12.prf'
then
	echo shar: over-writing existing file "'wind12.prf'"
fi
sed 's/^X//' << \SHAR_EOF > 'wind12.prf'
X.!****************************************************************************
X.! 
X.! ANTIC PUBLISHING INC., COPYRIGHT 1985.  REPRINTED BY PERMISSION.
X.!
X.! ** Professional GEM ** by Tim Oren
X.!
X.! Proff File by ST enthusiasts at
X.! Case Western Reserve University
X.! Cleveland, Ohio
X.! uucp : decvax!cwruecmp!bammi
X.! csnet: bammi@case
X.! arpa : bammi%case@csnet-relay
X.! compuserve: 71515,155
X.!
X.!****************************************************************************
X.!
X.!
X.!****************************************************************************
X.!
X.!			Begin Part 12
X.!
X.!****************************************************************************
X.!
X.PART XII GEM Events and Program Structure
X.PP
XSo I fibbed a little.  This issue (#12) of ST PRO GEM started
Xout to be another discussion of interface issues.  But, as Tolkien
Xonce said, the tale grew in the telling, and this is now the first
Xof  a series of three articles.   This part will discuss AES event
Xhandling  and  its implications for GEM  program  structure.   The
Xfollowing  article will contain a "home brew" dialog handler  with
Xsome  new  features,  and  the third will,  finally,  take up  the
Xdiscussion  of  interface design,  using the dialog handler as  an
Xexample.   (There is no download for this article.   The downloads
Xwill return, with a vengeance, in ST PRO GEM #13.)
X
X.SH ALL FOR ONE, AND ONE FOR ALL.
XA quick inspection of the AES
Xdocuments  shows that there are five routines devoted  to  waiting
Xfor individual types of events, and one routine, evnt_multi, which
Xis  used  when more than one type is desired.   This article  will
Xdiscuss  ONLY evnt_multi for two reasons.   First,  it is the most
Xfrequently used of the routines.   Second, waiting for one type of
Xevent is a bad practice.   Any event call turns the system over to
Xthe AES and suspends the application and its interaction with  the
Xuser.   In  such  cases,  some  "escape clause",  such as a timer,
Xshould be inserted to revive the program and prompt the user if no
Xevent  is  forthcoming.   Otherwise,  the  application may end  up
Xapparently  (or  actually)  hung,  with a  resulting  reboot,  and
Xprobably a very annoyed user.
X.SH STARTING  AHEAD.
XOne  possible type of event is a  message.
XMessages  are usually sent to the application by the AES,  and are
Xassociated  with  windows or the menu.   Two previous articles  in
Xthis  series have discussed such messages.   ST PRO GEM number two
Xconsidered   window  messages,   and  number  seven  handled  menu
Xmessages.  You may want to review these topics before proceeding.
X.PP
XThe actual evnt_multi call is a horrendous thing:
X.FB evnt_multi()
Xev_which = evnt_multi(ev_flags,
X           btn_clicks, btn_mask, btn_state,
X           r1_flags, r1_x, r1_y, r1_w, r1_h,
X           r2_flags, r2_x, r2_y, r2_w, r2_h,
X           &msg_buff,
X           time_lo, time_hi,
X           &mx, &my, &btn, &kbd, &char, &clicks);
X.FE
XEach  of  the lines in the call relate to a different  event,  and
Xthey  will be discussed in the order in which they  appear.
X.PP
XNote  that a call with this number of parameters causes  some
Xoverhead stacking and retrieval of the values.   In  most
Xcases,  this  should be of little concern on a machine as fast  as
Xthe ST.   However, where throughput is a concern, such as in close
Xtracking  of the mouse cursor,  you may want to write a customized
Xbinding  for evnt_multi which dispenses with the  parameter  list.
XThis  can  be accomplished by maintaining the values in  a  static
Xarray  and moving them as a block into the binding  arrays  int_in
X(for all values but &msg_buff), and addr_in (for &msg_buff).  Note
Xthat  you  may NOT simply leave the values in  int_in;  other  AES
Xbindings reuse this space.
X.PP
XEv_flags  and ev_which are both 16-bit integers  composed  of
Xflag bits.  Bits set in ev_flags determine which event(s) the call
Xwill  wait  for;  those  set in ev_which  indicate  what  event(s)
Xactually occurred.   Both use the following flag bit mnemonics and
Xfunctions:
X.BO
X     0x0001 - MU_KEYBD - Keyboard input
X.EO
X.BO
X     0x0002 - MU_BUTTON - Mouse button(s)
X.EO
X.BO
X     0x0004 - MU_M1 - Mouse rectangle #1
X.EO
X.BO
X     0x0008 - MU_M2 - Mouse rectangle #2
X.EO
X.BO
X     0x0010 - MU_MESAG - AES message
X.EO
X.BO
X     0x0020 - MU_TIMER - Timer
X.EO
X.sp 1
XThe  appropriate mnemonics are ORed together to create the  proper
Xev_flags value.
X.PP
XThere  is  one  common pitfall here.   Notice  that  multiple
Xevents  may  be reported from one evnt_multi.   Event  merging  is
Xperformed  by the AES in order to save space on the  application's
Xevent queue.   If events have been merged,  more than one bit will
Xbe  set in the ev_which word.   Your application must check ALL of
Xthe  bits  before  returning to a new  evnt_multi  call.   If  you
Xdon't do this, some events may be effectively lost.
X.PP
XThe  first event to be considered is the mouse button.   This
Xis probably the most difficult event to understand and use, and it
Xhas one major shortcoming.
X.PP
XThe  parameter  btn_clicks tells GEM the  maximum  number  of
Xclicks which you are interested in seeing.   This value is usually
Xtwo,  if your program uses the double-click method, or one if only
Xsingle  clicks  are used.   The AES returns the number  of  clicks
Xwhich caused the event through &clicks, which must be a pointer to
Xa word.
X.PP
XGEM determines the number of clicks by the following  method.
XWhen the first button-down is detected, a time delay is begun.  If
Xanother  complete button-up,  button-down cycle is detected before
Xthe time expires,  then the result is a double click.   Otherwise,
Xthe  event is a single click.    Note that the final state of  the
Xbuttons  is  returned via &btn,  as described below.   By checking
Xthis  final state,  you may determine whether a single click event
Xended with the button up (a full click),  or with the button still
Xdown  (which  may  be  interpreted as  the  beginning  of  a  drag
Xoperation).   Double clicking is meaningless,  and not checked, if
Xthe evnt_multi is waiting on more than one button (see below).
X.PP
XThe double-click detection delay is variable,  and may be set
Xby your program using the call
X.FB ev_dclick()
Xev_dspeed = ev_dclick(ev_dnew, ev_dfunc);
X.FE
XEv_dfunc  is a flag which determines the purpose of the call.   If
Xit  is  zero,  the  current  double click  speed  is  returned  in
Xev_dspeed.   If ev_dfunc is non-zero, then ev_dnew becomes the new
Xdouble-click   speed.    Both  ev_dspeed  and  ev_dnew  are  words
Xcontaining  a "magic number" between zero and four.   Zero is  the
Xslowest  (i.e.,  longest)  double-click,  and four is the fastest.
X(These  correspond  to  the  slow-fast  range  in  the   Desktop's
XPreferences  dialog.)  In general,  you should not reset the click
Xspeed  unless  specifically requested,  because such a change  can
Xthrow off the user's timing and destroy the hand/eye  coordination
Xinvolved in using the mouse.
X.PP
XGEM  was  originally designed to work with  a  single  button
Xinput device.   This allows GEM applications interaction well with
Xdevices such as light pens and digitizing tablets.   However, some
Xfeatures are available for dealing with multi-button mice like the
XST's.
X.PP
XThe  evnt_multi parameters btn_mask and btn_state  are  words
Xcontaining  flag bits corresponding to buttons.   The lowest order
Xbit corresponds to the left-most button,  and so on.  A bit is set
Xin  the  btn_mask parameter if the AES is to  watch  a  particular
Xbutton.   The  corresponding bit in btn_state is set to the  value
Xfor  which  the program is waiting.   The word returned  via  &btn
Xuses  the  same  bit system to show the state of  the  buttons  at
Xcompletion.   It  is  important to notice that all of  the  target
Xstates in btn_state must occur SIMULTANEOUSLY for the event to  be
Xtriggered.
X.PP
XNote the limiting nature of this last statement.  It prevents
Xa  program from waiting for EITHER the left or right button to  be
Xpressed.  Instead, it must wait for BOTH to be pressed, which is a
Xdifficult  operation  at best.   As a result,  the standard  mouse
Xbutton  procedure is practically useless if you want to take  full
Xadvantage  of  both buttons on the ST mouse.   In this case,  your
Xprogram  must "poll" the mouse state and  determine  double-clicks
Xitself.   (More  on  polling later.)  By the way,  many  designers
X(myself  included) believe that using both buttons  is  inherently
Xconfusing and should be avoided anyway.
X.SH MOUSE RECTANGLES.
XOne of GEM's nicer features is its ability
Xto watch the mouse pointer's position for you, and report an event
Xonly  when it enters or departs a given screen region.   Since you
Xdon't  have to track the mouse pixel by pixel,  this eliminates  a
Xlot  of application over.   The evnt_multi call gives you  the
Xability  to  specify one or two rectangular areas  which  will  be
Xwatched.   An event can be generated either when the mouse pointer
Xenters the rectangle,  or when it leaves the rectangle.  The "r1_"
Xseries  of  parameters specifies one of the  rectangles,  and  the
X"r2_" series specifies the other, as follows:
X.sp 1
X.ti +2
Xr1_flag, r2_flag - zero if waiting to enter rectangle,
X.br
X.ti +2
X                   one if waiting to leave rectangle
X.br
X.ti +2
Xr1_x, r2_x - upper left X raster coordinate of wait rectangle
X.br
X.ti +2
Xr1_y, r2_y - upper left Y raster coordinate of wait rectangle
X.br
X.ti +2
Xr1_w, r2_w - width of wait rectangle in pixels
X.br
X.ti +2
Xr1_h, r2_h - height of wait rectangle in pixels
X.br
X.sp 1
XEach  rectangle  wait will only be active if its  associated  flag
X(MU_M1 or MU_M2) was set in ev_flags.
X.PP
XThere  are two common uses of rectangle waits.   The first is
Xused when creating mouse-sensitive regions on the screen.   Mouse-
Xsensitive regions, also called "hot spots", are objects which show
Xa  visual effect,  such as inversion or outlining,  when the mouse
Xcursor  moves  over them.   The items in a menu dropdown,  or  the
Xinversion  of  Desktop icons during a drag operation,  are  common
Xexamples.
X.PP
XHot spots are commonly created by grouping  the  sensitive
Xobjects  into  one  or  two areas,  and then setting  up  a  mouse
Xrectangle  wait  for  entering  the  area.    When  the  event  is
Xgenerated,  the  &mx  and &my returns may be examined to find  the
Xtrue  mouse coordinates,  and objc_find or some other search  will
Xdetermine  the affected object.   The object is then  highlighted,
Xand  a new wait for exiting the object rectangle is  posted.   (ST
XPRO  GEM  #13 will show how to create more  complex  effects  with
Xrectangle waits.)
X.PP
XThe  second common use of rectangle waits is in  animating  a
Xdrag operation.  In many cases, you can use standard AES animation
Xroutines such as graf_dragbox or graf_rubberbox.   In other cases,
Xyou  may  want  a figure other than a simple  box,  or  desire  to
Xcombine   waits  for  other  conditions  such  as  keystrokes   or
Xcollision with hotspots.  Then you will need to implement the drag
Xoperation  yourself,  using  the  mouse rectangles  to  track  the
Xcursor.
X.PP
XIf you want to track the cursor closely, simply wait for exit
Xon a one pixel rectangle at the current position,  and perform the
Xanimation routine at each event.  If the drag operation only works
Xon a grid,  such as character positions,  you can specify a larger
Xwait  rectangle and only update the display when a legal  boundary
Xis crossed.
X.SH MESSAGES.
XThe  &msg_buff parameter of evnt_multi gives  the
Xaddress  of a 16 byte buffer to receive an AES message.   As noted
Xabove,  I have discussed standard AES messages elsewhere. The last
Xcolumn  also mentioned that messages may be used to  simulate  co-
Xroutines  within  a single GEM program.
X.PP
XA  further possibility which bears examination is the use  of
Xmessages  to coordinate the activities of multiple  programs.   In
Xsingle-tasking  GEM,  at least one of these programs would have to
Xbe  a  desk accessory.   In any such use of the GEM messages,  you
Xshould pay careful attention to the possibility of overloading the
Xqueue.   Only  eight  slots are provided per task,  and  messages,
Xunlike events, cannot be merged by the AES.
X.SH TIMER.
XThe  timer event gives you a way of pacing action on
Xthe  screen,  clocking out messages,  or providing a time-out exit
Xfor   an  operation.    Evnt_multi  has  two  16-bit  timer  input
Xparameters,  time_hi  and  time_lo,  which are the top and  bottom
Xhalves,  respectively,  of  a  32-bit millisecond count.   However,
Xthis documented time resolution must be taken with a grain of salt
Xon the ST, considering that its internal clock frequency is 200Hz!
X.PP
XThe  timer  event is also extremely useful  for  polling  the
Xevent  queue.   A  "poll"  tests the queue  for  completed  events
Xwithout going into a wait state if none are present.  In GEM, this
Xis   done  by  generating  a  null  event  which   always   occurs
Ximmediately.  A timer count of zero will do just that.
X.PP
XTherefore,  you  can poll for any set of events by specifying
Xthem  in  the evnt_multi parameters.   A zero timer wait  is  then
Xadded to ensure immediate completion.   Upon return,  if any eveit(s) OTHER than MU_TIMER are set,  a significant event was found
Xon the queue.  If only MU_TIMER is set, the poll failed to find an
Xevent.
X.SH KEYBOARD.
XThere  are  no input parameters for the  keyboard
Xevent.   The  character  which  is read is returned  as  a  16-bit
Xquantity through the &char parameter.  For historical reasons, the
Xcodes  which  are returned are compatible with the IBM  PC's  BIOS
Xlevel scan codes.  You can find this character table in Appendix D
Xof  the  GEM VDI manual.   In general,  the high byte need only be
Xconsidered  if  the lower byte is zero.   If the low byte is  non-
Xzero, it is a valid ASCII character.
X.PP
XEvnt_multi  also returns the status of several modifier  keys
Xthrough  the &kbd parameter.   This word contains four significant
Xbits as follows:
X.BO
X     0x0001 - Right hand shift key
X.EO
X.BO
X     0x0002 - Left hand shift key
X.EO
X.BO
X     0x0004 - Control key
X.EO
X.BO
X     0x0008 - ALT key
X.EO
X.sp 1
XIf  a  bit  is  one,  the key was depressed  when  the  event  was
Xgenerated.   Otherwise,  the key was up.  Since the state of these
Xkeys  is already taken into account in generating the  &char  scan
Xcode,  the  &kbd word is most useful when creating enhanced  mouse
Xfunctions, such as shift-click or control-drag.
X.SH RANDOM NOTES ON EVENTS.
XAlthough the &mx,  &my,  &btn,  and
X&kbd returns are nominally associated with particular event types,
Xthey are valid on any return from evnt_multi, and reflect the last
Xevent  which was merged into that return by the AES.  If you  want
Xmore  current values,  you may use graf_mkstate to resample  them.
XWhichever method you choose, be consistent within the application,
Xsince  the point of sampling has an effect on mouse  and  keyboard
Xtiming.
X.PP
XAlthough  this and preceding columns have been  presented  in
Xterms of a GEM application,  the event system has many interesting
Ximplications  for desk accessories.   Since the AES scheduler uses
Xnon-preemptive  dispatching,  accessories  have an event  priority
Xeffectively  equal  to  the main  application.   Though  "typical"
Xaccessories  wait  only for AC_OPEN or AC_CLOSE messages  when  in
Xtheir  quiescent state,  this is not a requirement of the  system.
XTimer  and  other events may also be requested  by  an  accessory.
X(Indeed,  there  is  no  absolute requirement  that  an  accessory
Xadvertise  its presence with a menu_register call.)  The  aspiring
XGEM hacker might consider how these facts could be used to  create
Xaccessories  similar  to  "BUGS" on the Mac,  or  to  the  "Crabs"
Xprogram  described  in  the September,  1985 issue  of  Scientific
XAmerican.
X.SH EVENTS  AND GEM PROGRAM STRUCTURE.
XAlthough the  evnt_multi
Xcall  might seem to be a small part of the entire GEM system,  its
Xusage has deep implications for the structure of any  application.
XIt is generally true that each use of evnt_multi corresponds to  a
Xmode  in  the  program.   For instance,  form_do contains its  own
Xevnt_multi,  and its invocation creates a moded dialog.  While the
Xdialog  is in progress,  other features such as windows and  menus
Xare unusable.  The graf_dragbox, graf_rubberbox, and graf_slidebox
Xroutines also contain evnt_multi calls.   They create a mode which
Xis sometimes called "spring-loaded",  since the mode vanishes when
Xsome continuing condition (a depressed mouse button) is removed.
X.PP
XIn consequence,  a well-designed,  non-modal GEM program will
Xcontain only one explicit evnt_multi call.  This call is part of a
Xtop-level  loop  which  decodes events as they  are  received  and
Xdispatches  control  to  the appropriate  handling  routine.   The
Xdispatcher  must  always  distinguish  between  event  types.   In
Xprograms  where  multiple windows are used,  it may also  need  to
Xdetermine which local data structure is associated with the active
Xwindow.
X.PP
XThis  construction  is  sometimes  called  a  "push"  program
Xstructure,  because  it  allows the user to drive the  application
Xby generating events in any order.  This contrasts with the "pull"
Xstructure of traditional command line or menu programs,  where the
Xapplication is in control and demands input at each step before it
Xproceeds.    "Push"  structure  promotes  consistent  use  of  the
Xuser interface and a feeling of control on the part of the user.
X.PP
XThe  next ST PRO GEM column will look more closely at  events
Xand  program  structure in the context of a large piece  of  code.
XThe  code  implements an alternate dialog  handler,  incorporating
Xmouse-sensitive objects as part of the standard interface.   Since
Xthis  code  is  "open",  it may be modified and  merged  with  any
Xapplication's main event loop, resulting in non-modal dialogs.
X.!
X.!
X.!*****************************************************************************
X.!*									      *
X.!*				End Part 1				      *
X.!*									      *
X.!*****************************************************************************
SHAR_EOF
if test 18067 -ne "`wc -c 'wind12.prf'`"
then
	echo shar: error transmitting "'wind12.prf'" '(should have been 18067 characters)'
fi
echo shar: extracting "'apndx9.prf'" '(4655 characters)'
if test -f 'apndx9.prf'
then
	echo shar: over-writing existing file "'apndx9.prf'"
fi
sed 's/^X//' << \SHAR_EOF > 'apndx9.prf'
X.!****************************************************************************
X.! 
X.! ANTIC PUBLISHING INC., COPYRIGHT 1985.  REPRINTED BY PERMISSION.
X.!
X.! ** Professional GEM ** by Tim Oren
X.!
X.! Proff File by ST enthusiasts at
X.! Case Western Reserve University
X.! Cleveland, Ohio
X.! uucp : decvax!cwruecmp!bammi
X.! csnet: bammi@case
X.! arpa : bammi%case@csnet-relay
X.! compuserve: 71515,155
X.!
X.!****************************************************************************
X.!
X.!			Begin Appendix 9
X.!
X.!***************************************************************************
X.!
X.!
X.AP IX Sample Code for Part XI
X/* >>>>>>>>>>>>>> Sample code for initializing User Objects <<<<<<<<<<<<<<<< */
X
XGLOBAL	USERBLK extobjs[MAX_OBJS];	/* APPLBLK defined in OBDEFS.H	*/
XGLOBAL	WORD	n_extobjs;		/* Set MAX_OBJS to total user   */
X 					/* objects in resource		*/
X
XVOID
Xobj_init()				/* Scan whole resource for user   */
X{					/* objects.  Uses map_tree()      */
X	LONG	tree, obspec;		/* from GEMCL5.C		  */
X	WORD	itree, i, obj;
X	
X	n_extobjs = 0;			/* Replace TREE0 with your first  */
X	/* tree, TREEN with the last      */
X	for (itree = TREE0; itree <= TREEN; itree++)
X	{
X		rsrc_gaddr(R_TREE, itree, &tree);
X		map_tree(tree, ROOT, NIL, fix_obj);
X	}
X}
X
XWORD
Xfix_obj(tree, obj)			/* Code to check and fix up	*/
XLONG	tree;			/* a user defined object	*/
XWORD	obj;
X{
X	WORD	hibyte;
X	
X	hibyte = LWGET(OB_TYPE(obj)) & 0xff00;		/* check extended */
X	if (!hibyte)					/* type - if none */
X	    return (TRUE);				/* ignore object  */
X	extobjs[n_extobjs].ub_code = dr_code;		/* set drawcode   */
X	extobjs[n_extobjs].ub_parm = LLGET(OB_SPEC(obj)); /* copy obspec  */
X	LLSET(OB_SPEC(obj), ADDR(&extobjs[n_extobjs]));   /* point obspec */
X	LWSET(OB_TYPE(obj), G_USERDEF | hibyte);	/* to userblk &   */
X	n_extobjs++;					/* patch type     */
X	return (TRUE);
X}
X.bp
X/* >>>>>>>>>>>>>>>>>>>> Sample User Object Drawing Code <<<<<<<<<<<<<<<<<<<< */
X/* >>>>>>>>>>>>>>>>>>>> Implements Rounded Box based    <<<<<<<<<<<<<<<<<<<< */
X/* >>>>>>>>>>>>>>>>>>>> on G_BOX type		        <<<<<<<<<<<<<<<<<<<< */
X
XWORD
Xdr_code(pb)				/* Sample user object drawing   */
XPARMBLK	*pb;				/* code.  Caution: NOT portable */
X{					/* to Intel small data models   */
X	LONG	tree, obspec;
X	WORD	slct, flip, type, ext_type, flags;
X	WORD	pxy[4];
X	WORD	bgc, interior, style, bdc, width, chc;
X	
X	tree = pb->pb_tree;
X	obspec = LLGET(pb->pb_parm);	/* original obspec from USERBLK  */
X	ext_type = LHIBT(LWGET(OB_TYPE(pb->pb_obj)));
X	slct = SELECTED & pb->pb_currstate;
X	flip = SELECTED & (pb->pb_currstate ^ pb->pb_prevstate);
X	set_clip(TRUE, &pb->pb_xc);	/* These two routines in GEMCL9.C */
X	grect_to_array(&pb->pb_x, pxy);	
X	
X	switch (ext_type) {
X	    case 1:			/* Rounded box       */
X		/* Crack color word  */
X		get_colrwd(obspec, &bgc, &style, &interior,
X			   &bdc, &width, &chc);
X		/* For select effect, use char color */
X		if (slct)	/* In place of background	     */
X		    bgc = chc;
X		/* Fill in background		     */
X		rr_fill(MD_REPLACE, (width? 0: 1), bgc, interior, 
X			style, pxy);
X		/* Do perimeter if needed	     */
X		/* rr_perim is in GEMCL9.C	     */
X		if (width && !flip)
X		{
X			pxy[0] -= width; pxy[2] += width; 
X			rr_perim(MD_REPLACE, bdc, FIS_SOLID, width, pxy);
X		}
X		break;
X	    default:		/* Add more types here		    */
X		break;
X	}
X	return (0);
X}
X
XVOID				/* Cracks the obspec color word    */
Xget_colrwd(obspec, bgc, style, interior, bdc, width, chc)
XLONG	obspec;
XWORD	*bgc, *style, *interior, *bdc, *width, *chc, *chmode;
X{
X	WORD	colorwd;
X	
X	colorwd = LLOWD(obspec);
X	*bgc = colorwd & 0xf;
X	*style = (colorwd & 0x70) >> 4;
X	if ( !(*style) )
X	    *interior = 0;
X	else if (*style == 7)
X	    *interior = 1;
X	else if (colorwd & 0x80)	/* HACK: Uses character writing mode */
X	    *interior = 3;		/* bit to select alternate interior  */
X	else				/* styles!			     */
X	    *interior = 2;
X	*bdc = (colorwd & 0xf000) >> 12;
X	
X	*width = LHIWD(obspec) & 0xff;
X	if (*width > 127)
X	    *width = 256 - *width;
X	
X	if (*width && !(*width & 0x1))		/* VDI only renders odd */
X	    (*width)--;				/* widths!		*/
X	
X	*chc = (colorwd & 0x0f00) >> 8;		/* used for select effect */
X}
X
XVOID				/* Fill a rounded rectangle	*/
Xrr_fill(mode, perim, color, interior, style, pxy)
XWORD	mode, perim, color, style, interior, *pxy;
X{
X	vswr_mode(vdi_handle, mode);
X	vsf_color(vdi_handle, color);
X	vsf_style(vdi_handle, style);
X	vsf_interior(vdi_handle, interior);
X	vsf_perimeter(vdi_handle, perim);
X	v_rfbox(vdi_handle, pxy);
X}
X.!
X.!****************************************************************************
X.!
X.!			End Appendix 9
X.!
X.!****************************************************************************
SHAR_EOF
if test 4655 -ne "`wc -c 'apndx9.prf'`"
then
	echo shar: error transmitting "'apndx9.prf'" '(should have been 4655 characters)'
fi
#	End of shell archive
exit 0
-- 
					Jwahar R. Bammi
			       Usenet:  .....!decvax!cwruecmp!bammi
			        CSnet:  bammi@case
				 Arpa:  bammi%case@csnet-relay
			   CompuServe:  71515,155