home *** CD-ROM | disk | FTP | other *** search
/ Falcon 030 Power 2 / F030_POWER2.iso / ST_STE / MAGS / ICTARI04.ARJ / ictari.04 / C / GEM_TUT / GEM.004 < prev    next >
Text File  |  1993-05-12  |  18KB  |  334 lines

  1.                        **Professional GEM**
  2.                            by Tim Oren
  3.  
  4.                              11/7/85
  5.  
  6.  
  7.    Welcome to the fourth installment of ST PRO GEM.  We are about to
  8. delve into the mysteries of GEM resource structure, and then use this
  9. knowledge to create some useful utilities for handling dialogs.  As
  10. with the past columns, there is once again a download file.  You will
  11. find it under the name GEMCL4.C in the ATARI 16-bit Forum (GO PCS-58).
  12.  
  13.    The first and largest part of the download contains a C image of a
  14. sample resource file.  To create this listing, I used the GEM
  15. Resource  Construction Set to create a dummy resource with three
  16. dialogs including examples of all object types, then enabled the C
  17. output option and saved  the resource.  If you have access to a copy
  18. of RCS, I suggest that you  create your own listing in order to get a
  19. feel for the results.  Then, using  either listing as a roadmap to
  20. the resource, you can follow along as  we enter...
  21.  
  22.    A MAZE OF TWISTY LITTLE PASSAGES.  While a GEM resource is loaded
  23. as a block of binary information, it is actually composed of a number
  24. of different data structures.  These structures are linked together
  25. in a rather tangled hierarchy.  Our first job is to map this linkage
  26. system.
  27.  
  28.    The topmost structure in a resource file is the resource header.
  29. This is an array of words containing the size and offset within the
  30. resource of the other structures which follow.  This information is
  31. used by  GEM during the resource load process, and you should never
  32. need to access it. (The resource header does not appear in the C
  33. output file; it is generated by the RSCREATE utility if the C file is
  34. used to recreate the resource.)
  35.  
  36.    The next structure of interest is the tree index.  This is an
  37. array of long pointers, each of which addresses the beginning of an
  38. object tree. Again, you wouldn't normally access this structure
  39. directly.  The GEM  rsrc_gaddr call uses it when finding trees'
  40. addresses.  This structure is called "rs_trindex" in the C output.
  41.  
  42.    If you look at the contents of rs_trindex you will notice that the
  43. values are integers, instead of the pointers I described.  What has
  44. happened is that RCS has converted the pointers to indices into the
  45. object array. (If you actually used the C file to recreate the
  46. resource file, then the  pointers would be regenerated by RSCREATE.)
  47.  
  48.  
  49.    Now you can follow the link from rs_trindex to the objects stored
  50. in rs_object.  Take (for instance) the second entry in rs_trindex and
  51. count down that many lines in rs_object.  The following line (object)
  52. should start with a -1.  This indicates that it is the root object of
  53. a tree.  The following objects down to the next root belong to that
  54. tree. We'll pass over the details of inter-object linkage for now,
  55. leaving it for a later column.
  56.  
  57.    There are a number of different fields in an object, but right now
  58. we'll concentrate on two of them: OB_TYPE and OB_SPEC.  The OB_TYPE
  59. is the field which contains mnemonics like G_STRING and G_BOX
  60. indicating the type of the object.  The OB_SPEC is the only field in
  61. each object which  is a LONG - you can tell it by the L after the
  62. number.
  63.  
  64.    What's in OB_SPEC depends on the object type, so we need to talk
  65. about what kinds of objects are available, what you might use them
  66. for, and finally how they use the OB_SPEC field.
  67.  
  68.    The box type objects are G_BOX, G_IBOX, and G_BOXCHAR.  A G_BOX is
  69. an opaque rectangle, with an optional border.  It's used to create a
  70. solid patch of color or pattern on which to place other objects.  For
  71. instance, the background of a dialog is a G_BOX.
  72.  
  73.    A G_IBOX is a hollow box which has only a border.  (If the border
  74. has no thickness, then the box is "invisible", hence the name.)  The
  75. favorite use for IBOXes is to hold radio buttons.  There is also one
  76. neat trick you can play with an IBOX.  If you have more than one
  77. object (say an image and a string) which you would like to have
  78. selected all at once, you can insert them in a dialog, then cover
  79. them with an IBOX. Since the box is transparent, they will show
  80. through.  If you now make the box selectable, clicking on it will
  81. highlight the whole area at once!
  82.  
  83.    The G_BOXCHAR is just like a G_BOX, except that a single character
  84. is drawn in its center.  They are mostly used as "control points":
  85. the FULLER, CLOSER, SIZER, and arrows in GEM windows are BOXCHARs, as
  86. are  the components of the color selection gadgets in the RCS.
  87.  
  88.    The OB_SPEC for box type objects is a packed bit array.  Its
  89. various fields contain the background color and pattern, the border
  90. thickness and color, and the optional character and its color.
  91.  
  92.    The string type objects are G_STRING, G_BUTTON, and G_TITLE.
  93. G_STRINGs (in addition to being a bad pun) are for setting up static
  94. explanatory text within dialogs.  The characters are always written
  95. in the "system font": full size, black, with no special effects.
  96.  
  97.    We have already discussed many of the uses of G_BUTTONs.  They add
  98. a border around the text.  The thickness of a G_BUTTON's border is
  99. determined by what flags are set for the object.  All buttons start
  100. out with a border thickness of one pixel.  One pixel is added if the
  101. EXIT attribute is set, and one more is added if the DEFAULT attribute
  102. is set.
  103.  
  104.    The G_TITLE type is a specially formatted text string used only in
  105. the title bar of menus.  This type is needed to make sure that the
  106. menus redraw correctly.  The Resource Construction Set automatically
  107. handles inserting G_TITLEs, so you will seldom use them directly.
  108.  
  109.    In a resource, the OB_SPEC for all string objects is a long
  110. pointer to a null terminated ASCII string.  The string data in the C
  111. file is shown in the BYTE array rs_strings.  Again you will notice
  112. that  the OB_SPECs in the C file have been converted to indices into
  113. rs_string. To find the string which matches the object, take the
  114. value of OB_SPEC and count down that many lines in rs_strings.  The
  115. next line is the correct string.
  116.  
  117.    The formatted text object types are G_TEXT, G_BOXTEXT, G_FTEXT,
  118. and G_FBOXTEXT.  G_TEXTs are a lot like strings, except that you can
  119. specify a color, different sizes, and a positioning rule for the
  120. text.   Since they require more memory than G_STRINGs, G_TEXTs should
  121. be used  sparingly to draw attention to important information within
  122. a dialog.   G_TEXTs are also useful for automatic centering of dialog
  123. text which is  changed at run-time.  I will describe this technique
  124. in detail later on.
  125.  
  126.    The G_BOXTEXT type adds a solid background and border to the
  127. G_TEXT type.  These objects are occasionally used in place of
  128. G_BUTTONs when their color will draw attention to an important
  129. object.
  130.  
  131.    The G_FTEXT object is an editable text field.  You are able to
  132. specify a constant "template" of characters, a validation field for
  133. those characters which are to be typed in, and an initial value for
  134. the input characters.  You may also select color, size, and
  135. positioning rule for G_FTEXTs.  We'll discuss text editing at length
  136. below.
  137.  
  138.    The G_FBOXTEXT object, as you might suspect, is the same as
  139. G_FTEXT with the addition of background and border.  This type is
  140. seldom used: the extra appearance details distract attention from the
  141. text being edited.
  142.  
  143.    The OB_SPEC for a formatted text object is a pointer to yet
  144. another type of structure: a TEDINFO.  In the C file, you will find
  145. these in rs_tedinfo.  Take the OB_SPEC value from each text type
  146. object and count down that many entries in rs_tedinfo, finding the
  147. matching TEDINFO on the next line.  Each contains pointers to ASCII
  148. strings for the template, validation, and initialization.  You can
  149. find these strings in rs_strings, just as above.
  150.  
  151.    There are also fields for the optional background and border
  152. details, and for the length of the template and text.  As we will see
  153. when discussing  editing, the most important TEDINFO fields are the
  154. TE_PTEXT pointer to  initialized text and the TE_TXTLEN field which
  155. gives its length.
  156.  
  157.    The G_IMAGE object type is the only one of its kind.  A G_IMAGE is
  158. a monochrome bit image.  For examples, see the images within the
  159. various GEM alert boxes.  Note that monochrome does not necessarily
  160. mean black.  The image may be any color, but all parts of it are the
  161. SAME color.  G_IMAGEs are used as visual cues in dialogs.  They are
  162. seldom used as selectable items because their entire rectangle is
  163. inverted when they are clicked.  This effect is seldom visually
  164. pleasing, particularly if the image is colored.
  165.  
  166.    G_IMAGE objects have an OB_SPEC which is a pointer to a further
  167. structure type: the BITBLK.  By now, you should guess that you will
  168. find it in the C file in the array rs_bitblk.  The BITBLK contains
  169. fields describing the height and width of the image in pixels, its
  170. color,nd it also contains a long pointer to the actual bits which
  171. make up the image.  In the C file, the images are encoded as
  172. hexadecimal words and stored in arrays named IMAG0, IMAG1, and so on.
  173.  
  174.    The last type of object is the G_ICON.  Like the G_IMAGE, the
  175. G_ICON is a bit image, but it adds a mask array which selects what
  176. portions of the image will be drawn, as well as an explanatory text
  177. field.  A G_ICON may also specify different colors for its
  178. "foreground" pixels (the ones that are normally black), and its
  179. "background" pixels (which are normally white).
  180.  
  181.    The pictures which you see in Desktop windows are G_ICONs, and so
  182. are the disks and trashcan on the desktop surface.  With the latter
  183. you will notice the effects of the mask.  The desktop shows through
  184. right up to the edge of the G_ICON, and only the icon itself (not a
  185. rectangle) is inverted when a disk is selected.
  186.  
  187.    The OB_SPEC of an icon points to another structure called an
  188. ICONBLK.  It is shown in the C file as rs_iconblk.  The ICONBLK
  189. contains long pointers to its foreground bit array, to the mask bit
  190. array, and to the ASCII string of explanatory text.  It also has the
  191. foreground and background colors as well as the location of the text
  192. area from the  upper left of the icon.  The most common use of
  193. G_ICONs and ICONBLKs  is not in dialogs, instead they are used
  194. frequently in trees which are build at run-time, such as Desktop
  195. windows.  In a future article, we will return to a discussion of
  196. building such "on-the-fly" trees with G_ICONs.
  197.  
  198.    Now, let's recap the hierarchy of resource structures:  The
  199. highest level structures are the resource header, and then the tree
  200. index.  The tree index points to the beginning of each object tree.
  201. The objects making up the tree are of several types, and depending on
  202. that type, they may contain pointers to ASCII strings, or to TEDINFO,
  203. ICONBLK, or BITBLK structures.  TEDINFOs contain further pointers to
  204. strings; BITBLKs have pointers to bit images; and ICONBLKs have both.
  205.  
  206.    PUTTING IT TO WORK.  The most common situations requiring you to
  207. understand resource structures involve the use of text and editable
  208. text objects in dialogs.  We'll look at two such techniques.
  209.  
  210.    Often an application requires two or more dialogs which are very
  211. similar except for one or two title lines.  In this circumstance, you
  212. can save a good deal of resource space by building only one dialog,
  213. and changing the title at run time.
  214.  
  215.    It is easy to go wrong with this practice, however, because the
  216. obvious tactic of using a G_STRING and writing over its text at run
  217. time can go wrong.  The first problem is that you must know in
  218. advance the longest title to be used, and put a string that long into
  219. the resource. If you don't you will damage other objects in the
  220. resource as you copy in characters.  The other problem is that a
  221. G_STRING is always drawn at the same place in a dialog.  If the
  222. length of the title changes from time to time, the dialog will have
  223. an unbalanced and sloppy  appearance.
  224.  
  225.    A better way to do this is to exploit the G_TEXT object type, and
  226. the TEDINFO structure.  The set_text() routine in the download shows
  227. how.  The parameters provided are the tree address, the object
  228. number, and the 32-bit address of the string to be substituted.  For
  229. this to work, the object referenced should be defined as a G_TEXT
  230. type object.   Additionally, the Centered text type should be chosen,
  231. and the object should have been "stretched" so that it fills the
  232. dialog box from side to side.
  233.  
  234.    In the code, the first action is to get the OB_SPEC from the
  235. object which was referenced.  Since we know that the object is a
  236. G_TEXT, the OB_SPEC must point to a TEDINFO.  We need to change two
  237. fields in the TEDINFO.  The TE_PTEXT field is the pointer to the
  238. actual string to be displayed; we replace it with the address of our
  239. new string. The TE_TXTLEN field is loaded with the new string's
  240. length.  Since the Centered attribute was specified for the object,
  241. changing the TE_TXTLEN will cause the string to be correctly
  242. positioned in the middle of the dialog!
  243.  
  244.    Editing text also requires working with the TEDINFO structure. One
  245. way of doing this is shown in the download.  The object to be used
  246. (EDITOBJ) is assumed to be a G_FTEXT or G_FBOXTEXT.  Since we will
  247. replace the initialized text at run time, that field may be left
  248. empty when building the object in the RCS.
  249.  
  250.    The basic trick of this code is to point the TEDINFO's TE_PTEXT at
  251. a string which is defined in your code's local stack.  The advantages
  252. of this technique are that you save resource space, save static data
  253. by putting the string in reusable stack memory, and automatically
  254. create a scratch string which may be discarded if the dialog is
  255. cancelled.
  256.  
  257.    The text string shown is arbitrarily 41 characters long.  You
  258. should give yours a length equal to the number of blanks in the
  259. object's template field plus one.  Note that the code is shown as a
  260. segment,  rather than a subroutine.  This is required because the
  261. text string must be allocated within the context of dialog handling
  262. routine itself,  rather than a routine which it calls!
  263.  
  264.    After the tree address is found, the code proceeds to find the
  265. TEDINFO and modify its TE_PTEXT as described above.  However, the
  266. length which is inserted into TE_TXTLEN must be the maximum string
  267. length,  including the null!
  268.  
  269.    The final line of code inserts a null into the first character of
  270. the uninitialized string.  This will produce an empty editing field
  271. when the dialog is displayed.  If there is an existing value for  the
  272. object, you should instead use strcpy() to move it into text[]. Once
  273. the dialog is complete, you should check its final status as
  274. described in the last article.  If an "OK" button was clicked, you
  275. will then use strcpy() to move the value in text[] back to its static
  276. location.
  277.  
  278.    Although I prefer this method of handling editable text, another
  279. method deserves mention also.  This procedure allocates a full length
  280. text string of blanks when creating the editable object in the RCS.
  281. At  run-time, the TE_PTEXT link is followed to find this string's
  282. location in  the resource, and any pre-existing value is copied in.
  283. After the dialog is run, the resulting value is copied back out if
  284. the dialog completed successfully.
  285.  
  286.    Note that in both editing techniques a copy of the current string
  287. value is kept within the application's data area.  Threading the
  288. resource whenever you need to check a string's value is extremely
  289. wasteful.
  290.  
  291.    One final note on editable text objects:  GEM's editor uses the
  292. commercial at sign '@' as a "meta-character".  If it is the first
  293. byte of the initialized text, then the field is displayed blank no
  294. matter what follows.  This can be useful, but is sometimes confusing
  295. when a user in all innocence enters an @ and has his text disappear
  296. the next time the dialog is drawn!
  297.  
  298.    LETTERS, WE GET LETTERS.  The Feedback section on ANTIC ST ONLINE
  299. is now functional and is producing a gratifying volume of response. A
  300. number of requests were made for topics such as ST hardware and ST
  301. BASIC which are beyond the intended scope of this column.  These have
  302. been referred to ANTIC's editorial staff for action.
  303.  
  304.    So many good GEM questions were received that I will devote part
  305. of the next column to answering several of general interest.  Also,
  306. your  requests have resulting in scheduling future columns on VDI
  307. text output  and on the principles (or mythology) of designing GEM
  308. application interfaces. Finally, a tip of the hat to the anonymous
  309. reader who suggested including the actual definitions of all macro
  310. symbols, so that those without the appropriate H files can follow
  311. along.  As a result of this suggestion, the definitions for this
  312. column and the previous three are included at the end of the
  313. download.  Future articles will continue this practice.
  314.  
  315.    STRAW POLL!  I'd like to make a practice of using the Feedback to
  316. get your opinions on the column's format.  As a first trial, I'd like
  317. to know your feelings about my use of "portability macros" in the
  318. sample code.  These macros, LLGET for example, are used for
  319. compatibility between 68K GEM systems like the ST, and Intel based
  320. systems like the IBM PC.  This may be important to many developers.
  321. On the other hand, omitting them results in more natural looking C
  322. code.  For instance, in the download you will find a second version
  323. of set_text() as  described above, but without the portability
  324. macros.  So, I would like to know if you think we should  (A) Keep
  325. the macros - portability is important to serious developers, (B) Get
  326. rid of them - who cares about Intel chips anyway, or (C) Who cares?
  327. I'll tally the votes in two weeks and announce the results here.
  328.  
  329.    STAY TUNED!  As well as answers to feedback questions, the next
  330. column will discuss how GEM objects are linked to form trees, and how
  331. to use AES calls and your own code to manipulate them for fun and
  332. profit.  In the following installment, we'll look at the VDI raster
  333. operations (also known as "blit" functions).
  334.