Professional GEM - Appendices
Appendix I - Sample redraw code
/* >>>>>>>>>>>>>>>>>>>>>>>>> Sample Redraw Code <<<<<<<<<<<<<<<<<<<<<<<<<<< */ VOID doredraw(wh, area) /* wh = window handle from msg[3] */ WORD wh; /* area = pointer to redraw rect- */ GRECT *area; /* tangle in msg[4] thru msg[7] */ { GRECT box; grafmouse(MOFF, 0x0L); windupdate(BEGUPDATE); windget(wh, WFFIRSTXYWH, &box.gx, &box.gy, &box.gw, &box.gh); while ( box.gw && box.gh ) { if (rcintersect(full, &box)) /* Full is entire screen */ if (rcintersect(area, &box)) { if (wh == w1handle) /* Test for window 1 handle */ { /* AES redraw example */ objcdraw(w1tree, ROOT, MAXDEPTH, box.gx, box.gy, box.gw, box.gh); } else if (wh == w2handle) /* Test for window 2 handle */ { /* VDI redraw example */ setclip(TRUE, &box); /* Put VDI drawing calls here */ } /* add more windows here */ } windget(wh, WFNEXTXYWH, &box.gx, &box.gy, &box.gw, &box.gh); } windupdate(ENDUPDATE); grafmouse(MON, 0x0L); }
Appendix I - Utilities used in doredraw
/* >>>>>>>>>>>>>>>>>>>>>>>> Utilities used in doredraw <<<<<<<<<<<<<<<<<<<< */ VOID setclip(clipflag, area) /* set clip to specified area */ WORD clipflag; GRECT *area; { WORD pxy[4]; grecttoarray(area, pxy); vsclip(vdihandle, clipflag, pxy); } VOID grecttoarray(area, array) /* convert x,y,w,h to upr lt x,y and */ GRECT *area; /* lwr rt x,y */ WORD *array; { *array++ = area->gx; *array++ = area->gy; *array++ = area->gx + area->gw - 1; *array = area->gy + area->gh - 1; } WORD rcintersect(p1, p2) /* compute intersect of two rectangles */ GRECT *p1, *p2; { WORD tx, ty, tw, th; tw = min(p2->gx + p2->gw, p1->gx + p1->gw); th = min(p2->gy + p2->gh, p1->gy + p1->gh); tx = max(p2->gx, p1->gx); ty = max(p2->gy, p1->gy); p2->gx = tx; p2->gy = ty; p2->gw = tw - tx; p2->gh = th - ty; return( (tw > tx) && (th > ty) ); }
Appendix I - "Self-redraw" Utility
/* >>>>>>>>>>>>>>>>>>>>>>> "Self-redraw" Utility <<<<<<<<<<<<<<<<<<<<<<<<< */ VOID sendredraw(wh, p) WORD wh; GRECT *p; { WORD msg[8]; msg[0] = WMREDRAW; /* Defined in GEMBIND.H */ msg[1] = glapid; /* As returned by applinit */ msg[2] = 0; msg[3] = wh; /* Handle of window to redraw */ msg[4] = p->gx; msg[5] = p->gy; msg[6] = p->gw; msg[7] = p->gh; applwrite(glapid, 16, &msg); /* Use ADDR(msg) for portability */ }
Appendix I - Utilities for Window Requests
/* >>>>>>>>>>>>>>>>>>>> Utilities for Window Requests <<<<<<<<<<<<<<<<<< */ VOID rcconstrain(pc, pt) GRECT *pc; GRECT *pt; { if (pt->gx < pc->gx) pt->gx = pc->gx; if (pt->gy < pc->gy) pt->gy = pc->gy; if ((pt->gx + pt->gw) > (pc->gx + pc->gw)) pt->gx = (pc->gx + pc->gw) - pt->gw; if ((pt->gy + pt->gh) > (pc->gy + pc->gh)) pt->gy = (pc->gy + pc->gh) - pt->gh; } WORD align(x,n) /* Snap position x to an n-bit grid */ WORD x, n; /* Use n = 16 for horizontal word alignment */ { x += (n >> 2) - 1; /* Round and... */ x = n * (x / n); /* remove residue */ return (x); }
Appendix I - Window full utility
/* >>>>>>>>>>>>>>>>>>>>>>> Window full utility <<<<<<<<<<<<<<<<<<<<<<< */ VOID hndlfull(wh) /* depending on current window state, make window */ WORD wh; /* full size -or- return to previous shrunken size */ { /* graf calls are optional special effects. */ GRECT prev; GRECT curr; GRECT full; windget(wh, WFCXYWH, &curr.gx, &curr.gy, &curr.gw, &curr.gh); windget(wh, WFPXYWH, &prev.gx, &prev.gy, &prev.gw, &prev.gh); windget(wh, WFFXYWH, &full.gx, &full.gy, &full.gw, &full.gh); if ( rcequal(&curr, &full) ) { /* Is full, change to previous */ grafshrinkbox(prev.gx, prev.gy, prev.gw, prev.gh, full.gx, full.gy, full.gw, full.gh); windset(wh, WFCXYWH, prev.gx, prev.gy, prev.gw, prev.gh); /* put sendredraw here if you need it */ } else { /* is not full, so set to full */ grafgrowbox(curr.gx, curr.gy, curr.gw, curr.gh, full.gx, full.gy, full.gw, full.gh); windset(wh, WFCXYWH, full.gx, full.gy, full.gw, full.gh); } } WORD rcequal(p1, p2) /* tests for two rectangles equal */ GRECT *p1, *p2; { if ((p1->gx != p2->gx) || (p1->gy != p2->gy) || (p1->gw != p2->gw) || (p1->gh != p2->gh)) return(FALSE); return(TRUE); }
Appendix II - Basic Dialog Handler
/* >>>>>>>>>>>>>>>>>>>>>>> Basic Dialog Handler <<<<<<<<<<<<<<<<<<<<<<< */ WORD hndldial(tree, def, x, y, w, h) LONG tree; WORD def; WORD x, y, w, h; { WORD xdial, ydial, wdial, hdial, exitobj; formcenter(tree, &xdial, &ydial, &wdial, &hdial); formdial(0, x, y, w, h, xdial, ydial, wdial, hdial); formdial(1, x, y, w, h, xdial, ydial, wdial, hdial); objcdraw(tree, ROOT, MAXDEPTH, xdial, ydial, wdial, hdial); exitobj = formdo(tree, def) & 0x7FFF; formdial(2, x, y, w, h, xdial, ydial, wdial, hdial); formdial(3, x, y, w, h, xdial, ydial, wdial, hdial); return (exitobj); }
Appendix II - Object rectangle utility
/* >>>>>>>>>>>>>>>>>>>>>>> Object rectangle utility <<<<<<<<<<<<<<<<<<<<<<<<< */ VOID objcxywh(tree, obj, p) /* get x,y,w,h for specified object */ LONG tree; WORD obj; GRECT *p; { objcoffset(tree, obj, &p->gx, &p->gy); p->gw = LWGET(OBWIDTH(obj)); p->gh = LWGET(OBHEIGHT(obj)); }
Appendix II - Object flag utilities
/* >>>>>>>>>>>>>>>>>>>>>>> Object flag utilities <<<<<<<<<<<<<<<<<<<<<<<<<<< */ VOID undoobj(tree, which, bit) /* clear specified bit in object state */ LONG tree; WORD which, bit; { WORD state; state = LWGET(OBSTATE(which)); LWSET(OBSTATE(which), state & ~bit); } VOID deselobj(tree, which) /* turn off selected bit of spcfd object*/ LONG tree; WORD which; { undoobj(tree, which, SELECTED); } VOID doobj(tree, which, bit) /* set specified bit in object state */ LONG tree; WORD which, bit; { WORD state; state = LWGET(OBSTATE(which)); LWSET(OBSTATE(which), state | bit); } VOID selobj(tree, which) /* turn on selected bit of spcfd object */ LONG tree; WORD which; { doobj(tree, which, SELECTED); } BOOLEAN statep(tree, which, bit) LONG tree; WORD which; WORD bit; { return ( (LWGET(OBSTATE(which)) & bit) != 0); } BOOLEAN selectp(tree, which) LONG tree; WORD which; { return statep(tree, which, SELECTED); }
Appendix II - Sample radio buttons after dialog
/* >>>>>>>>>>>>>>>>>>>>>> Sample radio buttons after dialog <<<<<<<<<<<<<<<<<<<< */ WORD encode(tree, ob1st, num) LONG tree; WORD ob1st, num; { for (; num--; ) if (selectp(ob1st+num)) return(num); return (-1); }
Appendix III - Sample C output file from RCS
/* >>>>>>>>>>>>>>>>>>>>>>>>>> Sample C output file from RCS <<<<<<<<<<<<<<<<<<<< */ /* (Comments added) */ BYTE *rsstrings[] = { /* ASCII data */ "Title String", "Exit", "Centered Text", "", "", "Butt", "Tokyo", "", "Time: _:_:_", "999999", "", "Time: _:_:_ ", "999999", "New York"}; WORD IMAG0[] = { /* Bitmap for GIMAGE */ 0x7FF, 0xFFFF, 0xFF80, 0xC00, 0x0, 0xC0, 0x183F, 0xF03F, 0xF060, 0x187F, 0xF860, 0x1860, 0x187F, 0xF860, 0x1860, 0x187F, 0xF860, 0x1860, 0x187F, 0xF860, 0x1860, 0x187F, 0xF860, 0x1860, 0x187F, 0xF860, 0x1860, 0x187F, 0xF860, 0x1860, 0x187F, 0xF860, 0x1860, 0x187F, 0xF860, 0x1860, 0x187F, 0xF860, 0x1860, 0x187F, 0xF860, 0x1860, 0x183F, 0xF03F, 0xF060, 0xC00, 0x0, 0xC0, 0x7FF, 0xFFFF, 0xFF80, 0x0, 0x0, 0x0, 0x3F30, 0xC787, 0x8FE0, 0xC39, 0xCCCC, 0xCC00, 0xC36, 0xCFCC, 0xF80, 0xC30, 0xCCCD, 0xCC00, 0x3F30, 0xCCC7, 0xCFE0, 0x0, 0x0, 0x0}; WORD IMAG1[] = { /* Mask for first icon */ 0x0, 0x0, 0x0, 0x0, 0x7FFE, 0x0, 0x1F, 0xFFFF, 0xFC00, 0xFF, 0xFFFF, 0xFF00, 0x3FF, 0xFFFF, 0xFFC0, 0xFFF, 0xFFFF, 0xFFF0, 0x3FFF, 0xFFFF, 0xFFFC, 0x7FFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7FFF, 0xFFFF, 0xFFFE, 0x3FFF, 0xFFFF, 0xFFFC, 0xFFF, 0xFFFF, 0xFFF0, 0x3FF, 0xFFFF, 0xFFC0, 0xFF, 0xFFFF, 0xFF00, 0x1F, 0xFFFF, 0xF800, 0x0, 0x7FFE, 0x0}; WORD IMAG2[] = { /* Data for first icon */ 0x0, 0x0, 0x0, 0x0, 0x3FFC, 0x0, 0xF, 0xC003, 0xF000, 0x78, 0x180, 0x1E00, 0x180, 0x180, 0x180, 0x603, 0x180, 0xC060, 0x1C00, 0x6, 0x38, 0x3000, 0x18C, 0xC, 0x60C0, 0x198, 0x306, 0x6000, 0x1B0, 0x6, 0x4000, 0x1E0, 0x2, 0xC000, 0x1C0, 0x3, 0xCFC0, 0x180, 0x3F3, 0xC000, 0x0, 0x3, 0x4000, 0x0, 0x2, 0x6000, 0x0, 0x6, 0x60C0, 0x0, 0x306, 0x3000, 0x0, 0xC, 0x1C00, 0x0, 0x38, 0x603, 0x180, 0xC060, 0x180, 0x180, 0x180, 0x78, 0x180, 0x1E00, 0xF, 0xC003, 0xF000, 0x0, 0x3FFC, 0x0}; WORD IMAG3[] = { /* Mask for second icon */ 0x0, 0x0, 0x0, 0x0, 0x7FFE, 0x0, 0x1F, 0xFFFF, 0xFC00, 0xFF, 0xFFFF, 0xFF00, 0x3FF, 0xFFFF, 0xFFC0, 0xFFF, 0xFFFF, 0xFFF0, 0x3FFF, 0xFFFF, 0xFFFC, 0x7FFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7FFF, 0xFFFF, 0xFFFE, 0x3FFF, 0xFFFF, 0xFFFC, 0xFFF, 0xFFFF, 0xFFF0, 0x3FF, 0xFFFF, 0xFFC0, 0xFF, 0xFFFF, 0xFF00, 0x1F, 0xFFFF, 0xF800, 0x0, 0x7FFE, 0x0}; WORD IMAG4[] = { /* Data for second icon */ 0x0, 0x0, 0x0, 0x0, 0x3FFC, 0x0, 0xF, 0xC003, 0xF000, 0x78, 0x180, 0x1E00, 0x180, 0x180, 0x180, 0x603, 0x180, 0xC060, 0x1C00, 0x6, 0x38, 0x3000, 0x18C, 0xC, 0x60C0, 0x198, 0x306, 0x6000, 0x1B0, 0x6, 0x4000, 0x1E0, 0x2, 0xC000, 0x1C0, 0x3, 0xCFC0, 0x180, 0x3F3, 0xC000, 0x0, 0x3, 0x4000, 0x0, 0x2, 0x6000, 0x0, 0x6, 0x60C0, 0x0, 0x306, 0x3000, 0x0, 0xC, 0x1C00, 0x0, 0x38, 0x603, 0x180, 0xC060, 0x180, 0x180, 0x180, 0x78, 0x180, 0x1E00, 0xF, 0xC003, 0xF000, 0x0, 0x3FFC, 0x0}; LONG rsfrstr[] = { /* Free string index - unused */ 0}; BITBLK rsbitblk[] = { /* First entry is index to image data */ 0L, 6, 24, 0, 0, 0}; LONG rsfrimg[] = { /* Free image index - unused */ 0}; ICONBLK rsiconblk[] = { 1L, 2L, 10L, 4096,0,0, 0,0,48,24, 9,24,30,8, /* First pointer is mask */ 3L, 4L, 17L, 4864,0,0, 0,0,48,24, 0,24,48,8}; /* Second is data, third */ /* is to title string */ TEDINFO rstedinfo[] = { 2L, 3L, 4L, 3, 6, 2, 0x1180, 0x0, -1, 14,1, /* First pointer is text */ 7L, 8L, 9L, 3, 6, 2, 0x2072, 0x0, -3, 11,1, /* Second is template */ 11L, 12L, 13L, 3, 6, 0, 0x1180, 0x0, -1, 1,15, /* Third is validation */ 14L, 15L, 16L, 3, 6, 1, 0x1173, 0x0, 0, 1,17}; OBJECT rsobject[] = { -1, 1, 3, GBOX, NONE, OUTLINED, 0x21100L, 0,0, 18,12, /* Pointers are to: */ 2, -1, -1, GSTRING, NONE, NORMAL, 0x0L, 3,1, 12,1, /* rsstrings */ 3, -1, -1, GBUTTON, 0x7, NORMAL, 0x1L, 5,9, 8,1, /* rsstrings */ 0, 4, 4, GBOX, NONE, NORMAL, 0xFF1172L, 3,3, 12,5, 3, -1, -1, GIMAGE, LASTOB, NORMAL, 0x0L, 3,1, 6,3, /* rsbitblk */ -1, 1, 6, GBOX, NONE, OUTLINED, 0x21100L, 0,0, 23,12, 2, -1, -1, GTEXT, NONE, NORMAL, 0x0L, 0,1, 23,1, /* rstedinfo */ 6, 3, 5, GIBOX, NONE, NORMAL, 0x1100L, 6,3, 11,5, 4, -1, -1, GBUTTON, 0x11, NORMAL, 0x5L, 0,0, 11,1, /* rsstrings */ 5, -1, -1, GBUTTON, 0x11, NORMAL, 0x6L, 0,2, 11,1, /* rsstrings */ 2, -1, -1, GBOXCHAR, 0x11, NORMAL, 0x43FF1400L, 0,4, 11,1, 0, -1, -1, GBOXTEXT, 0x27, NORMAL, 0x1L, 5,9, 13,1, /* rstedinfo */ -1, 1, 3, GBOX, NONE, OUTLINED, 0x21100L, 0,0, 32,11, 2, -1, -1, GICON, NONE, NORMAL, 0x0L, 4,1, 6,4, /* rsiconblk */ 3, -1, -1, GFTEXT, EDITABLE, NORMAL, 0x2L, 12,2, 14,1, /* rstedinfo */ 0, 4, 4, GFBOXTEXT, 0xE, NORMAL, 0x3L, 3,5, 25,4, /* rstedinfo */ 3, -1, -1, GICON, LASTOB, NORMAL, 0x1L, 1,0, 6,4}; /* rsiconblk */ LONG rstrindex[] = { /* Points to start of trees in */ 0L, /* rsobject */ 5L, 12L}; struct foobar { /* Temporary structure used by */ WORD dummy; /* RSCREATE when setting up image */ WORD *image; /* pointers. */ } rsimdope[] = { 0, &IMAG0[0], 0, &IMAG1[0], 0, &IMAG2[0], 0, &IMAG3[0], 0, &IMAG4[0]}; /* Counts of structures defined */ #define NUMSTRINGS 18 #define NUMFRSTR 0 #define NUMIMAGES 5 #define NUMBB 1 #define NUMFRIMG 0 #define NUMIB 2 #define NUMTI 4 #define NUMOBS 17 #define NUMTREE 3 BYTE pname[] = "DEMO.RSC";
Appendix III - Title change utility
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Title change utility <<<<<<<<<<<<<<<<<<<<< */ VOID settext(tree, obj, str) LONG tree, str; WORD obj; { LONG obspec; obspec = LLGET(OBSPEC(obj)); /* Get TEDINFO address */ LLSET(TEPTEXT(obspec), str); /* Set new text pointer */ LWSET(TETXTLEN(obspec), LSTRLEN(str)); /* Set new length */ }
Appendix III - Text edit code segment
/* >>>>>>>>>>>>>>>>>>>>>> Text edit code segment <<<<<<<<<<<<<<<<<<<<<<<<<< */ LONG tree, obspec; BYTE text[41]; rsrcgaddr(RTREE, DIALOG, &tree); /* Get tree address */ obspec = LLGET(OBSPEC(EDITOBJ)); /* Get TEDINFO address */ LLSET(TEPTEXT(obspec), ADDR(str)); /* Set new text pointer */ LWSET(TETXTLEN(obspec), 41); /* Set max length */ text[0] = '\0'; /* Make empty string */
Appendix III - Sample 68K only source code
/* >>>>>>>>>>>>>>>>>>>> Sample 68K only source code <<<<<<<<<<<<<<<<<<<<<< */ VOID settext(tree, obj, str) OBJECT *tree; WORD obj; BYTE *str; { TEDINFO *obspec; obspec = (TEDINFO *) (tree + obj)->obspec; /* Get TEDINFO address */ obspec->teptext = str; /* Set new text pointer */ obspec->tetxtlen = strlen(str); /* Set new length */ }
Appendix III - Symbol definitions
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>> Symbol definitions <<<<<<<<<<<<<<<<<<<<<<<<< */ /* Window parts */ #define NAME 0x0001 #define CLOSER 0x0002 #define FULLER 0x0004 #define MOVER 0x0008 #define INFO 0x0010 #define SIZER 0x0020 #define UPARROW 0x0040 #define DNARROW 0x0080 #define VSLIDE 0x0100 #define LFARROW 0x0200 #define RTARROW 0x0400 #define HSLIDE 0x0800 #define WFKIND 1 /* windget/set parameters */ #define WFNAME 2 #define WFINFO 3 #define WFWXYWH 4 #define WFCXYWH 5 #define WFPXYWH 6 #define WFFXYWH 7 #define WFHSLIDE 8 #define WFVSLIDE 9 #define WFTOP 10 #define WFFIRSTXYWH 11 #define WFNEXTXYWH 12 #define WFNEWDESK 14 #define WFHSLSIZ 15 #define WFVSLSIZ 16 /* window messages */ #define WMREDRAW 20 #define WMTOPPED 21 #define WMCLOSED 22 #define WMFULLED 23 #define WMARROWED 24 #define WMHSLID 25 #define WMVSLID 26 #define WMSIZED 27 #define WMMOVED 28 #define WMNEWTOP 29 /* arrow messages */ #define WAUPPAGE 0 #define WADNPAGE 1 #define WAUPLINE 2 #define WADNLINE 3 #define WALFPAGE 4 #define WARTPAGE 5 #define WALFLINE 6 #define WARTLINE 7 #define RTREE 0 /* Redraw definitions */ #define ROOT 0 #define MAXDEPTH 8 /* update flags */ #define ENDUPDATE 0 #define BEGUPDATE 1 #define ENDMCTRL 2 #define BEGMCTRL 3 /* Mouse state changes */ #define MOFF 256 #define MON 257 /* Object flags */ #define NONE 0x0 #define SELECTABLE 0x1 #define DEFAULT 0x2 #define EXIT 0x4 #define EDITABLE 0x8 #define RBUTTON 0x10 /* Object states */ #define SELECTED 0x1 #define CROSSED 0x2 #define CHECKED 0x4 #define DISABLED 0x8 #define OUTLINED 0x10 #define SHADOWED 0x20 #define GBOX 20 #define GTEXT 21 #define GBOXTEXT 22 #define GIMAGE 23 #define GIBOX 25 #define GBUTTON 26 #define GBOXCHAR 27 #define GSTRING 28 #define GFTEXT 29 #define GFBOXTEXT 30 #define GICON 31 #define GTITLE 32 /* Data structures */ typedef struct grect { int gx; int gy; int gw; int gh; } GRECT; typedef struct object { int obnext; /* -> object's next sibling */ int obhead; /* -> head of object's children */ int obtail; /* -> tail of object's children */ unsigned int obtype; /* type of object- BOX, CHAR,...*/ unsigned int obflags; /* flags */ unsigned int obstate; /* state- SELECTED, OPEN, ... */ long obspec; /* "out"- -> anything else */ int obx; /* upper left corner of object */ int oby; /* upper left corner of object */ int obwidth; /* width of obj */ int obheight; /* height of obj */ } OBJECT; typedef struct textedinfo { long teptext; /* ptr to text (must be 1st) */ long teptmplt; /* ptr to template */ long tepvalid; /* ptr to validation chrs. */ int tefont; /* font */ int tejunk1; /* junk word */ int tejust; /* justification- left, right...*/ int tecolor; /* color information word */ int tejunk2; /* junk word */ int tethickness; /* border thickness */ int tetxtlen; /* length of text string */ int tetmplen; /* length of template string */ } TEDINFO; /* "Portable" data definitions */ #define OBNEXT(x) (tree + (x) * sizeof(OBJECT) + 0) #define OBHEAD(x) (tree + (x) * sizeof(OBJECT) + 2) #define OBTAIL(x) (tree + (x) * sizeof(OBJECT) + 4) #define OBTYPE(x) (tree + (x) * sizeof(OBJECT) + 6) #define OBFLAGS(x) (tree + (x) * sizeof(OBJECT) + 8) #define OBSTATE(x) (tree + (x) * sizeof(OBJECT) + 10) #define OBSPEC(x) (tree + (x) * sizeof(OBJECT) + 12) #define OBX(x) (tree + (x) * sizeof(OBJECT) + 16) #define OBY(x) (tree + (x) * sizeof(OBJECT) + 18) #define OBWIDTH(x) (tree + (x) * sizeof(OBJECT) + 20) #define OBHEIGHT(x) (tree + (x) * sizeof(OBJECT) + 22) #define TEPTEXT(x) (x) #define TETXTLEN(x) (x + 24)
Appendix IV - Sample object trees
/* >>>>>>>>>>>>>>>>>>>>>>>>>>> Sample object trees <<<<<<<<<<<<<<<<<<<<<<<< */ OBJECT rsobject[] = { -1, 1, 3, GBOX, NONE, OUTLINED, 0x21100L, 0,0, 18,12, /* Tree # 1 */ 2, -1, -1, GSTRING, NONE, NORMAL, 0x0L, 3,1, 12,1, 3, -1, -1, GBUTTON, 0x7, NORMAL, 0x1L, 5,9, 8,1, 0, 4, 4, GBOX, NONE, NORMAL, 0xFF1172L, 3,3, 12,5, 3, -1, -1, GIMAGE, LASTOB, NORMAL, 0x0L, 3,1, 6,3, -1, 1, 6, GBOX, NONE, OUTLINED, 0x21100L, 0,0, 23,12, /* Tree # 2 */ 2, -1, -1, GTEXT, NONE, NORMAL, 0x0L, 0,1, 23,1, 6, 3, 5, GIBOX, NONE, NORMAL, 0x1100L, 6,3, 11,5, 4, -1, -1, GBUTTON, 0x11, NORMAL, 0x5L, 0,0, 11,1, 5, -1, -1, GBUTTON, 0x11, NORMAL, 0x6L, 0,2, 11,1, 2, -1, -1, GBOXCHAR, 0x11, NORMAL, 0x43FF1400L, 0,4, 11,1, 0, -1, -1, GBOXTEXT, 0x27, NORMAL, 0x1L, 5,9, 13,1, -1, 1, 3, GBOX, NONE, OUTLINED, 0x21100L, 0,0, 32,11, /* Tree # 3 */ 2, -1, -1, GICON, NONE, NORMAL, 0x0L, 4,1, 6,4, 3, -1, -1, GFTEXT, EDITABLE, NORMAL, 0x2L, 12,2, 14,1, 0, 4, 4, GFBOXTEXT, 0xE, NORMAL, 0x3L, 3,5, 25,4, 3, -1, -1, GICON, LASTOB, NORMAL, 0x1L, 1,0, 6,4};
Appendix IV - Object tree walk utility
/* >>>>>>>>>>>>>>>>>>>>>>>>>> Object tree walk utility <<<<<<<<<<<<<<<<<<<<<< */ VOID maptree(tree, this, last, routine) LONG tree; WORD this, last; WORD (*routine)(); { WORD tmp1; tmp1 = this; /* Initialize to impossible value: */ /* TAIL won't point to self! */ /* Look until final node, or off */ /* the end of tree */ while (this != last && this != NIL) /* Did we 'pop' into this node */ /* for the second time? */ if (LWGET(OBTAIL(this)) != tmp1) { tmp1 = this; /* This is a new node */ this = NIL; /* Apply operation, testing */ /* for rejection of sub-tree */ if ((*routine)(tree, tmp1)) this = LWGET(OBHEAD(tmp1)); /* Subtree path not taken, */ /* so traverse right */ if (this == NIL) this = LWGET(OBNEXT(tmp1)); } else /* Revisiting parent: */ /* No operation, move right */ { tmp1 = this; this = LWGET(OBNEXT(tmp1)); } }
Appendix IV - Sample routine to use with maptree()
/* >>>>>>>>>>>>>>>>>> Sample routine to use with maptree() <<<<<<<<<<<<<<< */ VOID undoobj(tree, which, bit) /* clear specified bit in object state */ LONG tree; WORD which, bit; { WORD state; state = LWGET(OBSTATE(which)); LWSET(OBSTATE(which), state & ~bit); } VOID deselobj(tree, which) /* turn off selected bit of spcfd object*/ LONG tree; WORD which; { undoobj(tree, which, SELECTED); return (TRUE); }
Appendix IV - Sample .ICN Files
/* >>>>>>>>>>>>>>>>>>>>>>>>>> Sample .ICN Files <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< >>>>>>>>>> Save everything between >>><<< lines as CLOCK.ICN <<<<<<<<<<<<<< */ /* GEM Icon Definition: */ #define ICONW 0x0030 #define ICONH 0x0018 #define DATASIZE 0x0048 UWORD clock[DATASIZE] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x3FFC, 0x0000, 0x000F, 0xC003, 0xF000, 0x0078, 0x0180, 0x1E00, 0x0180, 0x0180, 0x0180, 0x0603, 0x0180, 0xC060, 0x1C00, 0x0006, 0x0038, 0x3000, 0x018C, 0x000C, 0x60C0, 0x0198, 0x0306, 0x6000, 0x01B0, 0x0006, 0x4000, 0x01E0, 0x0002, 0xC000, 0x01C0, 0x0003, 0xCFC0, 0x0180, 0x03F3, 0xC000, 0x0000, 0x0003, 0x4000, 0x0000, 0x0002, 0x6000, 0x0000, 0x0006, 0x60C0, 0x0000, 0x0306, 0x3000, 0x0000, 0x000C, 0x1C00, 0x0000, 0x0038, 0x0603, 0x0180, 0xC060, 0x0180, 0x0180, 0x0180, 0x0078, 0x0180, 0x1E00, 0x000F, 0xC003, 0xF000, 0x0000, 0x3FFC, 0x0000 }; /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> End of CLOCK.ICN <<<<<<<<<<<<<<<<<<<<<<<<<< */ /* >>>>>>>>> Save everything between >>>><<<<< lines as CLOCKM.ICN <<<<<<<<<< */ /* GEM Icon Definition: */ #define ICONW 0x0030 #define ICONH 0x0018 #define DATASIZE 0x0048 UWORD clockm[DATASIZE] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x7FFE, 0x0000, 0x001F, 0xFFFF, 0xFC00, 0x00FF, 0xFFFF, 0xFF00, 0x03FF, 0xFFFF, 0xFFC0, 0x0FFF, 0xFFFF, 0xFFF0, 0x3FFF, 0xFFFF, 0xFFFC, 0x7FFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7FFF, 0xFFFF, 0xFFFE, 0x3FFF, 0xFFFF, 0xFFFC, 0x0FFF, 0xFFFF, 0xFFF0, 0x03FF, 0xFFFF, 0xFFC0, 0x00FF, 0xFFFF, 0xFF00, 0x001F, 0xFFFF, 0xF800, 0x0000, 0x7FFE, 0x0000 }; /* >>>>>>>>>>>>>>>>>>>>>>>>> End of CLOCKM.ICN <<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
Appendix V - MFDB Structure
/* >>>>>>>>>>>>>>>>>>>>>>>>>>> MFDB Structure <<<<<<<<<<<<<<<<<<<<<<<<<< */ /* Memory Form Definition Block */ typedef struct fdbstr { long fdaddr; /* Form address */ int fdw; /* Form width in pixels */ int fdh; /* Form height in pixels */ int fdwdwidth; /* Form width in memory words */ int fdstand; /* Standard form flag */ int fdnplanes; /* Number of color planes */ int fdr1; /* Dummy locations: */ int fdr2; /* Reserved for future use */ int fdr3; } MFDB;
Appendix V - Resource Transform Utilities
/* >>>>>>>>>>>>>>>>>>>> Resource Transform Utilities <<<<<<<<<<<<<<<<<< */ /*------------------------------*/ /* vdifix */ /*------------------------------*/ VOID vdifix(pfd, theaddr, wb, h) /* This routine loads the MFDB */ MFDB *pfd; /* Input values are the MFDB's */ LONG theaddr; /* address, the form's address,*/ WORD wb, h; /* the form's width in bytes, */ { /* and the height in pixels */ pfd->fww = wb >> 1; pfd->fwp = wb << 3; pfd->fh = h; pfd->np = 1; /* Monochrome assumed */ pfd->mp = theaddr; } /*------------------------------*/ /* vditrans */ /*------------------------------*/ WORD vditrans(saddr, swb, daddr, dwb, h) /* Transform the standard form */ LONG saddr; /* pointed at by saddr and */ UWORD swb; /* store in the form at daddr */ LONG daddr; /* Byte widths and pixel height*/ UWORD dwb; /* are given */ UWORD h; { MFDB src, dst; /* These are on-the-fly MFDBs */ vdifix(&src, saddr, swb, h); /* Load the source MFDB */ src.ff = TRUE; /* Set it's std form flag */ vdifix(&dst, daddr, dwb, h); /* Load the destination MFDB */ dst.ff = FALSE; /* Clear the std flag */ vrtrnfm(vdihandle, &src, &dst ); /* Call the VDI */ } /*------------------------------*/ /* transbitblk */ /*------------------------------*/ VOID transbitblk(obspec) /* Transform the image belonging */ LONG obspec; /* to the bitblk pointed to by */ { /* obspec. This routine may also*/ LONG taddr; /* be used with free images */ WORD wb, hl; if ( (taddr = LLGET(BIPDATA(obspec))) == -1L) return; /* Get and validate image address */ wb = LWGET(BIWB(obspec)); /* Extract image dimensions */ hl = LWGET(BIHL(obspec)); vditrans(taddr, wb, taddr, wb, hl); /* Perform a transform */ } /* in place */ /*------------------------------*/ /* transobj */ /*------------------------------*/ VOID transobj(tree, obj) /* Examine the input object. If */ LONG tree; /* it is an icon or image, trans- */ WORD obj; /* form the associated raster */ { /* forms in place. */ WORD type, wb, hl; /* This routine may be used with */ LONG taddr, obspec; /* maptree() to transform an */ /* entire resource tree */ type = LLOBT(LWGET(OBTYPE(obj))); /* Load object type */ if ( (obspec = LLGET(OBSPEC(obj))) == -1L) /* Load and check */ return (TRUE); /* obspec pointer */ switch (type) { case GIMAGE: transbitblk(obspec); /* Transform image */ return (TRUE); case GICON: /* Load icon size */ hl = LWGET(IBHICON(obspec)); wb = (LWGET(IBWICON(obspec)) + 7) >> 3; /* Transform data */ if ( (taddr = LLGET(IBPDATA(obspec))) != -1L) vditrans(taddr, wb, taddr, wb, hl); /* Transform mask */ if ( (taddr = LLGET(IBPMASK(obspec))) != -1L) vditrans(taddr, wb, taddr, wb, hl); return (TRUE); default: return (TRUE); } } /* >>>>>>>>>>>>>>>> Macro definitions for the code above <<<<<<<<<<<<<<< */ #define BIPDATA(x) (x) #define BIWB(x) (x + 4) #define BIHL(x) (x + 6) #define OBTYPE(x) (tree + (x) * sizeof(OBJECT) + 6) #define OBSPEC(x) (tree + (x) * sizeof(OBJECT) + 12) #define IBPMASK(x) (x) #define IBPDATA(x) (x + 4) #define IBWICON(x) (x + 22) #define IBHICON(x) (x + 24)
Appendix V - VDI Copy Mode Table
/* >>>>>>>>>>>>>>>>>>>>>>>> VDI Copy Mode Table <<<<<<<<<<<<<<<<<<<<<<<<< */ Symbols: N = new destination pixel value (0 or 1) D = old destination pixel value (0 or 1) S = source pixel value (0 or 1) ~ = Boolean not (inversion) & = Boolean and | = Boolean or ^ = Boolean xor (exclusive-or) Mode Number Action ---------- ------ 0 N = 0 (USE VBAR INSTEAD) 1 N = S & D 2 N = S & ~D 3 N = S (REPLACE) 4 N = ~S & D (ERASE) 5 N = D (USELESS) 6 N = S ^ D (XOR) 7 N = S | D (TRANSPARENT) 8 N = ~ (S | D) 9 N = ~ (S ^ D) 10 N = ~D (USE VBAR INSTEAD) 11 N = S | ~D 12 N = ~S 13 N = ~S | D (REVERSE TRANSPARENT) 14 N = ~ (S & D) 15 N = 1 (USE VBAR INSTEAD) /* >>>>>>>>>>>>>>>>>>>>>>>> END OF DOWNLOAD <<<<<<<<<<<<<<<<<<<<<<<<<< */
Appendix VI - Download file for GEM column #7
/* >>>>>>>>>>>>>>>>>>>>>> Download file for GEM column #7 <<<<<<<<<<<<<<<<<<<<< >>>>>>>>>>>>>>>>>>>>>>>>>>>> Sample Menu Tree <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ -1, 1, 6, GIBOX, NONE, NORMAL, 0x0L, 0,0, 80,25, /* ROOT */ 6, 2, 2, GBOX, NONE, NORMAL, 0x1100L, 0,0, 80,513, /* THE BAR */ 1, 3, 5, GIBOX, NONE, NORMAL, 0x0L, 2,0, 20,769, /* THE ACTIVE */ 4, -1, -1, GTITLE, NONE, NORMAL, 0x0L, 0,0, 6,769, /* Title #1 */ 5, -1, -1, GTITLE, NONE, NORMAL, 0x1L, 6,0, 6,769, /* Title #2 */ 2, -1, -1, GTITLE, NONE, NORMAL, 0x2L, 12,0, 8,769, /* Title #3 */ 0, 7, 22, GIBOX, NONE, NORMAL, 0x0L, 0,769, 80,19, /* THE SCREEN */ 16, 8, 15, GBOX, NONE, NORMAL, 0xFF1100L, 2,0, 20,8, /* Drop-down #1 */ 9, -1, -1, GSTRING, NONE, NORMAL, 0x3L, 0,0, 19,1, /* About... entry */ 10, -1, -1, GSTRING, NONE, DISABLED, 0x4L, 0,1, 20,1, 11, -1, -1, GSTRING, NONE, NORMAL, 0x5L, 0,2, 20,1, /* Desk acc entries */ 12, -1, -1, GSTRING, NONE, NORMAL, 0x6L, 0,3, 20,1, 13, -1, -1, GSTRING, NONE, NORMAL, 0x7L, 0,4, 20,1, 14, -1, -1, GSTRING, NONE, NORMAL, 0x8L, 0,5, 20,1, 15, -1, -1, GSTRING, NONE, NORMAL, 0x9L, 0,6, 20,1, 7, -1, -1, GSTRING, NONE, NORMAL, 0xAL, 0,7, 20,1, 22, 17, 21, GBOX, NONE, NORMAL, 0xFF1100L, 8,0, 13,5, /* Drop-down #2 */ 18, -1, -1, GSTRING, NONE, NORMAL, 0xBL, 0,0, 13,1, 19, -1, -1, GSTRING, NONE, DISABLED, 0xCL, 0,1, 13,1, 20, -1, -1, GSTRING, NONE, NORMAL, 0xDL, 0,4, 13,1, 21, -1, -1, GSTRING, NONE, NORMAL, 0xEL, 0,2, 13,1, 16, -1, -1, GSTRING, NONE, DISABLED, 0xFL, 0,3, 13,1, 6, 23, 25, GBOX, NONE, NORMAL, 0xFF1100L, 14,0, 26,3, /* Drop down #3 */ 24, -1, -1, GSTRING, NONE, NORMAL, 0x10L, 0,2, 26,1, 25, -1, -1, GSTRING, NONE, NORMAL, 0x11L, 0,0, 26,1, 22, -1, -1, GSTRING, LASTOB, DISABLED, 0x12L, 0,1, 26,1 /* >>>>>>>>>>>>>>>>>>>>>>>> Menu enable/disable utility <<<<<<<<<<<<<<<<<<<<<< */ /*------------------------------*/ /* undoobj */ /*------------------------------*/ VOID undoobj(tree, which, bit) LONG tree; WORD which; UWORD bit; { WORD state; state = LWGET(OBSTATE(which)); LWSET(OBSTATE(which), state & ~bit); } /*------------------------------*/ /* enabobj */ /*------------------------------*/ WORD enabobj(tree, which) LONG tree; WORD which; { undoobj(tree, which, (UWORD) DISABLED); return (TRUE); } /*------------------------------*/ /* doobj */ /*------------------------------*/ VOID doobj(tree, which, bit) LONG tree; WORD which; UWORD bit; { WORD state; state = LWGET(OBSTATE(which)); LWSET(OBSTATE(which), state | bit); } /*------------------------------*/ /* disabobj */ /*------------------------------*/ WORD disabobj(tree, which) LONG tree; WORD which; { doobj(tree, which, (UWORD) DISABLED); return (TRUE); } /*------------------------------*/ /* setmenu */ /*------------------------------*/ VOID setmenu(tree, change) /* change[0] TRUE selects all entries*/ LONG tree; /* FALSE deselects all. Change list */ WORD *change; /* of items is then toggled. */ { WORD dflt, screen, drop, obj; dflt = *change++; /* What is default? */ screen = LWGET(OBTAIL(ROOT)); /* Get SCREEN */ drop = LWGET(OBHEAD(screen)); /* Get DESK drop-down */ /* and skip it */ for (; (drop = LWGET(OBNEXT(drop))) != screen; ) { obj = LWGET(OBHEAD(drop)); if (obj != NIL) if (dflt) maptree(tree, obj, drop, enabobj); else maptree(tree, obj, drop, disabobj); } for (; *change; change++) if (dflt) disabobj(tree, *change); else enabobj(tree, *change); } /* >>>>>>>>>>>>>>>>>>>>> Definitions used in this article <<<<<<<<<<<<<<<<<<<<<< */ #define ROOT 0 #define GIBOX 25 #define GSTRING 28 #define GTITLE 32 #define RTREE 0 #define MNSELECTED 10 #define CHECKED 0x4 #define DISABLED 0x8 #define OBNEXT(x) (tree + (x) * sizeof(OBJECT) + 0) #define OBHEAD(x) (tree + (x) * sizeof(OBJECT) + 2) #define OBTAIL(x) (tree + (x) * sizeof(OBJECT) + 4) #define OBTYPE(x) (tree + (x) * sizeof(OBJECT) + 6) #define OBFLAGS(x) (tree + (x) * sizeof(OBJECT) + 8) #define OBSTATE(x) (tree + (x) * sizeof(OBJECT) + 10) #define OBSPEC(x) (tree + (x) * sizeof(OBJECT) + 12) #define OBX(x) (tree + (x) * sizeof(OBJECT) + 16) #define OBY(x) (tree + (x) * sizeof(OBJECT) + 18) #define OBWIDTH(x) (tree + (x) * sizeof(OBJECT) + 20) #define OBHEIGHT(x) (tree + (x) * sizeof(OBJECT) + 22) #define MOFF 256 #define MON 257
Appendix VII - Routines to set clip to a GRECT
/* >>>>>>>>>>>>>>>> Routines to set clip to a GRECT <<<<<<<<<<<<<<<< */ VOID grecttoarray(area, array) /* convert x,y,w,h to upr lt x,y and */ GRECT *area; /* lwr rt x,y */ WORD *array; { *array++ = area->gx; *array++ = area->gy; *array++ = area->gx + area->gw - 1; *array = area->gy + area->gh - 1; } VOID setclip(clipflag, sarea) /* set clip to specified area */ WORD clipflag; GRECT *sarea; { WORD pxy[4]; grecttoarray(sarea, pxy); vsclip(vdihandle, clipflag, pxy); }
Appendix VII - Routines to set attributes before output
/* >>>>>>>>>> Routines to set attributes before output <<<<<<<<<<<< */ VOID rrperim(mode, color, type, width, pxy) /* Draw a rounded */ WORD mode, color, width, *pxy; /* rectangle outline */ { vswrmode(vdihandle, mode); vslcolor(vdihandle, color); vsltype(vdihandle, type); vslwidth(vdihandle, width); vrbox(vdihandle, pxy); vswrmode(vdihandle, MDREPLACE); } VOID plperim(mode, type, color, width, npts, pxy) /* Draw a polygonal */ /* figure */ WORD mode, type, color, width, npts, *pxy; { vswrmode(vdihandle, mode); vsltype(vdihandle, type); vslcolor(vdihandle, color); vslwidth(vdihandle, width); vpline(vdihandle, npts, pxy); } VOID /* Draw a filled polygonal area */ plfill(mode, perim, color, interior, style, npts, pxy) WORD mode, perim, color, interior, style, npts, *pxy; { vswrmode(vdihandle, mode); vsfcolor(vdihandle, color); vsfstyle(vdihandle, style); vsfinterior(vdihandle, interior); vsfperimeter(vdihandle, perim); vfillarea(vdihandle, npts, pxy); } VOID /* Draw a filled rectangle */ rectfill(mode, perim, color, interior, style, pxy) WORD mode, perim, color, style, interior, *pxy; { vswrmode(vdihandle, mode); vsfcolor(vdihandle, color); vsfstyle(vdihandle, style); vsfinterior(vdihandle, interior); vsfperimeter(vdihandle, perim); vrrecfl(vdihandle, pxy); }
Appendix VIII - Demonstration of byte alignment of window interior
/* >>>>>>>>>>> Demonstration of byte alignment of window interior <<<<<<<<<<< */ #define FEATURES 0x0fef /* what border features are used */ WORD msg[8]; /* message from evntmulti */ GRECT workarea; /* defines working area */ WORD whndl; /* handle for window being changed */ windcalc(1, FEATURES, msg[4], msg[5], msg[6], msg[7], &workarea.gx, &workarea.gy, &workarea.gw, &workarea.gh); workarea.gx = alignx(workarea.gx); workarea.gw = alignx(workarea.gw); windcalc(0, FEATURES, workarea.gx, workarea.gy, workarea.gw, workarea.gh, &msg[4], &msg[5], &msg[6], &msg[7]); windset(whndl, WFCXYWH, msg[4], msg[5], msg[6], msg[7]); /* >>>>>>>>>>>>>>>>>>>>> Subroutine for above <<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ WORD alignx(x) /* forces word alignment for column position */ WORD x; /* rounding to nearest word */ { return((x & 0xfff0) + ((x & 0x0008) ? 0x0010 : 0)); } /* >>>>>>>>>>>>>>>>>>>>> Standard vgtext binding <<<<<<<<<<<<<<<<<<<<<<<<< */ WORD vgtext( handle, x, y, string) WORD handle, x, y; BYTE *string; { WORD i; ptsin[0] = x; ptsin[1] = y; i = 0; while (intin[i++] = *string++) /* Copy characters to intin */ ; /* There is NO error checking! */ contrl[0] = 8; contrl[1] = 1; contrl[3] = --i; contrl[6] = handle; vdi(); }