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