comparison lisp/leim/quail.el @ 155:43dd3413c7c7 r20-3b4

Import from CVS: tag r20-3b4
author cvs
date Mon, 13 Aug 2007 09:39:39 +0200
parents
children 5a88923fcbfe
comparison
equal deleted inserted replaced
154:94141801dd7e 155:43dd3413c7c7
1 ;;; quail.el -- provides simple input method for multilingual text
2
3 ;; Copyright (C) 1995 Free Software Foundation, Inc.
4 ;; Copyright (C) 1995 Electrotechnical Laboratory, JAPAN.
5 ;; Copyright (C) 1997 MORIOKA Tomohiko
6
7 ;; Author: Kenichi HANDA <handa@etl.go.jp>
8 ;; Naoto TAKAHASHI <ntakahas@etl.go.jp>
9 ;; modified by MORIOKA Tomohiko <morioka@jaist.ac.jp> for XEmacs
10 ;; Keywords: mule, multilingual, input method
11
12 ;; This file is part of GNU Emacs.
13
14 ;; GNU Emacs is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; any later version.
18
19 ;; GNU Emacs is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;; GNU General Public License for more details.
23
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with GNU Emacs; see the file COPYING. If not, write to the
26 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27 ;; Boston, MA 02111-1307, USA.
28
29 ;;; Commentary:
30
31 ;; In Quail minor mode, you can input multilingual text easily. By
32 ;; defining a translation table (named Quail map) which maps ASCII key
33 ;; string to multilingual character or string, you can input any text
34 ;; from ASCII keyboard.
35 ;;
36 ;; We use words "translation" and "conversion" differently. The
37 ;; former is done by Quail package itself, the latter is the further
38 ;; process of converting a translated text to some more desirable
39 ;; text. For instance, Quail package for Japanese (`quail-jp')
40 ;; translates Roman text (transliteration of Japanese in Latin
41 ;; alphabets) to Hiragana text, which is then converted to
42 ;; Kanji-and-Kana mixed text or Katakana text by commands specified in
43 ;; CONVERSION-KEYS argument of the Quail package.
44
45 ;;; Code:
46
47 (eval-when-compile
48 (if (string-match "XEmacs" emacs-version)
49 (require 'overlay)
50 ))
51
52 (cond
53 ((featurep 'xemacs)
54 (require 'overlay)
55 )
56 (t
57 (require 'faces)
58 ))
59
60 ;; Buffer local variables
61
62 (defvar quail-current-package nil
63 "The current Quail package to input multilingual text in Quail minor mode.
64 See the documentation of `quail-package-alist' for the format.")
65 (make-variable-buffer-local 'quail-current-package)
66 (put 'quail-current-package 'permanent-local t)
67
68 ;; Quail uses the following two buffers to assist users.
69 ;; A buffer to show available key sequence or translation list.
70 (defvar quail-guidance-buf nil)
71 ;; A buffer to show completion list of the current key sequence.
72 (defvar quail-completion-buf nil)
73
74 (defvar quail-mode nil
75 "Non-nil if in Quail minor mode.")
76 (make-variable-buffer-local 'quail-mode)
77 (put 'quail-mode 'permanent-local t)
78
79 (defvar quail-overlay nil
80 "Overlay which covers the current translation region of Quail.")
81 (make-variable-buffer-local 'quail-overlay)
82
83 (defvar quail-conv-overlay nil
84 "Overlay which covers the text to be converted in Quail mode.")
85 (make-variable-buffer-local 'quail-conv-overlay)
86
87 (defvar quail-current-key nil
88 "Current key for translation in Quail mode.")
89
90 (defvar quail-current-str nil
91 "Currently selected translation of the current key.")
92
93 (defvar quail-current-translations nil
94 "Cons of indices and vector of possible translations of the current key.")
95
96 ;; A flag to control conversion region. Normally nil, but if set to
97 ;; t, it means we must start the new conversion region if new key to
98 ;; be translated is input.
99 (defvar quail-reset-conversion-region nil)
100
101 ;; Quail package handlers.
102
103 (defvar quail-package-alist nil
104 "List of Quail packages.
105 A Quail package is a list of these elements:
106 NAME, TITLE, QUAIL-MAP, GUIDANCE, DOCSTRING, TRANSLATION-KEYS,
107 FORGET-LAST-SELECTION, DETERMINISTIC, KBD-TRANSLATE, SHOW-LAYOUT,
108 DECODE-MAP, MAXIMUM-SHORTEST, OVERLAY-PLIST, UPDATE-TRANSLATION-FUNCTION,
109 CONVERSION-KEYS.
110
111 QUAIL-MAP is a data structure to map key strings to translations. For
112 the format, see the documentation of `quail-map-p'.
113
114 DECODE-MAP is an alist of translations and corresponding keys.
115
116 See the documentation of `quail-define-package' for the other elements.")
117
118 ;; Return various slots in the current quail-package.
119
120 (defsubst quail-name ()
121 "Return the name of the current Quail package."
122 (nth 0 quail-current-package))
123 (defsubst quail-title ()
124 "Return the title of the current Quail package."
125 (nth 1 quail-current-package))
126 (defsubst quail-map ()
127 "Return the translation map of the current Quail package."
128 (nth 2 quail-current-package))
129 (defsubst quail-guidance ()
130 "Return an object used for `guidance' feature of the current Quail package.
131 See also the documentation of `quail-define-package'."
132 (nth 3 quail-current-package))
133 (defsubst quail-docstring ()
134 "Return the documentation string of the current Quail package."
135 (nth 4 quail-current-package))
136 (defsubst quail-translation-keymap ()
137 "Return translation keymap in the current Quail package.
138 Translation keymap is a keymap used while translation region is active."
139 (nth 5 quail-current-package))
140 (defsubst quail-forget-last-selection ()
141 "Return `forget-last-selection' flag of the current Quail package.
142 See also the documentation of `quail-define-package'."
143 (nth 6 quail-current-package))
144 (defsubst quail-deterministic ()
145 "Return `deterministic' flag of the current Quail package.
146 See also the documentation of `quail-define-package'."
147 (nth 7 quail-current-package))
148 (defsubst quail-kbd-translate ()
149 "Return `kbd-translate' flag of the current Quail package.
150 See also the documentation of `quail-define-package'."
151 (nth 8 quail-current-package))
152 (defsubst quail-show-layout ()
153 "Return `show-layout' flag of the current Quail package.
154 See also the documentation of `quail-define-package'."
155 (nth 9 quail-current-package))
156 (defsubst quail-decode-map ()
157 "Return decode map of the current Quail package.
158 It is an alist of translations and corresponding keys."
159 (nth 10 quail-current-package))
160 (defsubst quail-maximum-shortest ()
161 "Return `maximum-shortest' flag of the current Quail package.
162 See also the documentation of `quail-define-package'."
163 (nth 11 quail-current-package))
164 (defsubst quail-overlay-plist ()
165 "Return property list of an overly used in the current Quail package."
166 (nth 12 quail-current-package))
167 (defsubst quail-update-translation-function ()
168 "Return a function for updating translation in the current Quail package."
169 (nth 13 quail-current-package))
170 (defsubst quail-conversion-keymap ()
171 "Return conversion keymap in the current Quail package.
172 Conversion keymap is a keymap used while conversion region is active
173 but translation region is not active."
174 (nth 14 quail-current-package))
175
176 (defsubst quail-package (name)
177 "Return Quail package named NAME."
178 (assoc name quail-package-alist))
179
180 (defun quail-add-package (package)
181 "Add Quail package PACKAGE to `quail-package-alist'."
182 (let ((pac (quail-package (car package))))
183 (if pac
184 (setcdr pac (cdr package))
185 (setq quail-package-alist (cons package quail-package-alist)))))
186
187 (defun quail-select-package (name)
188 "Select Quail package named NAME as the current Quail package."
189 (let ((package (quail-package name)))
190 (if (null package)
191 (error "No Quail package `%s'" name))
192 (setq quail-current-package package)
193 (setq-default quail-current-package package)
194 name))
195
196 ;;;###autoload
197 (defun quail-use-package (package-name &rest libraries)
198 "Start using Quail package PACKAGE-NAME.
199 The remaining arguments are libraries to be loaded before using the package."
200 (while libraries
201 (if (not (load (car libraries) t))
202 (progn
203 (with-output-to-temp-buffer "*Help*"
204 (princ "Quail package \"")
205 (princ package-name)
206 (princ "\" can't be activated\n because library \"")
207 (princ (car libraries))
208 (princ "\" is not in `load-path'.
209
210 The most common case is that you have not yet installed appropriate
211 libraries in LEIM (Libraries of Emacs Input Method) which is
212 distributed separately from Emacs.
213
214 Installation of LEIM for Quail is very simple, just copy Quail
215 packages (byte-compiled Emacs Lisp files) to somewhere in your
216 `load-path'.
217
218 LEIM is available from the same ftp directory as Emacs."))
219 (error ""))
220 (setq libraries (cdr libraries))))
221 (quail-select-package package-name)
222 (setq current-input-method-title (quail-title))
223 (quail-mode 1))
224
225 (defun quail-inactivate ()
226 "Turn off Quail input method."
227 (interactive)
228 (throw 'quail-tag t))
229
230 (or (assq 'quail-mode minor-mode-alist)
231 (setq minor-mode-alist
232 (cons '(quail-mode " Quail") minor-mode-alist)))
233
234 (defvar quail-mode-map
235 (let ((map (make-keymap))
236 (i ? ))
237 (while (< i 127)
238 (define-key map (char-to-string i) 'quail-start-translation)
239 (setq i (1+ i)))
240 map)
241 "Keymap for Quail mode.")
242
243 (or (assq 'quail-mode minor-mode-map-alist)
244 (setq minor-mode-map-alist
245 (cons (cons 'quail-mode quail-mode-map) minor-mode-map-alist)))
246
247 ;; Since some Emacs Lisp programs (e.g. viper.el) make
248 ;; minor-mode-map-alist buffer-local, we must be sure to register
249 ;; quail-mode-map in default-value of minor-mode-map-alist.
250 (if (local-variable-p 'minor-mode-map-alist nil)
251 (let ((map (default-value 'minor-mode-map-alist)))
252 (or (assq 'quail-mode map)
253 (set-default 'minor-mode-map-alist (cons 'quail-mode map)))))
254
255 (defvar quail-translation-keymap
256 (let ((map (make-keymap))
257 (i 0))
258 (while (< i ?\ )
259 (define-key map (char-to-string i) 'quail-execute-non-quail-command)
260 (setq i (1+ i)))
261 (while (< i 127)
262 (define-key map (char-to-string i) 'quail-self-insert-command)
263 (setq i (1+ i)))
264 (define-key map "\177" 'quail-delete-last-char)
265 (define-key map "\C-\\" 'quail-inactivate)
266 (define-key map "\C-f" 'quail-next-translation)
267 (define-key map "\C-b" 'quail-prev-translation)
268 (define-key map "\C-n" 'quail-next-translation-block)
269 (define-key map "\C-p" 'quail-prev-translation-block)
270 (define-key map "\C-i" 'quail-completion)
271 (define-key map "\C-@" 'quail-select-current)
272 (define-key map "\C-c" 'quail-abort-translation)
273 (define-key map "\C-h" 'quail-translation-help)
274 ;; 1997/5/26 by MORIOKA Tomohiko
275 ;; modified for XEmacs
276 ;;(define-key map "\e" '(keymap (t . quail-execute-non-quail-command)))
277 (let ((emap (make-sparse-keymap)))
278 (set-keymap-default-binding emap 'quail-execute-non-quail-command)
279 (define-key map "\e" emap)
280 )
281 (define-key map [tab] 'quail-completion)
282 (define-key map [delete] 'quail-delete-last-char)
283 (define-key map [backspace] 'quail-delete-last-char)
284 ;; At last, define default key binding.
285 (set-keymap-default-binding map 'quail-execute-non-quail-command)
286 map)
287 "Keymap used processing translation in Quail mode.
288 This map is activated while translation region is active.")
289
290 (defvar quail-conversion-keymap
291 (let ((map (make-keymap))
292 (i 0))
293 (while (< i ?\ )
294 (define-key map (char-to-string i) 'quail-execute-non-quail-command)
295 (setq i (1+ i)))
296 (while (< i 127)
297 (define-key map (char-to-string i)
298 'quail-start-translation-in-conversion-mode)
299 (setq i (1+ i)))
300 (define-key map "\C-b" 'quail-conversion-backward-char)
301 (define-key map "\C-f" 'quail-conversion-forward-char)
302 (define-key map "\C-a" 'quail-conversion-beginning-of-region)
303 (define-key map "\C-e" 'quail-conversion-end-of-region)
304 (define-key map "\C-d" 'quail-conversion-delete-char)
305 (define-key map "\C-h" 'quail-conversion-help)
306 (define-key map "\C-\\" 'quail-inactivate)
307 ;; 1997/5/26 by MORIOKA Tomohiko
308 ;; modified for XEmacs
309 ;;(define-key map "\e" '(keymap (t . quail-execute-non-quail-command)))
310 (let ((emap (make-sparse-keymap)))
311 (set-keymap-default-binding emap 'quail-execute-non-quail-command)
312 (define-key map "\e" emap)
313 )
314 (define-key map "\177" 'quail-conversion-backward-delete-char)
315 (define-key map [delete] 'quail-conversion-backward-delete-char)
316 (define-key map [backspace] 'quail-conversion-backward-delete-char)
317 ;; At last, define default key binding.
318 (set-keymap-default-binding map 'quail-execute-non-quail-command)
319 map)
320 "Keymap used for processing conversion in Quail mode.
321 This map is activated while convesion region is active but translation
322 region is not active.")
323
324 (defun quail-define-package (name language title
325 &optional guidance docstring translation-keys
326 forget-last-selection deterministic
327 kbd-translate show-layout create-decode-map
328 maximum-shortest overlay-plist
329 update-translation-function
330 conversion-keys)
331 "Define NAME as a new Quail package for input LANGUAGE.
332 TITLE is a string to be displayed at mode-line to indicate this package.
333 Optional arguments are GUIDANCE, DOCSTRING, TRANLSATION-KEYS,
334 FORGET-LAST-SELECTION, DETERMINISTIC, KBD-TRANSLATE, SHOW-LAYOUT,
335 CREATE-DECODE-MAP, MAXIMUM-SHORTEST, OVERLAY-PLIST,
336 UPDATE-TRANSLATION-FUNCTION, and CONVERSION-KEYS.
337
338 GUIDANCE specifies how a guidance string is shown in echo area.
339 If it is t, list of all possible translations for the current key is shown
340 with the currently selected translation being highlighted.
341 If it is an alist, the element has the form (CHAR . STRING). Each character
342 in the current key is searched in the list and the corresponding string is
343 shown.
344 If it is nil, the current key is shown.
345
346 DOCSTRING is the documentation string of this package.
347
348 TRANSLATION-KEYS specifies additional key bindings used while translation
349 region is active. It is an alist of single key character vs. corresponding
350 command to be called.
351
352 FORGET-LAST-SELECTION non-nil means a selected translation is not kept
353 for the future to translate the same key. If this flag is nil, a
354 translation selected for a key is remembered so that it can be the
355 first candidate when the same key is entered later.
356
357 DETERMINISTIC non-nil means the first candidate of translation is
358 selected automatically without allowing users to select another
359 translation for a key. In this case, unselected translations are of
360 no use for an interactive use of Quail but can be used by some other
361 programs. If this flag is non-nil, FORGET-LAST-SELECTION is also set
362 to t.
363
364 KBD-TRANSLATE non-nil means input characters are translated from a
365 user's keyboard layout to the standard keyboard layout. See the
366 documentation of `quail-keyboard-layout' and
367 `quail-keyboard-layout-standard' for more detail.
368
369 SHOW-LAYOUT non-nil means the `quail-help' command should show
370 the user's keyboard layout visually with translated characters.
371 If KBD-TRANSLATE is set, it is desirable to set also this flag unless
372 this package defines no translations for single character keys.
373
374 CREATE-DECODE-MAP non-nil means decode map is also created. A decode
375 map is an alist of translations and corresponding original keys.
376 Although this map is not used by Quail itself, it can be used by some
377 other programs. For instance, Vietnamese supporting needs this map to
378 convert Vietnamese text to VIQR format which uses only ASCII
379 characters to represent Vietnamese characters.
380
381 MAXIMUM-SHORTEST non-nil means break key sequence to get maximum
382 length of the shortest sequence. When we don't have a translation of
383 key \"..ABCD\" but have translations of \"..AB\" and \"CD..\", break
384 the key at \"..AB\" and start translation of \"CD..\". Hangul
385 packages, for instance, use this facility. If this flag is nil, we
386 break the key just at \"..ABC\" and start translation of \"D..\".
387
388 OVERLAY-PLIST if non-nil is a property list put on an overlay which
389 covers Quail translation region.
390
391 UPDATE-TRANSLATION-FUNCTION if non-nil is a function to call to update
392 the current translation region accoding to a new translation data. By
393 default, a tranlated text or a user's key sequence (if no transltion
394 for it) is inserted.
395
396 CONVERSION-KEYS specifies additional key bindings used while
397 conversion region is active. It is an alist of single key character
398 vs. corresponding command to be called."
399 (let (translation-keymap conversion-keymap)
400 (if deterministic (setq forget-last-selection t))
401 (if translation-keys
402 (progn
403 (setq translation-keymap (copy-keymap quail-translation-keymap))
404 (while translation-keys
405 (define-key translation-keymap
406 (car (car translation-keys)) (cdr (car translation-keys)))
407 (setq translation-keys (cdr translation-keys))))
408 (setq translation-keymap quail-translation-keymap))
409 (if conversion-keys
410 (progn
411 (setq conversion-keymap (copy-keymap quail-conversion-keymap))
412 (while conversion-keys
413 (define-key conversion-keymap
414 (car (car conversion-keys)) (cdr (car conversion-keys)))
415 (setq conversion-keys (cdr conversion-keys)))))
416 (quail-add-package
417 (list name title (list nil) guidance (or docstring "")
418 translation-keymap
419 forget-last-selection deterministic kbd-translate show-layout
420 (if create-decode-map (list 'decode-map) nil)
421 maximum-shortest overlay-plist update-translation-function
422 conversion-keymap)))
423 (register-input-method language (list name 'quail-use-package))
424 (quail-select-package name))
425
426 ;; Quail minor mode handlers.
427
428 ;; Setup overlays used in Quail mode.
429 (defun quail-setup-overlays ()
430 (let ((pos (point)))
431 (if (overlayp quail-overlay)
432 (move-overlay quail-overlay pos pos)
433 (setq quail-overlay (make-overlay pos pos nil nil t))
434 (overlay-put quail-overlay 'face 'underline)
435 (let ((l (quail-overlay-plist)))
436 (while l
437 (overlay-put quail-overlay (car l) (car (cdr l)))
438 (setq l (cdr (cdr l))))))
439 (if (overlayp quail-conv-overlay)
440 (move-overlay quail-conv-overlay pos pos)
441 (setq quail-conv-overlay (make-overlay pos pos nil nil t))
442 (overlay-put quail-conv-overlay 'face 'underline)
443 ;;(overlay-put quail-conv-overlay 'modification-hooks
444 ;;'(quail-conv-overlay-modification-hook))
445 )))
446
447 ;; Delete overlays used in Quail mode.
448 (defun quail-delete-overlays ()
449 (if (overlayp quail-overlay)
450 (delete-overlay quail-overlay))
451 (if (overlayp quail-conv-overlay)
452 (delete-overlay quail-conv-overlay)))
453
454 ;; While translating and converting, we enter the recursive edit and
455 ;; exit it frequently, which results in frequent and annoying change
456 ;; of and annoying in mode line. To avoid it, we use a modified
457 ;; mode-line-format.
458 (defvar quail-mode-line-format nil)
459
460 ;; Return a modified mode-line-format which doesn't show the recursive
461 ;; editing level. But, we only pay attention to the top level
462 ;; elements of the current mode-line-format.
463 (defun quail-generate-mode-line-format ()
464 (if (listp mode-line-format)
465 (let ((new (copy-sequence mode-line-format))
466 l elt idx)
467 (setq l new)
468 (while l
469 (setq elt (car l))
470 (if (and (stringp elt)
471 (or (setq idx (string-match "%\\[" elt))
472 (setq idx (string-match "%\\]" elt))))
473 (setcar l (concat (substring elt 0 idx)
474 (substring elt (+ idx 2)))))
475 (setq l (cdr l)))
476 new)
477 mode-line-format))
478
479 (defun quail-mode (&optional arg)
480 "Toggle Quail minor mode.
481 With arg, turn Quail mode on if and only if arg is positive.
482 Try \\[describe-bindings] in Quail mode to see the available key binding.
483 The command \\[describe-input-method] describes the current Quail package."
484 (interactive "P")
485 (setq quail-mode
486 (if (null arg) (null quail-mode)
487 (> (prefix-numeric-value arg) 0)))
488 (if (null quail-mode)
489 ;; Let's turn off Quail mode.
490 (progn
491 (quail-hide-guidance-buf)
492 (quail-delete-overlays)
493 (setq describe-current-input-method-function nil)
494 (setq current-input-method nil)
495 (run-hooks 'quail-mode-exit-hook)
496 (run-hooks 'input-method-inactivate-hook))
497 ;; Let's turn on Quail mode.
498 ;; At first, be sure that quail-mode is at the first element of
499 ;; minor-mode-map-alist.
500 (or (eq (car minor-mode-map-alist) 'quail-mode)
501 (let ((l minor-mode-map-alist))
502 (while (cdr l)
503 (if (eq (car (cdr l)) 'quail-mode)
504 (progn
505 (setcdr l (cdr (cdr l)))
506 (setq l nil))
507 (setq l (cdr l))))
508 (setq minor-mode-map-alist (cons 'quail-mode minor-mode-map-alist))))
509 (if (null quail-current-package)
510 ;; Quail package is not yet selected. Select one now.
511 (let (name)
512 (if quail-package-alist
513 (setq name (car (car quail-package-alist)))
514 (setq quail-mode nil)
515 (error "No Quail package loaded"))
516 (quail-select-package name)))
517 (setq inactivate-current-input-method-function 'quail-mode)
518 (setq describe-current-input-method-function 'quail-help)
519 (setq quail-mode-line-format (quail-generate-mode-line-format))
520 (quail-delete-overlays)
521 (quail-show-guidance-buf)
522 ;; If we are in minibuffer, turn off Quail mode before exiting.
523 (if (eq (selected-window) (minibuffer-window))
524 (add-hook 'minibuffer-exit-hook 'quail-exit-from-minibuffer))
525 (make-local-hook 'post-command-hook)
526 (run-hooks 'quail-mode-hook)
527 (run-hooks 'input-method-activate-hook))
528 (force-mode-line-update))
529
530 (defun quail-exit-from-minibuffer ()
531 (if quail-mode (quail-mode -1))
532 (if (<= (minibuffer-depth) 1)
533 (remove-hook 'minibuffer-exit-hook 'quail-exit-from-minibuffer)))
534
535 (defvar quail-saved-overriding-local-map nil)
536 (defvar quail-saved-current-buffer nil)
537
538 ;; Toggle `quail-mode'. This function is added to `post-command-hook'
539 ;; in Quail mode, to turn Quail mode temporarily off, or back on
540 ;; after one non-Quail command.
541 (defun quail-toggle-mode-temporarily ()
542 (if quail-mode
543 ;; We are going to handle following events out of Quail mode.
544 (setq quail-mode nil
545 quail-saved-overriding-local-map overriding-local-map
546 quail-saved-current-buffer (current-buffer)
547 overriding-local-map nil)
548 ;; We have just executed one non-Quail command. We don't need
549 ;; this hook any more.
550 (remove-hook 'post-command-hook 'quail-toggle-mode-temporarily t)
551 ;; If the command changed the current buffer, we should not go
552 ;; back to Quail mode.
553 (if (not (eq (current-buffer) quail-saved-current-buffer))
554 (throw 'quail-tag nil)
555 ;; Let's go back to Quail mode.
556 (setq quail-mode t)
557 (setq overriding-local-map quail-saved-overriding-local-map)
558 ;; If whole text in conversion area was deleted, exit from the
559 ;; recursive edit.
560 (let ((start (overlay-start quail-conv-overlay)))
561 (if (and start (= start (overlay-end quail-conv-overlay)))
562 (throw 'quail-tag nil)))
563 )))
564
565 (defun quail-execute-non-quail-command ()
566 "Execute one non-Quail command in Quail mode.
567 The current translation and conversion are terminated."
568 (interactive)
569 (setq unread-command-events (cons last-input-event unread-command-events))
570 (quail-delete-overlays)
571 (if (buffer-live-p quail-guidance-buf)
572 (save-excursion
573 (set-buffer quail-guidance-buf)
574 (erase-buffer)))
575 (throw 'quail-tag nil))
576
577 ;; Keyboard layout translation handlers.
578
579 ;; Some Quail packages provide localized keyboard simulation which
580 ;; requires a particular keyboard layout. In this case, what we need
581 ;; is locations of keys the user entered, not character codes
582 ;; generated by those keys. However, for the moment, there's no
583 ;; common way to get such information. So, we ask a user to give
584 ;; information of his own keyboard layout, then translate it to the
585 ;; standard layout which we defined so that all Quail packages depend
586 ;; just on it.
587
588 (defconst quail-keyboard-layout-standard
589 "\
590 \
591 1!2@3#4$5%6^7&8*9(0)-_=+`~ \
592 qQwWeErRtTyYuUiIoOpP[{]} \
593 aAsSdDfFgGhHjJkKlL;:'\"\\| \
594 zZxXcCvVbBnNmM,<.>/? \
595 "
596 "Standard keyboard layout of printable characters Quail assumes.
597 See the documentation of `quail-keyboard-layout' for this format.
598 This layout is almost the same as that of VT100,
599 but the location of key \\ (backslash) is just right of key ' (single-quote),
600 not right of RETURN key.")
601
602 (defvar quail-keyboard-layout quail-keyboard-layout-standard
603 "A string which represents physical key layout of a particular keyboard.
604 We assume there are six rows and each row has 15 keys (columns),
605 the first row is above the `1' - `0' row,
606 the first column of the second row is left of key `1',
607 the first column of the third row is left of key `q',
608 the first column of the fourth row is left of key `a',
609 the first column of the fifth row is left of key `z',
610 the sixth row is below the `z' - `/' row.
611 Nth (N is even) and (N+1)th characters in the string are non-shifted
612 and shifted characters respectively at the same location.
613 The location of Nth character is row (N / 30) and column ((N mod 30) / 2).")
614
615 (defconst quail-keyboard-layout-len 180)
616
617 ;; Here we provide several examples of famous keyboard layouts.
618
619 (defvar quail-keyboard-layout-alist
620 (list
621 '("sun-type3" . "\
622 \
623 1!2@3#4$5%6^7&8*9(0)-_=+\\|`~\
624 qQwWeErRtTyYuUiIoOpP[{]} \
625 aAsSdDfFgGhHjJkKlL;:'\" \
626 zZxXcCvVbBnNmM,<.>/? \
627 ")
628 (cons "standard" quail-keyboard-layout-standard))
629 "Alist of keyboard names and corresponding layout strings.
630 See the documentation of `quail-keyboard-layout' for the format of
631 the layout string.")
632
633 (defun quail-set-keyboard-layout (kbd-type)
634 "Set the current keyboard layout to the same as keyboard KBD-TYPE.
635
636 Since some Quail packages depends on a physical layout of keys (not
637 characters generated by them), those are created by assuming the
638 standard layout defined in `quail-keyboard-layout-standard'. This
639 function tells Quail system the layout of your keyboard so that what
640 you type is correctly handled."
641 (interactive
642 (let* ((completing-ignore-case t)
643 (type (completing-read "Keyboard type: "
644 quail-keyboard-layout-alist)))
645 (list type)))
646 (let ((layout (assoc kbd-type quail-keyboard-layout-alist)))
647 (if (null layout)
648 ;; Here, we had better ask a user to define his own keyboard
649 ;; layout interactively.
650 (error "Unknown keyboard type `%s'" kbd-type))
651 (setq quail-keyboard-layout (cdr layout))))
652
653 (defun quail-keyboard-translate (ch)
654 "Translate CHAR according to `quail-keyboard-layout' and return the result."
655 (if (eq quail-keyboard-layout quail-keyboard-layout-standard)
656 ch
657 (let ((i 0))
658 (while (and (< i quail-keyboard-layout-len)
659 (/= ch (aref quail-keyboard-layout i)))
660 (setq i (1+ i)))
661 (if (= i quail-keyboard-layout-len)
662 (error "Character `%c' not found in your keyboard layout" ch))
663 (aref quail-keyboard-layout-standard i))))
664
665 ;; Quail map
666
667 (defsubst quail-map-p (object)
668 "Return t if OBJECT is a Quail map.
669
670 A Quail map holds information how a particular key should be translated.
671 Its format is (TRANSLATION . ALIST).
672 TRANSLATION is either a character, or a cons (INDEX . VECTOR).
673 In the latter case, each element of VECTOR is a candidate for the translation,
674 and INDEX points the currently selected translation.
675
676 ALIST is normally a list of elements that look like (CHAR . DEFN),
677 where DEFN is another Quail map for a longer key (CHAR added to the
678 current key). It may also be a symbol of a function which returns an
679 alist of the above format.
680
681 Just after a Quail package is read, TRANSLATION may be a string or a
682 vector. Then each element of the string or vector is a candidate for
683 the translation. These objects are transformed to cons cells in the
684 format \(INDEX . VECTOR), as described above."
685 (and (consp object)
686 (let ((translation (car object)))
687 (or (integerp translation) (consp translation) (null translation)
688 (vectorp translation) (stringp translation)
689 (symbolp translation)))
690 (let ((alist (cdr object)))
691 (or (listp alist) (symbolp alist)))))
692
693 (defmacro quail-define-rules (&rest rules)
694 "Define translation rules of the current Quail package.
695 Each argument is a list of KEY and TRANSLATION.
696 KEY is a string meaning a sequence of keystrokes to be translated.
697 TRANSLATION is a character, a string, a vector, a Quail map, or a function.
698 It it is a character, it is the sole translation of KEY.
699 If it is a string, each character is a candidate for the translation.
700 If it is a vector, each element (string or character) is a candidate
701 for the translation.
702 In these cases, a key specific Quail map is generated and assigned to KEY.
703
704 If TRANSLATION is a Quail map or a function symbol which returns a Quail map,
705 it is used to handle KEY."
706 `(quail-install-map
707 ',(let ((l rules)
708 (map (list nil)))
709 (while l
710 (quail-defrule-internal (car (car l)) (car (cdr (car l))) map)
711 (setq l (cdr l)))
712 map)))
713
714 (defun quail-install-map (map)
715 "Install the Quail map MAP in the current Quail package.
716 The installed map can be referred by the function `quail-map'."
717 (if (null quail-current-package)
718 (error "No current Quail package"))
719 (if (null (quail-map-p map))
720 (error "Invalid Quail map `%s'" map))
721 (setcar (cdr (cdr quail-current-package)) map))
722
723 (defun quail-defrule (key translation &optional name)
724 "Add one translation rule, KEY to TRANSLATION, in the current Quail package.
725 KEY is a string meaning a sequence of keystrokes to be translated.
726 TRANSLATION is a character, a string, a vector, a Quail map, or a function.
727 It it is a character, it is the sole translation of KEY.
728 If it is a string, each character is a candidate for the translation.
729 If it is a vector, each element (string or character) is a candidate
730 for the translation.
731 In these cases, a key specific Quail map is generated and assigned to KEY.
732
733 If TRANSLATION is a Quail map or a function symbol which returns a Quail map,
734 it is used to handle KEY.
735 Optional argument NAME, if specified, says which Quail package
736 to define this translation rule in. The default is to define it in the
737 current Quail package."
738 (if name
739 (let ((package (quail-package name)))
740 (if (null package)
741 (error "No Quail package `%s'" name))
742 (setq quail-current-package package)))
743 (quail-defrule-internal key translation (quail-map)))
744
745 ;; Define KEY as TRANS in a Quail map MAP.
746 (defun quail-defrule-internal (key trans map)
747 (if (null (stringp key))
748 "Invalid Quail key `%s'" key)
749 ;; 1997/5/26 by MORIOKA Tomohiko
750 ;; modified for XEmacs
751 (if (not (or (characterp trans) (stringp trans) (vectorp trans)
752 (symbolp trans)
753 (quail-map-p trans)))
754 (error "Invalid Quail translation `%s'" trans))
755 (if (null (quail-map-p map))
756 (error "Invalid Quail map `%s'" map))
757 (let ((len (length key))
758 (idx 0)
759 ch entry)
760 (while (< idx len)
761 (if (null (consp map))
762 ;; We come here, for example, when we try to define a rule
763 ;; for "ABC" but a rule for "AB" is already defined as a
764 ;; symbol.
765 (error "Quail key %s is too long" key))
766 (setq ch (aref key idx)
767 entry (assq ch (cdr map)))
768 (if (null entry)
769 (progn
770 (setq entry (cons ch (list nil)))
771 (setcdr map (cons entry (cdr map)))))
772 (setq map (cdr entry))
773 (setq idx (1+ idx)))
774 (if (symbolp trans)
775 (if (cdr map)
776 ;; We come here, for example, when we try to define a rule
777 ;; for "AB" as a symbol but a rule for "ABC" is already
778 ;; defined.
779 (error "Quail key %s is too short" key)
780 (setcdr entry trans))
781 (if (quail-map-p trans)
782 (if (not (listp (cdr map)))
783 ;; We come here, for example, when we try to define a rule
784 ;; for "AB" as a symbol but a rule for "ABC" is already
785 ;; defined.
786 (error "Quail key %s is too short" key)
787 (if (not (listp (cdr trans)))
788 (if (cdr map)
789 ;; We come here, for example, when we try to
790 ;; define a rule for "AB" as a symbol but a rule
791 ;; for "ABC" is already defined.
792 (error "Quail key %s is too short" key)
793 (setcdr entry trans))
794 (setcdr entry (append trans (cdr map)))))
795 (setcar map trans)))))
796
797 (defun quail-get-translation (map key len)
798 "Return the translation specified in Quail map MAP for KEY of length LEN.
799 The translation is either a character or a cons of the form (INDEX . VECTOR),
800 where VECTOR is a vector of candidates (character or string) for
801 the translation, and INDEX points into VECTOR to specify the currently
802 selected translation."
803 (let ((def (car map)))
804 (if (and def (symbolp def))
805 ;; DEF is a symbol of a function which returns valid translation.
806 (setq def (funcall def key len)))
807 (cond
808 ((or (characterp def) (consp def))
809 def)
810
811 ((null def)
812 ;; No translation.
813 nil)
814
815 ((stringp def)
816 ;; Each character in DEF is a candidate of translation. Reform
817 ;; it as (INDEX . VECTOR).
818 (setq def (string-to-vector def))
819 ;; But if the length is 1, we don't need vector but a single
820 ;; character as the translation.
821 (if (= (length def) 1)
822 (aref def 0)
823 (cons 0 def)))
824
825 ((vectorp def)
826 ;; Each element (string or character) in DEF is a candidate of
827 ;; translation. Reform it as (INDEX . VECTOR).
828 (cons 0 def))
829
830 (t
831 (error "Invalid object in Quail map: %s" def)))))
832
833 (defun quail-lookup-key (key len)
834 "Lookup KEY of length LEN in the current Quail map and return the definition.
835 The returned value is a Quail map specific to KEY."
836 (let ((idx 0)
837 (map (quail-map))
838 (kbd-translate (quail-kbd-translate))
839 slot ch translation)
840 (while (and map (< idx len))
841 (setq ch (if kbd-translate (quail-keyboard-translate (aref key idx))
842 (aref key idx)))
843 (setq idx (1+ idx))
844 (if (and (cdr map) (symbolp (cdr map)))
845 (setcdr map (funcall (cdr map) key idx)))
846 (setq slot (assq ch (cdr map)))
847 (if (and (cdr slot) (symbolp (cdr slot)))
848 (setcdr slot (funcall (cdr slot) key idx)))
849 (setq map (cdr slot)))
850 (if (and map (setq translation (quail-get-translation map key len)))
851 (progn
852 ;; We may have to reform car part of MAP.
853 (if (not (equal (car map) translation))
854 (setcar map translation))
855 (if (consp translation)
856 (progn
857 (setq quail-current-translations translation)
858 (if (quail-forget-last-selection)
859 (setcar quail-current-translations 0))))
860 ;; We may have to reform cdr part of MAP.
861 (if (and (cdr map) (symbolp (cdr map)))
862 (progn
863 (setcdr map (funcall (cdr map) key len))))
864 ))
865 map))
866
867 (defun quail-conv-overlay-modification-hook (overlay after &rest ignore)
868 (if (and after
869 (= (overlay-start overlay) (overlay-end overlay)))
870 ;; Whole text in conversion area was deleted. Let's exit from
871 ;; the recursive edit.
872 (throw 'exit nil)))
873
874 (defvar quail-suppress-conversion nil
875 "If non-nil, suppress converting facility of the current Quail package.")
876
877 ;; If set to non-nil, exit conversion mode before starting new translation.
878 (defvar quail-exit-conversion-mode nil)
879
880 (defun quail-start-translation ()
881 "Start translating the typed character in Quail mode."
882 (interactive "*")
883 (setq unread-command-events
884 (cons last-command-event unread-command-events))
885 ;; Check the possibility of translating the last key.
886 ;; 1997/5/26 by MORIOKA Tomohiko <morioka@jaist.ac.jp>
887 ;; modified for XEmacs
888 (if (assq (event-key last-command-event) (cdr (quail-map)))
889 ;; Ok, we can start translation.
890 (let ((mode-line-format quail-mode-line-format))
891 (quail-setup-overlays)
892 (if (catch 'quail-tag
893 (if (and (not quail-suppress-conversion)
894 (quail-conversion-keymap))
895 ;; We must start translation in conversion mode.
896 (let ((overriding-local-map (quail-conversion-keymap)))
897 (setq quail-exit-conversion-mode nil)
898 (recursive-edit)
899 (if (and auto-fill-function
900 (> (current-column) (current-fill-column)))
901 (run-hooks 'auto-fill-function)))
902 (let ((overriding-local-map (quail-translation-keymap)))
903 (setq quail-current-key "")
904 (recursive-edit)))
905 (let ((start (overlay-start quail-conv-overlay))
906 (end (overlay-end quail-conv-overlay)))
907 (if (and start end
908 (prog1 (< start end)
909 (delete-overlay quail-conv-overlay)))
910 (run-hooks 'input-method-after-insert-chunk-hook)))
911 nil)
912 ;; Someone has thrown a tag with value t, which means
913 ;; we should turn Quail mode off.
914 (quail-mode -1)))
915 ;; Since the typed character doesn't start any translation, handle
916 ;; it out of Quail mode. We come back to Quail mode later because
917 ;; function `quail-toggle-mode-temporarily' is in
918 ;; `post-command-hook'.
919 (add-hook 'post-command-hook 'quail-toggle-mode-temporarily nil t)))
920
921 (defsubst quail-point-in-conversion-region ()
922 "Return non-nil value if the point is in conversion region of Quail mode."
923 (let (start pos)
924 (and (setq start (overlay-start quail-conv-overlay))
925 (>= (setq pos (point)) start)
926 (<= pos (overlay-end quail-conv-overlay)))))
927
928 (defun quail-start-translation-in-conversion-mode ()
929 "Start translating the typed character in conversion mode of Quail mode."
930 (interactive "*")
931 (setq unread-command-events
932 (cons last-command-event unread-command-events))
933 (if (or quail-exit-conversion-mode
934 (not (quail-point-in-conversion-region)))
935 (progn
936 ;; We must start translation with new conversion region.
937 (setq quail-exit-conversion-mode nil)
938 (throw 'exit nil)))
939 ;; Check the possibility of translating the last key.
940 ;; 1997/5/26 by MORIOKA Tomohiko <morioka@jaist.ac.jp>
941 ;; modified for XEmacs
942 (if (assq (event-key last-command-event) (cdr (quail-map)))
943 ;; Ok, we can start translation.
944 (let ((overriding-local-map (quail-translation-keymap)))
945 (setq quail-current-key "")
946 (move-overlay quail-overlay (point) (point))
947 (recursive-edit))
948 ;; Since the typed character doesn't start any translation, handle
949 ;; it out of Quail mode. We come back to Quail mode later because
950 ;; function `quail-toggle-mode-temporarily' is in
951 ;; `post-command-hook'.
952 (add-hook 'post-command-hook 'quail-toggle-mode-temporarily nil t)))
953
954 (defun quail-terminate-translation ()
955 "Terminate the translation of the current key."
956 (let ((start (overlay-start quail-overlay)))
957 (if (and start
958 (< start (overlay-end quail-overlay)))
959 ;; Here we simulate self-insert-command.
960 (let (last-command-char)
961 (goto-char start)
962 ;; The first one might want to expand an abbrev.
963 (setq last-command-char (following-char))
964 (delete-char 1)
965 (self-insert-command 1)
966 (let ((end (overlay-end quail-overlay)))
967 (if (and end (< (point) end))
968 (if overwrite-mode
969 (while (< (point) end)
970 (setq last-command-char (following-char))
971 (delete-char 1)
972 (self-insert-command 1))
973 ;; The last one might still want to auto-fill.
974 (goto-char end)
975 (let ((last-command-char (preceding-char)))
976 (delete-char -1)
977 (self-insert-command 1))))))))
978 (delete-overlay quail-overlay)
979 (if (buffer-live-p quail-guidance-buf)
980 (save-excursion
981 (set-buffer quail-guidance-buf)
982 (erase-buffer)))
983 (throw 'exit nil))
984
985 (defsubst quail-delete-region ()
986 "Delete the text in the current translation region of Quail."
987 (let ((start (overlay-start quail-overlay))
988 (end (overlay-end quail-overlay)))
989 (and start end (delete-region start end))))
990
991 (defun quail-select-current ()
992 "Select the current text shown in Quail translation region."
993 (interactive)
994 (quail-terminate-translation))
995
996 ;; Update the current translation status according to CONTROL-FLAG.
997 ;; If CONTROL-FLAG is integer value, it is the number of keys in the
998 ;; head quail-current-key which can be translated. The remaining keys
999 ;; are put back to unread-command-events to be handled again.
1000 ;; If CONTROL-FLAG is t, terminate the translation for the whole keys
1001 ;; in quail-current-key.
1002 ;; If CONTROL-FLAG is nil, proceed the translation with more keys.
1003
1004 (defun quail-update-translation (control-flag)
1005 (quail-delete-region)
1006 (let ((func (quail-update-translation-function)))
1007 (if func
1008 (funcall func control-flag)
1009 (if (numberp control-flag)
1010 (let ((len (length quail-current-key)))
1011 (while (> len control-flag)
1012 (setq len (1- len))
1013 (setq unread-command-events
1014 ;; 1997/5/26 by MORIOKA Tomohiko
1015 ;; modified for XEmacs
1016 (cons (character-to-event (aref quail-current-key len))
1017 unread-command-events)))
1018 (insert (or quail-current-str
1019 (substring quail-current-key 0 len))))
1020 (insert (or quail-current-str quail-current-key)))))
1021 (quail-update-guidance)
1022 (if control-flag
1023 (quail-terminate-translation)))
1024
1025 (defun quail-self-insert-command ()
1026 "Add the typed character to the key for translation."
1027 (interactive "*")
1028 ;; 1997/5/26 by MORIOKA Tomohiko <morioka@jaist.ac.jp>
1029 ;; modified for XEmacs
1030 (setq quail-current-key
1031 (concat quail-current-key (char-to-string
1032 (event-to-character last-command-event))))
1033 (quail-update-translation (quail-translate-key)))
1034
1035 (defun quail-translate-key ()
1036 "Translate the current key sequence according to the current Quail map.
1037 Return t if we can terminate the translation.
1038 Return nil if the current key sequence may be followed by more keys.
1039 Return number if we can't find any translation for the current key
1040 sequence. The number is the count of valid keys in the current
1041 sequence counting from the head."
1042 (let* ((len (length quail-current-key))
1043 (map (quail-lookup-key quail-current-key len))
1044 def ch)
1045 (if map
1046 (let ((def (car map)))
1047 (setq quail-current-str
1048 (if (consp def) (aref (cdr def) (car def)) def))
1049 ;; Return t only if we can terminate the current translation.
1050 (and
1051 ;; No alternative translations.
1052 (or (null (consp def)) (= (length (cdr def)) 1))
1053 ;; No translation for the longer key.
1054 (null (cdr map))
1055 ;; No shorter breaking point.
1056 (or (null (quail-maximum-shortest))
1057 (< len 3)
1058 (null (quail-lookup-key quail-current-key (1- len)))
1059 (null (quail-lookup-key
1060 (substring quail-current-key -2 -1) 1)))))
1061
1062 ;; There's no translation for the current key sequence. Before
1063 ;; giving up, we must check two possibilities.
1064 (cond ((and
1065 (quail-maximum-shortest)
1066 (>= len 4)
1067 (setq def (car (quail-lookup-key quail-current-key (- len 2))))
1068 (quail-lookup-key (substring quail-current-key -2) 2))
1069 ;; Now the sequence is "...ABCD", which can be split into
1070 ;; "...AB" and "CD..." to get valid translation.
1071 ;; At first, get translation of "...AB".
1072 (setq quail-current-str
1073 (if (consp def) (aref (cdr def) (car def)) def))
1074 ;; Then, return the length of "...AB".
1075 (- len 2))
1076
1077 ((and quail-current-translations
1078 (not (quail-deterministic))
1079 (setq ch (aref quail-current-key (1- len)))
1080 (>= ch ?0) (<= ch ?9))
1081 ;; A numeric key is entered to select a desirable translation.
1082 (setq quail-current-key (substring quail-current-key 0 -1))
1083 (quail-select-translation
1084 (+ (* (/ (car quail-current-translations) 10) 10)
1085 ;; We treat key 1,2..,9,0 as specifying 0,1,..8,9.
1086 (if (= ch ?0) 9 (- ch ?1))))
1087 ;; And, we can terminate the current translation.
1088 t)
1089
1090 (t
1091 ;; No way to handle the last character in this context.
1092 (1- len))))))
1093
1094 (defun quail-next-translation ()
1095 "Select next translation in the current batch of candidates."
1096 (interactive)
1097 (if quail-current-translations
1098 (progn
1099 (quail-select-translation (1+ (car quail-current-translations)))
1100 (quail-update-translation nil))
1101 (beep)))
1102
1103 (defun quail-prev-translation ()
1104 "Select previous translation in the current batch of candidates."
1105 (interactive)
1106 (if quail-current-translations
1107 (progn
1108 (quail-select-translation (1- (car quail-current-translations)))
1109 (quail-update-translation nil))
1110 (beep)))
1111
1112 (defun quail-next-translation-block ()
1113 "Select the next batch of 10 translation candidates."
1114 (interactive)
1115 (if quail-current-translations
1116 (let ((limit (1- (length (cdr quail-current-translations))))
1117 (n (car quail-current-translations)))
1118 (if (< (/ n 10) (/ limit 10))
1119 (progn
1120 (quail-select-translation (min (+ n 10) limit))
1121 (quail-update-translation nil))
1122 ;; We are already at the last block.
1123 (beep)))
1124 (beep)))
1125
1126 (defun quail-prev-translation-block ()
1127 "Select the previous batch of 10 translation candidates."
1128 (interactive)
1129 (if (and quail-current-translations
1130 (>= (car quail-current-translations) 10))
1131 (progn
1132 (quail-select-translation (- (car quail-current-translations) 10))
1133 (quail-update-translation nil))
1134 (beep)))
1135
1136 (defun quail-select-translation (n)
1137 "Select Nth translation in the current batch of translation candidates."
1138 (if (or (< n 0) (>= n (length (cdr quail-current-translations))))
1139 (beep)
1140 (setcar quail-current-translations n)
1141 (setq quail-current-str (aref (cdr quail-current-translations) n))))
1142
1143 (defun quail-abort-translation ()
1144 "Abort translation and delete the current Quail key sequence."
1145 (interactive)
1146 (quail-delete-region)
1147 (quail-terminate-translation))
1148
1149 (defun quail-delete-last-char ()
1150 "Delete the last input character from the current Quail key sequence."
1151 (interactive)
1152 (if (= (length quail-current-key) 1)
1153 (quail-abort-translation)
1154 (setq quail-current-key (substring quail-current-key 0 -1))
1155 (quail-update-translation (quail-translate-key))))
1156
1157 ;; For conversion mode.
1158
1159 (defun quail-conversion-backward-char ()
1160 (interactive)
1161 (if (<= (point) (overlay-start quail-conv-overlay))
1162 (error "Beginning of conversion region"))
1163 (forward-char -1))
1164
1165 (defun quail-conversion-forward-char ()
1166 (interactive)
1167 (if (>= (point) (overlay-end quail-conv-overlay))
1168 (error "End of conversion region"))
1169 (forward-char 1))
1170
1171 (defun quail-conversion-beginning-of-region ()
1172 (interactive)
1173 (goto-char (overlay-start quail-conv-overlay)))
1174
1175 (defun quail-conversion-end-of-region ()
1176 (interactive)
1177 (goto-char (overlay-end quail-conv-overlay)))
1178
1179 (defun quail-conversion-delete-char ()
1180 (interactive)
1181 (if (>= (point) (overlay-end quail-conv-overlay))
1182 (error "End of conversion region"))
1183 (delete-char 1)
1184 (if (= (overlay-start quail-conv-overlay)
1185 (overlay-end quail-conv-overlay))
1186 (throw 'quail-tag nil)))
1187
1188 (defun quail-conversion-backward-delete-char ()
1189 (interactive)
1190 (if (<= (point) (overlay-start quail-conv-overlay))
1191 (error "Beginning of conversion region"))
1192 (delete-char -1)
1193 (if (= (overlay-start quail-conv-overlay)
1194 (overlay-end quail-conv-overlay))
1195 (throw 'quail-tag nil)))
1196
1197 (defun quail-do-conversion (func &rest args)
1198 "Call FUNC to convert text in the current conversion region of Quail.
1199 Remaining args are for FUNC."
1200 (delete-overlay quail-overlay)
1201 (apply func args))
1202
1203 (defun quail-no-conversion ()
1204 "Do no conversion of the current conversion region of Quail."
1205 (interactive)
1206 (throw 'exit nil))
1207
1208 ;; Guidance, Completion, and Help buffer handlers.
1209
1210 (defun quail-show-guidance-buf ()
1211 "Display a Quail guidance buffer in some window.
1212 Create the buffer if it does not exist yet.
1213 The window is normally shown in a minibuffer,
1214 but if the selected window is a minibuffer, it is shown in
1215 the bottommost ordinary window."
1216
1217 (if (or (null input-method-tersely-flag)
1218 (not (eq (selected-window) (minibuffer-window))))
1219 (progn
1220 ;; At first, setup a guidance buffer.
1221 (or (buffer-live-p quail-guidance-buf)
1222 (setq quail-guidance-buf
1223 (get-buffer-create " *Quail-guidance*")))
1224 (save-excursion
1225 (let ((title (quail-title)))
1226 (set-buffer quail-guidance-buf)
1227 ;; Show the title of Quail package in the left of mode-line.
1228 (setq current-input-method nil)
1229 (setq current-input-method-title title)
1230 (setq mode-line-format (cons '("[" current-input-method-title "]")
1231 default-mode-line-format))
1232 (erase-buffer)
1233 (or (overlayp quail-overlay)
1234 (progn
1235 (setq quail-overlay (make-overlay 1 1))
1236 (overlay-put quail-overlay 'face 'highlight)))
1237 (delete-overlay quail-overlay)
1238 (set-buffer-modified-p nil)))
1239 (bury-buffer quail-guidance-buf)
1240
1241 ;; Then, display it in an appropriate window.
1242 (if (not (get-buffer-window quail-guidance-buf))
1243 ;; Guidance buffer is not yet shown in any window.
1244 (let ((win (minibuffer-window)))
1245 (if (eq (selected-window) win)
1246 ;; Since we are in minibuffer, we can't use it for guidance.
1247 ;; Let's find the bottom window.
1248 (let (height)
1249 (setq win (window-at 0 (- (frame-height) 2)))
1250 (setq height (window-height win))
1251 ;; If WIN is too tall, split it vertically and use
1252 ;; the lower one.
1253 (if (>= height 4)
1254 (let ((window-min-height 2))
1255 ;; Here, `split-window' returns a lower window
1256 ;; which is what we wanted.
1257 (setq win (split-window win (- height 2)))))
1258 (set-window-buffer win quail-guidance-buf)
1259 (set-window-dedicated-p win t))
1260 (set-window-buffer win quail-guidance-buf))))))
1261
1262 ;; And, create a buffer for completion.
1263 (or (buffer-live-p quail-completion-buf)
1264 (progn
1265 (setq quail-completion-buf (get-buffer-create "*Quail Completions*"))
1266 (save-excursion
1267 (set-buffer quail-completion-buf)
1268 (setq quail-overlay (make-overlay 1 1))
1269 (overlay-put quail-overlay 'face 'highlight))))
1270 (bury-buffer quail-completion-buf))
1271
1272 (defun quail-hide-guidance-buf ()
1273 "Hide the Quail guidance buffer."
1274 (let* ((win (minibuffer-window))
1275 (buf (window-buffer win)))
1276 (if (eq buf quail-guidance-buf)
1277 ;; Quail guidance buffer is at echo area. Vacate it to the
1278 ;; deepest minibuffer.
1279 (set-window-buffer win (format " *Minibuf-%d*" (minibuffer-depth)))
1280 ;; Delete the window for guidance buffer.
1281 (if (or (null input-method-tersely-flag)
1282 (not (eq (selected-window) (minibuffer-window))))
1283 (progn
1284 (setq win (get-buffer-window quail-guidance-buf))
1285 (set-window-dedicated-p win nil)
1286 (delete-window win))))))
1287
1288 (defun quail-update-guidance ()
1289 "Update the Quail guidance buffer and completion buffer (if displayed now)."
1290 ;; Update guidance buffer.
1291 (if (or (null input-method-tersely-flag)
1292 (not (eq (selected-window) (minibuffer-window))))
1293 (let ((guidance (quail-guidance)))
1294 (cond ((eq guidance t)
1295 ;; Show the current possible translations.
1296 (quail-show-translations))
1297 ((null guidance)
1298 ;; Show the current input keys.
1299 (let ((key quail-current-key))
1300 (save-excursion
1301 (set-buffer quail-guidance-buf)
1302 (erase-buffer)
1303 (insert key))))
1304 ((listp guidance)
1305 ;; Show alternative characters specified in this alist.
1306 (let* ((key quail-current-key)
1307 (len (length key))
1308 (i 0)
1309 ch alternative)
1310 (save-excursion
1311 (set-buffer quail-guidance-buf)
1312 (erase-buffer)
1313 (while (< i len)
1314 (setq ch (aref key i))
1315 (setq alternative (cdr (assoc ch guidance)))
1316 (insert (or alternative ch))
1317 (setq i (1+ i)))))))))
1318
1319 ;; Update completion buffer if displayed now. We highlight the
1320 ;; selected candidate string in *Completion* buffer if any.
1321 (let ((win (get-buffer-window quail-completion-buf))
1322 key str pos)
1323 (if win
1324 (save-excursion
1325 (setq str (if (stringp quail-current-str)
1326 quail-current-str
1327 (if (numberp quail-current-str)
1328 (char-to-string quail-current-str)))
1329 key quail-current-key)
1330 (set-buffer quail-completion-buf)
1331 (goto-char (point-min))
1332 (if (null (search-forward (concat " " key ":") nil t))
1333 (delete-overlay quail-overlay)
1334 (setq pos (point))
1335 (if (and str (search-forward (concat "." str) nil t))
1336 (move-overlay quail-overlay (1+ (match-beginning 0)) (point))
1337 (move-overlay quail-overlay (match-beginning 0) (point)))
1338 ;; Now POS points end of KEY and (point) points end of STR.
1339 (if (pos-visible-in-window-p (point) win)
1340 ;; STR is already visible.
1341 nil
1342 ;; We want to make both KEY and STR visible, but if the
1343 ;; window is too short, make at least STR visible.
1344 (setq pos (progn (point) (goto-char pos)))
1345 (beginning-of-line)
1346 (set-window-start win (point))
1347 (if (not (pos-visible-in-window-p pos win))
1348 (set-window-start win pos))
1349 ))))))
1350
1351 (defun quail-show-translations ()
1352 "Show the current possible translations."
1353 (let ((key quail-current-key)
1354 (map (quail-lookup-key quail-current-key (length quail-current-key))))
1355 (save-excursion
1356 (set-buffer quail-guidance-buf)
1357 (erase-buffer)
1358
1359 ;; Show the current key.
1360 (insert key)
1361
1362 ;; Show possible following keys.
1363 (if (cdr map)
1364 (let ((l (cdr map)))
1365 (insert "[")
1366 (while l
1367 (insert (car (car l)))
1368 (setq l (cdr l)))
1369 (insert "]")))
1370
1371 ;; Show list of translations.
1372 (if (consp (car map))
1373 (let* ((idx (car (car map)))
1374 (translations (cdr (car map)))
1375 (from (* (/ idx 10) 10))
1376 (to (min (+ from 10) (length translations))))
1377 (indent-to 10)
1378 (insert (format "(%d/%d)"
1379 (1+ (/ from 10))
1380 (1+ (/ (length translations) 10))))
1381 (while (< from to)
1382 ;; We show the last digit of FROM, but by changing
1383 ;; 0,1,..,9 to 1,2,..,0.
1384 (insert (format " %d."
1385 (if (= (% from 10) 9) 0 (1+ (% from 10)))))
1386 (let ((pos (point)))
1387 (insert (aref translations from))
1388 (if (= idx from)
1389 (move-overlay quail-overlay pos (point))))
1390 (setq from (1+ from)))))
1391 )))
1392
1393 (defun quail-completion ()
1394 "List all completions for the current key.
1395 All possible translations of the current key and whole possible longer keys
1396 are shown."
1397 (interactive)
1398 (let ((key quail-current-key)
1399 (map (quail-lookup-key quail-current-key (length quail-current-key))))
1400 (save-excursion
1401 (set-buffer quail-completion-buf)
1402 (erase-buffer)
1403 (insert "Possible completion and corresponding translations are:\n")
1404 (quail-completion-1 key map 1)
1405 (goto-char (point-min))
1406 (display-buffer (current-buffer)))
1407 (quail-update-guidance)))
1408
1409 ;; List all completions of KEY in MAP with indentation INDENT.
1410 (defun quail-completion-1 (key map indent)
1411 (let ((len (length key)))
1412 (indent-to indent)
1413 (insert key ":")
1414 (if (and (symbolp map) (fboundp map))
1415 (setq map (funcall map key len)))
1416 (if (car map)
1417 (quail-completion-list-translations map key (+ indent len 1))
1418 (insert " -\n"))
1419 (setq indent (+ indent 2))
1420 (if (cdr map)
1421 (let ((l (cdr map))
1422 (newkey (make-string (1+ len) 0))
1423 (i 0))
1424 ;; Set KEY in the first LEN characters of NEWKEY.
1425 (while (< i len)
1426 (aset newkey i (aref key i))
1427 (setq i (1+ i)))
1428 (while l ; L = ((CHAR . DEFN) ....) ;
1429 (aset newkey len (car (car l)))
1430 (quail-completion-1 newkey (cdr (car l)) indent)
1431 (setq l (cdr l)))))))
1432
1433 ;; List all possible translations of KEY in Quail map MAP with
1434 ;; indentation INDENT."
1435 (defun quail-completion-list-translations (map key indent)
1436 (let ((translations
1437 (quail-get-translation map key (length key))))
1438 (if (integerp translations)
1439 (insert "(1/1) 1." translations "\n")
1440 ;; We need only vector part.
1441 (setq translations (cdr translations))
1442 ;; Insert every 10 elements with indices in a line.
1443 (let ((len (length translations))
1444 (i 0)
1445 (first t)
1446 num)
1447 (while (< i len)
1448 (if first
1449 (progn
1450 (insert "(1/1)")
1451 (setq first nil))
1452 (if (= (% i 10) 0)
1453 (progn
1454 (newline)
1455 (indent-to indent)
1456 (insert (format "(%d/%d)" (1+ (/ i 10)) (1+ (/ len 10)))))))
1457 ;; We show the last digit of FROM while converting
1458 ;; 0,1,..,9 to 1,2,..,0.
1459 (insert (format " %d." (if (= (% i 10) 9) 0 (1+ (% i 10)))))
1460 (insert (aref translations i))
1461 (setq i (1+ i)))
1462 (newline)))))
1463
1464 (defun quail-help ()
1465 "Show brief description of the current Quail package."
1466 (interactive)
1467 (let ((package quail-current-package)
1468 (buf (get-buffer-create "*Quail-help*")))
1469 (save-excursion
1470 (set-buffer buf)
1471 (erase-buffer)
1472 (setq quail-current-package package)
1473 (insert "Quail input method (name:"
1474 (quail-name)
1475 ", mode line indicator:["
1476 (quail-title)
1477 "])\n---- Documentation ----\n"
1478 (quail-docstring))
1479 (newline)
1480 (if (quail-show-layout) (quail-show-kbd-layout))
1481 (insert )
1482 (quail-help-insert-keymap-description
1483 quail-mode-map
1484 "---- Key bindings (before starting translation) ----
1485 key binding
1486 --- -------\n")
1487 (quail-help-insert-keymap-description
1488 (quail-translation-keymap)
1489 "--- Key bindings (while translating) ---
1490 key binding
1491 --- -------\n")
1492 (if (quail-conversion-keymap)
1493 (quail-help-insert-keymap-description
1494 (quail-conversion-keymap)
1495 "--- Key bindings (while converting) ---
1496 key binding
1497 --- -------\n"))
1498 (goto-char (point-min))
1499 (set-buffer-modified-p nil)
1500 (help-mode))
1501 (display-buffer buf)))
1502
1503 (defun quail-help-insert-keymap-description (keymap &optional header)
1504 (let (from to)
1505 (if header
1506 (insert header))
1507 (save-excursion
1508 (save-window-excursion
1509 (let ((overriding-local-map keymap))
1510 (describe-bindings))
1511 (set-buffer "*Help*")
1512 (goto-char (point-min))
1513 (forward-line 4)
1514 (setq from (point))
1515 (search-forward "Global Bindings:" nil 'move)
1516 (beginning-of-line)
1517 (setq to (point))))
1518 (insert-buffer-substring "*Help*" from to)))
1519
1520 (defun quail-show-kbd-layout ()
1521 "Show keyboard layout with key tops of multilingual characters."
1522 (insert "--- Keyboard layout ---\n")
1523 (let* ((i 0) ch)
1524 (while (< i quail-keyboard-layout-len)
1525 (if (= (% i 30) 0)
1526 (progn
1527 (newline)
1528 (indent-to (/ i 30)))
1529 (if (= (% i 2) 0)
1530 (insert " ")))
1531 (setq ch (aref quail-keyboard-layout i))
1532 (if (= ch ?\ )
1533 (insert ch)
1534 (let* ((map (cdr (assq ch (cdr (quail-map)))))
1535 (translation (and map (quail-get-translation
1536 map (char-to-string ch) 1))))
1537 (if (integerp translation)
1538 (insert translation)
1539 (if (consp translation)
1540 (insert (aref (cdr translation) (car translation)))
1541 (insert ch)))))
1542 (setq i (1+ i))))
1543 (newline))
1544
1545 (defun quail-translation-help ()
1546 "Show help message while translating in Quail mode."
1547 (interactive)
1548 (let ((package quail-current-package)
1549 (current-key quail-current-key)
1550 (buf (get-buffer-create "*Quail-Help*")))
1551 (save-excursion
1552 (set-buffer buf)
1553 (erase-buffer)
1554 (setq quail-current-package package)
1555 (insert
1556 (format "You are translating the key sequence \"%s\" in Quail mode.\n"
1557 quail-current-key))
1558 (quail-help-insert-keymap-description
1559 (quail-translation-keymap)
1560 "-----------------------
1561 key binding
1562 --- -------\n")
1563 (goto-char (point-min))
1564 (set-buffer-modified-p nil))
1565 (display-buffer buf)))
1566
1567 (defun quail-conversion-help ()
1568 "Show help message while converting in Quail mode."
1569 (interactive)
1570 (let ((package quail-current-package)
1571 (str (buffer-substring (overlay-start quail-conv-overlay)
1572 (overlay-end quail-conv-overlay)))
1573 (buf (get-buffer-create "*Quail-Help*")))
1574 (save-excursion
1575 (set-buffer buf)
1576 (erase-buffer)
1577 (setq quail-current-package package)
1578 (insert
1579 (format "You are converting the string \"%s\" in Quail mode.\n" str))
1580 (quail-help-insert-keymap-description
1581 (quail-conversion-keymap)
1582 "-----------------------
1583 key binding
1584 --- -------\n")
1585 (goto-char (point-min))
1586 (set-buffer-modified-p nil))
1587 (display-buffer buf)))
1588
1589 ;;
1590 (provide 'quail)
1591
1592 ;;; quail.el ends here