
;; Below are two editor functions which form a part of the editor stream.
;; The first is a simple display editor which is a partial emacs, and the
;; second is a printing terminal rubout handler for use via supdup.

;; These functions get called whenever a :TYI message is sent to the stream
;; and we are inside the rubout handler.  If the user types a normal
;; character it is echoed, put in the buffer, and returned.  If the user
;; types a rubout, or any other editing character, any number of editing
;; commands are processed by modifying the buffer, then, when the first
;; non-editing character is typed, a throw is done back to the top level of
;; the read function and the buffered input will be re-scanned.  The
;; character must be typed at the end of the line in order for the throw to
;; take place.  This may be a bug. 

(DEFVAR DISPLAY-EDITOR-COMMAND-ALIST NIL)

(DEFUN DISPLAY-EDITOR
       (STREAM &AUX CH CH-CHAR CH-CONTROL-META COMMAND
	       (OPTIONS TV-MAKE-STREAM-RUBOUT-HANDLER-OPTIONS)
	       (RUBBED-OUT-SOME NIL)
	       (PASS-THROUGH (CDR (ASSQ ':PASS-THROUGH OPTIONS)))
	       (NUMERIC-ARG NIL))
  ;; Read characters.  If an ordinary character typed and nothing rubbed out,
  ;; return immediately.  Otherwise, let all editing operations complete
  ;; before returning. 
  ;; This {{#/}} is correct, but is it needed?
  (SETF (TYPEIN-POINTER) (FILL-POINTER))
  (*CATCH
    'RETURN-CHARACTER
    (DO () (NIL)
      ;; Read a character from the underlying stream.  This is a kludge for
      ;; speed to avoid making two function calls -- one back to the editor
      ;; stream and then one to the console stream.
      ;; Really should be:
      ;; (LET ((RUBOUT-HANDLER NIL)) (FUNCALL STREAM ':TYI))
      ;; or better (FUNCALL STREAM ':RAW-TYI) which would bypass the rubout handler.
      (SETQ CH (FUNCALL ES-CONSOLE-STREAM ':TYI))
      (SETQ CH-CHAR (LDB %%KBD-CHAR CH))
      (SETQ CH-CONTROL-META (LDB %%KBD-CONTROL-META CH))
      (SETQ COMMAND (ASSQ (CHAR-UPCASE CH) DISPLAY-EDITOR-COMMAND-ALIST))
      
      (COND
	;; Don't touch this character
	((MEMQ CH PASS-THROUGH)
	 (DE-INSERT-CHAR STREAM CH 1 RUBBED-OUT-SOME)
	 (SETQ RUBBED-OUT-SOME T))
	;; A stream editor character of some sort.  The RUBBED-OUT-SOME bit can
	;; only be cleared by entering this function again.  The stream editor
	;; editor function is passed the stream and a numeric argument.
	(COMMAND
	  (SETQ RUBBED-OUT-SOME
		(OR (FUNCALL (CDR COMMAND) STREAM (OR NUMERIC-ARG 1)) RUBBED-OUT-SOME))
	  (SETQ NUMERIC-ARG NIL))
	
	;;Handle control-number, control-u, and control-minus specially.
	((AND (NOT (ZEROP CH-CONTROL-META))
	      ({{#/}} CH-CHAR #/0)
	      ({{#/}} CH-CHAR #/9))
	 (SETQ CH-CHAR (- CH-CHAR #/0))
	 (SETQ NUMERIC-ARG (+ (* (OR NUMERIC-ARG 0) 10.) CH-CHAR)))
	((= (CHAR-UPCASE CH) #{{#/}}/U)
	 (SETQ NUMERIC-ARG (* (OR NUMERIC-ARG 1) 4)))
	
	;; Some other random control character -- beep and ignore
	((NOT (ZEROP CH-CONTROL-META))
	 (FUNCALL STREAM ':BEEP)
	 (SETQ NUMERIC-ARG NIL))
	
	;; Self-inserting character.  Set RUBBED-OUT-SOME since if we return,
	;; we were typing in the middle of the line.  Typing at the end of the
	;; line throws to RETURN-CHARACTER.
	(T (DE-INSERT-CHAR STREAM CH (OR NUMERIC-ARG 1) RUBBED-OUT-SOME)
	   (SETQ NUMERIC-ARG NIL)
	   (SETQ RUBBED-OUT-SOME T))))))

;; A self-inserting character.  A character gets here by being non-control-meta
;; and not having an editing command associated with it.  Or it can get here
;; via the :PASS-THROUGH option.  If a control-meta character gets here, it is
;; echoed as one, but loses its control-meta bits in the buffer.  Also, inserting
;; a character with bucky bits on doesn't currently work since TV-CHAR-WIDTH returns
;; 0 as the width, and TV-TYO can't print it.

(DEFUN DE-INSERT-CHAR (STREAM CH N RUBBED-OUT-SOME &AUX STRING)
  (SETQ STRING (MAKE-ARRAY NIL 'ART-16B N))
  (DOTIMES (I N) (ASET CH STRING I))
  (UNWIND-PROTECT (DE-INSERT-STRING STREAM STRING 0 N RUBBED-OUT-SOME)
		  (RETURN-ARRAY STRING)))

;; Insert a string into the buffer and print it on the screen.  The string
;; is inserted at the current cursor position, and the cursor is left after the string.

(DEFUN DE-INSERT-STRING (STREAM STRING BEGIN END RUBBED-OUT-SOME
				&AUX (WIDTH (- END BEGIN))
				     (TYPEIN-POINTER (TYPEIN-POINTER))
				     (FILL-POINTER   (FILL-POINTER)))
  ;; Increase the size of of the typein buffer, if necessary.
  (IF (= FILL-POINTER (ARRAY-LENGTH ES-BUFFER))
      (ADJUST-ARRAY-SIZE ES-BUFFER (+ (* 2 FILL-POINTER) WIDTH)))
  ;; Make room for the characters to be inserted.  Be sure to increment the fill
