16.1 Input Editing

An input editing stream "encapsulates" an interactive stream. That is, most operations are handled by the encapsulated interactive stream, but some operations are handled directly by the input editing stream itself. (See Appendix D, Common Lisp Streams for a discussion of encapsulating streams.)

An input editing stream has the following components:

The encapsulated interactive stream

A buffer with a fill pointer, which we shall refer to as FP . The buffer contains all of the user's input, and FP is the length of that input.

An insertion pointer, which we shall refer to as IP . The insertion pointer is the point in the buffer at which the "editing cursor" is.

A scan pointer, which we shall refer to as SP . The scan pointer is the point in the buffer from which CLIM will get the next input gesture object (in the sense of read-gesture ).

A "rescan queued" flag, indicating that the programmer (or CLIM) requested that a "rescan" operation should take place before the next gesture is read from the user

A "rescan in progress" flag, indicating that CLIM is rescanning the user's input, rather than reading freshly supplied gestures from the user

The input editor reads either "real" gestures from the user (such as characters from the keyboard or pointer button events) or input editing commands, which can modify the state of the input buffer. When they do so, the input buffer must be "rescanned"; that is, the scan pointer SP must be reset to its original state, and the contents of the input editor buffer must be reparsed before any other gestures from the user are read. While this rescanning operation is taking place, the "rescan in progress" flag is set to t . The relationship SP IP FP always holds.

The overall control structure of the input editor is:

(catch 'rescan                                ;thrown to when a rescan is invoked 
  (reset-scan-pointer stream)                ;sets STREAM-RESCANNING-P to T 
   (funcall continuation stream))) 

where stream is the input editing stream and continuation is the code supplied by the programmer, which typically contains calls to such functions as accept and read-token (which will eventually call stream-read-gesture ). When a rescan operation is invoked, it throws to the rescan tag in the previous example. The loop is terminated when an activation gesture is seen, and at that point the values produced by continuation are returned as values from the input editor.

The important point is that functions such as accept , read-gesture , and unread-gesture read (or restore) the next gesture object from the buffer at the position pointed to by the scan pointer SP . However, insertion and input editing commands take place at the position pointed to by IP . The purpose of the rescanning operation is to ensure that all the input gestures issued by the user (typed characters, pointer button presses, and so forth) have been read by CLIM. During input editing, the input editor maintains some sort of visible cursor to remind the user of the position of IP .

The overall structure of stream-read-gesture on an input editing stream is:

  (rescan-if-necessary stream) 
   ;; If SP is less than FP 
   ;;         Then get the next gesture from the input editor buffer at SP 
   ;;         and increment SP 
   ;;         Else read the next gesture from the encapsulated stream 
   ;;         and insert it into the buffer at IP 
   ;; Set the "rescan in progress" flag to false 
   ;; Call STREAM-PROCESS-GESTURE on the gesture 
   ;;         If it was a "real" gesture 
   ;;         Then exit with the gesture as the result 
   ;;         Else it was an input editing command (which has already been 
   ;;         processed), so continue looping 

A new gesture object is inserted into the input editor buffer at the insertion pointer IP . If IP = FP , this is accomplished by a vector-push-extend -like operation on the input buffer and FP , and then incrementing IP . If IP < FP , CLIM must first "make room" for the new gesture in the input buffer, then insert the gesture at IP , and finally increment both IP and FP .

When the user requests an input editor motion command, only the insertion pointer IP is affected. Motion commands do not need to request a rescan operation.

When the user requests an input editor deletion command, the sequence of gesture objects at IP is removed, and IP and FP must be modified to reflect the new state of the input buffer. Deletion commands (and other commands that modify the input buffer) must call immediate-rescan when they are done modifying the buffer.

CLIM is free to put special objects in the input editor buffer, such as "noise strings" and "accept results." A "noise string" is used to represent some sort of in-line prompt and is never seen as input; the prompt-for-accept method may insert a noise string into the input buffer. An "accept result" is an object in the input buffer that is used to represent some object that was inserted into the input buffer (typically via a pointer gesture) that has no readable representation (in the Lisp sense); presentation-replace-input may create accept results. Noise strings are skipped over by input editing commands, and accept results are treated as a single gesture.

See 16.7, Advanced Topics for an in-depth discussion of the input editing stream protocol.

16.1.1 Operators for Input Editing

16.1.2 Input Editor Commands

CommonLisp Interface Manager 2.0 User's Guide - 18 Mar 2005