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