(set-default-coding-systems): Set
[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.
387136f6 188This sets the following 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:
387136f6 192 o default value used as file-name-coding-system for converting file names.
8efc03e1
KH
193 o default value for the command `set-terminal-coding-system'
194 o default value for the command `set-keyboard-coding-system'"
de94d711
KH
195 (check-coding-system coding-system)
196 (setq-default buffer-file-coding-system coding-system)
387136f6 197 (setq default-file-name-coding-system coding-system)
de94d711
KH
198 (setq default-terminal-coding-system coding-system)
199 (setq default-keyboard-coding-system coding-system)
200 (setq default-process-coding-system (cons coding-system coding-system)))
201
0c3154d2
KH
202(defun prefer-coding-system (coding-system)
203 "Add CODING-SYSTEM at the front of the priority list for automatic detection.
387136f6 204This also sets the following coding systems:
0c3154d2 205 o coding system of a newly created buffer
8efc03e1
KH
206 o default coding system for subprocess I/O
207This also sets the following values:
387136f6 208 o default value used as file-name-coding-system for converting file names.
8efc03e1
KH
209 o default value for the command `set-terminal-coding-system'
210 o default value for the command `set-keyboard-coding-system'"
0c3154d2
KH
211 (interactive "zPrefer coding system: ")
212 (if (not (and coding-system (coding-system-p coding-system)))
213 (error "Invalid coding system `%s'" coding-system))
214 (let ((coding-category (coding-system-category coding-system))
8efc03e1 215 (base (coding-system-base coding-system)))
0c3154d2
KH
216 (if (not coding-category)
217 ;; CODING-SYSTEM is no-conversion or undecided.
218 (error "Can't prefer the coding system `%s'" coding-system))
8efc03e1 219 (set coding-category (or base coding-system))
54b226f7 220 (update-iso-coding-systems)
0c3154d2
KH
221 (if (not (eq coding-category (car coding-category-list)))
222 ;; We must change the order.
223 (setq coding-category-list
224 (cons coding-category
225 (delq coding-category coding-category-list))))
8efc03e1
KH
226 (if (and base (interactive-p))
227 (message "Highest priority is set to %s (base of %s)"
228 base coding-system))
229 (set-default-coding-systems (or base coding-system))))
0c3154d2 230
b7079457 231(defun find-safe-coding-system-list-subset-p (list1 list2)
54b226f7
KH
232 "Return non-nil if all elements in LIST1 are included in LIST2.
233Comparison done with EQ."
234 (catch 'tag
235 (while list1
236 (or (memq (car list1) list2)
237 (throw 'tag nil))
238 (setq list1 (cdr list1)))
239 t))
240
241(defun find-safe-coding-system (from to)
242 "Return a list of proper coding systems to encode a text between FROM and TO.
243All coding systems in the list can safely encode any multibyte characters
244in the text.
245
246If the text contains no multibyte charcters, return a list of a single
247element `undecided'.
248
249Kludgy feature: if FROM is a string, the string is the target text,
250and TO is ignored."
251 (let ((charset-list (if (stringp from) (find-charset-string from)
252 (find-charset-region from to))))
d5266ddf
KH
253 (if (or (null charset-list)
254 (and (= (length charset-list) 1)
255 (eq 'ascii (car charset-list))))
54b226f7
KH
256 '(undecided)
257 (let ((l coding-system-list)
258 (prefered-codings
259 (mapcar (function
260 (lambda (x)
261 (get-charset-property x 'prefered-coding-system)))
262 charset-list))
263 codings coding safe)
264 (while l
265 (setq coding (car l) l (cdr l))
266 (if (and (eq coding (coding-system-base coding))
267 (setq safe (coding-system-get coding 'safe-charsets))
268 (or (eq safe t)
b7079457
RS
269 (find-safe-coding-system-list-subset-p
270 charset-list safe)))
54b226f7
KH
271 ;; We put the higher priority to coding systems included
272 ;; in PREFERED-CODINGS, and within them, put the higher
273 ;; priority to coding systems which support smaller
274 ;; number of charsets.
275 (let ((priority
276 (logior (if (coding-system-get coding 'mime-charset)
277 256 0)
278 (if (memq coding prefered-codings) 128 0)
279 (if (> (coding-system-type coding) 0) 64 0)
280 (if (consp safe) (- 64 (length safe)) 0))))
281 (setq codings (cons (cons priority coding) codings)))))
282 (mapcar 'cdr
283 (sort codings (function (lambda (x y) (> (car x) (car y))))))
284 ))))
285
286(defun select-safe-coding-system (from to &optional default-coding-system)
d5266ddf
KH
287 "Ask a user to select a safe coding system from candidates.
288The candidates of coding systems which can safely encode a text
289between FROM and TO are shown in a popup window.
54b226f7
KH
290
291Optional arg DEFAULT-CODING-SYSTEM specifies a coding system to be
292checked at first. If omitted, buffer-file-coding-system of the
293current buffer is used.
294
d5266ddf
KH
295If the text can be encoded safely by DEFAULT-CODING-SYSTEM, it is
296returned without any user interaction.
54b226f7
KH
297
298Kludgy feature: if FROM is a string, the string is the target text,
299and TO is ignored."
300 (or default-coding-system
301 (setq default-coding-system buffer-file-coding-system))
302 (let ((safe-coding-systems (find-safe-coding-system from to)))
303 (if (or (eq (car safe-coding-systems) 'undecided)
304 (and default-coding-system
305 (memq (coding-system-base default-coding-system)
306 safe-coding-systems)))
307 default-coding-system
308
309 ;; Ask a user to select a proper coding system.
310 (save-window-excursion
311 ;; At first, show a helpful message.
312 (with-output-to-temp-buffer "*Warning*"
313 (save-excursion
314 (set-buffer standard-output)
315 (insert (format "\
316The target text contains a multibyte character which can't be
317encoded safely by the coding system %s.
318
319Please select one from the following safe coding systems:\n"
320 default-coding-system))
321 (let ((pos (point))
322 (fill-prefix " "))
323 (mapcar (function (lambda (x) (princ " ") (princ x)))
324 safe-coding-systems)
325 (fill-region-as-paragraph pos (point)))))
326
327 ;; Read a coding system.
328 (let* ((safe-names (mapcar (lambda (x) (list (symbol-name x)))
329 safe-coding-systems))
330 (name (completing-read
331 (format "Select coding system (default %s): "
332 (car safe-coding-systems))
333 safe-names nil t nil nil (car (car safe-names)))))
1f776399 334 (kill-buffer "*Warning*")
54b226f7
KH
335 (intern name))))))
336
337(setq select-safe-coding-system-function 'select-safe-coding-system)
338
4ed46869
KH
339\f
340;;; Language support staffs.
341
4ed46869
KH
342(defvar language-info-alist nil
343 "Alist of language names vs the corresponding information of various kind.
344Each element looks like:
345 (LANGUAGE-NAME . ((KEY . INFO) ...))
346where LANGUAGE-NAME is a string,
347KEY is a symbol denoting the kind of information,
348INFO is any Lisp object which contains the actual information related
349to KEY.")
350
351(defun get-language-info (language-name key)
352 "Return the information for LANGUAGE-NAME of the kind KEY.
4ed46869 353KEY is a symbol denoting the kind of required information."
4ef06f75
KH
354 (if (symbolp language-name)
355 (setq language-name (symbol-name language-name)))
15b3e511 356 (let ((lang-slot (assoc-ignore-case language-name language-info-alist)))
4ed46869
KH
357 (if lang-slot
358 (cdr (assq key (cdr lang-slot))))))
359
54b226f7
KH
360(defun set-language-info (language-name key info
361 &optional describe-map setup-map)
4ed46869 362 "Set for LANGUAGE-NAME the information INFO under KEY.
4ed46869 363KEY is a symbol denoting the kind of information.
54b226f7
KH
364INFO is any Lisp object which contains the actual information specific
365 to LANGUAGE-NAME.
4ed46869
KH
366
367Currently, the following KEYs are used by Emacs:
281d03ec 368
54b226f7
KH
369charset: list of charsets.
370
371coding-system: list of coding systems.
281d03ec 372
54b226f7 373coding-priority: list of coding systems ordered by priority.
281d03ec 374
4ed46869 375tutorial: a tutorial file name written in the language.
281d03ec 376
4ed46869 377sample-text: one line short text containing characters of the language.
281d03ec 378
15b3e511 379documentation: t or a string describing how Emacs supports the language.
54b226f7
KH
380 If a string is specified, it is shown before any other information
381 of the language by the command `describe-language-environment'.
281d03ec 382
13e82c04 383setup-function: a function to call for setting up environment
54b226f7 384 convenient for a user of the language.
13e82c04 385
281d03ec 386We will define more KEYs in the future. To avoid conflict,
54b226f7
KH
387if you want to use your own KEY values, make them start with `user-'.
388
389Optional 4th and 5th args DESCRIBE-MAP and SETUP-MAP are keymaps to
390register LANGUAGE-NAME in the menu of `Mule'->`Describe Language
391Environment' and `Mule'->`Setup Language Environment' respectively."
4ef06f75
KH
392 (if (symbolp language-name)
393 (setq language-name (symbol-name language-name)))
4ed46869
KH
394 (let (lang-slot key-slot)
395 (setq lang-slot (assoc language-name language-info-alist))
396 (if (null lang-slot) ; If no slot for the language, add it.
397 (setq lang-slot (list language-name)
398 language-info-alist (cons lang-slot language-info-alist)))
399 (setq key-slot (assq key lang-slot))
400 (if (null key-slot) ; If no slot for the key, add it.
401 (progn
402 (setq key-slot (list key))
403 (setcdr lang-slot (cons key-slot (cdr lang-slot)))))
4ed46869 404 ;; Setup menu.
48082651 405 (cond ((eq key 'documentation)
54b226f7
KH
406 (define-key-after describe-map (vector (intern language-name))
407 (cons language-name 'describe-specified-language-support) t))
ef8a8c8c 408 ((eq key 'setup-function)
54b226f7
KH
409 (define-key-after setup-map (vector (intern language-name))
410 (cons language-name 'setup-specified-language-environment) t)))
15b3e511
KH
411
412 (setcdr key-slot info)
4ed46869
KH
413 ))
414
54b226f7 415(defun set-language-info-alist (language-name alist &optional parents)
4ed46869
KH
416 "Set for LANGUAGE-NAME the information in ALIST.
417ALIST is an alist of KEY and INFO. See the documentation of
54b226f7
KH
418`set-langauge-info' for the meanings of KEY and INFO.
419
420Optional arg PARENTS is a list of parent language environments ordered
421from the highest to the lower. If it is nil, we make LANGUAGE-NAME
422the top level language environment."
4ef06f75
KH
423 (if (symbolp language-name)
424 (setq language-name (symbol-name language-name)))
54b226f7
KH
425 (let ((describe-map describe-language-environment-map)
426 (setup-map setup-language-environment-map))
427 (if parents
428 (let ((l parents)
429 map parent-symbol parent)
430 (while l
431 (if (symbolp (setq parent-symbol (car l)))
432 (setq parent (symbol-name parent))
433 (setq parent parent-symbol parent-symbol (intern parent)))
434 (setq map (lookup-key describe-map (vector parent-symbol)))
435 (if (not map)
436 (progn
437 (setq map (intern (format "describe-%s-environment-map"
438 (downcase parent))))
439 (define-prefix-command map)
440 (define-key-after describe-map (vector parent-symbol)
441 (cons parent map) t)))
442 (setq describe-map (symbol-value map))
443 (setq map (lookup-key setup-map (vector parent-symbol)))
444 (if (not map)
445 (progn
446 (setq map (intern (format "setup-%s-environment-map"
447 (downcase parent))))
448 (define-prefix-command map)
449 (define-key-after setup-map (vector parent-symbol)
450 (cons parent map) t)))
451 (setq setup-map (symbol-value map))
452 (setq l (cdr l)))))
453 (while alist
454 (set-language-info language-name (car (car alist)) (cdr (car alist))
455 describe-map setup-map)
456 (setq alist (cdr alist)))))
4ed46869 457
ae302641 458(defun read-language-name (key prompt &optional default)
4ef06f75 459 "Read language name which has information for KEY, prompting with PROMPT.
ae302641 460DEFAULT is the default choice of language.
fc0678af 461This returns a language name as a string."
4ed46869
KH
462 (let* ((completion-ignore-case t)
463 (name (completing-read prompt
464 language-info-alist
465 (function (lambda (elm) (assq key elm)))
ae302641 466 t nil nil default)))
13e82c04
KH
467 (if (and (> (length name) 0)
468 (get-language-info name key))
469 name)))
4ed46869
KH
470\f
471;;; Multilingual input methods.
472
d0b9c3ab
KH
473(defconst leim-list-file-name "leim-list.el"
474 "Name of LEIM list file.
475This file contains a list of libraries of Emacs input methods (LEIM)
476in the format of Lisp expression for registering each input method.
477Emacs loads this file at startup time.")
478
479(defvar leim-list-header (format "\
480;;; %s -- list of LEIM (Library of Emacs Input Method)
481;;
482;; This file contains a list of LEIM (Library of Emacs Input Method)
483;; in the same directory as this file. Loading this file registeres
484;; the whole input methods in Emacs.
485;;
d33d5fbe 486;; Each entry has the form:
d0b9c3ab
KH
487;; (register-input-method
488;; INPUT-METHOD LANGUAGE-NAME ACTIVATE-FUNC
489;; TITLE DESCRIPTION
490;; ARG ...)
491;; See the function `register-input-method' for the meanings of arguments.
492;;
493;; If this directory is included in load-path, Emacs automatically
494;; loads this file at startup time.
495
496"
497 leim-list-file-name)
498 "Header to be inserted in LEIM list file.")
499
e55e92ee 500(defvar leim-list-entry-regexp "^(register-input-method"
d0b9c3ab
KH
501 "Regexp matching head of each entry in LEIM list file.
502See also the variable `leim-list-header'")
503
504(defvar update-leim-list-functions
505 '(quail-update-leim-list-file)
506 "List of functions to call to update LEIM list file.
507Each function is called with one arg, LEIM directory name.")
508
a337fe7f
RS
509(defun update-leim-list-file (&rest dirs)
510 "Update LEIM list file in directories DIRS."
d0b9c3ab
KH
511 (let ((functions update-leim-list-functions))
512 (while functions
a337fe7f 513 (apply (car functions) dirs)
d0b9c3ab
KH
514 (setq functions (cdr functions)))))
515
4ed46869
KH
516(defvar current-input-method nil
517 "The current input method for multilingual text.
96db204a 518If nil, that means no input method is activated now.")
4ed46869
KH
519(make-variable-buffer-local 'current-input-method)
520(put 'current-input-method 'permanent-local t)
521
522(defvar current-input-method-title nil
d0b9c3ab 523 "Title string of the current input method shown in mode line.")
4ed46869
KH
524(make-variable-buffer-local 'current-input-method-title)
525(put 'current-input-method-title 'permanent-local t)
526
b4fba33f
KH
527(defcustom default-input-method nil
528 "*Default input method for multilingual text.
529This is the input method activated automatically by the command
9b10b5a3 530`toggle-input-method' (\\[toggle-input-method])."
b4fba33f
KH
531 :group 'mule)
532
723a427a
KH
533(defvar input-method-history nil
534 "History list for some commands that read input methods.")
535(make-variable-buffer-local 'input-method-history)
536(put 'input-method-history 'permanent-local t)
4ed46869
KH
537
538(defvar inactivate-current-input-method-function nil
539 "Function to call for inactivating the current input method.
540Every input method should set this to an appropriate value when activated.
f17ccaee
KH
541This function is called with no argument.
542
543This function should never change the value of `current-input-method'.
544It is set to nil by the function `inactivate-input-method'.")
4ed46869
KH
545(make-variable-buffer-local 'inactivate-current-input-method-function)
546(put 'inactivate-current-input-method-function 'permanent-local t)
547
548(defvar describe-current-input-method-function nil
549 "Function to call for describing the current input method.
550This function is called with no argument.")
551(make-variable-buffer-local 'describe-current-input-method-function)
552(put 'describe-current-input-method-function 'permanent-local t)
553
d0b9c3ab
KH
554(defvar input-method-alist nil
555 "Alist of input method names vs the corresponding information to use it.
556Each element has the form:
557 (INPUT-METHOD LANGUAGE-NAME ACTIVATE-FUNC TITLE DESCRIPTION ...)
558See the function `register-input-method' for the meanings of each elements.")
559
560(defun register-input-method (input-method language-name &rest args)
561 "Register INPUT-METHOD as an input method for LANGUAGE-NAME.
4ef06f75 562INPUT-METHOD and LANGUAGE-NAME are symbols or strings.
d0b9c3ab
KH
563The remaining arguments are:
564 ACTIVATE-FUNC, TITLE, DESCRIPTION, and ARG ...
565 where,
566ACTIVATE-FUNC is a function to call for activating this method.
567TITLE is a string shown in mode-line while this method is active,
568DESCRIPTION is a string describing about this method,
569Arguments to ACTIVATE-FUNC are INPUT-METHOD and ARGs."
4ef06f75
KH
570 (if (symbolp language-name)
571 (setq language-name (symbol-name language-name)))
572 (if (symbolp input-method)
573 (setq input-method (symbol-name input-method)))
d0b9c3ab
KH
574 (let ((info (cons language-name args))
575 (slot (assoc input-method input-method-alist)))
576 (if slot
577 (setcdr slot info)
578 (setq slot (cons input-method info))
579 (setq input-method-alist (cons slot input-method-alist)))))
580
4d5ac029 581(defun read-input-method-name (prompt &optional default inhibit-null)
d0b9c3ab 582 "Read a name of input method from a minibuffer prompting with PROMPT.
4d5ac029
RS
583If DEFAULT is non-nil, use that as the default,
584 and substitute it into PROMPT at the first `%s'.
4ef06f75
KH
585If INHIBIT-NULL is non-nil, null input signals an error.
586
587The return value is a string."
4d5ac029
RS
588 (if default
589 (setq prompt (format prompt default)))
d0b9c3ab 590 (let* ((completion-ignore-case t)
723a427a
KH
591 ;; This binding is necessary because input-method-history is
592 ;; buffer local.
d0b9c3ab 593 (input-method (completing-read prompt input-method-alist
87505a98
RS
594 nil t nil 'input-method-history
595 default)))
d0b9c3ab
KH
596 (if (> (length input-method) 0)
597 input-method
598 (if inhibit-null
43807b77 599 (error "No valid input method is specified")))))
d0b9c3ab 600
d0b9c3ab 601(defun activate-input-method (input-method)
f17ccaee
KH
602 "Turn INPUT-METHOD on.
603If some input method is already on, turn it off at first."
4ef06f75
KH
604 (if (symbolp input-method)
605 (setq input-method (symbol-name input-method)))
723a427a
KH
606 (if (and current-input-method
607 (not (string= current-input-method input-method)))
42395763
RS
608 (inactivate-input-method))
609 (unless current-input-method
d0b9c3ab
KH
610 (let ((slot (assoc input-method input-method-alist)))
611 (if (null slot)
723a427a 612 (error "Can't activate input method `%s'" input-method))
8efc03e1
KH
613 (let ((func (nth 2 slot)))
614 (if (functionp func)
615 (apply (nth 2 slot) input-method (nthcdr 5 slot))
616 (if (and (consp func) (symbolp (car func)) (symbolp (cdr func)))
617 (progn
618 (require (cdr func))
619 (apply (car func) input-method (nthcdr 5 slot)))
620 (error "Can't activate input method `%s'" input-method))))
d0b9c3ab 621 (setq current-input-method input-method)
723a427a
KH
622 (setq current-input-method-title (nth 3 slot))
623 (run-hooks 'input-method-activate-hook))))
15b3e511 624
15b3e511 625(defun inactivate-input-method ()
f17ccaee 626 "Turn off the current input method."
723a427a
KH
627 (when current-input-method
628 (if input-method-history
629 (unless (string= current-input-method (car input-method-history))
630 (setq input-method-history
631 (cons current-input-method
632 (delete current-input-method input-method-history))))
633 (setq input-method-history (list current-input-method)))
634 (unwind-protect
635 (funcall inactivate-current-input-method-function)
15b3e511 636 (unwind-protect
723a427a
KH
637 (run-hooks 'input-method-inactivate-hook)
638 (setq current-input-method nil
639 current-input-method-title nil)))))
4ed46869 640
8b784951 641(defun set-input-method (input-method)
723a427a
KH
642 "Select and turn on INPUT-METHOD.
643This sets the default input method to what you specify,
644and turn it on for the current buffer."
d0b9c3ab 645 (interactive
723a427a 646 (let* ((default (or (car input-method-history) default-input-method)))
42395763 647 (list (read-input-method-name
87505a98 648 (if default "Select input method (default %s): " "Select input method: ")
42395763 649 default t))))
d0b9c3ab 650 (activate-input-method input-method)
42395763 651 (setq default-input-method input-method))
4ed46869
KH
652
653(defun toggle-input-method (&optional arg)
15b3e511 654 "Turn on or off a multilingual text input method for the current buffer.
723a427a 655
d0b9c3ab 656With arg, read an input method from minibuffer and turn it on.
723a427a 657
15b3e511 658Without arg, if some input method is currently activated, turn it off,
723a427a
KH
659else turn on an input method selected last time
660or the default input method (see `default-input-method').
661
662When there's no input method to turn on, turn on what read from minibuffer."
4ed46869 663 (interactive "P")
723a427a 664 (let* ((default (or (car input-method-history) default-input-method)))
b4fba33f
KH
665 (if (and current-input-method (not arg))
666 (inactivate-input-method)
723a427a
KH
667 (activate-input-method
668 (if (or arg (not default))
669 (read-input-method-name
670 (if default "Input method (default %s): " "Input method: " )
671 default t)
672 default))
673 (or default-input-method
674 (setq default-input-method current-input-method)))))
d0b9c3ab
KH
675
676(defun describe-input-method (input-method)
4ef06f75 677 "Describe input method INPUT-METHOD."
d0b9c3ab
KH
678 (interactive
679 (list (read-input-method-name
680 "Describe input method (default, current choice): ")))
78754934 681 (if (and input-method (symbolp input-method))
4ef06f75 682 (setq input-method (symbol-name input-method)))
d0b9c3ab
KH
683 (if (null input-method)
684 (describe-current-input-method)
685 (with-output-to-temp-buffer "*Help*"
686 (let ((elt (assoc input-method input-method-alist)))
687 (princ (format "Input method: %s (`%s' in mode line) for %s\n %s\n"
688 input-method (nth 3 elt) (nth 1 elt) (nth 4 elt)))))))
689
690(defun describe-current-input-method ()
96db204a 691 "Describe the input method currently in use."
4ed46869
KH
692 (if current-input-method
693 (if (and (symbolp describe-current-input-method-function)
694 (fboundp describe-current-input-method-function))
695 (funcall describe-current-input-method-function)
696 (message "No way to describe the current input method `%s'"
697 (cdr current-input-method))
698 (ding))
d0b9c3ab 699 (error "No input method is activated now")))
4ed46869 700
d3459641 701(defun read-multilingual-string (prompt &optional initial-input input-method)
4ed46869
KH
702 "Read a multilingual string from minibuffer, prompting with string PROMPT.
703The input method selected last time is activated in minibuffer.
15b3e511 704If optional second arg INITIAL-INPUT is non-nil, insert it in the minibuffer
d0b9c3ab
KH
705initially.
706Optional 3rd argument INPUT-METHOD specifies the input method
4ef06f75
KH
707to be activated instead of the one selected last time. It is a symbol
708or a string."
88d559ec
KH
709 (setq input-method
710 (or input-method
d3459641 711 current-input-method
88d559ec
KH
712 default-input-method
713 (read-input-method-name "Input method: " nil t)))
3df60841 714 (if (and input-method (symbolp input-method))
4ef06f75 715 (setq input-method (symbol-name input-method)))
d3459641
KH
716 (let ((previous-input-method current-input-method))
717 (unwind-protect
718 (progn
719 (activate-input-method input-method)
720 (read-string prompt initial-input nil nil t))
721 (if previous-input-method
722 (activate-input-method previous-input-method)
723 (inactivate-input-method)))))
4ed46869
KH
724
725;; Variables to control behavior of input methods. All input methods
726;; should react to these variables.
727
8efc03e1
KH
728(defcustom input-method-verbose-flag 'default
729 "*A flag to control extra guidance given by input methods.
730The value should be nil, t, `complex-only', or `default'.
4ed46869 731
cb29dfb6 732The extra guidance is done by showing list of available keys in echo
8efc03e1
KH
733area. When you use the input method in the minibuffer, the guidance
734is shown at the bottom short window (split from the existing window).
c27c4ed8 735
8efc03e1
KH
736If the value is t, extra guidance is always given, if the value is
737nil, extra guidance is always suppressed.
738
739If the value is `complex-only', only complex input methods such as
740`chinese-py' and `japanese' give extra guidance.
741
742If the value is `default', complex input methods always give extra
743guidance, but simple input methods give it only when you are not in
744the minibuffer.
745
746See also the variable `input-method-highlight-flag'."
747 :type '(choice (const t) (const nil) (const complex-only) (const default))
42395763
RS
748 :group 'mule)
749
750(defcustom input-method-highlight-flag t
751 "*If this flag is non-nil, input methods highlight partially-entered text.
752For instance, while you are in the middle of a Quail input method sequence,
753the text inserted so far is temporarily underlined.
8efc03e1
KH
754The underlining goes away when you finish or abort the input method sequence.
755See also the variable `input-method-verbose-flag'."
42395763
RS
756 :type 'boolean
757 :group 'mule)
4ed46869
KH
758
759(defvar input-method-activate-hook nil
f17ccaee
KH
760 "Normal hook run just after an input method is activated.
761
762The variable `current-input-method' keeps the input method name
763just activated.")
4ed46869
KH
764
765(defvar input-method-inactivate-hook nil
f17ccaee
KH
766 "Normal hook run just after an input method is inactivated.
767
768The variable `current-input-method' still keeps the input method name
4d0e6a11 769just inactivated.")
4ed46869
KH
770
771(defvar input-method-after-insert-chunk-hook nil
772 "Normal hook run just after an input method insert some chunk of text.")
773
723a427a
KH
774(defvar input-method-exit-on-invalid-key nil
775 "This flag controls the behaviour of an input method on invalid key input.
776Usually, when a user types a key which doesn't start any character
777handled by the input method, the key is handled by turning off the
778input method temporalily. After the key is handled, the input method is
779back on.
780But, if this flag is non-nil, the input method is never back on.")
781
4ed46869 782\f
8efc03e1
KH
783(defvar set-language-environment-hook nil
784 "Normal hook run after some language environment is set.
785
786When you set some hook function here, that effect usually should not
787be inherited to another language environment. So, you had better set
788another function in `exit-language-environment-hook' (which see) to
789cancel the effect.")
790
791(defvar exit-language-environment-hook nil
792 "Normal hook run after exiting from some language environment.
793When this hook is run, the variable `current-language-environment'
794is still bound to the language environment being exited.
795
796This hook is mainly used for cancelling the effect of
797`set-language-environment-hook' (which-see).")
798
15b3e511 799(defun setup-specified-language-environment ()
f850d782 800 "Set up multi-lingual environment convenient for the specified language."
15b3e511 801 (interactive)
f850d782 802 (let (language-name)
15b3e511
KH
803 (if (and (symbolp last-command-event)
804 (or (not (eq last-command-event 'Default))
805 (setq last-command-event 'English))
f850d782
RS
806 (setq language-name (symbol-name last-command-event)))
807 (set-language-environment language-name)
15b3e511 808 (error "Bogus calling sequence"))))
4ed46869 809
f850d782
RS
810(defvar current-language-environment "English"
811 "The last language environment specified with `set-language-environment'.")
812
166246f7 813(defun set-language-environment (language-name)
6c05d680
RS
814 "Set up multi-lingual environment for using LANGUAGE-NAME.
815This sets the coding system priority and the default input method
816and sometimes other things."
8efc03e1
KH
817 (interactive (list (read-language-name
818 'setup-function
819 "Set language environment (default, English): ")))
4ef06f75
KH
820 (if language-name
821 (if (symbolp language-name)
822 (setq language-name (symbol-name language-name)))
823 (setq language-name "English"))
b4fba33f 824 (if (null (get-language-info language-name 'setup-function))
f850d782 825 (error "Language environment not defined: %S" language-name))
8efc03e1
KH
826 (if current-language-environment
827 (let ((func (get-language-info current-language-environment
828 'exit-function)))
e63645c2
KH
829 (run-hooks 'exit-language-environment-hook)
830 (if (fboundp func) (funcall func))))
f850d782 831 (setq current-language-environment language-name)
8efc03e1
KH
832 (funcall (get-language-info language-name 'setup-function))
833 (run-hooks 'set-language-environment-hook)
f850d782 834 (force-mode-line-update t))
4ed46869 835
54b226f7
KH
836(defun set-language-environment-coding-systems (language-name)
837 "Do various coding system setups for language environment LANGUAGE-NAME."
838 (let* ((priority (get-language-info language-name 'coding-priority))
839 (default-coding (car priority)))
840 (if priority
841 (let ((categories (mapcar 'coding-system-category priority)))
842 (set-default-coding-systems default-coding)
843 (set-coding-priority categories)
844 (while priority
845 (set (car categories) (car priority))
846 (setq priority (cdr priority) categories (cdr categories)))
847 (update-iso-coding-systems)))))
848
4ed46869
KH
849;; Print all arguments with `princ', then print "\n".
850(defsubst princ-list (&rest args)
851 (while args (princ (car args)) (setq args (cdr args)))
852 (princ "\n"))
853
48082651 854;; Print a language specific information such as input methods,
13e82c04 855;; charsets, and coding systems. This function is intended to be
48082651 856;; called from the menu:
281d03ec 857;; [menu-bar mule describe-language-environment LANGUAGE]
48082651
KH
858;; and should not run it by `M-x describe-current-input-method-function'.
859(defun describe-specified-language-support ()
96db204a 860 "Describe how Emacs supports the specified language environment."
48082651 861 (interactive)
281d03ec 862 (let (language-name)
48082651 863 (if (not (and (symbolp last-command-event)
281d03ec 864 (setq language-name (symbol-name last-command-event))))
48082651 865 (error "Bogus calling sequence"))
281d03ec
RS
866 (describe-language-environment language-name)))
867
868(defun describe-language-environment (language-name)
869 "Describe how Emacs supports language environment LANGUAGE-NAME."
78754934
KH
870 (interactive
871 (list (read-language-name
872 'documentation
8adfa8be 873 "Describe language environment (default, current choice): ")))
f850d782
RS
874 (if (null language-name)
875 (setq language-name current-language-environment))
281d03ec
RS
876 (if (or (null language-name)
877 (null (get-language-info language-name 'documentation)))
878 (error "No documentation for the specified language"))
4ef06f75
KH
879 (if (symbolp language-name)
880 (setq language-name (symbol-name language-name)))
281d03ec 881 (let ((doc (get-language-info language-name 'documentation)))
48082651 882 (with-output-to-temp-buffer "*Help*"
13e82c04 883 (if (stringp doc)
d0b9c3ab
KH
884 (progn
885 (princ-list doc)
886 (terpri)))
15b3e511
KH
887 (let ((str (get-language-info language-name 'sample-text)))
888 (if (stringp str)
889 (progn
281d03ec 890 (princ "Sample text:\n")
d0b9c3ab
KH
891 (princ-list " " str)
892 (terpri))))
281d03ec 893 (princ "Input methods:\n")
d0b9c3ab 894 (let ((l input-method-alist))
15b3e511 895 (while l
d0b9c3ab
KH
896 (if (string= language-name (nth 1 (car l)))
897 (princ-list " " (car (car l))
898 (format " (`%s' in mode line)" (nth 3 (car l)))))
15b3e511 899 (setq l (cdr l))))
281d03ec
RS
900 (terpri)
901 (princ "Character sets:\n")
15b3e511
KH
902 (let ((l (get-language-info language-name 'charset)))
903 (if (null l)
904 (princ-list " nothing specific to " language-name)
905 (while l
906 (princ-list " " (car l) ": "
907 (charset-description (car l)))
908 (setq l (cdr l)))))
281d03ec
RS
909 (terpri)
910 (princ "Coding systems:\n")
15b3e511
KH
911 (let ((l (get-language-info language-name 'coding-system)))
912 (if (null l)
913 (princ-list " nothing specific to " language-name)
48082651 914 (while l
281d03ec
RS
915 (princ (format " %s (`%c' in mode line):\n\t%s\n"
916 (car l)
917 (coding-system-mnemonic (car l))
a904b20b 918 (coding-system-doc-string (car l))))
8efc03e1
KH
919 (let ((aliases (coding-system-get (car l) 'alias-coding-systems)))
920 (when aliases
921 (princ "\t")
922 (princ (cons 'alias: (cdr aliases)))
923 (terpri)))
15b3e511 924 (setq l (cdr l))))))))
4ed46869
KH
925\f
926;;; Charset property
927
928(defsubst get-charset-property (charset propname)
929 "Return the value of CHARSET's PROPNAME property.
930This is the last value stored with
96db204a 931 (put-charset-property CHARSET PROPNAME VALUE)."
4ed46869
KH
932 (plist-get (charset-plist charset) propname))
933
934(defsubst put-charset-property (charset propname value)
935 "Store CHARSETS's PROPNAME property with value VALUE.
936It can be retrieved with `(get-charset-property CHARSET PROPNAME)'."
937 (set-charset-plist charset
938 (plist-put (charset-plist charset) propname value)))
939
940;;; Character code property
941(put 'char-code-property-table 'char-table-extra-slots 0)
942
943(defvar char-code-property-table
944 (make-char-table 'char-code-property-table)
945 "Char-table containing a property list of each character code.
946
947See also the documentation of `get-char-code-property' and
96db204a 948`put-char-code-property'.")
4ed46869
KH
949
950(defun get-char-code-property (char propname)
951 "Return the value of CHAR's PROPNAME property in `char-code-property-table'."
952 (let ((plist (aref char-code-property-table char)))
953 (if (listp plist)
954 (car (cdr (memq propname plist))))))
955
956(defun put-char-code-property (char propname value)
957 "Store CHAR's PROPNAME property with VALUE in `char-code-property-table'.
958It can be retrieved with `(get-char-code-property CHAR PROPNAME)'."
959 (let ((plist (aref char-code-property-table char)))
960 (if plist
961 (let ((slot (memq propname plist)))
962 (if slot
963 (setcar (cdr slot) value)
964 (nconc plist (list propname value))))
965 (aset char-code-property-table char (list propname value)))))
966
967;;; mule-cmds.el ends here