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