(ideographic-radical):
[chise/xemacs-chise.git-] / lisp / utf-2000 / char-db-util.el
1 ;;; char-db-util.el --- Character Database utility -*- coding: utf-8-er; -*-
2
3 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
4 ;;   2007, 2008, 2009, 2010 MORIOKA Tomohiko.
5
6 ;; Author: MORIOKA Tomohiko <tomo@kanji.zinbun.kyoto-u.ac.jp>
7 ;; Keywords: CHISE, Character Database, ISO/IEC 10646, UCS, Unicode, MULE.
8
9 ;; This file is part of XEmacs CHISE.
10
11 ;; XEmacs CHISE is free software; you can redistribute it and/or
12 ;; modify it under the terms of the GNU General Public License as
13 ;; published by the Free Software Foundation; either version 2, or (at
14 ;; your option) any later version.
15
16 ;; XEmacs CHISE 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 GNU
19 ;; General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with XEmacs CHISE; see the file COPYING.  If not, write to
23 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
25
26 ;;; Code:
27
28 (require 'alist)
29
30 (defconst unidata-normative-category-alist
31   '(("Lu" letter        uppercase)
32     ("Ll" letter        lowercase)
33     ("Lt" letter        titlecase)
34     ("Mn" mark          non-spacing)
35     ("Mc" mark          spacing-combining)
36     ("Me" mark          enclosing)
37     ("Nd" number        decimal-digit)
38     ("Nl" number        letter)
39     ("No" number        other)
40     ("Zs" separator     space)
41     ("Zl" separator     line)
42     ("Zp" separator     paragraph)
43     ("Cc" other         control)
44     ("Cf" other         format)
45     ("Cs" other         surrogate)
46     ("Co" other         private-use)
47     ("Cn" other         not-assigned)))
48
49 (defconst unidata-informative-category-alist
50   '(("Lm" letter        modifier)
51     ("Lo" letter        other)
52     ("Pc" punctuation   connector)
53     ("Pd" punctuation   dash)
54     ("Ps" punctuation   open)
55     ("Pe" punctuation   close)
56     ("Pi" punctuation   initial-quote)
57     ("Pf" punctuation   final-quote)
58     ("Po" punctuation   other)
59     ("Sm" symbol        math)
60     ("Sc" symbol        currency)
61     ("Sk" symbol        modifier)
62     ("So" symbol        other)
63     ))
64
65 (defconst ideographic-radicals
66   (let ((v (make-vector 215 nil))
67         (i 1))
68     (while (< i 215)
69       (aset v i (decode-char '=ucs (+ #x2EFF i)))
70       (setq i (1+ i)))
71     v))
72
73 ;;;###autoload
74 (defun ideographic-radical (number)
75   "Return character corresponding with Kangxi-radical number."
76   (aref ideographic-radicals number))
77
78 (defconst shuowen-radicals
79   [?一 ?上 ?示 ?三 ?王 ?玉 ?玨 ?气 ?士 ?丨 ; 010
80    ?屮 ?艸 ?蓐 ?茻 ?小 ?八 ?釆 ?半 ?牛 ?犛 ; 020
81    ?告 ?口 ?凵 ?吅 ?哭 ?走 ?止 ?癶 ?步 ?此 ; 030
82    ?正 ?是 ?辵 ?彳 ?廴 ?㢟 ?行 ?齒 ?牙 ?足 ; 040
83    ?疋 ?品 ?龠 ?冊 ?㗊 ?舌 ?干 ?谷 ?只 ?㕯 ; 050
84    ?句 ?丩 ?古 ?十 ?卅 ?言 ?誩 ?音 ?䇂 ?丵 ; 060
85    ?菐 ?𠬞 ?廾 ?共 ?異 ?舁 ?𦥑 ?䢅 ?爨 ?革 ; 070
86    ?鬲 ?䰜 ?爪 ?𠃨 ?鬥 ?又 ?𠂇 ?㕜 ?支 ?𦘒 ; 080
87    ?聿 ?畫 ?隶 ?臤 ?臣 ?殳 ?殺 ?𠘧 ?寸 ?皮 ; 090
88    ?㼱 ?攴 ?敎 ?卜 ?用 ?爻 ?㸚 ?𥄎 ?目 ?䀠 ; 100
89    ?眉 ?盾 ?自 ?白 ?鼻 ?皕 ?習 ?羽 ?隹 ?奞 ; 110
90    ?萑 ?𦫳 ?苜 ?羊 ?羴 ?瞿 ?雔 ?雥 ?鳥 ?烏 ; 120
91    ?𠦒 ?冓 ?幺 ?𢆶 ?叀 ?玄 ?予 ?放 ?𠬪 ?𣦼 ; 130
92    ?歺 ?死 ?冎 ?骨 ?肉 ?筋 ?刀 ?刃 ?㓞 ?丰 ; 140
93    ?耒 ?𧢲 ?竹 ?箕 ?丌 ?左 ?工 ?㠭 ?巫 ?甘 ; 150
94    ?曰 ?乃 ?丂 ?可 ?兮 ?号 ?亏 ?旨 ?喜 ?壴 ; 160
95    ?鼓 ?豈 ?豆 ?豊 ?豐 ?䖒 ?虍 ?虎 ?虤 ?皿 ; 170
96    ?𠙴 ?去 ?血 ?丶 ?丹 ?青 ?井 ?皀 ?鬯 ?食 ; 180
97    ?亼 ?會 ?倉 ?入 ?缶 ?矢 ?高 ?冂 ?𩫏 ?京 ; 190
98    ?亯 ?𣆪 ?畗 ?㐭 ?嗇 ?來 ?麥 ?夊 ?舛 ?䑞 ; 200
99    ?韋 ?弟 ?夂 ?久 ?桀 ?木 ?東 ?林 ?才 ?叒 ; 210
100    ?之 ?帀 ?出 ?𣎵 ?生 ?乇 ?𠂹 ?𠌶 ?華 ?𥝌 ; 220
101    ?稽 ?巢 ?桼 ?束 ?㯻 ?囗 ?員 ?貝 ?邑 ?𨛜 ; 230
102    ?日 ?旦 ?倝 ?㫃 ?冥 ?晶 ?月 ?有 ?明 ?囧 ; 240
103    ?夕 ?多 ?毌 ?𢎘 ?𣐺 ?卣 ?齊 ?朿 ?片 ?鼎 ; 250
104    ?克 ?彔 ?禾 ?秝 ?黍 ?香 ?米 ?毇 ?臼 ?凶 ; 260
105    ?𣎳 ?林 ?麻 ?尗 ?耑 ?韭 ?瓜 ?瓠 ?宀 ?宮 ; 270
106    ?呂 ?穴 ?㝱 ?𤕫 ?冖 ?𠔼 ?冃 ?㒳 ?网 ?襾 ; 280
107    ?巾 ?巿 ?帛 ?白 ?㡀 ?黹 ?人 ?𠤎 ?匕 ?从 ; 290
108    ])
109
110 (defun shuowen-radical (number)
111   (aref shuowen-radicals (1- number)))
112
113 (defvar char-db-file-coding-system 'utf-8-mcs-er)
114
115 (defvar char-db-feature-domains
116   '(ucs ucs/compat daikanwa cns gt jis jis/alt jis/a jis/b
117         jis-x0212 jis-x0213 cdp shinjigen misc unknown))
118
119 (defvar char-db-ignored-attributes '(ideographic-products))
120
121 (defun char-attribute-name< (ka kb)
122   (cond
123    ((eq '->denotational kb)
124     t)
125    ((eq '->subsumptive kb)
126     (not (eq '->denotational ka)))
127    ((eq '->denotational ka)
128     nil)
129    ((eq '->subsumptive ka)
130     nil)
131    ((and (symbolp ka)
132          (string-match "^->" (symbol-name ka)))
133     (cond ((and (symbolp kb)
134                 (string-match "^->" (symbol-name kb)))
135            (string< (symbol-name ka)
136                     (symbol-name kb))
137            ))
138     )
139    ((and (symbolp kb)
140          (string-match "^->" (symbol-name kb)))
141     t)
142    ((and (symbolp ka)
143          (string-match "^<-" (symbol-name ka)))
144     (cond ((symbolp kb)
145            (cond ((string-match "^<-" (symbol-name kb))
146                   (string< (symbol-name ka)
147                            (symbol-name kb))
148                   )
149                  ;; ((string-match "^->" (symbol-name kb))
150                  ;;  t)
151                  )))
152     )
153    ((and (symbolp kb)
154          (string-match "^<-" (symbol-name kb)))
155     t
156     ;; (not (string-match "^->" (symbol-name ka)))
157     )
158    ((find-charset ka)
159     (if (find-charset kb)
160         (let (a-ir b-ir)
161           (if (setq a-ir (charset-property ka 'iso-ir))
162               (if (setq b-ir (charset-property kb 'iso-ir))
163                   (cond
164                    ((= a-ir b-ir)
165                     (< (charset-id ka)(charset-id kb))
166                     )
167                    ((= a-ir 177)
168                     t)
169                    ((= b-ir 177)
170                     nil)
171                    ((< a-ir
172                        b-ir)
173                     ))
174                 t)
175             (if (charset-property kb 'iso-ir)
176                 nil
177               (< (charset-id ka)(charset-id kb)))))
178       nil)
179     )
180    ((find-charset kb))
181    ((symbolp ka)
182     (cond ((symbolp kb)
183            (string< (symbol-name ka)
184                     (symbol-name kb)))
185           (t)))
186    ((symbolp kb)
187     nil)))
188
189 (defvar char-db-coded-charset-priority-list
190   '(ascii
191     control-1
192     latin-iso8859-1
193     latin-iso8859-2
194     latin-iso8859-3
195     latin-iso8859-4
196     latin-iso8859-9
197     latin-jisx0201
198     cyrillic-iso8859-5
199     greek-iso8859-7
200     thai-tis620
201     =jis-x0208
202     =jis-x0208@1978
203     =jis-x0208@1983
204     japanese-jisx0212
205     chinese-gb2312
206     =jis-x0208@1990
207     chinese-cns11643-1
208     chinese-cns11643-2
209     chinese-cns11643-3
210     chinese-cns11643-4
211     chinese-cns11643-5
212     chinese-cns11643-6
213     chinese-cns11643-7
214     =jis-x0213-1
215     =jis-x0213-1@2000
216     =jis-x0213-1@2004
217     =jis-x0213-2
218     korean-ksc5601
219     chinese-isoir165
220     katakana-jisx0201
221     hebrew-iso8859-8
222     chinese-gb12345
223     latin-viscii
224     ethiopic-ucs
225     =big5-cdp
226     =gt
227     =>>gt
228     ideograph-daikanwa-2
229     ideograph-daikanwa
230     =cbeta
231     ideograph-hanziku-1
232     ideograph-hanziku-2
233     ideograph-hanziku-3
234     ideograph-hanziku-4
235     ideograph-hanziku-5
236     ideograph-hanziku-6
237     ideograph-hanziku-7
238     ideograph-hanziku-8
239     ideograph-hanziku-9
240     ideograph-hanziku-10
241     ideograph-hanziku-11
242     ideograph-hanziku-12
243     =gt-k
244     =ucs@iso
245     =ucs@unicode
246     =>>jis-x0208
247     =>>jis-x0213-1
248     =>>jis-x0213-1@2000
249     =>>jis-x0213-1@2004
250     =>>jis-x0213-2
251     =>>jis-x0208@1978
252     =>jis-x0208
253     =>jis-x0208@1997
254     =>jis-x0213-1
255     =>jis-x0213-1@2000
256     =>jis-x0213-1@2004
257     =>jis-x0213-2
258     =big5
259     =big5-eten
260     =zinbun-oracle
261     =ruimoku-v6
262     =jef-china3
263     =shinjigen))
264
265 (defun char-db-make-char-spec (char)
266   (let (ret char-spec)
267     (cond ((characterp char)
268            (cond ((and (setq ret (encode-char char '=ucs 'defined-only))
269                        (not (and (<= #xE000 ret)(<= ret #xF8FF))))
270                   (setq char-spec (list (cons '=ucs ret)))
271                   (cond ((setq ret (get-char-attribute char 'name))
272                          (setq char-spec (cons (cons 'name ret) char-spec))
273                          )
274                         ((setq ret (get-char-attribute char 'name*))
275                          (setq char-spec (cons (cons 'name* ret) char-spec))
276                          ))
277                   )
278                  ((setq ret
279                         (catch 'tag
280                           (let ((rest char-db-coded-charset-priority-list)
281                                 ccs)
282                             (while rest
283                               (setq ccs (charset-name
284                                          (find-charset (car rest))))
285                               (if (setq ret
286                                         (encode-char char ccs
287                                                      'defined-only))
288                                   (throw 'tag (cons ccs ret)))
289                               (setq rest (cdr rest))))))
290                   (setq char-spec (list ret))
291                   (dolist (ccs (delq (car ret) (charset-list)))
292                     (if (and (or (charset-iso-final-char ccs)
293                                  (memq ccs
294                                        '(=daikanwa
295                                          =daikanwa@rev2
296                                          ;; =gt-k
297                                          =jis-x0208@1997
298                                          ))
299                                  (string-match "=ucs@" (symbol-name ccs)))
300                              (setq ccs (charset-name ccs))
301                              (null (assq ccs char-spec))
302                              (setq ret (encode-char char ccs 'defined-only)))
303                         (setq char-spec (cons (cons ccs ret) char-spec))))
304                   (if (null char-spec)
305                       (setq char-spec (split-char char)))
306                   (cond ((setq ret (get-char-attribute char 'name))
307                          (setq char-spec (cons (cons 'name ret) char-spec))
308                          )
309                         ((setq ret (get-char-attribute char 'name*))
310                          (setq char-spec (cons (cons 'name* ret) char-spec))
311                          ))
312                   )
313                  ((setq ret (get-char-attribute
314                              char 'ideographic-combination))
315                   (setq char-spec
316                         (cons (cons 'ideographic-combination ret)
317                               char-spec))
318                   ))
319            char-spec)
320           ((consp char)
321            char))))
322     
323 (defun char-db-insert-char-spec (char &optional readable column
324                                       required-features)
325   (unless column
326     (setq column (current-column)))
327   (let (char-spec temp-char)
328     (setq char-spec (char-db-make-char-spec char))
329     (unless (or (characterp char) ; char
330                 (condition-case nil
331                     (setq char (find-char char-spec))
332                   (error nil)))
333       ;; define temporary character
334       ;;   Current implementation is dirty.
335       (setq temp-char (define-char (cons '(ideograph-daikanwa . 0)
336                                          char-spec)))
337       (remove-char-attribute temp-char 'ideograph-daikanwa)
338       (setq char temp-char))
339     (insert-char-attributes char
340                             readable
341                             (union (mapcar #'car char-spec)
342                                    required-features))
343     (when temp-char
344       ;; undefine temporary character
345       ;;   Current implementation is dirty.
346       (setq char-spec (char-attribute-alist temp-char))
347       (while char-spec
348         (remove-char-attribute temp-char (car (car char-spec)))
349         (setq char-spec (cdr char-spec))))))
350
351 (defun char-db-insert-alist (alist &optional readable column)
352   (unless column
353     (setq column (current-column)))
354   (let ((line-breaking
355          (concat "\n" (make-string (1+ column) ?\ )))
356         name value
357         ret al ; cal
358         key
359         lbs cell rest separator)
360     (insert "(")
361     (while alist
362       (setq name (car (car alist))
363             value (cdr (car alist)))
364       (cond ((eq name 'char)
365              (insert "(char . ")
366              (if (setq ret (condition-case nil
367                                (find-char value)
368                              (error nil)))
369                  (progn
370                    (setq al nil
371                          ;; cal nil
372                          )
373                    (while value
374                      (setq key (car (car value)))
375                      ;; (if (find-charset key)
376                      ;;     (setq cal (cons key cal))
377                      (setq al (cons key al))
378                      ;; )
379                      (setq value (cdr value)))
380                    (insert-char-attributes ret
381                                            readable
382                                            (or al 'none) ; cal
383                                            ))
384                (insert (prin1-to-string value)))
385              (insert ")")
386              (insert line-breaking))
387             ((consp value)
388              (insert (format "(%-18s " name))
389              (setq lbs (concat "\n" (make-string (current-column) ?\ )))
390              (while (consp value)
391                (setq cell (car value))
392                (if (and (consp cell)
393                         (consp (car cell))
394                         (setq ret (condition-case nil
395                                       (find-char cell)
396                                     (error nil)))
397                         )
398                    (progn
399                      (setq rest cell
400                            al nil
401                            ;; cal nil
402                            )
403                      (while rest
404                        (setq key (car (car rest)))
405                        ;; (if (find-charset key)
406                        ;;     (setq cal (cons key cal))
407                        (setq al (cons key al))
408                        ;; )
409                        (setq rest (cdr rest)))
410                      (if separator
411                          (insert lbs))
412                      (insert-char-attributes ret
413                                              readable
414                                              al ; cal
415                                              )
416                      (setq separator lbs))
417                  (if separator
418                      (insert separator))
419                  (insert (prin1-to-string cell))
420                  (setq separator " "))
421                (setq value (cdr value)))
422              (insert ")")
423              (insert line-breaking))
424             (t
425              (insert (format "(%-18s . %S)%s"
426                              name value
427                              line-breaking))))
428       (setq alist (cdr alist))))
429   (insert ")"))
430
431 (defun char-db-insert-char-reference (plist &optional readable column)
432   (unless column
433     (setq column (current-column)))
434   (let ((line-breaking
435          (concat "\n" (make-string (1+ column) ?\ )))
436         (separator "")
437         name value)
438     (insert "(")
439     (while plist
440       (setq name (pop plist))
441       (setq value (pop plist))
442       (cond ((eq name :char)
443              (insert separator)
444              (insert ":char\t")
445              (cond ((numberp value)
446                     (setq value (decode-char '=ucs value)))
447                    ;; ((consp value)
448                    ;;  (setq value (or (find-char value)
449                    ;;                  value)))
450                    )
451              (char-db-insert-char-spec value readable)
452              (insert line-breaking)
453              (setq separator ""))
454             ((eq name :radical)
455              (insert (format "%s%s\t%d ; %c%s"
456                              separator
457                              name value
458                              (ideographic-radical value)
459                              line-breaking))
460              (setq separator ""))
461             (t
462              (insert (format "%s%s\t%S" separator name value))
463              (setq separator line-breaking)))
464       ))
465   (insert ")"))
466
467 (defun char-db-decode-isolated-char (ccs code-point)
468   (let (ret)
469     (setq ret
470           (cond ((eq ccs 'arabic-iso8859-6)
471                  (decode-char ccs code-point))
472                 ((and (memq ccs '(=gt-pj-1
473                                   =gt-pj-2
474                                   =gt-pj-3
475                                   =gt-pj-4
476                                   =gt-pj-5
477                                   =gt-pj-6
478                                   =gt-pj-7
479                                   =gt-pj-8
480                                   =gt-pj-9
481                                   =gt-pj-10
482                                   =gt-pj-11))
483                       (setq ret (decode-char ccs code-point))
484                       (setq ret (encode-char ret '=gt 'defined-only)))
485                  (decode-builtin-char '=gt ret))
486                 (t
487                  (decode-builtin-char ccs code-point))))
488     (cond ((and (<= 0 (char-int ret))
489                 (<= (char-int ret) #x1F))
490            (decode-char '=ucs (+ #x2400 (char-int ret))))
491           ((= (char-int ret) #x7F)
492            ?\u2421)
493           (t ret))))
494
495 (defvar char-db-convert-obsolete-format t)
496
497 (defun char-db-insert-ccs-feature (name value line-breaking)
498   (insert
499    (format
500     (cond ((memq name '(=shinjigen
501                         =shinjigen@1ed
502                         =shinjigen@rev =shinjigen/+p@rev))
503            "(%-18s .  %04d)\t; %c")
504           ((eq name '=shinjigen@1ed/24pr)
505            "(%-18s . %04d)\t; %c")
506           ((or (memq name '(=daikanwa
507                             =daikanwa@rev1 =daikanwa@rev2
508                             =gt =>>gt =>gt =gt-k =cbeta =zinbun-oracle))
509                (string-match "^=adobe-" (symbol-name name)))
510            "(%-18s . %05d)\t; %c")
511           ((eq name 'mojikyo)
512            "(%-18s . %06d)\t; %c")
513           ((>= (charset-dimension name) 2)
514            "(%-18s . #x%04X)\t; %c")
515           (t
516            "(%-18s . #x%02X)\t; %c"))
517     name
518     (if (= (charset-iso-graphic-plane name) 1)
519         (logior value
520                 (cond ((= (charset-dimension name) 1)
521                        #x80)
522                       ((= (charset-dimension name) 2)
523                        #x8080)
524                       ((= (charset-dimension name) 3)
525                        #x808080)
526                       (t 0)))
527       value)
528     (char-db-decode-isolated-char name value)))
529   (if (and (= (charset-chars name) 94)
530            (= (charset-dimension name) 2))
531       (insert (format " [%02d-%02d]"
532                       (- (lsh value -8) 32)
533                       (- (logand value 255) 32))))
534   (insert line-breaking))
535
536 (defun char-db-insert-relation-feature (char name value line-breaking
537                                              ccss readable)
538   (insert (format "(%-18s%s " name line-breaking))
539   (let ((lbs (concat "\n" (make-string (current-column) ?\ )))
540         separator cell sources required-features
541         ret)
542     (while (consp value)
543       (setq cell (car value))
544       (if (integerp cell)
545           (setq cell (decode-char '=ucs cell)))
546       (cond
547        ((eq name '->subsumptive)
548         (when (or (not (some (lambda (atr)
549                                (get-char-attribute cell atr))
550                              char-db-ignored-attributes))
551                   (some (lambda (ccs)
552                           (encode-char cell ccs 'defined-only))
553                         ccss))
554           (if separator
555               (insert lbs))
556           (let ((char-db-ignored-attributes
557                  (cons '<-subsumptive
558                        char-db-ignored-attributes)))
559             (insert-char-attributes cell readable))
560           (setq separator lbs))
561         )
562        ((characterp cell)
563         (setq sources
564               (get-char-attribute
565                char (intern (format "%s*sources" name))))
566         (setq required-features nil)
567         (dolist (source sources)
568           (cond
569            ((memq source '(JP
570                            JP/Jouyou
571                            shinjigen shinjigen@1ed shinjigen@rev))
572             (setq required-features
573                   (union required-features
574                          '(=jis-x0208
575                            =jis-x0208@1990
576                            =jis-x0213-1-2000
577                            =jis-x0213-2-2000
578                            =jis-x0212
579                            =jis-x0208@1983
580                            =jis-x0208@1978
581                            =shinjigen))))
582            ((eq source 'CN)
583             (setq required-features
584                   (union required-features
585                          '(=gb2312
586                            =gb12345
587                            =iso-ir165)))))
588           (cond
589            ((find-charset (setq ret (intern (format "=%s" source))))
590             (setq required-features
591                   (cons ret required-features)))
592            (t (setq required-features
593                     (cons source required-features)))))
594         (cond ((string-match "@JP" (symbol-name name))
595                (setq required-features
596                      (union required-features
597                             '(=jis-x0208
598                               =jis-x0208@1990
599                               =jis-x0213-1-2000
600                               =jis-x0213-2-2000
601                               =jis-x0212
602                               =jis-x0208@1983
603                               =jis-x0208@1978))))
604               ((string-match "@CN" (symbol-name name))
605                (setq required-features
606                      (union required-features
607                             '(=gb2312
608                               =gb12345
609                               =iso-ir165)))))
610         (if separator
611             (insert lbs))
612         (if readable
613             (insert (format "%S" cell))
614           (char-db-insert-char-spec cell readable
615                                     nil
616                                     required-features))
617         (setq separator lbs))
618        ((consp cell)
619         (if separator
620             (insert lbs))
621         (if (consp (car cell))
622             (char-db-insert-char-spec cell readable)
623           (char-db-insert-char-reference cell readable))
624         (setq separator lbs))
625        (t
626         (if separator
627             (insert separator))
628         (insert (prin1-to-string cell))
629         (setq separator " ")))
630       (setq value (cdr value)))
631     (insert ")")
632     (insert line-breaking)))
633
634 (defun insert-char-attributes (char &optional readable attributes column)
635   (unless column
636     (setq column (current-column)))
637   (let (name value ; has-long-ccs-name
638         rest
639         radical strokes
640         (line-breaking
641          (concat "\n" (make-string (1+ column) ?\ )))
642         lbs cell separator ret
643         key al cal
644         dest-ccss ; sources required-features
645         ccss)
646     (let (atr-d)
647       (setq attributes
648             (sort (if attributes
649                       (if (consp attributes)
650                           (progn
651                             (dolist (name attributes)
652                               (unless (memq name char-db-ignored-attributes)
653                                 (if (find-charset name)
654                                     (push name ccss))
655                                 (push name atr-d)))
656                             atr-d))
657                     (dolist (name (char-attribute-list))
658                       (unless (memq name char-db-ignored-attributes)
659                         (if (find-charset name)
660                             (push name ccss))
661                         (push name atr-d)))
662                     atr-d)
663                   #'char-attribute-name<)))
664     (insert "(")
665     (when (memq '<-subsumptive attributes)
666       (when readable
667         (when (setq value (get-char-attribute char '<-subsumptive))
668           (char-db-insert-relation-feature char '<-subsumptive value
669                                            line-breaking
670                                            ccss readable)))
671       (setq attributes (delq '<-subsumptive attributes)))
672     (when (and (memq '<-denotational attributes)
673                (setq value (get-char-attribute char '<-denotational)))
674       (char-db-insert-relation-feature char '<-denotational value
675                                        line-breaking
676                                        ccss readable)
677       (setq attributes (delq '<-denotational attributes)))
678     (when (and (memq 'name attributes)
679                (setq value (get-char-attribute char 'name)))
680       (insert (format
681                (if (> (+ (current-column) (length value)) 48)
682                    "(name . %S)%s"
683                  "(name               . %S)%s")
684                value line-breaking))
685       (setq attributes (delq 'name attributes))
686       )
687     (when (and (memq 'name* attributes)
688                (setq value (get-char-attribute char 'name*)))
689       (insert (format
690                (if (> (+ (current-column) (length value)) 48)
691                    "(name* . %S)%s"
692                  "(name*              . %S)%s")
693                value line-breaking))
694       (setq attributes (delq 'name* attributes))
695       )
696     (when (and (memq 'script attributes)
697                (setq value (get-char-attribute char 'script)))
698       (insert (format "(script\t\t%s)%s"
699                       (mapconcat (function prin1-to-string)
700                                  value " ")
701                       line-breaking))
702       (setq attributes (delq 'script attributes))
703       )
704     (dolist (name '(=>ucs =>ucs*))
705       (when (and (memq name attributes)
706                  (setq value (get-char-attribute char name)))
707         (insert (format "(%-18s . #x%04X)\t; %c%s"
708                         name value (decode-char '=ucs value)
709                         line-breaking))
710         (setq attributes (delq name attributes))))
711     (dolist (name '(=>ucs@gb =>ucs@cns =>ucs@jis =>ucs@ks =>ucs@big5))
712       (when (and (memq name attributes)
713                  (setq value (get-char-attribute char name)))
714         (insert (format "(%-18s . #x%04X)\t; %c%s"
715                         name value
716                         (decode-char (intern
717                                       (concat "="
718                                               (substring
719                                                (symbol-name name) 2)))
720                                      value)
721                         line-breaking))
722         (setq attributes (delq name attributes))
723         ))
724     (dolist (name '(=>daikanwa))
725       (when (and (memq name attributes)
726                  (setq value (get-char-attribute char name)))
727         (insert
728          (if (integerp value)
729              (format "(%-18s . %05d)\t; %c%s"
730                      name value (decode-char '=daikanwa value)
731                      line-breaking)
732            (format "(%-18s %s)\t; %c%s"
733                    name
734                    (mapconcat (function prin1-to-string)
735                               value " ")
736                    (char-representative-of-daikanwa char)
737                    line-breaking)))
738         (setq attributes (delq name attributes))))
739     (when (and (memq 'general-category attributes)
740                (setq value (get-char-attribute char 'general-category)))
741       (insert (format
742                "(general-category\t%s) ; %s%s"
743                (mapconcat (lambda (cell)
744                             (format "%S" cell))
745                           value " ")
746                (cond ((rassoc value unidata-normative-category-alist)
747                       "Normative Category")
748                      ((rassoc value unidata-informative-category-alist)
749                       "Informative Category")
750                      (t
751                       "Unknown Category"))
752                line-breaking))
753       (setq attributes (delq 'general-category attributes))
754       )
755     (when (and (memq 'bidi-category attributes)
756                (setq value (get-char-attribute char 'bidi-category)))
757       (insert (format "(bidi-category\t. %S)%s"
758                       value
759                       line-breaking))
760       (setq attributes (delq 'bidi-category attributes))
761       )
762     (unless (or (not (memq 'mirrored attributes))
763                 (eq (setq value (get-char-attribute char 'mirrored 'empty))
764                     'empty))
765       (insert (format "(mirrored\t\t. %S)%s"
766                       value
767                       line-breaking))
768       (setq attributes (delq 'mirrored attributes))
769       )
770     (cond
771      ((and (memq 'decimal-digit-value attributes)
772            (setq value (get-char-attribute char 'decimal-digit-value)))
773       (insert (format "(decimal-digit-value . %S)%s"
774                       value
775                       line-breaking))
776       (setq attributes (delq 'decimal-digit-value attributes))
777       (when (and (memq 'digit-value attributes)
778                  (setq value (get-char-attribute char 'digit-value)))
779         (insert (format "(digit-value\t . %S)%s"
780                         value
781                         line-breaking))
782         (setq attributes (delq 'digit-value attributes))
783         )
784       (when (and (memq 'numeric-value attributes)
785                  (setq value (get-char-attribute char 'numeric-value)))
786         (insert (format "(numeric-value\t . %S)%s"
787                         value
788                         line-breaking))
789         (setq attributes (delq 'numeric-value attributes))
790         )
791       )
792      (t
793       (when (and (memq 'digit-value attributes)
794                  (setq value (get-char-attribute char 'digit-value)))
795         (insert (format "(digit-value\t. %S)%s"
796                         value
797                         line-breaking))
798         (setq attributes (delq 'digit-value attributes))
799         )
800       (when (and (memq 'numeric-value attributes)
801                  (setq value (get-char-attribute char 'numeric-value)))
802         (insert (format "(numeric-value\t. %S)%s"
803                         value
804                         line-breaking))
805         (setq attributes (delq 'numeric-value attributes))
806         )))
807     (when (and (memq 'iso-10646-comment attributes)
808                (setq value (get-char-attribute char 'iso-10646-comment)))
809       (insert (format "(iso-10646-comment\t. %S)%s"
810                       value
811                       line-breaking))
812       (setq attributes (delq 'iso-10646-comment attributes))
813       )
814     (when (and (memq 'morohashi-daikanwa attributes)
815                (setq value (get-char-attribute char 'morohashi-daikanwa)))
816       (insert (format "(morohashi-daikanwa\t%s)%s"
817                       (mapconcat (function prin1-to-string) value " ")
818                       line-breaking))
819       (setq attributes (delq 'morohashi-daikanwa attributes))
820       )
821     (setq radical nil
822           strokes nil)
823     (when (and (memq 'ideographic-radical attributes)
824                (setq value (get-char-attribute char 'ideographic-radical)))
825       (setq radical value)
826       (insert (format "(ideographic-radical . %S)\t; %c%s"
827                       radical
828                       (ideographic-radical radical)
829                       line-breaking))
830       (setq attributes (delq 'ideographic-radical attributes))
831       )
832     (when (and (memq 'shuowen-radical attributes)
833                (setq value (get-char-attribute char 'shuowen-radical)))
834       (insert (format "(shuowen-radical\t. %S)\t; %c%s"
835                       value
836                       (shuowen-radical value)
837                       line-breaking))
838       (setq attributes (delq 'shuowen-radical attributes))
839       )
840     (let (key)
841       (dolist (domain
842                (append
843                 char-db-feature-domains
844                 (let (dest domain)
845                   (dolist (feature (char-attribute-list))
846                     (setq feature (symbol-name feature))
847                     (when (string-match
848                            "\\(radical\\|strokes\\)@\\([^@*]+\\)\\(\\*\\|$\\)"
849                            feature)
850                       (setq domain (intern (match-string 2 feature)))
851                      (unless (memq domain dest)
852                        (setq dest (cons domain dest)))))
853                   (sort dest #'string<))))
854         (setq key (intern (format "%s@%s" 'ideographic-radical domain)))
855         (when (and (memq key attributes)
856                    (setq value (get-char-attribute char key)))
857           (setq radical value)
858           (insert (format "(%s . %S)\t; %c%s"
859                           key
860                           radical
861                           (ideographic-radical radical)
862                           line-breaking))
863           (setq attributes (delq key attributes))
864           )
865         (setq key (intern (format "%s@%s" 'ideographic-strokes domain)))
866         (when (and (memq key attributes)
867                    (setq value (get-char-attribute char key)))
868           (setq strokes value)
869           (insert (format "(%s . %S)%s"
870                           key
871                           strokes
872                           line-breaking))
873           (setq attributes (delq key attributes))
874           )
875         (setq key (intern (format "%s@%s" 'total-strokes domain)))
876         (when (and (memq key attributes)
877                    (setq value (get-char-attribute char key)))
878           (insert (format "(%s       . %S)%s"
879                           key
880                           value
881                           line-breaking))
882           (setq attributes (delq key attributes))
883           )
884         (dolist (feature '(ideographic-radical
885                            ideographic-strokes
886                            total-strokes))
887           (setq key (intern (format "%s@%s*sources" feature domain)))
888           (when (and (memq key attributes)
889                      (setq value (get-char-attribute char key)))
890             (insert (format "(%s%s" key line-breaking))
891             (dolist (cell value)
892               (insert (format " %s" cell)))
893             (insert ")")
894             (insert line-breaking)
895             (setq attributes (delq key attributes))
896             ))
897         ))
898     (when (and (memq 'ideographic-strokes attributes)
899                (setq value (get-char-attribute char 'ideographic-strokes)))
900       (setq strokes value)
901       (insert (format "(ideographic-strokes . %S)%s"
902                       strokes
903                       line-breaking))
904       (setq attributes (delq 'ideographic-strokes attributes))
905       )
906     (when (and (memq 'kangxi-radical attributes)
907                (setq value (get-char-attribute char 'kangxi-radical)))
908       (unless (eq value radical)
909         (insert (format "(kangxi-radical\t . %S)\t; %c%s"
910                         value
911                         (ideographic-radical value)
912                         line-breaking))
913         (or radical
914             (setq radical value)))
915       (setq attributes (delq 'kangxi-radical attributes))
916       )
917     (when (and (memq 'kangxi-strokes attributes)
918                (setq value (get-char-attribute char 'kangxi-strokes)))
919       (unless (eq value strokes)
920         (insert (format "(kangxi-strokes\t . %S)%s"
921                         value
922                         line-breaking))
923         (or strokes
924             (setq strokes value)))
925       (setq attributes (delq 'kangxi-strokes attributes))
926       )
927     (when (and (memq 'japanese-radical attributes)
928                (setq value (get-char-attribute char 'japanese-radical)))
929       (unless (eq value radical)
930         (insert (format "(japanese-radical\t . %S)\t; %c%s"
931                         value
932                         (ideographic-radical value)
933                         line-breaking))
934         (or radical
935             (setq radical value)))
936       (setq attributes (delq 'japanese-radical attributes))
937       )
938     (when (and (memq 'japanese-strokes attributes)
939                (setq value (get-char-attribute char 'japanese-strokes)))
940       (unless (eq value strokes)
941         (insert (format "(japanese-strokes\t . %S)%s"
942                         value
943                         line-breaking))
944         (or strokes
945             (setq strokes value)))
946       (setq attributes (delq 'japanese-strokes attributes))
947       )
948     (when (and (memq 'cns-radical attributes)
949                (setq value (get-char-attribute char 'cns-radical)))
950       (insert (format "(cns-radical\t . %S)\t; %c%s"
951                       value
952                       (ideographic-radical value)
953                       line-breaking))
954       (setq attributes (delq 'cns-radical attributes))
955       )
956     (when (and (memq 'cns-strokes attributes)
957                (setq value (get-char-attribute char 'cns-strokes)))
958       (unless (eq value strokes)
959         (insert (format "(cns-strokes\t . %S)%s"
960                         value
961                         line-breaking))
962         (or strokes
963             (setq strokes value)))
964       (setq attributes (delq 'cns-strokes attributes))
965       )
966     (when (and (memq 'shinjigen-1-radical attributes)
967                (setq value (get-char-attribute char 'shinjigen-1-radical)))
968       (unless (eq value radical)
969         (insert (format "(shinjigen-1-radical . %S)\t; %c%s"
970                         value
971                         (ideographic-radical value)
972                         line-breaking))
973         (or radical
974             (setq radical value)))
975       (setq attributes (delq 'shinjigen-1-radical attributes))
976       )
977     (when (and (memq 'ideographic- attributes)
978                (setq value (get-char-attribute char 'ideographic-)))
979       (insert "(ideographic-       ")
980       (setq lbs (concat "\n" (make-string (current-column) ?\ ))
981             separator nil)
982       (while (consp value)
983         (setq cell (car value))
984         (if (integerp cell)
985             (setq cell (decode-char '=ucs cell)))
986         (cond ((characterp cell)
987                (if separator
988                    (insert lbs))
989                (if readable
990                    (insert (format "%S" cell))
991                  (char-db-insert-char-spec cell readable))
992                (setq separator lbs))
993               ((consp cell)
994                (if separator
995                    (insert lbs))
996                (if (consp (car cell))
997                    (char-db-insert-char-spec cell readable)
998                  (char-db-insert-char-reference cell readable))
999                (setq separator lbs))
1000               (t
1001                (if separator
1002                    (insert separator))
1003                (insert (prin1-to-string cell))
1004                (setq separator " ")))
1005         (setq value (cdr value)))
1006       (insert ")")
1007       (insert line-breaking)
1008       (setq attributes (delq 'ideographic- attributes)))
1009     (when (and (memq 'total-strokes attributes)
1010                (setq value (get-char-attribute char 'total-strokes)))
1011       (insert (format "(total-strokes       . %S)%s"
1012                       value
1013                       line-breaking))
1014       (setq attributes (delq 'total-strokes attributes))
1015       )
1016     (when (and (memq '->ideograph attributes)
1017                (setq value (get-char-attribute char '->ideograph)))
1018       (insert (format "(->ideograph\t%s)%s"
1019                       (mapconcat (lambda (code)
1020                                    (cond ((symbolp code)
1021                                           (symbol-name code))
1022                                          ((integerp code)
1023                                           (format "#x%04X" code))
1024                                          (t
1025                                           (format "%s %S"
1026                                                   line-breaking code))))
1027                                  value " ")
1028                       line-breaking))
1029       (setq attributes (delq '->ideograph attributes))
1030       )
1031     ;; (when (and (memq '->decomposition attributes)
1032     ;;            (setq value (get-char-attribute char '->decomposition)))
1033     ;;   (insert (format "(->decomposition\t%s)%s"
1034     ;;                   (mapconcat (lambda (code)
1035     ;;                                (cond ((symbolp code)
1036     ;;                                       (symbol-name code))
1037     ;;                                      ((characterp code)
1038     ;;                                       (if readable
1039     ;;                                           (format "%S" code)
1040     ;;                                         (format "#x%04X"
1041     ;;                                                 (char-int code))
1042     ;;                                         ))
1043     ;;                                      ((integerp code)
1044     ;;                                       (format "#x%04X" code))
1045     ;;                                      (t
1046     ;;                                       (format "%s%S" line-breaking code))))
1047     ;;                              value " ")
1048     ;;                   line-breaking))
1049     ;;   (setq attributes (delq '->decomposition attributes))
1050     ;;   )
1051     (if (equal (get-char-attribute char '->titlecase)
1052                (get-char-attribute char '->uppercase))
1053         (setq attributes (delq '->titlecase attributes)))
1054     (when (and (memq '->mojikyo attributes)
1055                (setq value (get-char-attribute char '->mojikyo)))
1056       (insert (format "(->mojikyo\t\t. %06d)\t; %c%s"
1057                       value (decode-char 'mojikyo value)
1058                       line-breaking))
1059       (setq attributes (delq '->mojikyo attributes))
1060       )
1061     (when (and (memq 'hanyu-dazidian-vol attributes)
1062                (setq value (get-char-attribute char 'hanyu-dazidian-vol)))
1063       (insert (format "(hanyu-dazidian-vol  . %d)%s"
1064                       value line-breaking))
1065       (setq attributes (delq 'hanyu-dazidian-vol attributes))
1066       )
1067     (when (and (memq 'hanyu-dazidian-page attributes)
1068                (setq value (get-char-attribute char 'hanyu-dazidian-page)))
1069       (insert (format "(hanyu-dazidian-page . %d)%s"
1070                       value line-breaking))
1071       (setq attributes (delq 'hanyu-dazidian-page attributes))
1072       )
1073     (when (and (memq 'hanyu-dazidian-char attributes)
1074                (setq value (get-char-attribute char 'hanyu-dazidian-char)))
1075       (insert (format "(hanyu-dazidian-char . %d)%s"
1076                       value line-breaking))
1077       (setq attributes (delq 'hanyu-dazidian-char attributes))
1078       )
1079     (unless readable
1080       (dolist (ignored '(composition
1081                          ->denotational <-subsumptive ->ucs-unified
1082                          ->ideographic-component-forms))
1083         (setq attributes (delq ignored attributes))))
1084     (while attributes
1085       (setq name (car attributes))
1086       (if (setq value (get-char-attribute char name))
1087           (cond ((setq ret (find-charset name))
1088                  (setq name (charset-name ret))
1089                  (if (and (not (memq name dest-ccss))
1090                           (prog1
1091                               (setq value (get-char-attribute char name))
1092                             (setq dest-ccss (cons name dest-ccss))))
1093                      (char-db-insert-ccs-feature name value line-breaking))
1094                  )
1095                 ((string-match "^=>ucs@" (symbol-name name))
1096                  (insert (format "(%-18s . #x%04X)\t; %c%s"
1097                                  name value (decode-char '=ucs value)
1098                                  line-breaking))
1099                  )
1100                 ((eq name 'jisx0208-1978/4X)
1101                  (insert (format "(%-18s . #x%04X)%s"
1102                                  name value
1103                                  line-breaking))
1104                  )
1105                 ((and
1106                   (not readable)
1107                   (not (eq name '->subsumptive))
1108                   (not (eq name '->uppercase))
1109                   (not (eq name '->lowercase))
1110                   (not (eq name '->titlecase))
1111                   (not (eq name '->canonical))
1112                   (not (eq name '->Bopomofo))
1113                   (not (eq name '->mistakable))
1114                   (not (eq name '->ideographic-variants))
1115                   (null (get-char-attribute
1116                          char (intern (format "%s*sources" name))))
1117                   (not (string-match "\\*sources$" (symbol-name name)))
1118                   (null (get-char-attribute
1119                          char (intern (format "%s*note" name))))
1120                   (not (string-match "\\*note$" (symbol-name name)))
1121                   (or (eq name '<-identical)
1122                       (eq name '<-uppercase)
1123                       (eq name '<-lowercase)
1124                       (eq name '<-titlecase)
1125                       (eq name '<-canonical)
1126                       (eq name '<-ideographic-variants)
1127                       ;; (eq name '<-synonyms)
1128                       (string-match "^<-synonyms" (symbol-name name))
1129                       (eq name '<-mistakable)
1130                       (when (string-match "^->" (symbol-name name))
1131                         (cond
1132                          ((string-match "^->fullwidth" (symbol-name name))
1133                           (not (and (consp value)
1134                                     (characterp (car value))
1135                                     (encode-char
1136                                      (car value) '=ucs 'defined-only)))
1137                           )
1138                          (t)))
1139                       ))
1140                  )
1141                 ((or (eq name 'ideographic-structure)
1142                      (eq name 'ideographic-combination)
1143                      (eq name 'ideographic-)
1144                      (eq name '=decomposition)
1145                      (string-match "^=>decomposition" (symbol-name name))
1146                      (string-match "^\\(->\\|<-\\)[^*]*$" (symbol-name name))
1147                      (string-match "^\\(->\\|<-\\)[^*]*\\*sources$"
1148                                    (symbol-name name))
1149                      )
1150                  (char-db-insert-relation-feature char name value
1151                                                   line-breaking
1152                                                   ccss readable))
1153                 ((memq name '(ideograph=
1154                               original-ideograph-of
1155                               ancient-ideograph-of
1156                               vulgar-ideograph-of
1157                               wrong-ideograph-of
1158                               ;; simplified-ideograph-of
1159                               ideographic-variants
1160                               ;; ideographic-different-form-of
1161                               ))
1162                  (insert (format "(%-18s%s " name line-breaking))
1163                  (setq lbs (concat "\n" (make-string (current-column) ?\ ))
1164                        separator nil)
1165                  (while (consp value)
1166                    (setq cell (car value))
1167                    (if (and (consp cell)
1168                             (consp (car cell)))
1169                        (progn
1170                          (if separator
1171                              (insert lbs))
1172                          (char-db-insert-alist cell readable)
1173                          (setq separator lbs))
1174                      (if separator
1175                          (insert separator))
1176                      (insert (prin1-to-string cell))
1177                      (setq separator " "))
1178                    (setq value (cdr value)))
1179                  (insert ")")
1180                  (insert line-breaking))
1181                 ((consp value)
1182                  (insert (format "(%-18s " name))
1183                  (setq lbs (concat "\n" (make-string (current-column) ?\ ))
1184                        separator nil)
1185                  (while (consp value)
1186                    (setq cell (car value))
1187                    (if (and (consp cell)
1188                             (consp (car cell))
1189                             (setq ret (condition-case nil
1190                                           (find-char cell)
1191                                         (error nil))))
1192                        (progn
1193                          (setq rest cell
1194                                al nil
1195                                cal nil)
1196                          (while rest
1197                            (setq key (car (car rest)))
1198                            (if (find-charset key)
1199                                (setq cal (cons key cal))
1200                              (setq al (cons key al)))
1201                            (setq rest (cdr rest)))
1202                          (if separator
1203                              (insert lbs))
1204                          (insert-char-attributes ret
1205                                                  readable
1206                                                  al cal)
1207                          (setq separator lbs))
1208                      (setq ret (prin1-to-string cell))
1209                      (if separator
1210                          (if (< (+ (current-column)
1211                                    (length ret)
1212                                    (length separator))
1213                                 76)
1214                              (insert separator)
1215                            (insert lbs)))
1216                      (insert ret)
1217                      (setq separator " "))
1218                    (setq value (cdr value)))
1219                  (insert ")")
1220                  (insert line-breaking))
1221                 (t
1222                  (insert (format "(%-18s" name))
1223                  (setq ret (prin1-to-string value))
1224                  (unless (< (+ (current-column)
1225                                (length ret)
1226                                3)
1227                             76)
1228                    (insert line-breaking))
1229                  (insert " . " ret ")" line-breaking)
1230                  ;; (insert (format "(%-18s . %S)%s"
1231                  ;;                 name value
1232                  ;;                 line-breaking))
1233                  )
1234                 ))
1235       (setq attributes (cdr attributes)))
1236     (insert ")")))
1237
1238 (defun insert-char-data (char &optional readable
1239                               attributes)
1240   (save-restriction
1241     (narrow-to-region (point)(point))
1242     (insert "(define-char
1243   '")
1244     (insert-char-attributes char readable attributes)
1245     (insert ")\n")
1246     (goto-char (point-min))
1247     (while (re-search-forward "[ \t]+$" nil t)
1248       (replace-match ""))
1249     ;; from tabify.
1250     (goto-char (point-min))
1251     (while (re-search-forward "[ \t][ \t][ \t]*" nil t)
1252       (let ((column (current-column))
1253             (indent-tabs-mode t))
1254         (delete-region (match-beginning 0) (point))
1255         (indent-to column)))
1256     (goto-char (point-max))
1257     ;; (tabify (point-min)(point-max))
1258     ))
1259
1260 (defun insert-char-data-with-variant (char &optional printable
1261                                            no-ucs-unified
1262                                            script excluded-script)
1263   (insert-char-data char printable)
1264   (let ((variants (char-variants char))
1265         rest
1266         variant vs ret)
1267     (setq variants (sort variants #'<))
1268     (setq rest variants)
1269     (setq variants (cons char variants))
1270     (while rest
1271       (setq variant (car rest))
1272       (unless (get-char-attribute variant '<-subsumptive)
1273         (if (and (or (null script)
1274                      (null (setq vs (get-char-attribute variant 'script)))
1275                      (memq script vs))
1276                  (or (null excluded-script)
1277                      (null (setq vs (get-char-attribute variant 'script)))
1278                      (not (memq excluded-script vs))))
1279             (unless (and no-ucs-unified (get-char-attribute variant '=ucs))
1280               (insert-char-data variant printable)
1281               (if (setq ret (char-variants variant))
1282                   (while ret
1283                     (or (memq (car ret) variants)
1284                         ;; (get-char-attribute (car ret) '<-subsumptive)
1285                         (setq rest (nconc rest (list (car ret)))))
1286                     (setq ret (cdr ret)))))))
1287       (setq rest (cdr rest)))))
1288
1289 (defun insert-char-range-data (min max &optional script excluded-script)
1290   (let ((code min)
1291         char)
1292     (while (<= code max)
1293       (setq char (decode-char '=ucs code))
1294       (if (encode-char char '=ucs 'defined-only)
1295           (insert-char-data-with-variant char nil 'no-ucs-unified
1296                                          script excluded-script))
1297       (setq code (1+ code)))))
1298
1299 (defun write-char-range-data-to-file (min max file
1300                                           &optional script excluded-script)
1301   (let ((coding-system-for-write char-db-file-coding-system))
1302     (with-temp-buffer
1303       (insert (format ";; -*- coding: %s -*-\n"
1304                       char-db-file-coding-system))
1305       (insert-char-range-data min max script excluded-script)
1306       (write-region (point-min)(point-max) file))))
1307
1308 (defvar what-character-original-window-configuration)
1309
1310 ;;;###autoload
1311 (defun what-char-definition (char)
1312   (interactive (list (char-after)))
1313   (let ((buf (get-buffer-create "*Character Description*"))
1314         (the-buf (current-buffer))
1315         (win-conf (current-window-configuration)))
1316     (pop-to-buffer buf)
1317     (make-local-variable 'what-character-original-window-configuration)
1318     (setq what-character-original-window-configuration win-conf)
1319     (setq buffer-read-only nil)
1320     (erase-buffer)
1321     (condition-case err
1322         (progn
1323           (insert-char-data-with-variant char 'printable)
1324           (unless (char-attribute-alist char)
1325             (insert (format ";; = %c\n"
1326                             (let* ((rest (split-char char))
1327                                    (ccs (pop rest))
1328                                    (code (pop rest)))
1329                               (while rest
1330                                 (setq code (logior (lsh code 8)
1331                                                    (pop rest))))
1332                               (decode-char ccs code)))))
1333           ;; (char-db-update-comment)
1334           (set-buffer-modified-p nil)
1335           (view-mode the-buf (lambda (buf)
1336                                (set-window-configuration
1337                                 what-character-original-window-configuration)
1338                                ))
1339           (goto-char (point-min)))
1340       (error (progn
1341                (set-window-configuration
1342                 what-character-original-window-configuration)
1343                (signal (car err) (cdr err)))))))
1344
1345 (provide 'char-db-util)
1346
1347 ;;; char-db-util.el ends here