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