for
"Boxes" should be 0001. For "Lines" to turn off "Boxes"
the pattern should be 0010. The binary patterns for each menu item are
shown below.
3210 = Item # for each bit
We also need to put a checkmark beside the "Lines" item since the program starts that way. (07) We can easily assign a command sequence for menu items using the EZMENU.COMMSEQ! word. Now when the program is running, you will be able to hold down the "right Amiga key" and then hit a 'C' on the ASCII keyboard to Clear the window. The menu initialization is now complete. (8) This code is responsible for drawing the lines and boxes. SAFE.RECT sorts the corners of a rectangle before drawing it. The Amiga does not check for backwards rectangles (for speed reasons) and freaks out if you try to draw one. Notice the use of GR.RECT, is one of the JForth graphic routines which start with the prefix "GR" . ( The JForth graphics toolbox is based on the concept of a current window. Most JForth graphics words operate on the RastPort of that window.) The word WANDER.XY is interesting because it uses JForth's structure referencing tools. If you have done any Amiga programming, you have no doubt encountered the use of structures. Structures allow you to package together the data needed to describe something in the computer, like a window or menu. In this word, I wanted to keep the lines and boxes from going outside the window. I couldn't just use the original sizes because people might resize the window. Luckily, the current width and height are stored inside the window structure. The x position is clipped to the window by the line:-
0 Max GR-CURWINDOW @ ..@
Let's examine this line in detail. The x value has been left on the stack by the previous line. The word MAX takes two numbers off the stack and returns the biggest. Thus if our x position is negative, zero is bigger and we are left with zero. If x is positive, we are left with x. We then get our window structure pointer from the variable GR-CURWINDOW . |
This is passed
to ..@ which fetches the width of the GIMMEZEROZERO
window from the structure. In 'C' this line would look something
like:-
If
(x <0) x = 0 ; /* equivalent
'C' codel */
The JForth word ..@ calculates an address by adding the offset for the wdGZZWidth member to the structure. It then calls either C@ , W@ or @ depending on whether the width is an 8 bit, 16 bit or 32 bit value. You don't have to know the size of a structure member to reference it. We have a saying around here, "The size of your member is not as important as what you do with it ! " . The final word, MIN, clips the x value to the window width. There are more examples of accessing structures in section (10). (9) This section contains the program's main loop. The word LOOP.DRAW draws a line or box then checks to see if the user has generated any events. The events are associated with a specific window so we must pass EV.GETCLASS our window address. It returns an event class. If the class is zero, there was no event so we just keep looping. If there was an event we pass it to HANDLE.EVENT for processing. HANDLE.EVENT only checks for two kinds of events, MENUPICK and CLOSEWINDOW. If a menu is picked, the menu code is passed to EXMENU.EXEC which then figures out the item selected. EZMMENU.EXEC then calls the word you specified in section 5 using EZMENU.CFA[] . If the CLOSEWINDOW gadget was hit, we set QUIT-NOW which causes LOOP.DRAW to exit later. (10) I find it very helpful to separate most programs into three sections : Initialization, Execution and Termination. If you look at the final word EZWALKER, you can see this organization. When debugging, I can initialize the application with one word, e.g. EZMENU.INIT. I can then examine structures, test graphic words, look at variables, etc., under the same conditions that the program would execute. When I am done, I can clean up with one word. At the beginning of this section, we declare a NewWindow structure. This is used as a template for how we want our window to look when we open it. We can set the default values for this window using :- MY-WINDOW NewWindow.Setup |