home *** CD-ROM | disk | FTP | other *** search
- **Professional GEM**
- by Tim Oren
-
- 11/7/85
-
-
- Welcome to the fourth installment of ST PRO GEM. We are about to
- delve into the mysteries of GEM resource structure, and then use this
- knowledge to create some useful utilities for handling dialogs. As
- with the past columns, there is once again a download file. You will
- find it under the name GEMCL4.C in the ATARI 16-bit Forum (GO PCS-58).
-
- The first and largest part of the download contains a C image of a
- sample resource file. To create this listing, I used the GEM
- Resource Construction Set to create a dummy resource with three
- dialogs including examples of all object types, then enabled the C
- output option and saved the resource. If you have access to a copy
- of RCS, I suggest that you create your own listing in order to get a
- feel for the results. Then, using either listing as a roadmap to
- the resource, you can follow along as we enter...
-
- A MAZE OF TWISTY LITTLE PASSAGES. While a GEM resource is loaded
- as a block of binary information, it is actually composed of a number
- of different data structures. These structures are linked together
- in a rather tangled hierarchy. Our first job is to map this linkage
- system.
-
- The topmost structure in a resource file is the resource header.
- This is an array of words containing the size and offset within the
- resource of the other structures which follow. This information is
- used by GEM during the resource load process, and you should never
- need to access it. (The resource header does not appear in the C
- output file; it is generated by the RSCREATE utility if the C file is
- used to recreate the resource.)
-
- The next structure of interest is the tree index. This is an
- array of long pointers, each of which addresses the beginning of an
- object tree. Again, you wouldn't normally access this structure
- directly. The GEM rsrc_gaddr call uses it when finding trees'
- addresses. This structure is called "rs_trindex" in the C output.
-
- If you look at the contents of rs_trindex you will notice that the
- values are integers, instead of the pointers I described. What has
- happened is that RCS has converted the pointers to indices into the
- object array. (If you actually used the C file to recreate the
- resource file, then the pointers would be regenerated by RSCREATE.)
-
-
- Now you can follow the link from rs_trindex to the objects stored
- in rs_object. Take (for instance) the second entry in rs_trindex and
- count down that many lines in rs_object. The following line (object)
- should start with a -1. This indicates that it is the root object of
- a tree. The following objects down to the next root belong to that
- tree. We'll pass over the details of inter-object linkage for now,
- leaving it for a later column.
-
- There are a number of different fields in an object, but right now
- we'll concentrate on two of them: OB_TYPE and OB_SPEC. The OB_TYPE
- is the field which contains mnemonics like G_STRING and G_BOX
- indicating the type of the object. The OB_SPEC is the only field in
- each object which is a LONG - you can tell it by the L after the
- number.
-
- What's in OB_SPEC depends on the object type, so we need to talk
- about what kinds of objects are available, what you might use them
- for, and finally how they use the OB_SPEC field.
-
- The box type objects are G_BOX, G_IBOX, and G_BOXCHAR. A G_BOX is
- an opaque rectangle, with an optional border. It's used to create a
- solid patch of color or pattern on which to place other objects. For
- instance, the background of a dialog is a G_BOX.
-
- A G_IBOX is a hollow box which has only a border. (If the border
- has no thickness, then the box is "invisible", hence the name.) The
- favorite use for IBOXes is to hold radio buttons. There is also one
- neat trick you can play with an IBOX. If you have more than one
- object (say an image and a string) which you would like to have
- selected all at once, you can insert them in a dialog, then cover
- them with an IBOX. Since the box is transparent, they will show
- through. If you now make the box selectable, clicking on it will
- highlight the whole area at once!
-
- The G_BOXCHAR is just like a G_BOX, except that a single character
- is drawn in its center. They are mostly used as "control points":
- the FULLER, CLOSER, SIZER, and arrows in GEM windows are BOXCHARs, as
- are the components of the color selection gadgets in the RCS.
-
- The OB_SPEC for box type objects is a packed bit array. Its
- various fields contain the background color and pattern, the border
- thickness and color, and the optional character and its color.
-
- The string type objects are G_STRING, G_BUTTON, and G_TITLE.
- G_STRINGs (in addition to being a bad pun) are for setting up static
- explanatory text within dialogs. The characters are always written
- in the "system font": full size, black, with no special effects.
-
- We have already discussed many of the uses of G_BUTTONs. They add
- a border around the text. The thickness of a G_BUTTON's border is
- determined by what flags are set for the object. All buttons start
- out with a border thickness of one pixel. One pixel is added if the
- EXIT attribute is set, and one more is added if the DEFAULT attribute
- is set.
-
- The G_TITLE type is a specially formatted text string used only in
- the title bar of menus. This type is needed to make sure that the
- menus redraw correctly. The Resource Construction Set automatically
- handles inserting G_TITLEs, so you will seldom use them directly.
-
- In a resource, the OB_SPEC for all string objects is a long
- pointer to a null terminated ASCII string. The string data in the C
- file is shown in the BYTE array rs_strings. Again you will notice
- that the OB_SPECs in the C file have been converted to indices into
- rs_string. To find the string which matches the object, take the
- value of OB_SPEC and count down that many lines in rs_strings. The
- next line is the correct string.
-
- The formatted text object types are G_TEXT, G_BOXTEXT, G_FTEXT,
- and G_FBOXTEXT. G_TEXTs are a lot like strings, except that you can
- specify a color, different sizes, and a positioning rule for the
- text. Since they require more memory than G_STRINGs, G_TEXTs should
- be used sparingly to draw attention to important information within
- a dialog. G_TEXTs are also useful for automatic centering of dialog
- text which is changed at run-time. I will describe this technique
- in detail later on.
-
- The G_BOXTEXT type adds a solid background and border to the
- G_TEXT type. These objects are occasionally used in place of
- G_BUTTONs when their color will draw attention to an important
- object.
-
- The G_FTEXT object is an editable text field. You are able to
- specify a constant "template" of characters, a validation field for
- those characters which are to be typed in, and an initial value for
- the input characters. You may also select color, size, and
- positioning rule for G_FTEXTs. We'll discuss text editing at length
- below.
-
- The G_FBOXTEXT object, as you might suspect, is the same as
- G_FTEXT with the addition of background and border. This type is
- seldom used: the extra appearance details distract attention from the
- text being edited.
-
- The OB_SPEC for a formatted text object is a pointer to yet
- another type of structure: a TEDINFO. In the C file, you will find
- these in rs_tedinfo. Take the OB_SPEC value from each text type
- object and count down that many entries in rs_tedinfo, finding the
- matching TEDINFO on the next line. Each contains pointers to ASCII
- strings for the template, validation, and initialization. You can
- find these strings in rs_strings, just as above.
-
- There are also fields for the optional background and border
- details, and for the length of the template and text. As we will see
- when discussing editing, the most important TEDINFO fields are the
- TE_PTEXT pointer to initialized text and the TE_TXTLEN field which
- gives its length.
-
- The G_IMAGE object type is the only one of its kind. A G_IMAGE is
- a monochrome bit image. For examples, see the images within the
- various GEM alert boxes. Note that monochrome does not necessarily
- mean black. The image may be any color, but all parts of it are the
- SAME color. G_IMAGEs are used as visual cues in dialogs. They are
- seldom used as selectable items because their entire rectangle is
- inverted when they are clicked. This effect is seldom visually
- pleasing, particularly if the image is colored.
-
- G_IMAGE objects have an OB_SPEC which is a pointer to a further
- structure type: the BITBLK. By now, you should guess that you will
- find it in the C file in the array rs_bitblk. The BITBLK contains
- fields describing the height and width of the image in pixels, its
- color,nd it also contains a long pointer to the actual bits which
- make up the image. In the C file, the images are encoded as
- hexadecimal words and stored in arrays named IMAG0, IMAG1, and so on.
-
- The last type of object is the G_ICON. Like the G_IMAGE, the
- G_ICON is a bit image, but it adds a mask array which selects what
- portions of the image will be drawn, as well as an explanatory text
- field. A G_ICON may also specify different colors for its
- "foreground" pixels (the ones that are normally black), and its
- "background" pixels (which are normally white).
-
- The pictures which you see in Desktop windows are G_ICONs, and so
- are the disks and trashcan on the desktop surface. With the latter
- you will notice the effects of the mask. The desktop shows through
- right up to the edge of the G_ICON, and only the icon itself (not a
- rectangle) is inverted when a disk is selected.
-
- The OB_SPEC of an icon points to another structure called an
- ICONBLK. It is shown in the C file as rs_iconblk. The ICONBLK
- contains long pointers to its foreground bit array, to the mask bit
- array, and to the ASCII string of explanatory text. It also has the
- foreground and background colors as well as the location of the text
- area from the upper left of the icon. The most common use of
- G_ICONs and ICONBLKs is not in dialogs, instead they are used
- frequently in trees which are build at run-time, such as Desktop
- windows. In a future article, we will return to a discussion of
- building such "on-the-fly" trees with G_ICONs.
-
- Now, let's recap the hierarchy of resource structures: The
- highest level structures are the resource header, and then the tree
- index. The tree index points to the beginning of each object tree.
- The objects making up the tree are of several types, and depending on
- that type, they may contain pointers to ASCII strings, or to TEDINFO,
- ICONBLK, or BITBLK structures. TEDINFOs contain further pointers to
- strings; BITBLKs have pointers to bit images; and ICONBLKs have both.
-
- PUTTING IT TO WORK. The most common situations requiring you to
- understand resource structures involve the use of text and editable
- text objects in dialogs. We'll look at two such techniques.
-
- Often an application requires two or more dialogs which are very
- similar except for one or two title lines. In this circumstance, you
- can save a good deal of resource space by building only one dialog,
- and changing the title at run time.
-
- It is easy to go wrong with this practice, however, because the
- obvious tactic of using a G_STRING and writing over its text at run
- time can go wrong. The first problem is that you must know in
- advance the longest title to be used, and put a string that long into
- the resource. If you don't you will damage other objects in the
- resource as you copy in characters. The other problem is that a
- G_STRING is always drawn at the same place in a dialog. If the
- length of the title changes from time to time, the dialog will have
- an unbalanced and sloppy appearance.
-
- A better way to do this is to exploit the G_TEXT object type, and
- the TEDINFO structure. The set_text() routine in the download shows
- how. The parameters provided are the tree address, the object
- number, and the 32-bit address of the string to be substituted. For
- this to work, the object referenced should be defined as a G_TEXT
- type object. Additionally, the Centered text type should be chosen,
- and the object should have been "stretched" so that it fills the
- dialog box from side to side.
-
- In the code, the first action is to get the OB_SPEC from the
- object which was referenced. Since we know that the object is a
- G_TEXT, the OB_SPEC must point to a TEDINFO. We need to change two
- fields in the TEDINFO. The TE_PTEXT field is the pointer to the
- actual string to be displayed; we replace it with the address of our
- new string. The TE_TXTLEN field is loaded with the new string's
- length. Since the Centered attribute was specified for the object,
- changing the TE_TXTLEN will cause the string to be correctly
- positioned in the middle of the dialog!
-
- Editing text also requires working with the TEDINFO structure. One
- way of doing this is shown in the download. The object to be used
- (EDITOBJ) is assumed to be a G_FTEXT or G_FBOXTEXT. Since we will
- replace the initialized text at run time, that field may be left
- empty when building the object in the RCS.
-
- The basic trick of this code is to point the TEDINFO's TE_PTEXT at
- a string which is defined in your code's local stack. The advantages
- of this technique are that you save resource space, save static data
- by putting the string in reusable stack memory, and automatically
- create a scratch string which may be discarded if the dialog is
- cancelled.
-
- The text string shown is arbitrarily 41 characters long. You
- should give yours a length equal to the number of blanks in the
- object's template field plus one. Note that the code is shown as a
- segment, rather than a subroutine. This is required because the
- text string must be allocated within the context of dialog handling
- routine itself, rather than a routine which it calls!
-
- After the tree address is found, the code proceeds to find the
- TEDINFO and modify its TE_PTEXT as described above. However, the
- length which is inserted into TE_TXTLEN must be the maximum string
- length, including the null!
-
- The final line of code inserts a null into the first character of
- the uninitialized string. This will produce an empty editing field
- when the dialog is displayed. If there is an existing value for the
- object, you should instead use strcpy() to move it into text[]. Once
- the dialog is complete, you should check its final status as
- described in the last article. If an "OK" button was clicked, you
- will then use strcpy() to move the value in text[] back to its static
- location.
-
- Although I prefer this method of handling editable text, another
- method deserves mention also. This procedure allocates a full length
- text string of blanks when creating the editable object in the RCS.
- At run-time, the TE_PTEXT link is followed to find this string's
- location in the resource, and any pre-existing value is copied in.
- After the dialog is run, the resulting value is copied back out if
- the dialog completed successfully.
-
- Note that in both editing techniques a copy of the current string
- value is kept within the application's data area. Threading the
- resource whenever you need to check a string's value is extremely
- wasteful.
-
- One final note on editable text objects: GEM's editor uses the
- commercial at sign '@' as a "meta-character". If it is the first
- byte of the initialized text, then the field is displayed blank no
- matter what follows. This can be useful, but is sometimes confusing
- when a user in all innocence enters an @ and has his text disappear
- the next time the dialog is drawn!
-
- LETTERS, WE GET LETTERS. The Feedback section on ANTIC ST ONLINE
- is now functional and is producing a gratifying volume of response. A
- number of requests were made for topics such as ST hardware and ST
- BASIC which are beyond the intended scope of this column. These have
- been referred to ANTIC's editorial staff for action.
-
- So many good GEM questions were received that I will devote part
- of the next column to answering several of general interest. Also,
- your requests have resulting in scheduling future columns on VDI
- text output and on the principles (or mythology) of designing GEM
- application interfaces. Finally, a tip of the hat to the anonymous
- reader who suggested including the actual definitions of all macro
- symbols, so that those without the appropriate H files can follow
- along. As a result of this suggestion, the definitions for this
- column and the previous three are included at the end of the
- download. Future articles will continue this practice.
-
- STRAW POLL! I'd like to make a practice of using the Feedback to
- get your opinions on the column's format. As a first trial, I'd like
- to know your feelings about my use of "portability macros" in the
- sample code. These macros, LLGET for example, are used for
- compatibility between 68K GEM systems like the ST, and Intel based
- systems like the IBM PC. This may be important to many developers.
- On the other hand, omitting them results in more natural looking C
- code. For instance, in the download you will find a second version
- of set_text() as described above, but without the portability
- macros. So, I would like to know if you think we should (A) Keep
- the macros - portability is important to serious developers, (B) Get
- rid of them - who cares about Intel chips anyway, or (C) Who cares?
- I'll tally the votes in two weeks and announce the results here.
-
- STAY TUNED! As well as answers to feedback questions, the next
- column will discuss how GEM objects are linked to form trees, and how
- to use AES calls and your own code to manipulate them for fun and
- profit. In the following installment, we'll look at the VDI raster
- operations (also known as "blit" functions).
-
-
-