1 ;;; -*- coding: iso-2022-7bit; byte-compile-dynamic: t -*-
2 ;;; mucs.el --- Mule-UCS setup file.
4 ;; Copyright (C) 1997-2001 Miyashita Hisashi
6 ;; Keywords: mule, multilingual,
7 ;; character set, coding-system, ISO10646, Unicode
9 ;; This file is part of Mule-UCS
11 ;; Mule-UCS is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; Mule-UCS is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with this program; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
29 ;; 0.80->JISHOJI Temple
31 ;; 1.00->SHINNYODO Temple
32 ;; 1.10->SHIGAKOEMICHI Ave.
35 ;; 1.40->ROKUONJI Temple
36 ;; 1.50->NINNAJI Temple
37 ;; 1.60->HORIKAWA Liver
42 (defconst mucs-version "0.84 (KOUGETSUDAI:
\e$B8~7nBf
\e(B)")
44 ;; For error handling.
55 (defvar mucs-data-path "reldata/")
57 (defun mucs-require-data (package)
58 (or (featurep package)
59 ;; I cannot find out more appropriate way to
60 ;; construct realtive file name.
61 (load (file-relative-name
62 (expand-file-name (symbol-name package)
68 (defun mucs-require-supplement (package &optional base)
69 "require supplement module."
70 (or (featurep package)
71 (if (or load-in-progress
73 (load (expand-file-name
76 (if (and (boundp 'load-file-name)
77 (stringp load-file-name))
82 (error "Cannot resolve the location of %s!"
88 (defvar emacs-value-bits 28)
89 (defvar mucs-code-range-bits 27)
90 (defvar mucs-code-range-specials 100)
91 (defvar mucs-invalid-code -1
92 "invalid code. If this value is set, skip operation.")
94 (defun mucs-max-code ()
95 (1- (lsh 1 mucs-code-range-bits)))
97 (defun mucs-special-code (code)
99 (>= code mucs-code-range-specials))
100 (error "Invalid code:%d" code))
101 (- (lsh 1 mucs-code-range-bits) 1 code))
103 (defun mucs-arithmetic-adjust ()
104 (* 3 (lsh 1 (- mucs-code-range-bits 2))))
106 (defun mucs-arithmetic-range-lower ()
107 (lsh 1 (1- mucs-code-range-bits)))
109 (defun mucs-arithmetic-range-upper ()
110 (- (lsh 1 mucs-code-range-bits)
111 mucs-code-range-specials 1))
113 (defun mucs-max-number ()
114 (1- (lsh 1 (1- mucs-code-range-bits))))
116 (defun mucs-number-mask ()
120 ;;; version detection
123 (defvar mule-parsed-version
124 (and (boundp 'mule-version)
125 (string-match "^\\([0-9]+\\)\\.\\([0-9]+\\)" mule-version)
126 (cons (string-to-number (match-string 1 mule-version))
127 (string-to-number (match-string 2 mule-version)))))
129 (defun mule-version-satisfied-p (major minor)
130 (and mule-parsed-version
131 (or (> (car mule-parsed-version) major)
132 (and (= (car mule-parsed-version) major)
133 (>= (cdr mule-parsed-version) minor)))))
135 (defun xemacs-mule-p ()
136 (and (featurep 'xemacs)
139 (defmacro funcall-if-possible (func &rest args)
140 `(if (functionp ,func)
141 (funcall ,func ,@args)
144 ;;; Package management.
146 (defvar mucs-current-package nil)
148 (defvar mucs-current-type nil
149 "Mule-UCS code generator's internal variable.
150 This variable specifies the type of data that the current context stores.")
152 (defvar mucs-package-definition-end-hook nil
153 "At the end of package definition, call this hook.
154 In order to embed data or lisp code, use this hook.")
156 (defmacro mucs-embed-package-signature ()
158 (cons mucs-current-package
159 (get mucs-current-package 'mucs-imported-packages)))
161 cont result tempfunc)
164 (setq cont (get package
165 'mucs-registered-alist))
168 `((put (quote ,package)
169 'mucs-registered-alist
172 (setq cont (get package
173 'mucs-imported-packages))
177 `((put (quote ,package)
178 'mucs-imported-packages
183 (setq sig (append sig (funcall tempfunc (car packages)))
184 packages (cdr packages)))
187 (defmacro mucs-embed-program-with-hooks (hooksym)
188 (let ((hookval (symbol-value hooksym))
190 (if (functionp hookval)
191 (setq hookval (list hookval))
192 (if (not (listp hookval))
193 (error "Invalid hook:%S" hooksym)))
196 (funcall (car hookval))
198 hookval (cdr hookval)))
202 (defmacro mucs-define-package (package &rest form)
203 "Enclose a unit of package with this.
204 By this specification, Mule-UCS may judge
205 whether generate a new program to prepare.
206 You should make PACKAGE the same as your package name
207 that you set at `provide' function."
208 (if (not (symbolp package))
209 (signal 'wrong-type-argument
210 (list 'symbolp package)))
211 (setq mucs-current-package package)
212 (put mucs-current-package 'mucs-registered-alist nil)
214 `(let ((mucs-current-package (quote ,package))))
216 '((mucs-embed-program-with-hooks
217 mucs-package-definition-end-hook)
218 (mucs-embed-package-signature))))
220 (defmacro mucs-import-package (package)
222 (let ((mucs-ignore-version-incompatibilities t))
225 (get mucs-current-package 'mucs-imported-packages)))
226 (if (memq package import-list)
228 (put mucs-current-package 'mucs-imported-packages
229 (cons package import-list)))
230 `(let ((mucs-ignore-version-incompatibilities t))
231 (require (quote ,package))))))
233 (defsubst mucs-get-current-registered-alist ()
234 (get mucs-current-package
235 'mucs-registered-alist))
237 (defsubst mucs-set-current-registered-alist (alist)
238 (put mucs-current-package
239 'mucs-registered-alist
242 (defsubst mucs-get-registered-kind-alist (kind)
244 (cons mucs-current-package
245 (get mucs-current-package 'mucs-imported-packages)))
252 'mucs-registered-alist)))
254 packages (cdr packages)))
257 (defsubst mucs-get-registered-slot (kind object)
258 "If OBJECT have been already registered, return registered slot."
260 (mucs-get-registered-kind-alist kind)))
262 (defalias 'mucs-registered-p 'mucs-get-registered-slot)
264 (defsubst mucs-embedded-p (kind object)
265 (nth 1 (mucs-get-registered-slot kind object)))
267 (defun mucs-registered-object-list (kind)
269 (mucs-get-registered-kind-alist kind))
271 (while (setq elem (car objlist))
272 (setq result (cons (car elem) result)
273 objlist (cdr objlist)))
276 (defun mucs-unembedded-object-list (kind)
278 (mucs-get-registered-kind-alist kind))
280 (while (setq elem (car objlist))
281 (if (not (nth 1 elem))
282 (setq result (cons (car elem) result)))
283 (setq objlist (cdr objlist)))
286 (defun mucs-notify-embedment (kind object)
287 (let ((slot (mucs-get-registered-slot kind object)))
289 (error "%S has not been registered yet.(KIND:%S)"
291 (setcar (cdr slot) t)))
293 (defun mucs-register-object (kind object &optional embed)
294 "Register OBJECT to curent package's record.
295 If OBJECT have been already registered, return non-nil;
296 otherwise return nil."
297 (if mucs-current-package
298 (or (mucs-registered-p kind object)
300 (mucs-get-current-registered-alist))
303 (objslot (list object embed)))
306 (cons objslot (cdr slot)))
307 (mucs-set-current-registered-alist
308 (cons (list kind objslot)
312 (defun mucs-unregister-object (kind object)
314 (mucs-get-current-registered-alist))
319 (setq slot2 (assq object slot1))
321 (delq slot2 (cdr slot1))))))
323 ;;; Fundamental configuration ends here.
326 ;;; Mule-UCS conversion engine setup!
327 ;;; (currently, only CCL)
329 (cond ((fboundp 'ccl-execute)
331 ; ((fboundp 'cdl-execute)
332 ; (require 'mucs-cdl))
334 (error "This Emacs does not have Mule-UCS conversion engine!")))
338 ;; "conversion" manager
340 ;; PROPERTY SYMBOL LIST
342 ;; mucs-conversion-program:
343 ;; mucs-conversion-properties:
344 ;; mucs-conversion-program-marker:
346 (defvar mucs-current-conversion nil)
348 (defsubst mucs-conversion-p (symbol)
349 (or (get symbol 'mucs-conv-type)
352 (defsubst mucs-conversion-get (symbol key)
353 (if (not (mucs-conversion-p symbol))
354 (error "%S is not mucs-conversion." symbol))
355 (plist-get (get symbol 'mucs-conversion-properties)
358 (defsubst mucs-conversion-put (symbol key val)
359 (if (not (mucs-conversion-p symbol))
360 (error "%S is not mucs-conversion." symbol))
362 'mucs-conversion-properties
363 (plist-put (get symbol 'mucs-conversion-properties)
366 (defmacro mucs-define-conversion (symbol convtype definition)
368 SYMBOL is a symbol to identify the defined conversion.
369 CONVTYPE specifies how this conversion is used; You can specify
370 stream(symbol), font(symbol), or (FROM-TYPE . TO-TYPE),
371 where FROM-TYPE and TO-TYPE are defined MULE-UCS-TYPE.
372 If CONVTYPE is stream, this conversion is used for stream, i.e.
373 this can be used by coding-system.
374 If CONVTYPE is font, this conversion is used for font encoding.
375 If CONVTYPE is (FROM-TYPE . TO-TYPE), this conversion is used for
376 converting data of FROM-TYPE into data of TO-TYPE.
377 DEFINITION specifies the definition of the conversion.
379 conversions defined by this function are embedded to .elc file.
380 Therefore, you can use these without any Mule-UCS modules.
382 All arguments are NOT evaluated!"
383 (if (not (or (eq convtype 'stream)
386 (mucs-type-p (car convtype))
387 (mucs-type-p (cdr convtype))))
388 (error "Invalid CONVTYPE:%S" convtype))
389 (put symbol 'mucs-conv-type convtype)
391 (put (quote ,symbol) 'mucs-conv-type (quote ,convtype))
392 ,@(mucs-setup-conversion symbol definition)
393 (put (quote ,symbol) 'mucs-conversion-program
394 ,(mucs-conversion-get
395 symbol 'mucs-conversion-program-prep))
398 (defun mucs-conversion-set-program-marker (marker-sym program)
399 (list '\, `(cdar (put (quote ,mucs-current-conversion)
400 'mucs-conversion-program-marker
401 (cons (cons (quote ,marker-sym)
403 (get (quote ,mucs-current-conversion)
404 'mucs-conversion-program-marker))))))
406 (defsubst mucs-retrieve-marked-conversion-program (conv mark)
407 (cdr (assq mark (get conv 'mucs-conversion-program-marker))))
409 (defsubst mucs-substitute-conversion-program (conv mark newprog)
410 (let ((spot (mucs-retrieve-marked-conversion-program conv mark)))
411 (setcar spot (car newprog))
412 (setcdr spot (cdr newprog))))
414 (defun mucs-modify-conversion (conv mark newprog)
415 (mucs-substitute-conversion-program conv mark newprog)
416 (mucs-refresh-conversion
417 conv (get conv 'mucs-conversion-program)))
419 (defun mucs-conversion-definition-mag (definition)
420 (eval (car definition)))
422 (defun mucs-conversion-definition-main-prog (definition)
425 (defun mucs-conversion-definition-eof-prog (definition)
428 (defsubst mucs-conversion-get-conv-type (symbol)
429 (get symbol 'mucs-conv-type))
431 (defsubst mucs-conversion-set-program-and-compiled-code
432 (symbol program code)
433 (mucs-conversion-put symbol 'mucs-conversion-program-prep program)
437 'mucs-compiled-code code)))
440 ;;; Coding system API
443 (defmacro mucs-define-coding-system
444 (symbol mnemonic doc-string
445 decode-conversion encode-conversion
446 &optional alist eol-type)
447 (cond ((xemacs-mule-p)
449 (cond ((eq eol-type 'unix)
457 `(or (find-coding-system ,symbol)
458 (mucs-make-coding-system
459 ,symbol 'ccl ,doc-string
460 (list 'decode ,decode-conversion
461 'encode ,encode-conversion
462 'mnemonic (if (stringp ,mnemonic)
464 (char-to-string ,mnemonic))
465 'eol-type ,eol-type))))
466 ((mule-version-satisfied-p 4 1)
467 `(mucs-make-coding-system
468 ,symbol 4 ,mnemonic ,doc-string
469 (cons ,decode-conversion
473 `(mucs-make-coding-system
474 ,symbol 4 ,mnemonic ,doc-string
475 (cons ,decode-conversion
479 (error "This Emacs has no Mule feature."))))
482 ;;; Encoding/Decoding API.
485 ;;; Symbol's property
486 ;; mucs-encoding-backend
487 ;; mucs-encoding-default-backend
488 ;; mucs-decoding-backend
489 ;; mucs-decoding-default-backend
491 ;; Currently, supported restriction classes are:
495 (defsubst mucs-get-representation-encoding-backend
496 (representation restriction)
498 (or (and (listp restriction)
500 (assq (car restriction)
501 (get representation 'mucs-encoding-backend))))
502 (error "Invalid restriction:%S" restriction))
503 (get representation 'mucs-encoding-default-backend)))
505 (defsubst mucs-get-representation-decoding-backend
506 (representation restriction)
508 (or (and (listp restriction)
510 (assq (car restriction)
511 (get representation 'mucs-decoding-backend))))
512 (error "Invalid restriction:%S" restriction))
513 (get representation 'mucs-decoding-default-backend)))
515 (defun mucs-register-representation-encoding-backend
516 (representation restriction-category backend)
518 (cond ((eq restriction-category 'nil)
519 (put representation 'mucs-encoding-default-backend
521 ((symbolp restriction-category)
522 (setq alist (get representation 'mucs-encoding-backend)
523 slot (assq restriction-category representation))
525 (put representation 'mucs-encoding-backend
526 (cons (cons restriction-category backend)
528 (setcdr slot backend)))
530 (error "Invalid restriction category:%S." restriction-category)))))
532 (defun mucs-register-representation-decoding-backend
533 (representation restriction-category backend)
535 (cond ((eq restriction-category 'nil)
536 (put representation 'mucs-decoding-default-backend
538 ((symbolp restriction-category)
539 (setq alist (get representation 'mucs-decoding-backend)
540 slot (assq restriction-category representation))
542 (put representation 'mucs-decoding-backend
543 (cons (cons restriction-category backend)
545 (setcdr slot backend)))
547 (error "Invalid restriction category:%S." restriction-category)))))
549 (defun encode-char (char representation &optional restriction)
550 "Return character representation(code-point, explanation, category, attribute
551 and so on.) in REPRESENTATION that corresponds to CHAR.
552 Return nil if CHAR cannot be represented.
553 Available representation list can be obtained by mucs-representation-list.
555 Optional argument RESTRICTION specifies a way to map CHAR to
556 representation. Its interpretation depends on the given
557 REPRESENTATION. If not specified, the default restriction of
558 REPRESENTATION is used."
559 (let ((fs (mucs-get-representation-encoding-backend
560 representation restriction))
567 char representation restriction))))
571 (defun decode-char (representation object &optional restriction)
572 "Return a character represented by OBJECT in view of REPRESENTATION.
573 Return nil if OBJECT cannot be mapped to only one character.
574 Available representation list can be obtained by mucs-representation-list.
575 Optional argument RESTRICTION specifies a way to map OBJECT to
576 a character. Its interpretation depends on the given
577 REPRESENTATION. If not specified, the default restriction of REPRESENTATION
579 (let ((fs (mucs-get-representation-decoding-backend
580 representation restriction))
587 representation object restriction))))