update.
[chise/chiset.git] / char-db-turtle.el
1 ;;; char-db-turtle.el --- Character Database utility -*- coding: utf-8-er; -*-
2
3 ;; Copyright (C) 2017 MORIOKA Tomohiko.
4
5 ;; Author: MORIOKA Tomohiko <tomo@kanji.zinbun.kyoto-u.ac.jp>
6 ;; Keywords: CHISE, Character Database, RDF, Turtle, ISO/IEC 10646, UCS, Unicode, MULE.
7
8 ;; This file is part of CHISET (CHISE/Turtle).
9
10 ;; XEmacs CHISE is free software; you can redistribute it and/or
11 ;; modify it under the terms of the GNU General Public License as
12 ;; published by the Free Software Foundation; either version 2, or (at
13 ;; your option) any later version.
14
15 ;; XEmacs CHISE is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 ;; General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with XEmacs CHISE; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;; Code:
26
27 (require 'char-db-util)
28 (require 'cwiki-common)
29 (require 'isd-turtle)
30 (require 'ideograph-util)
31
32 (setq est-coded-charset-priority-list
33   '(; =ucs
34     =mj
35     =adobe-japan1-0
36     =adobe-japan1-1
37     =adobe-japan1-2
38     =adobe-japan1-3
39     =adobe-japan1-4
40     =adobe-japan1-5
41     =adobe-japan1-6
42     =ucs@iso
43     =jis-x0208 =jis-x0208@1990
44     =jis-x0213-1
45     =jis-x0213-1@2000 =jis-x0213-1@2004
46     =jis-x0213-2
47     =jis-x0212
48     =gt
49     =hanyo-denshi/ks
50     =hanyo-denshi/tk
51     =ucs-itaiji-001
52     =ucs-itaiji-002
53     =ucs-itaiji-003
54     =ucs-itaiji-004
55     =ucs-itaiji-005
56     =ucs-itaiji-006
57     =ucs-itaiji-007
58     =ucs-itaiji-009
59     =ucs-itaiji-084
60     =ucs-var-001
61     =ucs-var-002
62     =ucs-var-003
63     =ucs-var-004
64     =cns11643-1 =cns11643-2 =cns11643-3
65     =cns11643-4 =cns11643-5 =cns11643-6 =cns11643-7
66     =gb2312
67     =big5-cdp
68     =ks-x1001
69     =gt-k
70     =ucs@unicode
71     =ucs@JP/hanazono
72     =gb12345
73     =ucs@cns
74     =ucs@gb
75     =zinbun-oracle =>zinbun-oracle
76     =daikanwa
77     =ruimoku-v6
78     =cbeta =jef-china3
79     =daikanwa/+2p
80     =+>ucs@iso =+>ucs@unicode
81     =+>ucs@jis
82     =+>ucs@cns
83     =+>ucs@ks
84     =+>ucs@jis/1990
85     =>mj
86     =>jis-x0208 =>jis-x0213-1
87     =>jis-x0208@1997
88     =>ucs@iwds-1
89     =>ucs@component
90     =>iwds-1
91     =>ucs@iso
92     =>ucs@unicode
93     =>ucs@jis =>ucs@cns =>ucs@ks
94     =>gt
95     =>gt-k
96     =>>ucs@iso =>>ucs@unicode
97     =>>ucs@jis =>>ucs@cns =>>ucs@ks
98     =>>gt-k
99     =>>hanyo-denshi/ks
100     ==mj
101     ==ucs@iso
102     ==ucs@unicode
103     ==adobe-japan1-0
104     ==adobe-japan1-1
105     ==adobe-japan1-2
106     ==adobe-japan1-3
107     ==adobe-japan1-4
108     ==adobe-japan1-5
109     ==adobe-japan1-6
110     ==ks-x1001
111     ==hanyo-denshi/ks
112     ==hanyo-denshi/tk
113     ==ucs@jis
114     ==gt
115     ==cns11643-1 ==cns11643-2 ==cns11643-3
116     ==cns11643-4 ==cns11643-5 ==cns11643-6 ==cns11643-7
117     ==jis-x0212
118     ==ucs@cns
119     ==koseki
120     ==daikanwa
121     ==gt-k
122     ==ucs@gb
123     ==ucs-itaiji-003
124     ==ucs@JP/hanazono
125     ==daikanwa/+2p
126     =>>jis-x0208 =>>jis-x0213-1 =>>jis-x0213-2
127     =+>jis-x0208 =+>jis-x0213-1 =+>jis-x0213-2
128     =+>hanyo-denshi/jt
129     =+>jis-x0208@1978
130     =>>gt
131     =+>adobe-japan1
132     =>>adobe-japan1
133     =jis-x0208@1983 =jis-x0208@1978
134     =>ucs-itaiji-001
135     =>ucs-itaiji-002
136     =>ucs-itaiji-005
137     ==>ucs@bucs
138     =big5
139     =>cbeta
140     ===mj
141     ===ucs@iso
142     ===ucs@unicode
143     ===hanyo-denshi/ks
144     ===ks-x1001
145     ===gt
146     ===gt-k
147     ===ucs@ks
148     ===ucs@gb
149     =shinjigen
150     =shinjigen@rev
151     =shinjigen@1ed
152     =shinjigen/+p@rev
153     ==shinjigen
154     ==shinjigen@rev
155     ==daikanwa/+p
156     ==shinjigen@1ed
157     ===daikanwa/+p
158     =>daikanwa/ho
159     ===daikanwa/ho
160     ))
161
162 (defvar chise-turtle-ccs-prefix-alist nil)
163
164 (defun charset-code-point-format-spec (ccs)
165   (cond ((memq ccs '(=ucs))
166          "0x%04X")
167         (t
168          (let ((ccs-name (symbol-name ccs)))
169            (cond
170             ((string-match
171               "\\(shinjigen\\|daikanwa/ho\\|=>iwds-1\\)"
172               ccs-name)
173              "%04d")
174             ((string-match
175               "\\(gt\\|daikanwa\\|adobe-japan1\\|cbeta\\|zinbun-oracle\\|hng\\)"
176               ccs-name)
177              "%05d")
178             ((string-match "\\(hanyo-denshi/ks\\|koseki\\|mj\\)" ccs-name)
179              "%06d")
180             ((string-match "hanyo-denshi/tk" ccs-name)
181              "%08d")
182             (t
183              "0x%X"))))))
184
185 (defun chise-turtle-uri-decode-feature-name (uri-feature)
186   (cond ((string= "a.ucs" uri-feature)
187          '=ucs)
188         ((string= "a.big5" uri-feature)
189          '=big5)
190         (t
191          (www-uri-decode-feature-name uri-feature))))
192
193 (defun chise-turtle-uri-encode-ccs-name (feature-name)
194   (cond
195    ((eq '=ucs feature-name)
196     "a.ucs")
197    ((eq '=big5 feature-name)
198     "a.big5")
199    ((eq '==>ucs@bucs feature-name)
200     "bucs")
201    (t
202     (mapconcat (lambda (c)
203                  (cond
204                   ((eq c ?@)
205                    "_")
206                   ((eq c ?+)
207                    "._.")
208                   ((eq c ?=)
209                    ".:.")
210                   (t
211                    (char-to-string c))))
212                (www-uri-encode-feature-name feature-name)
213                ""))))
214
215 (defun chise-turtle-uri-encode-feature-name (feature-name)
216   (cond
217    ((eq '->subsumptive feature-name)
218     ":subsume")
219    ((eq '<-denotational feature-name)
220     ":denotation-of")
221    ((eq '<-formed feature-name)
222     ":form-of")
223    ((eq '<-same feature-name)
224     "ideo:same-as")
225    ((eq '<-simplified feature-name)
226     "ideo:simplified-form-of")
227    ((eq '<-vulgar feature-name)
228     "ideo:vulgar-form-of")
229    ((eq '<-ancient feature-name)
230     "ideo:ancient-form-of")
231    ((eq '->mistakable feature-name)
232     "ideo:mistakable")
233    ((eq 'hanyu-dazidian feature-name)
234     "ideo:hanyu-dazidian")
235    (t
236     (concat ":" (chise-turtle-uri-encode-ccs-name feature-name)))))
237
238 (defun chise-turtle-format-ccs-code-point (ccs code-point)
239   (let ((ccs-uri (chise-turtle-uri-encode-ccs-name ccs)))
240     (unless (assoc ccs-uri chise-turtle-ccs-prefix-alist)
241       (setq chise-turtle-ccs-prefix-alist
242             (cons (cons ccs-uri ccs)
243                   chise-turtle-ccs-prefix-alist)))
244     (format "%s:%s"
245             ccs-uri
246             (format (charset-code-point-format-spec ccs)
247                     code-point))))
248
249 (defun chise-turtle-encode-char (object)
250   (let ((ccs-list est-coded-charset-priority-list)
251         ccs ret ret2)
252     (if (setq ret (encode-char object '=ucs))
253         (chise-turtle-format-ccs-code-point '=ucs ret)
254       (while (and ccs-list
255                   (setq ccs (pop ccs-list))
256                   (not (setq ret (encode-char object ccs 'defined-only)))))
257       (cond (ret
258              (chise-turtle-format-ccs-code-point ccs ret)
259              )
260             ((and (setq ccs (car (split-char object)))
261                   (setq ret (encode-char object ccs)))
262              (chise-turtle-format-ccs-code-point ccs ret)
263              )
264             ((setq ret (get-char-attribute object 'ideographic-combination))
265              (format "ideocomb:%s"
266                      (mapconcat (lambda (cell)
267                                   (cond ((characterp cell)
268                                          (char-to-string cell)
269                                          )
270                                         ((setq ret2 (find-char cell))
271                                          (char-to-string ret2)
272                                          )
273                                         (t
274                                          (format "%S" cell)
275                                          )))
276                                 ret ""))
277              )
278             (t
279              (format (if est-hide-cgi-mode
280                          "system-char-id=0x%X"
281                        "system-char-id:0x%X")
282                      (encode-char object 'system-char-id))
283              )))))
284
285 (defun chise-split-feature-name (feature-name)
286   (let (base domain number meta)
287     (setq feature-name (symbol-name feature-name))
288     (if (string-match ".\\*." feature-name)
289         (setq meta (intern
290                     (format ":%s" (substring feature-name (1- (match-end 0)))))
291               feature-name (substring feature-name 0 (1+ (match-beginning 0)))))
292     (if (string-match "\\$_\\([0-9]+\\)$" feature-name)
293         (setq number (car (read-from-string (match-string 1 feature-name)))
294               feature-name (substring feature-name 0 (match-beginning 0))))
295     (if (string-match "@" feature-name)
296         (setq domain (car (read-from-string (substring feature-name (match-end 0))))
297               base (intern (substring feature-name 0 (match-beginning 0))))
298       (setq base (intern feature-name)))
299     (list base domain number meta)))
300
301 (defun chise-compose-feature-name (base domain number meta)
302   (let ((name (if domain
303                   (format "%s@%s" base domain)
304                 (symbol-name base))))
305     (if number
306         (setq name (format "%s$_%d" name number)))
307     (if meta
308         (setq name (format "%s*%s" name
309                            (substring (symbol-name meta) 1))))
310     (intern name)))
311
312 (defvar chise-feature-name-base-metadata-alist nil)
313
314 (defun chise-update-feature-name-base-metadata-alist ()
315   (interactive)
316   (let (base domain number metadata
317              bcell dcell ncell ret)
318     (setq chise-feature-name-base-metadata-alist nil)
319     (dolist (fname (sort (char-attribute-list)
320                          #'char-attribute-name<))
321       (setq ret (chise-split-feature-name fname)
322             base (car ret)
323             domain (nth 1 ret)
324             number (nth 2 ret)
325             metadata (nth 3 ret))
326       (when metadata
327         (if (setq bcell (assq base chise-feature-name-base-metadata-alist))
328             (if (setq dcell (assq domain (cdr bcell)))
329                 (if (setq ncell (assq number (cdr dcell)))
330                     (unless (memq metadata (cdr ncell))
331                       (setcdr ncell (nconc (cdr ncell)
332                                            (list metadata))))
333                   (setcdr dcell (cons (list number metadata)
334                                       (cdr dcell))))
335               (setcdr bcell (cons (list domain (list number metadata))
336                                   (cdr bcell))))
337           (setq chise-feature-name-base-metadata-alist
338                 (cons (list base (list domain (list number metadata)))
339                       chise-feature-name-base-metadata-alist))
340           )))))
341
342 (chise-update-feature-name-base-metadata-alist)
343
344 (defun chise-get-char-attribute-with-metadata (character feature-name-base domain)
345   (let ((value (get-char-attribute
346                 character
347                 (chise-compose-feature-name feature-name-base domain nil nil)
348                 '*feature-value-is-empty*))
349         dcell
350         base-metadata metadata
351         ret m i rest dest)
352     (unless (eq value '*feature-value-is-empty*)
353       (cond
354        ((and (setq ret (assq feature-name-base
355                              chise-feature-name-base-metadata-alist))
356              (setq dcell (assq domain (cdr ret))))
357         (if (setq ret (assq nil (cdr dcell)))
358             (dolist (bmn (cdr ret))
359               (when (setq m (get-char-attribute
360                              character
361                              (chise-compose-feature-name
362                               feature-name-base domain nil bmn)))
363                 (setq base-metadata
364                       (list* bmn m base-metadata)))))
365         (setq i 1
366               rest value)
367         (while (consp rest)
368           (setq dest
369                 (cons (cond
370                        ((setq ret (assq i (cdr dcell)))
371                         (setq metadata nil)
372                         (dolist (mn (cdr ret))
373                           (when (setq m (get-char-attribute
374                                          character
375                                          (chise-compose-feature-name
376                                           feature-name-base domain i mn)))
377                             (setq metadata (list* mn m metadata))))
378                         (if metadata
379                             (list* :target (car rest) metadata)
380                           (car rest))
381                         )
382                        (t (car rest)))
383                       dest))
384           (setq i (1+ i)
385                 rest (cdr rest)))
386         (list (nconc (nreverse dest) rest)
387               base-metadata)
388         )
389        (t (list value nil)))
390       )))
391           
392 (defun chise-split-ccs-name (ccs)
393   (cond ((eq ccs '=ucs)
394          '(ucs abstract-character nil)
395          )
396         ((eq ccs '=big5)
397          '(big5 abstract-character nil)
398          )
399         (t
400          (setq ccs (symbol-name ccs))
401          (let (ret)
402            (if (string-match "^\\(=[=+>]*\\)\\([^=>@*]+\\)@?" ccs)
403                (list (intern (match-string 2 ccs))
404                      (chise-decode-ccs-prefix (match-string 1 ccs))
405                      (if (string= (setq ret (substring ccs (match-end 0))) "")
406                          nil
407                        (intern ret))))
408            ))))
409
410 (defun chise-decode-ccs-prefix (ccs)
411   (or (cdr (assoc ccs '(("==>" . super-abstract-character)
412                         ("=>"  . abstract-character)
413                         ("=+>" . unified-glyph)
414                         ("="   . abstract-glyph)
415                         ("=>>" . detailed-glyph)
416                         ("=="  . abstract-glyph-form)
417                         ("===" . glyph-image))))
418       'character))
419
420 (defun chise-turtle-uri-split-ccs (uri-ccs)
421   (cond
422    ((string-match "^a2\\." uri-ccs)
423     (cons ":super-abstract-character"
424           (substring uri-ccs (match-end 0)))
425     )
426    ((string-match "^a\\." uri-ccs)
427     (cons ":abstract-character"
428           (substring uri-ccs (match-end 0)))
429     )
430    ((string-match "^o\\." uri-ccs)
431     (cons ":unified-glyph"
432           (substring uri-ccs (match-end 0)))
433     )
434    ((string-match "^rep\\." uri-ccs)
435     (cons ":abstract-glyph"
436           (substring uri-ccs (match-end 0)))
437     )
438    ((string-match "^g\\." uri-ccs)
439     (cons ":detailed-glyph"
440           (substring uri-ccs (match-end 0)))
441     )
442    ((string-match "^g2\\." uri-ccs)
443     (cons ":abstract-glyph-form"
444           (substring uri-ccs (match-end 0)))
445     )
446    ((string-match "^gi\\." uri-ccs)
447     (cons ":abstract-glyph-form"
448           (substring uri-ccs (match-end 0)))
449     )
450    ((string-match "^repi\\." uri-ccs)
451     (cons ":glyph-image"
452           (substring uri-ccs (match-end 0)))
453     )
454    (t (cons ":character" uri-ccs))))
455
456 (defun char-db-turtle-insert-relation-feature (char name value line-breaking
457                                                     ccss readable)
458   (insert (format "    %s%s        "
459                   (chise-turtle-uri-encode-feature-name name)
460                   line-breaking))
461   (char-db-turtle-insert-relations value readable)
462   (insert " ;")
463   )
464
465 (defun char-db-turtle-insert-metadata (name value)
466   (let (col indent)
467     (insert (format "%-7s " name))
468     (cond
469      ((or (eq name :sources)
470           (eq name :denied))
471       (setq col (current-column))
472       (setq indent (make-string col ?\ ))
473       (insert (format "chisebib:%s"
474                       (chise-turtle-uri-encode-ccs-name (car value))))
475       (dolist (source (cdr value))
476         (insert (format " ,\n%schisebib:%s" indent
477                         (chise-turtle-uri-encode-ccs-name source))))
478       nil)
479      (t
480       (insert (format "%S" value))
481       nil))))
482
483 (defun char-db-turtle-insert-radical (radical-number)
484   (insert (format "        %3d ; # %c"
485                   radical-number
486                   (ideographic-radical radical-number)))
487   'with-separator)
488
489 (defun char-db-turtle-insert-list (value &optional readable)
490   (let (lbs separator rest cell al cal key ret)
491     (insert "( ")
492     (setq lbs (concat "\n" (make-string (current-column) ?\ ))
493           separator nil)
494     (while (consp value)
495       (setq cell (car value))
496       (if (and (consp cell)
497                (consp (car cell))
498                (setq ret (condition-case nil
499                              (find-char cell)
500                            (error nil))))
501           (progn
502             (setq rest cell
503                   al nil
504                   cal nil)
505             (while rest
506               (setq key (car (car rest)))
507               (if (find-charset key)
508                   (setq cal (cons key cal))
509                 (setq al (cons key al)))
510               (setq rest (cdr rest)))
511             (if separator
512                 (insert lbs))
513             (char-db-turtle-insert-char-features ret
514                                                  readable
515                                                  al
516                                                  nil 'for-sub-node)
517             (setq separator lbs))
518         (setq ret (prin1-to-string cell))
519         (if separator
520             (if (< (+ (current-column)
521                       (length ret)
522                       (length separator))
523                    76)
524                 (insert separator)
525               (insert lbs)))
526         (insert ret)
527         (setq separator " "))
528       (setq value (cdr value)))
529     (insert " ) ;")
530     'with-separator))
531
532 (defun char-db-turtle-insert-source-list (value &optional readable)
533   (let (lbs separator rest cell al cal key ret)
534     (setq lbs (concat " ,\n" (make-string (current-column) ?\ ))
535           separator nil)
536     (while (consp value)
537       (setq cell (car value))
538       (if (and (consp cell)
539                (consp (car cell))
540                (setq ret (condition-case nil
541                              (find-char cell)
542                            (error nil))))
543           (progn
544             (setq rest cell
545                   al nil
546                   cal nil)
547             (while rest
548               (setq key (car (car rest)))
549               (if (find-charset key)
550                   (setq cal (cons key cal))
551                 (setq al (cons key al)))
552               (setq rest (cdr rest)))
553             (if separator
554                 (insert lbs))
555             (char-db-turtle-insert-char-features ret
556                                                  readable
557                                                  al
558                                                  nil 'for-sub-node)
559             (setq separator lbs))
560         (setq ret (prin1-to-string cell))
561         (if separator
562             (if (< (+ (current-column)
563                       (length ret)
564                       (length separator))
565                    76)
566                 (insert separator)
567               (insert lbs)))
568         (if (string-match "=" ret)
569             (insert (format "%s:%s"
570                             (substring ret 0 (match-beginning 0))
571                             (substring ret (match-end 0))))
572           (insert (format "chisebib:%s" ret)))
573         (setq separator " , "))
574       (setq value (cdr value)))
575     (insert " ;")
576     'with-separator))
577
578 (defun char-db-turtle-insert-relations (value &optional readable)
579   (let ((lbs (concat "\n" (make-string (current-column) ?\ )))
580         separator cell)
581     (if (characterp value)
582         (setq value (list value)))
583     (while (consp value)
584       (setq cell (car value))
585       (if (integerp cell)
586           (setq cell (decode-char '=ucs cell)))
587       (if separator
588           (insert separator)
589         (setq separator (format " ,%s" lbs)))
590       (if (characterp cell)
591           (insert (format "%-20s" (chise-turtle-encode-char cell)))
592         (char-db-turtle-insert-char-ref cell '<-formed))
593       (setq value (cdr value)))
594     nil))
595
596 (defun char-db-turtle-insert-target-value (value feature-name-base &optional readable)
597   (cond ((eq feature-name-base 'ideographic-radical)
598          (char-db-turtle-insert-radical value)
599          )
600         ((or (eq feature-name-base 'ideographic-combination)
601              (eq feature-name-base '=decomposition)
602              (eq feature-name-base '<-formed)
603              (string-match "^\\(->\\|<-\\)[^*]*$" (symbol-name feature-name-base)))
604          (char-db-turtle-insert-relations value readable)
605          )
606         ((eq feature-name-base 'comment)
607          (insert (format "%S" value))
608          nil)
609         ((eq feature-name-base 'sources)
610          (char-db-turtle-insert-source-list value readable)
611          )
612         ((consp value)
613          (char-db-turtle-insert-list value readable)
614          )
615         (t
616          (insert (format " %-14s" value))
617          nil)))
618
619 (defun char-db-turtle-insert-feature-value (value metadata domain feature-name-base)
620   (let (indent0 indent rest mdname mdval lb)
621     (cond
622      ((or metadata domain)
623       (setq indent0 (make-string (current-column) ?\ ))
624       (insert "[ ")
625       (setq indent (make-string (current-column) ?\ ))
626       (when domain
627         (insert (format ":context domain:%-7s ;"
628                         (chise-turtle-uri-encode-ccs-name domain)))
629         (setq lb t))
630       (setq rest metadata)
631       (while rest
632         (setq mdname (pop rest)
633               mdval  (pop rest))
634         (if lb
635             (insert (format "\n%s" indent))
636           (setq lb t))
637         (unless (char-db-turtle-insert-metadata mdname mdval)
638           (insert " ;")))
639       (if lb
640           (insert (format "\n%s" indent)))
641       (insert ":target  ")
642       (if (char-db-turtle-insert-target-value value feature-name-base)
643           (insert (format "\n%s] ;" indent0))
644         (insert " ] ;"))
645       'with-separator)
646      (t
647       (char-db-turtle-insert-target-value value feature-name-base)
648       ))))
649
650 (defun char-db-turtle-insert-char-ref (char-ref feature-name-base)
651   (let (indent0 indent rest mdname mdval lb last-sep)
652     (setq indent0 (make-string (current-column) ?\ ))
653     (insert "[ ")
654     (setq indent (make-string (current-column) ?\ ))
655     (setq rest char-ref)
656     (while rest
657       (setq mdname (pop rest)
658             mdval  (pop rest))
659       (if lb
660           (insert (format "%s\n%s"
661                           (if last-sep
662                               ""
663                             " ;")
664                           indent))
665         (setq lb t))
666       (setq last-sep
667             (cond ((eq mdname :target)
668                    (insert ":target  ")
669                    (char-db-turtle-insert-target-value mdval feature-name-base)
670                      )
671                   (t
672                    (char-db-turtle-insert-metadata mdname mdval)))))
673     (if last-sep
674         (insert (format "\n%s]" indent0))
675       (insert " ]"))
676     nil))
677   
678 (defun char-db-turtle-insert-char-features (char
679                                             &optional readable attributes column
680                                             for-sub-node)
681   (unless column
682     (setq column (current-column)))
683   (let ((est-coded-charset-priority-list est-coded-charset-priority-list)
684         (est-view-url-prefix "http://chise.org/est/view")
685         id obj-id type domain
686         name value metadata
687         name-base name-domain
688         radical strokes
689         (line-breaking (concat "\n" (make-string column ?\ )))
690         line-separator
691         ret
692         skey
693         dest-ccss ; sources required-features
694         ccss eq-cpos-list
695         uri-ccs uri-cpos ccs-base children child-ccs-list col indent)
696     (let (atr-d)
697       (setq attributes
698             (sort (if attributes
699                       (if (consp attributes)
700                           (progn
701                             (dolist (name attributes)
702                               (unless (or (memq name char-db-ignored-attributes)
703                                           (string-match "\\*" (symbol-name name)))
704                                 (if (find-charset name)
705                                     (push name ccss))
706                                 (push name atr-d)))
707                             atr-d))
708                     (dolist (name (char-attribute-list))
709                       (unless (or (memq name char-db-ignored-attributes)
710                                   (string-match "\\*" (symbol-name name)))
711                         (if (find-charset name)
712                             (push name ccss))
713                         (push name atr-d)))
714                     atr-d)
715                   #'char-attribute-name<)))
716     (setq line-separator line-breaking)
717     (setq id (chise-turtle-encode-char char))
718     (setq obj-id (file-name-nondirectory id))
719     (string-match ":" obj-id)
720     (setq uri-ccs (substring obj-id 0 (match-beginning 0))
721           uri-cpos (substring obj-id (match-end 0)))
722     (insert (format "%s" obj-id))
723     (setq ret (assoc uri-ccs chise-turtle-ccs-prefix-alist))
724     (setq dest-ccss (list (cdr ret)))
725     (setq ret (chise-split-ccs-name (cdr ret)))
726     (setq ccs-base (car ret)
727           type (nth 1 ret)
728           domain (nth 2 ret))
729     (insert (format "%s    a chisegg:%s ;" line-separator type))
730     (insert (format "%s    :%s-of" line-breaking type))
731     (if (null domain)
732         (insert (format " %s:%s ;"
733                         (chise-turtle-uri-encode-ccs-name ccs-base) uri-cpos))
734       (insert " [ ")
735       (setq col (current-column))
736       (insert (format ":context domain:%-7s ;\n%s:target %7s:%-7s ] ;"
737                       (chise-turtle-uri-encode-ccs-name domain)
738                       (make-string col ?\ )
739                       (chise-turtle-uri-encode-ccs-name ccs-base) uri-cpos)))
740     (when (memq '<-subsumptive attributes)
741       (when (or readable (not for-sub-node))
742         (when (setq value (get-char-attribute char '<-subsumptive))
743           (insert line-separator)
744           (char-db-turtle-insert-relation-feature char '<-subsumptive value
745                                                   line-breaking
746                                                   ccss readable)
747           ))
748       (setq attributes (delq '<-subsumptive attributes))
749       )
750     (when (and (memq '<-denotational attributes)
751                (setq value (get-char-attribute char '<-denotational)))
752       (insert line-separator)
753       (char-db-turtle-insert-relation-feature char '<-denotational value
754                                             line-breaking
755                                             ccss readable)
756       (setq attributes (delq '<-denotational attributes)))
757     (when (and (memq '<-denotational@component attributes)
758                (setq value
759                      (get-char-attribute char '<-denotational@component)))
760       (insert line-separator)
761       (char-db-turtle-insert-relation-feature
762        char '<-denotational@component value
763        line-breaking
764        ccss readable)
765       (setq attributes (delq '<-denotational@component attributes)))
766     (when (and (memq 'name attributes)
767                (setq value (get-char-attribute char 'name)))
768       (insert (format "%s    " line-separator))
769       (insert (format
770                (if (> (+ (current-column) (length value)) 48)
771                    ":name %S ;"
772                  ":name                 %S ;")
773                value))
774       (setq attributes (delq 'name attributes))
775       )
776     (when (and (memq 'name* attributes)
777                (setq value (get-char-attribute char 'name*)))
778       (insert line-separator)
779       (insert (format
780                (if (> (+ (current-column) (length value)) 48)
781                    " \"name*\": %S"
782                  " \"name*\":                 %S")
783                value))
784       (setq attributes (delq 'name* attributes))
785       )
786     (when (and (memq 'script attributes)
787                (setq value (get-char-attribute char 'script)))
788       (insert (format "%s    :script\t\t  ( %s ) ;"
789                       line-separator
790                       (mapconcat (lambda (cell)
791                                    (format "script:%s" cell))
792                                  value " ")))
793       (setq attributes (delq 'script attributes))
794       )
795     ;; (dolist (name '(=>ucs =>ucs*))
796     ;;   (when (and (memq name attributes)
797     ;;              (setq value (get-char-attribute char name)))
798     ;;     (insert line-separator)
799     ;;     (insert (format " \"%-20s\":  #x%04X,\t\"_comment\": \"%c\""
800     ;;                     name value (decode-char '=ucs value)))
801     ;;     (setq attributes (delq name attributes))))
802     (when (and (memq '=>ucs attributes)
803                (setq value (get-char-attribute char '=>ucs)))
804       (insert (format "%s    :to.ucs\t\t  a.ucs:0x%04X ; # %c"
805                       line-separator value (decode-char '=ucs value)))
806       (setq attributes (delq '=>ucs attributes))
807       )
808     (when (setq value (get-char-attribute char '=>ucs*))
809       (insert (format "%s    :to.canonical-ucs\ta.ucs:0x%04X ; # %c"
810                       line-separator value (decode-char '=ucs value)))
811       (setq attributes (delq '=>ucs* attributes))
812       )
813     (dolist (name '(=>ucs@gb =>ucs@big5))
814       (when (and (memq name attributes)
815                  (setq value (get-char-attribute char name)))
816         (insert line-separator)
817         (insert (format " \"%-20s\":  #x%04X,\t\"_comment\": \"%c\"%s"
818                         name value
819                         (decode-char (intern
820                                       (concat "="
821                                               (substring
822                                                (symbol-name name) 2)))
823                                      value)
824                         line-breaking))
825         (setq attributes (delq name attributes))
826         ))
827     (when (and (memq 'general-category attributes)
828                (setq value (get-char-attribute char 'general-category)))
829       (insert (format "%s    :general-category     \"%s\" ; # %s"
830                       line-separator value
831                       (cond ((rassoc value unidata-normative-category-alist)
832                              "Normative Category")
833                             ((rassoc value unidata-informative-category-alist)
834                              "Informative Category")
835                             (t
836                              "Unknown Category"))))
837       (setq attributes (delq 'general-category attributes))
838       )
839     (when (and (memq 'bidi-category attributes)
840                (setq value (get-char-attribute char 'bidi-category)))
841       (insert (format "%s    :bidi-category        %S ;"
842                       line-separator
843                       value))
844       (setq attributes (delq 'bidi-category attributes))
845       )
846     (unless (or (not (memq 'mirrored attributes))
847                 (eq (setq value (get-char-attribute char 'mirrored 'empty))
848                     'empty))
849       (insert (format "%s    :mirrored             \"%s\" ;"
850                       line-separator
851                       value))
852       (setq attributes (delq 'mirrored attributes))
853       )
854     (cond
855      ((and (memq 'decimal-digit-value attributes)
856            (setq value (get-char-attribute char 'decimal-digit-value)))
857       (insert (format "%s    :decimal-digit-value  %2d ;"
858                       line-separator value))
859       (setq attributes (delq 'decimal-digit-value attributes))
860       (when (and (memq 'digit-value attributes)
861                  (setq value (get-char-attribute char 'digit-value)))
862         (insert (format "%s    :digit-value\t  %2d ;"
863                         line-separator value))
864         (setq attributes (delq 'digit-value attributes))
865         )
866       (when (and (memq 'numeric-value attributes)
867                  (setq value (get-char-attribute char 'numeric-value)))
868         (insert (format "%s    :numeric-value\t  %2d ;"
869                         line-separator value))
870         (setq attributes (delq 'numeric-value attributes))
871         )
872       )
873      (t
874       (when (and (memq 'digit-value attributes)
875                  (setq value (get-char-attribute char 'digit-value)))
876         (insert line-separator)
877         (insert (format "%s    :digit-value\t  %2d ;"
878                         line-separator value))
879         (setq attributes (delq 'digit-value attributes))
880         )
881       (when (and (memq 'numeric-value attributes)
882                  (setq value (get-char-attribute char 'numeric-value)))
883         (insert line-separator)
884         (insert (format "%s    :numeric-value\t  %2d ;"
885                         line-separator value))
886         (setq attributes (delq 'numeric-value attributes))
887         )))
888     (when (and (memq 'iso-10646-comment attributes)
889                (setq value (get-char-attribute char 'iso-10646-comment)))
890       (insert line-separator)
891       (insert (format "{\"iso-10646-comment\":\t %S}%s"
892                       value
893                       line-breaking))
894       (setq attributes (delq 'iso-10646-comment attributes))
895       )
896     (when (and (memq 'morohashi-daikanwa attributes)
897                (setq value (get-char-attribute char 'morohashi-daikanwa)))
898       (insert line-separator)
899       (insert (format "%s    :morohashi-daikanwa\t  %S ;"
900                       line-separator value))
901       (setq attributes (delq 'morohashi-daikanwa attributes))
902       )
903     (setq radical nil
904           strokes nil)
905     (when (and (memq 'ideographic-radical attributes)
906                (setq value (get-char-attribute char 'ideographic-radical)))
907       (setq radical value)
908       (insert (format "%s    ideo:radical         %3d ; # %c "
909                       line-separator
910                       radical
911                       (ideographic-radical radical)
912                       ))
913       (setq attributes (delq 'ideographic-radical attributes))
914       )
915     (when (and (memq 'shuowen-radical attributes)
916                (setq value (get-char-attribute char 'shuowen-radical)))
917       (insert line-separator)
918       (insert (format " \"shuowen-radical\":\t %S,\t\"_comment\": \"%c\""
919                       value
920                       (shuowen-radical value)))
921       (setq attributes (delq 'shuowen-radical attributes))
922       )
923     (let (key)
924       (dolist (domain
925                (append
926                 char-db-feature-domains
927                 (let (dest domain)
928                   (dolist (feature (char-attribute-list))
929                     (setq feature (symbol-name feature))
930                     (when (string-match
931                            "\\(radical\\|strokes\\)@\\([^@*]+\\)\\(\\*\\|$\\)"
932                            feature)
933                       (setq domain (intern (match-string 2 feature)))
934                      (unless (memq domain dest)
935                        (setq dest (cons domain dest)))))
936                   (sort dest #'string<))))
937         (setq key (intern (format "%s@%s" 'ideographic-radical domain)))
938         (when (and (memq key attributes)
939                    (setq value (get-char-attribute char key)))
940           (setq radical value)
941           (insert (format "%s    ideo:radical           "
942                           line-separator))
943           (char-db-turtle-insert-feature-value value nil domain 'ideographic-radical)
944           (setq attributes (delq key attributes))
945           )
946         (setq key (intern (format "%s@%s" 'ideographic-strokes domain)))
947         (when (and (memq key attributes)
948                    (setq value (get-char-attribute char key)))
949           (setq strokes value)
950           (insert (format "%s    ideo:strokes           [ "
951                           line-separator))
952           (setq col (current-column))
953           (setq indent (make-string col ?\ ))
954           (insert (format ":context domain:%-7s ;\n%s:target  %S"
955                           (chise-turtle-uri-encode-ccs-name domain)
956                           indent strokes))
957           (setq attributes (delq key attributes))
958           (setq skey (intern (format "%s*sources" key)))
959           (when (and (memq skey attributes)
960                      (setq value (get-char-attribute char skey)))
961             (insert (format " ;\n%s:sources (" indent))
962             (setq col (current-column))
963             (setq indent (make-string col ?\ ))
964             (insert (format " chisebib:%s" (car value)))
965             (dolist (cell (cdr value))
966               (insert (format "\n%s chisebib:%s" indent cell)))
967             (insert " )"))
968           (setq attributes (delq skey attributes))
969           (insert " ] ;")
970           )
971         (setq key (intern (format "%s@%s" 'total-strokes domain)))
972         (when (and (memq key attributes)
973                    (setq value (get-char-attribute char key)))
974           (insert (format "%s    ideo:total-strokes     [ "
975                           line-separator))
976           (setq col (current-column))
977           (insert (format ":context domain:%-7s ;\n%s:target  %S"
978                           (chise-turtle-uri-encode-ccs-name domain)
979                           (make-string col ?\ )
980                           value))
981           (setq attributes (delq key attributes))
982           (setq skey (intern (format "%s*sources" key)))
983           (insert " ] ;")
984           )
985         (dolist (feature '(ideographic-radical
986                            ideographic-strokes
987                            total-strokes))
988           (setq key (intern (format "%s@%s*sources" feature domain)))
989           (when (and (memq key attributes)
990                      (setq value (get-char-attribute char key)))
991             (insert line-separator)
992             (insert (format " \"%s\":%s" key line-breaking))
993             (dolist (cell value)
994               (insert (format " %s" cell)))
995             (setq attributes (delq key attributes))
996             ))
997         ))
998     (when (and (memq 'ideographic-strokes attributes)
999                (setq value (get-char-attribute char 'ideographic-strokes)))
1000       (setq strokes value)
1001       (insert (format "%s    ideo:strokes          %2d ;"
1002                       line-separator strokes))
1003       (setq attributes (delq 'ideographic-strokes attributes))
1004       )
1005     (when (and (memq 'kangxi-radical attributes)
1006                (setq value (get-char-attribute char 'kangxi-radical)))
1007       (unless (eq value radical)
1008         (insert line-separator)
1009         (insert (format "{\"kangxi-radical\":\t%S},\t\"_comment\": \"%c\"%s"
1010                         value
1011                         (ideographic-radical value)
1012                         line-breaking))
1013         (or radical
1014             (setq radical value)))
1015       (setq attributes (delq 'kangxi-radical attributes))
1016       )
1017     (when (and (memq 'kangxi-strokes attributes)
1018                (setq value (get-char-attribute char 'kangxi-strokes)))
1019       (unless (eq value strokes)
1020         (insert line-separator)
1021         (insert (format "{\"kangxi-strokes\":\t%S}%s"
1022                         value
1023                         line-breaking))
1024         (or strokes
1025             (setq strokes value)))
1026       (setq attributes (delq 'kangxi-strokes attributes))
1027       )
1028     (when (and (memq 'japanese-strokes attributes)
1029                (setq value (get-char-attribute char 'japanese-strokes)))
1030       (unless (eq value strokes)
1031         (insert line-separator)
1032         (insert (format "{\"japanese-strokes\":\t%S}%s"
1033                         value
1034                         line-breaking))
1035         (or strokes
1036             (setq strokes value)))
1037       (setq attributes (delq 'japanese-strokes attributes))
1038       )
1039     (when (and (memq 'cns-radical attributes)
1040                (setq value (get-char-attribute char 'cns-radical)))
1041       (insert line-separator)
1042       (insert (format "{\"cns-radical\":\t%S},\t\"_comment\": \"%c\"%s"
1043                       value
1044                       (ideographic-radical value)
1045                       line-breaking))
1046       (setq attributes (delq 'cns-radical attributes))
1047       )
1048     (when (and (memq 'cns-strokes attributes)
1049                (setq value (get-char-attribute char 'cns-strokes)))
1050       (unless (eq value strokes)
1051         (insert line-separator)
1052         (insert (format "{\"cns-strokes\":\t%S}%s"
1053                         value
1054                         line-breaking))
1055         (or strokes
1056             (setq strokes value)))
1057       (setq attributes (delq 'cns-strokes attributes))
1058       )
1059     (when (and (memq 'total-strokes attributes)
1060                (setq value (get-char-attribute char 'total-strokes)))
1061       (insert (format "%s    ideo:total-strokes    %2d ;"
1062                       line-separator value))
1063       (setq attributes (delq 'total-strokes attributes))
1064       )
1065     (if (equal (get-char-attribute char '->titlecase)
1066                (get-char-attribute char '->uppercase))
1067         (setq attributes (delq '->titlecase attributes)))
1068     (unless readable
1069       (dolist (ignored '(composition
1070                          ->denotational <-subsumptive ->ucs-unified
1071                          ->ideographic-component-forms))
1072         (setq attributes (delq ignored attributes))))
1073     (while attributes
1074       (setq name (car attributes))
1075       (setq ret (chise-split-feature-name name))
1076       (setq name-base (car ret)
1077             name-domain (nth 1 ret))
1078       (when (setq value (chise-get-char-attribute-with-metadata
1079                          char name-base name-domain))
1080         (setq metadata (nth 1 value)
1081               value (car value))
1082         (cond ((setq ret (find-charset name))
1083                (setq name (charset-name ret))
1084                (when (not (memq name dest-ccss))
1085                  (setq dest-ccss (cons name dest-ccss))
1086                  (if (null value)
1087                      (insert (format "%s    :%-25s rdf:nil ;" line-separator
1088                                      (chise-turtle-uri-encode-ccs-name name)))
1089                    (setq ret (chise-turtle-format-ccs-code-point name value))
1090                    (insert (format "%s    :eq %-25s ; # %c" line-separator
1091                                    ret
1092                                    (char-db-decode-isolated-char name value)))
1093                    (setq eq-cpos-list (cons (list ret name value) eq-cpos-list))))
1094                (if (find-charset
1095                     (setq ret (if (eq name '=ucs)
1096                                   (if (< value #x10000)
1097                                       '==ucs@unicode
1098                                     '==ucs@iso)
1099                                 (intern (format "=%s" name)))))
1100                    (setq child-ccs-list (cons ret child-ccs-list)))
1101                )
1102               ((and
1103                 (not readable)
1104                 (not (eq name '->subsumptive))
1105                 (not (eq name '->uppercase))
1106                 (not (eq name '->lowercase))
1107                 (not (eq name '->titlecase))
1108                 (not (eq name '->canonical))
1109                 (not (eq name '->Bopomofo))
1110                 (not (eq name '->mistakable))
1111                 (not (eq name '->ideographic-variants))
1112                 (or (eq name '<-identical)
1113                     (eq name '<-uppercase)
1114                     (eq name '<-lowercase)
1115                     (eq name '<-titlecase)
1116                     (eq name '<-canonical)
1117                     (eq name '<-ideographic-variants)
1118                     ;; (eq name '<-synonyms)
1119                     (string-match "^<-synonyms" (symbol-name name))
1120                     (eq name '<-mistakable)
1121                     (when (string-match "^->" (symbol-name name))
1122                       (cond
1123                        ((string-match "^->fullwidth" (symbol-name name))
1124                         (not (and (consp value)
1125                                   (characterp (car value))
1126                                   (encode-char
1127                                    (car value) '=ucs 'defined-only)))
1128                         )
1129                        (t)))
1130                     ))
1131                )
1132               ((eq name 'ideographic-structure)
1133                (insert (isd-turtle-format-char nil nil value (/ column 4)
1134                                                'isd 'without-head-char))
1135                (insert " ;")
1136                )
1137               ((eq name '->subsumptive)
1138                (insert line-separator)
1139                (char-db-turtle-insert-relation-feature char name value
1140                                                        line-breaking
1141                                                        ccss readable)
1142                (setq children value)
1143                )
1144               (t
1145                (insert (format "%s    %-20s "
1146                                line-separator
1147                                (chise-turtle-uri-encode-feature-name name-base)))
1148                (unless (char-db-turtle-insert-feature-value
1149                         value metadata name-domain name-base)
1150                  (insert " ;"))
1151                )
1152               ))
1153       (setq attributes (cdr attributes)))
1154     (insert (format "%s    ." line-breaking))
1155     (dolist (eq-cpos (nreverse eq-cpos-list))
1156       (setq ret (chise-split-ccs-name (nth 1 eq-cpos)))
1157       (insert (format "%s    %s" line-breaking
1158                       (car eq-cpos)))
1159       (insert (format "%s        %25s" line-breaking
1160                       (format ":%s-of" (nth 1 ret))))
1161       (if (null (nth 2 ret))
1162           (insert (format " %14s:%-7s ."
1163                           (chise-turtle-uri-encode-ccs-name (car ret))
1164                           (nth 1 (split-string (car eq-cpos) ":"))))
1165         (insert " [ ")
1166         (setq col (current-column))
1167         (insert (format ":context domain:%-7s ;\n%s:target %7s:%-7s ] ."
1168                         (chise-turtle-uri-encode-ccs-name (nth 2 ret))
1169                         (make-string col ?\ )
1170                         (chise-turtle-uri-encode-ccs-name (car ret))
1171                         (nth 1 (split-string (car eq-cpos) ":"))))))
1172     (setq est-coded-charset-priority-list
1173           (append est-coded-charset-priority-list
1174                   (nreverse child-ccs-list)))
1175     (when children
1176       (dolist (child children)
1177         (insert (format "%s    " line-breaking))
1178         (char-db-turtle-insert-char-features child nil nil nil 'for-sub-node)))
1179     ))
1180
1181 (defun char-db-turtle-insert-char-data (char &optional readable attributes)
1182   (save-restriction
1183     (narrow-to-region (point)(point))
1184     (char-db-turtle-insert-char-features char readable attributes)
1185     (insert "\n\n")
1186     ))
1187
1188 (defun char-db-turtle-insert-prefix ()
1189   (let (base-ccs-list ret)
1190     (insert "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
1191 @prefix : <http://rdf.chise.org/rdf/property/character/main/> .
1192 @prefix ideo: <http://rdf.chise.org/rdf/property/character/ideo/> .
1193 @prefix isd: <http://rdf.chise.org/rdf/property/character/isd/> .
1194 @prefix idc: <http://rdf.chise.org/rdf/type/character/idc/> .
1195 @prefix chisegg: <http://rdf.chise.org/rdf/type/character/ggg/> .
1196 @prefix domain: <http://rdf.chise.org/data/domain/> .
1197 @prefix script: <http://rdf.chise.org/data/script/> .
1198 @prefix ideocomb: <http://rdf.chise.org/data/character/ideo/combination/> .
1199 @prefix chisebib: <http://rdf.chise.org/data/bibliography/> .
1200 @prefix ruimoku: <http://www.chise.org/est/view/article@ruimoku/rep.id=/> .
1201 @prefix zob1959: <http://chise.zinbun.kyoto-u.ac.jp/koukotsu/rubbings/> .
1202
1203 ")
1204     (dolist (cell (sort chise-turtle-ccs-prefix-alist
1205                         (lambda (a b)
1206                           (char-attribute-name< (cdr a)(cdr b)))))
1207       (insert (format "@prefix %s: <%s/%s=> .\n"
1208                       (car cell)
1209                       "http://www.chise.org/est/view/character"
1210                       (www-uri-encode-feature-name (cdr cell))))
1211       (setq ret (chise-split-ccs-name (cdr cell)))
1212       (unless (memq (car ret) base-ccs-list)
1213         (setq base-ccs-list (cons (car ret) base-ccs-list))))
1214     (insert "\n")
1215     (dolist (base-ccs (nreverse base-ccs-list))
1216       (insert (format "@prefix %s: <%s/%s/code-point/> .\n"
1217                       (chise-turtle-uri-encode-ccs-name base-ccs)
1218                       "http://rdf.chise.org/data/ccs"
1219                       (www-uri-encode-feature-name base-ccs))))))
1220
1221 (defun char-db-turtle-insert-ideograph-radical-char-data (radical)
1222   (let ((chars
1223          (sort (copy-list (aref ideograph-radical-chars-vector radical))
1224                (lambda (a b)
1225                  (ideograph-char< a b radical))))
1226         attributes)
1227     (dolist (name (char-attribute-list))
1228       (unless (memq name char-db-ignored-attributes)
1229         (push name attributes)
1230         ))
1231     (setq attributes (sort attributes #'char-attribute-name<))
1232     (aset ideograph-radical-chars-vector radical chars)
1233     (dolist (char chars)
1234       (when (not (some (lambda (atr)
1235                          (get-char-attribute char atr))
1236                        char-db-ignored-attributes))
1237         (char-db-turtle-insert-char-data char nil attributes)))
1238     ))
1239
1240 (defun char-db-turtle-write-ideograph-radical-char-data (radical file)
1241   (if (file-directory-p file)
1242       (let ((name (char-feature (decode-char 'ucs (+ #x2EFF radical))
1243                                 'name)))
1244         (if (string-match "KANGXI RADICAL " name)
1245             (setq name (capitalize (substring name (match-end 0)))))
1246         (setq name (mapconcat (lambda (char)
1247                                 (if (eq char ? )
1248                                     "-"
1249                                   (char-to-string char))) name ""))
1250         (setq file
1251               (expand-file-name
1252                (format "Ideograph-R%03d-%s.ttl" radical name)
1253                file))))
1254   (let (chise-turtle-ccs-prefix-alist)
1255     (with-temp-buffer
1256       (char-db-turtle-insert-ideograph-radical-char-data radical)
1257       (goto-char (point-min))
1258       (char-db-turtle-insert-prefix)
1259       (insert "\n")
1260       (goto-char (point-min))
1261       (insert (format "# -*- coding: %s -*-\n"
1262                       char-db-file-coding-system))
1263       (let ((coding-system-for-write char-db-file-coding-system))
1264         (write-region (point-min)(point-max) file)))))
1265
1266
1267 ;;; @ end
1268 ;;;
1269
1270 (provide 'char-db-turtle)
1271
1272 ;;; char-db-turtle.el ends here