Professional GEM - Appendices: Difference between revisions

From AtariForumWiki
Jump to navigation Jump to search
>Zorro 2
No edit summary
 
>Rb
No edit summary
 
Line 1: Line 1:
<pre>
{{Professional GEM}}
 
 
        Professional GEM           Appendix I                          78
 
 
                                  Appendix I
                            Sample Code Part I


==Appendix I - Sample redraw code==


<pre>


         /* >>>>>>>>>>>>>>>>>>>>>>>>> Sample Redraw Code <<<<<<<<<<<<<<<<<<<<<<<<<<< */
         /* >>>>>>>>>>>>>>>>>>>>>>>>> Sample Redraw Code <<<<<<<<<<<<<<<<<<<<<<<<<<< */
Line 48: Line 43:
         }
         }


</pre>




==Appendix I - Utilities used in doredraw==


 
     
 
<pre>
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix I                          79
 


         /* >>>>>>>>>>>>>>>>>>>>>>>> Utilities used in doredraw <<<<<<<<<<<<<<<<<<<< */
         /* >>>>>>>>>>>>>>>>>>>>>>>> Utilities used in doredraw <<<<<<<<<<<<<<<<<<<< */
Line 106: Line 92:
         }
         }


</pre>




==Appendix I - "Self-redraw" Utility==




<pre>


        /* >>>>>>>>>>>>>>>>>>>>>>> "Self-redraw" Utility <<<<<<<<<<<<<<<<<<<<<<<<< */


 
         VOID
 
         sendredraw(wh, p)
 
         WORD    wh;
 
         GRECT  *p;
 
         {
 
                 WORD    msg[8];
 
       
 
 
        Professional GEM          Appendix I                          80
 
 
        /* >>>>>>>>>>>>>>>>>>>>>>> "Self-redraw" Utility <<<<<<<<<<<<<<<<<<<<<<<<< */
 
         VOID
         sendredraw(wh, p)
         WORD    wh;
         GRECT  *p;
         {
                 WORD    msg[8];


                 msg[0] = WMREDRAW;              /* Defined in GEMBIND.H    */
                 msg[0] = WMREDRAW;              /* Defined in GEMBIND.H    */
Line 145: Line 120:
         }
         }


</pre>




==Appendix I - Utilities for Window Requests==




<pre>


        /* >>>>>>>>>>>>>>>>>>>> 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);
        }     


</pre>




==Appendix I - Window full utility==




<pre>


        /* >>>>>>>>>>>>>>>>>>>>>>> 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);
        }


</pre>




==Appendix II - Basic Dialog Handler==




<pre>


        /*
        >>>>>>>>>>>>>>>>>>>>>>> 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);
        }


</pre>




==Appendix II - Object rectangle utility==




<pre>


        /*
        >>>>>>>>>>>>>>>>>>>>>>> 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));
        }


</pre>
==Appendix II - Object flag utilities==




       
<pre>
 
 
 
         /*
         Professional GEM          Appendix I                          81
         >>>>>>>>>>>>>>>>>>>>>>> Object flag utilities <<<<<<<<<<<<<<<<<<<<<<<<<<<
 
        */
 
         /* >>>>>>>>>>>>>>>>>>>> Utilities for Window Requests <<<<<<<<<<<<<<<<<< */


         VOID
         VOID
         rcconstrain(pc, pt)
         undoobj(tree, which, bit)       /* clear specified bit in object state  */
         GRECT          *pc;
         LONG    tree;
         GRECT          *pt;
         WORD    which, bit;
         {
         {
                 if (pt->gx < pc->gx)
                 WORD    state;
                    pt->gx = pc->gx;
 
                 if (pt->gy < pc->gy)
                 state = LWGET(OBSTATE(which));
                    pt->gy = pc->gy;
                 LWSET(OBSTATE(which), state & ~bit);
                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
         VOID
         align(x,n)             /* Snap position x to an n-bit grid        */  
         deselobj(tree, which)           /* turn off selected bit of spcfd object*/
         WORD    x, n;   /* Use n = 16 for horizontal word alignment */
        LONG    tree;
         WORD    which;
         {
         {
                 x += (n >> 2) - 1;              /* Round and... */
                 undoobj(tree, which, SELECTED);
                x = n * (x / n);                /* remove residue */
         }
                return (x);
         }      
 
 
 
 
 
 
 
 
 
 


        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);
        }


