Requester Windows In Amiga BASIC
Tom R. Halfhill, Editor
Here's how to add your own custom requester windows to any Amiga BASIC program. Like dialog boxes on the Macintosh, requester windows allow your programs to flag errors or request confirmation before carrying out important functions. The routine is written for Microsoft Amiga BASIC, which is now being shipped in place of MetaComCo ABasiC and is available as an upgrade to early Amiga owners.
Amiga BASIC is the most powerful BASIC interpreter supplied with any personal computer on the market. Written by Microsoft, it combines in a single language almost every feature found in IBM PC Advanced BASIC plus Microsoft BASIC for the Macintosh. In fact, many IBM BASICA and Macintosh BASIC programs will run on the Amiga with minor modifications.
However, Amiga BASIC does lack two key statements found in Macintosh BASIC: DIALOG and BUTTON. Both are important for writing BASIC programs which retain the mouse-and-window user interface common to the Macintosh and Amiga Workbench. Fortunately, both commands can be simulated fairly easily with Amiga BASIC'S WINDOW and MOUSE statements.
In Macintosh BASIC, the DIALOG command lets a program open a dialog box (a small window) like those displayed by the Macintosh's operating system whenever the user must choose between two or more options. Dialog boxes also flag errors and alert users when they're about to activate a function that has irreversible consequences—such as quitting a program without saving the data on disk. For example, if the user pulls down a menu and selects Quit, a dialog box might open up and ask, "Quit program? (Data file not saved.)" Below this message is usually a pair of small boxes or circles called buttons which might be labeled OK and CANCEL. Pointing and clicking the mouse on the OK button exits the program; pointing and clicking on the CANCEL button cancels the Quit function and returns to the main program so the user can save his data if desired.
In Amiga BASIC, the DIALOG and BUTTON commands must be simulated by a routine that uses the WINDOW and MOUSE statements. For greater convenience, the routine can be written as a subprogram, another advanced feature included in Amiga BASIC. Subprograms are similar to subroutines, except they can have local variables. These are variables which are independent of the main program. For instance, if your main program uses a variable X for some purpose, a subprogram can also use a variable named X and it is treated as a separate variable. If the subprogram changes the value of its variable X, the main program's variable X is unaffected, and vice versa. On the other hand, a subprogram can also specify shared variables, sometimes known as global variables—those which are common to both the subprogram and the main program.
A major advantage of subprograms is that you can build up a library of useful routines on disk and add them to any new programs you write. This saves you the trouble of writing the same subprograms again and again. Although you can do the same thing with ordinary BASIC subroutines, there's always the chance that a subroutine variable might conflict with an identically named variable in your main program. Since subprogram variables are local, you're freed from this worry. Subprograms are truly programs within a program.
The Requester Subprogram
On the Amiga, dialog boxes are called requesters. Probably the most frequently encountered requester is the one that pops up when the Amiga asks you to insert a different disk. For the sake of consistency, an Amiga requester generally appears as a small window in the upper-left corner of the screen, has a title bar labeled System Request, has two or three buttons, does not have a resizing gadget or close gadget, and cannot be moved elsewhere on the screen.
The "Requester Window Subprogram" listed below duplicates most of these features. It creates a window that appears in the upper-left corner of the screen (or up to the full width of the screen in low-resolution modes); the window has a title bar labeled Program Request (to distinguish it from System Request windows); there is no resizing gadget or close gadget; and the window cannot be moved elsewhere on the screen. Unlike system requesters, this requester always displays two buttons, and they're always labeled OK and CANCEL.
The subprogram lets you display one or two lines of your own text in the Program Request window. The maximum number of characters allowed in each line depends on whether the Amiga has been set for 60- or 80-column text with the Preferences tool. If Preferences is set for 60 columns, each requester line can be up to 31 characters long. If Preferences is set for 80 columns, each line can be up to 39 characters. (You can adjust the subprogram for either mode by changing a single program statement; see the remarks in the listing.) If you try to display a line of text which exceeds these limits, the subprogram leaves off the extra characters. Since you won't know how Preferences is set if you're writing programs that might be used by other people, it's safest to assume 60 columns and restrict each line of your message to 31 characters.
A short subprogram lets you quickly and easily add custom requester windows to your own Amiga BASIC programs.
Opening a Program Request window is this simple:
requestl$="This is the first line." request2$="This is the second line." CALL Requester
The two lines of your message are defined in the string variables requestl$ and request2$, and the CALL statement runs the subprogram (similar to GOSUB). The subprogram opens the requester window and waits for the user to click on the OK or CANCEL button. Clicks outside the buttons are ignored, although a click outside the requester window itself deselects it as the active window. It can be reselected, of course, by clicking within the window.
If the user clicks on OK, the subprogram returns a value of 1 in the variable answer. If the user clicks on CANCEL, answer equals 0. In either case, the subprogram closes the requester window after the button click and passes control back to the line following the CALL Requester statement. By testing answer, your program can branch to different routines to handle the user's response as required.
Requester Window Subprogram
RequesterSub: SUB Requester STATIC SHARED requestl$,request2$,answer:' Global variables. ' Add screen parameter if needed to next line. WINDOW 2,"Program Request",(0,0)-(311,45),16 ' Following lines truncate prompts if too long. ' If Preferences is set for 60 columns, ' use maxwldth=INT(WINDOW(2)/10) for next line; ' otherwise use maxwidth=INT(WIND0W(2)/8). maxwidth - INT(WIMrD0W(2)/l 0) requestl$=LEFT$(requestl$,inaxwidth) request2$=LEFT$(request2$ .maxwidth) PRINT requestl$:PRINT request2$ ' This section draws buttons. LINE (12,20)-(50,38),l,b LINE (l52,20)-(228,38),l,b LOCATE 4,1:PRINT PTAB(20);"OK"; PRINT PTAB(160);"CANCEL" ' This section gets input, reqloop: WHILE MOU8E(0)=0:WEND:' Wait for button click. ml =M0USE(l):m2=M0USE(2) IF ml>12 AND ml<80 AND m2>20 AND m2<38 THEN answer=l:' OK was selected. LINE (12,20)-(80,38),l,bf::' Flash OK box. WHILE MOUSE(0)<>0:WEND:' Wait for button release. WINDOW CLOSE 2:EXIT SUB ELSE IF ml>182 AND ml<228 AND m2>20 AND m2<38 THEN answer=0:' CANCEL was selected. LINE (182,20)-(228,38),l) bf:' Flash CANCEL box. WHILE MOUSE(0)<>0:WEND:' Wait for button release. WINDOW CLOSE 2:EXIT SUB ELSE GOTO reqloop END IF END IF GOTO reqloop END SUB
Hints For Use
Here's an example. Suppose your BASIC program sets up a Project menu with a Quit selection (a consistent feature in Amiga software). When your MENU statement detects that Quit has been selected, it can GOSUB Quit:
Quit: MENU OFF:CLS requestl$="Quit program?" request2$="(OK exits to Workbench or CLL.)" CALL Requester IF answer=0 THEN RETURN SYSTEM
If the user selects Quit by accident or changes his mind, he can click on CANCEL and no harm is done—the Quit routine merely RETURNs. Otherwise, a click on OK stops the program and exits BASIC with the SYSTEM command. Of course, you could also include a check to see if any data created with the program has been saved, and if necessary prompt the user to save it before quitting.
There are only two more details to keep in mind when using the requester routine. First, the WINDOW statement near the beginning of the subprogram opens WINDOW 2. If there's a chance that your program might already have two or more windows open when the requester is called, change this statement to WINDOW 3, or WINDOW 4, or whatever is necessary to avoid a conflict.
Second, the WINDOW statement defaults to the primary (Workbench) screen. That means the requester window always pops up on the primary screen. If your main program creates a secondary screen with the SCREEN statement, you'll want the requester window to appear on that screen instead of the primary screen. Otherwise, the requester will be invisible. To make the requester window appear on your program's secondary screen, append the screen's number to the WINDOW statement.
For instance, if your program creates a secondary screen with a statement such as this:
change the WINDOW statement in the requester subprogram as follows:
WINDOW 2,"Program Request",(0,0)-(31145)161
This makes sure the requester will be visible.