PROGRAMMING
The ins and outs of GFA BASIC.
by Ian Chadwick
This is one of two columns in which we'll explore the options of getting data into your program, then getting output. This issue, we cover the former: input. This doesn't cover input through alerts or dialog boxes. Alerts were discussed in a previous column; dialog boxes will be covered later. What we'll discuss here is input through the keyboard.
There are two basic types of input statements: those that stop program execution and wait for input before continuing, and those that do it "on the fly," without interrupting execution:
Program Stops On the fly INP INKEY$ INPUT INPUT# FORM INPUT LINE INPUT LINE INPUT#
There are also commands to read data from files (GET and BGET), which will be discussed in a later column about I/O and files, along with the input commands above suffixed with a number sign (INPUT#, LINE INPUT#). These function the same as their basic commands, except that they wait for input from a previously opened data channel, rather than through the keyboard.
INPUT is the essential command. It allows the user to enter one or more variables—numeric and/or strings can be combined here—as long as each variable in the command is separated by a comma. The number of variables possible is limited to the line length, but I've managed to fit sixty-nine in a single statement. Of course, this is a pointless academic exercise—you want to limit the input to something more readily usable: three or four variables might be best. For example:
INPUT CASH_VALUE, SALES_PRICE INPUT A, B$, C, D$ INPUT NAMES, AGE
Multiple variables can either be entered by the user on the same line, separated by commas; or one after another, one variable at a time, by pressing RETURN for each one. Both the comma and RETURN are valid separators in data.
INPUT can also be attached to its own text prompt, which is displayed before the data is requested:
INPUT "What is your name and age";name$, age INPUT "Enter item name, part number and quantity", part$, pnum, pquant
If the text is separated from the variable by a semicolon, then a question mark is added at the right end of the text. Otherwise, the variable information is typed in immediately after the text, so add a space before the final quotation to separate the two:
INPUT "Enter your age", age
Input variables are limited to 255 characters and are terminated by pressing RETURN, which either signifies to continue the program, or, if there are more variables to enter, get the next.
A problem arises when you want to include commas in your data. You can splice them in using MID$, but that's not always effective. Instead, you can use LINE INPUT, which functions like INPUT, except it works for strings only and accepts commas as valid characters in the data or string (only RETURN is recognized as a separator). Be careful when asking for more than one variable in a single statement, since each string must be entered on its own line.
LINE INPUT "Enter your name and address", Name$, Address$
In all other features, LINE INPUT functions identically to INPUT. FORM INPUT is another variation on INPUT with two important differences: you can specify the number of characters in the string, thus limiting the entry for use in applications such as databases. This is particularly important when creating fixed size records on disk. It is often associated with the FIELD command.
FORM INPUT 20, Address$
The other difference is that you cannot tag a text line with FORM INPUT. If you want a text prompt, you must use the PRINT statement first.
FORM INPUT doesn't work with a data channel, as do INPUT# and LINE INPUT#. This means it's not good for reading data from a file on disk or from another peripheral. Entry is only through the keyboard. However, data input with this command can be written to disk with no problems.
FORM INPUT AS is not an input command per se, but rather a function to change existing strings from user keyboard input. As such, it will be discussed in a later column on string handling.
These three commands are pretty much alike, except for the minor differences described above. You can enter special characters into all three forms by pressing ALT, CONTROL-S or CONTROL-A, as described in the GFA BASIC manual.
INP is somewhat different from INPUT. First, it accepts only a single byte, which is fine for character input, but poor for a lot of disk I/O, and simply not suitable for long string data. That doesn't mean it has no strengths. Since it reads a byte, rather than a character or string, it can read the keyboard keys you can't use for other types of input, including the function and cursor keys, and HELP and UNDO. For example:
OPEN "",#1, "CON:" DO A = INP(#1) PRINT A, CHR$(A) EXIT IF A = 32 LOOP CLOSE #1 END
This simply reads the keyboard and tells you what was pressed. If it was the SPACE BAR, that ends the program. INP offers an alternate way of handling input from peripherals, so you don't need to OPEN a channel for a device:
DO A = INP(2) PRINT A, CHR$(A) EXIT IF A = 32 LOOP END
Aside from this small convenience, the two examples perform the same. You'll note, by the way, when you try this, that the function and SHIFT-function keys produce different results, but that CONTROL-function and ALT-function don't. Experiment a bit to see what results you get from different key combinations.
It's important to note that, unlike the other input functions, INP doesn't have data separators and doesn't wait for RETURN to be pressed. RETURN is treated like any other character.
INP can also be directed to take data from an opened channel like INPUT and LINE INPUT, using INP#. However, if the keyboard is the channel you want to use, then INP(2) is slightly more efficient and shorter.
INKEY$ is a lot like INP in that it reads a single character (not byte, although a character in this case is a byte), rather than a string or large number like INPUT and its variations. However, it does it immediately—on the fly, if you will—without waiting for anything to happen. If nothing is pressed, then it continues on. For example:
DO A$ = INKEY$ PRINT A$, ASC(A$) EXIT IF ASC(A$) = 32 LOOP
This streams by your screen pretty quickly, but you get the drift. The power in INKEY$ is that it works without waiting, as you can see by this simple loop. What you don't see properly is that function, cursor, HELP and UNDO keys produce a two-character string. The first character is always the ASCII code for 0. In order to see the two codes produced, try this example:
DO REPEAT A$ = INKEY$ UNTIL AS<> "" IF LEN(A$) = 2 PRINT LEFT$(A$), ASC(A$), RIGHT$(A$), ASC(RIGHT$(A$)) ELSE PRINT A$, ASC(A$) ENDIF EXIT IF ASC(A$) = 32 LOOP
This shows you the function key codes. It also pauses execution, thanks to the REPEAT loop, so that you can see each key as it's pressed individually. In order to get the ASCII code for any two-character key, use:
KEY = CHR$(8) + CHR$(ASC(A$))
Which method of input you use depends, of course, on what you want to do with the data and how you want to get it. Obviously, if you need strings and multiple entries, then INP and INKEY$ are inadequate.
New products.
MichTron recently sent me a copy of their latest effort, GFA Companion, a Resource Construction Set (RCS) for GFA BASIC. What it does is create dialog boxes, error messages and text boxes with buttons and sliders that you can incorporate within your programs. The process is vastly simplified using Companion, as opposed to trying to hack it out with the language and an ST Developer's Kit.
The code generated is an ASCII .LST code you can merge into your own programs. Very easy to use, although the documentation is far too vague and thin for a product of this sort. You'd be well advised to try several examples and read the code they generate, as well as look through the examples provided. The code comes out commented—a nice touch which makes it fairly easy to use and alter. However, more effort in the manual would have been appreciated.
There are some small drawbacks, which really do not detract from the program in any way. First, you can only have a single slider in a box and a limited number of buttons. If you want more, you'll have to hack the source code and create your own. This isn't terribly difficult, but it's an annoying limitation. A public domain program on CompuServe called DIOX lets you create dialogs with 128 radio buttons, so you might look into it if you need more than the seven allowed by Companion.
The other problem is that the source code cannot accompany any program you create unless compiled or PSAVED (protection-saved). I understand the rationale for this step, but I don't agree with its necessity, except as far as their own comments in the output go. I feel this reduces the friendliness of the GFA environment and restricts the product's usefulness.
I like to be able to read other people's code, examine it, and sometimes tinker with it. Not with Companion's output. This isn't a problem if you're planning to compile everything and not sell or give out the source code, but it discourages its use—and you won't see output examples on GEnie, Delphi or CompuServe. A simple request for a line about code being produced with the Companion would have—I think—served them better.
The program comes with a tutorial consisting of several short lessons. I found this of dubious value. I'm not sure I understand why they bothered with it. I'd much rather have seen them offer a window construction set with sliders, so users could create their own tutorials for their programs. This aside, the Companion is a useful development tool and certainly worth the price.
By the way, GFA BASIC and Compiler version 2.02 is now available. There are some improvements in syntax handling and a new ON MENU time command. Contact MichTron for information regarding upgrades.