CLIM mail archive


Wanted: readline-no-echo

    Date: Wed, 6 May 1992 13:59 EDT
    From: Jeff Morrill <jmorrill@BBN.COM>

    I want a version of read-line that does not echo.  I need
    it to read a password.  The following code works in dynamic
    windows but not in CLIM 1.1 (Allegro 4.1).  It does not
    work because read-char never returns #\rubout, it
    just beeps, therefore the typist had better not make a mistake.

Unfortunately, #\rubout isn't a standard character, and READ-CHAR is
only supposed to returns it standard characters.  It seems pretty clear
that we need a way to disable echoing inside of the input editor...
A kludge fix at the end follows at the end of the message.

    I can't tell if the fault is with CLIM or with Allegro underneath.

    This is used as the parser for a presentation-type and
    invoked from an accepting values dialog.

    What should I do?

(in-package :clim)

;; Bind this to T to disabled input editor echoing
(defvar *disable-input-editor-echo* nil)

(defmethod stream-write-char ((istream interactive-stream-mixin) char)
  (unless *disable-input-editor-echo*
    (stream-write-char (slot-value istream 'stream) char)))

(defmethod stream-write-string ((istream interactive-stream-mixin) string &optional start end)
  (unless *disable-input-editor-echo*
    (stream-write-string (slot-value istream 'stream) string start end)))

(defmethod redraw-input-buffer ((istream interactive-stream-mixin)
				&optional (start-position 0))
  (with-slots (input-buffer insertion-pointer) istream
    (multiple-value-bind (x-pos y-pos)
	(input-buffer-input-position->cursor-position* istream start-position)
      (stream-set-cursor-position* istream x-pos y-pos))
    (macrolet ((do-part (from &optional to)
		 `(do-input-buffer-pieces (input-buffer :start ,from :end ,to)
					  (start-index end-index noise-string)
		   :normal (with-temp-substring (buf input-buffer start-index end-index)
			     (replace buf input-buffer :start2 start-index :end2 end-index)
			     (write-string buf istream))
		   :noise-string (with-text-style (*noise-string-style* istream)
				   (write-string (noise-string-display-string noise-string)
      (let ((ip (min insertion-pointer (fill-pointer input-buffer))))
	(do-part start-position ip)
	;; Remember where the cursor goes (at the insertion pointer!)
	(multiple-value-bind (x-pos y-pos) (stream-cursor-position* istream)
	  (do-part ip)
	  ;; And put it there.
	  (stream-set-cursor-position* istream x-pos y-pos))))
    (force-output istream)))

;; Here's an example of it's use.  Note that you might need to bind
;; *DISABLE-INPUT-EDITOR-ECHO* around a higher level call to accept in
;; some cases, although I'm not sure of that.
(define-presentation-type password () 
  :inherit-from 'string
  :history nil)

(define-presentation-method accept ((type password) stream (view textual-view) &key)
  (let ((*disable-input-editor-echo* t))
    (accept 'string :stream stream :prompt nil :default nil)))

Follow-Ups: References:

Main Index | Thread Index