(U+5B69): Add `<-denotational@usage' for BUCS+5B69; add
[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,
5 ;;   2020, 2021, 2022, 2023 MORIOKA Tomohiko.
6
7 ;; Author: MORIOKA Tomohiko <tomo@kanji.zinbun.kyoto-u.ac.jp>
8 ;; Keywords: CHISE, Character Database, ISO/IEC 10646, UCS, Unicode, MULE.
9
10 ;; This file is part of XEmacs CHISE.
11
12 ;; XEmacs CHISE is free software; you can redistribute it and/or
13 ;; modify it under the terms of the GNU General Public License as
14 ;; published by the Free Software Foundation; either version 2, or (at
15 ;; your option) any later version.
16
17 ;; XEmacs CHISE is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 ;; General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with XEmacs CHISE; see the file COPYING.  If not, write to
24 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;; Boston, MA 02111-1307, USA.
26
27 ;;; Code:
28
29 (require 'chise-subr)
30 (require 'ideograph-subr)
31
32 (defconst unidata-normative-category-alist
33   '(("Lu" letter        uppercase)
34     ("Ll" letter        lowercase)
35     ("Lt" letter        titlecase)
36     ("Mn" mark          non-spacing)
37     ("Mc" mark          spacing-combining)
38     ("Me" mark          enclosing)
39     ("Nd" number        decimal-digit)
40     ("Nl" number        letter)
41     ("No" number        other)
42     ("Zs" separator     space)
43     ("Zl" separator     line)
44     ("Zp" separator     paragraph)
45     ("Cc" other         control)
46     ("Cf" other         format)
47     ("Cs" other         surrogate)
48     ("Co" other         private-use)
49     ("Cn" other         not-assigned)))
50
51 (defconst unidata-informative-category-alist
52   '(("Lm" letter        modifier)
53     ("Lo" letter        other)
54     ("Pc" punctuation   connector)
55     ("Pd" punctuation   dash)
56     ("Ps" punctuation   open)
57     ("Pe" punctuation   close)
58     ("Pi" punctuation   initial-quote)
59     ("Pf" punctuation   final-quote)
60     ("Po" punctuation   other)
61     ("Sm" symbol        math)
62     ("Sc" symbol        currency)
63     ("Sk" symbol        modifier)
64     ("So" symbol        other)
65     ))
66
67 (defconst shuowen-radicals
68   [?一 ?上 ?示 ?三 ?王 ?玉 ?玨 ?气 ?士 ?丨 ; 010
69    ?屮 ?艸 ?蓐 ?茻 ?小 ?八 ?釆 ?半 ?牛 ?犛 ; 020
70    ?告 ?口 ?凵 ?吅 ?哭 ?走 ?止 ?癶 ?步 ?此 ; 030
71    ?正 ?是 ?辵 ?彳 ?廴 ?㢟 ?行 ?齒 ?牙 ?足 ; 040
72    ?疋 ?品 ?龠 ?冊 ?㗊 ?舌 ?干 ?𧮫 ?只 ?㕯 ; 050
73    ?句 ?丩 ?古 ?十 ?卅 ?言 ?誩 ?音 ?䇂 ?丵 ; 060
74    ?菐 ?𠬞 ?𠬜 ?共 ?異 ?舁 ?𦥑 ?䢅 ?爨 ?革 ; 070
75    ?鬲 ?䰜 ?爪 ?𠃨 ?鬥 ?又 ?𠂇 ?史 ?支 ?𦘒 ; 080
76    ?聿 ?畫 ?隶 ?臤 ?臣 ?殳 ?殺 ?𠘧 ?寸 ?皮 ; 090
77    ?㼱 ?攴 ?敎 ?卜 ?用 ?爻 ?㸚 ?𥄎 ?目 ?䀠 ; 100
78    ?眉 ?盾 ?自 ?白 ?鼻 ?皕 ?習 ?羽 ?隹 ?奞 ; 110
79    ?雈 ?𦫳 ?𥄕 ?羊 ?羴 ?瞿 ?雔 ?雥 ?鳥 ?烏 ; 120
80    ?𠦒 ?冓 ?幺 ?𢆶 ?叀 ?玄 ?予 ?放 ?𠬪 ?𣦼 ; 130
81    ?歺 ?死 ?冎 ?骨 ?肉 ?筋 ?刀 ?刃 ?㓞 ?丯 ; 140
82    ?耒 ?角 ?竹 ?箕 ?丌 ?左 ?工 ?㠭 ?巫 ?甘 ; 150
83    ?曰 ?乃 ?丂 ?可 ?兮 ?号 ?亏 ?旨 ?喜 ?壴 ; 160
84 ;  ?旨 ?曰 ?乃 ?丂 ?可 ?兮 ?号 ?亏 ?喜 ?壴 ; 160
85    ?鼓 ?豈 ?豆 ?豊 ?豐 ?䖒 ?虍 ?虎 ?虤 ?皿 ; 170
86    ?𠙴 ?去 ?血 ?丶 ?丹 ?青 ?井 ?皀 ?鬯 ?食 ; 180
87    ?亼 ?會 ?倉 ?入 ?缶 ?矢 ?高 ?冂 ?𩫏 ?京 ; 190
88    ?亯 ?𣆪 ?畗 ?㐭 ?嗇 ?來 ?麥 ?夊 ?舛 ?䑞 ; 200
89    ?韋 ?弟 ?夂 ?久 ?桀 ?木 ?東 ?林 ?才 ?叒 ; 210
90    ?之 ?帀 ?出 ?𣎵 ?生 ?乇 ?𠂹 ?𠌶 ?華 ?𥝌 ; 220
91    ?稽 ?巢 ?桼 ?束 ?㯻 ?囗 ?員 ?貝 ?邑 ?𨛜 ; 230
92    ?日 ?旦 ?倝 ?㫃 ?冥 ?晶 ?月 ?有 ?明 ?囧 ; 240
93    ?夕 ?多 ?毌 ?𢎘 ?𣐺 ?卣 ?齊 ?朿 ?片 ?鼎 ; 250
94    ?克 ?彔 ?禾 ?秝 ?黍 ?香 ?米 ?毇 ?臼 ?凶 ; 260
95    ?𣎳 ?𣏟 ?麻 ?尗 ?耑 ?韭 ?瓜 ?瓠 ?宀 ?宮 ; 270
96    ?呂 ?穴 ?㝱 ?疒 ?冖 ?𠔼 ?冃 ?㒳 ?网 ?襾 ; 280
97    ?巾 ?巿 ?帛 ?白 ?㡀 ?黹 ?人 ?𠤎 ?匕 ?从 ; 290
98    ?比 ?北 ?丘 ?㐺 ?𡈼 ?重 ?臥 ?身 ?㐆 ?衣 ; 300
99    ?裘 ?老 ?毛 ?毳 ?尸 ?尺 ?尾 ?履 ?舟 ?方 ; 310
100    ?儿 ?兄 ?兂 ?皃 ?𠑹 ?先 ?秃 ?見 ?覞 ?欠 ; 320
101    ?㱃 ?㳄 ?旡 ?頁 ?𦣻 ?面 ?丏 ?首 ?𥄉 ?須 ; 330
102    ?彡 ?彣 ?文 ?髟 ?后 ?司 ?卮 ?卩 ?印 ?色 ; 340
103    ?𠨍 ?辟 ?勹 ?包 ?茍 ?鬼 ?甶 ?厶 ?嵬 ?山 ; 350
104    ?屾 ?屵 ?广 ?厂 ?丸 ?危 ?石 ?長 ?勿 ?冄 ; 360
105    ?而 ?豕 ?㣇 ?彑 ?豚 ?豸 ?𤉡 ?易 ?象 ?馬 ; 370
106    ?𢊁 ?鹿 ?麤 ?㲋 ?兔 ?萈 ?犬 ?㹜 ?鼠 ?能 ; 380
107    ?熊 ?火 ?炎 ?黑 ?囪 ?焱 ?炙 ?赤 ?大 ?亦 ; 390
108    ?夨 ?夭 ?交 ?尣 ?壺 ?壹 ?㚔 ?奢 ?亢 ?夲 ; 400
109    ?夰 ?亣 ?夫 ?立 ?竝 ?囟 ?思 ?心 ?惢 ?水 ; 410
110    ?沝 ?瀕 ?𡿨 ?巜 ?川 ?泉 ?灥 ?永 ?𠂢 ?谷 ; 420
111    ?仌 ?雨 ?雲 ?魚 ?𩺰 ?燕 ?龍 ?飛 ?非 ?卂 ; 430
112    ?𠃉 ?不 ?至 ?西 ?鹵 ?鹽 ?戶 ?門 ?耳 ?𦣝 ; 440
113    ?手 ?𠦬 ?女 ?毋 ?民 ?丿 ?𠂆 ?乁 ?氏 ?氐 ; 450
114    ?戈 ?戉 ?我 ?亅 ?琴 ?𠃊 ?亡 ?匸 ?匚 ?曲 ; 460
115    ?甾 ?瓦 ?弓 ?弜 ?弦 ?系 ?糸 ?素 ?絲 ?率 ; 470
116    ?虫 ?䖵 ?蟲 ?風 ?它 ?龜 ?黽 ?卵 ?二 ?土 ; 480
117    ?垚 ?堇 ?里 ?田 ?畕 ?黃 ?男 ?力 ?劦 ?金 ; 490
118    ?幵 ?勺 ?几 ?且 ?斤 ?斗 ?矛 ?車 ?𠂤 ?𨸏 ; 500
119    ?𨺅 ?厽 ?四 ?宁 ?叕 ?亞 ?五 ?六 ?七 ?九 ; 510
120    ?禸 ?嘼 ?甲 ?乙 ?丙 ?丁 ?戊 ?己 ?巴 ?庚 ; 520
121    ?辛 ?辡 ?壬 ?癸 ?子 ?了 ?孨 ?𠫓 ?丑 ?寅 ; 530
122    ?卯 ?辰 ?巳 ?午 ?未 ?申 ?酉 ?酋 ?戌 ?亥 ; 540
123    ])
124
125 (defun shuowen-radical (number)
126   (aref shuowen-radicals (1- number)))
127
128 (defvar char-db-file-coding-system 'utf-8-mcs-er)
129
130 (defvar char-db-ignored-attributes '(ideographic-products))
131
132 (defvar char-db-coded-charset-priority-list
133   '(ascii
134     control-1
135     latin-iso8859-1
136     latin-iso8859-2
137     latin-iso8859-3
138     latin-iso8859-4
139     latin-iso8859-9
140     latin-jisx0201
141     cyrillic-iso8859-5
142     greek-iso8859-7
143     thai-tis620
144     ;; =mj
145     ;; =adobe-japan1-0
146     ;; =adobe-japan1-1
147     ;; =adobe-japan1-2
148     ;; =adobe-japan1-3
149     ;; =adobe-japan1-4
150     ;; =adobe-japan1-5
151     ;; =adobe-japan1-6
152     =jis-x0208
153     =jis-x0208@1978
154     =jis-x0208@1983
155     japanese-jisx0212
156     chinese-gb2312
157     =jis-x0208@1990
158     chinese-cns11643-1
159     chinese-cns11643-2
160     chinese-cns11643-3
161     chinese-cns11643-4
162     chinese-cns11643-5
163     chinese-cns11643-6
164     chinese-cns11643-7
165     =jis-x0213-1
166     =jis-x0213-1@2000
167     =jis-x0213-1@2004
168     =jis-x0213-2
169     korean-ksc5601
170     chinese-isoir165
171     katakana-jisx0201
172     hebrew-iso8859-8
173     chinese-gb12345
174     latin-viscii
175     ethiopic-ucs
176     =big5-cdp
177     =hanyo-denshi/ja
178     =hanyo-denshi/jb
179     =hanyo-denshi/jc
180     =hanyo-denshi/jd
181     =hanyo-denshi/ft
182     =hanyo-denshi/ia
183     =hanyo-denshi/ib
184     =hanyo-denshi/hg
185     =hanyo-denshi/ip
186     =hanyo-denshi/jt
187     =hanyo-denshi/ks
188     =hanyo-denshi/tk
189     ;; ==mj
190     ;; ==adobe-japan1-0
191     ;; ==adobe-japan1-1
192     ;; ==adobe-japan1-2
193     ;; ==adobe-japan1-3
194     ;; ==adobe-japan1-4
195     ;; ==adobe-japan1-5
196     ;; ==adobe-japan1-6
197     ==jis-x0208
198     ==jis-x0213-1
199     ==jis-x0213-2
200     ==jis-x0212
201     ==hanyo-denshi/ja
202     ==hanyo-denshi/jb
203     ==hanyo-denshi/jc
204     ==hanyo-denshi/ft
205     ==hanyo-denshi/ia
206     ==hanyo-denshi/ib
207     ==hanyo-denshi/hg
208     ==hanyo-denshi/jt
209     ==hanyo-denshi/ks
210     ==hanyo-denshi/tk
211     =gt
212     =gt-k
213     =daikanwa
214     =daijiten
215     =daikanwa@rev2
216     =daikanwa@rev1
217     =daikanwa/+p
218     =daikanwa/ho
219     ==daikanwa
220     ==daijiten
221     =cbeta
222     ideograph-hanziku-1
223     ideograph-hanziku-2
224     ideograph-hanziku-3
225     ideograph-hanziku-4
226     ideograph-hanziku-5
227     ideograph-hanziku-6
228     ideograph-hanziku-7
229     ideograph-hanziku-8
230     ideograph-hanziku-9
231     ideograph-hanziku-10
232     ideograph-hanziku-11
233     ideograph-hanziku-12
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-2
244     ;; =>>>hanyo-denshi/ja
245     ;; =>>>hanyo-denshi/jb
246     ;; =>>>hanyo-denshi/jc
247     ;; =>>>hanyo-denshi/ft
248     ;; =>>>hanyo-denshi/ib
249     ;; =>>>hanyo-denshi/hg
250     ;; =>>>hanyo-denshi/jt
251     ;; =>>>hanyo-denshi/ks
252     ;; =>>>gt
253     =>>mj
254     =>>adobe-japan1-0
255     =>>adobe-japan1-1
256     =>>adobe-japan1-2
257     =>>adobe-japan1-3
258     =>>adobe-japan1-4
259     =>>adobe-japan1-5
260     =>>adobe-japan1-6
261     =>>jis-x0208
262     =>>jis-x0213-1
263     =>>jis-x0213-1@2000
264     =>>jis-x0213-1@2004
265     =>>jis-x0213-2
266     =>>jis-x0208@1978
267     =>>hanyo-denshi/ft
268     =>>hanyo-denshi/jt
269     =>>hanyo-denshi/ks
270     =>>gt
271     =>>daikanwa
272     =>>cbeta
273     =+>jis-x0208
274     =+>jis-x0213-1
275     =+>jis-x0213-2
276     =+>adobe-japan1-0
277     =+>adobe-japan1-1
278     =+>adobe-japan1-2
279     =+>adobe-japan1-3
280     =+>adobe-japan1-4
281     =+>adobe-japan1-5
282     =+>adobe-japan1-6
283     =+>jis-x0208@1978
284     =>jis-x0208
285     =>jis-x0208@1997
286     =>jis-x0213-1
287     =>jis-x0213-1@2000
288     =>jis-x0213-1@2004
289     =>jis-x0213-2
290     ==>ucs@bucs
291     ==>daijiten
292     ;; =>ucs@hanyo-denshi
293     =>ucs@iso
294     =>ucs@unicode
295     =>ucs@jis
296     =>ucs@cns
297     =>ucs@ks
298     =+>ucs@iso
299     =+>ucs@unicode
300     =+>ucs@jis
301     =+>ucs@jis/1990
302     =+>ucs@cns
303     =+>ucs@ks
304     =>>ucs@iso
305     =>>ucs@unicode
306     =>>ucs@jis
307     =>>ucs@JP
308     =>>ucs@cns
309     =>>>ucs@iso
310     =>>>ucs@unicode
311     ==ucs@iso
312     ==ucs@unicode
313     ;; ==ucs@cns
314     ==gb2312
315     ==ks-x1001
316     ==cns11643-1
317     ==cns11643-2
318     ==cns11643-3
319     ==cns11643-4
320     ==cns11643-5
321     ==cns11643-6
322     ==cns11643-7
323     ==gt
324     ==jis-x0208@1990
325     ;; ==jis-x0208@1983
326     ==jis-x0208@1978
327     ==gt-k
328     =ucs@iso
329     =ucs@unicode
330     =ucs@cns
331     ==big5-cdp
332     ==cbeta
333     =>>big5-cdp
334     =>>gt-k
335     =+>gt
336     =+>big5-cdp
337     =>big5-cdp
338     =>big5-cdp@iwds-1
339     =>mj
340     =>hanyo-denshi/tk
341     =>iwds-1
342     =big5
343     =big5-eten
344     =zinbun-oracle
345     =>zinbun-oracle
346     =ruimoku-v6
347     =>>ruimoku-v6
348     ==ruimoku-v6
349     =>ruimoku-v6
350     =jef-china3
351     =shinjigen
352     =>cns11643-5
353     =>cns11643-7
354     =>gt
355     =>gt-k
356     =>daikanwa
357     =>daikanwa/ho
358     =>cbeta
359     =ucs-var-001
360     =ucs-var-002
361     =ucs-var-003
362     =ucs-var-004
363     =ucs-var-005
364     =ucs-var-006
365     =ucs-var-007
366     =ucs-var-008
367     =ucs-var-010
368     =ucs-itaiji-001
369     =ucs-itaiji-002
370     =ucs-itaiji-003
371     =ucs-itaiji-004
372     =ucs-itaiji-005
373     =ucs-itaiji-006
374     =ucs-itaiji-007
375     =ucs-itaiji-008
376     =ucs-itaiji-009
377     =ucs-itaiji-010
378     =ucs-itaiji-011
379     =ucs-itaiji-012
380     =ucs-itaiji-014
381     =ucs-itaiji-016
382     =+>ucs-var-003
383     =>ucs-itaiji-001
384     =>ucs-itaiji-002
385     =>ucs-itaiji-003
386     =>ucs-itaiji-004
387     =>ucs-itaiji-005
388     =>ucs-itaiji-006
389     =>ucs-itaiji-007
390     =>ucs-itaiji-008
391     =>ucs-itaiji-009
392     =>ucs-itaiji-010
393     =>ucs-itaiji-011
394     =>ucs-itaiji-012
395     =>ucs-itaiji-014
396     =>ucs-itaiji-016
397     =big5-cdp-var-001
398     =big5-cdp-var-002
399     =big5-cdp-var-003
400     =big5-cdp-var-004
401     =big5-cdp-var-005
402     =big5-cdp-var-007
403     =big5-cdp-var-008
404     =big5-cdp-var-010
405     =big5-cdp-itaiji-001
406     =big5-cdp-itaiji-002
407     =big5-cdp-itaiji-003
408     =big5-cdp-itaiji-004
409     =big5-cdp-itaiji-005
410     =>big5-cdp-itaiji-001
411     =>big5-cdp-itaiji-002
412     =>big5-cdp-itaiji-003
413     =>big5-cdp-itaiji-004
414     =>big5-cdp-itaiji-005
415     =>big5-cdp-itaiji-006
416     =>big5-cdp-var-001
417     =>ucs@iwds-1
418     =>ucs@cognate
419     =>ucs@component
420     =>ucs@iwds-1/normalized
421     =>ucs-itaiji-001@iwds-1
422     =>ucs-itaiji-002@iwds-1
423     =>ucs-itaiji-003@iwds-1
424     =>ucs-itaiji-006@iwds-1
425     =>big5-cdp@component
426     =>big5-cdp@cognate
427     ==ucs@gb
428     =ucs@gb
429     ==ucs-var-002
430     ==ucs-itaiji-002
431     =ucs@JP/hanazono
432     =koseki
433     =shuowen-jiguge
434     =>shuowen-jiguge
435     ===shuowen-jiguge5
436     ===shuowen-jiguge4
437     ===chise-hdic-ktb-seal))
438
439
440 ;;; @ char-db formatters
441 ;;;
442
443 (defun char-db-make-char-spec (char)
444   (let (ret char-spec)
445     (cond ((characterp char)
446            (cond ((and (setq ret (encode-char char '=ucs 'defined-only))
447                        (not (and (<= #xE000 ret)(<= ret #xF8FF))))
448                   (setq char-spec (list (cons '=ucs ret)))
449                   (cond ((setq ret (get-char-attribute char 'name))
450                          (setq char-spec (cons (cons 'name ret) char-spec))
451                          )
452                         ((setq ret (get-char-attribute char 'name*))
453                          (setq char-spec (cons (cons 'name* ret) char-spec))
454                          ))
455                   )
456                  ((encode-char char '=mj 'defined-only)
457                   (setq char-spec nil)
458                   (dolist (ccs (charset-list))
459                     (if (and (or (eq ccs '=mj)
460                                  ;; (eq (charset-property ccs 'iso-ir) 177)
461                                  (string-match "=ucs@" (symbol-name ccs))
462                                  )
463                              (setq ccs (charset-name ccs))
464                              (null (assq ccs char-spec))
465                              (setq ret (encode-char char ccs 'defined-only)))
466                         (setq char-spec (cons (cons ccs ret) char-spec))))
467                   )
468                  ((encode-char char '==mj 'defined-only)
469                   (setq char-spec nil)
470                   (dolist (ccs (charset-list))
471                     (if (and (or (eq ccs '==mj)
472                                  ;; (eq (charset-property ccs 'iso-ir) 177)
473                                  (string-match "=ucs@" (symbol-name ccs))
474                                  )
475                              (setq ccs (charset-name ccs))
476                              (null (assq ccs char-spec))
477                              (setq ret (encode-char char ccs 'defined-only)))
478                         (setq char-spec (cons (cons ccs ret) char-spec))))
479                   )
480                  ((encode-char char '=adobe-japan1 'defined-only)
481                   (setq char-spec nil)
482                   (dolist (ccs (charset-list))
483                     (if (and (or (memq ccs
484                                        '(=adobe-japan1-0
485                                          =adobe-japan1-1
486                                          =adobe-japan1-2
487                                          =adobe-japan1-3
488                                          =adobe-japan1-4
489                                          =adobe-japan1-5
490                                          =adobe-japan1-6
491                                          ))
492                                  ;; (eq (charset-property ccs 'iso-ir) 177)
493                                  (string-match "=ucs@" (symbol-name ccs))
494                                  )
495                              (setq ccs (charset-name ccs))
496                              (null (assq ccs char-spec))
497                              (setq ret (encode-char char ccs 'defined-only)))
498                         (setq char-spec (cons (cons ccs ret) char-spec))))
499                   )
500                  ((encode-char char '==adobe-japan1 'defined-only)
501                   (setq char-spec nil)
502                   (dolist (ccs (charset-list))
503                     (if (and (or (memq ccs
504                                        '(==adobe-japan1-0
505                                          ==adobe-japan1-1
506                                          ==adobe-japan1-2
507                                          ==adobe-japan1-3
508                                          ==adobe-japan1-4
509                                          ==adobe-japan1-5
510                                          ==adobe-japan1-6
511                                          ))
512                                  ;; (eq (charset-property ccs 'iso-ir) 177)
513                                  (string-match "=ucs@" (symbol-name ccs))
514                                  )
515                              (setq ccs (charset-name ccs))
516                              (null (assq ccs char-spec))
517                              (setq ret (encode-char char ccs 'defined-only)))
518                         (setq char-spec (cons (cons ccs ret) char-spec))))
519                   )
520                  ((setq ret
521                         (catch 'tag
522                           (let ((rest char-db-coded-charset-priority-list)
523                                 ccs)
524                             (while rest
525                               (setq ccs (charset-name
526                                          (find-charset (car rest))))
527                               (if (setq ret
528                                         (encode-char char ccs
529                                                      'defined-only))
530                                   (throw 'tag (cons ccs ret)))
531                               (setq rest (cdr rest))))))
532                   (setq char-spec (list ret))
533                   (dolist (ccs (delq (car ret) (charset-list)))
534                     (if (and (or (charset-iso-final-char ccs)
535                                  (memq ccs
536                                        '(=daikanwa
537                                          =daikanwa@rev2
538                                          ;; =gt-k
539                                          =jis-x0208@1997
540                                          ))
541                                  (and (eq (charset-property ccs 'iso-ir) 177)
542                                       (not (eq (charset-name ccs) '=ucs@big5)))
543                                  ;; (string-match "=ucs@" (symbol-name ccs))
544                                  )
545                              (setq ccs (charset-name ccs))
546                              (null (assq ccs char-spec))
547                              (setq ret (encode-char char ccs 'defined-only)))
548                         (setq char-spec (cons (cons ccs ret) char-spec))))
549                   (if (null char-spec)
550                       (setq char-spec (split-char char)))
551                   (cond ((setq ret (get-char-attribute char 'name))
552                          (setq char-spec (cons (cons 'name ret) char-spec))
553                          )
554                         ((setq ret (get-char-attribute char 'name*))
555                          (setq char-spec (cons (cons 'name* ret) char-spec))
556                          ))
557                   )
558                  ((setq ret (get-char-attribute
559                              char 'ideographic-combination))
560                   (setq char-spec
561                         (cons (cons 'ideographic-combination ret)
562                               char-spec))
563                   ))
564            char-spec)
565           ((consp char)
566            char))))
567     
568 (defun char-db-insert-char-spec (char &optional readable column
569                                       required-features)
570   (unless column
571     (setq column (current-column)))
572   (let (char-spec temp-char)
573     (setq char-spec (char-db-make-char-spec char))
574     (unless (or (characterp char) ; char
575                 (condition-case nil
576                     (setq char (find-char char-spec))
577                   (error nil)))
578       ;; define temporary character
579       ;;   Current implementation is dirty.
580       (setq temp-char (define-char (cons '(ideograph-daikanwa . 0)
581                                          char-spec)))
582       (remove-char-attribute temp-char 'ideograph-daikanwa)
583       (setq char temp-char))
584     (insert-char-attributes char
585                             readable
586                             (union (mapcar #'car char-spec)
587                                    required-features)
588                             nil 'for-sub-node)
589     (when temp-char
590       ;; undefine temporary character
591       ;;   Current implementation is dirty.
592       (setq char-spec (char-attribute-alist temp-char))
593       (while char-spec
594         (remove-char-attribute temp-char (car (car char-spec)))
595         (setq char-spec (cdr char-spec))))))
596
597 (defun char-db-insert-alist (alist &optional readable column)
598   (unless column
599     (setq column (current-column)))
600   (let ((line-breaking
601          (concat "\n" (make-string (1+ column) ?\ )))
602         name value
603         ret al ; cal
604         key
605         lbs cell rest separator)
606     (insert "(")
607     (while alist
608       (setq name (car (car alist))
609             value (cdr (car alist)))
610       (cond ((eq name 'char)
611              (insert "(char . ")
612              (if (setq ret (condition-case nil
613                                (find-char value)
614                              (error nil)))
615                  (progn
616                    (setq al nil
617                          ;; cal nil
618                          )
619                    (while value
620                      (setq key (car (car value)))
621                      ;; (if (find-charset key)
622                      ;;     (setq cal (cons key cal))
623                      (setq al (cons key al))
624                      ;; )
625                      (setq value (cdr value)))
626                    (insert-char-attributes ret
627                                            readable
628                                            (or al 'none) ; cal
629                                            nil 'for-sub-node))
630                (insert (prin1-to-string value)))
631              (insert ")")
632              (insert line-breaking))
633             ((consp value)
634              (insert (format "(%-18s " name))
635              (setq lbs (concat "\n" (make-string (current-column) ?\ )))
636              (while (consp value)
637                (setq cell (car value))
638                (if (and (consp cell)
639                         (consp (car cell))
640                         (setq ret (condition-case nil
641                                       (find-char cell)
642                                     (error nil)))
643                         )
644                    (progn
645                      (setq rest cell
646                            al nil
647                            ;; cal nil
648                            )
649                      (while rest
650                        (setq key (car (car rest)))
651                        ;; (if (find-charset key)
652                        ;;     (setq cal (cons key cal))
653                        (setq al (cons key al))
654                        ;; )
655                        (setq rest (cdr rest)))
656                      (if separator
657                          (insert lbs))
658                      (insert-char-attributes ret
659                                              readable
660                                              al ; cal
661                                              nil 'for-sub-node)
662                      (setq separator lbs))
663                  (if separator
664                      (insert separator))
665                  (insert (prin1-to-string cell))
666                  (setq separator " "))
667                (setq value (cdr value)))
668              (insert ")")
669              (insert line-breaking))
670             (t
671              (insert (format "(%-18s . %S)%s"
672                              name value
673                              line-breaking))))
674       (setq alist (cdr alist))))
675   (insert ")"))
676
677 (defun char-db-insert-char-reference (plist &optional readable column)
678   (unless column
679     (setq column (current-column)))
680   (let ((line-breaking
681          (concat "\n" (make-string (1+ column) ?\ )))
682         (separator "")
683         name value)
684     (insert "(")
685     (while plist
686       (setq name (pop plist))
687       (setq value (pop plist))
688       (cond ((eq name :char)
689              (insert separator)
690              (insert ":char\t")
691              (cond ((numberp value)
692                     (setq value (decode-char '=ucs value)))
693                    ;; ((consp value)
694                    ;;  (setq value (or (find-char value)
695                    ;;                  value)))
696                    )
697              (char-db-insert-char-spec value readable)
698              (insert line-breaking)
699              (setq separator ""))
700             ((eq name :radical)
701              (insert (format "%s%s\t%d ; %c%s"
702                              separator
703                              name value
704                              (ideographic-radical value)
705                              line-breaking))
706              (setq separator ""))
707             (t
708              (insert (format "%s%s\t%S" separator name value))
709              (setq separator line-breaking)))
710       ))
711   (insert ")"))
712
713 (defun char-db-decode-isolated-char (ccs code-point)
714   (let (ret)
715     (setq ret
716           (cond ((eq ccs 'arabic-iso8859-6)
717                  (decode-char ccs code-point))
718                 ;; ((eq ccs '=gt)
719                 ;;  (decode-builtin-char '==gt code-point))
720                 ((and (memq ccs '(=gt-pj-1
721                                   =gt-pj-2
722                                   =gt-pj-3
723                                   =gt-pj-4
724                                   =gt-pj-5
725                                   =gt-pj-6
726                                   =gt-pj-7
727                                   =gt-pj-8
728                                   =gt-pj-9
729                                   =gt-pj-10
730                                   =gt-pj-11))
731                       (setq ret (decode-char ccs code-point))
732                       (setq ret (encode-char ret '=gt 'defined-only)))
733                  (decode-builtin-char '=gt ret))
734                 (t
735                  (decode-builtin-char ccs code-point))))
736     (cond ((null ret)
737            (or (decode-char ccs code-point)
738                (define-char (list (cons ccs code-point)))))
739           ((and (<= 0 (char-int ret))
740                 (<= (char-int ret) #x1F))
741            (decode-char '=ucs (+ #x2400 (char-int ret))))
742           ((= (char-int ret) #x7F)
743            ?\u2421)
744           (t ret))))
745
746 (defvar char-db-convert-obsolete-format t)
747
748 (defun char-db-insert-ccs-feature (name value line-breaking)
749   (cond
750    ((integerp value)
751     (insert
752      (format
753       (cond
754        ((memq name '(=>iwds-1
755                      ==shinjigen
756                      =shinjigen
757                      =shinjigen@1ed ==shinjigen@1ed
758                      =shinjigen@rev ==shinjigen@rev
759                      =shinjigen/+p@rev ==shinjigen/+p@rev
760                      ===daikanwa/ho ==daikanwa/ho
761                      =daikanwa/ho =>>daikanwa/ho =>daikanwa/ho))
762         "(%-18s .  %04d)\t; %c")
763        ((eq name '=shinjigen@1ed/24pr)
764         "(%-18s . %04d)\t; %c")
765        ((or
766          (memq name
767                '(===daikanwa
768                  ==daikanwa =daikanwa =>>daikanwa =>daikanwa
769                  =daikanwa@rev1 =daikanwa@rev2
770                  =daikanwa/+p ==daikanwa/+p ===daikanwa/+p
771                  =>>daikanwa/+p
772                  =daikanwa/+2p =>>daikanwa/+2p
773                  =gt ==gt ===gt
774                  =>>gt =+>gt =>gt
775                  =gt-k ==gt-k ===gt-k
776                  =>>gt-k =>gt-k
777                  =adobe-japan1-0 ==adobe-japan1-0 ===adobe-japan1-0
778                  =adobe-japan1-1 ==adobe-japan1-1 ===adobe-japan1-1
779                  =adobe-japan1-2 ==adobe-japan1-2 ===adobe-japan1-2
780                  =adobe-japan1-3 ==adobe-japan1-3 ===adobe-japan1-3
781                  =adobe-japan1-4 ==adobe-japan1-4 ===adobe-japan1-4
782                  =adobe-japan1-5 ==adobe-japan1-5 ===adobe-japan1-5
783                  =adobe-japan1-6 ==adobe-japan1-6 ===adobe-japan1-6
784                  =>>adobe-japan1-0 =+>adobe-japan1-0
785                  =>>adobe-japan1-1 =+>adobe-japan1-1
786                  =>>adobe-japan1-2 =+>adobe-japan1-2
787                  =>>adobe-japan1-3 =+>adobe-japan1-3
788                  =>>adobe-japan1-4 =+>adobe-japan1-4
789                  =>>adobe-japan1-5 =+>adobe-japan1-5
790                  =>>adobe-japan1-6 =+>adobe-japan1-6
791                  =>cbeta =cbeta =>>cbeta ==cbeta ===cbeta
792                  =zinbun-oracle =>zinbun-oracle
793                  =daijiten ==daijiten ===daijiten ==>daijiten
794                  ===hng-jou ===hng-keg ===hng-dng ===hng-mam
795                  ===hng-drt ===hng-kgk ===hng-myz ===hng-kda
796                  ===hng-khi ===hng-khm ===hng-fhs ===hng-hok
797                  ===hng-kyd ===hng-sok
798                  ===hng-yhk ===hng-kak ===hng-kar ===hng-kae
799                  ===hng-sys ===hng-tsu ===hng-tzj
800                  ===hng-hos ===hng-kkh ===hng-nak ===hng-jhk
801                  ===hng-hod ===hng-gok ===hng-ink ===hng-nto
802                  ===hng-nkm ===hng-k24 ===hng-ini ===hng-nkk
803                  ===hng-kcc ===hng-kcj ===hng-kbk ===hng-sik
804                  ===hng-skk ===hng-kyu ===hng-ksk ===hng-wan
805                  ===hng-okd ===hng-wad ===hng-kmi
806                  ===hng-zkd ===hng-doh ===hng-jyu ===hng-tzs
807                  ===hng-sai ===hng-kad ===hng-kss
808                  ===hng-kyo ===hng-ykk ===hng-saa
809                  ===hng-sab ===hng-wks ===hng-wke ===hng-smk
810                  ===hng-sgs ===hng-sts ===hng-kkd
811                  =>shuowen-jiguge =shuowen-jiguge
812                  ===shuowen-jiguge4 ===shuowen-jiguge5 ===shuowen-jiguge-A30))
813          ;; (string-match "^=adobe-" (symbol-name name))
814          )
815         "(%-18s . %05d)\t; %c")
816        ((memq name '(=hanyo-denshi/ks
817                      ==hanyo-denshi/ks ===hanyo-denshi/ks
818                      =>>hanyo-denshi/ks
819                      =koseki ==koseki
820                      =mj ==mj ===mj =>>mj =>mj
821                      =zihai mojikyo))
822         "(%-18s . %06d)\t; %c")
823        ((memq name '(=hanyo-denshi/tk =>hanyo-denshi/tk ==hanyo-denshi/tk))
824         "(%-18s . %08d)\t; %c")
825        ((>= (charset-dimension name) 2)
826         "(%-18s . #x%04X)\t; %c")
827        (t
828         "(%-18s . #x%02X)\t; %c"))
829       name
830       (if (= (charset-iso-graphic-plane name) 1)
831           (logior value
832                   (cond ((= (charset-dimension name) 1)
833                          #x80)
834                         ((= (charset-dimension name) 2)
835                          #x8080)
836                         ((= (charset-dimension name) 3)
837                          #x808080)
838                         (t 0)))
839         value)
840       (char-db-decode-isolated-char name value)))
841     (if (and (= (charset-chars name) 94)
842              (= (charset-dimension name) 2))
843         (insert (format " [%02d-%02d]"
844                         (- (lsh value -8) 32)
845                         (- (logand value 255) 32))))
846     )
847    (t
848     (insert (format "(%-18s . %s)" name value))
849     ))
850   (insert line-breaking))
851
852 (defun char-db-insert-relation-feature (char name value line-breaking
853                                              ccss readable)
854   (insert (format "(%-18s%s " name line-breaking))
855   (let ((lbs (concat "\n" (make-string (current-column) ?\ )))
856         separator cell sources required-features
857         ret)
858     (while (consp value)
859       (setq cell (car value))
860       (if (integerp cell)
861           (setq cell (decode-char '=ucs cell)))
862       (cond
863        ((eq name '->subsumptive)
864         (when (or (not (some (lambda (atr)
865                                (get-char-attribute cell atr))
866                              char-db-ignored-attributes))
867                   (some (lambda (ccs)
868                           (encode-char cell ccs 'defined-only))
869                         ccss))
870           (if separator
871               (insert lbs))
872           (let ((char-db-ignored-attributes
873                  (cons '<-subsumptive
874                        char-db-ignored-attributes)))
875             (insert-char-attributes cell readable nil nil 'for-sub-node))
876           (setq separator lbs))
877         )
878        ((characterp cell)
879         (setq sources
880               (get-char-attribute
881                char (intern (format "%s*sources" name))))
882         (setq required-features nil)
883         (dolist (source sources)
884           (cond
885            ((memq source '(JP
886                            JP/Jouyou
887                            shinjigen shinjigen@1ed shinjigen@rev))
888             (setq required-features
889                   (union required-features
890                          '(=jis-x0208
891                            =jis-x0208@1990
892                            =jis-x0213-1@2000
893                            =jis-x0213-1@2004
894                            =jis-x0213-2
895                            =jis-x0212
896                            =jis-x0208@1983
897                            =jis-x0208@1978
898                            =shinjigen
899                            =shinjigen@1ed
900                            =shinjigen@rev
901                            =shinjigen/+p@rev))))
902            ((eq source 'CN)
903             (setq required-features
904                   (union required-features
905                          '(=gb2312
906                            =gb12345
907                            =iso-ir165)))))
908           (cond
909            ((find-charset (setq ret (intern (format "=%s" source))))
910             (setq required-features
911                   (cons ret required-features)))
912            (t (setq required-features
913                     (cons source required-features)))))
914         (cond ((string-match "@JP" (symbol-name name))
915                (setq required-features
916                      (union required-features
917                             '(=jis-x0208
918                               =jis-x0208@1990
919                               =jis-x0213-1-2000
920                               =jis-x0213-2-2000
921                               =jis-x0212
922                               =jis-x0208@1983
923                               =jis-x0208@1978))))
924               ((string-match "@CN" (symbol-name name))
925                (setq required-features
926                      (union required-features
927                             '(=gb2312
928                               =gb12345
929                               =iso-ir165)))))
930         (if separator
931             (insert lbs))
932         (if readable
933             (insert (format "%S" cell))
934           (char-db-insert-char-spec cell readable
935                                     nil
936                                     required-features))
937         (setq separator lbs))
938        ((consp cell)
939         (if separator
940             (insert lbs))
941         (if (consp (car cell))
942             (char-db-insert-char-spec cell readable)
943           (char-db-insert-char-reference cell readable))
944         (setq separator lbs))
945        (t
946         (if separator
947             (insert separator))
948         (insert (prin1-to-string cell))
949         (setq separator " ")))
950       (setq value (cdr value)))
951     (insert ")")
952     (insert line-breaking)))
953
954 (defun insert-char-attributes (char &optional readable attributes column
955                                     for-sub-node)
956   (unless column
957     (setq column (current-column)))
958   (let (name value ; has-long-ccs-name
959         rest
960         radical strokes
961         (line-breaking
962          (concat "\n" (make-string (1+ column) ?\ )))
963         lbs cell separator ret
964         key al cal
965         dest-ccss ; sources required-features
966         ccss)
967     (let (atr-d)
968       (setq attributes
969             (sort (if attributes
970                       (if (consp attributes)
971                           (progn
972                             (dolist (name attributes)
973                               (unless (memq name char-db-ignored-attributes)
974                                 (if (find-charset name)
975                                     (push name ccss))
976                                 (push name atr-d)))
977                             atr-d))
978                     (dolist (name (char-attribute-list))
979                       (unless (memq name char-db-ignored-attributes)
980                         (if (find-charset name)
981                             (push name ccss))
982                         (push name atr-d)))
983                     atr-d)
984                   #'char-attribute-name<)))
985     (insert "(")
986     (when (memq '<-subsumptive attributes)
987       (when (or readable (not for-sub-node))
988         (when (setq value (get-char-attribute char '<-subsumptive))
989           (char-db-insert-relation-feature char '<-subsumptive value
990                                            line-breaking
991                                            ccss readable)))
992       (setq attributes (delq '<-subsumptive attributes)))
993     (when (and (memq '<-denotational attributes)
994                (setq value (get-char-attribute char '<-denotational)))
995       (char-db-insert-relation-feature char '<-denotational value
996                                        line-breaking
997                                        ccss readable)
998       (setq attributes (delq '<-denotational attributes)))
999     (when (and (memq '<-denotational@component attributes)
1000                (setq value (get-char-attribute char '<-denotational@component)))
1001       (char-db-insert-relation-feature char '<-denotational@component value
1002                                        line-breaking
1003                                        ccss readable)
1004       (setq attributes (delq '<-denotational@component attributes)))
1005     (when (and (memq '<-denotational@usage attributes)
1006                (setq value (get-char-attribute char '<-denotational@usage)))
1007       (char-db-insert-relation-feature char '<-denotational@usage value
1008                                        line-breaking
1009                                        ccss readable)
1010       (setq attributes (delq '<-denotational@usage attributes)))
1011     (when (and (memq 'name attributes)
1012                (setq value (get-char-attribute char 'name)))
1013       (insert (format
1014                (if (> (+ (current-column) (length value)) 48)
1015                    "(name . %S)%s"
1016                  "(name               . %S)%s")
1017                value line-breaking))
1018       (setq attributes (delq 'name attributes))
1019       )
1020     (when (and (memq 'name* attributes)
1021                (setq value (get-char-attribute char 'name*)))
1022       (insert (format
1023                (if (> (+ (current-column) (length value)) 48)
1024                    "(name* . %S)%s"
1025                  "(name*              . %S)%s")
1026                value line-breaking))
1027       (setq attributes (delq 'name* attributes))
1028       )
1029     (when (and (memq 'script attributes)
1030                (setq value (get-char-attribute char 'script)))
1031       (insert (format "(script\t\t%s)%s"
1032                       (mapconcat (function prin1-to-string)
1033                                  value " ")
1034                       line-breaking))
1035       (setq attributes (delq 'script attributes))
1036       )
1037     (dolist (name '(=>ucs =>ucs*))
1038       (when (and (memq name attributes)
1039                  (setq value (get-char-attribute char name)))
1040         (insert (format "(%-18s . #x%04X)\t; %c%s"
1041                         name value (decode-char '=ucs value)
1042                         line-breaking))
1043         (setq attributes (delq name attributes))))
1044     (dolist (name '(=>ucs@gb =>ucs@big5))
1045       (when (and (memq name attributes)
1046                  (setq value (get-char-attribute char name)))
1047         (insert (format "(%-18s . #x%04X)\t; %c%s"
1048                         name value
1049                         (decode-char (intern
1050                                       (concat "="
1051                                               (substring
1052                                                (symbol-name name) 2)))
1053                                      value)
1054                         line-breaking))
1055         (setq attributes (delq name attributes))
1056         ))
1057     ;; (dolist (name '(=>daikanwa))
1058     ;;   (when (and (memq name attributes)
1059     ;;              (setq value (get-char-attribute char name)))
1060     ;;     (insert
1061     ;;      (if (integerp value)
1062     ;;          (format "(%-18s . %05d)\t; %c%s"
1063     ;;                  name value (decode-char '=daikanwa value)
1064     ;;                  line-breaking)
1065     ;;        (format "(%-18s %s)\t; %c%s"
1066     ;;                name
1067     ;;                (mapconcat (function prin1-to-string)
1068     ;;                           value " ")
1069     ;;                (char-representative-of-daikanwa char)
1070     ;;                line-breaking)))
1071     ;;     (setq attributes (delq name attributes))))
1072     (when (and (memq 'general-category attributes)
1073                (setq value (get-char-attribute char 'general-category)))
1074       (insert (format
1075                "(general-category\t%s) ; %s%s"
1076                (mapconcat (lambda (cell)
1077                             (format "%S" cell))
1078                           value " ")
1079                (cond ((rassoc value unidata-normative-category-alist)
1080                       "Normative Category")
1081                      ((rassoc value unidata-informative-category-alist)
1082                       "Informative Category")
1083                      (t
1084                       "Unknown Category"))
1085                line-breaking))
1086       (setq attributes (delq 'general-category attributes))
1087       )
1088     (when (and (memq 'bidi-category attributes)
1089                (setq value (get-char-attribute char 'bidi-category)))
1090       (insert (format "(bidi-category\t. %S)%s"
1091                       value
1092                       line-breaking))
1093       (setq attributes (delq 'bidi-category attributes))
1094       )
1095     (unless (or (not (memq 'mirrored attributes))
1096                 (eq (setq value (get-char-attribute char 'mirrored 'empty))
1097                     'empty))
1098       (insert (format "(mirrored\t\t. %S)%s"
1099                       value
1100                       line-breaking))
1101       (setq attributes (delq 'mirrored attributes))
1102       )
1103     (cond
1104      ((and (memq 'decimal-digit-value attributes)
1105            (setq value (get-char-attribute char 'decimal-digit-value)))
1106       (insert (format "(decimal-digit-value . %S)%s"
1107                       value
1108                       line-breaking))
1109       (setq attributes (delq 'decimal-digit-value attributes))
1110       (when (and (memq 'digit-value attributes)
1111                  (setq value (get-char-attribute char 'digit-value)))
1112         (insert (format "(digit-value\t . %S)%s"
1113                         value
1114                         line-breaking))
1115         (setq attributes (delq 'digit-value attributes))
1116         )
1117       (when (and (memq 'numeric-value attributes)
1118                  (setq value (get-char-attribute char 'numeric-value)))
1119         (insert (format "(numeric-value\t . %S)%s"
1120                         value
1121                         line-breaking))
1122         (setq attributes (delq 'numeric-value attributes))
1123         )
1124       )
1125      (t
1126       (when (and (memq 'digit-value attributes)
1127                  (setq value (get-char-attribute char 'digit-value)))
1128         (insert (format "(digit-value\t. %S)%s"
1129                         value
1130                         line-breaking))
1131         (setq attributes (delq 'digit-value attributes))
1132         )
1133       (when (and (memq 'numeric-value attributes)
1134                  (setq value (get-char-attribute char 'numeric-value)))
1135         (insert (format "(numeric-value\t. %S)%s"
1136                         value
1137                         line-breaking))
1138         (setq attributes (delq 'numeric-value attributes))
1139         )))
1140     (when (and (memq 'iso-10646-comment attributes)
1141                (setq value (get-char-attribute char 'iso-10646-comment)))
1142       (insert (format "(iso-10646-comment\t. %S)%s"
1143                       value
1144                       line-breaking))
1145       (setq attributes (delq 'iso-10646-comment attributes))
1146       )
1147     (when (and (memq 'morohashi-daikanwa attributes)
1148                (setq value (get-char-attribute char 'morohashi-daikanwa)))
1149       (insert (format "(morohashi-daikanwa\t%s)%s"
1150                       (mapconcat (function prin1-to-string) value " ")
1151                       line-breaking))
1152       (setq attributes (delq 'morohashi-daikanwa attributes))
1153       )
1154     (setq radical nil
1155           strokes nil)
1156     (when (and (memq 'ideographic-radical attributes)
1157                (setq value (get-char-attribute char 'ideographic-radical)))
1158       (setq radical value)
1159       (insert (format "(ideographic-radical . %S)\t; %c%s"
1160                       radical
1161                       (ideographic-radical radical)
1162                       line-breaking))
1163       (setq attributes (delq 'ideographic-radical attributes))
1164       )
1165     (when (and (memq 'shuowen-radical attributes)
1166                (setq value (get-char-attribute char 'shuowen-radical)))
1167       (insert (format "(shuowen-radical\t. %S)\t; %c%s"
1168                       value
1169                       (shuowen-radical value)
1170                       line-breaking))
1171       (setq attributes (delq 'shuowen-radical attributes))
1172       )
1173     (let (key)
1174       (dolist (domain
1175                (append
1176                 char-db-feature-domains
1177                 (let (dest domain)
1178                   (dolist (feature (char-attribute-list))
1179                     (setq feature (symbol-name feature))
1180                     (when (string-match
1181                            "\\(radical\\|strokes\\)@\\([^@*]+\\)\\(\\*\\|$\\)"
1182                            feature)
1183                       (setq domain (intern (match-string 2 feature)))
1184                      (unless (memq domain dest)
1185                        (setq dest (cons domain dest)))))
1186                   (sort dest #'string<))))
1187         (setq key (intern (format "%s@%s" 'ideographic-radical domain)))
1188         (when (and (memq key attributes)
1189                    (setq value (get-char-attribute char key)))
1190           (setq radical value)
1191           (insert (format "(%s . %S)\t; %c%s"
1192                           key
1193                           radical
1194                           (ideographic-radical radical)
1195                           line-breaking))
1196           (setq attributes (delq key attributes))
1197           )
1198         (setq key (intern (format "%s@%s" 'ideographic-strokes domain)))
1199         (when (and (memq key attributes)
1200                    (setq value (get-char-attribute char key)))
1201           (setq strokes value)
1202           (insert (format "(%s . %S)%s"
1203                           key
1204                           strokes
1205                           line-breaking))
1206           (setq attributes (delq key attributes))
1207           )
1208         (setq key (intern (format "%s@%s" 'total-strokes domain)))
1209         (when (and (memq key attributes)
1210                    (setq value (get-char-attribute char key)))
1211           (insert (format "(%s       . %S)%s"
1212                           key
1213                           value
1214                           line-breaking))
1215           (setq attributes (delq key attributes))
1216           )
1217         (dolist (feature '(ideographic-radical
1218                            ideographic-strokes
1219                            total-strokes))
1220           (setq key (intern (format "%s@%s*sources" feature domain)))
1221           (when (and (memq key attributes)
1222                      (setq value (get-char-attribute char key)))
1223             (insert (format "(%s%s" key line-breaking))
1224             (dolist (cell value)
1225               (insert (format " %s" cell)))
1226             (insert ")")
1227             (insert line-breaking)
1228             (setq attributes (delq key attributes))
1229             ))
1230         ))
1231     (when (and (memq 'ideographic-strokes attributes)
1232                (setq value (get-char-attribute char 'ideographic-strokes)))
1233       (setq strokes value)
1234       (insert (format "(ideographic-strokes . %S)%s"
1235                       strokes
1236                       line-breaking))
1237       (setq attributes (delq 'ideographic-strokes attributes))
1238       )
1239     (when (and (memq 'kangxi-radical attributes)
1240                (setq value (get-char-attribute char 'kangxi-radical)))
1241       (unless (eq value radical)
1242         (insert (format "(kangxi-radical\t . %S)\t; %c%s"
1243                         value
1244                         (ideographic-radical value)
1245                         line-breaking))
1246         (or radical
1247             (setq radical value)))
1248       (setq attributes (delq 'kangxi-radical attributes))
1249       )
1250     (when (and (memq 'kangxi-strokes attributes)
1251                (setq value (get-char-attribute char 'kangxi-strokes)))
1252       (unless (eq value strokes)
1253         (insert (format "(kangxi-strokes\t . %S)%s"
1254                         value
1255                         line-breaking))
1256         (or strokes
1257             (setq strokes value)))
1258       (setq attributes (delq 'kangxi-strokes attributes))
1259       )
1260     ;; (when (and (memq 'japanese-radical attributes)
1261     ;;            (setq value (get-char-attribute char 'japanese-radical)))
1262     ;;   (unless (eq value radical)
1263     ;;     (insert (format "(japanese-radical\t . %S)\t; %c%s"
1264     ;;                     value
1265     ;;                     (ideographic-radical value)
1266     ;;                     line-breaking))
1267     ;;     (or radical
1268     ;;         (setq radical value)))
1269     ;;   (setq attributes (delq 'japanese-radical attributes))
1270     ;;   )
1271     (when (and (memq 'japanese-strokes attributes)
1272                (setq value (get-char-attribute char 'japanese-strokes)))
1273       (unless (eq value strokes)
1274         (insert (format "(japanese-strokes\t . %S)%s"
1275                         value
1276                         line-breaking))
1277         (or strokes
1278             (setq strokes value)))
1279       (setq attributes (delq 'japanese-strokes attributes))
1280       )
1281     (when (and (memq 'cns-radical attributes)
1282                (setq value (get-char-attribute char 'cns-radical)))
1283       (insert (format "(cns-radical\t . %S)\t; %c%s"
1284                       value
1285                       (ideographic-radical value)
1286                       line-breaking))
1287       (setq attributes (delq 'cns-radical attributes))
1288       )
1289     (when (and (memq 'cns-strokes attributes)
1290                (setq value (get-char-attribute char 'cns-strokes)))
1291       (unless (eq value strokes)
1292         (insert (format "(cns-strokes\t . %S)%s"
1293                         value
1294                         line-breaking))
1295         (or strokes
1296             (setq strokes value)))
1297       (setq attributes (delq 'cns-strokes attributes))
1298       )
1299     ;; (when (and (memq 'ideographic- attributes)
1300     ;;            (setq value (get-char-attribute char 'ideographic-)))
1301     ;;   (insert "(ideographic-       ")
1302     ;;   (setq lbs (concat "\n" (make-string (current-column) ?\ ))
1303     ;;         separator nil)
1304     ;;   (while (consp value)
1305     ;;     (setq cell (car value))
1306     ;;     (if (integerp cell)
1307     ;;         (setq cell (decode-char '=ucs cell)))
1308     ;;     (cond ((characterp cell)
1309     ;;            (if separator
1310     ;;                (insert lbs))
1311     ;;            (if readable
1312     ;;                (insert (format "%S" cell))
1313     ;;              (char-db-insert-char-spec cell readable))
1314     ;;            (setq separator lbs))
1315     ;;           ((consp cell)
1316     ;;            (if separator
1317     ;;                (insert lbs))
1318     ;;            (if (consp (car cell))
1319     ;;                (char-db-insert-char-spec cell readable)
1320     ;;              (char-db-insert-char-reference cell readable))
1321     ;;            (setq separator lbs))
1322     ;;           (t
1323     ;;            (if separator
1324     ;;                (insert separator))
1325     ;;            (insert (prin1-to-string cell))
1326     ;;            (setq separator " ")))
1327     ;;     (setq value (cdr value)))
1328     ;;   (insert ")")
1329     ;;   (insert line-breaking)
1330     ;;   (setq attributes (delq 'ideographic- attributes)))
1331     (when (and (memq 'total-strokes attributes)
1332                (setq value (get-char-attribute char 'total-strokes)))
1333       (insert (format "(total-strokes       . %S)%s"
1334                       value
1335                       line-breaking))
1336       (setq attributes (delq 'total-strokes attributes))
1337       )
1338     ;; (when (and (memq '->ideograph attributes)
1339     ;;            (setq value (get-char-attribute char '->ideograph)))
1340     ;;   (insert (format "(->ideograph\t%s)%s"
1341     ;;                   (mapconcat (lambda (code)
1342     ;;                                (cond ((symbolp code)
1343     ;;                                       (symbol-name code))
1344     ;;                                      ((integerp code)
1345     ;;                                       (format "#x%04X" code))
1346     ;;                                      (t
1347     ;;                                       (format "%s %S"
1348     ;;                                               line-breaking code))))
1349     ;;                              value " ")
1350     ;;                   line-breaking))
1351     ;;   (setq attributes (delq '->ideograph attributes))
1352     ;;   )
1353     ;; (when (and (memq '->decomposition attributes)
1354     ;;            (setq value (get-char-attribute char '->decomposition)))
1355     ;;   (insert (format "(->decomposition\t%s)%s"
1356     ;;                   (mapconcat (lambda (code)
1357     ;;                                (cond ((symbolp code)
1358     ;;                                       (symbol-name code))
1359     ;;                                      ((characterp code)
1360     ;;                                       (if readable
1361     ;;                                           (format "%S" code)
1362     ;;                                         (format "#x%04X"
1363     ;;                                                 (char-int code))
1364     ;;                                         ))
1365     ;;                                      ((integerp code)
1366     ;;                                       (format "#x%04X" code))
1367     ;;                                      (t
1368     ;;                                       (format "%s%S" line-breaking code))))
1369     ;;                              value " ")
1370     ;;                   line-breaking))
1371     ;;   (setq attributes (delq '->decomposition attributes))
1372     ;;   )
1373     (if (equal (get-char-attribute char '->titlecase)
1374                (get-char-attribute char '->uppercase))
1375         (setq attributes (delq '->titlecase attributes)))
1376     (when (and (memq '->mojikyo attributes)
1377                (setq value (get-char-attribute char '->mojikyo)))
1378       (insert (format "(->mojikyo\t\t. %06d)\t; %c%s"
1379                       value (decode-char 'mojikyo value)
1380                       line-breaking))
1381       (setq attributes (delq '->mojikyo attributes))
1382       )
1383     (unless readable
1384       (dolist (ignored '(composition
1385                          ->denotational <-subsumptive ->ucs-unified
1386                          ;; ->ideographic-component-forms
1387                          ))
1388         (setq attributes (delq ignored attributes))))
1389     (while attributes
1390       (setq name (car attributes))
1391       (unless (eq (setq value (get-char-attribute char name 'value-is-empty))
1392                   'value-is-empty)
1393         (cond ((setq ret (find-charset name))
1394                (setq name (charset-name ret))
1395                (when (not (memq name dest-ccss))
1396                  (setq dest-ccss (cons name dest-ccss))
1397                  (char-db-insert-ccs-feature name value line-breaking))
1398                )
1399               ((string-match "^=>ucs@" (symbol-name name))
1400                (insert (format "(%-18s . #x%04X)\t; %c%s"
1401                                name value (decode-char '=ucs value)
1402                                line-breaking))
1403                )
1404               ((eq name 'jisx0208-1978/4X)
1405                (insert (format "(%-18s . #x%04X)%s"
1406                                name value
1407                                line-breaking))
1408                )
1409               ((and
1410                 (not readable)
1411                 (not (eq name '->subsumptive))
1412                 (not (eq name '->uppercase))
1413                 (not (eq name '->lowercase))
1414                 (not (eq name '->titlecase))
1415                 (not (eq name '->canonical))
1416                 (not (eq name '->Bopomofo))
1417                 (not (eq name '->mistakable))
1418                 (not (eq name '->ideographic-variants))
1419                 (null (get-char-attribute
1420                        char (intern (format "%s*sources" name))))
1421                 (not (string-match "\\*sources$" (symbol-name name)))
1422                 (null (get-char-attribute
1423                        char (intern (format "%s*note" name))))
1424                 (not (string-match "\\*note$" (symbol-name name)))
1425                 (or (eq name '<-identical)
1426                     (eq name '<-uppercase)
1427                     (eq name '<-lowercase)
1428                     (eq name '<-titlecase)
1429                     (eq name '<-canonical)
1430                     (eq name '<-ideographic-variants)
1431                     ;; (eq name '<-synonyms)
1432                     (string-match "^<-synonyms" (symbol-name name))
1433                     (eq name '<-mistakable)
1434                     (when (string-match "^->" (symbol-name name))
1435                       (cond
1436                        ((string-match "^->fullwidth" (symbol-name name))
1437                         (not (and (consp value)
1438                                   (characterp (car value))
1439                                   (encode-char
1440                                    (car value) '=ucs 'defined-only)))
1441                         )
1442                        (t)))
1443                     ))
1444                )
1445               ((or (eq name 'ideographic-structure)
1446                    (eq name 'ideographic-structure@apparent)
1447                    (eq name 'ideographic-structure@apparent/leftmost)
1448                    (eq name 'ideographic-structure@apparent/rightmost)
1449                    (eq name 'ideographic-combination)
1450                    ;; (eq name 'ideographic-)
1451                    (eq name '=decomposition)
1452                    (char-feature-base-name= '=decomposition name)
1453                    (char-feature-base-name= '=>decomposition name)
1454                    ;; (string-match "^=>*decomposition\\(@[^*]+\\)?$"
1455                    ;;               (symbol-name name))
1456                    (string-match "^\\(->\\|<-\\)[^*]*$" (symbol-name name))
1457                    (string-match "^\\(->\\|<-\\)[^*]*\\*sources$"
1458                                  (symbol-name name))
1459                    )
1460                (char-db-insert-relation-feature char name value
1461                                                 line-breaking
1462                                                 ccss readable))
1463               ;; ((memq name '(ideograph=
1464               ;;               original-ideograph-of
1465               ;;               ancient-ideograph-of
1466               ;;               vulgar-ideograph-of
1467               ;;               wrong-ideograph-of
1468               ;;               ;; simplified-ideograph-of
1469               ;;               ideographic-variants
1470               ;;               ;; ideographic-different-form-of
1471               ;;               ))
1472               ;;  (insert (format "(%-18s%s " name line-breaking))
1473               ;;  (setq lbs (concat "\n" (make-string (current-column) ?\ ))
1474               ;;        separator nil)
1475               ;;  (while (consp value)
1476               ;;    (setq cell (car value))
1477               ;;    (if (and (consp cell)
1478               ;;             (consp (car cell)))
1479               ;;        (progn
1480               ;;          (if separator
1481               ;;              (insert lbs))
1482               ;;          (char-db-insert-alist cell readable)
1483               ;;          (setq separator lbs))
1484               ;;      (if separator
1485               ;;          (insert separator))
1486               ;;      (insert (prin1-to-string cell))
1487               ;;      (setq separator " "))
1488               ;;    (setq value (cdr value)))
1489               ;;  (insert ")")
1490               ;;  (insert line-breaking))
1491               ((consp value)
1492                (insert (format "(%-18s " name))
1493                (setq lbs (concat "\n" (make-string (current-column) ?\ ))
1494                      separator nil)
1495                (while (consp value)
1496                  (setq cell (car value))
1497                  (if (and (consp cell)
1498                           (consp (car cell))
1499                           (setq ret (condition-case nil
1500                                         (find-char cell)
1501                                       (error nil))))
1502                      (progn
1503                        (setq rest cell
1504                              al nil
1505                              cal nil)
1506                        (while rest
1507                          (setq key (car (car rest)))
1508                          (if (find-charset key)
1509                              (setq cal (cons key cal))
1510                            (setq al (cons key al)))
1511                          (setq rest (cdr rest)))
1512                        (if separator
1513                            (insert lbs))
1514                        (insert-char-attributes ret
1515                                                readable
1516                                                al ; cal
1517                                                nil 'for-sub-node)
1518                        (setq separator lbs))
1519                    (setq ret (prin1-to-string cell))
1520                    (if separator
1521                        (if (< (+ (current-column)
1522                                  (length ret)
1523                                  (length separator))
1524                               76)
1525                            (insert separator)
1526                          (insert lbs)))
1527                    (insert ret)
1528                    (setq separator " "))
1529                  (setq value (cdr value)))
1530                (insert ")")
1531                (insert line-breaking))
1532               (t
1533                (insert (format "(%-18s" name))
1534                (setq ret (prin1-to-string value))
1535                (unless (< (+ (current-column)
1536                              (length ret)
1537                              3)
1538                           76)
1539                  (insert line-breaking))
1540                (insert " . " ret ")" line-breaking)
1541                ;; (insert (format "(%-18s . %S)%s"
1542                ;;                 name value
1543                ;;                 line-breaking))
1544                )
1545               ))
1546       (setq attributes (cdr attributes)))
1547     (insert ")")))
1548
1549 (defun insert-char-data (char &optional readable
1550                               attributes)
1551   (save-restriction
1552     (narrow-to-region (point)(point))
1553     (insert "(define-char
1554   '")
1555     (insert-char-attributes char readable attributes)
1556     (insert ")\n")
1557     (goto-char (point-min))
1558     (while (re-search-forward "[ \t]+$" nil t)
1559       (replace-match ""))
1560     ;; from tabify.
1561     (goto-char (point-min))
1562     (while (re-search-forward "[ \t][ \t][ \t]*" nil t)
1563       (let ((column (current-column))
1564             (indent-tabs-mode t))
1565         (delete-region (match-beginning 0) (point))
1566         (indent-to column)))
1567     (goto-char (point-max))
1568     ;; (tabify (point-min)(point-max))
1569     ))
1570
1571 (defun insert-char-data-with-variant (char &optional printable
1572                                            no-ucs-unified
1573                                            script excluded-script)
1574   (insert-char-data char printable)
1575   (let ((variants (char-variants char))
1576         rest
1577         variant vs ret)
1578     (setq variants (sort variants #'<))
1579     (setq rest variants)
1580     (setq variants (cons char variants))
1581     (while rest
1582       (setq variant (car rest))
1583       (unless (get-char-attribute variant '<-subsumptive)
1584         (if (and (or (null script)
1585                      (null (setq vs (get-char-attribute variant 'script)))
1586                      (memq script vs))
1587                  (or (null excluded-script)
1588                      (null (setq vs (get-char-attribute variant 'script)))
1589                      (not (memq excluded-script vs))))
1590             (unless (and no-ucs-unified (get-char-attribute variant '=ucs))
1591               (insert-char-data variant printable)
1592               (if (setq ret (char-variants variant))
1593                   (while ret
1594                     (or (memq (car ret) variants)
1595                         ;; (get-char-attribute (car ret) '<-subsumptive)
1596                         (setq rest (nconc rest (list (car ret)))))
1597                     (setq ret (cdr ret)))))))
1598       (setq rest (cdr rest)))))
1599
1600 (defun insert-char-range-data (min max &optional script excluded-script)
1601   (let ((code min)
1602         char)
1603     (while (<= code max)
1604       (setq char (decode-char '=ucs code))
1605       (if (encode-char char '=ucs 'defined-only)
1606           (insert-char-data-with-variant char nil 'no-ucs-unified
1607                                          script excluded-script))
1608       (setq code (1+ code)))))
1609
1610 (defun write-char-range-data-to-file (min max file
1611                                           &optional script excluded-script)
1612   (let ((coding-system-for-write char-db-file-coding-system))
1613     (with-temp-buffer
1614       (insert (format ";; -*- coding: %s -*-\n"
1615                       char-db-file-coding-system))
1616       (insert-char-range-data min max script excluded-script)
1617       (write-region (point-min)(point-max) file))))
1618
1619 (defvar what-character-original-window-configuration)
1620
1621 ;;;###autoload
1622 (defun what-char-definition (char)
1623   (interactive (list (char-after)))
1624   (let ((buf (get-buffer-create "*Character Description*"))
1625         (the-buf (current-buffer))
1626         (win-conf (current-window-configuration)))
1627     (pop-to-buffer buf)
1628     (make-local-variable 'what-character-original-window-configuration)
1629     (setq what-character-original-window-configuration win-conf)
1630     (setq buffer-read-only nil)
1631     (erase-buffer)
1632     (condition-case err
1633         (progn
1634           (insert-char-data-with-variant char 'printable)
1635           (unless (char-attribute-alist char)
1636             (insert (format ";; = %c\n"
1637                             (let* ((rest (split-char char))
1638                                    (ccs (pop rest))
1639                                    (code (pop rest)))
1640                               (while rest
1641                                 (setq code (logior (lsh code 8)
1642                                                    (pop rest))))
1643                               (decode-char ccs code)))))
1644           ;; (char-db-update-comment)
1645           (set-buffer-modified-p nil)
1646           (view-mode the-buf (lambda (buf)
1647                                (set-window-configuration
1648                                 what-character-original-window-configuration)
1649                                ))
1650           (goto-char (point-min)))
1651       (error (progn
1652                (set-window-configuration
1653                 what-character-original-window-configuration)
1654                (signal (car err) (cdr err)))))))
1655
1656
1657 ;;; @ end
1658 ;;;
1659
1660 (provide 'char-db-util)
1661
1662 ;;; char-db-util.el ends here