</pre>




==Appendix II - Sample radio buttons after dialog==
       


<pre>


        /*
        >>>>>>>>>>>>>>>>>>>>>> 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);
        }


</pre>




==Appendix III - Sample C output file from RCS==




<pre>


        /*
        >>>>>>>>>>>>>>>>>>>>>>>>>> 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,  
        Professional GEM          Appendix I                          82
         0xF060, 0x187F, 0xF860, 0x1860,
 
         0x187F, 0xF860, 0x1860, 0x187F,  
 
        0xF860, 0x1860, 0x187F, 0xF860,  
        /* >>>>>>>>>>>>>>>>>>>>>>> Window full utility <<<<<<<<<<<<<<<<<<<<<<< */
        0x1860, 0x187F, 0xF860, 0x1860,  
 
        0x187F, 0xF860, 0x1860, 0x187F,  
         VOID
        0xF860, 0x1860, 0x187F, 0xF860,  
         hndlfull(wh)            /* depending on current window state, make window    */
        0x1860, 0x187F, 0xF860, 0x1860,  
         WORD    wh;    /*  full size -or- return to previous shrunken size */
        0x187F, 0xF860, 0x1860, 0x187F,  
         {              /* graf calls are optional special effects.          */
        0xF860, 0x1860, 0x183F, 0xF03F,  
                GRECT  prev;
        0xF060, 0xC00, 0x0, 0xC0,  
                GRECT  curr;
        0x7FF, 0xFFFF, 0xFF80, 0x0,  
                GRECT  full;
        0x0, 0x0, 0x3F30, 0xC787,  
 
         0x8FE0, 0xC39, 0xCCCC, 0xCC00,
                windget(wh, WFCXYWH, &curr.gx, &curr.gy, &curr.gw, &curr.gh);
         0xC36, 0xCFCC, 0xF80, 0xC30,
                windget(wh, WFPXYWH, &prev.gx, &prev.gy, &prev.gw, &prev.gh);
         0xCCCD, 0xCC00, 0x3F30, 0xCCC7,  
                windget(wh, WFFXYWH, &full.gx, &full.gy, &full.gw, &full.gh);
         0xCFE0, 0x0, 0x0, 0x0};
                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);
        }
 
 
 
 
 
 
 
 


        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};


         Professional GEM          Appendix II                        83
         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    */


                                  Appendix II
        LONG rstrindex[] = {                    /* Points to start of trees in */
                            Sample Code Part II
        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";
</pre>




        /*
==Appendix III - Title change utility==
        >>>>>>>>>>>>>>>>>>>>>>> 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);
        }
 
 




<pre>


        /*
        >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 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        */
                }


</pre>




==Appendix III - Text edit code segment==




<pre>


        /*
        >>>>>>>>>>>>>>>>>>>>>> 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 */


</pre>
       


==Appendix III - Sample 68K only source code==




<pre>


        /*
        >>>>>>>>>>>>>>>>>>>> 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      */
                }


</pre>




==Appendix III - Symbol definitions==




