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