(char-db-coded-charset-priority-list): Add `=ucs-itaiji-012'.
[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,2007,
4 ;;   2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019 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    ?裘 ?老 ?毛 ?毳 ?尸 ?尺 ?尾 ?履 ?舟 ?方 ; 310
99    ?儿 ?兄 ?兂 ?皃 ?𠑹 ?先 ?秃 ?見 ?覞 ?欠 ; 320
100    ?㱃 ?㳄 ?旡 ?頁 ?𦣻 ?面 ?丏 ?首 ?𥄉 ?須 ; 330
101    ?彡 ?彣 ?文 ?髟 ?后 ?司 ?卮 ?卩 ?印 ?色 ; 340
102    ?𠨍 ?辟 ?勹 ?包 ?茍 ?鬼 ?甶 ?厶 ?嵬 ?山 ; 350
103    ?屾 ?屵 ?广 ?厂 ?丸 ?危 ?石 ?長 ?勿 ?冄 ; 360
104    ?而 ?豕 ?㣇 ?彑 ?豚 ?豸 ?𤉡 ?易 ?象 ?馬 ; 370
105    ?𢊁 ?鹿 ?麤 ?㲋 ?兔 ?萈 ?犬 ?㹜 ?鼠 ?能 ; 380
106    ?熊 ?火 ?炎 ?黑 ?囪 ?焱 ?炙 ?赤 ?大 ?亦 ; 390
107    ?夨 ?夭 ?交 ?尣 ?壺 ?壹 ?㚔 ?奢 ?亢 ?夲 ; 400
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-ignored-attributes '(ideographic-products))
116
117 (defvar char-db-coded-charset-priority-list
118   '(ascii
119     control-1
120     latin-iso8859-1
121     latin-iso8859-2
122     latin-iso8859-3
123     latin-iso8859-4
124     latin-iso8859-9
125     latin-jisx0201
126     cyrillic-iso8859-5
127     greek-iso8859-7
128     thai-tis620
129     ;; =mj
130     ;; =adobe-japan1-0
131     ;; =adobe-japan1-1
132     ;; =adobe-japan1-2
133     ;; =adobe-japan1-3
134     ;; =adobe-japan1-4
135     ;; =adobe-japan1-5
136     ;; =adobe-japan1-6
137     =jis-x0208
138     =jis-x0208@1978
139     =jis-x0208@1983
140     japanese-jisx0212
141     chinese-gb2312
142     =jis-x0208@1990
143     chinese-cns11643-1
144     chinese-cns11643-2
145     chinese-cns11643-3
146     chinese-cns11643-4
147     chinese-cns11643-5
148     chinese-cns11643-6
149     chinese-cns11643-7
150     =jis-x0213-1
151     =jis-x0213-1@2000
152     =jis-x0213-1@2004
153     =jis-x0213-2
154     korean-ksc5601
155     chinese-isoir165
156     katakana-jisx0201
157     hebrew-iso8859-8
158     chinese-gb12345
159     latin-viscii
160     ethiopic-ucs
161     =big5-cdp
162     =hanyo-denshi/ja
163     =hanyo-denshi/jb
164     =hanyo-denshi/jc
165     =hanyo-denshi/jd
166     =hanyo-denshi/ft
167     =hanyo-denshi/ia
168     =hanyo-denshi/ib
169     =hanyo-denshi/hg
170     =hanyo-denshi/jt
171     =hanyo-denshi/ks
172     =hanyo-denshi/tk
173     ;; ==mj
174     ;; ==adobe-japan1-0
175     ;; ==adobe-japan1-1
176     ;; ==adobe-japan1-2
177     ;; ==adobe-japan1-3
178     ;; ==adobe-japan1-4
179     ;; ==adobe-japan1-5
180     ;; ==adobe-japan1-6
181     ==jis-x0208
182     ==jis-x0213-1
183     ==jis-x0213-2
184     ==jis-x0212
185     ==hanyo-denshi/ja
186     ==hanyo-denshi/jb
187     ==hanyo-denshi/jc
188     ==hanyo-denshi/ft
189     ==hanyo-denshi/ia
190     ==hanyo-denshi/ib
191     ==hanyo-denshi/hg
192     ==hanyo-denshi/jt
193     ==hanyo-denshi/ks
194     ==hanyo-denshi/tk
195     =gt
196     =gt-k
197     =daikanwa
198     =daikanwa@rev2
199     =daikanwa@rev1
200     =daikanwa/+p
201     ==daikanwa
202     =cbeta
203     ideograph-hanziku-1
204     ideograph-hanziku-2
205     ideograph-hanziku-3
206     ideograph-hanziku-4
207     ideograph-hanziku-5
208     ideograph-hanziku-6
209     ideograph-hanziku-7
210     ideograph-hanziku-8
211     ideograph-hanziku-9
212     ideograph-hanziku-10
213     ideograph-hanziku-11
214     ideograph-hanziku-12
215     ;; =>>>adobe-japan1-0
216     ;; =>>>adobe-japan1-1
217     ;; =>>>adobe-japan1-2
218     ;; =>>>adobe-japan1-3
219     ;; =>>>adobe-japan1-4
220     ;; =>>>adobe-japan1-5
221     ;; =>>>adobe-japan1-6
222     ;; =>>>jis-x0208
223     ;; =>>>jis-x0213-1
224     ;; =>>>jis-x0213-2
225     ;; =>>>hanyo-denshi/ja
226     ;; =>>>hanyo-denshi/jb
227     ;; =>>>hanyo-denshi/jc
228     ;; =>>>hanyo-denshi/ft
229     ;; =>>>hanyo-denshi/ib
230     ;; =>>>hanyo-denshi/hg
231     ;; =>>>hanyo-denshi/jt
232     ;; =>>>hanyo-denshi/ks
233     ;; =>>>gt
234     =>>adobe-japan1-0
235     =>>adobe-japan1-1
236     =>>adobe-japan1-2
237     =>>adobe-japan1-3
238     =>>adobe-japan1-4
239     =>>adobe-japan1-5
240     =>>adobe-japan1-6
241     =>>jis-x0208
242     =>>jis-x0213-1
243     =>>jis-x0213-1@2000
244     =>>jis-x0213-1@2004
245     =>>jis-x0213-2
246     =>>jis-x0208@1978
247     =>>hanyo-denshi/ft
248     =>>hanyo-denshi/jt
249     =>>hanyo-denshi/ks
250     =>>gt
251     =>>daikanwa
252     =>>cbeta
253     =+>jis-x0208
254     =+>jis-x0213-1
255     =+>jis-x0213-2
256     =+>adobe-japan1-0
257     =+>adobe-japan1-1
258     =+>adobe-japan1-2
259     =+>adobe-japan1-3
260     =+>adobe-japan1-4
261     =+>adobe-japan1-5
262     =+>adobe-japan1-6
263     =+>jis-x0208@1978
264     =>jis-x0208
265     =>jis-x0208@1997
266     =>jis-x0213-1
267     =>jis-x0213-1@2000
268     =>jis-x0213-1@2004
269     =>jis-x0213-2
270     ==>ucs@bucs
271     =>iwds-1
272     ;; =>ucs@hanyo-denshi
273     =>ucs@iso
274     =>ucs@unicode
275     =>ucs@jis
276     =>ucs@cns
277     =>ucs@ks
278     =+>ucs@iso
279     =+>ucs@unicode
280     =+>ucs@jis
281     =+>ucs@jis/1990
282     =+>ucs@cns
283     =+>ucs@ks
284     =>>ucs@iso
285     =>>ucs@unicode
286     =>>ucs@jis
287     =>>ucs@cns
288     =>>>ucs@iso
289     =>>>ucs@unicode
290     ==ucs@iso
291     ==ucs@unicode
292     ;; ==ucs@cns
293     ==gb2312
294     ==ks-x1001
295     ==cns11643-1
296     ==cns11643-2
297     ==cns11643-3
298     ==cns11643-4
299     ==cns11643-5
300     ==cns11643-6
301     ==cns11643-7
302     ==gt
303     ==jis-x0208@1990
304     ;; ==jis-x0208@1983
305     ==jis-x0208@1978
306     ==gt-k
307     =ucs@iso
308     =ucs@unicode
309     =ucs@cns
310     ==big5-cdp
311     ==cbeta
312     =>>big5-cdp
313     =>>gt-k
314     =+>gt
315     =+>big5-cdp
316     =>gt
317     =>mj
318     =>big5-cdp
319     =>daikanwa
320     =>daikanwa/ho
321     =>cns11643-5
322     =>cns11643-7
323     =big5
324     =big5-eten
325     =>gt-k
326     =zinbun-oracle
327     =>zinbun-oracle
328     =ruimoku-v6
329     =>>ruimoku-v6
330     ==ruimoku-v6
331     =jef-china3
332     =>cbeta
333     =shinjigen
334     =ucs-var-001
335     =ucs-var-002
336     =ucs-var-003
337     =ucs-var-004
338     =ucs-var-005
339     =ucs-var-006
340     =ucs-var-008
341     =ucs-var-010
342     =ucs-itaiji-001
343     =ucs-itaiji-002
344     =ucs-itaiji-003
345     =ucs-itaiji-004
346     =ucs-itaiji-005
347     =ucs-itaiji-006
348     =ucs-itaiji-007
349     =ucs-itaiji-008
350     =ucs-itaiji-009
351     =ucs-itaiji-010
352     =ucs-itaiji-011
353     =ucs-itaiji-012
354     =>ucs-itaiji-001
355     =>ucs-itaiji-002
356     =>ucs-itaiji-003
357     =>ucs-itaiji-004
358     =>ucs-itaiji-005
359     =>ucs-itaiji-006
360     =>ucs-itaiji-007
361     =>ucs-itaiji-009
362     =big5-cdp-var-001
363     =big5-cdp-var-002
364     =big5-cdp-var-003
365     =big5-cdp-var-004
366     =big5-cdp-var-005
367     =big5-cdp-var-010
368     =big5-cdp-itaiji-001
369     =big5-cdp-itaiji-002
370     =big5-cdp-itaiji-003
371     =>big5-cdp-itaiji-001
372     =>ucs@iwds-1
373     =>ucs@cognate
374     =>ucs@component
375     =>ucs-itaiji-001@iwds-1
376     =>big5-cdp@iwds-1
377     =>big5-cdp@component
378     =>big5-cdp@cognate
379     ==ucs@gb
380     =ucs@gb
381     ==ucs-var-002
382     =ucs@JP/hanazono))
383
384
385 ;;; @ char-db formatters
386 ;;;
387
388 (defun char-db-make-char-spec (char)
389   (let (ret char-spec)
390     (cond ((characterp char)
391            (cond ((and (setq ret (encode-char char '=ucs 'defined-only))
392                        (not (and (<= #xE000 ret)(<= ret #xF8FF))))
393                   (setq char-spec (list (cons '=ucs ret)))
394                   (cond ((setq ret (get-char-attribute char 'name))
395                          (setq char-spec (cons (cons 'name ret) char-spec))
396                          )
397                         ((setq ret (get-char-attribute char 'name*))
398                          (setq char-spec (cons (cons 'name* ret) char-spec))
399                          ))
400                   )
401                  ((encode-char char '=mj 'defined-only)
402                   (setq char-spec nil)
403                   (dolist (ccs (charset-list))
404                     (if (and (or (eq ccs '=mj)
405                                  ;; (eq (charset-property ccs 'iso-ir) 177)
406                                  (string-match "=ucs@" (symbol-name ccs))
407                                  )
408                              (setq ccs (charset-name ccs))
409                              (null (assq ccs char-spec))
410                              (setq ret (encode-char char ccs 'defined-only)))
411                         (setq char-spec (cons (cons ccs ret) char-spec))))
412                   )
413                  ((encode-char char '==mj 'defined-only)
414                   (setq char-spec nil)
415                   (dolist (ccs (charset-list))
416                     (if (and (or (eq ccs '==mj)
417                                  ;; (eq (charset-property ccs 'iso-ir) 177)
418                                  (string-match "=ucs@" (symbol-name ccs))
419                                  )
420                              (setq ccs (charset-name ccs))
421                              (null (assq ccs char-spec))
422                              (setq ret (encode-char char ccs 'defined-only)))
423                         (setq char-spec (cons (cons ccs ret) char-spec))))
424                   )
425                  ((encode-char char '=adobe-japan1 'defined-only)
426                   (setq char-spec nil)
427                   (dolist (ccs (charset-list))
428                     (if (and (or (memq ccs
429                                        '(=adobe-japan1-0
430                                          =adobe-japan1-1
431                                          =adobe-japan1-2
432                                          =adobe-japan1-3
433                                          =adobe-japan1-4
434                                          =adobe-japan1-5
435                                          =adobe-japan1-6
436                                          ))
437                                  ;; (eq (charset-property ccs 'iso-ir) 177)
438                                  (string-match "=ucs@" (symbol-name ccs))
439                                  )
440                              (setq ccs (charset-name ccs))
441                              (null (assq ccs char-spec))
442                              (setq ret (encode-char char ccs 'defined-only)))
443                         (setq char-spec (cons (cons ccs ret) char-spec))))
444                   )
445                  ((encode-char char '==adobe-japan1 'defined-only)
446                   (setq char-spec nil)
447                   (dolist (ccs (charset-list))
448                     (if (and (or (memq ccs
449                                        '(==adobe-japan1-0
450                                          ==adobe-japan1-1
451                                          ==adobe-japan1-2
452                                          ==adobe-japan1-3
453                                          ==adobe-japan1-4
454                                          ==adobe-japan1-5
455                                          ==adobe-japan1-6
456                                          ))
457                                  ;; (eq (charset-property ccs 'iso-ir) 177)
458                                  (string-match "=ucs@" (symbol-name ccs))
459                                  )
460                              (setq ccs (charset-name ccs))
461                              (null (assq ccs char-spec))
462                              (setq ret (encode-char char ccs 'defined-only)))
463                         (setq char-spec (cons (cons ccs ret) char-spec))))
464                   )
465                  ((setq ret
466                         (catch 'tag
467                           (let ((rest char-db-coded-charset-priority-list)
468                                 ccs)
469                             (while rest
470                               (setq ccs (charset-name
471                                          (find-charset (car rest))))
472                               (if (setq ret
473                                         (encode-char char ccs
474                                                      'defined-only))
475                                   (throw 'tag (cons ccs ret)))
476                               (setq rest (cdr rest))))))
477                   (setq char-spec (list ret))
478                   (dolist (ccs (delq (car ret) (charset-list)))
479                     (if (and (or (charset-iso-final-char ccs)
480                                  (memq ccs
481                                        '(=daikanwa
482                                          =daikanwa@rev2
483                                          ;; =gt-k
484                                          =jis-x0208@1997
485                                          ))
486                                  (and (eq (charset-property ccs 'iso-ir) 177)
487                                       (not (eq (charset-name ccs) '=ucs@big5)))
488                                  ;; (string-match "=ucs@" (symbol-name ccs))
489                                  )
490                              (setq ccs (charset-name ccs))
491                              (null (assq ccs char-spec))
492                              (setq ret (encode-char char ccs 'defined-only)))
493                         (setq char-spec (cons (cons ccs ret) char-spec))))
494                   (if (null char-spec)
495                       (setq char-spec (split-char char)))
496                   (cond ((setq ret (get-char-attribute char 'name))
497                          (setq char-spec (cons (cons 'name ret) char-spec))
498                          )
499                         ((setq ret (get-char-attribute char 'name*))
500                          (setq char-spec (cons (cons 'name* ret) char-spec))
501                          ))
502                   )
503                  ((setq ret (get-char-attribute
504                              char 'ideographic-combination))
505                   (setq char-spec
506                         (cons (cons 'ideographic-combination ret)
507                               char-spec))
508                   ))
509            char-spec)
510           ((consp char)
511            char))))
512     
513 (defun char-db-insert-char-spec (char &optional readable column
514                                       required-features)
515   (unless column
516     (setq column (current-column)))
517   (let (char-spec temp-char)
518     (setq char-spec (char-db-make-char-spec char))
519     (unless (or (characterp char) ; char
520                 (condition-case nil
521                     (setq char (find-char char-spec))
522                   (error nil)))
523       ;; define temporary character
524       ;;   Current implementation is dirty.
525       (setq temp-char (define-char (cons '(ideograph-daikanwa . 0)
526                                          char-spec)))
527       (remove-char-attribute temp-char 'ideograph-daikanwa)
528       (setq char temp-char))
529     (insert-char-attributes char
530                             readable
531                             (union (mapcar #'car char-spec)
532                                    required-features)
533                             nil 'for-sub-node)
534     (when temp-char
535       ;; undefine temporary character
536       ;;   Current implementation is dirty.
537       (setq char-spec (char-attribute-alist temp-char))
538       (while char-spec
539         (remove-char-attribute temp-char (car (car char-spec)))
540         (setq char-spec (cdr char-spec))))))
541
542 (defun char-db-insert-alist (alist &optional readable column)
543   (unless column
544     (setq column (current-column)))
545   (let ((line-breaking
546          (concat "\n" (make-string (1+ column) ?\ )))
547         name value
548         ret al ; cal
549         key
550         lbs cell rest separator)
551     (insert "(")
552     (while alist
553       (setq name (car (car alist))
554             value (cdr (car alist)))
555       (cond ((eq name 'char)
556              (insert "(char . ")
557              (if (setq ret (condition-case nil
558                                (find-char value)
559                              (error nil)))
560                  (progn
561                    (setq al nil
562                          ;; cal nil
563                          )
564                    (while value
565                      (setq key (car (car value)))
566                      ;; (if (find-charset key)
567                      ;;     (setq cal (cons key cal))
568                      (setq al (cons key al))
569                      ;; )
570                      (setq value (cdr value)))
571                    (insert-char-attributes ret
572                                            readable
573                                            (or al 'none) ; cal
574                                            nil 'for-sub-node))
575                (insert (prin1-to-string value)))
576              (insert ")")
577              (insert line-breaking))
578             ((consp value)
579              (insert (format "(%-18s " name))
580              (setq lbs (concat "\n" (make-string (current-column) ?\ )))
581              (while (consp value)
582                (setq cell (car value))
583                (if (and (consp cell)
584                         (consp (car cell))
585                         (setq ret (condition-case nil
586                                       (find-char cell)
587                                     (error nil)))
588                         )
589                    (progn
590                      (setq rest cell
591                            al nil
592                            ;; cal nil
593                            )
594                      (while rest
595                        (setq key (car (car rest)))
596                        ;; (if (find-charset key)
597                        ;;     (setq cal (cons key cal))
598                        (setq al (cons key al))
599                        ;; )
600                        (setq rest (cdr rest)))
601                      (if separator
602                          (insert lbs))
603                      (insert-char-attributes ret
604                                              readable
605                                              al ; cal
606                                              nil 'for-sub-node)
607                      (setq separator lbs))
608                  (if separator
609                      (insert separator))
610                  (insert (prin1-to-string cell))
611                  (setq separator " "))
612                (setq value (cdr value)))
613              (insert ")")
614              (insert line-breaking))
615             (t
616              (insert (format "(%-18s . %S)%s"
617                              name value
618                              line-breaking))))
619       (setq alist (cdr alist))))
620   (insert ")"))
621
622 (defun char-db-insert-char-reference (plist &optional readable column)
623   (unless column
624     (setq column (current-column)))
625   (let ((line-breaking
626          (concat "\n" (make-string (1+ column) ?\ )))
627         (separator "")
628         name value)
629     (insert "(")
630     (while plist
631       (setq name (pop plist))
632       (setq value (pop plist))
633       (cond ((eq name :char)
634              (insert separator)
635              (insert ":char\t")
636              (cond ((numberp value)
637                     (setq value (decode-char '=ucs value)))
638                    ;; ((consp value)
639                    ;;  (setq value (or (find-char value)
640                    ;;                  value)))
641                    )
642              (char-db-insert-char-spec value readable)
643              (insert line-breaking)
644              (setq separator ""))
645             ((eq name :radical)
646              (insert (format "%s%s\t%d ; %c%s"
647                              separator
648                              name value
649                              (ideographic-radical value)
650                              line-breaking))
651              (setq separator ""))
652             (t
653              (insert (format "%s%s\t%S" separator name value))
654              (setq separator line-breaking)))
655       ))
656   (insert ")"))
657
658 (defun char-db-decode-isolated-char (ccs code-point)
659   (let (ret)
660     (setq ret
661           (cond ((eq ccs 'arabic-iso8859-6)
662                  (decode-char ccs code-point))
663                 ;; ((eq ccs '=gt)
664                 ;;  (decode-builtin-char '==gt code-point))
665                 ((and (memq ccs '(=gt-pj-1
666                                   =gt-pj-2
667                                   =gt-pj-3
668                                   =gt-pj-4
669                                   =gt-pj-5
670                                   =gt-pj-6
671                                   =gt-pj-7
672                                   =gt-pj-8
673                                   =gt-pj-9
674                                   =gt-pj-10
675                                   =gt-pj-11))
676                       (setq ret (decode-char ccs code-point))
677                       (setq ret (encode-char ret '=gt 'defined-only)))
678                  (decode-builtin-char '=gt ret))
679                 (t
680                  (decode-builtin-char ccs code-point))))
681     (cond ((null ret)
682            (or (decode-char ccs code-point)
683                (define-char (list (cons ccs code-point)))))
684           ((and (<= 0 (char-int ret))
685                 (<= (char-int ret) #x1F))
686            (decode-char '=ucs (+ #x2400 (char-int ret))))
687           ((= (char-int ret) #x7F)
688            ?\u2421)
689           (t ret))))
690
691 (defvar char-db-convert-obsolete-format t)
692
693 (defun char-db-insert-ccs-feature (name value line-breaking)
694   (cond
695    ((integerp value)
696     (insert
697      (format
698       (cond
699        ((memq name '(=>iwds-1
700                      ==shinjigen
701                      =shinjigen
702                      =shinjigen@1ed ==shinjigen@1ed
703                      =shinjigen@rev ==shinjigen@rev
704                      =shinjigen/+p@rev ==shinjigen/+p@rev
705                      ===daikanwa/ho ==daikanwa/ho
706                      =daikanwa/ho =>>daikanwa/ho =>daikanwa/ho))
707         "(%-18s .  %04d)\t; %c")
708        ((eq name '=shinjigen@1ed/24pr)
709         "(%-18s . %04d)\t; %c")
710        ((or
711          (memq name
712                '(===daikanwa
713                  ==daikanwa =daikanwa =>>daikanwa =>daikanwa
714                  =daikanwa@rev1 =daikanwa@rev2
715                  =daikanwa/+p ==daikanwa/+p ===daikanwa/+p
716                  =>>daikanwa/+p
717                  =daikanwa/+2p =>>daikanwa/+2p
718                  =gt ==gt ===gt
719                  =>>gt =+>gt =>gt
720                  =gt-k ==gt-k ===gt-k
721                  =>>gt-k =>gt-k
722                  =adobe-japan1-0 ==adobe-japan1-0 ===adobe-japan1-0
723                  =adobe-japan1-1 ==adobe-japan1-1 ===adobe-japan1-1
724                  =adobe-japan1-2 ==adobe-japan1-2 ===adobe-japan1-2
725                  =adobe-japan1-3 ==adobe-japan1-3 ===adobe-japan1-3
726                  =adobe-japan1-4 ==adobe-japan1-4 ===adobe-japan1-4
727                  =adobe-japan1-5 ==adobe-japan1-5 ===adobe-japan1-5
728                  =adobe-japan1-6 ==adobe-japan1-6 ===adobe-japan1-6
729                  =>>adobe-japan1-0 =+>adobe-japan1-0
730                  =>>adobe-japan1-1 =+>adobe-japan1-1
731                  =>>adobe-japan1-2 =+>adobe-japan1-2
732                  =>>adobe-japan1-3 =+>adobe-japan1-3
733                  =>>adobe-japan1-4 =+>adobe-japan1-4
734                  =>>adobe-japan1-5 =+>adobe-japan1-5
735                  =>>adobe-japan1-6 =+>adobe-japan1-6
736                  =>cbeta =cbeta =>>cbeta ==cbeta ===cbeta
737                  =zinbun-oracle =>zinbun-oracle
738                  =daijiten ==daijiten ===daijiten ==>daijiten
739                  ===hng-jou ===hng-keg ===hng-dng ===hng-mam
740                  ===hng-drt ===hng-kgk ===hng-myz ===hng-kda
741                  ===hng-khi ===hng-khm ===hng-fhs ===hng-hok
742                  ===hng-kyd ===hng-sok
743                  ===hng-yhk ===hng-kak ===hng-kar ===hng-kae
744                  ===hng-sys ===hng-tsu ===hng-tzj
745                  ===hng-hos ===hng-nak ===hng-jhk
746                  ===hng-hod ===hng-gok ===hng-ink ===hng-nto
747                  ===hng-nkm ===hng-k24 ===hng-nkk
748                  ===hng-kcc ===hng-kcj ===hng-kbk ===hng-sik
749                  ===hng-skk ===hng-kyu ===hng-ksk ===hng-wan
750                  ===hng-okd ===hng-wad ===hng-kmi
751                  ===hng-zkd ===hng-doh ===hng-jyu
752                  ===hng-tzs ===hng-kss ===hng-kyo
753                  ===hng-smk
754                  =shuowen-jiguge ===shuowen-jiguge4 ===shuowen-jiguge5))
755          ;; (string-match "^=adobe-" (symbol-name name))
756          )
757         "(%-18s . %05d)\t; %c")
758        ((memq name '(=hanyo-denshi/ks
759                      ==hanyo-denshi/ks ===hanyo-denshi/ks
760                      =>>hanyo-denshi/ks
761                      =koseki ==koseki
762                      =mj ==mj ===mj =>>mj =>mj
763                      =zihai mojikyo))
764         "(%-18s . %06d)\t; %c")
765        ((memq name '(=hanyo-denshi/tk ==hanyo-denshi/tk))
766         "(%-18s . %08d)\t; %c")
767        ((>= (charset-dimension name) 2)
768         "(%-18s . #x%04X)\t; %c")
769        (t
770         "(%-18s . #x%02X)\t; %c"))
771       name
772       (if (= (charset-iso-graphic-plane name) 1)
773           (logior value
774                   (cond ((= (charset-dimension name) 1)
775                          #x80)
776                         ((= (charset-dimension name) 2)
777                          #x8080)
778                         ((= (charset-dimension name) 3)
779                          #x808080)
780                         (t 0)))
781         value)
782       (char-db-decode-isolated-char name value)))
783     (if (and (= (charset-chars name) 94)
784              (= (charset-dimension name) 2))
785         (insert (format " [%02d-%02d]"
786                         (- (lsh value -8) 32)
787                         (- (logand value 255) 32))))
788     )
789    (t
790     (insert (format "(%-18s . %s)" name value))
791     ))
792   (insert line-breaking))
793
794 (defun char-db-insert-relation-feature (char name value line-breaking
795                                              ccss readable)
796   (insert (format "(%-18s%s " name line-breaking))
797   (let ((lbs (concat "\n" (make-string (current-column) ?\ )))
798         separator cell sources required-features
799         ret)
800     (while (consp value)
801       (setq cell (car value))
802       (if (integerp cell)
803           (setq cell (decode-char '=ucs cell)))
804       (cond
805        ((eq name '->subsumptive)
806         (when (or (not (some (lambda (atr)
807                                (get-char-attribute cell atr))
808                              char-db-ignored-attributes))
809                   (some (lambda (ccs)
810                           (encode-char cell ccs 'defined-only))
811                         ccss))
812           (if separator
813               (insert lbs))
814           (let ((char-db-ignored-attributes
815                  (cons '<-subsumptive
816                        char-db-ignored-attributes)))
817             (insert-char-attributes cell readable nil nil 'for-sub-node))
818           (setq separator lbs))
819         )
820        ((characterp cell)
821         (setq sources
822               (get-char-attribute
823                char (intern (format "%s*sources" name))))
824         (setq required-features nil)
825         (dolist (source sources)
826           (cond
827            ((memq source '(JP
828                            JP/Jouyou
829                            shinjigen shinjigen@1ed shinjigen@rev))
830             (setq required-features
831                   (union required-features
832                          '(=jis-x0208
833                            =jis-x0208@1990
834                            =jis-x0213-1@2000
835                            =jis-x0213-1@2004
836                            =jis-x0213-2
837                            =jis-x0212
838                            =jis-x0208@1983
839                            =jis-x0208@1978
840                            =shinjigen
841                            =shinjigen@1ed
842                            =shinjigen@rev
843                            =shinjigen/+p@rev))))
844            ((eq source 'CN)
845             (setq required-features
846                   (union required-features
847                          '(=gb2312
848                            =gb12345
849                            =iso-ir165)))))
850           (cond
851            ((find-charset (setq ret (intern (format "=%s" source))))
852             (setq required-features
853                   (cons ret required-features)))
854            (t (setq required-features
855                     (cons source required-features)))))
856         (cond ((string-match "@JP" (symbol-name name))
857                (setq required-features
858                      (union required-features
859                             '(=jis-x0208
860                               =jis-x0208@1990
861                               =jis-x0213-1-2000
862                               =jis-x0213-2-2000
863                               =jis-x0212
864                               =jis-x0208@1983
865                               =jis-x0208@1978))))
866               ((string-match "@CN" (symbol-name name))
867                (setq required-features
868                      (union required-features
869                             '(=gb2312
870                               =gb12345
871                               =iso-ir165)))))
872         (if separator
873             (insert lbs))
874         (if readable
875             (insert (format "%S" cell))
876           (char-db-insert-char-spec cell readable
877                                     nil
878                                     required-features))
879         (setq separator lbs))
880        ((consp cell)
881         (if separator
882             (insert lbs))
883         (if (consp (car cell))
884             (char-db-insert-char-spec cell readable)
885           (char-db-insert-char-reference cell readable))
886         (setq separator lbs))
887        (t
888         (if separator
889             (insert separator))
890         (insert (prin1-to-string cell))
891         (setq separator " ")))
892       (setq value (cdr value)))
893     (insert ")")
894     (insert line-breaking)))
895
896 (defun insert-char-attributes (char &optional readable attributes column
897                                     for-sub-node)
898   (unless column
899     (setq column (current-column)))
900   (let (name value ; has-long-ccs-name
901         rest
902         radical strokes
903         (line-breaking
904          (concat "\n" (make-string (1+ column) ?\ )))
905         lbs cell separator ret
906         key al cal
907         dest-ccss ; sources required-features
908         ccss)
909     (let (atr-d)
910       (setq attributes
911             (sort (if attributes
912                       (if (consp attributes)
913                           (progn
914                             (dolist (name attributes)
915                               (unless (memq name char-db-ignored-attributes)
916                                 (if (find-charset name)
917                                     (push name ccss))
918                                 (push name atr-d)))
919                             atr-d))
920                     (dolist (name (char-attribute-list))
921                       (unless (memq name char-db-ignored-attributes)
922                         (if (find-charset name)
923                             (push name ccss))
924                         (push name atr-d)))
925                     atr-d)
926                   #'char-attribute-name<)))
927     (insert "(")
928     (when (memq '<-subsumptive attributes)
929       (when (or readable (not for-sub-node))
930         (when (setq value (get-char-attribute char '<-subsumptive))
931           (char-db-insert-relation-feature char '<-subsumptive value
932                                            line-breaking
933                                            ccss readable)))
934       (setq attributes (delq '<-subsumptive attributes)))
935     (when (and (memq '<-denotational attributes)
936                (setq value (get-char-attribute char '<-denotational)))
937       (char-db-insert-relation-feature char '<-denotational value
938                                        line-breaking
939                                        ccss readable)
940       (setq attributes (delq '<-denotational attributes)))
941     (when (and (memq '<-denotational@component attributes)
942                (setq value (get-char-attribute char '<-denotational@component)))
943       (char-db-insert-relation-feature char '<-denotational@component value
944                                        line-breaking
945                                        ccss readable)
946       (setq attributes (delq '<-denotational@component attributes)))
947     (when (and (memq '<-denotational@usage attributes)
948                (setq value (get-char-attribute char '<-denotational@usage)))
949       (char-db-insert-relation-feature char '<-denotational@usage value
950                                        line-breaking
951                                        ccss readable)
952       (setq attributes (delq '<-denotational@usage attributes)))
953     (when (and (memq 'name attributes)
954                (setq value (get-char-attribute char 'name)))
955       (insert (format
956                (if (> (+ (current-column) (length value)) 48)
957                    "(name . %S)%s"
958                  "(name               . %S)%s")
959                value line-breaking))
960       (setq attributes (delq 'name attributes))
961       )
962     (when (and (memq 'name* attributes)
963                (setq value (get-char-attribute char 'name*)))
964       (insert (format
965                (if (> (+ (current-column) (length value)) 48)
966                    "(name* . %S)%s"
967                  "(name*              . %S)%s")
968                value line-breaking))
969       (setq attributes (delq 'name* attributes))
970       )
971     (when (and (memq 'script attributes)
972                (setq value (get-char-attribute char 'script)))
973       (insert (format "(script\t\t%s)%s"
974                       (mapconcat (function prin1-to-string)
975                                  value " ")
976                       line-breaking))
977       (setq attributes (delq 'script attributes))
978       )
979     (dolist (name '(=>ucs =>ucs*))
980       (when (and (memq name attributes)
981                  (setq value (get-char-attribute char name)))
982         (insert (format "(%-18s . #x%04X)\t; %c%s"
983                         name value (decode-char '=ucs value)
984                         line-breaking))
985         (setq attributes (delq name attributes))))
986     (dolist (name '(=>ucs@gb =>ucs@big5))
987       (when (and (memq name attributes)
988                  (setq value (get-char-attribute char name)))
989         (insert (format "(%-18s . #x%04X)\t; %c%s"
990                         name value
991                         (decode-char (intern
992                                       (concat "="
993                                               (substring
994                                                (symbol-name name) 2)))
995                                      value)
996                         line-breaking))
997         (setq attributes (delq name attributes))
998         ))
999     ;; (dolist (name '(=>daikanwa))
1000     ;;   (when (and (memq name attributes)
1001     ;;              (setq value (get-char-attribute char name)))
1002     ;;     (insert
1003     ;;      (if (integerp value)
1004     ;;          (format "(%-18s . %05d)\t; %c%s"
1005     ;;                  name value (decode-char '=daikanwa value)
1006     ;;                  line-breaking)
1007     ;;        (format "(%-18s %s)\t; %c%s"
1008     ;;                name
1009     ;;                (mapconcat (function prin1-to-string)
1010     ;;                           value " ")
1011     ;;                (char-representative-of-daikanwa char)
1012     ;;                line-breaking)))
1013     ;;     (setq attributes (delq name attributes))))
1014     (when (and (memq 'general-category attributes)
1015                (setq value (get-char-attribute char 'general-category)))
1016       (insert (format
1017                "(general-category\t%s) ; %s%s"
1018                (mapconcat (lambda (cell)
1019                             (format "%S" cell))
1020                           value " ")
1021                (cond ((rassoc value unidata-normative-category-alist)
1022                       "Normative Category")
1023                      ((rassoc value unidata-informative-category-alist)
1024                       "Informative Category")
1025                      (t
1026                       "Unknown Category"))
1027                line-breaking))
1028       (setq attributes (delq 'general-category attributes))
1029       )
1030     (when (and (memq 'bidi-category attributes)
1031                (setq value (get-char-attribute char 'bidi-category)))
1032       (insert (format "(bidi-category\t. %S)%s"
1033                       value
1034                       line-breaking))
1035       (setq attributes (delq 'bidi-category attributes))
1036       )
1037     (unless (or (not (memq 'mirrored attributes))
1038                 (eq (setq value (get-char-attribute char 'mirrored 'empty))
1039                     'empty))
1040       (insert (format "(mirrored\t\t. %S)%s"
1041                       value
1042                       line-breaking))
1043       (setq attributes (delq 'mirrored attributes))
1044       )
1045     (cond
1046      ((and (memq 'decimal-digit-value attributes)
1047            (setq value (get-char-attribute char 'decimal-digit-value)))
1048       (insert (format "(decimal-digit-value . %S)%s"
1049                       value
1050                       line-breaking))
1051       (setq attributes (delq 'decimal-digit-value attributes))
1052       (when (and (memq 'digit-value attributes)
1053                  (setq value (get-char-attribute char 'digit-value)))
1054         (insert (format "(digit-value\t . %S)%s"
1055                         value
1056                         line-breaking))
1057         (setq attributes (delq 'digit-value attributes))
1058         )
1059       (when (and (memq 'numeric-value attributes)
1060                  (setq value (get-char-attribute char 'numeric-value)))
1061         (insert (format "(numeric-value\t . %S)%s"
1062                         value
1063                         line-breaking))
1064         (setq attributes (delq 'numeric-value attributes))
1065         )
1066       )
1067      (t
1068       (when (and (memq 'digit-value attributes)
1069                  (setq value (get-char-attribute char 'digit-value)))
1070         (insert (format "(digit-value\t. %S)%s"
1071                         value
1072                         line-breaking))
1073         (setq attributes (delq 'digit-value attributes))
1074         )
1075       (when (and (memq 'numeric-value attributes)
1076                  (setq value (get-char-attribute char 'numeric-value)))
1077         (insert (format "(numeric-value\t. %S)%s"
1078                         value
1079                         line-breaking))
1080         (setq attributes (delq 'numeric-value attributes))
1081         )))
1082     (when (and (memq 'iso-10646-comment attributes)
1083                (setq value (get-char-attribute char 'iso-10646-comment)))
1084       (insert (format "(iso-10646-comment\t. %S)%s"
1085                       value
1086                       line-breaking))
1087       (setq attributes (delq 'iso-10646-comment attributes))
1088       )
1089     (when (and (memq 'morohashi-daikanwa attributes)
1090                (setq value (get-char-attribute char 'morohashi-daikanwa)))
1091       (insert (format "(morohashi-daikanwa\t%s)%s"
1092                       (mapconcat (function prin1-to-string) value " ")
1093                       line-breaking))
1094       (setq attributes (delq 'morohashi-daikanwa attributes))
1095       )
1096     (setq radical nil
1097           strokes nil)
1098     (when (and (memq 'ideographic-radical attributes)
1099                (setq value (get-char-attribute char 'ideographic-radical)))
1100       (setq radical value)
1101       (insert (format "(ideographic-radical . %S)\t; %c%s"
1102                       radical
1103                       (ideographic-radical radical)
1104                       line-breaking))
1105       (setq attributes (delq 'ideographic-radical attributes))
1106       )
1107     (when (and (memq 'shuowen-radical attributes)
1108                (setq value (get-char-attribute char 'shuowen-radical)))
1109       (insert (format "(shuowen-radical\t. %S)\t; %c%s"
1110                       value
1111                       (shuowen-radical value)
1112                       line-breaking))
1113       (setq attributes (delq 'shuowen-radical attributes))
1114       )
1115     (let (key)
1116       (dolist (domain
1117                (append
1118                 char-db-feature-domains
1119                 (let (dest domain)
1120                   (dolist (feature (char-attribute-list))
1121                     (setq feature (symbol-name feature))
1122                     (when (string-match
1123                            "\\(radical\\|strokes\\)@\\([^@*]+\\)\\(\\*\\|$\\)"
1124                            feature)
1125                       (setq domain (intern (match-string 2 feature)))
1126                      (unless (memq domain dest)
1127                        (setq dest (cons domain dest)))))
1128                   (sort dest #'string<))))
1129         (setq key (intern (format "%s@%s" 'ideographic-radical domain)))
1130         (when (and (memq key attributes)
1131                    (setq value (get-char-attribute char key)))
1132           (setq radical value)
1133           (insert (format "(%s . %S)\t; %c%s"
1134                           key
1135                           radical
1136                           (ideographic-radical radical)
1137                           line-breaking))
1138           (setq attributes (delq key attributes))
1139           )
1140         (setq key (intern (format "%s@%s" 'ideographic-strokes domain)))
1141         (when (and (memq key attributes)
1142                    (setq value (get-char-attribute char key)))
1143           (setq strokes value)
1144           (insert (format "(%s . %S)%s"
1145                           key
1146                           strokes
1147                           line-breaking))
1148           (setq attributes (delq key attributes))
1149           )
1150         (setq key (intern (format "%s@%s" 'total-strokes domain)))
1151         (when (and (memq key attributes)
1152                    (setq value (get-char-attribute char key)))
1153           (insert (format "(%s       . %S)%s"
1154                           key
1155                           value
1156                           line-breaking))
1157           (setq attributes (delq key attributes))
1158           )
1159         (dolist (feature '(ideographic-radical
1160                            ideographic-strokes
1161                            total-strokes))
1162           (setq key (intern (format "%s@%s*sources" feature domain)))
1163           (when (and (memq key attributes)
1164                      (setq value (get-char-attribute char key)))
1165             (insert (format "(%s%s" key line-breaking))
1166             (dolist (cell value)
1167               (insert (format " %s" cell)))
1168             (insert ")")
1169             (insert line-breaking)
1170             (setq attributes (delq key attributes))
1171             ))
1172         ))
1173     (when (and (memq 'ideographic-strokes attributes)
1174                (setq value (get-char-attribute char 'ideographic-strokes)))
1175       (setq strokes value)
1176       (insert (format "(ideographic-strokes . %S)%s"
1177                       strokes
1178                       line-breaking))
1179       (setq attributes (delq 'ideographic-strokes attributes))
1180       )
1181     (when (and (memq 'kangxi-radical attributes)
1182                (setq value (get-char-attribute char 'kangxi-radical)))
1183       (unless (eq value radical)
1184         (insert (format "(kangxi-radical\t . %S)\t; %c%s"
1185                         value
1186                         (ideographic-radical value)
1187                         line-breaking))
1188         (or radical
1189             (setq radical value)))
1190       (setq attributes (delq 'kangxi-radical attributes))
1191       )
1192     (when (and (memq 'kangxi-strokes attributes)
1193                (setq value (get-char-attribute char 'kangxi-strokes)))
1194       (unless (eq value strokes)
1195         (insert (format "(kangxi-strokes\t . %S)%s"
1196                         value
1197                         line-breaking))
1198         (or strokes
1199             (setq strokes value)))
1200       (setq attributes (delq 'kangxi-strokes attributes))
1201       )
1202     ;; (when (and (memq 'japanese-radical attributes)
1203     ;;            (setq value (get-char-attribute char 'japanese-radical)))
1204     ;;   (unless (eq value radical)
1205     ;;     (insert (format "(japanese-radical\t . %S)\t; %c%s"
1206     ;;                     value
1207     ;;                     (ideographic-radical value)
1208     ;;                     line-breaking))
1209     ;;     (or radical
1210     ;;         (setq radical value)))
1211     ;;   (setq attributes (delq 'japanese-radical attributes))
1212     ;;   )
1213     (when (and (memq 'japanese-strokes attributes)
1214                (setq value (get-char-attribute char 'japanese-strokes)))
1215       (unless (eq value strokes)
1216         (insert (format "(japanese-strokes\t . %S)%s"
1217                         value
1218                         line-breaking))
1219         (or strokes
1220             (setq strokes value)))
1221       (setq attributes (delq 'japanese-strokes attributes))
1222       )
1223     (when (and (memq 'cns-radical attributes)
1224                (setq value (get-char-attribute char 'cns-radical)))
1225       (insert (format "(cns-radical\t . %S)\t; %c%s"
1226                       value
1227                       (ideographic-radical value)
1228                       line-breaking))
1229       (setq attributes (delq 'cns-radical attributes))
1230       )
1231     (when (and (memq 'cns-strokes attributes)
1232                (setq value (get-char-attribute char 'cns-strokes)))
1233       (unless (eq value strokes)
1234         (insert (format "(cns-strokes\t . %S)%s"
1235                         value
1236                         line-breaking))
1237         (or strokes
1238             (setq strokes value)))
1239       (setq attributes (delq 'cns-strokes attributes))
1240       )
1241     ;; (when (and (memq 'ideographic- attributes)
1242     ;;            (setq value (get-char-attribute char 'ideographic-)))
1243     ;;   (insert "(ideographic-       ")
1244     ;;   (setq lbs (concat "\n" (make-string (current-column) ?\ ))
1245     ;;         separator nil)
1246     ;;   (while (consp value)
1247     ;;     (setq cell (car value))
1248     ;;     (if (integerp cell)
1249     ;;         (setq cell (decode-char '=ucs cell)))
1250     ;;     (cond ((characterp cell)
1251     ;;            (if separator
1252     ;;                (insert lbs))
1253     ;;            (if readable
1254     ;;                (insert (format "%S" cell))
1255     ;;              (char-db-insert-char-spec cell readable))
1256     ;;            (setq separator lbs))
1257     ;;           ((consp cell)
1258     ;;            (if separator
1259     ;;                (insert lbs))
1260     ;;            (if (consp (car cell))
1261     ;;                (char-db-insert-char-spec cell readable)
1262     ;;              (char-db-insert-char-reference cell readable))
1263     ;;            (setq separator lbs))
1264     ;;           (t
1265     ;;            (if separator
1266     ;;                (insert separator))
1267     ;;            (insert (prin1-to-string cell))
1268     ;;            (setq separator " ")))
1269     ;;     (setq value (cdr value)))
1270     ;;   (insert ")")
1271     ;;   (insert line-breaking)
1272     ;;   (setq attributes (delq 'ideographic- attributes)))
1273     (when (and (memq 'total-strokes attributes)
1274                (setq value (get-char-attribute char 'total-strokes)))
1275       (insert (format "(total-strokes       . %S)%s"
1276                       value
1277                       line-breaking))
1278       (setq attributes (delq 'total-strokes attributes))
1279       )
1280     ;; (when (and (memq '->ideograph attributes)
1281     ;;            (setq value (get-char-attribute char '->ideograph)))
1282     ;;   (insert (format "(->ideograph\t%s)%s"
1283     ;;                   (mapconcat (lambda (code)
1284     ;;                                (cond ((symbolp code)
1285     ;;                                       (symbol-name code))
1286     ;;                                      ((integerp code)
1287     ;;                                       (format "#x%04X" code))
1288     ;;                                      (t
1289     ;;                                       (format "%s %S"
1290     ;;                                               line-breaking code))))
1291     ;;                              value " ")
1292     ;;                   line-breaking))
1293     ;;   (setq attributes (delq '->ideograph attributes))
1294     ;;   )
1295     ;; (when (and (memq '->decomposition attributes)
1296     ;;            (setq value (get-char-attribute char '->decomposition)))
1297     ;;   (insert (format "(->decomposition\t%s)%s"
1298     ;;                   (mapconcat (lambda (code)
1299     ;;                                (cond ((symbolp code)
1300     ;;                                       (symbol-name code))
1301     ;;                                      ((characterp code)
1302     ;;                                       (if readable
1303     ;;                                           (format "%S" code)
1304     ;;                                         (format "#x%04X"
1305     ;;                                                 (char-int code))
1306     ;;                                         ))
1307     ;;                                      ((integerp code)
1308     ;;                                       (format "#x%04X" code))
1309     ;;                                      (t
1310     ;;                                       (format "%s%S" line-breaking code))))
1311     ;;                              value " ")
1312     ;;                   line-breaking))
1313     ;;   (setq attributes (delq '->decomposition attributes))
1314     ;;   )
1315     (if (equal (get-char-attribute char '->titlecase)
1316                (get-char-attribute char '->uppercase))
1317         (setq attributes (delq '->titlecase attributes)))
1318     (when (and (memq '->mojikyo attributes)
1319                (setq value (get-char-attribute char '->mojikyo)))
1320       (insert (format "(->mojikyo\t\t. %06d)\t; %c%s"
1321                       value (decode-char 'mojikyo value)
1322                       line-breaking))
1323       (setq attributes (delq '->mojikyo attributes))
1324       )
1325     (unless readable
1326       (dolist (ignored '(composition
1327                          ->denotational <-subsumptive ->ucs-unified
1328                          ;; ->ideographic-component-forms
1329                          ))
1330         (setq attributes (delq ignored attributes))))
1331     (while attributes
1332       (setq name (car attributes))
1333       (unless (eq (setq value (get-char-attribute char name 'value-is-empty))
1334                   'value-is-empty)
1335         (cond ((setq ret (find-charset name))
1336                (setq name (charset-name ret))
1337                (when (not (memq name dest-ccss))
1338                  (setq dest-ccss (cons name dest-ccss))
1339                  (char-db-insert-ccs-feature name value line-breaking))
1340                )
1341               ((string-match "^=>ucs@" (symbol-name name))
1342                (insert (format "(%-18s . #x%04X)\t; %c%s"
1343                                name value (decode-char '=ucs value)
1344                                line-breaking))
1345                )
1346               ((eq name 'jisx0208-1978/4X)
1347                (insert (format "(%-18s . #x%04X)%s"
1348                                name value
1349                                line-breaking))
1350                )
1351               ((and
1352                 (not readable)
1353                 (not (eq name '->subsumptive))
1354                 (not (eq name '->uppercase))
1355                 (not (eq name '->lowercase))
1356                 (not (eq name '->titlecase))
1357                 (not (eq name '->canonical))
1358                 (not (eq name '->Bopomofo))
1359                 (not (eq name '->mistakable))
1360                 (not (eq name '->ideographic-variants))
1361                 (null (get-char-attribute
1362                        char (intern (format "%s*sources" name))))
1363                 (not (string-match "\\*sources$" (symbol-name name)))
1364                 (null (get-char-attribute
1365                        char (intern (format "%s*note" name))))
1366                 (not (string-match "\\*note$" (symbol-name name)))
1367                 (or (eq name '<-identical)
1368                     (eq name '<-uppercase)
1369                     (eq name '<-lowercase)
1370                     (eq name '<-titlecase)
1371                     (eq name '<-canonical)
1372                     (eq name '<-ideographic-variants)
1373                     ;; (eq name '<-synonyms)
1374                     (string-match "^<-synonyms" (symbol-name name))
1375                     (eq name '<-mistakable)
1376                     (when (string-match "^->" (symbol-name name))
1377                       (cond
1378                        ((string-match "^->fullwidth" (symbol-name name))
1379                         (not (and (consp value)
1380                                   (characterp (car value))
1381                                   (encode-char
1382                                    (car value) '=ucs 'defined-only)))
1383                         )
1384                        (t)))
1385                     ))
1386                )
1387               ((or (eq name 'ideographic-structure)
1388                    (eq name 'ideographic-combination)
1389                    ;; (eq name 'ideographic-)
1390                    (eq name '=decomposition)
1391                    (char-feature-base-name= '=decomposition name)
1392                    (char-feature-base-name= '=>decomposition name)
1393                    ;; (string-match "^=>*decomposition\\(@[^*]+\\)?$"
1394                    ;;               (symbol-name name))
1395                    (string-match "^\\(->\\|<-\\)[^*]*$" (symbol-name name))
1396                    (string-match "^\\(->\\|<-\\)[^*]*\\*sources$"
1397                                  (symbol-name name))
1398                    )
1399                (char-db-insert-relation-feature char name value
1400                                                 line-breaking
1401                                                 ccss readable))
1402               ;; ((memq name '(ideograph=
1403               ;;               original-ideograph-of
1404               ;;               ancient-ideograph-of
1405               ;;               vulgar-ideograph-of
1406               ;;               wrong-ideograph-of
1407               ;;               ;; simplified-ideograph-of
1408               ;;               ideographic-variants
1409               ;;               ;; ideographic-different-form-of
1410               ;;               ))
1411               ;;  (insert (format "(%-18s%s " name line-breaking))
1412               ;;  (setq lbs (concat "\n" (make-string (current-column) ?\ ))
1413               ;;        separator nil)
1414               ;;  (while (consp value)
1415               ;;    (setq cell (car value))
1416               ;;    (if (and (consp cell)
1417               ;;             (consp (car cell)))
1418               ;;        (progn
1419               ;;          (if separator
1420               ;;              (insert lbs))
1421               ;;          (char-db-insert-alist cell readable)
1422               ;;          (setq separator lbs))
1423               ;;      (if separator
1424               ;;          (insert separator))
1425               ;;      (insert (prin1-to-string cell))
1426               ;;      (setq separator " "))
1427               ;;    (setq value (cdr value)))
1428               ;;  (insert ")")
1429               ;;  (insert line-breaking))
1430               ((consp value)
1431                (insert (format "(%-18s " name))
1432                (setq lbs (concat "\n" (make-string (current-column) ?\ ))
1433                      separator nil)
1434                (while (consp value)
1435                  (setq cell (car value))
1436                  (if (and (consp cell)
1437                           (consp (car cell))
1438                           (setq ret (condition-case nil
1439                                         (find-char cell)
1440                                       (error nil))))
1441                      (progn
1442                        (setq rest cell
1443                              al nil
1444                              cal nil)
1445                        (while rest
1446                          (setq key (car (car rest)))
1447                          (if (find-charset key)
1448                              (setq cal (cons key cal))
1449                            (setq al (cons key al)))
1450                          (setq rest (cdr rest)))
1451                        (if separator
1452                            (insert lbs))
1453                        (insert-char-attributes ret
1454                                                readable
1455                                                al ; cal
1456                                                nil 'for-sub-node)
1457                        (setq separator lbs))
1458                    (setq ret (prin1-to-string cell))
1459                    (if separator
1460                        (if (< (+ (current-column)
1461                                  (length ret)
1462                                  (length separator))
1463                               76)
1464                            (insert separator)
1465                          (insert lbs)))
1466                    (insert ret)
1467                    (setq separator " "))
1468                  (setq value (cdr value)))
1469                (insert ")")
1470                (insert line-breaking))
1471               (t
1472                (insert (format "(%-18s" name))
1473                (setq ret (prin1-to-string value))
1474                (unless (< (+ (current-column)
1475                              (length ret)
1476                              3)
1477                           76)
1478                  (insert line-breaking))
1479                (insert " . " ret ")" line-breaking)
1480                ;; (insert (format "(%-18s . %S)%s"
1481                ;;                 name value
1482                ;;                 line-breaking))
1483                )
1484               ))
1485       (setq attributes (cdr attributes)))
1486     (insert ")")))
1487
1488 (defun insert-char-data (char &optional readable
1489                               attributes)
1490   (save-restriction
1491     (narrow-to-region (point)(point))
1492     (insert "(define-char
1493   '")
1494     (insert-char-attributes char readable attributes)
1495     (insert ")\n")
1496     (goto-char (point-min))
1497     (while (re-search-forward "[ \t]+$" nil t)
1498       (replace-match ""))
1499     ;; from tabify.
1500     (goto-char (point-min))
1501     (while (re-search-forward "[ \t][ \t][ \t]*" nil t)
1502       (let ((column (current-column))
1503             (indent-tabs-mode t))
1504         (delete-region (match-beginning 0) (point))
1505         (indent-to column)))
1506     (goto-char (point-max))
1507     ;; (tabify (point-min)(point-max))
1508     ))
1509
1510 (defun insert-char-data-with-variant (char &optional printable
1511                                            no-ucs-unified
1512                                            script excluded-script)
1513   (insert-char-data char printable)
1514   (let ((variants (char-variants char))
1515         rest
1516         variant vs ret)
1517     (setq variants (sort variants #'<))
1518     (setq rest variants)
1519     (setq variants (cons char variants))
1520     (while rest
1521       (setq variant (car rest))
1522       (unless (get-char-attribute variant '<-subsumptive)
1523         (if (and (or (null script)
1524                      (null (setq vs (get-char-attribute variant 'script)))
1525                      (memq script vs))
1526                  (or (null excluded-script)
1527                      (null (setq vs (get-char-attribute variant 'script)))
1528                      (not (memq excluded-script vs))))
1529             (unless (and no-ucs-unified (get-char-attribute variant '=ucs))
1530               (insert-char-data variant printable)
1531               (if (setq ret (char-variants variant))
1532                   (while ret
1533                     (or (memq (car ret) variants)
1534                         ;; (get-char-attribute (car ret) '<-subsumptive)
1535                         (setq rest (nconc rest (list (car ret)))))
1536                     (setq ret (cdr ret)))))))
1537       (setq rest (cdr rest)))))
1538
1539 (defun insert-char-range-data (min max &optional script excluded-script)
1540   (let ((code min)
1541         char)
1542     (while (<= code max)
1543       (setq char (decode-char '=ucs code))
1544       (if (encode-char char '=ucs 'defined-only)
1545           (insert-char-data-with-variant char nil 'no-ucs-unified
1546                                          script excluded-script))
1547       (setq code (1+ code)))))
1548
1549 (defun write-char-range-data-to-file (min max file
1550                                           &optional script excluded-script)
1551   (let ((coding-system-for-write char-db-file-coding-system))
1552     (with-temp-buffer
1553       (insert (format ";; -*- coding: %s -*-\n"
1554                       char-db-file-coding-system))
1555       (insert-char-range-data min max script excluded-script)
1556       (write-region (point-min)(point-max) file))))
1557
1558 (defvar what-character-original-window-configuration)
1559
1560 ;;;###autoload
1561 (defun what-char-definition (char)
1562   (interactive (list (char-after)))
1563   (let ((buf (get-buffer-create "*Character Description*"))
1564         (the-buf (current-buffer))
1565         (win-conf (current-window-configuration)))
1566     (pop-to-buffer buf)
1567     (make-local-variable 'what-character-original-window-configuration)
1568     (setq what-character-original-window-configuration win-conf)
1569     (setq buffer-read-only nil)
1570     (erase-buffer)
1571     (condition-case err
1572         (progn
1573           (insert-char-data-with-variant char 'printable)
1574           (unless (char-attribute-alist char)
1575             (insert (format ";; = %c\n"
1576                             (let* ((rest (split-char char))
1577                                    (ccs (pop rest))
1578                                    (code (pop rest)))
1579                               (while rest
1580                                 (setq code (logior (lsh code 8)
1581                                                    (pop rest))))
1582                               (decode-char ccs code)))))
1583           ;; (char-db-update-comment)
1584           (set-buffer-modified-p nil)
1585           (view-mode the-buf (lambda (buf)
1586                                (set-window-configuration
1587                                 what-character-original-window-configuration)
1588                                ))
1589           (goto-char (point-min)))
1590       (error (progn
1591                (set-window-configuration
1592                 what-character-original-window-configuration)
1593                (signal (car err) (cdr err)))))))
1594
1595
1596 ;;; @ end
1597 ;;;
1598
1599 (provide 'char-db-util)
1600
1601 ;;; char-db-util.el ends here