GEM OBJECTS AND RESOURCES ========================= By: M†rten Lindstr”m This text just about sums up what I presently know about the subject and comes from many sources, perhaps most important of which are articles in the 'ST Magazin' - a German ST magazine now unfortunately dead. For the info about colour icons I admit to have drawn exclusively on the Atari Compendium. (I haven't got a TOS version capable of dealing with colour icons so with them I lack experiences of my own.) Any further info - or corrections - most welcome! ABBREVIATIONS: In the descriptions below I have used the following abbreviations: N = Nybble = half a byte (i.e. 4 bits or 1 hexadecimal digit) B = Byte W = Word = 2 bytes L = Longword = 4 bytes POINTERS: All pointers and address offsets in an RSC file are, on disk, relative to file start. Before use in memory, longword pointers have to be relocated, i.e. the file start address added to each pointer. This is done automati- cally by RSRC_LOAD. If you don't use RSRC_LOAD, but include an RSC file directly in your program code during assembly/compilation, you will have to make sure that the relocation is done by other means. One L pointer can be found at offset 12 in each object structure, except in those of the simple box types (20, 25 and 27). In a resource with images or formatted text objects, further pointers can be found in other structures (TEDINFO, BITBLK, ICONBLK). See more below. Note that WORD offsets are UNSIGNED, which means that they can be up to 64K (and also, in assembler terms, that a single Motorola instruction isn't enough to add them to the RSC base address; instead you have to load them in a cleared data register and add this - as a long - to the base address). MEASURES: Coordinates and dimensions are, in an RSC file on disk, measured in CHARACTERS, but note that the higher ordered byte is reserved for extra pixels; i.e. a height of $301 is to be read as 1 full character plus 3 extra pixels. (The exception is measures within the BITBLK and ICONBLK secondary structures for images and icons - see below.) When in use in memory, however, all measures are in PIXELS. So in ST colour resolutions a height of $301 will have been converted into 11 (8+3) while in ST high rez the same disk based height will have become 19 (16+3). You normally don't have to worry too much about how this conversion is performed since the AES will do it for you, either during RSC file loading with RSRC_LOAD, or you can call the function RSRC_OBFIX for each object. But it still is worth knowing. COLOURS: Any colour definition, in objects or secondary structures, is always contained in ONE NYBBLE. This gives a range of 16 possible colours: 0=White, 1=Black, 2=Red, 3=Green, 4=Blue, 5=Cyan, 6=Yellow, 7=Magenta 8=Light, 9=Dark, 10=Light, 11=Light, 12=Light, 13=Light, 14=Light, 15=Light gray gray red green blue cyan yellow magenta OBJECTS AND TREES: A GEM object is, on the screen, a box. The box can be invisible, can contain text, fill patterns etc. and can in some cases be assigned the function as a button to be clicked on. A GEM object tree is, on the screen, a collection of boxes within each other, together forming a dialogue box or a menu. Each of the inner boxes is termed 'CHILD' of the next outer box - the 'PARENT' - containing it. The outermost box is called the 'ROOT' of the tree. In program memory, or in a file, an object is a 12-word structure (24 bytes) which may contain a pointer to either a text string or to further structures. A tree, in program memory, is simply a list of object structures, the first of which is the root object, provided that the relational data for all objects are sensible. Each object is assigned a number according to its place in the tree object list (root=0), and these numbers are used in the relational data. The first word of each object specifies the next sibling or, for the last sibling, parent (or -1 for the root which has neither siblings nor parent). And word 2 and 3 give the first and last child of the object (-1 for childless objects). NOTE: Some experiments that I have made seem to indicate that not only do the objects of a tree need to be listed in one uninterrupted list of object specifications (the first of which must be the 'progenitor'), but the same applies for all 'sub-trees' within the tree. I.e. all children, 'grand- children' etc. of an object need to be listed immediately after itself and before a sibling or any of its offspring is listed. RESOURCE FILES: Anyone can create object trees directly in the source text of a program, in which case the one and only requirement on the order of the structures is the one just mentioned (for objects belonging to the same tree). As long as all pointers are right, different trees can be placed wherever desired, and so can all the other, secondary, structures. However, as a convenience, a set of AES routines exists to deal with a collection of many object trees with associated structures, strings and images placed together in an RSC FILE. The RSC file in addition has room for so called 'free' strings and images - i.e. not associated with the object-related structures; this makes it possible to include for instance alertbox definitions as well in an RSC file - as free strings. When an RSC file is loaded with RSRC_LOAD two modifications to the file data are, as mentioned, made automatically: 1) All measures are converted from CHARACTERS into PIXELS. 2) All Long pointers are relocated. Not using RSC_LOAD means these modifications must be made some other way. What is NOT made automatically is conversion of IMAGES/ICONS (apparently with the of exception colour icons in TOS 4) from the VDI standard format, used in the RSC file, into device specific format. This isn't a big problem since the images are 'monochrome' (1 plane images), which means that errors could occur only with certain graphic cards. Still, a perfectionist should let the VDI function VR_TRNFM have a go with each mono image in the RSC file. FORMAT OF RSC FILES ------------------- (All offsets are relative to file start, and UNSIGNED) HEADER: (18 words) W: RCS version number: bit 2 set => TOS 4+ (i.e. 0 or 1 = old, 4 = new) W: Offset to first object W: Offset to first TEDINFO (secondary structure for formatted text string) W: Offset to first ICONBLK (secondary structure for icon) W: Offset to first BITBLK (secondary structure for simple image) W: Offset to pointer table (L) - free strings (typically alertbox strings) W: Offset to first string - free or not W: Offset to first image data (or mask) - free or not W: Offset to pointer table (L) - free images W: Offset to pointer table (L) - object trees (i.e. root objects) W: Number of objects W: Number of trees W: Number of TEDINFOs W: Number of ICONBLKs W: Number of BITBLKs W: Number of free strings W: Number of free images W: File length in bytes (or offset to TOS 4+ extension see v number above) After this the structures come, apparently always in the following order (this order shouldn't be a requirement, but you never know): Strings (null-ended) Images BITBLKs (14 bytes each) ICONBLKs (34 bytes each) TEDINFOs (28 bytes each) Objects (trees) (24 bytes/object) Table of pointers (L) to object trees (i.e. to root objects) Table of pointers (L) to free strings Table of pointers (L) to free images The whole pre-TOS4 RSC file must always be less than 64K in size (since the file length is given in just a WORD in the header). --------------- EXTENSION (TOS 4+) may follow after above structures (see v number above): L: REAL length of the RSC file (no longer any 64K limit) L: Pointer to 'pointer table' to CICONBLKs (for colour icons) ?L: Possible further pointers which however not yet are defined. -1 = 'Empty' pointer; 0 = No more pointers The pointers in the CICONBLK pointer table can actually be zeroed in the file, since when loading with RSRC_LOAD they will automatically be filled in. (This is possible for the AES to do because the CICONBLKs are - in an RSC file - REQUIRED to follow directly on the pointer table.) The pointer table is ended with a -1. So the actual structure, to which the pointer in the second longword of the extension is pointing, looks like this in an RSC file on disk: L: 0 (= there is a first CICONBLK following this table) L: 0 (= there is a second CICONBLK following this table) ... etc. L: -1 = no more CICONBLKs 1st CICONBLK (and its related structures - se below) 2nd CICONBLK ( - " - ) OBJECTS ------- Each OBJECT is built as follows (12 words = 24 bytes): W: # of next sibling object (for last child: # of parent; for root: -1) W: # of first child object (or -1 for childless object) W: # of last child object (or -1 for childless object) W: Object type. B: 'Extended type', program definable. B: Basic object type (20-33) used by system - see below. W: Flags - bit 0: Selectable (in dialogue boxes; not used for menu items) 1: Default (= selectable through RETURN key) 2: EXIT (when left mouse button pressed and released) 3: Editable (Set in G_FTEXT and G_FBOXTEXT objects) 4: Radio button (= deselects sibling radio buttons) 5: Last object of tree (in object list). IMPORTANT BIT! 6: TOUCHEXIT (immediately when left mouse button pressed) 7: This and subordinate objects hidden/ignored (See below) 8: Further indirection of object spec. (Not normally used) TOS 4+ only: 9: 3D 'indicator' (for radio buttons & on/off buttons) 10: 3D 'activator' (for exit buttons) BOTH 9&10 set: 3D background obj. => any OUTLINE in 3D, plus if fill colour = white and fill pattern = 0 replace with default 3D BG colour. 11: Sub-menu attached (for menu items only) W: State - bit 0: Selected (Drawn in inverse video) 1: Crossed (with WHITE lines) 2: Checked (Check mark to the (upper) left) 3: Disabled (Any text written in light style) 4: Outlined ((Extra) border drawn around object) 5: Shadowed (down and right) L: Object specification: 1) Simple B: Character (for G_BOXCHAR - object type 27), or zero boxes B: Border thickness (0=none,positive=inwards,neg.=outw.) possibly N: Border colour with N: Text colour single N: Fill level (0-7) +8 for any opaque (white) char. backgr character N: Fill colour 2) For other objects the specification is a pointer to either a simple text string, or to a further structure with more data (see below). W: X coordinate relative to the parent W: Y coordinate relative to the parent W: Width W: Height -------- 12 words (24 bytes) OBJECT TYPES: Object spec Boxes: 20. G_BOX see above 25. G_IBOX Invisible see above 27. G_BOXCHAR With single character see above Simple text: 26. G_BUTTON Centred in box -> string 28. G_STRING -> string 32. G_TITLE Menu title -> string Formatted text: 21. G_TEXT -> TEDINFO 22. G_BOXTEXT In box -> TEDINFO 29. G_FTEXT Editable -> TEDINFO 30. G_FBOXTEXT Editable in box -> TEDINFO Images: 23. G_IMAGE -> BITBLK 31. G_ICON with mask + possib. text -> ICONBLK 33. G_CICON Ditto in colour (TOS 4) -> CICONBLK Special objects: 24. G_PROGDEF Freely definable -> APPLBLK If the indirection flag (bit 8 of flag word) is set, each of the above object specifications is replaced with A POINTER TO the respective specification. (This would for most objects mean a pointer to a pointer). The indirection flag seems however to be rarely used (and never in an RSC file). THE EXTENDED TYPE (the upper type byte) is free to be used for any program- defined purpose. For instance a justification code could be placed here, telling the program to justify (left, right, centre) an object (string) within its parent before use. Other codes could instruct the program to change the object into a G_PROGDEF. NOTE: Objects of type G_PROGDEF never occur in RSC files, but are always set up by the program. Typically the to-be-G_PROGDEF object is stored in the RSC file as one of the other standard type objects, but with the upper type byte (extended type) filled in as well - with some value that only the program will understand and use to translate the object into a G_PROGDEF with a suitable APPLBLK. This is the way that a program can have dialogue boxes with round buttons, or buttons that when selected become crossed instead of shown inverse video etc. EDITABLE OBJECTS - BUGS: Only in objects of types 29 or 30 (G_FTEXT and G_FBOXTEXT) should the editable flag (bit 3) normally be set. It tells the AES in what objects to place any cursor for text editing. Unfortunately there are (in earlier TOS versions) two bugs connected to this flag: 1) Editable last object: One bug shows itself when an editable object is also the last one in the object list for a tree (in which case the vitally important last-object bit should be set). The object won't be found by TOS when moving the cursor around with the keys. (TOS simply reads and acts upon the last-object bit before it does the editable bit.) The solution is however very simple. Just make sure the last object never is editable, if need be by adding a further little invisible box to the end of the list. 2) Editable hidden objects: The other bug makes itself known when an editable object is 'hidden' - i.e. when the 'hidden bit' (bit 7 in flag word) is set in either the object itself or in one of its 'ancestors'. The whole sub-tree, originating in an object with its hidden bit set, should be invisible and ignored, but TOS does NOT ignore editable objects when moving the cursor around with the keys. The idea (or at least one of them) behind hidden sub-trees is to make possible alternative sub-trees between which could be easily toggled without the need for a complete rearrangement of the tree. A cure for the bug proposed in ST Magazin (by Laurenz Práner in issue 6/92 of this now extinct German magazine) is a sub-routine that clears any editable bits in a hidden sub-tree, plus another routine that restores these bits when the sub-tree is made unhidden again. The objects on which to perform these manipulations should I think be exactly the objects of types 29 or 30. (Laurenz Práner proposes another method to mark objects to manipulate - making use of one of the currently unused flag bits - but this I think would be more prone to cause future incompatibility problems.) TREES ----- An object tree is stored as a list of object structures, and each object is identified by its order number in this list. The root object is always the first object and is assigned the number zero. The last object in the list must have its last-object flag set (bit 5 in flag word at offset 8 or in the BYTE at offset 9 from object start). MENUS: Whereas the construction of a dialogue box is restrained by very few rules, menu object trees always look like follows (I have used line graphics here - if you don't use a PC or Protext, use PC_LINES.PRG to get them right on screen): ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄ´ TITLE: G_TITLE ³ ³ MENU BAR: ³ ³ ACTIVE: G_IBOX ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ G_BOX, but ³ ³ X=2, Y=0, H= ³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄ´ no fill or ÃÄ´ $301, W=enough ÃÄÅÄ´ TITLE: G_TITLE ³ ³ ³ border,X=0 ³ ³ for the titles,³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ Y=0,H=$201 ³ ³ not more ³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄ´ TITLE: G_TITLE ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÄÄÄ¿ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ MENU: ³ ³ ÚÄ´ MENU ITEM: G_STRING ³ ³ I_BOX ³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ Extent: ÃÄ´ ³ DROPBOX: G_BOX ³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Screen ³ ³ ³ Border thick- ÃÄÅÄ´ MENU ITEM: G_STRING ³ ÀÄÄÄÄÄÄÄÄÄÙ ³ ÚÄ´ ness = -1, ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³ Big enough for ³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ ³ its menu items ³ ÀÄ´ MENU ITEM: G_STRING ³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ DROP AREA: ³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ G_IBOX, ³ ³ ³ DROPBOX: G_BOX ³ ÚÄ´ MENU ITEM: G_STRING ³ ³ ³ Y=$301, ³ ³ ³ Border thick- ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄ´ Extent: ÃÄÅÄ´ ness = -1, ÃÄ´ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ area below ³ ³ ³ Big enough for ³ ÀÄ´ MENU ITEM: G_STRING ³ ³ menu bar ³ ³ ³ its menu items ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄ´ MENU ITEM: G_STRING ³ ³ ³ DROPBOX: G_BOX ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ Border thick- ³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÀÄ´ ness = -1, ÃÄÅÄ´ MENU ITEM: G_STRING ³ ³ Big enough for ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ its menu items ³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄ´ MENU ITEM: G_STRING ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ As can be seen the root of the MENU is a G_IBOX (invisible box) which should cover just about the whole screen (possibly leaving out the bottom lines). It has got two children: the menu bar (= top screen line) and the drop area (below this). As you can see the height of the menu bar should be '$201' (=1 full character plus two more pixels), while the height of its child is one pixel more (??? Don't ask me why, it's a complete mystery to me, but all menus look like this). Also the drop area doesn't begin until 1 character + 3 pixels down. The child of the menu bar, an invisible box called ACTIVE, defines the area within which the AES is to watch the mouse. It should be wide enough for all the titles but not more. First title should be the program name (in uppercase letters according to at least German standard I think). First dropbox should contain EIGHT menu items, the first of which is usually 'About ...', the second should be a disabled separator line ('---------' use as many hyphens as needed). The remaining six are dummy objects used by the AES for accessories, and are typically initialized to point to strings containing '1', '2' etc. up to '6' but I really don't think it matters what these strings contain. Each title should be preceded by a space and followed by another one. The strings used for menu items should each begin with two spaces (enough for a check mark + space). The selectable flag is NOT used in menu item objects (they are selectable anyway, as long as they aren't disabled). For a weird programmer, some very small changes to the above description are possible I think, without jeopardizing the function of the menu. For instance a second child could be added to the menu line, in the form of some symbol in the upper right corner of the screen. And for menu items could in some cases be used images instead of G_STRINGs. SECONDARY STRUCTURES -------------------- pointed to by the object specification pointer of some objects TEDINFO: (14 words = 28 bytes) L: Pointer to string (If 1st char. is '@' the rest interpreted as spaces) L: Pointer to 'template' (= String with underlines for editable positions) L: Pointer to 'validation string' (containing symbols for valid characters) W: Font: 3=sys(16/8 x8), 5=mini(6x6), 0,1,2=Speedo (0=prop,1=mono,2=bitmap) W: =6 (or font-ID with SpeedoGDOS and TOS 4) W: Justification (0=left, 1=right, 2=centred) W: Colour etc.: N: Border colour (Border and fill only used with N: Text colour G_BOXTEXT and G_FBOXTEXT) N: Fill level (0-7) +8 for any opaque (white) text backgr. N: Fill colour W: =0 (or font-size with SpeedoGDOS and TOS 4) W: Border thickness (0=none, positive=inwards, negative=outwards) W: String length incl. ending NULL byte W: Template length incl. ending NULL byte -------- 14 words (28 bytes) For G_TEXT and G_BOXTEXT (object types 21 and 22) only the first pointer is of interest. The other two pointers are used only with the editable objects G_FTEXT and G_FBOXTEXT (types 29 and 30). For these the text made visible is a combination of text template and string. Basically the template comes first followed by the string, whereby however any editable positions (underlines) in the template are treated as free gaps to fill with the characters from the string that are in turn. In the validation string each character corresponds to an editable position and defines what characters are allowed in this position. 9 must be a digit (0-9) A uppercase letter or space a uppercase or lowercase letter or space N digit, uppercase letter or space n digit, uppercase or lowercase letter or space F Any valid DOS pathname character plus : * ? P Any valid DOS pathname character plus \ : * ? p Any valid DOS pathname character plus \ : X Anything Note that (contrary to what is indicated in for instance the Atari compendium) the A, a, N and n options work just as well with 'non-English' letters in the Atari character set. (I.e. the AES is capable of recognizing letters in the extended character set as such and to distinguish between uppercase and lowercase versions of these.) However, this doesn't fully apply when F, P or p is used, to limit input to DOS characters. In this case AES will for A-Z accept only uppercase versions, but from the extended set will unfortunately accept ANY letter (e.g. even lowercase „ in spite of the fact that uppercase Ž also exists in the set). On the other hand the DOS functions themselves are incapable of making out the difference between uppercase and lowercase for these. (I would recommend that any lowercase input is converted, when possible, into uppercase before being used in a GEMDOS call.) Interestingly the AES will, as DOS characters, NOT accept special characters such as '+' or '-' even though these, like the 'extended letters' are actually tolerated by the DOS functions. (The above notes apply to my own Swedish TOS, but I don't think this differs between TOS nationalities.) --------------- BITBLK: (7 words = 14 bytes, but see under ICONBLK) L: Pointer to image data W: Width in bytes (must be even) W: Height in pixels W: X-offset in pixels into image data (skip image part to the left of this) W: Y-offset in pixels into image data (skip image rows above) W: Colour (0-15) ------- 7 words (14 bytes) --------------- ICONBLK: (17 words = 34 bytes, but see below) (ALL measures and coordinates within ICONBLK are IN PIXELS.) L: Pointer to mask L: Pointer to image L: Pointer to icon text string N: Foreground colour N: Background colour B: Icon letter/character W: X of icon letter RELATIVE TO THE IMAGE W: Y - " - W: X of image RELATIVE TO THE OBJECT W: Y - " - W: Image width in pixels (must be divisible by 16) W: Image height i pixels W: X of icon text RELATIVE TO THE OBJECT W: Y - " - W: Width of icon text area W: Height - " - -------- 17 words (34 bytes) The lengths given for BITBLK and ICONBLK are those I have found in newer documentation (e.g. the Atari compendium) as well as in existing RSC files. But some older sources (Katherine Peel's Concise Atari ... Reference Guide and Abacus' GEM book) add one extra null word to the end of ICONBLK and one ditto to the end of BITBLK (the latter according to Peel only). This may have been an early specification now dropped, maybe anyone else knows more? In any case this probably means some caution is advised in assuming that the next ICONBLK will follow at offset 34 from the current one. However, in an RSC file on disk I think it can be safely assumed that if the longword at offset 34 is non-zero it IS the first longword (the image pointer) of the next ICONBLK. (Should it read zero it must consist of an ending null-word + only the upper word of the image pointer in the beginning if next ICONBLK.) And the similar thing, for offset 14, goes for BITBLKs. The argument is of course that, within a file less than 64 K in size, any longword address has its upper word zeroed. --------------- CICONBLK (TOS 4): (19 words or 38 bytes) 17W = ICONBLK (Here the length of 17 words should be certain ?) L: In an RSC file on disk: Number of CICONs associated with the icon When in use in memory : Pointer to the first CICON. -------- 19 words (38 bytes) CICON: (11 words = 22 bytes) W: Number of colour planes for this CICON L: Pointer to image for unselected icon L: Pointer to mask for unselected icon L: Pointer to image for selected icon (or 0 if "unselected image" used) L: Pointer to mask for selected icon (if image pointer wasn't 0) L: 0 = No more CICONs Otherwise pointer to next CICON (or =1 in a file) -------- 11 words (22 bytes) Colour images should match dimensions etc. given in (the part of CICONBLK that corresponds to an) ICONBLK. If the AES doesn't find a CICON with a usable number of colour planes, the mono icon defined by ICONBLK will be used. In an RSC file on disk the CICON pointers don't have to be right (since the data will follow immediately after the CICON anyway), but if a separate image is used for selected icons, this must at least be signalled by its image pointer being non-zero. In an RSC file on disk all structures and data for a colour icon must be in the following order: CICONBLK Mono data Mono mask 12 bytes for any icon text First CICON its data for unselected icon its mask for unselected icon ( its data for selected icon if corresponding CICON pointer non-zero) ( its mask for selected icon if above CICON data pointer was non-zero) Next CICON etc. Should you create colour icons not in an RSC file, you can ignore the above but need to make sure the pointers are right. --------------- APPLBLK: (2 longs or 8 bytes - though the last longword could be omitted) L: Pointer to sub-routine for drawing the object on screen L: Any data to be passed to the routine by the AES -------- 4 words (8 bytes) The sub-routine is called by the AES each time the object (or part of it) needs to be redrawn. It should call VDI routines only (no AES), the first of which should be VS_CLIP to set a clip rectangle according to coordinates received from the AES. Any VDI call could then be used, including VRO_CPYFM, so it would for instance be possible to copy an image block of pre-drawn fancy buttons and indicators. A VDI virtual workstation of your own should be used, NOT the physical screen workstation of the AES, even though the sub-routine will be used in the AES context. A pointer is passed as input from the AES and a word value is to be returned as output. The input is on the stack - i.e. a longword found at 4(SP) - and the return value is to be placed in D0 (like with other C routines on the ST). You are NOT free to use all registers as you like. Specifically I have established, in experiments, that change of contents in A5, A6 or D3 leads to visible bad results, but probably none of registers D3-D7 or A3-A6 should be touched. On the other hand registers D0-D2 and A0-A2 are documented as being used as work registers by the VDI functions your routine is to call and can probably be used directly in the routine as well. An addition there is VERY LITTLE ROOM ON STACK within the routine (a system stack is used here), which, among other things means that you cannot solve the previously mentioned problem by saving all registers on stack (though you can save them elsewhere of course). Some tests I have made seem to indicate that there is room for only about 6 or so longwords on the stack (with TOS 1.04). Remember that any sub-routine call will use up one of these. Maybe someone else has got more precise official documentation regarding use of registers and stack within the custom object drawing routines? The INPUT pointer - from 4(SP) - points to the structure PARMBLK: PARMBLK: (15 words, set up by the AES - don't worry about where) L: Pointer to tree W: Object number within tree W: Previous state (according to which the object shown on screen at entry) if this = Current state, then nothing is on screen at time of entry W: Current state (to be drawn by routine or left for the AES to do) W: X of object W: Y -"- W: Width -"- W: Height -"- W: X of clip rectangle to be set by routine W: Y - " - W: Width - " - W: Height - " - L: The program-defined data from the APPLBLK -------- 15 words (30 bytes) If Previous state = Current state, then the sub-routine must draw the complete object from scratch. If not, then the routine could possibly just add the necessary modifications to make the object image on screen reflect the new state. (Reasonably, the latter case could only occur for selectable objects, with the selected bit being toggled on and off.) As OUTPUT (in D0.W) should be returned a word containing the state bits that the routine leaves for the AES to draw. In most cases the current state word is simply read from offset 8 in PARMBLK and returned as it is. But the routine could also clear certain bits that it takes care of itself. For instance a program defined button could have a routine draw a cross in it when it is selected and clear the selected state bit from the return value to prevent the AES from inverting colours. NOTE 1: The AES, in my experience, doesn't care to draw the SHADOWED state for G_PROGDEFs, so any such effect must be drawn by the custom routine. NOTE 2: Only in connection to the initial drawing (the one where Previous state = Current state) the AES (of TOS 1.04) seems to draw ANYTHING AT ALL! This shouldn't make a difference for non-selectible objects, but a G_PROGDEF that is SELECTABLE probably must do any and all of the desired states itself (except for a possible outline, which shouldn't normally be affected by further redraws after the initial one, since it lies outside the actual object area).