(help-map): Bind I to describe-input-method.
[bpt/emacs.git] / lisp / international / mule-cmds.el
1 ;;; mule-cmds.el --- Commands for mulitilingual environment
2
3 ;; Copyright (C) 1995 Electrotechnical Laboratory, JAPAN.
4 ;; Licensed to the Free Software Foundation.
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
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.
24
25 ;;; Code:
26
27 ;;; MULE related key bindings and menus.
28
29 (defvar mule-keymap nil
30 "Keymap for MULE (Multilingual environment) specific commands.")
31 (define-prefix-command 'mule-keymap)
32
33 ;; Keep "C-x C-m ..." for mule specific commands.
34 (define-key ctl-x-map "\C-m" 'mule-keymap)
35
36 (define-key mule-keymap "m" 'toggle-enable-multibyte-characters)
37 (define-key mule-keymap "f" 'set-buffer-file-coding-system)
38 (define-key mule-keymap "t" 'set-terminal-coding-system)
39 (define-key mule-keymap "k" 'set-keyboard-coding-system)
40 (define-key mule-keymap "p" 'set-buffer-process-coding-system)
41 (define-key mule-keymap "\C-\\" 'select-input-method)
42 (define-key mule-keymap "c" 'universal-coding-system-argument)
43
44 (define-key help-map "\C-L" 'describe-language-environment)
45 (define-key help-map "L" 'describe-language-environment)
46 (define-key help-map "\C-\\" 'describe-input-method)
47 (define-key help-map "I" 'describe-input-method)
48 (define-key help-map "C" 'describe-coding-system)
49 (define-key help-map "h" 'view-hello-file)
50
51 (defvar mule-menu-keymap nil
52 "Keymap for MULE (Multilingual environment) menu specific commands.")
53 (define-prefix-command 'mule-menu-keymap)
54
55 (define-key global-map [menu-bar mule] (cons "Mule" mule-menu-keymap))
56
57 (setq menu-bar-final-items (cons 'mule menu-bar-final-items))
58
59 (defvar describe-language-environment-map nil)
60 (define-prefix-command 'describe-language-environment-map)
61
62 (defvar setup-language-environment-map nil)
63 (define-prefix-command 'setup-language-environment-map)
64
65 (defvar set-coding-system-map nil)
66 (define-prefix-command 'set-coding-system-map)
67
68 (define-key-after mule-menu-keymap [toggle-mule]
69 '("Toggle MULE facility" . toggle-enable-multibyte-characters)
70 t)
71 (define-key-after mule-menu-keymap [describe-language-environment]
72 '("Describe language environment" . describe-language-environment-map)
73 t)
74 (define-key-after mule-menu-keymap [set-language-environment]
75 '("Set language environment" . setup-language-environment-map)
76 t)
77 (define-key-after mule-menu-keymap [mouse-set-font]
78 '("Set font/fontset" . mouse-set-font)
79 t)
80 (define-key-after mule-menu-keymap [separator-mule]
81 '("--")
82 t)
83 (define-key-after mule-menu-keymap [toggle-input-method]
84 '("Toggle input method" . toggle-input-method)
85 t)
86 (define-key-after mule-menu-keymap [select-input-method]
87 '("Select input method" . select-input-method)
88 t)
89 (define-key-after mule-menu-keymap [describe-input-method]
90 '("Describe input method" . describe-input-method)
91 t)
92 (define-key-after mule-menu-keymap [separator-input-method]
93 '("--")
94 t)
95 (define-key-after mule-menu-keymap [describe-coding-system]
96 '("Describe coding systems" . describe-coding-system)
97 t)
98 (define-key-after mule-menu-keymap [set-various-coding-system]
99 '("Set coding systems" . set-coding-system-map)
100 t)
101 (define-key-after mule-menu-keymap [separator-coding-system]
102 '("--")
103 t)
104 (define-key-after mule-menu-keymap [mule-diag]
105 '("Show diagnosis for MULE" . mule-diag)
106 t)
107 (define-key-after mule-menu-keymap [view-hello-file]
108 '("Show many languages" . view-hello-file)
109 t)
110
111 (define-key-after set-coding-system-map [set-buffer-file-coding-system]
112 '("Buffer file" . set-buffer-file-coding-system)
113 t)
114 (define-key-after set-coding-system-map [set-terminal-coding-system]
115 '("Terminal" . set-terminal-coding-system)
116 t)
117 (define-key-after set-coding-system-map [set-keyboard-coding-system]
118 '("Keyboard" . set-keyboard-coding-system)
119 t)
120 (define-key-after set-coding-system-map [set-buffer-process-coding-system]
121 '("Buffer process" . set-buffer-process-coding-system)
122 t)
123
124 (define-key setup-language-environment-map
125 [Default] '("Default" . setup-specified-language-environment))
126
127 ;; These are meaningless when running under X.
128 (put 'set-terminal-coding-system 'menu-enable
129 '(null window-system))
130 (put 'set-keyboard-coding-system 'menu-enable
131 '(null window-system))
132 ;; This is meaningless when the current buffer has no process.
133 (put 'set-buffer-process-coding-system 'menu-enable
134 '(get-buffer-process (current-buffer)))
135
136 ;; This should be a single character key binding because users use it
137 ;; very frequently while editing multilingual text. Now we can use
138 ;; only two such keys: "\C-\\" and "\C-^", but the latter is not
139 ;; convenient because it requires shifting on most keyboards. An
140 ;; alternative is "\C-\]" which is now bound to `abort-recursive-edit'
141 ;; but it won't be used that frequently.
142 (define-key global-map "\C-\\" 'toggle-input-method)
143
144 (defun toggle-enable-multibyte-characters (&optional arg)
145 "Change whether this buffer enables multibyte characters.
146 With arg, make them enable iff arg is positive."
147 (interactive "P")
148 (setq enable-multibyte-characters
149 (if (null arg) (null enable-multibyte-characters)
150 (> (prefix-numeric-value arg) 0)))
151 (force-mode-line-update))
152
153 (defun view-hello-file ()
154 "Display the HELLO file which list up many languages and characters."
155 (interactive)
156 ;; We have to decode the file in any environment.
157 (let ((default-enable-multibyte-characters t)
158 (coding-system-for-read 'iso-2022-7bit))
159 (find-file-read-only (expand-file-name "HELLO" data-directory))))
160
161 (defun universal-coding-system-argument ()
162 "Execute an I/O command using the specified coding system."
163 (interactive)
164 (let* ((coding-system (read-coding-system "Coding system: "))
165 (keyseq (read-key-sequence
166 (format "With coding system %s:" coding-system)))
167 (cmd (key-binding keyseq)))
168 (let ((coding-system-for-read coding-system)
169 (coding-system-for-write coding-system))
170 (message "")
171 (call-interactively cmd))))
172
173 \f
174 ;;; Language support staffs.
175
176 (defvar primary-language "English"
177 "Name of a user's primary language.
178 Emacs provide various language supports based on this variable.")
179
180 (defvar language-info-alist nil
181 "Alist of language names vs the corresponding information of various kind.
182 Each element looks like:
183 (LANGUAGE-NAME . ((KEY . INFO) ...))
184 where LANGUAGE-NAME is a string,
185 KEY is a symbol denoting the kind of information,
186 INFO is any Lisp object which contains the actual information related
187 to KEY.")
188
189 (defun get-language-info (language-name key)
190 "Return the information for LANGUAGE-NAME of the kind KEY.
191 LANGUAGE-NAME is a string.
192 KEY is a symbol denoting the kind of required information."
193 (let ((lang-slot (assoc-ignore-case language-name language-info-alist)))
194 (if lang-slot
195 (cdr (assq key (cdr lang-slot))))))
196
197 (defun set-language-info (language-name key info)
198 "Set for LANGUAGE-NAME the information INFO under KEY.
199 LANGUAGE-NAME is a string
200 KEY is a symbol denoting the kind of information.
201 INFO is any Lisp object which contains the actual information.
202
203 Currently, the following KEYs are used by Emacs:
204
205 charset: list of symbols whose values are charsets specific to the language.
206
207 coding-system: list of coding systems specific to the langauge.
208
209 tutorial: a tutorial file name written in the language.
210
211 sample-text: one line short text containing characters of the language.
212
213 documentation: t or a string describing how Emacs supports the language.
214 If a string is specified, it is shown before any other information
215 of the language by the command `describe-language-environment'.
216
217 setup-function: a function to call for setting up environment
218 convenient for a user of the language.
219
220 If KEY is documentation or setup-function, you can also specify
221 a cons cell as INFO, in which case, the car part should be
222 a normal value as INFO for KEY (as described above),
223 and the cdr part should be a symbol whose value is a menu keymap
224 in which an entry for the language is defined. But, only the car part
225 is actually set as the information.
226
227 We will define more KEYs in the future. To avoid conflict,
228 if you want to use your own KEY values, make them start with `user-'."
229 (let (lang-slot key-slot)
230 (setq lang-slot (assoc language-name language-info-alist))
231 (if (null lang-slot) ; If no slot for the language, add it.
232 (setq lang-slot (list language-name)
233 language-info-alist (cons lang-slot language-info-alist)))
234 (setq key-slot (assq key lang-slot))
235 (if (null key-slot) ; If no slot for the key, add it.
236 (progn
237 (setq key-slot (list key))
238 (setcdr lang-slot (cons key-slot (cdr lang-slot)))))
239 ;; Setup menu.
240 (cond ((eq key 'documentation)
241 (define-key-after
242 (if (consp info)
243 (prog1 (symbol-value (cdr info))
244 (setq info (car info)))
245 describe-language-environment-map)
246 (vector (intern language-name))
247 (cons language-name 'describe-specified-language-support)
248 t))
249 ((eq key 'setup-function)
250 (define-key-after
251 (if (consp info)
252 (prog1 (symbol-value (cdr info))
253 (setq info (car info)))
254 setup-language-environment-map)
255 (vector (intern language-name))
256 (cons language-name 'setup-specified-language-environment)
257 t)))
258
259 (setcdr key-slot info)
260 ))
261
262 (defun set-language-info-alist (language-name alist)
263 "Set for LANGUAGE-NAME the information in ALIST.
264 ALIST is an alist of KEY and INFO. See the documentation of
265 `set-langauge-info' for the meanings of KEY and INFO."
266 (while alist
267 (set-language-info language-name (car (car alist)) (cdr (car alist)))
268 (setq alist (cdr alist))))
269
270 (defun read-language-name (key prompt &optional initial-input)
271 "Read language name which has information for KEY, prompting with PROMPT."
272 (let* ((completion-ignore-case t)
273 (name (completing-read prompt
274 language-info-alist
275 (function (lambda (elm) (assq key elm)))
276 t
277 initial-input)))
278 (if (and (> (length name) 0)
279 (get-language-info name key))
280 name)))
281 \f
282 ;;; Multilingual input methods.
283
284 (defconst leim-list-file-name "leim-list.el"
285 "Name of LEIM list file.
286 This file contains a list of libraries of Emacs input methods (LEIM)
287 in the format of Lisp expression for registering each input method.
288 Emacs loads this file at startup time.")
289
290 (defvar leim-list-header (format "\
291 ;;; %s -- list of LEIM (Library of Emacs Input Method)
292 ;;
293 ;; This file contains a list of LEIM (Library of Emacs Input Method)
294 ;; in the same directory as this file. Loading this file registeres
295 ;; the whole input methods in Emacs.
296 ;;
297 ;; Each entry is has the form:
298 ;; (register-input-method
299 ;; INPUT-METHOD LANGUAGE-NAME ACTIVATE-FUNC
300 ;; TITLE DESCRIPTION
301 ;; ARG ...)
302 ;; See the function `register-input-method' for the meanings of arguments.
303 ;;
304 ;; If this directory is included in load-path, Emacs automatically
305 ;; loads this file at startup time.
306
307 "
308 leim-list-file-name)
309 "Header to be inserted in LEIM list file.")
310
311 (defvar leim-list-entry-regexp "(register-input-method"
312 "Regexp matching head of each entry in LEIM list file.
313 See also the variable `leim-list-header'")
314
315 (defvar update-leim-list-functions
316 '(quail-update-leim-list-file)
317 "List of functions to call to update LEIM list file.
318 Each function is called with one arg, LEIM directory name.")
319
320 (defun update-leim-list-file (dir)
321 "Update LEIM list file in directory DIR."
322 (let ((functions update-leim-list-functions))
323 (while functions
324 (funcall (car functions) (expand-file-name dir))
325 (setq functions (cdr functions)))))
326
327 (defun update-all-leim-list-files ()
328 "Update all the LEIM list files."
329 (interactive)
330 (let ((l load-path))
331 (while l
332 (if (string-match "leim" (car l))
333 (update-leim-list-file (car l)))
334 (setq l (cdr l)))))
335
336 (defvar current-input-method nil
337 "The current input method for multilingual text.
338 If nil, it means no input method is activated now.")
339 (make-variable-buffer-local 'current-input-method)
340 (put 'current-input-method 'permanent-local t)
341
342 (defvar current-input-method-title nil
343 "Title string of the current input method shown in mode line.")
344 (make-variable-buffer-local 'current-input-method-title)
345 (put 'current-input-method-title 'permanent-local t)
346
347 (defvar default-input-method nil
348 "Default input method for multilingual text.
349 The default input method is the one activated automatically by the command
350 `toggle-input-method' (\\[toggle-input-method]).")
351 (make-variable-buffer-local 'default-input-method)
352 (put 'default-input-method 'permanent-local t)
353
354 (defvar previous-input-method nil
355 "Input method selected previously in the current buffer.
356 This is the one selected before the current input method is selected.
357 See also the documentation of `default-input-method'.")
358 (make-variable-buffer-local 'previous-input-method)
359 (put 'previous-input-method 'permanent-local t)
360
361 (defvar inactivate-current-input-method-function nil
362 "Function to call for inactivating the current input method.
363 Every input method should set this to an appropriate value when activated.
364 This function is called with no argument.")
365 (make-variable-buffer-local 'inactivate-current-input-method-function)
366 (put 'inactivate-current-input-method-function 'permanent-local t)
367
368 (defvar describe-current-input-method-function nil
369 "Function to call for describing the current input method.
370 This function is called with no argument.")
371 (make-variable-buffer-local 'describe-current-input-method-function)
372 (put 'describe-current-input-method-function 'permanent-local t)
373
374 (defvar input-method-alist nil
375 "Alist of input method names vs the corresponding information to use it.
376 Each element has the form:
377 (INPUT-METHOD LANGUAGE-NAME ACTIVATE-FUNC TITLE DESCRIPTION ...)
378 See the function `register-input-method' for the meanings of each elements.")
379
380 (defun register-input-method (input-method language-name &rest args)
381 "Register INPUT-METHOD as an input method for LANGUAGE-NAME.
382 INPUT-METHOD and LANGUAGE-NAME are strings.
383 The remaining arguments are:
384 ACTIVATE-FUNC, TITLE, DESCRIPTION, and ARG ...
385 where,
386 ACTIVATE-FUNC is a function to call for activating this method.
387 TITLE is a string shown in mode-line while this method is active,
388 DESCRIPTION is a string describing about this method,
389 Arguments to ACTIVATE-FUNC are INPUT-METHOD and ARGs."
390 (let ((info (cons language-name args))
391 (slot (assoc input-method input-method-alist)))
392 (if slot
393 (setcdr slot info)
394 (setq slot (cons input-method info))
395 (setq input-method-alist (cons slot input-method-alist)))))
396
397 (defun read-input-method-name (prompt &optional initial-input inhibit-null)
398 "Read a name of input method from a minibuffer prompting with PROMPT.
399 If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.
400 If it is (STRING . POSITION), the initial input
401 is STRING, but point is placed POSITION characters into the string.
402 If INHIBIT-NULL is non-nil, null input signals an error."
403 (let* ((completion-ignore-case t)
404 (input-method (completing-read prompt input-method-alist
405 nil t initial-input)))
406 (if (> (length input-method) 0)
407 input-method
408 (if inhibit-null
409 (error "The specified input method is not avairable")))))
410
411 ;; Actvate INPUT-METHOD.
412 (defun activate-input-method (input-method)
413 (if (and current-input-method
414 (not (string= current-input-method input-method)))
415 (inactivate-input-method))
416 (if current-input-method
417 nil ; We have nothing to do.
418 (let ((slot (assoc input-method input-method-alist)))
419 (if (null slot)
420 (error "Invalid input method `%s'" input-method))
421 (apply (nth 2 slot) input-method (nthcdr 5 slot))
422 (setq current-input-method input-method)
423 (setq current-input-method-title (nth 3 slot))
424 (if (not (string= default-input-method current-input-method))
425 (setq previous-input-method default-input-method
426 default-input-method current-input-method)))))
427
428 ;; Inactivate the current input method.
429 (defun inactivate-input-method ()
430 (if current-input-method
431 (unwind-protect
432 (funcall inactivate-current-input-method-function)
433 (setq current-input-method nil))))
434
435 (defun select-input-method (input-method)
436 "Select and activate INPUT-METHOD.
437 Both the default and local values of default-input-method are
438 set to the selected input method.
439 See also the function `register-input-method'."
440 (interactive
441 (let* ((default (or previous-input-method default-input-method))
442 (initial (if default (cons default 0))))
443 (list (read-input-method-name "Input method: " initial t))))
444 (activate-input-method input-method)
445 (setq-default default-input-method default-input-method))
446
447 (defun toggle-input-method (&optional arg)
448 "Turn on or off a multilingual text input method for the current buffer.
449 With arg, read an input method from minibuffer and turn it on.
450 Without arg, if some input method is currently activated, turn it off,
451 else turn on default-input-method (which see).
452 In the latter case, if default-input-method is nil, select an input method
453 interactively."
454 (interactive "P")
455 (let* ((default (or previous-input-method default-input-method))
456 (initial (if default (cons default 0))))
457 (if arg
458 (activate-input-method
459 (read-input-method-name "Input method: " initial t))
460 (if current-input-method
461 (inactivate-input-method)
462 (if default-input-method
463 (activate-input-method default-input-method)
464 (activate-input-method
465 (read-input-method-name "Input method: " initial t)))))))
466
467 (defun describe-input-method (input-method)
468 "Describe the current input method."
469 (interactive
470 (list (read-input-method-name
471 "Describe input method (default, current choice): ")))
472 (if (null input-method)
473 (describe-current-input-method)
474 (with-output-to-temp-buffer "*Help*"
475 (let ((elt (assoc input-method input-method-alist)))
476 (princ (format "Input method: %s (`%s' in mode line) for %s\n %s\n"
477 input-method (nth 3 elt) (nth 1 elt) (nth 4 elt)))))))
478
479 (defun describe-current-input-method ()
480 "Describe the input method currently turned on."
481 (if current-input-method
482 (if (and (symbolp describe-current-input-method-function)
483 (fboundp describe-current-input-method-function))
484 (funcall describe-current-input-method-function)
485 (message "No way to describe the current input method `%s'"
486 (cdr current-input-method))
487 (ding))
488 (error "No input method is activated now")))
489
490 (defun read-multilingual-string (prompt &optional initial-input
491 input-method)
492 "Read a multilingual string from minibuffer, prompting with string PROMPT.
493 The input method selected last time is activated in minibuffer.
494 If optional second arg INITIAL-INPUT is non-nil, insert it in the minibuffer
495 initially.
496 Optional 3rd argument INPUT-METHOD specifies the input method
497 to be activated instead of the one selected last time."
498 (let ((default-input-method
499 (or input-method
500 default-input-method
501 (read-input-method-name "Input method: " nil t))))
502 (let ((minibuffer-setup-hook '(toggle-input-method)))
503 (read-string prompt initial-input))))
504
505 ;; Variables to control behavior of input methods. All input methods
506 ;; should react to these variables.
507
508 (defvar input-method-tersely-flag nil
509 "*If this flag is non-nil, input method works rather tersely.
510
511 For instance, Quail input method does not show guidance buffer while
512 inputting at minibuffer if this flag is t.")
513
514 (defvar input-method-activate-hook nil
515 "Normal hook run just after an input method is activated.")
516
517 (defvar input-method-inactivate-hook nil
518 "Normal hook run just after an input method is inactivated.")
519
520 (defvar input-method-after-insert-chunk-hook nil
521 "Normal hook run just after an input method insert some chunk of text.")
522
523 \f
524 (defun setup-specified-language-environment ()
525 "Setup multi-lingual environment convenient for the specified language."
526 (interactive)
527 (let (language-name func)
528 (if (and (symbolp last-command-event)
529 (or (not (eq last-command-event 'Default))
530 (setq last-command-event 'English))
531 (setq language-name (symbol-name last-command-event))
532 (setq func (get-language-info language-name 'setup-function)))
533 (progn
534 (funcall func)
535 (force-mode-line-update t))
536 (error "Bogus calling sequence"))))
537
538 ;;;###autoload
539 (defun set-language-environment (language-name)
540 "Set up multi-lingual environment for using LANGUAGE-NAME.
541 This sets the coding system priority and the default input method
542 and sometimes other things."
543 (interactive (list (read-language-name 'setup-function "Language: ")))
544 (if (or (null language-name)
545 (null (get-language-info language-name 'setup-function)))
546 (error "No way to setup environment for the specified language"))
547 (let ((last-command-event (intern language-name)))
548 (setup-specified-language-environment)))
549
550 ;; Print all arguments with `princ', then print "\n".
551 (defsubst princ-list (&rest args)
552 (while args (princ (car args)) (setq args (cdr args)))
553 (princ "\n"))
554
555 ;; Print a language specific information such as input methods,
556 ;; charsets, and coding systems. This function is intended to be
557 ;; called from the menu:
558 ;; [menu-bar mule describe-language-environment LANGUAGE]
559 ;; and should not run it by `M-x describe-current-input-method-function'.
560 (defun describe-specified-language-support ()
561 "Describe how Emacs supports the specified langugage."
562 (interactive)
563 (let (language-name)
564 (if (not (and (symbolp last-command-event)
565 (setq language-name (symbol-name last-command-event))))
566 (error "Bogus calling sequence"))
567 (describe-language-environment language-name)))
568
569 (defun describe-language-environment (language-name)
570 "Describe how Emacs supports language environment LANGUAGE-NAME."
571 (interactive (list (read-language-name 'documentation "Language: ")))
572 (if (or (null language-name)
573 (null (get-language-info language-name 'documentation)))
574 (error "No documentation for the specified language"))
575 (let ((doc (get-language-info language-name 'documentation)))
576 (with-output-to-temp-buffer "*Help*"
577 (if (stringp doc)
578 (progn
579 (princ-list doc)
580 (terpri)))
581 (let ((str (get-language-info language-name 'sample-text)))
582 (if (stringp str)
583 (progn
584 (princ "Sample text:\n")
585 (princ-list " " str)
586 (terpri))))
587 (princ "Input methods:\n")
588 (let ((l input-method-alist))
589 (while l
590 (if (string= language-name (nth 1 (car l)))
591 (princ-list " " (car (car l))
592 (format " (`%s' in mode line)" (nth 3 (car l)))))
593 (setq l (cdr l))))
594 (terpri)
595 (princ "Character sets:\n")
596 (let ((l (get-language-info language-name 'charset)))
597 (if (null l)
598 (princ-list " nothing specific to " language-name)
599 (while l
600 (princ-list " " (car l) ": "
601 (charset-description (car l)))
602 (setq l (cdr l)))))
603 (terpri)
604 (princ "Coding systems:\n")
605 (let ((l (get-language-info language-name 'coding-system)))
606 (if (null l)
607 (princ-list " nothing specific to " language-name)
608 (while l
609 (princ (format " %s (`%c' in mode line):\n\t%s\n"
610 (car l)
611 (coding-system-mnemonic (car l))
612 (coding-system-doc-string (car l))))
613 (setq l (cdr l))))))))
614 \f
615 ;;; Charset property
616
617 (defsubst get-charset-property (charset propname)
618 "Return the value of CHARSET's PROPNAME property.
619 This is the last value stored with
620 `(put-charset-property CHARSET PROPNAME VALUE)'."
621 (plist-get (charset-plist charset) propname))
622
623 (defsubst put-charset-property (charset propname value)
624 "Store CHARSETS's PROPNAME property with value VALUE.
625 It can be retrieved with `(get-charset-property CHARSET PROPNAME)'."
626 (set-charset-plist charset
627 (plist-put (charset-plist charset) propname value)))
628
629 ;;; Character code property
630 (put 'char-code-property-table 'char-table-extra-slots 0)
631
632 (defvar char-code-property-table
633 (make-char-table 'char-code-property-table)
634 "Char-table containing a property list of each character code.
635
636 See also the documentation of `get-char-code-property' and
637 `put-char-code-property'")
638
639 (defun get-char-code-property (char propname)
640 "Return the value of CHAR's PROPNAME property in `char-code-property-table'."
641 (let ((plist (aref char-code-property-table char)))
642 (if (listp plist)
643 (car (cdr (memq propname plist))))))
644
645 (defun put-char-code-property (char propname value)
646 "Store CHAR's PROPNAME property with VALUE in `char-code-property-table'.
647 It can be retrieved with `(get-char-code-property CHAR PROPNAME)'."
648 (let ((plist (aref char-code-property-table char)))
649 (if plist
650 (let ((slot (memq propname plist)))
651 (if slot
652 (setcar (cdr slot) value)
653 (nconc plist (list propname value))))
654 (aset char-code-property-table char (list propname value)))))
655
656 ;;; mule-cmds.el ends here