1 ;;; ideograph-util.el --- Ideographic Character Database utility
3 ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008,
4 ;; 2009, 2010, 2012, 2014, 2015 MORIOKA Tomohiko.
6 ;; Author: MORIOKA Tomohiko <tomo@kanji.zinbun.kyoto-u.ac.jp>
7 ;; Keywords: CHISE, Chaon model, ISO/IEC 10646, Unicode, UCS-4, MULE.
9 ;; This file is part of XEmacs CHISE.
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.
16 ;; XEmacs CHISE is distributed in the hope that it will be useful, but
17 ;; 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.
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.
29 (require 'ideograph-subr)
30 (require 'char-db-util)
33 (defvar ideograph-radical-chars-vector
34 (make-vector 215 nil))
38 (defun update-ideograph-radical-table ()
40 (let (ret rret radical script dest)
42 (cons 'ideographic-radical
44 (dolist (feature (char-attribute-list))
45 (if (string-match "^ideographic-radical@[^@*]+$"
46 (symbol-name feature))
47 (setq dest (cons feature dest))))
53 (get-char-attribute chr '<-subsumptive))
58 (unless (eq (get-char-attribute
59 pc 'ideographic-radical)
64 (setq ret (append ret (list rret)))
65 (setq dest (cons pc dest)))))
69 (get-char-attribute chr '<-identical)
70 (get-char-attribute chr '->denotational)))
76 (setq rest (cdr rest))
77 (setq dest (cons pc dest))
83 pc '->denotational)))))
87 (or (get-char-attribute
88 char 'ideographic-radical)
89 (char-ideographic-radical char radical)))
90 (null (char-ideographic-radical char)))
91 (or (null (setq script
92 (get-char-attribute char 'script)))
93 (memq 'Ideograph script)))
96 (aref ideograph-radical-chars-vector
98 (char-ideographic-strokes char)
99 (aset ideograph-radical-chars-vector radical
106 (setq radical (plist-get cell :radical))
108 (or (null (setq script (get-char-attribute char 'script)))
109 (memq 'Ideograph script)))
112 (aref ideograph-radical-chars-vector radical)))
113 (char-ideographic-strokes char)
114 (aset ideograph-radical-chars-vector radical
119 (defun int-list< (a b)
120 (if (numberp (car a))
121 (if (numberp (car b))
122 (if (= (car a) (car b))
123 (int-list< (cdr a)(cdr b))
128 (if (numberp (car b))
134 (defun morohashi-daikanwa< (a b)
139 (cond ((eq (car-safe a) 'ho)
140 (if (eq (car-safe b) 'ho)
141 (int-list< (cdr-safe a)(cdr-safe b))
149 (if (eq (car-safe b) 'ho)
153 ;; (defun nil=-int< (a b)
154 ;; (cond ((null a) nil)
158 ;; (defun nil>-int< (a b)
159 ;; (cond ((null a) nil)
163 (defvar ideographic-radical nil)
166 (defun char-representative-of-daikanwa (char &optional radical
167 ignore-default checked)
169 (setq radical ideographic-radical))
170 (if (or (null radical)
171 (eq (or (get-char-attribute char 'ideographic-radical)
172 (char-ideographic-radical char radical t))
174 (let ((ret (or (encode-char char '=daikanwa@rev2 'defined-only)
175 (encode-char char '=daikanwa/+p 'defined-only)
176 (encode-char char '=daikanwa/+2p 'defined-only)
177 (encode-char char '=daikanwa/ho 'defined-only)
180 (if (setq ret (get-char-attribute char 'morohashi-daikanwa))
181 (let ((m-m (car ret))
185 (or (decode-char '=daikanwa@rev2 m-m 'defined-only)
186 (decode-char '=daikanwa m-m))
187 (or (cond ((eq m-m 'ho)
188 (decode-char '=daikanwa/ho m-s))
190 (decode-char '=daikanwa/+p m-m))
192 (decode-char '=daikanwa/+2p m-m)))
194 (setq pat (list m-m m-s))
195 (map-char-attribute (lambda (c v)
198 'morohashi-daikanwa))))))
199 (and (setq ret (get-char-attribute char '=>daikanwa))
201 (or (decode-char '=daikanwa@rev2 ret 'defined-only)
202 (decode-char '=daikanwa ret))
203 (map-char-attribute (lambda (c v)
206 'morohashi-daikanwa)))
207 (unless (memq char checked)
210 (append (get-char-attribute char '->subsumptive)
211 (get-char-attribute char '->denotational)))
214 (setq checked (cons char checked))
217 (if (setq ret (char-representative-of-daikanwa
218 sc radical t checked))
220 (setq checked (cons sc checked)
223 (setq rest (get-char-attribute char '->identical))
226 (when (setq ret (char-representative-of-daikanwa
227 sc radical t checked))
229 (setq checked (cons sc checked)
232 (append (if (setq ret (get-char-attribute
233 char '<-subsumptive))
235 (if (setq ret (get-char-attribute
236 char '<-denotational))
240 (when (setq ret (char-representative-of-daikanwa
241 sc radical t checked))
243 (setq checked (cons sc checked)
245 (unless ignore-default
248 (defun char-attributes-poly< (c1 c2 accessors testers defaulters)
250 (let (a1 a2 accessor tester dm)
251 (while (and accessors testers)
252 (setq accessor (car accessors)
255 (when (and accessor tester)
256 (setq a1 (funcall accessor c1)
257 a2 (funcall accessor c2))
270 (cond ((funcall tester a1 a2)
272 ((funcall tester a2 a1)
273 (throw 'tag nil))))))
274 (setq accessors (cdr accessors)
275 testers (cdr testers)
276 defaulters (cdr defaulters))))))
278 (defun char-daikanwa-radical (char &optional radical ignore-sisters)
279 (or (and (encode-char char '=daikanwa@rev2 'defined-only)
280 (or (get-char-attribute char 'ideographic-radical@daikanwa)
281 (get-char-attribute char 'ideographic-radical)))
282 (char-ideographic-radical char radical ignore-sisters)))
284 (defun char-daikanwa-strokes (char &optional radical)
286 (setq radical ideographic-radical))
287 (let ((drc (char-representative-of-daikanwa char radical))
288 (r (char-ideographic-radical char radical)))
291 (= (char-ideographic-radical drc radical) r)))
293 (char-ideographic-strokes char radical '(daikanwa)))
296 (defun char-daikanwa (char &optional radical checked depth)
298 (setq radical ideographic-radical))
299 (if (or (null radical)
300 (eq (or (get-char-attribute char 'ideographic-radical)
301 (char-daikanwa-radical char radical t))
303 (let ((ret (or (encode-char char '=daikanwa@rev2 'defined-only)
304 ;; (encode-char char '=daikanwa 'defined-only)
305 (get-char-attribute char 'morohashi-daikanwa))))
308 ((setq ret (encode-char char '=daikanwa/+p 'defined-only))
309 (setq ret (list ret 1)))
310 ((setq ret (encode-char char '=daikanwa/+2p 'defined-only))
311 (setq ret (list ret 2)))
312 ((setq ret (encode-char char '=daikanwa/ho 'defined-only))
313 (setq ret (list 'ho ret)))))
318 (append ret (list depth)))
320 (and (setq ret (get-char-attribute char '=>daikanwa))
323 (append ret '(-10))))
324 (unless (memq char checked)
330 (get-char-attribute char '->subsumptive)
331 (get-char-attribute char '->denotational)
332 (get-char-attribute char '->denotational@component)
336 (setq checked (cons char checked))
339 (if (setq ret (char-daikanwa sc radical checked
342 (setq checked (cons sc checked)
345 (setq rest (get-char-attribute char '->identical))
348 (when (setq ret (char-daikanwa sc radical checked depth))
352 (append ret (list i)))))
353 (setq checked (cons sc checked)
357 (if (setq ret (get-char-attribute
358 char '<-subsumptive))
360 (if (setq ret (get-char-attribute
361 char '<-denotational))
363 (get-char-attribute char '<-denotational@component)
367 (when (setq ret (char-daikanwa sc radical checked depth))
371 (if (>= (setq lnum (car (last ret))) 0)
372 (append ret (list i))
374 (list 0 (- lnum) i))))))
375 (setq checked (cons sc checked)
376 rest (cdr rest))))))))))
378 (defun char-ideographic-strokes-diff (char &optional radical)
379 (if (or (get-char-attribute char '<-subsumptive)
380 (get-char-attribute char '<-denotational))
382 (when (and (setq s (char-ideographic-strokes char radical))
383 (setq ds (char-daikanwa-strokes char radical)))
388 (defun ideograph-char< (a b &optional radical)
389 (let ((ideographic-radical (or radical
390 ideographic-radical)))
391 (char-attributes-poly<
393 '(char-daikanwa-strokes char-daikanwa char-ucs
394 char-ideographic-strokes-diff char-id)
395 '(< morohashi-daikanwa< < < <)
398 (defun insert-ideograph-radical-char-data (radical)
400 (sort (copy-list (aref ideograph-radical-chars-vector radical))
402 (ideograph-char< a b radical))))
405 (dolist (name (char-attribute-list))
406 (unless (memq name char-db-ignored-attributes)
407 ;; (if (find-charset name)
409 (push name attributes)
412 (setq attributes (sort attributes #'char-attribute-name<)
413 ;; ccss (sort ccss #'char-attribute-name<)
415 (aset ideograph-radical-chars-vector radical chars)
418 (not (some (lambda (atr)
419 (get-char-attribute char atr))
420 char-db-ignored-attributes))
421 ;; (some (lambda (ccs)
422 ;; (encode-char char ccs 'defined-only))
425 (insert-char-data char nil attributes ;ccss
428 (defun write-ideograph-radical-char-data (radical file)
429 (if (file-directory-p file)
430 (let ((name (char-feature (decode-char 'ucs (+ #x2EFF radical))
432 (if (string-match "KANGXI RADICAL " name)
433 (setq name (capitalize (substring name (match-end 0)))))
434 (setq name (mapconcat (lambda (char)
437 (char-to-string char))) name ""))
440 (format "Ideograph-R%03d-%s.el" radical name)
443 (insert (format ";; -*- coding: %s -*-\n"
444 char-db-file-coding-system))
445 (insert-ideograph-radical-char-data radical)
446 (let ((coding-system-for-write char-db-file-coding-system))
447 (write-region (point-min)(point-max) file))))
449 (defun ideographic-structure= (char1 char2)
450 (if (char-ref-p char1)
451 (setq char1 (plist-get char1 :char)))
452 (if (char-ref-p char2)
453 (setq char2 (plist-get char2 :char)))
454 (let ((s1 (if (characterp char1)
455 (get-char-attribute char1 'ideographic-structure)
456 (cdr (assq 'ideographic-structure char1))))
457 (s2 (if (characterp char2)
458 (get-char-attribute char2 'ideographic-structure)
459 (cdr (assq 'ideographic-structure char2))))
461 (if (or (null s1)(null s2))
462 (char-spec= char1 char2)
467 (unless (ideographic-structure= e1 e2)
471 (and (null s1)(null s2))))))
474 (defun ideographic-structure-find-char (structure)
476 (map-char-attribute (lambda (char value)
477 (setq rest structure)
479 (while (and rest value)
480 (unless (ideographic-structure=
481 (car rest)(car value))
483 (setq rest (cdr rest)
485 (unless (or rest value)
487 'ideographic-structure)))
490 (provide 'ideograph-util)
492 ;;; ideograph-util.el ends here