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