changeset 50541:ad343b711d5e

* international/quail.el (quail-guidance-str) (quail-guidance-frame): New variables. (quail-guidance-win): Delete this variable. (quail-setup-overlays): Make overlay not rear-advancing. (quail-kill-guidance-buf): Delete this function. (quail-activate): Add/remove quail-show-guidance to/from post-command-hook. (quail-input-method): Don't setup quail-guidance-buf. Initialize quail-guidance-str to "". (quail-start-translation): Call quail-show-guidance at first. (quail-start-conversion): Likewise. (quail-terminate-translation): Don't erase quail-guidance-buf. (quail-update-translation): Stretch overlays if their starting and ending positions are same. (quail-update-current-translations): Check the width of the current window, not the width of quail-guidance-win. (quail-make-guidance-frame): Delete the arg BUF. Fix position calculation. Don't set the window buffer, just return the new frame. (quail-minibuffer-message): New function. (quail-show-guidance): Renamed from quail-show-guidance-buf. Use message and quail-minibuffer-message to display the guidance. (quail-hide-guidance): Renamed from quail-hide-guidance-buf. Only delete quail-guidance-frame. (quail-update-guidance): Just update quail-guidance-str, not display it. (quail-get-translations): Renamed from quail-show-translations. Return a string instead of inserting it in quail-guaidance-buf.
author Kenichi Handa <handa@m17n.org>
date Fri, 11 Apr 2003 03:58:00 +0000
parents 0f0bc7773998
children c76c817423aa
files lisp/international/quail.el
diffstat 1 files changed, 175 insertions(+), 207 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/international/quail.el	Fri Apr 11 02:07:08 2003 +0000
+++ b/lisp/international/quail.el	Fri Apr 11 03:58:00 2003 +0000
@@ -66,20 +66,19 @@
 (make-variable-buffer-local 'quail-current-package)
 (put 'quail-current-package 'permanent-local t)
 
-;; Quail uses the following two buffers to assist users.
-;; A buffer to show available key sequence or translation list.
-(defvar quail-guidance-buf nil)
+;; Quail uses the following variables to assist users.
+;; A string containing available key sequences or translation list.
+(defvar quail-guidance-str nil)
 ;; A buffer to show completion list of the current key sequence.
 (defvar quail-completion-buf nil)
+;; We may display the guidance string in a buffer on a one-line frame.
+(defvar quail-guidance-buf nil)
+(defvar quail-guidance-frame nil)
 
 ;; Each buffer in which Quail is activated should use different
-;; guidance buffers.
-(make-variable-buffer-local 'quail-guidance-buf)
-(put 'quail-guidance-buf 'permanent-local t)
-
-;; A main window showing Quail guidance buffer.
-(defvar quail-guidance-win nil)
-(make-variable-buffer-local 'quail-guidance-win)
+;; guidance string.
+(make-variable-buffer-local 'quail-guidance-str)
+(put 'quail-guidance-str 'permanent-local t)
 
 (defvar quail-overlay nil
   "Overlay which covers the current translation region of Quail.")
@@ -514,7 +513,7 @@
   (let ((pos (point)))
     (if (overlayp quail-overlay)
 	(move-overlay quail-overlay pos pos)
-      (setq quail-overlay (make-overlay pos pos nil nil t))
+      (setq quail-overlay (make-overlay pos pos))
       (if input-method-highlight-flag
 	  (overlay-put quail-overlay 'face 'underline))
       (let ((l (quail-overlay-plist)))
@@ -525,7 +524,7 @@
 	(if (overlayp quail-conv-overlay)
 	    (if (not (overlay-start quail-conv-overlay))
 		(move-overlay quail-conv-overlay pos pos))
-	  (setq quail-conv-overlay (make-overlay pos pos nil nil t))
+	  (setq quail-conv-overlay (make-overlay pos pos))
 	  (if input-method-highlight-flag
 	      (overlay-put quail-conv-overlay 'face 'underline))))))
 
@@ -536,11 +535,6 @@
   (if (and (overlayp quail-conv-overlay) (overlay-start quail-conv-overlay))
       (delete-overlay quail-conv-overlay)))
 
-;; Kill Quail guidance buffer.  Set in kill-buffer-hook.
-(defun quail-kill-guidance-buf ()
-  (if (buffer-live-p quail-guidance-buf)
-      (kill-buffer quail-guidance-buf)))
-
 (defun quail-inactivate ()
   "Inactivate Quail input method.
 
@@ -562,9 +556,10 @@
       ;; Let's inactivate Quail input method.
       (unwind-protect
 	  (progn
-	    (quail-hide-guidance-buf)
 	    (quail-delete-overlays)
 	    (setq describe-current-input-method-function nil)
+	    (quail-hide-guidance)
+	    (remove-hook 'post-command-hook 'quail-show-guidance t)
 	    (run-hooks 'quail-inactivate-hook))
 	(kill-local-variable 'input-method-function))
     ;; Let's activate Quail input method.
@@ -578,12 +573,13 @@
     (setq inactivate-current-input-method-function 'quail-inactivate)
     (setq describe-current-input-method-function 'quail-help)
     (quail-delete-overlays)
-    (quail-show-guidance-buf)
+    (setq quail-guidance-str "")
+    (quail-show-guidance)
     ;; If we are in minibuffer, turn off the current input method
     ;; before exiting.
-    (if (eq (selected-window) (minibuffer-window))
-	(add-hook 'minibuffer-exit-hook 'quail-exit-from-minibuffer))
-    (add-hook 'kill-buffer-hook 'quail-kill-guidance-buf nil t)
+    (when (eq (selected-window) (minibuffer-window))
+      (add-hook 'minibuffer-exit-hook 'quail-exit-from-minibuffer)
+      (add-hook 'post-command-hook 'quail-show-guidance nil t))
     (run-hooks 'quail-activate-hook)
     (make-local-variable 'input-method-function)
     (setq input-method-function 'quail-input-method)))
@@ -1313,25 +1309,17 @@
     (quail-setup-overlays (quail-conversion-keymap))
     (let ((modified-p (buffer-modified-p))
 	  (buffer-undo-list t))
-      (or (and quail-guidance-win
-	       (window-live-p quail-guidance-win)
-	       (eq (window-buffer quail-guidance-win) quail-guidance-buf)
-	       (not input-method-use-echo-area))
-	  (quail-show-guidance-buf))
       (unwind-protect
 	  (let ((input-string (if (quail-conversion-keymap)
 				  (quail-start-conversion key)
 				(quail-start-translation key))))
+	    (setq quail-guidance-str "")
 	    (when (and (stringp input-string)
 		       (> (length input-string) 0))
 	      (if input-method-exit-on-first-char
 		  (list (aref input-string 0))
 		(quail-input-string-to-events input-string))))
 	(quail-delete-overlays)
-	(if (buffer-live-p quail-guidance-buf)
-	    (with-current-buffer quail-guidance-buf
-	      (erase-buffer)))
-	(quail-hide-guidance-buf)
 	(set-buffer-modified-p modified-p)
 	;; Run this hook only when the current input method doesn't require
 	;; conversion.  When conversion is required, the conversion function
@@ -1378,6 +1366,7 @@
 	    (setq unread-command-events (cons key unread-command-events)))
 	(while quail-translating
 	  (set-buffer-modified-p modified-p)
+	  (quail-show-guidance)
 	  (let* ((keyseq (read-key-sequence
 			  (and input-method-use-echo-area
 			       (concat input-method-previous-message
@@ -1442,8 +1431,7 @@
 		      quail-current-str ""
 		      quail-translating t)
 		(quail-setup-overlays nil)))
-	  ;; Hide '... loaded' message.
-	  (message nil)
+	  (quail-show-guidance)
 	  (let* ((keyseq (read-key-sequence
 			  (and input-method-use-echo-area
 			       (concat input-method-previous-message
@@ -1492,9 +1480,7 @@
 (defun quail-terminate-translation ()
   "Terminate the translation of the current key."
   (setq quail-translating nil)
-  (if (buffer-live-p quail-guidance-buf)
-      (with-current-buffer quail-guidance-buf
-	(erase-buffer))))
+  (setq quail-guidance-str " "))
 
 (defun quail-select-current ()
   "Accept the currently selected translation."
@@ -1535,9 +1521,18 @@
 			(quail-simple))
 		   (setq control-flag t)))))))
   (or input-method-use-echo-area
-      (progn
+      (let (pos)
 	(quail-delete-region)
-	(insert quail-current-str)))
+	(setq pos (point))
+	(insert quail-current-str)
+	(move-overlay quail-overlay pos (point))
+	(if (overlayp quail-conv-overlay)
+	    (if (not (overlay-start quail-conv-overlay))
+		(move-overlay quail-conv-overlay pos (point))
+	      (if (< (overlay-end quail-conv-overlay) (point))
+		  (move-overlay quail-conv-overlay
+				(overlay-start quail-conv-overlay)
+				(point)))))))
   (let (quail-current-str)
     (quail-update-guidance))
   (or (stringp quail-current-str)
@@ -1601,7 +1596,7 @@
 	    (< cur start)		; We moved to the previous block.
 	    (>= cur end))		; We moved to the next block.
 	(let ((len (length (cdr quail-current-translations)))
-	      (maxcol (- (window-width quail-guidance-win)
+	      (maxcol (- (window-width)
 			 quail-guidance-translations-starting-column))
 	      (block (nth 3 indices))
 	      col idx width trans num-items blocks)
@@ -1863,8 +1858,8 @@
 
 ;; Guidance, Completion, and Help buffer handlers.
 
-(defun quail-make-guidance-frame (buf)
-  "Make a new one-line frame for Quail guidance buffer."
+(defun quail-make-guidance-frame ()
+  "Make a new one-line frame for Quail guidance."
   (let* ((fparam (frame-parameters))
 	 (top (cdr (assq 'top fparam)))
 	 (border (cdr (assq 'border-width fparam)))
@@ -1872,14 +1867,11 @@
 	 (newtop (- top
 		    (frame-char-height) (* internal-border 2) (* border 2))))
     (if (< newtop 0)
-	(setq newtop (+ top (frame-pixel-height))))
-    (let* ((frame (make-frame (append '((user-position . t) (height . 1)
-					(minibuffer) (menu-bar-lines . 0))
-				      (cons (cons 'top newtop) fparam))))
-	   (win (frame-first-window frame)))
-      (set-window-buffer win buf)
-      ;;(set-window-dedicated-p win t)
-      )))
+	(setq newtop (+ top (frame-pixel-height) internal-border border)))
+    (make-frame (append '((user-position . t) (height . 1)
+			  (minibuffer)
+			  (menu-bar-lines . 0) (tool-bar-lines . 0))
+			(cons (cons 'top newtop) fparam)))))
 
 (defun quail-setup-completion-buf ()
   "Setup Quail completion buffer."
@@ -1900,124 +1892,96 @@
 	     (not (quail-simple))
 	   t))))
 
-(defun quail-show-guidance-buf ()
-  "Display a guidance buffer for Quail input method in some window.
-Create the buffer if it does not exist yet.
-The buffer is normally displayed at the echo area,
-but if the current buffer is a minibuffer, it is shown in
-the bottom-most ordinary window of the same frame,
-or in a newly created frame (if the selected frame has no other windows)."
-  (when (quail-require-guidance-buf)
-    ;; At first, setup a guidance buffer.
-    (let ((default-enable-multibyte-characters enable-multibyte-characters))
-      (or (buffer-live-p quail-guidance-buf)
-	  (setq quail-guidance-buf (generate-new-buffer " *Quail-guidance*"))))
-    (let ((package quail-current-package))
-      (with-current-buffer quail-guidance-buf
-	;; To show the title of Quail package.
-	(setq quail-current-package package
-	      current-input-method (quail-name)
-	      current-input-method-title (quail-title))
-	(erase-buffer)
-	(or (overlayp quail-overlay)
-	    (progn
-	      (setq quail-overlay (make-overlay 1 1))
-	      (overlay-put quail-overlay 'face 'highlight)))
-	(delete-overlay quail-overlay)
-	(set-buffer-modified-p nil)))
-    (bury-buffer quail-guidance-buf)
+
+;; Quail specific version of minibuffer-message.  It displays STRING
+;; with timeout 1000000 seconds instead of two seconds.
 
-    ;; Assign the buffer " *Minibuf-N*" to all windows which are now
-    ;; displaying quail-guidance-buf.
-    (let ((win-list (get-buffer-window-list quail-guidance-buf t t)))
-      (while win-list
-	(set-window-buffer (car win-list)
-			   (format " *Minibuf-%d*" (minibuffer-depth)))
-	(setq win-list (cdr win-list))))
+(defun quail-minibuffer-message (string)
+  (message nil)
+  (let ((point-max (point-max))
+	(inhibit-quit t))
+    (save-excursion
+      (goto-char point-max)
+      (insert string))
+    (sit-for 1000000)
+    (delete-region point-max (point-max))
+    (when quit-flag
+      (setq quit-flag nil
+	    unread-command-events '(7)))))
+
+(defun quail-show-guidance ()
+  "Display a guidance for Quail input method in some window.
+The guidance is normally displayed at the echo area,
+or in a newly created frame (if the current buffer is a
+minibuffer and the selected frame has no other windows)."
+  ;; At first, setup a buffer for completion.
+  (quail-setup-completion-buf)
+  (bury-buffer quail-completion-buf)
 
-    ;; Then, display it in an appropriate window.
-    (let ((win (minibuffer-window)))
-      (if (or (eq (selected-window) win)
-	      input-method-use-echo-area)
-	  ;; Since we are in minibuffer, we can't use it for guidance.
-	  (if (eq win (frame-root-window))
-	      ;; Create a frame.  It is sure that we are using some
-	      ;; window system.
-	      (quail-make-guidance-frame quail-guidance-buf)
-	    ;; Find the bottom window and split it if necessary.
-	    (setq win (window-at
-		       0 (1- (- (frame-height) (window-height win)))))
-	    (let ((height (window-height win))
-		  (window-min-height 2))
-	      ;; If WIN is tall enough, split it vertically and use
-	      ;; the lower one.
-	      (when (>= height 4)
-		;; Here, `split-window' returns a lower window
-		;; which is what we wanted.
-		(setq win (split-window win (- height 2))))
-	      (set-window-buffer win quail-guidance-buf)
-	      (with-current-buffer quail-guidance-buf
-		(fit-window-to-buffer win nil (window-height win)))))
-	(set-window-buffer win quail-guidance-buf)
-	(set-minibuffer-window win))
-      (setq quail-guidance-win win)))
+  ;; Then, show the guidance.
+  (when (and (quail-require-guidance-buf)
+	     (null unread-command-events)
+	     (null unread-post-input-method-events))
+    (if (or (eq (selected-window) (minibuffer-window))
+	    input-method-use-echo-area)
+	(if (eq (minibuffer-window) (frame-root-window))
+	    ;; Use another frame.  It is sure that we are using some
+	    ;; window system.
+	    (let ((guidance quail-guidance-str))
+	      (or (frame-live-p quail-guidance-frame)
+		  (setq quail-guidance-frame 
+			(quail-make-guidance-frame)))
+	      (or (buffer-live-p quail-guidance-buf)
+		  (setq quail-guidance-buf
+			(get-buffer-create " *Quail-guidance*")))
+	      (save-excursion
+		(set-buffer quail-guidance-buf)
+		(erase-buffer)
+		(setq cursor-type nil)
+		(insert guidance))
+	      (set-window-buffer (frame-root-window quail-guidance-frame)
+				 quail-guidance-buf)
+	      (quail-minibuffer-message
+	       (format " [%s]" current-input-method-title)))
+	  ;; Show the guidance in the next line of the currrent
+	  ;; minibuffer.
+	  (quail-minibuffer-message
+	   (format "  [%s]\n%s" 
+		   current-input-method-title quail-guidance-str)))
+      ;; Show the guidance in echo area without logging.
+      (let ((message-log-max nil))
+	(message "%s" quail-guidance-str)))))
 
-  ;; And, create a buffer for completion.
-  (quail-setup-completion-buf)
-  (bury-buffer quail-completion-buf))
-
-(defun quail-hide-guidance-buf ()
-  "Hide the Quail guidance buffer."
-  (if (buffer-live-p quail-guidance-buf)
-      (let ((win-list (get-buffer-window-list quail-guidance-buf t t))
-	    win)
-	(while win-list
-	  (setq win (car win-list) win-list (cdr win-list))
-	  (if (window-minibuffer-p win)
-	      ;; We are using echo area for the guidance buffer.
-	      ;; Vacate it to the deepest minibuffer.
-	      (set-window-buffer win
-				 (format " *Minibuf-%d*" (minibuffer-depth)))
-	    (if (eq win (frame-root-window (window-frame win)))
-		(progn
-		  ;; We are using a separate frame for guidance buffer.
-		  ;;(set-window-dedicated-p win nil)
-		  (delete-frame (window-frame win)))
-	      ;;(set-window-dedicated-p win nil)
-	      (delete-window win))))
-	(setq quail-guidance-win nil))))
+(defun quail-hide-guidance ()
+  "Hide the Quail guidance."
+  (when (and (quail-require-guidance-buf)
+	     (or (eq (selected-window) (minibuffer-window))
+		 input-method-use-echo-area)
+	     (eq (minibuffer-window) (frame-root-window)))
+    ;; We are using another frame for the guidance.
+    (if (frame-live-p quail-guidance-frame)
+	(delete-frame quail-guidance-frame))
+    (if (buffer-live-p quail-guidance-buf)
+	(kill-buffer quail-guidance-buf))))
 
 (defun quail-update-guidance ()
   "Update the Quail guidance buffer and completion buffer (if displayed now)."
-  ;; Update guidance buffer.
-  (if (quail-require-guidance-buf)
-      (let ((guidance (quail-guidance)))
-	(unless (and (eq (selected-frame) (window-frame (minibuffer-window)))
-		     (eq (selected-frame) (window-frame quail-guidance-win)))
-	  ;; The guidance window is not shown in this frame, show it.
-	  (quail-show-guidance-buf))
-	(cond ((or (eq guidance t)
-		   (consp guidance))
-	       ;; Show the current possible translations.
-	       (quail-show-translations))
-	      ((null guidance)
-	       ;; Show the current input keys.
-	       (let ((key quail-current-key))
-		 (if (quail-kbd-translate)
-		     (setq key (quail-keyseq-translate key)))
-		 (with-current-buffer quail-guidance-buf
-		   (erase-buffer)
-		   (insert key)))))
-	;; Make sure the height of the guidance window is OK --
-	;; sometimes, if the minibuffer window expands due to user
-	;; input (for instance if the newly inserted character is in a
-	;; different font), it will cause the guidance window to be
-	;; only partially visible.  We force a redisplay first because
-	;; this automatic expansion doesn't happen until then, and we
-	;; want to see the window sizes after the expansion.
-	(sit-for 0)
-	(fit-window-to-buffer quail-guidance-win nil
-			      (window-height quail-guidance-win))))
+  ;; Update the guidance string.
+  (when (quail-require-guidance-buf)
+    (let ((guidance (quail-guidance)))
+      (cond ((or (eq guidance t)
+		 (consp guidance))
+	     ;; Show the current possible translations.
+	     (setq quail-guidance-str
+		   (quail-get-translations)))
+	    ((null guidance)
+	     ;; Show the current input keys.
+	     (let ((key quail-current-key))
+	       (if (quail-kbd-translate)
+		   (setq key (quail-keyseq-translate key)))
+	       (setq quail-guidance-str (if (stringp key) key (string key)))))
+	    (t
+	     (setq quail-guidance-str " ")))))
 
   ;; Update completion buffer if displayed now.  We highlight the
   ;; selected candidate string in *Completion* buffer if any.
@@ -2036,8 +2000,8 @@
 	      (delete-overlay quail-overlay)
 	    (setq pos (point))
 	    (if (and str (search-forward (concat "." str) nil t))
-		  (move-overlay quail-overlay (1+ (match-beginning 0)) (point))
-		(move-overlay quail-overlay (match-beginning 0) (point)))
+		(move-overlay quail-overlay (1+ (match-beginning 0)) (point))
+	      (move-overlay quail-overlay (match-beginning 0) (point)))
 	    ;; Now POS points end of KEY and (point) points end of STR.
 	    (if (pos-visible-in-window-p (point) win)
 		;; STR is already visible.
@@ -2051,63 +2015,67 @@
 		  (set-window-start win pos))
 	      ))))))
 
-(defun quail-show-translations ()
-  "Show the current possible translations."
-  (let* ((key quail-current-key)
-	 (map (quail-lookup-key quail-current-key))
-	 (current-translations quail-current-translations))
+(defun quail-get-translations ()
+  "Return a string containing the current possible translations."
+  (let ((map (quail-lookup-key quail-current-key))
+	(str (copy-sequence quail-current-key)))
     (if quail-current-translations
 	(quail-update-current-translations))
-    (with-current-buffer quail-guidance-buf
-      (erase-buffer)
 
-      ;; Show the current key.
-      (let ((guidance (quail-guidance)))
-	(if (listp guidance)
-	    ;; We must show the specified PROMPTKEY instead of the
-	    ;; actual typed keys.
-	    (let ((i 0)
-		  (len (length key))
-		  prompt-key)
-	      (while (< i len)
-		(setq prompt-key (cdr (assoc (aref key i) guidance)))
-		(insert (or prompt-key (aref key i)))
-		(setq i (1+ i))))
-	  (insert key)))
+    ;; Show the current key.
+    (let ((guidance (quail-guidance)))
+      (if (listp guidance)
+	  ;; We must replace thetyped key with the specified PROMPTKEY.
+	  (dotimes (i (length str))
+	    (let ((prompt-key (cdr (assoc (aref str i) guidance))))
+	      (if prompt-key
+		  (aset str i (aref prompt-key 0)))))))
 
       ;; Show followable keys.
-      (if (and (> (length key) 0) (cdr map))
-	  (let ((keys (mapcar (function (lambda (x) (car x)))
-			      (cdr map))))
-	    (setq keys (sort keys '<))
-	    (insert "[")
-	    (while keys
-	      (insert (car keys))
-	      (setq keys (cdr keys)))
-	    (insert "]")))
-
+      (if (and (> (length quail-current-key) 0) (cdr map))
+	  (setq str
+		(format "%s[%s]"
+			str
+			(concat (sort (mapcar (function (lambda (x) (car x)))
+					      (cdr map))
+				      '<)))))
       ;; Show list of translations.
-      (if (and current-translations
+      (if (and quail-current-translations
 	       (not (quail-deterministic)))
-	  (let* ((indices (car current-translations))
+	  (let* ((indices (car quail-current-translations))
 		 (cur (car indices))
 		 (start (nth 1 indices))
 		 (end (nth 2 indices))
 		 (idx start))
-	    (indent-to (- quail-guidance-translations-starting-column 7))
-	    (insert (format "(%02d/"(nth 3 indices))
-		    (if (nth 4 indices)
-			(format "%02d)" (nth 4 indices))
-		      "??)"))
+	    (if (< (string-width str)
+		   (- quail-guidance-translations-starting-column 7))
+		(setq str
+		      (concat str
+			      (make-string
+			       (- quail-guidance-translations-starting-column
+				  7 (string-width str))
+			       32))))
+	    (setq str (format "%s(%02d/%s)" 
+			      str (nth 3 indices)
+			      (if (nth 4 indices)
+				  (format "%02d" (nth 4 indices))
+				"??")))
 	    (while (< idx end)
-	      (insert (format " %d." (if (= (- idx start) 9) 0
-				       (1+ (- idx start)))))
-	      (let ((pos (point)))
-		(insert (aref (cdr current-translations) idx))
+	      (let ((len (length str))
+		    (trans (aref (cdr quail-current-translations) idx)))
+		(or (stringp trans)
+		    (setq trans (string trans)))
+		(setq str (format "%s %d.%s" 
+				  str
+				  (if (= (- idx start) 9) 0
+				    (1+ (- idx start)))
+				  trans))
 		(if (= idx cur)
-		    (move-overlay quail-overlay pos (point))))
-	      (setq idx (1+ idx)))))
-      )))
+		    (put-text-property (+ len 3) (length str)
+				      'face 'highlight str))
+		(setq idx (1+ idx))))))
+
+      str))
 
 (defvar quail-completion-max-depth 5
   "The maximum depth of Quail completion list.")