;;; -*- Mode:LISP; Package:K-KBUG; Readtable:CL; Base:10 -*- ;;; This is a wimpy terminal connection to the K (defmacro without-more-processing (the-window &body body) "execute body with more processing disabled" (let ((more-p (gentemp "morep")) (window (gentemp "window"))) `(let* ((,window ,the-window) (,more-p (si::send ,window :more-p))) (unwind-protect (progn (si::send ,window :set-more-p nil) ,@body) (si::send ,window ':set-more-p ,more-p))))) ;; ||| Make half-duplex wimp work with the rubout handler. -smh 22sep88 ;; The rubout handler used to get an incorrect cursor position. The wimp ;; main-line loop enters the rubout handler via READ-LINE, and then sends ;; the line to the falcon. The loop immediately reenters READ-LINE, at ;; which entry the rubout-handler's X and Y origins are bound. Some time ;; later the typeout receiving process gets printed result from the falcon ;; and send it to the stream -- typically before the user types anything -- ;; but even so the rubout handler doesn't find out about the cursor updating. ;; You *don't* want to know how the fix works, but it has to do with making ;; a lexical closure over some of the rubout handler variables so the two ;; processes can share them. tv: (defmethod (stream-mixin :rubout-handler) (options function &rest args) (declare (arglist rubout-handler-options function &rest args)) (if (and (eq rubout-handler self) (not (cdr (assq :nonrecursive options)))) (let ((rubout-handler-options (append options rubout-handler-options))) (apply function args)) (let ((rubout-handler-options options)) (if ( (rhb-fill-pointer) (rhb-scan-pointer)) (setf (rhb-fill-pointer) 0) (copy-array-portion rubout-handler-buffer (rhb-scan-pointer) (rhb-fill-pointer) rubout-handler-buffer 0 (array-length rubout-handler-buffer)) (if (numberp (rhb-typein-pointer)) (decf (rhb-typein-pointer) (rhb-scan-pointer))) (decf (rhb-fill-pointer) (rhb-scan-pointer))) (setf (rhb-scan-pointer) 0 (rhb-status) :initial-entry) (catch 'return-from-rubout-handler (progv (unless (boundp 'prompt-starting-x) ;smh '(prompt-starting-x prompt-starting-y rubout-handler-starting-x rubout-handler-starting-y)) (unless (boundp 'prompt-starting-x) '(nil nil nil nil)) (let ((rubout-handler self) (rubout-handler-inside self) (rubout-handler-re-echo-flag nil) (rubout-handler-activation-character nil)) (multiple-value (prompt-starting-x prompt-starting-y) (send self :read-cursorpos)) (setq rubout-handler-starting-x prompt-starting-x rubout-handler-starting-y prompt-starting-y) (do-forever (setq rubout-handler-re-echo-flag nil) (catch 'rubout-handler ;Throw here when rubbing out (condition-case (error) (return (multiple-value-prog1 (apply function args) ;Call READ or whatever. (setf (rhb-fill-pointer) (rhb-scan-pointer)) (and (rhb-typein-pointer) (> (rhb-typein-pointer) (rhb-fill-pointer)) (setf (rhb-typein-pointer) (rhb-fill-pointer))))) (sys:parse-error (send self :fresh-line) (princ ">>ERROR: " self) (send error :report self) (send self :fresh-line) (setq rubout-handler-re-echo-flag t) (do-forever (send self :tyi))))) ;If error, force user to rub out ;;Maybe return when user rubs all the way back (and (zerop (rhb-fill-pointer)) (let ((full-rubout-option (assq :full-rubout rubout-handler-options))) (when full-rubout-option ;; Get rid of the prompt, if any. (send self :clear-between-cursorposes prompt-starting-x prompt-starting-y (- cursor-x left-margin-size) (- cursor-y top-margin-size)) (send self :set-cursorpos prompt-starting-x prompt-starting-y) (return (values nil (cadr full-rubout-option))))))))))))) (defun wimp (&optional half-duplex) "communicate with the K stream" (without-more-processing *terminal-io* (si::*catch 'eof (let (p tv::prompt-starting-x tv::prompt-starting-y) (unwind-protect (progn (setq p (si::process-run-function "wimp input from K" (zl::closure '(tv::prompt-starting-x tv::prompt-starting-y tv::rubout-handler-starting-x tv::rubout-handler-starting-y) #'(lambda (to superior) (si::condition-case (x) (do ((c) (si:self to)) ((null (setq c (kbug:read-from-k-stream))) (format to "~&***CONNECTION CLOSED AT REMOTE END***~%")) (write-char c to) ;; Work around a lambda compiler bug in multiple-value-setq. ;; smh 22sep88 (let ((l (multiple-value-list (zl:send to :READ-CURSORPOS)))) (setq tv::prompt-starting-x (first l) tv::prompt-starting-y (second l))) (setq tv::rubout-handler-starting-x tv::prompt-starting-x tv::rubout-handler-starting-y tv::prompt-starting-y)) (si::error (si::send x :report to))) (si::send superior :interrupt #'(zl:lambda () (si::*throw 'eof nil))) (si:process-wait-forever))) ;;#'wimp-tty-characters-from-k *terminal-io* si::current-process)) (cond (half-duplex (do ((line)) (nil) (setq line (si::prompt-and-read :string "")) (do ((j 0 (1+ j)) (n (length line))) ((= j n)) (wimp-send-1-to-k (aref line j))) (wimp-send-1-to-k #\return))) ('else (si::do-forever (wimp-send-1-to-k (read-char *terminal-io*)))))) (and p (si::send p :kill))))))) (defun wimp-tty-characters-from-k (to superior) (si::condition-case (x) (do ((c)) ((null (setq c (kbug:read-from-k-stream))) (format to "~&***CONNECTION CLOSED AT REMOTE END***~%")) (write-char c to)) (si::error (si::send x :report to))) (si::send superior :interrupt #'(lambda () (si::*throw 'eof nil))) (si:process-wait-forever)) (defun wimp-send-1-to-k (char) (write-to-k-character-stream char)) (defun wimput-proc (*terminal-io*) "communicate with the K stream" (without-more-processing *terminal-io* (si::*catch 'eof (do ((line)) (nil) (setq line (si::prompt-and-read :string "")) (do ((j 0 (1+ j)) (n (length line))) ((= j n)) (wimp-send-1-to-k (aref line j))) (wimp-send-1-to-k #\return))))) (defun wimpout-proc (*terminal-io*) (loop do (zl:catch-error-restart (sys:abort "Wimpout") (si::condition-case (x) (do ((c)) () (unless (setq c (kbug:read-from-k-stream)) (format *terminal-io* "~&***CONNECTION CLOSED AT REMOTE END***~%") (zl:process-wait "Reopen" #'(lambda () (setq c (kbug:read-from-k-stream))))) (write-char c *terminal-io*)) (si::error (si::send x :report *terminal-io*)))))) (zl:defflavor wimpy-falcon () (tv:process-mixin tv:pane-mixin tv:window)) (zl:defflavor falcon-food () (tv:process-mixin tv:pane-mixin tv:window)) (zl:defflavor wimp () (tv:bordered-constraint-frame-with-shared-io-buffer tv:select-mixin tv:FULL-SCREEN-HACK-MIXIN tv:FRAME-DONT-SELECT-INFERIORS-WITH-MOUSE-MIXIN tv:inferiors-not-in-select-menu-mixin tv:alias-for-inferiors-mixin tv:label-mixin) (:DEFAULT-INIT-PLIST :SAVE-BITS :DELAYED :panes '((falcon wimpy-falcon :label nil :more-p nil :process (wimpout-proc)) (input falcon-food :label "Input" :more-p nil :process (wimput-proc))) :constraints '((main . ((falcon input) ((input 3 :lines)) ((falcon :even))))))) (tv:add-system-key #\Greek-L 'wimp "Falcon Listener window. Do m-L in KBUG2")