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