(insert-directory): Bind coding-system-for-read to
[bpt/emacs.git] / lisp / international / mule-cmds.el
CommitLineData
4ed46869
KH
1;;; mule-cmds.el --- Commands for mulitilingual environment
2
4ed46869 3;; Copyright (C) 1995 Electrotechnical Laboratory, JAPAN.
fa526c4a 4;; Licensed to the Free Software Foundation.
4ed46869
KH
5
6;; Keywords: mule, multilingual
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation; either version 2, or (at your option)
13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
369314dc
KH
21;; along with GNU Emacs; see the file COPYING. If not, write to the
22;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23;; Boston, MA 02111-1307, USA.
4ed46869
KH
24
25;;; Code:
26
27;;; MULE related key bindings and menus.
28
0709d285 29(defvar mule-keymap (make-sparse-keymap)
4ed46869 30 "Keymap for MULE (Multilingual environment) specific commands.")
4ed46869 31
8f81f784 32;; Keep "C-x C-m ..." for mule specific commands.
0709d285 33(define-key ctl-x-map "\C-m" mule-keymap)
ef8a8c8c 34
4ed46869
KH
35(define-key mule-keymap "f" 'set-buffer-file-coding-system)
36(define-key mule-keymap "t" 'set-terminal-coding-system)
15b3e511
KH
37(define-key mule-keymap "k" 'set-keyboard-coding-system)
38(define-key mule-keymap "p" 'set-buffer-process-coding-system)
8b784951 39(define-key mule-keymap "\C-\\" 'set-input-method)
15b3e511 40(define-key mule-keymap "c" 'universal-coding-system-argument)
b4fba33f 41(define-key mule-keymap "l" 'set-language-environment)
4ed46869 42
281d03ec 43(define-key help-map "\C-L" 'describe-language-environment)
ac4a3a2d 44(define-key help-map "L" 'describe-language-environment)
4ed46869 45(define-key help-map "\C-\\" 'describe-input-method)
ac4a3a2d 46(define-key help-map "I" 'describe-input-method)
d0b9c3ab 47(define-key help-map "C" 'describe-coding-system)
4ed46869
KH
48(define-key help-map "h" 'view-hello-file)
49
0709d285 50(defvar mule-menu-keymap (make-sparse-keymap "Mule")
15b3e511 51 "Keymap for MULE (Multilingual environment) menu specific commands.")
15b3e511
KH
52
53(define-key global-map [menu-bar mule] (cons "Mule" mule-menu-keymap))
54
55(setq menu-bar-final-items (cons 'mule menu-bar-final-items))
56
281d03ec
RS
57(defvar describe-language-environment-map nil)
58(define-prefix-command 'describe-language-environment-map)
15b3e511
KH
59
60(defvar setup-language-environment-map nil)
61(define-prefix-command 'setup-language-environment-map)
62
63(defvar set-coding-system-map nil)
64(define-prefix-command 'set-coding-system-map)
65
281d03ec 66(define-key-after mule-menu-keymap [describe-language-environment]
8e02924a 67 '("Describe Language Environment" . describe-language-environment-map)
15b3e511
KH
68 t)
69(define-key-after mule-menu-keymap [set-language-environment]
8e02924a 70 '("Set Language Environment" . setup-language-environment-map)
15b3e511 71 t)
a61f401d 72(define-key-after mule-menu-keymap [mouse-set-font]
8e02924a 73 '("Set Font/Fontset" . mouse-set-font)
a61f401d 74 t)
15b3e511
KH
75(define-key-after mule-menu-keymap [separator-mule]
76 '("--")
77 t)
78(define-key-after mule-menu-keymap [toggle-input-method]
8e02924a 79 '("Toggle Input Method" . toggle-input-method)
15b3e511 80 t)
8b784951
KH
81(define-key-after mule-menu-keymap [set-input-method]
82 '("Select Input Method" . set-input-method)
15b3e511
KH
83 t)
84(define-key-after mule-menu-keymap [describe-input-method]
8e02924a 85 '("Describe Input Method" . describe-input-method)
15b3e511
KH
86 t)
87(define-key-after mule-menu-keymap [separator-input-method]
88 '("--")
89 t)
d0b9c3ab 90(define-key-after mule-menu-keymap [describe-coding-system]
8e02924a 91 '("Describe Coding Systems" . describe-coding-system)
15b3e511
KH
92 t)
93(define-key-after mule-menu-keymap [set-various-coding-system]
8e02924a 94 '("Set Coding System" . set-coding-system-map)
15b3e511
KH
95 t)
96(define-key-after mule-menu-keymap [separator-coding-system]
97 '("--")
98 t)
99(define-key-after mule-menu-keymap [mule-diag]
8e02924a 100 '("Show All of MULE Status" . mule-diag)
15b3e511
KH
101 t)
102(define-key-after mule-menu-keymap [view-hello-file]
8e02924a 103 '("Show Script Examples" . view-hello-file)
15b3e511
KH
104 t)
105
106(define-key-after set-coding-system-map [set-buffer-file-coding-system]
8e02924a 107 '("Buffer File" . set-buffer-file-coding-system)
15b3e511 108 t)
3a151e98
RS
109(define-key-after set-coding-system-map [universal-coding-system-argument]
110 '("Next Command" . universal-coding-system-argument)
111 t)
15b3e511
KH
112(define-key-after set-coding-system-map [set-terminal-coding-system]
113 '("Terminal" . set-terminal-coding-system)
114 t)
115(define-key-after set-coding-system-map [set-keyboard-coding-system]
116 '("Keyboard" . set-keyboard-coding-system)
117 t)
118(define-key-after set-coding-system-map [set-buffer-process-coding-system]
8e02924a 119 '("Buffer Process" . set-buffer-process-coding-system)
15b3e511
KH
120 t)
121
122(define-key setup-language-environment-map
123 [Default] '("Default" . setup-specified-language-environment))
4ed46869
KH
124
125;; These are meaningless when running under X.
4ed46869 126(put 'set-terminal-coding-system 'menu-enable
9ba344f7 127 '(not (eq window-system 'x)))
15b3e511 128(put 'set-keyboard-coding-system 'menu-enable
9ba344f7 129 '(not (eq window-system 'x)))
d0b9c3ab
KH
130;; This is meaningless when the current buffer has no process.
131(put 'set-buffer-process-coding-system 'menu-enable
132 '(get-buffer-process (current-buffer)))
4ed46869 133
4ed46869
KH
134;; This should be a single character key binding because users use it
135;; very frequently while editing multilingual text. Now we can use
136;; only two such keys: "\C-\\" and "\C-^", but the latter is not
137;; convenient because it requires shifting on most keyboards. An
138;; alternative is "\C-\]" which is now bound to `abort-recursive-edit'
139;; but it won't be used that frequently.
140(define-key global-map "\C-\\" 'toggle-input-method)
141
a2ad45b9
RS
142;;; This is no good because people often type Shift-SPC
143;;; meaning to type SPC. -- rms.
144;;; ;; Here's an alternative key binding for X users (Shift-SPACE).
145;;; (define-key global-map [?\S- ] 'toggle-input-method)
b4fba33f 146
4ed46869 147(defun toggle-enable-multibyte-characters (&optional arg)
6998e1a1
RS
148 "Change whether this buffer uses multibyte characters.
149With arg, use multibyte characters if the arg is positive.
150
151Note that this command does not convert the byte contents of
152the buffer; it only changes the way those bytes are interpreted.
153In general, therefore, this command *changes* the sequence of
154characters that the current buffer contains.
155
156We suggest you avoid using use this command unless you know what you
157are doing. If you use it by mistake, and the buffer is now displayed
158wrong, use this command again to toggle back to the right mode."
4ed46869 159 (interactive "P")
b7079457
RS
160 (let ((new-flag
161 (if (null arg) (null enable-multibyte-characters)
162 (> (prefix-numeric-value arg) 0))))
163 (set-buffer-multibyte new-flag))
4ed46869
KH
164 (force-mode-line-update))
165
166(defun view-hello-file ()
167 "Display the HELLO file which list up many languages and characters."
168 (interactive)
8f81f784
KH
169 ;; We have to decode the file in any environment.
170 (let ((default-enable-multibyte-characters t)
95fa03b4 171 (coding-system-for-read 'iso-2022-7bit))
8f81f784 172 (find-file-read-only (expand-file-name "HELLO" data-directory))))
4ed46869 173
15b3e511
KH
174(defun universal-coding-system-argument ()
175 "Execute an I/O command using the specified coding system."
176 (interactive)
e14a8f4c 177 (let* ((coding-system (read-coding-system "Coding system for following command: "))
15b3e511 178 (keyseq (read-key-sequence
e14a8f4c 179 (format "Command to execute with %s:" coding-system)))
15b3e511
KH
180 (cmd (key-binding keyseq)))
181 (let ((coding-system-for-read coding-system)
182 (coding-system-for-write coding-system))
183 (message "")
184 (call-interactively cmd))))
185
de94d711 186(defun set-default-coding-systems (coding-system)
0c3154d2 187 "Set default value of various coding systems to CODING-SYSTEM.
8efc03e1 188This sets the follwing coding systems:
0c3154d2 189 o coding system of a newly created buffer
8efc03e1
KH
190 o default coding system for subprocess I/O
191This also sets the following values:
192 o default value for the command `set-terminal-coding-system'
193 o default value for the command `set-keyboard-coding-system'"
de94d711
KH
194 (check-coding-system coding-system)
195 (setq-default buffer-file-coding-system coding-system)
196 (setq default-terminal-coding-system coding-system)
197 (setq default-keyboard-coding-system coding-system)
198 (setq default-process-coding-system (cons coding-system coding-system)))
199
0c3154d2
KH
200(defun prefer-coding-system (coding-system)
201 "Add CODING-SYSTEM at the front of the priority list for automatic detection.
8efc03e1 202This also sets the follwing coding systems:
0c3154d2 203 o coding system of a newly created buffer
8efc03e1
KH
204 o default coding system for subprocess I/O
205This also sets the following values:
206 o default value for the command `set-terminal-coding-system'
207 o default value for the command `set-keyboard-coding-system'"
0c3154d2
KH
208 (interactive "zPrefer coding system: ")
209 (if (not (and coding-system (coding-system-p coding-system)))
210 (error "Invalid coding system `%s'" coding-system))
211 (let ((coding-category (coding-system-category coding-system))
8efc03e1 212 (base (coding-system-base coding-system)))
0c3154d2
KH
213 (if (not coding-category)
214 ;; CODING-SYSTEM is no-conversion or undecided.
215 (error "Can't prefer the coding system `%s'" coding-system))
8efc03e1 216 (set coding-category (or base coding-system))
54b226f7 217 (update-iso-coding-systems)
0c3154d2
KH
218 (if (not (eq coding-category (car coding-category-list)))
219 ;; We must change the order.
220 (setq coding-category-list
221 (cons coding-category
222 (delq coding-category coding-category-list))))
8efc03e1
KH
223 (if (and base (interactive-p))
224 (message "Highest priority is set to %s (base of %s)"
225 base coding-system))
226 (set-default-coding-systems (or base coding-system))))
0c3154d2 227
b7079457 228(defun find-safe-coding-system-list-subset-p (list1 list2)
54b226f7
KH
229 "Return non-nil if all elements in LIST1 are included in LIST2.
230Comparison done with EQ."
231 (catch 'tag
232 (while list1
233 (or (memq (car list1) list2)
234 (throw 'tag nil))
235 (setq list1 (cdr list1)))
236 t))
237
238(defun find-safe-coding-system (from to)
239 "Return a list of proper coding systems to encode a text between FROM and TO.
240All coding systems in the list can safely encode any multibyte characters
241in the text.
242
243If the text contains no multibyte charcters, return a list of a single
244element `undecided'.
245
246Kludgy feature: if FROM is a string, the string is the target text,
247and TO is ignored."
248 (let ((charset-list (if (stringp from) (find-charset-string from)
249 (find-charset-region from to))))
d5266ddf
KH
250 (if (or (null charset-list)
251 (and (= (length charset-list) 1)
252 (eq 'ascii (car charset-list))))
54b226f7
KH
253 '(undecided)
254 (let ((l coding-system-list)
255 (prefered-codings
256 (mapcar (function
257 (lambda (x)
258 (get-charset-property x 'prefered-coding-system)))
259 charset-list))
260 codings coding safe)
261 (while l
262 (setq coding (car l) l (cdr l))
263 (if (and (eq coding (coding-system-base coding))
264 (setq safe (coding-system-get coding 'safe-charsets))
265 (or (eq safe t)
b7079457
RS
266 (find-safe-coding-system-list-subset-p
267 charset-list safe)))
54b226f7
KH
268 ;; We put the higher priority to coding systems included
269 ;; in PREFERED-CODINGS, and within them, put the higher
270 ;; priority to coding systems which support smaller
271 ;; number of charsets.
272 (let ((priority
273 (logior (if (coding-system-get coding 'mime-charset)
274 256 0)
275 (if (memq coding prefered-codings) 128 0)
276 (if (> (coding-system-type coding) 0) 64 0)
277 (if (consp safe) (- 64 (length safe)) 0))))
278 (setq codings (cons (cons priority coding) codings)))))
279 (mapcar 'cdr
280 (sort codings (function (lambda (x y) (> (car x) (car y))))))
281 ))))
282
283(defun select-safe-coding-system (from to &optional default-coding-system)
d5266ddf
KH
284 "Ask a user to select a safe coding system from candidates.
285The candidates of coding systems which can safely encode a text
286between FROM and TO are shown in a popup window.
54b226f7
KH
287
288Optional arg DEFAULT-CODING-SYSTEM specifies a coding system to be
289checked at first. If omitted, buffer-file-coding-system of the
290current buffer is used.
291
d5266ddf
KH
292If the text can be encoded safely by DEFAULT-CODING-SYSTEM, it is
293returned without any user interaction.
54b226f7
KH
294
295Kludgy feature: if FROM is a string, the string is the target text,
296and TO is ignored."
297 (or default-coding-system
298 (setq default-coding-system buffer-file-coding-system))
299 (let ((safe-coding-systems (find-safe-coding-system from to)))
300 (if (or (eq (car safe-coding-systems) 'undecided)
301 (and default-coding-system
302 (memq (coding-system-base default-coding-system)
303 safe-coding-systems)))
304 default-coding-system
305
306 ;; Ask a user to select a proper coding system.
307 (save-window-excursion
308 ;; At first, show a helpful message.
309 (with-output-to-temp-buffer "*Warning*"
310 (save-excursion
311 (set-buffer standard-output)
312 (insert (format "\
313The target text contains a multibyte character which can't be
314encoded safely by the coding system %s.
315
316Please select one from the following safe coding systems:\n"
317 default-coding-system))
318 (let ((pos (point))
319 (fill-prefix " "))
320 (mapcar (function (lambda (x) (princ " ") (princ x)))
321 safe-coding-systems)
322 (fill-region-as-paragraph pos (point)))))
323
324 ;; Read a coding system.
325 (let* ((safe-names (mapcar (lambda (x) (list (symbol-name x)))
326 safe-coding-systems))
327 (name (completing-read
328 (format "Select coding system (default %s): "
329 (car safe-coding-systems))
330 safe-names nil t nil nil (car (car safe-names)))))
1f776399 331 (kill-buffer "*Warning*")
54b226f7
KH
332 (intern name))))))
333
334(setq select-safe-coding-system-function 'select-safe-coding-system)
335
4ed46869
KH
336\f
337;;; Language support staffs.
338
4ed46869
KH
339(defvar language-info-alist nil
340 "Alist of language names vs the corresponding information of various kind.
341Each element looks like:
342 (LANGUAGE-NAME . ((KEY . INFO) ...))
343where LANGUAGE-NAME is a string,
344KEY is a symbol denoting the kind of information,
345INFO is any Lisp object which contains the actual information related
346to KEY.")
347
348(defun get-language-info (language-name key)
349 "Return the information for LANGUAGE-NAME of the kind KEY.
4ed46869 350KEY is a symbol denoting the kind of required information."
4ef06f75
KH
351 (if (symbolp language-name)
352 (setq language-name (symbol-name language-name)))
15b3e511 353 (let ((lang-slot (assoc-ignore-case language-name language-info-alist)))
4ed46869
KH
354 (if lang-slot
355 (cdr (assq key (cdr lang-slot))))))
356
54b226f7
KH
357(defun set-language-info (language-name key info
358 &optional describe-map setup-map)
4ed46869 359 "Set for LANGUAGE-NAME the information INFO under KEY.
4ed46869 360KEY is a symbol denoting the kind of information.
54b226f7
KH
361INFO is any Lisp object which contains the actual information specific
362 to LANGUAGE-NAME.
4ed46869
KH
363
364Currently, the following KEYs are used by Emacs:
281d03ec 365
54b226f7
KH
366charset: list of charsets.
367
368coding-system: list of coding systems.
281d03ec 369
54b226f7 370coding-priority: list of coding systems ordered by priority.
281d03ec 371
4ed46869 372tutorial: a tutorial file name written in the language.
281d03ec 373
4ed46869 374sample-text: one line short text containing characters of the language.
281d03ec 375
15b3e511 376documentation: t or a string describing how Emacs supports the language.
54b226f7
KH
377 If a string is specified, it is shown before any other information
378 of the language by the command `describe-language-environment'.
281d03ec 379
13e82c04 380setup-function: a function to call for setting up environment
54b226f7 381 convenient for a user of the language.
13e82c04 382
281d03ec 383We will define more KEYs in the future. To avoid conflict,
54b226f7
KH
384if you want to use your own KEY values, make them start with `user-'.
385
386Optional 4th and 5th args DESCRIBE-MAP and SETUP-MAP are keymaps to
387register LANGUAGE-NAME in the menu of `Mule'->`Describe Language
388Environment' and `Mule'->`Setup Language Environment' respectively."
4ef06f75
KH
389 (if (symbolp language-name)
390 (setq language-name (symbol-name language-name)))
4ed46869
KH
391 (let (lang-slot key-slot)
392 (setq lang-slot (assoc language-name language-info-alist))
393 (if (null lang-slot) ; If no slot for the language, add it.
394 (setq lang-slot (list language-name)
395 language-info-alist (cons lang-slot language-info-alist)))
396 (setq key-slot (assq key lang-slot))
397 (if (null key-slot) ; If no slot for the key, add it.
398 (progn
399 (setq key-slot (list key))
400 (setcdr lang-slot (cons key-slot (cdr lang-slot)))))
4ed46869 401 ;; Setup menu.
48082651 402 (cond ((eq key 'documentation)
54b226f7
KH
403 (define-key-after describe-map (vector (intern language-name))
404 (cons language-name 'describe-specified-language-support) t))
ef8a8c8c 405 ((eq key 'setup-function)
54b226f7
KH
406 (define-key-after setup-map (vector (intern language-name))
407 (cons language-name 'setup-specified-language-environment) t)))
15b3e511
KH
408
409 (setcdr key-slot info)
4ed46869
KH
410 ))
411
54b226f7 412(defun set-language-info-alist (language-name alist &optional parents)
4ed46869
KH
413 "Set for LANGUAGE-NAME the information in ALIST.
414ALIST is an alist of KEY and INFO. See the documentation of
54b226f7
KH
415`set-langauge-info' for the meanings of KEY and INFO.
416
417Optional arg PARENTS is a list of parent language environments ordered
418from the highest to the lower. If it is nil, we make LANGUAGE-NAME
419the top level language environment."
4ef06f75
KH
420 (if (symbolp language-name)
421 (setq language-name (symbol-name language-name)))
54b226f7
KH
422 (let ((describe-map describe-language-environment-map)
423 (setup-map setup-language-environment-map))
424 (if parents
425 (let ((l parents)
426 map parent-symbol parent)
427 (while l
428 (if (symbolp (setq parent-symbol (car l)))
429 (setq parent (symbol-name parent))
430 (setq parent parent-symbol parent-symbol (intern parent)))
431 (setq map (lookup-key describe-map (vector parent-symbol)))
432 (if (not map)
433 (progn
434 (setq map (intern (format "describe-%s-environment-map"
435 (downcase parent))))
436 (define-prefix-command map)
437 (define-key-after describe-map (vector parent-symbol)
438 (cons parent map) t)))
439 (setq describe-map (symbol-value map))
440 (setq map (lookup-key setup-map (vector parent-symbol)))
441 (if (not map)
442 (progn
443 (setq map (intern (format "setup-%s-environment-map"
444 (downcase parent))))
445 (define-prefix-command map)
446 (define-key-after setup-map (vector parent-symbol)
447 (cons parent map) t)))
448 (setq setup-map (symbol-value map))
449 (setq l (cdr l)))))
450 (while alist
451 (set-language-info language-name (car (car alist)) (cdr (car alist))
452 describe-map setup-map)
453 (setq alist (cdr alist)))))
4ed46869 454
ae302641 455(defun read-language-name (key prompt &optional default)
4ef06f75 456 "Read language name which has information for KEY, prompting with PROMPT.
ae302641 457DEFAULT is the default choice of language.
fc0678af 458This returns a language name as a string."
4ed46869
KH
459 (let* ((completion-ignore-case t)
460 (name (completing-read prompt
461 language-info-alist
462 (function (lambda (elm) (assq key elm)))
ae302641 463 t nil nil default)))
13e82c04
KH
464 (if (and (> (length name) 0)
465 (get-language-info name key))
466 name)))
4ed46869
KH
467\f
468;;; Multilingual input methods.
469
d0b9c3ab
KH
470(defconst leim-list-file-name "leim-list.el"
471 "Name of LEIM list file.
472This file contains a list of libraries of Emacs input methods (LEIM)
473in the format of Lisp expression for registering each input method.
474Emacs loads this file at startup time.")
475
476(defvar leim-list-header (format "\
477;;; %s -- list of LEIM (Library of Emacs Input Method)
478;;
479;; This file contains a list of LEIM (Library of Emacs Input Method)
480;; in the same directory as this file. Loading this file registeres
481;; the whole input methods in Emacs.
482;;
d33d5fbe 483;; Each entry has the form:
d0b9c3ab
KH
484;; (register-input-method
485;; INPUT-METHOD LANGUAGE-NAME ACTIVATE-FUNC
486;; TITLE DESCRIPTION
487;; ARG ...)
488;; See the function `register-input-method' for the meanings of arguments.
489;;
490;; If this directory is included in load-path, Emacs automatically
491;; loads this file at startup time.
492
493"
494 leim-list-file-name)
495 "Header to be inserted in LEIM list file.")
496
e55e92ee 497(defvar leim-list-entry-regexp "^(register-input-method"
d0b9c3ab
KH
498 "Regexp matching head of each entry in LEIM list file.
499See also the variable `leim-list-header'")
500
501(defvar update-leim-list-functions
502 '(quail-update-leim-list-file)
503 "List of functions to call to update LEIM list file.
504Each function is called with one arg, LEIM directory name.")
505
a337fe7f
RS
506(defun update-leim-list-file (&rest dirs)
507 "Update LEIM list file in directories DIRS."
d0b9c3ab
KH
508 (let ((functions update-leim-list-functions))
509 (while functions
a337fe7f 510 (apply (car functions) dirs)
d0b9c3ab
KH
511 (setq functions (cdr functions)))))
512
4ed46869
KH
513(defvar current-input-method nil
514 "The current input method for multilingual text.
96db204a 515If nil, that means no input method is activated now.")
4ed46869
KH
516(make-variable-buffer-local 'current-input-method)
517(put 'current-input-method 'permanent-local t)
518
519(defvar current-input-method-title nil
d0b9c3ab 520 "Title string of the current input method shown in mode line.")
4ed46869
KH
521(make-variable-buffer-local 'current-input-method-title)
522(put 'current-input-method-title 'permanent-local t)
523
b4fba33f
KH
524(defcustom default-input-method nil
525 "*Default input method for multilingual text.
526This is the input method activated automatically by the command
9b10b5a3 527`toggle-input-method' (\\[toggle-input-method])."
b4fba33f
KH
528 :group 'mule)
529
723a427a
KH
530(defvar input-method-history nil
531 "History list for some commands that read input methods.")
532(make-variable-buffer-local 'input-method-history)
533(put 'input-method-history 'permanent-local t)
4ed46869
KH
534
535(defvar inactivate-current-input-method-function nil
536 "Function to call for inactivating the current input method.
537Every input method should set this to an appropriate value when activated.
f17ccaee
KH
538This function is called with no argument.
539
540This function should never change the value of `current-input-method'.
541It is set to nil by the function `inactivate-input-method'.")
4ed46869
KH
542(make-variable-buffer-local 'inactivate-current-input-method-function)
543(put 'inactivate-current-input-method-function 'permanent-local t)
544
545(defvar describe-current-input-method-function nil
546 "Function to call for describing the current input method.
547This function is called with no argument.")
548(make-variable-buffer-local 'describe-current-input-method-function)
549(put 'describe-current-input-method-function 'permanent-local t)
550
d0b9c3ab
KH
551(defvar input-method-alist nil
552 "Alist of input method names vs the corresponding information to use it.
553Each element has the form:
554 (INPUT-METHOD LANGUAGE-NAME ACTIVATE-FUNC TITLE DESCRIPTION ...)
555See the function `register-input-method' for the meanings of each elements.")
556
557(defun register-input-method (input-method language-name &rest args)
558 "Register INPUT-METHOD as an input method for LANGUAGE-NAME.
4ef06f75 559INPUT-METHOD and LANGUAGE-NAME are symbols or strings.
d0b9c3ab
KH
560The remaining arguments are:
561 ACTIVATE-FUNC, TITLE, DESCRIPTION, and ARG ...
562 where,
563ACTIVATE-FUNC is a function to call for activating this method.
564TITLE is a string shown in mode-line while this method is active,
565DESCRIPTION is a string describing about this method,
566Arguments to ACTIVATE-FUNC are INPUT-METHOD and ARGs."
4ef06f75
KH
567 (if (symbolp language-name)
568 (setq language-name (symbol-name language-name)))
569 (if (symbolp input-method)
570 (setq input-method (symbol-name input-method)))
d0b9c3ab
KH
571 (let ((info (cons language-name args))
572 (slot (assoc input-method input-method-alist)))
573 (if slot
574 (setcdr slot info)
575 (setq slot (cons input-method info))
576 (setq input-method-alist (cons slot input-method-alist)))))
577
4d5ac029 578(defun read-input-method-name (prompt &optional default inhibit-null)
d0b9c3ab 579 "Read a name of input method from a minibuffer prompting with PROMPT.
4d5ac029
RS
580If DEFAULT is non-nil, use that as the default,
581 and substitute it into PROMPT at the first `%s'.
4ef06f75
KH
582If INHIBIT-NULL is non-nil, null input signals an error.
583
584The return value is a string."
4d5ac029
RS
585 (if default
586 (setq prompt (format prompt default)))
d0b9c3ab 587 (let* ((completion-ignore-case t)
723a427a
KH
588 ;; This binding is necessary because input-method-history is
589 ;; buffer local.
d0b9c3ab 590 (input-method (completing-read prompt input-method-alist
87505a98
RS
591 nil t nil 'input-method-history
592 default)))
d0b9c3ab
KH
593 (if (> (length input-method) 0)
594 input-method
595 (if inhibit-null
43807b77 596 (error "No valid input method is specified")))))
d0b9c3ab 597
d0b9c3ab 598(defun activate-input-method (input-method)
f17ccaee
KH
599 "Turn INPUT-METHOD on.
600If some input method is already on, turn it off at first."
4ef06f75
KH
601 (if (symbolp input-method)
602 (setq input-method (symbol-name input-method)))
723a427a
KH
603 (if (and current-input-method
604 (not (string= current-input-method input-method)))
42395763
RS
605 (inactivate-input-method))
606 (unless current-input-method
d0b9c3ab
KH
607 (let ((slot (assoc input-method input-method-alist)))
608 (if (null slot)
723a427a 609 (error "Can't activate input method `%s'" input-method))
8efc03e1
KH
610 (let ((func (nth 2 slot)))
611 (if (functionp func)
612 (apply (nth 2 slot) input-method (nthcdr 5 slot))
613 (if (and (consp func) (symbolp (car func)) (symbolp (cdr func)))
614 (progn
615 (require (cdr func))
616 (apply (car func) input-method (nthcdr 5 slot)))
617 (error "Can't activate input method `%s'" input-method))))
d0b9c3ab 618 (setq current-input-method input-method)
723a427a
KH
619 (setq current-input-method-title (nth 3 slot))
620 (run-hooks 'input-method-activate-hook))))
15b3e511 621
15b3e511 622(defun inactivate-input-method ()
f17ccaee 623 "Turn off the current input method."
723a427a
KH
624 (when current-input-method
625 (if input-method-history
626 (unless (string= current-input-method (car input-method-history))
627 (setq input-method-history
628 (cons current-input-method
629 (delete current-input-method input-method-history))))
630 (setq input-method-history (list current-input-method)))
631 (unwind-protect
632 (funcall inactivate-current-input-method-function)
15b3e511 633 (unwind-protect
723a427a
KH
634 (run-hooks 'input-method-inactivate-hook)
635 (setq current-input-method nil
636 current-input-method-title nil)))))
4ed46869 637
8b784951 638(defun set-input-method (input-method)
723a427a
KH
639 "Select and turn on INPUT-METHOD.
640This sets the default input method to what you specify,
641and turn it on for the current buffer."
d0b9c3ab 642 (interactive
723a427a 643 (let* ((default (or (car input-method-history) default-input-method)))
42395763 644 (list (read-input-method-name
87505a98 645 (if default "Select input method (default %s): " "Select input method: ")
42395763 646 default t))))
d0b9c3ab 647 (activate-input-method input-method)
42395763 648 (setq default-input-method input-method))
4ed46869
KH
649
650(defun toggle-input-method (&optional arg)
15b3e511 651 "Turn on or off a multilingual text input method for the current buffer.
723a427a 652
d0b9c3ab 653With arg, read an input method from minibuffer and turn it on.
723a427a 654
15b3e511 655Without arg, if some input method is currently activated, turn it off,
723a427a
KH
656else turn on an input method selected last time
657or the default input method (see `default-input-method').
658
659When there's no input method to turn on, turn on what read from minibuffer."
4ed46869 660 (interactive "P")
723a427a 661 (let* ((default (or (car input-method-history) default-input-method)))
b4fba33f
KH
662 (if (and current-input-method (not arg))
663 (inactivate-input-method)
723a427a
KH
664 (activate-input-method
665 (if (or arg (not default))
666 (read-input-method-name
667 (if default "Input method (default %s): " "Input method: " )
668 default t)
669 default))
670 (or default-input-method
671 (setq default-input-method current-input-method)))))
d0b9c3ab
KH
672
673(defun describe-input-method (input-method)
4ef06f75 674 "Describe input method INPUT-METHOD."
d0b9c3ab
KH
675 (interactive
676 (list (read-input-method-name
677 "Describe input method (default, current choice): ")))
78754934 678 (if (and input-method (symbolp input-method))
4ef06f75 679 (setq input-method (symbol-name input-method)))
d0b9c3ab
KH
680 (if (null input-method)
681 (describe-current-input-method)
682 (with-output-to-temp-buffer "*Help*"
683 (let ((elt (assoc input-method input-method-alist)))
684 (princ (format "Input method: %s (`%s' in mode line) for %s\n %s\n"
685 input-method (nth 3 elt) (nth 1 elt) (nth 4 elt)))))))
686
687(defun describe-current-input-method ()
96db204a 688 "Describe the input method currently in use."
4ed46869
KH
689 (if current-input-method
690 (if (and (symbolp describe-current-input-method-function)
691 (fboundp describe-current-input-method-function))
692 (funcall describe-current-input-method-function)
693 (message "No way to describe the current input method `%s'"
694 (cdr current-input-method))
695 (ding))
d0b9c3ab 696 (error "No input method is activated now")))
4ed46869 697
d3459641 698(defun read-multilingual-string (prompt &optional initial-input input-method)
4ed46869
KH
699 "Read a multilingual string from minibuffer, prompting with string PROMPT.
700The input method selected last time is activated in minibuffer.
15b3e511 701If optional second arg INITIAL-INPUT is non-nil, insert it in the minibuffer
d0b9c3ab
KH
702initially.
703Optional 3rd argument INPUT-METHOD specifies the input method
4ef06f75
KH
704to be activated instead of the one selected last time. It is a symbol
705or a string."
88d559ec
KH
706 (setq input-method
707 (or input-method
d3459641 708 current-input-method
88d559ec
KH
709 default-input-method
710 (read-input-method-name "Input method: " nil t)))
3df60841 711 (if (and input-method (symbolp input-method))
4ef06f75 712 (setq input-method (symbol-name input-method)))
d3459641
KH
713 (let ((previous-input-method current-input-method))
714 (unwind-protect
715 (progn
716 (activate-input-method input-method)
717 (read-string prompt initial-input nil nil t))
718 (if previous-input-method
719 (activate-input-method previous-input-method)
720 (inactivate-input-method)))))
4ed46869
KH
721
722;; Variables to control behavior of input methods. All input methods
723;; should react to these variables.
724
8efc03e1
KH
725(defcustom input-method-verbose-flag 'default
726 "*A flag to control extra guidance given by input methods.
727The value should be nil, t, `complex-only', or `default'.
4ed46869 728
cb29dfb6 729The extra guidance is done by showing list of available keys in echo
8efc03e1
KH
730area. When you use the input method in the minibuffer, the guidance
731is shown at the bottom short window (split from the existing window).
c27c4ed8 732
8efc03e1
KH
733If the value is t, extra guidance is always given, if the value is
734nil, extra guidance is always suppressed.
735
736If the value is `complex-only', only complex input methods such as
737`chinese-py' and `japanese' give extra guidance.
738
739If the value is `default', complex input methods always give extra
740guidance, but simple input methods give it only when you are not in
741the minibuffer.
742
743See also the variable `input-method-highlight-flag'."
744 :type '(choice (const t) (const nil) (const complex-only) (const default))
42395763
RS
745 :group 'mule)
746
747(defcustom input-method-highlight-flag t
748 "*If this flag is non-nil, input methods highlight partially-entered text.
749For instance, while you are in the middle of a Quail input method sequence,
750the text inserted so far is temporarily underlined.
8efc03e1
KH
751The underlining goes away when you finish or abort the input method sequence.
752See also the variable `input-method-verbose-flag'."
42395763
RS
753 :type 'boolean
754 :group 'mule)
4ed46869
KH
755
756(defvar input-method-activate-hook nil
f17ccaee
KH
757 "Normal hook run just after an input method is activated.
758
759The variable `current-input-method' keeps the input method name
760just activated.")
4ed46869
KH
761
762(defvar input-method-inactivate-hook nil
f17ccaee
KH
763 "Normal hook run just after an input method is inactivated.
764
765The variable `current-input-method' still keeps the input method name
4d0e6a11 766just inactivated.")
4ed46869
KH
767
768(defvar input-method-after-insert-chunk-hook nil
769 "Normal hook run just after an input method insert some chunk of text.")
770
723a427a
KH
771(defvar input-method-exit-on-invalid-key nil
772 "This flag controls the behaviour of an input method on invalid key input.
773Usually, when a user types a key which doesn't start any character
774handled by the input method, the key is handled by turning off the
775input method temporalily. After the key is handled, the input method is
776back on.
777But, if this flag is non-nil, the input method is never back on.")
778
4ed46869 779\f
8efc03e1
KH
780(defvar set-language-environment-hook nil
781 "Normal hook run after some language environment is set.
782
783When you set some hook function here, that effect usually should not
784be inherited to another language environment. So, you had better set
785another function in `exit-language-environment-hook' (which see) to
786cancel the effect.")
787
788(defvar exit-language-environment-hook nil
789 "Normal hook run after exiting from some language environment.
790When this hook is run, the variable `current-language-environment'
791is still bound to the language environment being exited.
792
793This hook is mainly used for cancelling the effect of
794`set-language-environment-hook' (which-see).")
795
15b3e511 796(defun setup-specified-language-environment ()
f850d782 797 "Set up multi-lingual environment convenient for the specified language."
15b3e511 798 (interactive)
f850d782 799 (let (language-name)
15b3e511
KH
800 (if (and (symbolp last-command-event)
801 (or (not (eq last-command-event 'Default))
802 (setq last-command-event 'English))
f850d782
RS
803 (setq language-name (symbol-name last-command-event)))
804 (set-language-environment language-name)
15b3e511 805 (error "Bogus calling sequence"))))
4ed46869 806
f850d782
RS
807(defvar current-language-environment "English"
808 "The last language environment specified with `set-language-environment'.")
809
166246f7 810(defun set-language-environment (language-name)
6c05d680
RS
811 "Set up multi-lingual environment for using LANGUAGE-NAME.
812This sets the coding system priority and the default input method
813and sometimes other things."
8efc03e1
KH
814 (interactive (list (read-language-name
815 'setup-function
816 "Set language environment (default, English): ")))
4ef06f75
KH
817 (if language-name
818 (if (symbolp language-name)
819 (setq language-name (symbol-name language-name)))
820 (setq language-name "English"))
b4fba33f 821 (if (null (get-language-info language-name 'setup-function))
f850d782 822 (error "Language environment not defined: %S" language-name))
8efc03e1
KH
823 (if current-language-environment
824 (let ((func (get-language-info current-language-environment
825 'exit-function)))
e63645c2
KH
826 (run-hooks 'exit-language-environment-hook)
827 (if (fboundp func) (funcall func))))
f850d782 828 (setq current-language-environment language-name)
8efc03e1
KH
829 (funcall (get-language-info language-name 'setup-function))
830 (run-hooks 'set-language-environment-hook)
f850d782 831 (force-mode-line-update t))
4ed46869 832
54b226f7
KH
833(defun set-language-environment-coding-systems (language-name)
834 "Do various coding system setups for language environment LANGUAGE-NAME."
835 (let* ((priority (get-language-info language-name 'coding-priority))
836 (default-coding (car priority)))
837 (if priority
838 (let ((categories (mapcar 'coding-system-category priority)))
839 (set-default-coding-systems default-coding)
840 (set-coding-priority categories)
841 (while priority
842 (set (car categories) (car priority))
843 (setq priority (cdr priority) categories (cdr categories)))
844 (update-iso-coding-systems)))))
845
4ed46869
KH
846;; Print all arguments with `princ', then print "\n".
847(defsubst princ-list (&rest args)
848 (while args (princ (car args)) (setq args (cdr args)))
849 (princ "\n"))
850
48082651 851;; Print a language specific information such as input methods,
13e82c04 852;; charsets, and coding systems. This function is intended to be
48082651 853;; called from the menu:
281d03ec 854;; [menu-bar mule describe-language-environment LANGUAGE]
48082651
KH
855;; and should not run it by `M-x describe-current-input-method-function'.
856(defun describe-specified-language-support ()
96db204a 857 "Describe how Emacs supports the specified language environment."
48082651 858 (interactive)
281d03ec 859 (let (language-name)
48082651 860 (if (not (and (symbolp last-command-event)
281d03ec 861 (setq language-name (symbol-name last-command-event))))
48082651 862 (error "Bogus calling sequence"))
281d03ec
RS
863 (describe-language-environment language-name)))
864
865(defun describe-language-environment (language-name)
866 "Describe how Emacs supports language environment LANGUAGE-NAME."
78754934
KH
867 (interactive
868 (list (read-language-name
869 'documentation
8adfa8be 870 "Describe language environment (default, current choice): ")))
f850d782
RS
871 (if (null language-name)
872 (setq language-name current-language-environment))
281d03ec
RS
873 (if (or (null language-name)
874 (null (get-language-info language-name 'documentation)))
875 (error "No documentation for the specified language"))
4ef06f75
KH
876 (if (symbolp language-name)
877 (setq language-name (symbol-name language-name)))
281d03ec 878 (let ((doc (get-language-info language-name 'documentation)))
48082651 879 (with-output-to-temp-buffer "*Help*"
13e82c04 880 (if (stringp doc)
d0b9c3ab
KH
881 (progn
882 (princ-list doc)
883 (terpri)))
15b3e511
KH
884 (let ((str (get-language-info language-name 'sample-text)))
885 (if (stringp str)
886 (progn
281d03ec 887 (princ "Sample text:\n")
d0b9c3ab
KH
888 (princ-list " " str)
889 (terpri))))
281d03ec 890 (princ "Input methods:\n")
d0b9c3ab 891 (let ((l input-method-alist))
15b3e511 892 (while l
d0b9c3ab
KH
893 (if (string= language-name (nth 1 (car l)))
894 (princ-list " " (car (car l))
895 (format " (`%s' in mode line)" (nth 3 (car l)))))
15b3e511 896 (setq l (cdr l))))
281d03ec
RS
897 (terpri)
898 (princ "Character sets:\n")
15b3e511
KH
899 (let ((l (get-language-info language-name 'charset)))
900 (if (null l)
901 (princ-list " nothing specific to " language-name)
902 (while l
903 (princ-list " " (car l) ": "
904 (charset-description (car l)))
905 (setq l (cdr l)))))
281d03ec
RS
906 (terpri)
907 (princ "Coding systems:\n")
15b3e511
KH
908 (let ((l (get-language-info language-name 'coding-system)))
909 (if (null l)
910 (princ-list " nothing specific to " language-name)
48082651 911 (while l
281d03ec
RS
912 (princ (format " %s (`%c' in mode line):\n\t%s\n"
913 (car l)
914 (coding-system-mnemonic (car l))
a904b20b 915 (coding-system-doc-string (car l))))
8efc03e1
KH
916 (let ((aliases (coding-system-get (car l) 'alias-coding-systems)))
917 (when aliases
918 (princ "\t")
919 (princ (cons 'alias: (cdr aliases)))
920 (terpri)))
15b3e511 921 (setq l (cdr l))))))))
4ed46869
KH
922\f
923;;; Charset property
924
925(defsubst get-charset-property (charset propname)
926 "Return the value of CHARSET's PROPNAME property.
927This is the last value stored with
96db204a 928 (put-charset-property CHARSET PROPNAME VALUE)."
4ed46869
KH
929 (plist-get (charset-plist charset) propname))
930
931(defsubst put-charset-property (charset propname value)
932 "Store CHARSETS's PROPNAME property with value VALUE.
933It can be retrieved with `(get-charset-property CHARSET PROPNAME)'."
934 (set-charset-plist charset
935 (plist-put (charset-plist charset) propname value)))
936
937;;; Character code property
938(put 'char-code-property-table 'char-table-extra-slots 0)
939
940(defvar char-code-property-table
941 (make-char-table 'char-code-property-table)
942 "Char-table containing a property list of each character code.
943
944See also the documentation of `get-char-code-property' and
96db204a 945`put-char-code-property'.")
4ed46869
KH
946
947(defun get-char-code-property (char propname)
948 "Return the value of CHAR's PROPNAME property in `char-code-property-table'."
949 (let ((plist (aref char-code-property-table char)))
950 (if (listp plist)
951 (car (cdr (memq propname plist))))))
952
953(defun put-char-code-property (char propname value)
954 "Store CHAR's PROPNAME property with VALUE in `char-code-property-table'.
955It can be retrieved with `(get-char-code-property CHAR PROPNAME)'."
956 (let ((plist (aref char-code-property-table char)))
957 (if plist
958 (let ((slot (memq propname plist)))
959 (if slot
960 (setcar (cdr slot) value)
961 (nconc plist (list propname value))))
962 (aset char-code-property-table char (list propname value)))))
963
964;;; mule-cmds.el ends here