Events
Normal program flow can be interrupted by any of several events: CYCLE, DELAY, END, ERROR, INTR, KBD, KEY, KNOB, SIGNAL, TIME, and TIMEOUT.
The ON statement defines the action to take when an event occurs. It defines the event type, the servicing priority, the type of branch used, and the service routine. Event branching occurs between program lines and can be a GOTO, a GOSUB, a CALL, or a RECOVER.
The destination of a GOTO or GOSUB must be a program line in the present context. If the event occurs while execution is in a different context, the event is logged and execution continues. When control returns to the proper context, the branch then takes place.
The destination of a RECOVER must also be a program line in the present context. However, if the event occurs while execution is in a different context, then SUBEXITs are automatically performed until control is returned to the proper context.
The destination of a CALL must be a SUB context that defines no parameters. When the event occurs, a CALL is performed to the SUB context. Upon exit of the SUB context, control is returned to the context that was executing when the event occurred.
Event Priority
The event priority designates which events can interrupt other event service routines. An event can only interrupt a lower priority routine. If the present SYSTEM PRIORITY is equal to or larger than the priority of an event handling routine, the event is logged and serviced later when the SYSTEM PRIORITY allows it. The main context begins running at a priority of 0, allowing any event to be serviced. The event priority may be specified from 1 to 15 and if it is not specified, defaults to 1.
If the branch type is a CALL or GOSUB, then when the event is serviced the SYSTEM PRIORITY is changed to the specified event priority. When a SUBEXIT or RETURN is executed, the SYSTEM PRIORITY is restored to its value before the event was serviced. If the branch type is a GOTO, the system priority is not changed. If the branch type is a RECOVER, the automatic SUBEXITs restore the SYSTEM PRIORITY to the value it was when the defining context invoked another context.
The ON END, ERROR, and TIMEOUT events form a special class and each indicates an error condition. The priority of the END and TIMEOUT events is 15 so that no normal event can interrupt their service routines. However, they can interrupt service routines for any event, including another END or TIMEOUT event. The priority of an ERROR event is 17. It cannot be set or changed with the SYSTEM PRIORITY statement.
Event States
The ON/OFF state of an event and the key labels are local to each context. The initial state is inherited from the invoking context. When returning from a context, the state is restored to what it was when the context was invoked. CYCLE interval, DELAY time, KBD ALL modifier, KNOB interval, TIME value, and TIMEOUT values are global. Changing them in a context overrides their values specified in previous contexts. Consider this example:
10 ON KEY 1 LABEL "Done" RECOVER 40
20 CALL S
30 Spin: GOTO Spin
40 END
50 SUB S
60 ON KEY 2 LABEL "More" GOSUB More
70 SUBEXIT
80 More: PRINT "More"
90 RETURN
100 SUBEND
When Spin is reached, only KEY 1 will be defined. This is because events are local to the defining context and the contexts called from that context. When the SUBEXIT statement is executed in line 70, the ON KEY 2 in line 60 is discarded.
DISABLE Events
DISABLE disables all defined event branches except END, ERROR, and TIMEOUT. While disabled, the first event of each type that occurs is logged.
ENABLE re-enables event branching and all logged events are serviced in the order of their event priorities.
An event branch definition is removed with an OFF statement specifying the matching event type. This may include an I/O path name, an interface select code, a key number, or a signal number.
The following example illustrates use of two ON event statements to implement an Inkey$ function that inputs one keystroke. If no key is pressed within ten seconds, an empty string is returned.
A$=FNInkey$
PRINT LEN(A$),A$
END
DEF FNInkey$ ! Input one key without echo,
ON KBD GOTO Ret_key ! and a 10 second timeout
ON DELAY 10 GOTO Ret_empty
Here: GOTO Here
Ret_key: RETURN KBD$
Ret_empty: RETURN ""
FNEND