<pre>


        /*
        >>>>>>>>>>>>>>>>>>>>>>>>>>>> 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
         Professional GEM          Appendix II                        84
         #define GIMAGE  23
 
         #define GIBOX    25
 
         #define GBUTTON  26
         /*
         #define GBOXCHAR 27
         >>>>>>>>>>>>>>>>>>>>>>> Object rectangle utility <<<<<<<<<<<<<<<<<<<<<<<<<
         #define GSTRING  28
         */
         #define GFTEXT  29
 
         #define GFBOXTEXT 30
         VOID
         #define GICON   31
         objcxywh(tree, obj, p)          /* get x,y,w,h for specified object    */
         #define GTITLE   32
         LONG    tree;
                                                        /* Data structures      */
         WORD   obj;
         typedef struct grect
         GRECT   *p;
                {
         {
                 int    gx;
                 objcoffset(tree, obj, &p->gx, &p->gy);
                int    gy;
                 p->gw = LWGET(OBWIDTH(obj));
                 int    gw;
                 p->gh = LWGET(OBHEIGHT(obj));
                 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)


</pre>




==Appendix IV - Sample object trees==




<pre>


        /*
        >>>>>>>>>>>>>>>>>>>>>>>>>>> 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};     


</pre>




==Appendix IV - Object tree walk utility==




<pre>


        /*
        >>>>>>>>>>>>>>>>>>>>>>>>>> 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));
                                }
                }
</pre>




==Appendix IV - Sample routine to use with maptree()==


       
        Professional GEM          Appendix II                        85
        /*
        >>>>>>>>>>>>>>>>>>>>>>> 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
<pre>
         doobj(tree, which, bit) /* set specified bit in object state   */
 
        LONG    tree;
         /*
        WORD    which, bit;
        >>>>>>>>>>>>>>>>>> Sample routine to use with maptree() <<<<<<<<<<<<<<<
        {
        */
                VOID
         undoobj(tree, which, bit)       /* clear specified bit in object state */
                LONG    tree;
                WORD    which, bit;
                {
                 WORD    state;
                 WORD    state;


                 state = LWGET(OBSTATE(which));
                 state = LWGET(OBSTATE(which));
                 LWSET(OBSTATE(which), state | bit);
                 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
 
 
       
 
 
        Professional GEM          Appendix II                        86
 
 
        selectp(tree, which)
        LONG    tree;
        WORD    which;
        {
                 return statep(tree, which, SELECTED);
        }
 
 
 
 
 
 
 
 
 
 
 
 
 


                VOID
        deselobj(tree, which)          /* turn off selected bit of spcfd object*/
                LONG    tree;
                WORD    which;
                {
                undoobj(tree, which, SELECTED);
                return (TRUE);
                }


</pre>




==Appendix IV - Sample .ICN Files==




<pre>


        /*
        >>>>>>>>>>>>>>>>>>>>>>>>>> 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        */


</pre>




==Appendix V - MFDB Structure==




<pre>


        /* >>>>>>>>>>>>>>>>>>>>>>>>>>> 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;


</pre>




==Appendix V - Resource Transform Utilities==




<pre>


        /* >>>>>>>>>>>>>>>>>>>> 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)


</pre>




       
==Appendix V - VDI Copy Mode Table==
 
          
 
        Professional GEM          Appendix II                        87
 
 
        /*
        >>>>>>>>>>>>>>>>>>>>>> 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);
         }
 
 
 
 
 
 
 
 
 
 
 
 
 
 


<pre>


        /* >>>>>>>>>>>>>>>>>>>>>>>> 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 <<<<<<<<<<<<<<<<<<<<<<<<<< */


</pre>




==Appendix VI - Download file for GEM column #7==
       


<pre>
        /*
        >>>>>>>>>>>>>>>>>>>>>> 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


         Professional GEM          Appendix III                        88
         #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 III
</pre>
                            Sample Code Part IV
 
 
==Appendix VII - Routines to set clip to a GRECT==




<pre>


        /*
/*
         >>>>>>>>>>>>>>>>>>>>>>>>>> Sample C output file from RCS <<<<<<<<<<<<<<<<<<<<
         >>>>>>>>>>>>>>>> Routines to set clip to a GRECT <<<<<<<<<<<<<<<<
         */
         */
                                                /* (Comments added)    */
        BYTE *rsstrings[] = {                  /* ASCII data          */
        "Title String",
        "Exit",
        "Centered Text",
        "",
        "",
        "Butt",
        "Tokyo",
        "",
        "Time: _:_:_",
        "999999",
        "",
        "Time: _:_:_  ",
        "999999",
        "New York"};


         WORD IMAG0[] = {                                /* Bitmap for GIMAGE */
                VOID
        0x7FF, 0xFFFF, 0xFF80, 0xC00,  
         grecttoarray(area, array)    /* convert x,y,w,h to upr lt x,y and    */
        0x0, 0xC0, 0x183F, 0xF03F,  
                GRECT  *area;          /*                    lwr rt x,y        */
        0xF060, 0x187F, 0xF860, 0x1860,
                WORD    *array;
        0x187F, 0xF860, 0x1860, 0x187F,
                {
        0xF860, 0x1860, 0x187F, 0xF860,
                *array++ = area->gx;
        0x1860, 0x187F, 0xF860, 0x1860,
                *array++ = area->gy;
        0x187F, 0xF860, 0x1860, 0x187F,
                *array++ = area->gx + area->gw - 1;
        0xF860, 0x1860, 0x187F, 0xF860,
                *array = area->gy + area->gh - 1;
        0x1860, 0x187F, 0xF860, 0x1860,
                }
        0x187F, 0xF860, 0x1860, 0x187F,
 
        0xF860, 0x1860, 0x183F, 0xF03F,
                VOID
         0xF060, 0xC00, 0x0, 0xC0,  
         setclip(clipflag, sarea)    /* set clip to specified area          */
        0x7FF, 0xFFFF, 0xFF80, 0x0,
                WORD    clipflag;
        0x0, 0x0, 0x3F30, 0xC787,
                GRECT  *sarea;
        0x8FE0, 0xC39, 0xCCCC, 0xCC00,
                {
        0xC36, 0xCFCC, 0xF80, 0xC30,
                WORD    pxy[4];
        0xCCCD, 0xCC00, 0x3F30, 0xCCC7,
        0xCFE0, 0x0, 0x0, 0x0};


        WORD IMAG1[] = {                                /* Mask for first icon */
                grecttoarray(sarea, pxy);
        0x0, 0x0, 0x0, 0x0,  
                vsclip(vdihandle, clipflag, pxy);
        0x7FFE, 0x0, 0x1F, 0xFFFF,  
                }
        0xFC00, 0xFF, 0xFFFF, 0xFF00,
        0x3FF, 0xFFFF, 0xFFC0, 0xFFF,
        0xFFFF, 0xFFF0, 0x3FFF, 0xFFFF,
        0xFFFC, 0x7FFF, 0xFFFF, 0xFFFE,


</pre>


       


==Appendix VII - Routines to set attributes before output==


        Professional GEM          Appendix III                        89


<pre>


         0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
         /*
         0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
         >>>>>>>>>> Routines to set attributes before output <<<<<<<<<<<<
         0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
         */
         0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,  
                VOID
        0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,  
         rrperim(mode, color, type, width, pxy)      /* Draw a rounded    */
        0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,  
                WORD    mode, color, width, *pxy;    /* rectangle outline */
        0xFFFF, 0xFFFF, 0xFFFF, 0x7FFF,  
                {
        0xFFFF, 0xFFFE, 0x3FFF, 0xFFFF,  
                vswrmode(vdihandle, mode);
        0xFFFC, 0xFFF, 0xFFFF, 0xFFF0,  
                vslcolor(vdihandle, color);
        0x3FF, 0xFFFF, 0xFFC0, 0xFF,  
                vsltype(vdihandle, type);
        0xFFFF, 0xFF00, 0x1F, 0xFFFF,  
                vslwidth(vdihandle, width);
        0xF800, 0x0, 0x7FFE, 0x0};
                vrbox(vdihandle, pxy);
                vswrmode(vdihandle, MDREPLACE);
                }


        WORD IMAG2[] = {                                /* Data for first icon */
                VOID
         0x0, 0x0, 0x0, 0x0,  
         plperim(mode, type, color, width, npts, pxy)    /* Draw a polygonal */
        0x3FFC, 0x0, 0xF, 0xC003,  
                                                          /* figure          */
        0xF000, 0x78, 0x180, 0x1E00,
                WORD    mode, type, color, width, npts, *pxy;
        0x180, 0x180, 0x180, 0x603,  
                {
        0x180, 0xC060, 0x1C00, 0x6,  
                vswrmode(vdihandle, mode);
        0x38, 0x3000, 0x18C, 0xC,
                vsltype(vdihandle, type);
        0x60C0, 0x198, 0x306, 0x6000,  
                vslcolor(vdihandle, color);
        0x1B0, 0x6, 0x4000, 0x1E0,  
                vslwidth(vdihandle, width);
        0x2, 0xC000, 0x1C0, 0x3,  
                vpline(vdihandle, npts, pxy);
        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 */
                VOID                  /* Draw a filled polygonal area */
         0x0, 0x0, 0x0, 0x0,
         plfill(mode, perim, color, interior, style, npts, pxy)
        0x7FFE, 0x0, 0x1F, 0xFFFF,  
                WORD    mode, perim, color, interior, style, npts, *pxy;
        0xFC00, 0xFF, 0xFFFF, 0xFF00,  
                {
        0x3FF, 0xFFFF, 0xFFC0, 0xFFF,  
                vswrmode(vdihandle, mode);
        0xFFFF, 0xFFF0, 0x3FFF, 0xFFFF,
                vsfcolor(vdihandle, color);
        0xFFFC, 0x7FFF, 0xFFFF, 0xFFFE,  
                vsfstyle(vdihandle, style);
        0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,  
                vsfinterior(vdihandle, interior);
        0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,  
                vsfperimeter(vdihandle, perim);
        0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,  
                vfillarea(vdihandle, npts, pxy);
        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};


                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);
                }


       
</pre>




        Professional GEM          Appendix III                        90
==Appendix VIII - Demonstration of byte alignment of window interior==




<pre>


        WORD IMAG4[] = {                        /* Data for second icon */
         /*
        0x0, 0x0, 0x0, 0x0,
         >>>>>>>>>>> Demonstration of byte alignment of window interior <<<<<<<<<<<
        0x3FFC, 0x0, 0xF, 0xC003,
         */
        0xF000, 0x78, 0x180, 0x1E00,
 
        0x180, 0x180, 0x180, 0x603,
         #define FEATURES    0x0fef      /* what border features are used  */
        0x180, 0xC060, 0x1C00, 0x6,
         WORD    msg[8];                /* message from evntmulti          */
        0x38, 0x3000, 0x18C, 0xC,
         GRECT  workarea;              /* defines working area            */
        0x60C0, 0x198, 0x306, 0x6000,
         WORD    whndl;                  /* handle for window being changed */
        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,
 
 
       
 
 
        Professional GEM          Appendix III                        91
 
 
        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";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix III                        92
 
 
        /*
        >>>>>>>>>>>>>>>>>>>>>>>>>>>>> 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        */
                }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix III                        93
 
 
        /*
        >>>>>>>>>>>>>>>>>>>>>> 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 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix III                        94
 
 
        /*
        >>>>>>>>>>>>>>>>>>>> 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      */
                }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix III                        95
 
 
        /*
        >>>>>>>>>>>>>>>>>>>>>>>>>>>> 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
 
 
       
 
 
        Professional GEM          Appendix III                        96
 
 
 
        #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 */
 
 
       
 
 
        Professional GEM          Appendix III                        97
 
 
                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)
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix IV                        98
 
 
                                  Appendix IV
                            Sample Code Part V
 
 
 
        /*
        >>>>>>>>>>>>>>>>>>>>>>>>>>> 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};     
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix IV                        99
 
 
        /*
        >>>>>>>>>>>>>>>>>>>>>>>>>> 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));
                                }
                }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix IV                        100
 
 
        /*
        >>>>>>>>>>>>>>>>>> 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);
                }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix IV                        101
 
 
        /*
        >>>>>>>>>>>>>>>>>>>>>>>>>> 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 <<<<<<<<<<<<<<<<<<<<<<<<<<
        */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix IV                        102
 
 
        /*
        >>>>>>>>> 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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix V                        103
 
 
                                  Appendix V
                            Sample Code Part VI
 
 
 
        /* >>>>>>>>>>>>>>>>>>>>>>>>>>> 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;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix V                        104
 
 
        /* >>>>>>>>>>>>>>>>>>>> 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));
 
 
       
 
 
        Professional GEM          Appendix V                        105
 
 
                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);
                        }
                }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix V                        106
 
 
        /* >>>>>>>>>>>>>>>>  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)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix V                        107
 
 
        /* >>>>>>>>>>>>>>>>>>>>>>>> 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 <<<<<<<<<<<<<<<<<<<<<<<<<< */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix VI                        108
 
 
                                  Appendix VI
                            Sample Code Part VII
 
 
 
        /*
        >>>>>>>>>>>>>>>>>>>>>> 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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix VI                        109
 
 
        /*
        >>>>>>>>>>>>>>>>>>>>>>>> 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;
 
 
       
 
 
        Professional GEM          Appendix VI                        110
 
 
                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);
                }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix VI                        111
 
 
        /*
        >>>>>>>>>>>>>>>>>>>>> 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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix VII                        112
 
 
                                Appendix VII
                            Sample Code Part IX
 
 
 
        /*
        >>>>>>>>>>>>>>>> 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);
                }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix VII                        113
 
 
        /*
        >>>>>>>>>> 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);
                }
 
 
 
 
       
 
 
        Professional GEM          Appendix VIII                      114
 
 
                                Appendix VIII
                            Sample Code Part X
 
 
 
         /*
         >>>>>>>>>>> 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]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
       
 
 
        Professional GEM          Appendix VIII                      115


                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]);


         /*
         /*
Line 2,234: Line 1,405:
                 return((x & 0xfff0) + ((x & 0x0008) ? 0x0010 : 0));
                 return((x & 0xfff0) + ((x & 0x0008) ? 0x0010 : 0));
                 }       
                 }       
       
        Professional GEM          Appendix VIII                      116


         /*
         /*
Line 2,306: Line 1,427:
                 }
                 }


       
</pre>
</pre>
Back to [[Professional_GEM]]

Latest revision as of 19:05, 12 October 2006

Professional GEM
Part I -- Windows
In the beginningOpen sesameCleaning upThose fat slidersComing up nextFeedback
Part II -- Windows
ExcelsiorRedrawing windowsCaveat emptorInto the bitsA small confessionWindow control requestWindow slider messagesA common bugDept. of dirty tricksA sin of omissionComing soon
Part III -- The dialog handler
A meaningful dialogDefining termsBug alert!A handy trickClean upRecapButton ButtonWho's got the button?Coming up nextDispell gremlins
Part IV -- Resource structure
A maze of twisty little passagesPutting it to workLetters, we get lettersStraw poll!Stay tuned!
Part V -- Resource tree structures
How GEM does itThought experimentsA treewalker of our own
Part VI -- Raster operations
Seasons greetingsDefining termsMonochrome vs. colorStandard vs. device-specific formatEven-word vs. fringesMFDB'sLet's operateTransform formCopy raster opaqueCopy raster transparentThe mode parameterReplace modeErase modeXor modeTransparent modeReverse transparent modeThe problem of colorOptimizing raster operationsAvoid merged copiesMove to corresponding pixelsAvoid fringesUse another methodFeedback resultsThe next questionComing up soon
Part VII -- Menu structures
Happy new yearMenu basicsMenu structuresUsing the menuGetting fancyCheck please?Now you see it now you don'tLunch and dinner menusDo it yourselfMake prettyThat's it for now!
Part VIII -- User interfaces
And now for something completely different!Credit where it's dueFingertipsMusclesEyesShort-term memoryChunkingThink!Are we not men?Of modes and bandwidthTo do is to be!Amen...
Part IX -- VDI Graphics: Lines and solids
A bit of historyThe line forms on the leftSolidsTo be continued
Appendices
Main page

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();
                }