(ideographic-structure-compare-functional-and-apparent):
[chise/ids.git] / ids-find.el
1 ;;; ids-find.el --- search utility based on Ideographic-structures ;; -*- coding: utf-8-mcs-er -*-
2
3 ;; Copyright (C) 2002, 2003, 2005, 2006, 2007, 2017, 2020 MORIOKA Tomohiko
4
5 ;; Author: MORIOKA Tomohiko <tomo@kanji.zinbun.kyoto-u.ac.jp>
6 ;; Keywords: Kanji, Ideographs, search, IDS, CHISE, UCS, Unicode
7
8 ;; This file is a part of CHISE-IDS.
9
10 ;; This program 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 ;; This program is distributed in the hope that it will be useful, but
16 ;; 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 this program; 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 (defun ids-index-store-char (product component)
28   (let ((ret (get-char-attribute component 'ideographic-products)))
29     (unless (memq product ret)
30       (put-char-attribute component 'ideographic-products
31                           (cons product ret))
32       (when (setq ret (char-feature component 'ideographic-structure))
33         (ids-index-store-structure product ret)))
34     ))
35
36 (defun ids-index-store-structure (product structure)
37   (let (ret)
38     (dolist (cell (cdr structure))
39       (if (char-ref-p cell)
40           (setq cell (plist-get cell :char)))
41       (cond ((characterp cell)
42              (ids-index-store-char product cell))
43             ((setq ret (assq 'ideographic-structure cell))
44              (ids-index-store-structure product (cdr ret)))
45             ((setq ret (find-char cell))
46              (ids-index-store-char product ret))
47             ))))
48
49 ;;;###autoload
50 (defun ids-update-index (&optional in-memory)
51   (interactive)
52   (map-char-attribute
53    (lambda (c v)
54      (ids-index-store-structure c v)
55      nil)
56    'ideographic-structure)
57   (map-char-attribute
58    (lambda (c v)
59      (ids-index-store-structure c v)
60      nil)
61    'ideographic-structure@apparent)
62   (unless in-memory
63     (save-char-attribute-table 'ideographic-products)))
64
65
66 (mount-char-attribute-table 'ideographic-products)
67
68 ;;;###autoload
69 (defun ids-find-all-products (char)
70   (let (dest)
71     (dolist (cell (char-feature char 'ideographic-products))
72       (unless (memq cell dest)
73         (setq dest (cons cell dest)))
74       (setq dest (union dest (ids-find-all-products cell))))
75     dest))
76
77 (defun of-component-features ()
78   (let (dest)
79     (dolist (feature (char-attribute-list))
80       (when (string-match "^<-.*[@/]component\\(/[^*/]+\\)*$"
81                           (symbol-name feature))
82         (push feature dest)))
83     (list* '<-mistakable '->mistakable
84            '<-formed '->formed
85            '<-same '->same
86            '<-original '->original
87            '<-ancient '->ancient
88            dest)))
89
90 (defun to-component-features ()
91   (let (dest)
92     (dolist (feature (char-attribute-list))
93       (when (string-match "^->.*[@/]component\\(/[^*/]+\\)*$"
94                           (symbol-name feature))
95         (push feature dest)))
96     dest))
97
98 ;;;###autoload
99 (defun char-component-variants (char)
100   (let ((dest (list char))
101         ret uchr)
102     (dolist (feature (to-component-features))
103       (if (setq ret (get-char-attribute char feature))
104           (dolist (c ret)
105             (setq dest (union dest (char-component-variants c))))))
106     (cond
107      ;; ((setq ret (some (lambda (feature)
108      ;;                    (get-char-attribute char feature))
109      ;;                  (to-component-features)))
110      ;;  (dolist (c ret)
111      ;;    (setq dest (union dest (char-component-variants c))))
112      ;;  )
113      ((setq ret (get-char-attribute char '->ucs-unified))
114       (setq dest (cons char ret))
115       (dolist (c dest)
116         (setq dest (union dest
117                           (some (lambda (feature)
118                                   (get-char-attribute c feature))
119                                 (of-component-features))
120                           )))
121       )
122      ((and (setq ret (get-char-attribute char '=>ucs))
123            (setq uchr (decode-char '=ucs ret)))
124       (setq dest (cons uchr (char-variants uchr)))
125       (dolist (c dest)
126         (setq dest (union dest
127                           (some (lambda (feature)
128                                   (get-char-attribute c feature))
129                                 (of-component-features))
130                           )))
131       )
132      (t
133       (map-char-family
134        (lambda (c)
135          (unless (memq c dest)
136            (setq dest (cons c dest)))
137          (setq dest
138                (union dest
139                       (some (lambda (feature)
140                               (char-feature c feature))
141                             (of-component-features))
142                       ))
143          nil)
144        char)
145       ))
146     dest))
147
148 ;;;###autoload
149 (defun ideographic-products-find (&rest components)
150   (if (stringp (car components))
151       (setq components (string-to-char-list (car components))))
152   (let (dest products)
153     (dolist (variant (char-component-variants (car components)))
154       (setq products
155             (union products
156                    (get-char-attribute variant 'ideographic-products))))
157     (setq dest products)
158     (while (and dest
159                 (setq components (cdr components)))
160       (setq products nil)
161       (dolist (variant (char-component-variants (car components)))
162         (setq products
163               (union products
164                      (get-char-attribute variant 'ideographic-products))))
165       (setq dest (intersection dest products)))
166     dest))
167
168 (defun ideograph-find-products-with-variants (components &optional ignored-chars)
169   (if (stringp components)
170       (setq components (string-to-char-list components)))
171   (let (dest products)
172     (dolist (variant (char-component-variants (car components)))
173       (setq products
174             (union products
175                    (set-difference
176                     (get-char-attribute variant 'ideographic-products)
177                     ignored-chars))))
178     (setq dest products)
179     (while (and dest
180                 (setq components (cdr components)))
181       (setq products nil)
182       (dolist (variant (char-component-variants (car components)))
183         (setq products
184               (union products
185                      (set-difference
186                       (get-char-attribute variant 'ideographic-products)
187                       ignored-chars))))
188       (setq dest (intersection dest products)))
189     dest))
190
191 (defun ideograph-find-products (components &optional ignored-chars)
192   (if (stringp components)
193       (setq components (string-to-char-list components)))
194   (let (dest products)
195     ;; (dolist (variant (char-component-variants (car components)))
196     ;;   (setq products
197     ;;         (union products
198     ;;                (get-char-attribute variant 'ideographic-products))))
199     ;; (setq dest products)
200     (setq dest (get-char-attribute (car components) 'ideographic-products))
201     (while (and dest
202                 (setq components (cdr components)))
203       ;; (setq products nil)
204       ;; (dolist (variant (char-component-variants (car components)))
205       ;;   (setq products
206       ;;         (union products
207       ;;                (get-char-attribute variant 'ideographic-products))))
208       (setq products (get-char-attribute (car components) 'ideographic-products))
209       (setq dest (intersection dest products)))
210     dest))
211
212
213 (defun ideographic-structure-char= (c1 c2)
214   (or (eq c1 c2)
215       (and c1 c2
216            (let ((m1 (char-ucs c1))
217                  (m2 (char-ucs c2)))
218              (or (and m1 m2
219                       (eq m1 m2))
220                  (memq c1 (char-component-variants c2)))))))
221
222 (defun ideographic-structure-member-compare-components (component s-component)
223   (let (ret)
224     (cond ((char-ref= component s-component #'ideographic-structure-char=))
225           ((listp s-component)
226            (if (setq ret (assq 'ideographic-structure s-component))
227                (ideographic-structure-member component (cdr ret))))
228           ((setq ret (get-char-attribute s-component 'ideographic-structure))
229            (ideographic-structure-member component ret)))))
230
231 ;;;###autoload
232 (defun ideographic-structure-member (component structure)
233   "Return non-nil if COMPONENT is included in STRUCTURE."
234   (or (memq component structure)
235       (progn
236         (setq structure (cdr structure))
237         (ideographic-structure-member-compare-components
238          component (car structure)))
239       (progn
240         (setq structure (cdr structure))
241         (ideographic-structure-member-compare-components
242          component (car structure)))
243       (progn
244         (setq structure (cdr structure))
245         (and (car structure)
246              (ideographic-structure-member-compare-components
247               component (car structure))))))
248
249
250 ;;;###autoload
251 (defun ideographic-structure-repertoire-p (structure components)
252   "Return non-nil if STRUCTURE can be constructed by a subset of COMPONENTS."
253   (and structure
254        (let (ret s-component)
255          (catch 'tag
256            (while (setq structure (cdr structure))
257              (setq s-component (car structure))
258              (unless (characterp s-component)
259                (if (setq ret (find-char s-component))
260                    (setq s-component ret)))
261              (unless (cond
262                       ((listp s-component)
263                        (if (setq ret (assq 'ideographic-structure s-component))
264                            (ideographic-structure-repertoire-p
265                             (cdr ret) components)))
266                       ((member* s-component components
267                                 :test #'ideographic-structure-char=))
268                       ((setq ret
269                              (get-char-attribute s-component
270                                                  'ideographic-structure))
271                        (ideographic-structure-repertoire-p ret components)))
272                (throw 'tag nil)))
273            t))))
274
275
276 (defvar ids-find-result-buffer "*ids-chars*")
277
278 (defun ids-find-format-line (c v)
279   (format "%c\t%s\t%s\n"
280           c
281           (or (let ((ucs (or (char-ucs c)
282                              (encode-char c 'ucs))))
283                 (if ucs
284                     (cond ((<= ucs #xFFFF)
285                            (format "    U+%04X" ucs))
286                           ((<= ucs #x10FFFF)
287                            (format "U-%08X" ucs)))))
288               "          ")
289           (or (ideographic-structure-to-ids v)
290               v)))
291
292 (defun ids-insert-chars-including-components* (components
293                                                &optional level ignored-chars)
294   (unless level
295     (setq level 0))
296   (let (is i as bs)
297     (dolist (c (sort (copy-list (ideograph-find-products components
298                                                          ignored-chars))
299                      (lambda (a b)
300                        (if (setq as (char-total-strokes a))
301                            (if (setq bs (char-total-strokes b))
302                                (if (= as bs)
303                                    (ideograph-char< a b)
304                                  (< as bs))
305                              t)
306                          (ideograph-char< a b)))))
307       (unless (memq c ignored-chars)
308         (setq is (char-feature c 'ideographic-structure))
309         (setq i 0)
310         (while (< i level)
311           (insert "\t")
312           (setq i (1+ i)))
313         (insert (ids-find-format-line c is))
314         (setq ignored-chars
315               (ids-insert-chars-including-components*
316                (char-to-string c) (1+ level)
317                (cons c ignored-chars))))
318       )
319     )
320   ignored-chars)
321
322 (defun ids-insert-chars-including-components (components
323                                               &optional level ignored-chars)
324   (unless level
325     (setq level 0))
326   (setq ignored-chars
327         (nreverse
328          (ids-insert-chars-including-components* components
329                                                  level ignored-chars)))
330   (let (is i as bs)
331     (dolist (c ignored-chars)
332       (dolist (vc (char-component-variants c))
333         (unless (memq vc ignored-chars)
334           (when (setq is (get-char-attribute vc 'ideographic-structure))
335             (setq i 0)
336             (while (< i level)
337               (insert "\t")
338               (setq i (1+ i)))
339             (insert (ids-find-format-line vc is))
340             (setq ignored-chars
341                   (ids-insert-chars-including-components*
342                    (char-to-string vc) (1+ level)
343                    (cons vc ignored-chars)))))))
344     (dolist (c (sort (copy-list (ideograph-find-products-with-variants
345                                  components ignored-chars))
346                      (lambda (a b)
347                        (if (setq as (char-total-strokes a))
348                            (if (setq bs (char-total-strokes b))
349                                (if (= as bs)
350                                    (ideograph-char< a b)
351                                  (< as bs))
352                              t)
353                          (ideograph-char< a b)))))
354       (unless (memq c ignored-chars)
355         (setq is (get-char-attribute c 'ideographic-structure))
356         (setq i 0)
357         (while (< i level)
358           (insert "\t")
359           (setq i (1+ i)))
360         (insert (ids-find-format-line c is))
361         (setq ignored-chars
362               (ids-insert-chars-including-components*
363                (char-to-string c) (1+ level)
364                (cons c ignored-chars))))
365       )
366     )
367   ignored-chars)
368
369 ;;;###autoload
370 (defun ids-find-chars-including-components (components)
371   "Search Ideographs whose structures have COMPONENTS."
372   (interactive "sComponents : ")
373   (with-current-buffer (get-buffer-create ids-find-result-buffer)
374     (setq buffer-read-only nil)
375     (erase-buffer)
376     (ids-insert-chars-including-components components 0 nil)
377     ;; (let ((ignored-chars
378     ;;        (nreverse
379     ;;         (ids-insert-chars-including-components components 0 nil
380     ;;                                                #'ideograph-find-products)))
381     ;;       rest)
382     ;;   (setq rest ignored-chars)
383     ;;   ;; (dolist (c rest)
384     ;;   ;;   (setq ignored-chars
385     ;;   ;;         (union ignored-chars
386     ;;   ;;                (ids-insert-chars-including-components
387     ;;   ;;                 (list c) 0 ignored-chars
388     ;;   ;;                 #'ideograph-find-products-with-variants))))
389     ;;   (ids-insert-chars-including-components components 0 ignored-chars
390     ;;                                          #'ideograph-find-products-with-variants))
391     (goto-char (point-min)))
392   (view-buffer ids-find-result-buffer))
393
394 ;;;###autoload
395 (define-obsolete-function-alias 'ideographic-structure-search-chars
396   'ids-find-chars-including-components)
397
398 ;;;###autoload
399 (defun ids-find-chars-covered-by-components (components)
400   "Search Ideographs which structures are consisted by subsets of COMPONENTS."
401   (interactive "sComponents: ")
402   (if (stringp components)
403       (setq components (string-to-char-list components)))
404   (with-current-buffer (get-buffer-create ids-find-result-buffer)
405     (setq buffer-read-only nil)
406     (erase-buffer)
407     (map-char-attribute
408      (lambda (c v)
409        (when (ideographic-structure-repertoire-p v components)
410          (insert (ids-find-format-line c v))))
411      'ideographic-structure)
412     (goto-char (point-min)))
413   (view-buffer ids-find-result-buffer))
414
415
416 (defun ideographic-structure-merge-components-alist (ca1 ca2)
417   (let ((dest-alist ca1)
418         ret)
419     (dolist (cell ca2)
420       (if (setq ret (assq (car cell) dest-alist))
421           (setcdr ret (+ (cdr ret)(cdr cell)))
422         (setq dest-alist (cons cell dest-alist))))
423     dest-alist))
424
425 (defun ideographic-structure-to-components-alist (structure)
426   (apply #'ideographic-structure-to-components-alist* structure))
427
428 (defun ideographic-structure-to-components-alist* (operator component1 component2
429                                                             &optional component3
430                                                             &rest opts)
431   (let (dest-alist ret)
432     (setq dest-alist
433           (cond ((characterp component1)
434                  (unless (encode-char component1 'ascii)
435                    (list (cons component1 1)))
436                  )
437                 ((setq ret (assq 'ideographic-structure component1))
438                  (ideographic-structure-to-components-alist (cdr ret))
439                  )
440                 ((setq ret (find-char component1))
441                  (list (cons ret 1))
442                  )))
443     (setq dest-alist
444           (ideographic-structure-merge-components-alist
445            dest-alist
446            (cond ((characterp component2)
447                   (unless (encode-char component2 'ascii)
448                     (list (cons component2 1)))
449                   )
450                  ((setq ret (assq 'ideographic-structure component2))
451                   (ideographic-structure-to-components-alist (cdr ret))
452                   )
453                  ((setq ret (find-char component2))
454                   (list (cons ret 1))
455                   ))))
456     (if (memq operator '(?\u2FF2 ?\u2FF3))
457         (ideographic-structure-merge-components-alist
458          dest-alist
459          (cond ((characterp component3)
460                 (unless (encode-char component3 'ascii)
461                   (list (cons component3 1)))
462                 )
463                ((setq ret (assq 'ideographic-structure component3))
464                 (ideographic-structure-to-components-alist (cdr ret))
465                 )
466                ((setq ret (find-char component3))
467                 (list (cons ret 1))
468                 )))
469       dest-alist)))
470
471 (defun ids-find-merge-variables (ve1 ve2)
472   (cond ((eq ve1 t)
473          ve2)
474         ((eq ve2 t)
475          ve1)
476         (t
477          (let ((dest-alist ve1)
478                (rest ve2)
479                cell ret)
480            (while (and rest
481                        (setq cell (car rest))
482                        (if (setq ret (assq (car cell) ve1))
483                            (eq (cdr ret)(cdr cell))
484                          (setq dest-alist (cons cell dest-alist))))
485              (setq rest (cdr rest)))
486            (if rest
487                nil
488              dest-alist)))))
489
490 ;;;###autoload
491 (defun ideographic-structure-equal (structure1 structure2)
492   (let (dest-alist ret)
493     (and (setq dest-alist (ideographic-structure-character=
494                            (car structure1)(car structure2)))
495          (setq ret (ideographic-structure-character=
496                     (nth 1 structure1)(nth 1 structure2)))
497          (setq dest-alist (ids-find-merge-variables dest-alist ret))
498          (setq ret (ideographic-structure-character=
499                     (nth 2 structure1)(nth 2 structure2)))
500          (setq dest-alist (ids-find-merge-variables dest-alist ret))
501          (if (memq (car structure1) '(?\u2FF2 ?\u2FF3))
502              (and (setq ret (ideographic-structure-character=
503                              (nth 3 structure1)(nth 3 structure2)))
504                   (setq dest-alist (ids-find-merge-variables dest-alist ret)))
505            dest-alist))))
506
507 ;;;###autoload
508 (defun ideographic-structure-character= (c1 c2)
509   (let (ret ret2)
510     (cond ((characterp c1)
511            (cond ((encode-char c1 'ascii)
512                   (list (cons c1 c2))
513                   )
514                  ((characterp c2)
515                   (if (encode-char c2 'ascii)
516                       (list (cons c2 c1))
517                     (eq c1 c2))
518                   )
519                  ((setq ret2 (find-char c2))
520                   (eq c1 ret2)
521                   )
522                  ((setq ret2 (assq 'ideographic-structure c2))
523                   (and (setq ret (get-char-attribute c1 'ideographic-structure))
524                        (ideographic-structure-equal ret (cdr ret2)))
525                   ))
526            )
527           ((setq ret (assq 'ideographic-structure c1))
528            (cond ((characterp c2)
529                   (if (encode-char c2 'ascii)
530                       (list (cons c2 c1))
531                     (and (setq ret2 (get-char-attribute c2 'ideographic-structure))
532                          (ideographic-structure-equal (cdr ret) ret2)))
533                   )
534                  ((setq ret2 (find-char c2))
535                   (and (setq ret2 (get-char-attribute ret2 'ideographic-structure))
536                        (ideographic-structure-equal (cdr ret) ret2))
537                   )
538                  ((setq ret2 (assq 'ideographic-structure c2))
539                   (ideographic-structure-equal (cdr ret)(cdr ret2))
540                   ))
541            )
542           ((setq ret (find-char c1))
543            (cond ((characterp c2)
544                   (if (encode-char c2 'ascii)
545                       (list (cons c2 c1))
546                     (eq ret c2))
547                   )
548                  ((setq ret2 (find-char c2))
549                   (eq ret ret2)
550                   )
551                  ((setq ret2 (assq 'ideographic-structure c2))
552                   (and (setq ret (get-char-attribute ret 'ideographic-structure))
553                        (ideographic-structure-equal ret (cdr ret2))
554                        )))))))
555
556 ;;;###autoload
557 (defun ideographic-structure-find-chars (structure)
558   (let ((comp-alist (ideographic-structure-to-components-alist structure))
559         ret pl str)
560     (dolist (pc (caar
561                  (sort (mapcar (lambda (cell)
562                                  (if (setq ret (get-char-attribute
563                                                 (car cell) 'ideographic-products))
564                                      (cons ret (length ret))
565                                    (cons nil 0)))
566                                comp-alist)
567                        (lambda (a b)
568                          (< (cdr a)(cdr b))))))
569       (when (or (and (setq str
570                            (get-char-attribute pc 'ideographic-structure))
571                      (ideographic-structure-equal str structure))
572                 (and (setq str
573                            (get-char-attribute pc 'ideographic-structure@apparent))
574                      (ideographic-structure-equal str structure)))
575         (setq pl (cons pc pl))
576         ))
577     pl))
578
579 ;;;###autoload
580 (defun ideographic-char-count-components (char component)
581   (let ((dest 0)
582         structure)
583     (cond ((eq char component)
584            1)
585           ((setq structure (get-char-attribute char 'ideographic-structure))
586            (dolist (cell (ideographic-structure-to-components-alist structure))
587              (setq dest
588                    (+ dest
589                       (if (eq (car cell) char)
590                           (cdr cell)
591                         (* (ideographic-char-count-components (car cell) component)
592                            (cdr cell))))))
593            dest)
594           (t
595            0))))
596
597
598 ;;;###autoload
599 (defun ideographic-character-get-structure (character)
600   "Return ideographic-structure of CHARACTER.
601 CHARACTER can be a character or char-spec."
602   (let (ret)
603     (cond ((characterp character)
604            (get-char-attribute character 'ideographic-structure)
605            )
606           ((setq ret (assq 'ideographic-structure character))
607            (cdr ret)
608            )
609           ((setq ret (find-char character))
610            (get-char-attribute ret 'ideographic-structure)
611            ))))
612
613 ;;;###autoload
614 (defun ideographic-char-match-component (char component)
615   "Return non-nil if character CHAR has COMPONENT in ideographic-structure.
616 COMPONENT can be a character or char-spec."
617   (or (ideographic-structure-character= char component)
618       (let ((str (ideographic-character-get-structure char)))
619         (and str
620              (or (ideographic-char-match-component (nth 1 str) component)
621                  (ideographic-char-match-component (nth 2 str) component)
622                  (if (memq (car str) '(?\u2FF2 ?\u2FF3))
623                      (ideographic-char-match-component (nth 3 str) component)))))))
624
625 (defun ideographic-structure-char< (a b)
626   (let ((sa (get-char-attribute a 'ideographic-structure))
627         (sb (get-char-attribute b 'ideographic-structure))
628         tsa tsb)
629     (cond (sa
630            (cond (sb
631                   (setq tsa (char-total-strokes a)
632                         tsb (char-total-strokes b))
633                   (if tsa
634                       (if tsb
635                           (or (< tsa tsb)
636                               (and (= tsa tsb)
637                                    (ideograph-char< a b)))
638                         t)
639                     (if tsb
640                         nil
641                       (ideograph-char< a b))))
642                  (t
643                   nil))
644            )
645           (t
646            (cond (sb
647                   t)
648                  (t
649                   (setq tsa (char-total-strokes a)
650                         tsb (char-total-strokes b))
651                   (if tsa
652                       (if tsb
653                           (or (< tsa tsb)
654                               (and (= tsa tsb)
655                                    (ideograph-char< a b)))
656                         t)
657                     (if tsb
658                         nil
659                       (ideograph-char< a b)))
660                   ))
661            ))
662     ))
663
664 (defun ideo-comp-tree-adjoin (tree char)
665   (let ((rest tree)
666         included ; other
667         dest cell finished)
668     (while (and (not finished)
669                 rest)
670       (setq cell (pop rest))
671       (cond ((ideographic-structure-character= char (car cell))
672              (setq finished t
673                    dest tree
674                    rest nil)
675              )
676             ((ideographic-char-match-component char (car cell))
677              (setq dest
678                    (cons (cons (car cell)
679                                (ideo-comp-tree-adjoin (cdr cell) char))
680                          dest))
681              (setq finished t)
682              )
683             ((ideographic-char-match-component (car cell) char)
684              (setq included (cons cell included))
685              )
686             ;; (included
687             ;;  (setq other (cons cell other))
688             ;;  )
689             (t
690              (setq dest (cons cell dest))
691              )))
692     (cond (finished
693            (nconc dest rest)
694            )
695           (included
696            (cons (cons char included)
697                  (nconc dest rest))
698            )
699           (t
700            (cons (list char) tree)
701            ))))
702
703 (defun ideographic-chars-to-is-a-tree (chars)
704   (let (tree)
705     (dolist (char (sort (copy-list chars) #'ideographic-structure-char<))
706       (setq tree (ideo-comp-tree-adjoin tree char)))
707     tree))
708
709 (defun ids-find-chars-including-ids (structure)
710   (let (comp-alist comp-spec ret str rest)
711     (cond
712      ((characterp structure)
713       (setq rest (copy-list (get-char-attribute structure 'ideographic-products)))
714       )
715      ((setq ret (ideographic-structure-find-chars structure))
716       (dolist (pc ret)
717         (setq rest
718               (union
719                rest
720                (copy-list (get-char-attribute pc 'ideographic-products)))))
721       )
722      (t
723       (setq comp-alist (ideographic-structure-to-components-alist structure)
724             comp-spec (list (cons 'ideographic-structure structure)))
725       (dolist (pc (caar
726                    (sort (mapcar (lambda (cell)
727                                    (if (setq ret (get-char-attribute
728                                                   (car cell) 'ideographic-products))
729                                        (cons ret (length ret))
730                                      (cons nil 0)))
731                                  comp-alist)
732                          (lambda (a b)
733                            (< (cdr a)(cdr b))))))
734         (when (and (every (lambda (cell)
735                             (>= (ideographic-char-count-components pc (car cell))
736                                 (cdr cell)))
737                           comp-alist)
738                    (or (ideographic-char-match-component pc comp-spec)
739                        (and (setq str (get-char-attribute pc 'ideographic-structure))
740                             (ideographic-char-match-component
741                              (list
742                               (cons
743                                'ideographic-structure
744                                (functional-ideographic-structure-to-apparent-structure
745                                 str)))
746                              comp-spec))))
747           (push pc rest)))
748       ))
749     (ideographic-chars-to-is-a-tree rest)))
750
751 (defun functional-ideographic-structure-to-apparent-structure (structure)
752   (ideographic-structure-compare-functional-and-apparent
753    structure nil 'conversion-only))
754
755 ;;;###autoload
756 (defun ideographic-structure-compact (structure)
757   (let ((rest structure)
758         cell
759         ret dest sub)
760     (while rest
761       (setq cell (pop rest))
762       (cond
763        ((and (consp cell)
764              (cond ((setq ret (assq 'ideographic-structure cell))
765                     (setq sub (cdr ret))
766                     )
767                    ((atom (car cell))
768                     (setq sub cell)
769                     )))
770         (setq cell
771               (if (setq ret (ideographic-structure-find-chars sub))
772                   (car ret)
773                 (list (cons 'ideographic-structure sub))))
774         ))
775       (setq dest (cons cell dest)))
776     (nreverse dest)))
777
778 (defun ideographic-structure-compare-functional-and-apparent (structure
779                                                               &optional char
780                                                               conversion-only)
781   (let (enc enc-str enc2-str new-str new-str-c f-res a-res ret code)
782     (cond
783      ((eq (car structure) ?⿸)
784       (setq enc (nth 1 structure))
785       (when (setq enc-str
786                   (cond ((characterp enc)
787                          (get-char-attribute enc 'ideographic-structure)
788                          )
789                         ((consp enc)
790                          (cdr (assq 'ideographic-structure enc))
791                          )))
792         (cond
793          ((eq (car enc-str) ?⿰)
794           (unless conversion-only
795             (setq f-res (ids-find-chars-including-ids enc-str)))
796           (setq new-str (list ?⿱
797                               (nth 2 enc-str)
798                               (nth 2 structure)))
799           (setq new-str-c
800                 (if (setq ret (ideographic-structure-find-chars new-str))
801                     (car ret)
802                   (list (cons 'ideographic-structure new-str))))
803           (if conversion-only
804               (list ?⿰ (nth 1 enc-str) new-str-c)
805             (setq a-res (ids-find-chars-including-ids new-str))
806             (list enc
807                   f-res
808                   new-str-c
809                   a-res
810                   (list ?⿰ (nth 1 enc-str) new-str-c)
811                   111))
812           )
813          ((and (eq (car enc-str) ?⿲)
814                (memq (char-ucs (nth 1 enc-str)) '(#x4EBB #x2E85))
815                (eq (nth 2 enc-str) ?丨))
816           (unless conversion-only
817             (setq f-res (ids-find-chars-including-ids enc-str)))
818           (setq new-str (list ?⿱
819                               (nth 3 enc-str)
820                               (nth 2 structure)))
821           (setq new-str-c
822                 (if (setq ret (ideographic-structure-find-chars new-str))
823                     (car ret)
824                   (list (cons 'ideographic-structure new-str))))
825           (if conversion-only
826               (list ?⿰ (decode-char '=big5-cdp #x8B7A) new-str-c)
827             (setq a-res (ids-find-chars-including-ids new-str))
828             (list enc
829                   f-res
830                   new-str-c
831                   a-res
832                   (list ?⿰ (decode-char '=big5-cdp #x8B7A) new-str-c)
833                   112))
834           )
835          ((eq (car enc-str) ?⿱)
836           (unless conversion-only
837             (setq f-res (ids-find-chars-including-ids enc-str)))
838           (setq new-str
839                 (list
840                  (cond
841                   ((characterp (nth 2 enc-str))
842                    (if (or (memq (encode-char (nth 2 enc-str) '=>ucs@component)
843                                  '(#x20087 #x5382 #x4E06))
844                            (eq (encode-char (nth 2 enc-str) '=>ucs@iwds-1)
845                                #x4E06)
846                            (eq (encode-char (nth 2 enc-str) '=ucs-itaiji-001)
847                                #x2E282)
848                            (eq (encode-char (nth 2 enc-str) '=big5-cdp)
849                                #x89CE)
850                            (eq (encode-char (nth 2 enc-str) '=>big5-cdp)
851                                #x88E2)
852                            (eq (encode-char (nth 2 enc-str) '=big5-cdp)
853                                #x88AD)
854                            (eq (or (encode-char (nth 2 enc-str) '=>big5-cdp)
855                                    (encode-char (nth 2 enc-str) '=big5-cdp-itaiji-001))
856                                #x8766)
857                            (eq (car (get-char-attribute (nth 2 enc-str)
858                                                         'ideographic-structure))
859                                ?⿸))
860                        ?⿸
861                      ?⿰))
862                   ((eq (car (cdr (assq 'ideographic-structure (nth 2 enc-str))))
863                        ?⿸)
864                    ?⿸)
865                   (t
866                    ?⿰))
867                  (nth 2 enc-str)
868                  (nth 2 structure)))
869           (setq new-str-c
870                 (if (setq ret (ideographic-structure-find-chars new-str))
871                     (car ret)
872                   (list (cons 'ideographic-structure new-str))))
873           (if conversion-only
874               (list ?⿱ (nth 1 enc-str) new-str-c)
875             (setq a-res (ids-find-chars-including-ids new-str))
876             (list enc
877                   f-res
878                   new-str-c
879                   a-res
880                   (list ?⿱ (nth 1 enc-str) new-str-c)
881                   (if (eq (car new-str) ?⿸)
882                       121
883                     122)))
884           )
885          ((eq (car enc-str) ?⿸)
886           (unless conversion-only
887             (setq f-res (ids-find-chars-including-ids enc-str)))
888           (setq new-str (list (cond
889                                ((characterp (nth 2 enc-str))
890                                 (if (memq (char-ucs (nth 2 enc-str))
891                                           '(#x5F73))
892                                     ?⿰
893                                   ?⿱)
894                                 )
895                                (t
896                                 ?⿱))
897                               (nth 2 enc-str)
898                               (nth 2 structure)))
899           (setq new-str-c
900                 (if (setq ret (ideographic-structure-find-chars new-str))
901                     (car ret)
902                   (list (cons 'ideographic-structure new-str))))
903           (if conversion-only
904               (list ?⿸ (nth 1 enc-str) new-str-c)
905             (setq a-res (ids-find-chars-including-ids new-str))
906             (list enc
907                   f-res
908                   new-str-c
909                   a-res
910                   (list ?⿸ (nth 1 enc-str) new-str-c)
911                   (if (eq (car new-str) ?⿰)
912                       131
913                     132)))
914           )))
915       )
916      ((eq (car structure) ?⿹)
917       (setq enc (nth 1 structure))
918       (when (setq enc-str
919                   (cond ((characterp enc)
920                          (get-char-attribute enc 'ideographic-structure)
921                          )
922                         ((consp enc)
923                          (cdr (assq 'ideographic-structure enc))
924                          )))
925         (cond
926          ((eq (car enc-str) ?⿰)
927           (unless conversion-only
928             (setq f-res (ids-find-chars-including-ids enc-str)))
929           (setq new-str (list ?⿱
930                               (nth 1 enc-str)
931                               (nth 2 structure)))
932           (setq new-str-c
933                 (if (setq ret (ideographic-structure-find-chars new-str))
934                     (car ret)
935                   (list (cons 'ideographic-structure new-str))))
936           (if conversion-only
937               (list ?⿰ new-str-c (nth 2 enc-str))
938             (setq a-res (ids-find-chars-including-ids new-str))
939             (list enc
940                   f-res
941                   new-str-c
942                   a-res
943                   (list ?⿰ new-str-c (nth 2 enc-str))
944                   210))
945           )))
946       )
947      ((eq (get-char-attribute (car structure) '=ucs-itaiji-001) #x2FF6)
948       (setq enc (nth 1 structure))
949       (when (setq enc-str
950                   (cond ((characterp enc)
951                          (get-char-attribute enc 'ideographic-structure)
952                          )
953                         ((consp enc)
954                          (cdr (assq 'ideographic-structure enc))
955                          )))
956         (cond
957          ((eq (car enc-str) ?⿺)
958           (unless conversion-only
959             (setq f-res (ids-find-chars-including-ids enc-str)))
960           (setq new-str (list ?⿱
961                               (nth 2 structure)
962                               (nth 1 enc-str)))
963           (setq new-str-c
964                 (if (setq ret (ideographic-structure-find-chars new-str))
965                     (car ret)
966                   (list (cons 'ideographic-structure new-str))))
967           (if conversion-only
968               (list ?⿺ new-str-c (nth 2 enc-str))
969             (setq a-res (ids-find-chars-including-ids new-str))
970             (list enc
971                   f-res
972                   new-str-c
973                   a-res
974                   (list ?⿺ new-str-c (nth 2 enc-str))
975                   310))
976           )
977          ((eq (car enc-str) ?⿱)
978           (unless conversion-only
979             (setq f-res (ids-find-chars-including-ids enc-str)))
980           (setq new-str (list ?⿰
981                               (nth 2 structure)
982                               (nth 1 enc-str)))
983           (setq new-str-c
984                 (if (setq ret (ideographic-structure-find-chars new-str))
985                     (car ret)
986                   (list (cons 'ideographic-structure new-str))))
987           (if conversion-only
988               (list ?⿱ new-str-c (nth 2 enc-str))
989             (setq a-res (ids-find-chars-including-ids new-str))
990             (list enc
991                   f-res
992                   new-str-c
993                   a-res
994                   (list ?⿱ new-str-c (nth 2 enc-str))
995                   320))
996           )
997          ((eq (car enc-str) ?⿰)
998           (unless conversion-only
999             (setq f-res (ids-find-chars-including-ids enc-str)))
1000           (setq new-str (list ?⿱
1001                               (nth 2 structure)
1002                               (nth 1 enc-str)))
1003           (setq new-str-c
1004                 (if (setq ret (ideographic-structure-find-chars new-str))
1005                     (car ret)
1006                   (list (cons 'ideographic-structure new-str))))
1007           (if conversion-only
1008               (list ?⿰ new-str-c (nth 2 enc-str))
1009             (setq a-res (ids-find-chars-including-ids new-str))
1010             (list enc
1011                   f-res
1012                   new-str-c
1013                   a-res
1014                   (list ?⿰ new-str-c (nth 2 enc-str))
1015                   330))
1016           ))
1017         )
1018       )
1019      ((eq (car structure) ?⿴)
1020       (setq enc (nth 1 structure))
1021       (when (setq enc-str
1022                   (cond ((characterp enc)
1023                          (get-char-attribute enc 'ideographic-structure)
1024                          )
1025                         ((consp enc)
1026                          (cdr (assq 'ideographic-structure enc))
1027                          )))
1028         (cond
1029          ((eq (car enc-str) ?⿱)
1030           (cond
1031            ((and (characterp (nth 2 enc-str))
1032                  (or (memq (char-ucs (nth 2 enc-str)) '(#x56D7 #x5F51 #x897F))
1033                      (eq (char-feature (nth 2 enc-str) '=>big5-cdp)
1034                          #x87A5)))
1035             (unless conversion-only
1036               (setq f-res (ids-find-chars-including-ids enc-str)))
1037             (setq new-str (list ?⿴
1038                                 (nth 2 enc-str)
1039                                 (nth 2 structure)))
1040             (setq new-str-c
1041                   (if (setq ret (ideographic-structure-find-chars new-str))
1042                       (car ret)
1043                     (list (cons 'ideographic-structure new-str))))
1044             (if conversion-only
1045                 (list ?⿱ (nth 1 enc-str) new-str-c)
1046               (setq a-res (ids-find-chars-including-ids new-str))
1047               (list enc
1048                     f-res
1049                     new-str-c
1050                     a-res
1051                     (list ?⿱ (nth 1 enc-str) new-str-c)
1052                     411))
1053             )
1054            ((and (characterp (nth 2 enc-str))
1055                  (eq (char-ucs (nth 2 enc-str)) #x51F5))
1056             (unless conversion-only
1057               (setq f-res (ids-find-chars-including-ids enc-str)))
1058             (setq new-str (list ?⿶
1059                                 (nth 2 enc-str)
1060                                 (nth 2 structure)))
1061             (setq new-str-c
1062                   (if (setq ret (ideographic-structure-find-chars new-str))
1063                       (car ret)
1064                     (list (cons 'ideographic-structure new-str))))
1065             (if conversion-only
1066                 (list ?⿱ (nth 1 enc-str) new-str-c)
1067               (setq a-res (ids-find-chars-including-ids new-str))
1068               (list enc
1069                     f-res
1070                     new-str-c
1071                     a-res
1072                     (list ?⿱ (nth 1 enc-str) new-str-c)
1073                     412))
1074             )       
1075            ((and (characterp (nth 1 enc-str))
1076                  (eq (char-feature (nth 1 enc-str) '=>ucs@component)
1077                      #x300E6))
1078             (unless conversion-only
1079               (setq f-res (ids-find-chars-including-ids enc-str)))
1080             (setq new-str (list ?⿵
1081                                 (nth 1 enc-str)
1082                                 (nth 2 structure)))
1083             (setq new-str-c
1084                   (if (setq ret (ideographic-structure-find-chars new-str))
1085                       (car ret)
1086                     (list (cons 'ideographic-structure new-str))))
1087             (if conversion-only
1088                 (list ?⿱ new-str-c (nth 2 enc-str))
1089               (setq a-res (ids-find-chars-including-ids new-str))
1090               (list enc
1091                     f-res
1092                     new-str-c
1093                     a-res
1094                     (list ?⿱ new-str-c (nth 2 enc-str))
1095                     413))
1096             )
1097            (t
1098             (unless conversion-only
1099               (setq f-res (ids-find-chars-including-ids enc-str)))
1100             (setq new-str (list ?⿱ (nth 2 structure) (nth 2 enc-str)))
1101             (setq new-str-c
1102                   (if (setq ret (ideographic-structure-find-chars new-str))
1103                       (car ret)
1104                     (list (cons 'ideographic-structure new-str))))
1105             (if conversion-only
1106                 (list ?⿱ (nth 1 enc-str) new-str-c)
1107               (setq a-res (ids-find-chars-including-ids new-str))
1108               (list enc
1109                     f-res
1110                     new-str-c
1111                     a-res
1112                     (list ?⿱ (nth 1 enc-str) new-str-c)
1113                     414))
1114             ))
1115           )
1116          ((eq (car enc-str) ?⿳)
1117           (cond
1118            ((and (characterp (nth 2 enc-str))
1119                  (eq (char-ucs (nth 2 enc-str)) #x56D7))
1120             (unless conversion-only
1121               (setq f-res (ids-find-chars-including-ids enc-str)))
1122             (setq new-str (list ?⿴ (nth 2 enc-str) (nth 2 structure)))
1123             (setq new-str-c
1124                   (if (setq ret (ideographic-structure-find-chars new-str))
1125                       (car ret)
1126                     (list (cons 'ideographic-structure new-str))))
1127             (setq new-str (list ?⿱ (nth 1 enc-str) new-str-c))
1128             (setq new-str-c
1129                   (if (setq ret (ideographic-structure-find-chars new-str))
1130                       (car ret)
1131                     (list (cons 'ideographic-structure new-str))))
1132             (if conversion-only
1133                 (list ?⿱  new-str-c (nth 3 enc-str))
1134               (setq a-res (ids-find-chars-including-ids new-str))
1135               (list enc
1136                     f-res
1137                     new-str-c
1138                     a-res
1139                     (list ?⿱  new-str-c (nth 3 enc-str))
1140                     415))
1141             )
1142            ((and (characterp (nth 2 enc-str))
1143                  (eq (char-ucs (nth 2 enc-str)) #x5196))
1144             (unless conversion-only
1145               (setq f-res (ids-find-chars-including-ids enc-str)))
1146             (setq new-str (list ?⿱ (nth 1 enc-str) (nth 2 enc-str)))
1147             (setq new-str-c
1148                   (if (setq ret (ideographic-structure-find-chars new-str))
1149                       (car ret)
1150                     (list (cons 'ideographic-structure new-str))))
1151             (setq new-str (list ?⿱ new-str-c (nth 2 structure)))
1152             (setq new-str-c
1153                   (if (setq ret (ideographic-structure-find-chars new-str))
1154                       (car ret)
1155                     (list (cons 'ideographic-structure new-str))))
1156             (if conversion-only
1157                 (list ?⿱ new-str-c (nth 3 enc-str))
1158               (setq a-res (ids-find-chars-including-ids new-str))
1159               (list enc
1160                     f-res
1161                     new-str-c
1162                     a-res
1163                     (list ?⿱ new-str-c (nth 3 enc-str))
1164                     416))
1165             )
1166            ((and (characterp (nth 2 enc-str))
1167                  (or (eq (encode-char (nth 2 enc-str) '=>big5-cdp)
1168                          #x89A6)
1169                      (eq (encode-char (nth 2 enc-str) '=>gt-k)
1170                          146)
1171                      (eq (char-ucs (nth 2 enc-str)) #x2008A)))
1172             (unless conversion-only
1173               (setq f-res (ids-find-chars-including-ids enc-str)))
1174             (setq new-str (list ?⿱ (nth 2 structure) (nth 2 enc-str)))
1175             (setq new-str-c
1176                   (if (setq ret (ideographic-structure-find-chars new-str))
1177                       (car ret)
1178                     (list (cons 'ideographic-structure new-str))))
1179             (setq new-str (list ?⿸ new-str-c (nth 3 enc-str)))
1180             (setq new-str-c
1181                   (if (setq ret (ideographic-structure-find-chars new-str))
1182                       (car ret)
1183                     (list (cons 'ideographic-structure new-str))))
1184             (if conversion-only
1185                 (list ?⿱ (nth 1 enc-str) new-str-c)
1186               (setq a-res (ids-find-chars-including-ids new-str))
1187               (list enc
1188                     f-res
1189                     new-str-c
1190                     a-res
1191                     (list ?⿱ (nth 1 enc-str) new-str-c)
1192                     417))
1193             )
1194            (t
1195             (unless conversion-only
1196               (setq f-res (ids-find-chars-including-ids enc-str)))
1197             (setq new-str (list ?⿻ (nth 2 enc-str) (nth 2 structure)))
1198             (setq new-str-c
1199                   (if (setq ret (ideographic-structure-find-chars new-str))
1200                       (car ret)
1201                     (list (cons 'ideographic-structure new-str))))
1202             (setq new-str (list ?⿱ (nth 1 enc-str) new-str-c))
1203             (setq new-str-c
1204                   (if (setq ret (ideographic-structure-find-chars new-str))
1205                       (car ret)
1206                     (list (cons 'ideographic-structure new-str))))
1207             (if conversion-only
1208                 (list ?⿱  new-str-c (nth 3 enc-str))
1209               (setq a-res (ids-find-chars-including-ids new-str))
1210               (list enc
1211                     f-res
1212                     new-str-c
1213                     a-res
1214                     (list ?⿱  new-str-c (nth 3 enc-str))
1215                     419))
1216             ))
1217           )
1218          ((eq (car enc-str) ?⿰)
1219           (cond
1220            ((equal (nth 1 enc-str)(nth 2 enc-str))
1221             (unless conversion-only
1222               (setq f-res (ids-find-chars-including-ids enc-str)))
1223             (setq new-str (list ?⿲
1224                                 (nth 1 enc-str)
1225                                 (nth 2 structure)
1226                                 (nth 2 enc-str)))
1227             (setq new-str-c
1228                   (list (cons 'ideographic-structure new-str)))
1229             (if conversion-only
1230                 new-str
1231               (setq a-res (ids-find-chars-including-ids new-str))
1232               (list enc
1233                     f-res
1234                     new-str-c
1235                     a-res
1236                     new-str
1237                     421))
1238             )
1239            (t
1240             (unless conversion-only
1241               (setq f-res (ids-find-chars-including-ids enc-str)))
1242             (setq new-str (list ?⿰
1243                                 (nth 2 structure)
1244                                 (nth 2 enc-str)))
1245             (setq new-str-c
1246                   (if (setq ret (ideographic-structure-find-chars new-str))
1247                       (car ret)
1248                     (list (cons 'ideographic-structure new-str))))
1249             (if conversion-only
1250                 (list ?⿰ (nth 1 enc-str) new-str-c)
1251               (setq a-res (ids-find-chars-including-ids new-str))
1252               (list enc
1253                     f-res
1254                     new-str-c
1255                     a-res
1256                     (list ?⿰ (nth 1 enc-str) new-str-c)
1257                     422))
1258             ))
1259           ))
1260         )
1261       )
1262      ((eq (car structure) ?⿶)
1263       (setq enc (nth 1 structure))
1264       (when (setq enc-str
1265                   (cond ((characterp enc)
1266                          (get-char-attribute enc 'ideographic-structure)
1267                          )
1268                         ((consp enc)
1269                          (cdr (assq 'ideographic-structure enc))
1270                          )))
1271         (cond
1272          ((eq (car enc-str) ?⿱)
1273           (setq enc2-str (ideographic-character-get-structure (nth 1 enc-str)))
1274           (when (and enc2-str
1275                      (eq (car enc2-str) ?⿰))
1276             (unless conversion-only
1277               (setq f-res (ids-find-chars-including-ids enc-str)))
1278             (setq new-str (list ?⿲
1279                                 (nth 1 enc2-str)
1280                                 (nth 2 structure)
1281                                 (nth 2 enc2-str)))
1282             (setq new-str-c
1283                   (if (setq ret (ideographic-structure-find-chars new-str))
1284                       (car ret)
1285                     (list (cons 'ideographic-structure new-str))))
1286             (if conversion-only
1287                 (list ?⿱ new-str-c (nth 2 enc-str))
1288               (setq a-res (ids-find-chars-including-ids new-str))
1289               (list enc
1290                     f-res
1291                     new-str-c
1292                     a-res
1293                     (list ?⿱ new-str-c (nth 2 enc-str))
1294                     511))
1295             )
1296           )
1297          ((eq (car enc-str) ?⿳)
1298           (setq enc2-str (ideographic-character-get-structure (nth 1 enc-str)))
1299           (when (and enc2-str
1300                      (eq (car enc2-str) ?⿰))
1301             (unless conversion-only
1302               (setq f-res (ids-find-chars-including-ids enc-str)))
1303             (setq new-str (list ?⿲
1304                                 (nth 1 enc2-str)
1305                                 (nth 2 structure)
1306                                 (nth 2 enc2-str)))
1307             (setq new-str-c
1308                   (if (setq ret (ideographic-structure-find-chars new-str))
1309                       (car ret)
1310                     (list (cons 'ideographic-structure new-str))))
1311             (if conversion-only
1312                 (list ?⿳ new-str-c (nth 2 enc-str) (nth 3 enc-str))
1313               (setq a-res (ids-find-chars-including-ids new-str))
1314               (list enc
1315                     f-res
1316                     new-str-c
1317                     a-res
1318                     (list ?⿳ new-str-c (nth 2 enc-str) (nth 3 enc-str))
1319                     512))
1320             )
1321           )
1322          ((eq (car enc-str) ?⿲)
1323           (unless conversion-only
1324             (setq f-res (ids-find-chars-including-ids enc-str)))
1325           (setq new-str (list ?⿱
1326                               (nth 2 structure)
1327                               (nth 2 enc-str)))
1328           (setq new-str-c
1329                 (if (setq ret (ideographic-structure-find-chars new-str))
1330                     (car ret)
1331                   (list (cons 'ideographic-structure new-str))))
1332           (if conversion-only
1333               (list ?⿲ (nth 1 enc-str) new-str-c (nth 3 enc-str))
1334             (setq a-res (ids-find-chars-including-ids new-str))
1335             (list enc
1336                   f-res
1337                   new-str-c
1338                   a-res
1339                   (list ?⿲ (nth 1 enc-str) new-str-c (nth 3 enc-str))
1340                   520))
1341           )
1342          ((eq (car enc-str) ?⿴)
1343           (setq enc2-str (ideographic-character-get-structure (nth 1 enc-str)))
1344           (when (and enc2-str
1345                      (eq (car enc2-str) ?⿰))
1346             (unless conversion-only
1347               (setq f-res (ids-find-chars-including-ids enc-str)))
1348             (setq new-str (list ?⿱
1349                                 (nth 2 structure)
1350                                 (nth 2 enc-str)))
1351             (setq new-str-c
1352                   (if (setq ret (ideographic-structure-find-chars new-str))
1353                       (car ret)
1354                     (list (cons 'ideographic-structure new-str))))
1355             (if conversion-only
1356                 (list ?⿲ (nth 1 enc2-str) new-str-c (nth 2 enc2-str))
1357               (setq a-res (ids-find-chars-including-ids new-str))
1358               (list enc
1359                     f-res
1360                     new-str-c
1361                     a-res
1362                     (list ?⿲ (nth 1 enc2-str) new-str-c (nth 2 enc2-str))
1363                     530))
1364             )
1365           )))
1366       )
1367      ((eq (car structure) ?⿵)
1368       (setq enc (nth 1 structure))
1369       (when (setq enc-str
1370                   (cond ((characterp enc)
1371                          (get-char-attribute enc 'ideographic-structure)
1372                          )
1373                         ((consp enc)
1374                          (cdr (assq 'ideographic-structure enc))
1375                          )))
1376         (cond
1377          ((eq (car enc-str) ?⿱)         
1378           (cond
1379            ((and (characterp (nth 2 enc-str))
1380                  (memq (char-ucs (nth 2 enc-str))
1381                        '(#x9580 #x9B25)))
1382             (unless conversion-only
1383               (setq f-res (ids-find-chars-including-ids enc-str)))
1384             (setq new-str (list ?⿵
1385                                 (nth 2 enc-str)
1386                                 (nth 2 structure)))
1387             (setq new-str-c
1388                   (if (setq ret (ideographic-structure-find-chars new-str))
1389                       (car ret)
1390                     (list (cons 'ideographic-structure new-str))))
1391             (if conversion-only
1392                 (list ?⿱ (nth 1 enc-str) new-str-c)
1393               (setq a-res (ids-find-chars-including-ids new-str))
1394               (list enc
1395                     f-res
1396                     new-str-c
1397                     a-res
1398                     (list ?⿱ (nth 1 enc-str) new-str-c)
1399                     601))
1400             )
1401            ((and (setq enc2-str (ideographic-character-get-structure (nth 2 enc-str)))
1402                  (eq (car enc2-str) ?⿰))
1403             (unless conversion-only
1404               (setq f-res (ids-find-chars-including-ids enc-str)))
1405             (setq new-str (list ?⿲
1406                                 (nth 1 enc2-str)
1407                                 (nth 2 structure)
1408                                 (nth 2 enc2-str)))
1409             (setq new-str-c
1410                   (if (setq ret (ideographic-structure-find-chars new-str))
1411                       (car ret)
1412                     (list (cons 'ideographic-structure new-str))))
1413             (if conversion-only
1414                 (list ?⿱ (nth 1 enc-str) new-str-c)
1415               (setq a-res (ids-find-chars-including-ids new-str))
1416               (list enc
1417                     f-res
1418                     new-str-c
1419                     a-res
1420                     (list ?⿱ (nth 1 enc-str) new-str-c)
1421                     611))
1422             ))
1423           )
1424          ((eq (car enc-str) ?⿳)
1425           (setq enc2-str (ideographic-character-get-structure (nth 3 enc-str)))
1426           (when (and enc2-str
1427                      (eq (car enc2-str) ?⿰))
1428             (unless conversion-only
1429               (setq f-res (ids-find-chars-including-ids enc-str)))
1430             (setq new-str (list ?⿲
1431                                 (nth 1 enc2-str)
1432                                 (nth 2 structure)
1433                                 (nth 2 enc2-str)))
1434             (setq new-str-c
1435                   (if (setq ret (ideographic-structure-find-chars new-str))
1436                       (car ret)
1437                     (list (cons 'ideographic-structure new-str))))
1438             (if conversion-only
1439                 (list ?⿳ (nth 1 enc-str) (nth 2 enc-str) new-str-c)
1440               (setq a-res (ids-find-chars-including-ids new-str))
1441               (list enc
1442                     f-res
1443                     new-str-c
1444                     a-res
1445                     (list ?⿳ (nth 1 enc-str) (nth 2 enc-str) new-str-c)
1446                     612))
1447             )
1448           )
1449          ((eq (car enc-str) ?⿲)
1450           (unless conversion-only
1451             (setq f-res (ids-find-chars-including-ids enc-str)))
1452           (setq new-str (list ?⿱
1453                               (nth 2 enc-str)
1454                               (nth 2 structure)))
1455           (setq new-str-c
1456                 (if (setq ret (ideographic-structure-find-chars new-str))
1457                     (car ret)
1458                   (list (cons 'ideographic-structure new-str))))
1459           (if conversion-only
1460               (list ?⿲ (nth 1 enc-str) new-str-c (nth 3 enc-str))
1461             (setq a-res (ids-find-chars-including-ids new-str))
1462             (list enc
1463                   f-res
1464                   new-str-c
1465                   a-res
1466                   (list ?⿲ (nth 1 enc-str) new-str-c (nth 3 enc-str))
1467                   620))
1468           )
1469          ((eq (car enc-str) ?⿴)
1470           (setq enc2-str (ideographic-character-get-structure (nth 1 enc-str)))
1471           (when (and enc2-str
1472                      (eq (car enc2-str) ?⿰))
1473             (unless conversion-only
1474               (setq f-res (ids-find-chars-including-ids enc-str)))
1475             (setq new-str (list ?⿱
1476                                 (nth 2 enc-str)
1477                                 (nth 2 structure)))
1478             (setq new-str-c
1479                   (if (setq ret (ideographic-structure-find-chars new-str))
1480                       (car ret)
1481                     (list (cons 'ideographic-structure new-str))))
1482             (if conversion-only
1483                 (list ?⿲ (nth 1 enc2-str) new-str-c (nth 2 enc2-str))
1484               (setq a-res (ids-find-chars-including-ids new-str))
1485               (list enc
1486                     f-res
1487                     new-str-c
1488                     a-res
1489                     (list ?⿲ (nth 1 enc2-str) new-str-c (nth 2 enc2-str))
1490                     630))
1491             )
1492           )))
1493       )
1494      ((eq (car structure) ?⿷)
1495       (setq enc (nth 1 structure))
1496       (when (setq enc-str
1497                   (cond ((characterp enc)
1498                          (get-char-attribute enc 'ideographic-structure)
1499                          )
1500                         ((consp enc)
1501                          (cdr (assq 'ideographic-structure enc))
1502                          )))
1503         (cond
1504          ((eq (car enc-str) ?⿺)
1505           (unless conversion-only
1506             (setq f-res (ids-find-chars-including-ids enc-str)))
1507           (setq new-str (list ?⿱
1508                               (nth 2 enc-str)
1509                               (nth 2 structure)))
1510           (setq new-str-c
1511                 (if (setq ret (ideographic-structure-find-chars new-str))
1512                     (car ret)
1513                   (list (cons 'ideographic-structure new-str))))
1514           (if conversion-only
1515               (list ?⿺ (nth 1 enc-str) new-str-c)
1516             (setq a-res (ids-find-chars-including-ids new-str))
1517             (list enc
1518                   f-res
1519                   new-str-c
1520                   a-res
1521                   (list ?⿺ (nth 1 enc-str) new-str-c)
1522                   710))
1523           )))
1524       )
1525      ((eq (car structure) ?⿺)
1526       (setq enc (nth 1 structure))
1527       (when (setq enc-str
1528                   (cond ((characterp enc)
1529                          (or (get-char-attribute enc 'ideographic-structure)
1530                              (get-char-attribute enc 'ideographic-structure@apparent))
1531                          )
1532                         ((consp enc)
1533                          (or (cdr (assq 'ideographic-structure enc))
1534                              (cdr (assq 'ideographic-structure@apparent enc)))
1535                          )))
1536         (setq enc-str
1537               (mapcar (lambda (cell)
1538                         (or (and (listp cell)
1539                                  (find-char cell))
1540                             cell))
1541                       enc-str))
1542         (cond
1543          ((eq (car enc-str) ?⿱)
1544           (cond
1545            ((and (characterp (nth 1 enc-str))
1546                  (or (and (eq (char-ucs (nth 1 enc-str)) #x200CA)
1547                           (setq code 811))
1548                      (and (eq (char-feature (nth 1 enc-str) '=>iwds-1) 233)
1549                           (characterp (nth 2 structure))
1550                           (eq (char-ucs (nth 2 structure)) #x4E36)
1551                           (setq code 812))))
1552             (unless conversion-only
1553               (setq f-res (ids-find-chars-including-ids enc-str)))
1554             (setq new-str (list ?⿺
1555                                 (nth 1 enc-str)
1556                                 (nth 2 structure)))
1557             (setq new-str-c
1558                   (if (setq ret (ideographic-structure-find-chars new-str))
1559                       (car ret)
1560                     (list (cons 'ideographic-structure new-str))))
1561             (if conversion-only
1562                 (list ?⿱ new-str-c (nth 2 enc-str))
1563               (setq a-res (ids-find-chars-including-ids new-str))
1564               (list enc
1565                     f-res
1566                     new-str-c
1567                     a-res
1568                     (list ?⿱ new-str-c (nth 2 enc-str))
1569                     code))
1570             )
1571            ((and (characterp (nth 2 enc-str))
1572                  (memq (char-ucs (nth 2 enc-str))
1573                        '(#x4E00
1574                          #x706C
1575                          #x65E5 #x66F0 #x5FC3
1576                          #x2123C #x58EC #x738B #x7389)))
1577             (unless conversion-only
1578               (setq f-res (ids-find-chars-including-ids enc-str)))
1579             (setq new-str (list ?⿰
1580                                 (nth 1 enc-str)
1581                                 (nth 2 structure)))
1582             (setq new-str-c
1583                   (if (setq ret (ideographic-structure-find-chars new-str))
1584                       (car ret)
1585                     (list (cons 'ideographic-structure new-str))))
1586             (if conversion-only
1587                 (list ?⿱ new-str-c (nth 2 enc-str))
1588               (setq a-res (ids-find-chars-including-ids new-str))
1589               (list enc
1590                     f-res
1591                     new-str-c
1592                     a-res
1593                     (list ?⿱ new-str-c (nth 2 enc-str))
1594                     813))
1595             )
1596            ))))
1597       )
1598      ((eq (car structure) ?⿻)
1599       (setq enc (nth 1 structure))
1600       (when (setq enc-str
1601                   (cond ((characterp enc)
1602                          (get-char-attribute enc 'ideographic-structure)
1603                          )
1604                         ((consp enc)
1605                          (cdr (assq 'ideographic-structure enc))
1606                          )))
1607         (cond
1608          ((eq (car enc-str) ?⿱)
1609           (unless conversion-only
1610             (setq f-res (ids-find-chars-including-ids enc-str)))
1611           (if conversion-only
1612               (list ?⿳ (nth 1 enc-str) (nth 2 structure) (nth 2 enc-str))
1613             (list enc
1614                   f-res
1615                   new-str
1616                   nil
1617                   (list ?⿳
1618                         (nth 1 enc-str)
1619                         (nth 2 structure)
1620                         (nth 2 enc-str))
1621                   911))
1622           )))
1623       ))
1624     ))
1625
1626
1627 ;;; @ End.
1628 ;;;
1629
1630 (provide 'ids-find)
1631
1632 ;;; ids-find.el ends here