Sources of user events:
As of now (June 4, 1984 2:41:08 pm PDT) there are four sources of events that ultimately turn up in the User Event Queue:
I. Mouse and keyboard events on the main (image) viewer, generated by TIP, passed to the image viewer's NotifyProc, and inserted by the latter in the queue using AppentTIPEvent below;
II. Cursor pickup events, generated by the JunoCursorMenu interface, and passed (like TIP events) to the image viewer's NotifyProc.
III. Button events, generated by the JunoButtons module (with the help of Spreitzer's ViewRec), and inserted directly into the queue using AppendEvents below.
IV. The image viewer's DestroyProc. This does not generate an event in the proper sense, but rather closes the queue in such a way that JunoTop will get interrupted (by the signal Evs.UserAborted) the next time it tries to get something out of the queue.
Structure of the user event stream:
The raw events from all the four sources mentioned above are merged, reformatted and cleaned up in their passage through the queue, and emerge as a stream of Event s. This stream has the form
<stream> ==> {<command>}* Quit
<command> ==> {Cursor | Button} {<argument>}* End
Cursor or Button events denote respectively the selection of a new cursor or the clicking (trough the ViewRec interface) of a JunoButtons procedure. The value field is the atomic name of the cursor or button.
An End event may have value = $Escape, $Delete, $Return, $Tab, or $None. Value will be $None if it was interpolated by the event filter.
<argument> ==> <mouse click> | <character> | <other argument>
<mouse click> ==> MouseDown {Roll}* MouseUp
All events in a <mouse click> sequence have the same atomic value, the name ($Red, $Yellow, or $Blue) of the mouse button used in the click. The coords field gives the coordinates of the event, already mapped to the Juno coordinate system (this field is undefined for all other events).
<character> ==> Char | BackSpace
If the type is Char, then the value is a REF to a printable characer.
<other argument> ==> Atom | Rope | Real.
Such events are used to pass the arguments of a button procedure (if any) to JunoTop. The value is the atom or rope itself, or a REF to the real.
Null events are used only for internal hacks, and never appear at the output end of the queue.
How the raw user events are cleaned up:
TIP items are converted to the Event format when first inserted in the queue. At this time, mouse coordinates are converted to the Juno coordinate system.
When events are removed from the other end of the queue, they are passed through a filter that ensures the event stream has the nice format described above. This filtering is necessary due to the rather weird things the user can do with the mouse, and requires discarding spurious events and/or interpolating missing ones.
A new $Cursor event is automatically interpolated (if missing) after each $Escape, $Delete, $Return, or $Tab typed by the user, and after the End event that closes a Button command. The value will be the name of the cursor most recently picked up.
An End event (with value = $None) is automatically inserted before Button, Cursor, or Quit if it is missing.
Each of the present JunoButtons procedures always produces a sequence of events of the form Button {Atom | Rope | Real}* End. However, this module can cope also with JunoButtons procedures that add extra arguments to the current cursor command. Such procedures should append to the queue one or more "argument" events (i.e., of type Atom, Rope, Real, Char, or complete <mouse click>s) without the Button or the End.
The filter regularizes mouse clicks by keeping track of the first mouse button to go down (say, the Red one), and discarding any Yellow or Blue up/down events until finds a Red MouseUp event. Any Roll events encountered until then will pass through the filter, with value set to Red. If the next event in the queue is not MouseUp, MouseDown, or Roll, the filter will interpolate a Red MouseUp event, and consider the Red button released. After returning a MouseUp event (real or faked), and before encountering the next MouseDown, the filter will ignore any Roll and MouseUp events.