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