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