(ideographic-character-get-structure): Convert char-spec to
[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   (mapcar (lambda (cell)
603             (or (and (listp cell)
604                      (find-char cell))
605                 cell))
606           (let (ret)
607             (cond ((characterp character)
608                    (get-char-attribute character 'ideographic-structure)
609                    )
610                   ((setq ret (assq 'ideographic-structure character))
611                    (cdr ret)
612                    )
613                   ((setq ret (find-char character))
614                    (get-char-attribute ret 'ideographic-structure)
615                    )))))
616
617 ;;;###autoload
618 (defun ideographic-char-match-component (char component)
619   "Return non-nil if character CHAR has COMPONENT in ideographic-structure.
620 COMPONENT can be a character or char-spec."
621   (or (ideographic-structure-character= char component)
622       (let ((str (ideographic-character-get-structure char)))
623         (and str
624              (or (ideographic-char-match-component (nth 1 str) component)
625                  (ideographic-char-match-component (nth 2 str) component)
626                  (if (memq (car str) '(?\u2FF2 ?\u2FF3))
627                      (ideographic-char-match-component (nth 3 str) component)))))))
628
629 (defun ideographic-structure-char< (a b)
630   (let ((sa (get-char-attribute a 'ideographic-structure))
631         (sb (get-char-attribute b 'ideographic-structure))
632         tsa tsb)
633     (cond (sa
634            (cond (sb
635                   (setq tsa (char-total-strokes a)
636                         tsb (char-total-strokes b))
637                   (if tsa
638                       (if tsb
639                           (or (< tsa tsb)
640                               (and (= tsa tsb)
641                                    (ideograph-char< a b)))
642                         t)
643                     (if tsb
644                         nil
645                       (ideograph-char< a b))))
646                  (t
647                   nil))
648            )
649           (t
650            (cond (sb
651                   t)
652                  (t
653                   (setq tsa (char-total-strokes a)
654                         tsb (char-total-strokes b))
655                   (if tsa
656                       (if tsb
657                           (or (< tsa tsb)
658                               (and (= tsa tsb)
659                                    (ideograph-char< a b)))
660                         t)
661                     (if tsb
662                         nil
663                       (ideograph-char< a b)))
664                   ))
665            ))
666     ))
667
668 (defun ideo-comp-tree-adjoin (tree char)
669   (let ((rest tree)
670         included ; other
671         dest cell finished)
672     (while (and (not finished)
673                 rest)
674       (setq cell (pop rest))
675       (cond ((ideographic-structure-character= char (car cell))
676              (setq finished t
677                    dest tree
678                    rest nil)
679              )
680             ((ideographic-char-match-component char (car cell))
681              (setq dest
682                    (cons (cons (car cell)
683                                (ideo-comp-tree-adjoin (cdr cell) char))
684                          dest))
685              (setq finished t)
686              )
687             ((ideographic-char-match-component (car cell) char)
688              (setq included (cons cell included))
689              )
690             ;; (included
691             ;;  (setq other (cons cell other))
692             ;;  )
693             (t
694              (setq dest (cons cell dest))
695              )))
696     (cond (finished
697            (nconc dest rest)
698            )
699           (included
700            (cons (cons char included)
701                  (nconc dest rest))
702            )
703           (t
704            (cons (list char) tree)
705            ))))
706
707 (defun ideographic-chars-to-is-a-tree (chars)
708   (let (tree)
709     (dolist (char (sort (copy-list chars) #'ideographic-structure-char<))
710       (setq tree (ideo-comp-tree-adjoin tree char)))
711     tree))
712
713 (defun ids-find-chars-including-ids (structure)
714   (let (comp-alist comp-spec ret str rest)
715     (cond
716      ((characterp structure)
717       (setq rest (copy-list (get-char-attribute structure 'ideographic-products)))
718       )
719      ((setq ret (ideographic-structure-find-chars structure))
720       (dolist (pc ret)
721         (setq rest
722               (union
723                rest
724                (copy-list (get-char-attribute pc 'ideographic-products)))))
725       )
726      (t
727       (setq comp-alist (ideographic-structure-to-components-alist structure)
728             comp-spec (list (cons 'ideographic-structure structure)))
729       (dolist (pc (caar
730                    (sort (mapcar (lambda (cell)
731                                    (if (setq ret (get-char-attribute
732                                                   (car cell) 'ideographic-products))
733                                        (cons ret (length ret))
734                                      (cons nil 0)))
735                                  comp-alist)
736                          (lambda (a b)
737                            (< (cdr a)(cdr b))))))
738         (when (and (every (lambda (cell)
739                             (>= (ideographic-char-count-components pc (car cell))
740                                 (cdr cell)))
741                           comp-alist)
742                    (or (ideographic-char-match-component pc comp-spec)
743                        (and (setq str (get-char-attribute pc 'ideographic-structure))
744                             (ideographic-char-match-component
745                              (list
746                               (cons
747                                'ideographic-structure
748                                (functional-ideographic-structure-to-apparent-structure
749                                 str)))
750                              comp-spec))))
751           (push pc rest)))
752       ))
753     (ideographic-chars-to-is-a-tree rest)))
754
755 (defun functional-ideographic-structure-to-apparent-structure (structure)
756   (ideographic-structure-compare-functional-and-apparent
757    structure nil 'conversion-only))
758
759 ;;;###autoload
760 (defun ideographic-structure-compact (structure)
761   (let ((rest structure)
762         cell
763         ret dest sub)
764     (while rest
765       (setq cell (pop rest))
766       (cond
767        ((and (consp cell)
768              (cond ((setq ret (assq 'ideographic-structure cell))
769                     (setq sub (cdr ret))
770                     )
771                    ((atom (car cell))
772                     (setq sub cell)
773                     )))
774         (setq cell
775               (if (setq ret (ideographic-structure-find-chars sub))
776                   (car ret)
777                 (list (cons 'ideographic-structure sub))))
778         ))
779       (setq dest (cons cell dest)))
780     (nreverse dest)))
781
782 (defun ideographic-structure-compare-functional-and-apparent (structure
783                                                               &optional char
784                                                               conversion-only)
785   (let (enc enc-str enc2-str enc3-str new-str new-str-c f-res a-res ret code)
786     (cond
787      ((eq (car structure) ?⿸)
788       (setq enc (nth 1 structure))
789       (when (setq enc-str
790                   (cond ((characterp enc)
791                          (get-char-attribute enc 'ideographic-structure)
792                          )
793                         ((consp enc)
794                          (cdr (assq 'ideographic-structure enc))
795                          )))
796         (cond
797          ((eq (car enc-str) ?⿰)
798           (unless conversion-only
799             (setq f-res (ids-find-chars-including-ids enc-str)))
800           (setq new-str (list ?⿱
801                               (nth 2 enc-str)
802                               (nth 2 structure)))
803           (setq new-str-c
804                 (if (setq ret (ideographic-structure-find-chars new-str))
805                     (car ret)
806                   (list (cons 'ideographic-structure new-str))))
807           (if conversion-only
808               (list ?⿰ (nth 1 enc-str) new-str-c)
809             (setq a-res (ids-find-chars-including-ids new-str))
810             (list enc
811                   f-res
812                   new-str-c
813                   a-res
814                   (list ?⿰ (nth 1 enc-str) new-str-c)
815                   111))
816           )
817          ((and (eq (car enc-str) ?⿲)
818                (memq (char-ucs (nth 1 enc-str)) '(#x4EBB #x2E85))
819                (eq (nth 2 enc-str) ?丨))
820           (unless conversion-only
821             (setq f-res (ids-find-chars-including-ids enc-str)))
822           (setq new-str (list ?⿱
823                               (nth 3 enc-str)
824                               (nth 2 structure)))
825           (setq new-str-c
826                 (if (setq ret (ideographic-structure-find-chars new-str))
827                     (car ret)
828                   (list (cons 'ideographic-structure new-str))))
829           (if conversion-only
830               (list ?⿰ (decode-char '=big5-cdp #x8B7A) new-str-c)
831             (setq a-res (ids-find-chars-including-ids new-str))
832             (list enc
833                   f-res
834                   new-str-c
835                   a-res
836                   (list ?⿰ (decode-char '=big5-cdp #x8B7A) new-str-c)
837                   112))
838           )
839          ((eq (car enc-str) ?⿱)
840           (unless conversion-only
841             (setq f-res (ids-find-chars-including-ids enc-str)))
842           (setq new-str
843                 (list
844                  (cond
845                   ((characterp (nth 2 enc-str))
846                    (if (or (memq (encode-char (nth 2 enc-str) '=>ucs@component)
847                                  '(#x20087 #x5382 #x4E06))
848                            (eq (encode-char (nth 2 enc-str) '=>ucs@iwds-1)
849                                #x4E06)
850                            (eq (encode-char (nth 2 enc-str) '=ucs-itaiji-001)
851                                #x2E282)
852                            (eq (encode-char (nth 2 enc-str) '=big5-cdp)
853                                #x89CE)
854                            (eq (encode-char (nth 2 enc-str) '=>big5-cdp)
855                                #x88E2)
856                            (eq (encode-char (nth 2 enc-str) '=big5-cdp)
857                                #x88AD)
858                            (eq (or (encode-char (nth 2 enc-str) '=>big5-cdp)
859                                    (encode-char (nth 2 enc-str) '=big5-cdp-itaiji-001))
860                                #x8766)
861                            (eq (car (get-char-attribute (nth 2 enc-str)
862                                                         'ideographic-structure))
863                                ?⿸))
864                        ?⿸
865                      ?⿰))
866                   ((eq (car (cdr (assq 'ideographic-structure (nth 2 enc-str))))
867                        ?⿸)
868                    ?⿸)
869                   (t
870                    ?⿰))
871                  (nth 2 enc-str)
872                  (nth 2 structure)))
873           (setq new-str-c
874                 (if (setq ret (ideographic-structure-find-chars new-str))
875                     (car ret)
876                   (list (cons 'ideographic-structure new-str))))
877           (if conversion-only
878               (list ?⿱ (nth 1 enc-str) new-str-c)
879             (setq a-res (ids-find-chars-including-ids new-str))
880             (list enc
881                   f-res
882                   new-str-c
883                   a-res
884                   (list ?⿱ (nth 1 enc-str) new-str-c)
885                   (if (eq (car new-str) ?⿸)
886                       121
887                     122)))
888           )
889          ((eq (car enc-str) ?⿸)
890           (unless conversion-only
891             (setq f-res (ids-find-chars-including-ids enc-str)))
892           (setq new-str (list (cond
893                                ((characterp (nth 2 enc-str))
894                                 (if (memq (char-ucs (nth 2 enc-str))
895                                           '(#x5F73))
896                                     ?⿰
897                                   ?⿱)
898                                 )
899                                (t
900                                 ?⿱))
901                               (nth 2 enc-str)
902                               (nth 2 structure)))
903           (setq new-str-c
904                 (if (setq ret (ideographic-structure-find-chars new-str))
905                     (car ret)
906                   (list (cons 'ideographic-structure new-str))))
907           (if conversion-only
908               (list ?⿸ (nth 1 enc-str) new-str-c)
909             (setq a-res (ids-find-chars-including-ids new-str))
910             (list enc
911                   f-res
912                   new-str-c
913                   a-res
914                   (list ?⿸ (nth 1 enc-str) new-str-c)
915                   (if (eq (car new-str) ?⿰)
916                       131
917                     132)))
918           )))
919       )
920      ((eq (car structure) ?⿹)
921       (setq enc (nth 1 structure))
922       (when (setq enc-str
923                   (cond ((characterp enc)
924                          (get-char-attribute enc 'ideographic-structure)
925                          )
926                         ((consp enc)
927                          (cdr (assq 'ideographic-structure enc))
928                          )))
929         (cond
930          ((eq (car enc-str) ?⿰)
931           (unless conversion-only
932             (setq f-res (ids-find-chars-including-ids enc-str)))
933           (setq new-str (list ?⿱
934                               (nth 1 enc-str)
935                               (nth 2 structure)))
936           (setq new-str-c
937                 (if (setq ret (ideographic-structure-find-chars new-str))
938                     (car ret)
939                   (list (cons 'ideographic-structure new-str))))
940           (if conversion-only
941               (list ?⿰ new-str-c (nth 2 enc-str))
942             (setq a-res (ids-find-chars-including-ids new-str))
943             (list enc
944                   f-res
945                   new-str-c
946                   a-res
947                   (list ?⿰ new-str-c (nth 2 enc-str))
948                   210))
949           )))
950       )
951      ((eq (get-char-attribute (car structure) '=ucs-itaiji-001) #x2FF6)
952       (setq enc (nth 1 structure))
953       (when (setq enc-str
954                   (cond ((characterp enc)
955                          (get-char-attribute enc 'ideographic-structure)
956                          )
957                         ((consp enc)
958                          (cdr (assq 'ideographic-structure enc))
959                          )))
960         (cond
961          ((eq (car enc-str) ?⿺)
962           (unless conversion-only
963             (setq f-res (ids-find-chars-including-ids enc-str)))
964           (setq new-str (list ?⿱
965                               (nth 2 structure)
966                               (nth 1 enc-str)))
967           (setq new-str-c
968                 (if (setq ret (ideographic-structure-find-chars new-str))
969                     (car ret)
970                   (list (cons 'ideographic-structure new-str))))
971           (if conversion-only
972               (list ?⿺ new-str-c (nth 2 enc-str))
973             (setq a-res (ids-find-chars-including-ids new-str))
974             (list enc
975                   f-res
976                   new-str-c
977                   a-res
978                   (list ?⿺ new-str-c (nth 2 enc-str))
979                   310))
980           )
981          ((eq (car enc-str) ?⿱)
982           (unless conversion-only
983             (setq f-res (ids-find-chars-including-ids enc-str)))
984           (setq new-str (list ?⿰
985                               (nth 2 structure)
986                               (nth 1 enc-str)))
987           (setq new-str-c
988                 (if (setq ret (ideographic-structure-find-chars new-str))
989                     (car ret)
990                   (list (cons 'ideographic-structure new-str))))
991           (if conversion-only
992               (list ?⿱ new-str-c (nth 2 enc-str))
993             (setq a-res (ids-find-chars-including-ids new-str))
994             (list enc
995                   f-res
996                   new-str-c
997                   a-res
998                   (list ?⿱ new-str-c (nth 2 enc-str))
999                   320))
1000           )
1001          ((eq (car enc-str) ?⿰)
1002           (unless conversion-only
1003             (setq f-res (ids-find-chars-including-ids enc-str)))
1004           (setq new-str (list ?⿱
1005                               (nth 2 structure)
1006                               (nth 1 enc-str)))
1007           (setq new-str-c
1008                 (if (setq ret (ideographic-structure-find-chars new-str))
1009                     (car ret)
1010                   (list (cons 'ideographic-structure new-str))))
1011           (if conversion-only
1012               (list ?⿰ new-str-c (nth 2 enc-str))
1013             (setq a-res (ids-find-chars-including-ids new-str))
1014             (list enc
1015                   f-res
1016                   new-str-c
1017                   a-res
1018                   (list ?⿰ new-str-c (nth 2 enc-str))
1019                   330))
1020           ))
1021         )
1022       )
1023      ((eq (car structure) ?⿴)
1024       (setq enc (nth 1 structure))
1025       (when (setq enc-str
1026                   (cond ((characterp enc)
1027                          (get-char-attribute enc 'ideographic-structure)
1028                          )
1029                         ((consp enc)
1030                          (cdr (assq 'ideographic-structure enc))
1031                          )))
1032         (cond
1033          ((eq (car enc-str) ?⿱)
1034           (cond
1035            ((and (characterp (nth 2 enc-str))
1036                  (or (memq (char-ucs (nth 2 enc-str)) '(#x56D7 #x5F51 #x897F))
1037                      (eq (char-feature (nth 2 enc-str) '=>big5-cdp)
1038                          #x87A5)))
1039             (unless conversion-only
1040               (setq f-res (ids-find-chars-including-ids enc-str)))
1041             (setq new-str (list ?⿴
1042                                 (nth 2 enc-str)
1043                                 (nth 2 structure)))
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 ?⿱ (nth 1 enc-str) new-str-c)
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 ?⿱ (nth 1 enc-str) new-str-c)
1056                     411))
1057             )
1058            ((and (characterp (nth 2 enc-str))
1059                  (eq (char-ucs (nth 2 enc-str)) #x51F5))
1060             (unless conversion-only
1061               (setq f-res (ids-find-chars-including-ids enc-str)))
1062             (setq new-str (list ?⿶
1063                                 (nth 2 enc-str)
1064                                 (nth 2 structure)))
1065             (setq new-str-c
1066                   (if (setq ret (ideographic-structure-find-chars new-str))
1067                       (car ret)
1068                     (list (cons 'ideographic-structure new-str))))
1069             (if conversion-only
1070                 (list ?⿱ (nth 1 enc-str) new-str-c)
1071               (setq a-res (ids-find-chars-including-ids new-str))
1072               (list enc
1073                     f-res
1074                     new-str-c
1075                     a-res
1076                     (list ?⿱ (nth 1 enc-str) new-str-c)
1077                     412))
1078             )       
1079            ((and (characterp (nth 1 enc-str))
1080                  (eq (char-feature (nth 1 enc-str) '=>ucs@component)
1081                      #x300E6))
1082             (unless conversion-only
1083               (setq f-res (ids-find-chars-including-ids enc-str)))
1084             (setq new-str (list ?⿵
1085                                 (nth 1 enc-str)
1086                                 (nth 2 structure)))
1087             (setq new-str-c
1088                   (if (setq ret (ideographic-structure-find-chars new-str))
1089                       (car ret)
1090                     (list (cons 'ideographic-structure new-str))))
1091             (if conversion-only
1092                 (list ?⿱ new-str-c (nth 2 enc-str))
1093               (setq a-res (ids-find-chars-including-ids new-str))
1094               (list enc
1095                     f-res
1096                     new-str-c
1097                     a-res
1098                     (list ?⿱ new-str-c (nth 2 enc-str))
1099                     413))
1100             )
1101            (t
1102             (unless conversion-only
1103               (setq f-res (ids-find-chars-including-ids enc-str)))
1104             (setq new-str (list ?⿱ (nth 2 structure) (nth 2 enc-str)))
1105             (setq new-str-c
1106                   (if (setq ret (ideographic-structure-find-chars new-str))
1107                       (car ret)
1108                     (list (cons 'ideographic-structure new-str))))
1109             (if conversion-only
1110                 (list ?⿱ (nth 1 enc-str) new-str-c)
1111               (setq a-res (ids-find-chars-including-ids new-str))
1112               (list enc
1113                     f-res
1114                     new-str-c
1115                     a-res
1116                     (list ?⿱ (nth 1 enc-str) new-str-c)
1117                     414))
1118             ))
1119           )
1120          ((eq (car enc-str) ?⿳)
1121           (cond
1122            ((and (characterp (nth 2 enc-str))
1123                  (eq (char-ucs (nth 2 enc-str)) #x56D7))
1124             (unless conversion-only
1125               (setq f-res (ids-find-chars-including-ids enc-str)))
1126             (setq new-str (list ?⿴ (nth 2 enc-str) (nth 2 structure)))
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 ?⿱ (nth 1 enc-str) new-str-c))
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                     415))
1145             )
1146            ((and (characterp (nth 2 enc-str))
1147                  (eq (char-ucs (nth 2 enc-str)) #x5196))
1148             (unless conversion-only
1149               (setq f-res (ids-find-chars-including-ids enc-str)))
1150             (setq new-str (list ?⿱ (nth 1 enc-str) (nth 2 enc-str)))
1151             (setq new-str-c
1152                   (if (setq ret (ideographic-structure-find-chars new-str))
1153                       (car ret)
1154                     (list (cons 'ideographic-structure new-str))))
1155             (setq new-str (list ?⿱ new-str-c (nth 2 structure)))
1156             (setq new-str-c
1157                   (if (setq ret (ideographic-structure-find-chars new-str))
1158                       (car ret)
1159                     (list (cons 'ideographic-structure new-str))))
1160             (if conversion-only
1161                 (list ?⿱ new-str-c (nth 3 enc-str))
1162               (setq a-res (ids-find-chars-including-ids new-str))
1163               (list enc
1164                     f-res
1165                     new-str-c
1166                     a-res
1167                     (list ?⿱ new-str-c (nth 3 enc-str))
1168                     416))
1169             )
1170            ((and (characterp (nth 2 enc-str))
1171                  (or (eq (encode-char (nth 2 enc-str) '=>big5-cdp)
1172                          #x89A6)
1173                      (eq (encode-char (nth 2 enc-str) '=>gt-k)
1174                          146)
1175                      (eq (char-ucs (nth 2 enc-str)) #x2008A)))
1176             (unless conversion-only
1177               (setq f-res (ids-find-chars-including-ids enc-str)))
1178             (setq new-str (list ?⿱ (nth 2 structure) (nth 2 enc-str)))
1179             (setq new-str-c
1180                   (if (setq ret (ideographic-structure-find-chars new-str))
1181                       (car ret)
1182                     (list (cons 'ideographic-structure new-str))))
1183             (setq new-str (list ?⿸ new-str-c (nth 3 enc-str)))
1184             (setq new-str-c
1185                   (if (setq ret (ideographic-structure-find-chars new-str))
1186                       (car ret)
1187                     (list (cons 'ideographic-structure new-str))))
1188             (if conversion-only
1189                 (list ?⿱ (nth 1 enc-str) new-str-c)
1190               (setq a-res (ids-find-chars-including-ids new-str))
1191               (list enc
1192                     f-res
1193                     new-str-c
1194                     a-res
1195                     (list ?⿱ (nth 1 enc-str) new-str-c)
1196                     417))
1197             )
1198            (t
1199             (unless conversion-only
1200               (setq f-res (ids-find-chars-including-ids enc-str)))
1201             (setq new-str (list ?⿻ (nth 2 enc-str) (nth 2 structure)))
1202             (setq new-str-c
1203                   (if (setq ret (ideographic-structure-find-chars new-str))
1204                       (car ret)
1205                     (list (cons 'ideographic-structure new-str))))
1206             (setq new-str (list ?⿱ (nth 1 enc-str) new-str-c))
1207             (setq new-str-c
1208                   (if (setq ret (ideographic-structure-find-chars new-str))
1209                       (car ret)
1210                     (list (cons 'ideographic-structure new-str))))
1211             (if conversion-only
1212                 (list ?⿱  new-str-c (nth 3 enc-str))
1213               (setq a-res (ids-find-chars-including-ids new-str))
1214               (list enc
1215                     f-res
1216                     new-str-c
1217                     a-res
1218                     (list ?⿱  new-str-c (nth 3 enc-str))
1219                     419))
1220             ))
1221           )
1222          ((eq (car enc-str) ?⿰)
1223           (cond
1224            ((equal (nth 1 enc-str)(nth 2 enc-str))
1225             (unless conversion-only
1226               (setq f-res (ids-find-chars-including-ids enc-str)))
1227             (setq new-str (list ?⿲
1228                                 (nth 1 enc-str)
1229                                 (nth 2 structure)
1230                                 (nth 2 enc-str)))
1231             (setq new-str-c
1232                   (list (cons 'ideographic-structure new-str)))
1233             (if conversion-only
1234                 new-str
1235               (setq a-res (ids-find-chars-including-ids new-str))
1236               (list enc
1237                     f-res
1238                     new-str-c
1239                     a-res
1240                     new-str
1241                     421))
1242             )
1243            (t
1244             (unless conversion-only
1245               (setq f-res (ids-find-chars-including-ids enc-str)))
1246             (setq new-str (list ?⿰
1247                                 (nth 2 structure)
1248                                 (nth 2 enc-str)))
1249             (setq new-str-c
1250                   (if (setq ret (ideographic-structure-find-chars new-str))
1251                       (car ret)
1252                     (list (cons 'ideographic-structure new-str))))
1253             (if conversion-only
1254                 (list ?⿰ (nth 1 enc-str) new-str-c)
1255               (setq a-res (ids-find-chars-including-ids new-str))
1256               (list enc
1257                     f-res
1258                     new-str-c
1259                     a-res
1260                     (list ?⿰ (nth 1 enc-str) new-str-c)
1261                     422))
1262             ))
1263           ))
1264         )
1265       )
1266      ((eq (car structure) ?⿶)
1267       (setq enc (nth 1 structure))
1268       (when (setq enc-str
1269                   (cond ((characterp enc)
1270                          (get-char-attribute enc 'ideographic-structure)
1271                          )
1272                         ((consp enc)
1273                          (cdr (assq 'ideographic-structure enc))
1274                          )))
1275         (cond
1276          ((eq (car enc-str) ?⿱)
1277           (setq enc2-str (ideographic-character-get-structure (nth 1 enc-str)))
1278           (when (and enc2-str
1279                      (eq (car enc2-str) ?⿰))
1280             (unless conversion-only
1281               (setq f-res (ids-find-chars-including-ids enc-str)))
1282             (setq new-str (list ?⿲
1283                                 (nth 1 enc2-str)
1284                                 (nth 2 structure)
1285                                 (nth 2 enc2-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 ?⿱ new-str-c (nth 2 enc-str))
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 ?⿱ new-str-c (nth 2 enc-str))
1298                     511))
1299             )
1300           )
1301          ((eq (car enc-str) ?⿳)
1302           (setq enc2-str (ideographic-character-get-structure (nth 1 enc-str)))
1303           (when (and enc2-str
1304                      (eq (car enc2-str) ?⿰))
1305             (unless conversion-only
1306               (setq f-res (ids-find-chars-including-ids enc-str)))
1307             (setq new-str (list ?⿲
1308                                 (nth 1 enc2-str)
1309                                 (nth 2 structure)
1310                                 (nth 2 enc2-str)))
1311             (setq new-str-c
1312                   (if (setq ret (ideographic-structure-find-chars new-str))
1313                       (car ret)
1314                     (list (cons 'ideographic-structure new-str))))
1315             (if conversion-only
1316                 (list ?⿳ new-str-c (nth 2 enc-str) (nth 3 enc-str))
1317               (setq a-res (ids-find-chars-including-ids new-str))
1318               (list enc
1319                     f-res
1320                     new-str-c
1321                     a-res
1322                     (list ?⿳ new-str-c (nth 2 enc-str) (nth 3 enc-str))
1323                     512))
1324             )
1325           )
1326          ((eq (car enc-str) ?⿲)
1327           (unless conversion-only
1328             (setq f-res (ids-find-chars-including-ids enc-str)))
1329           (setq new-str (list ?⿱
1330                               (nth 2 structure)
1331                               (nth 2 enc-str)))
1332           (setq new-str-c
1333                 (if (setq ret (ideographic-structure-find-chars new-str))
1334                     (car ret)
1335                   (list (cons 'ideographic-structure new-str))))
1336           (if conversion-only
1337               (list ?⿲ (nth 1 enc-str) new-str-c (nth 3 enc-str))
1338             (setq a-res (ids-find-chars-including-ids new-str))
1339             (list enc
1340                   f-res
1341                   new-str-c
1342                   a-res
1343                   (list ?⿲ (nth 1 enc-str) new-str-c (nth 3 enc-str))
1344                   520))
1345           )
1346          ((eq (car enc-str) ?⿴)
1347           (setq enc2-str (ideographic-character-get-structure (nth 1 enc-str)))
1348           (when (and enc2-str
1349                      (eq (car enc2-str) ?⿰))
1350             (unless conversion-only
1351               (setq f-res (ids-find-chars-including-ids enc-str)))
1352             (setq new-str (list ?⿱
1353                                 (nth 2 structure)
1354                                 (nth 2 enc-str)))
1355             (setq new-str-c
1356                   (if (setq ret (ideographic-structure-find-chars new-str))
1357                       (car ret)
1358                     (list (cons 'ideographic-structure new-str))))
1359             (if conversion-only
1360                 (list ?⿲ (nth 1 enc2-str) new-str-c (nth 2 enc2-str))
1361               (setq a-res (ids-find-chars-including-ids new-str))
1362               (list enc
1363                     f-res
1364                     new-str-c
1365                     a-res
1366                     (list ?⿲ (nth 1 enc2-str) new-str-c (nth 2 enc2-str))
1367                     530))
1368             )
1369           )))
1370       )
1371      ((eq (car structure) ?⿵)
1372       (setq enc (nth 1 structure))
1373       (when (setq enc-str
1374                   (cond ((characterp enc)
1375                          (get-char-attribute enc 'ideographic-structure)
1376                          )
1377                         ((consp enc)
1378                          (cdr (assq 'ideographic-structure enc))
1379                          )))
1380         (cond
1381          ((eq (car enc-str) ?⿱)         
1382           (cond
1383            ((and (characterp (nth 2 enc-str))
1384                  (memq (char-ucs (nth 2 enc-str))
1385                        '(#x9580 #x9B25)))
1386             (unless conversion-only
1387               (setq f-res (ids-find-chars-including-ids enc-str)))
1388             (setq new-str (list ?⿵
1389                                 (nth 2 enc-str)
1390                                 (nth 2 structure)))
1391             (setq new-str-c
1392                   (if (setq ret (ideographic-structure-find-chars new-str))
1393                       (car ret)
1394                     (list (cons 'ideographic-structure new-str))))
1395             (if conversion-only
1396                 (list ?⿱ (nth 1 enc-str) new-str-c)
1397               (setq a-res (ids-find-chars-including-ids new-str))
1398               (list enc
1399                     f-res
1400                     new-str-c
1401                     a-res
1402                     (list ?⿱ (nth 1 enc-str) new-str-c)
1403                     601))
1404             )
1405            ((and (setq enc2-str (ideographic-character-get-structure (nth 2 enc-str)))
1406                  (cond
1407                   ((eq (car enc2-str) ?⿰)
1408                    (setq code 611)
1409                    )
1410                   ((and (eq (car enc2-str) ?⿱)
1411                         (setq enc3-str
1412                               (ideographic-character-get-structure (nth 2 enc2-str)))
1413                         (eq (car enc3-str) ?⿰))
1414                    (setq code 613)
1415                    )))
1416             (unless conversion-only
1417               (setq f-res (ids-find-chars-including-ids enc-str)))
1418             (setq new-str
1419                   (cond ((eq code 611)
1420                          (list ?⿲
1421                                (nth 1 enc2-str)
1422                                (nth 2 structure)
1423                                (nth 2 enc2-str))
1424                          )
1425                         ((eq code 613)
1426                          (list ?⿲
1427                                (nth 1 enc3-str)
1428                                (nth 2 structure)
1429                                (nth 2 enc3-str))
1430                          )))
1431             (setq new-str-c
1432                   (if (setq ret (ideographic-structure-find-chars new-str))
1433                       (car ret)
1434                     (list (cons 'ideographic-structure new-str))))
1435             (if conversion-only
1436                 (cond ((eq code 611)
1437                        (list ?⿱ (nth 1 enc-str) new-str-c)
1438                        )
1439                       ((eq code 613)
1440                        (list ?⿳ (nth 1 enc-str)(nth 1 enc2-str) new-str-c)
1441                        ))
1442               (setq a-res (ids-find-chars-including-ids new-str))
1443               (list enc
1444                     f-res
1445                     new-str-c
1446                     a-res
1447                     (cond ((eq code 611)
1448                            (list ?⿱ (nth 1 enc-str) new-str-c)
1449                            )
1450                           ((eq code 613)
1451                            (list ?⿳ (nth 1 enc-str)(nth 1 enc2-str) new-str-c)
1452                            ))
1453                     code))
1454             ))
1455           )
1456          ((eq (car enc-str) ?⿳)
1457           (setq enc2-str (ideographic-character-get-structure (nth 3 enc-str)))
1458           (when (and enc2-str
1459                      (eq (car enc2-str) ?⿰))
1460             (unless conversion-only
1461               (setq f-res (ids-find-chars-including-ids enc-str)))
1462             (setq new-str (list ?⿲
1463                                 (nth 1 enc2-str)
1464                                 (nth 2 structure)
1465                                 (nth 2 enc2-str)))
1466             (setq new-str-c
1467                   (if (setq ret (ideographic-structure-find-chars new-str))
1468                       (car ret)
1469                     (list (cons 'ideographic-structure new-str))))
1470             (if conversion-only
1471                 (list ?⿳ (nth 1 enc-str) (nth 2 enc-str) new-str-c)
1472               (setq a-res (ids-find-chars-including-ids new-str))
1473               (list enc
1474                     f-res
1475                     new-str-c
1476                     a-res
1477                     (list ?⿳ (nth 1 enc-str) (nth 2 enc-str) new-str-c)
1478                     612))
1479             )
1480           )
1481          ((eq (car enc-str) ?⿲)
1482           (unless conversion-only
1483             (setq f-res (ids-find-chars-including-ids enc-str)))
1484           (setq new-str (list ?⿱
1485                               (nth 2 enc-str)
1486                               (nth 2 structure)))
1487           (setq new-str-c
1488                 (if (setq ret (ideographic-structure-find-chars new-str))
1489                     (car ret)
1490                   (list (cons 'ideographic-structure new-str))))
1491           (if conversion-only
1492               (list ?⿲ (nth 1 enc-str) new-str-c (nth 3 enc-str))
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                   (list ?⿲ (nth 1 enc-str) new-str-c (nth 3 enc-str))
1499                   620))
1500           )
1501          ((eq (car enc-str) ?⿴)
1502           (setq enc2-str (ideographic-character-get-structure (nth 1 enc-str)))
1503           (when (and enc2-str
1504                      (eq (car enc2-str) ?⿰))
1505             (unless conversion-only
1506               (setq f-res (ids-find-chars-including-ids enc-str)))
1507             (setq new-str (list ?⿱
1508                                 (nth 2 enc-str)
1509                                 (nth 2 structure)))
1510             (setq new-str-c
1511                   (if (setq ret (ideographic-structure-find-chars new-str))
1512                       (car ret)
1513                     (list (cons 'ideographic-structure new-str))))
1514             (if conversion-only
1515                 (list ?⿲ (nth 1 enc2-str) new-str-c (nth 2 enc2-str))
1516               (setq a-res (ids-find-chars-including-ids new-str))
1517               (list enc
1518                     f-res
1519                     new-str-c
1520                     a-res
1521                     (list ?⿲ (nth 1 enc2-str) new-str-c (nth 2 enc2-str))
1522                     630))
1523             )
1524           )))
1525       )
1526      ((eq (car structure) ?⿷)
1527       (setq enc (nth 1 structure))
1528       (when (setq enc-str
1529                   (cond ((characterp enc)
1530                          (get-char-attribute enc 'ideographic-structure)
1531                          )
1532                         ((consp enc)
1533                          (cdr (assq 'ideographic-structure enc))
1534                          )))
1535         (cond
1536          ((eq (car enc-str) ?⿺)
1537           (unless conversion-only
1538             (setq f-res (ids-find-chars-including-ids enc-str)))
1539           (setq new-str (list ?⿱
1540                               (nth 2 enc-str)
1541                               (nth 2 structure)))
1542           (setq new-str-c
1543                 (if (setq ret (ideographic-structure-find-chars new-str))
1544                     (car ret)
1545                   (list (cons 'ideographic-structure new-str))))
1546           (if conversion-only
1547               (list ?⿺ (nth 1 enc-str) new-str-c)
1548             (setq a-res (ids-find-chars-including-ids new-str))
1549             (list enc
1550                   f-res
1551                   new-str-c
1552                   a-res
1553                   (list ?⿺ (nth 1 enc-str) new-str-c)
1554                   710))
1555           )))
1556       )
1557      ((eq (car structure) ?⿺)
1558       (setq enc (nth 1 structure))
1559       (when (setq enc-str
1560                   (cond ((characterp enc)
1561                          (or (get-char-attribute enc 'ideographic-structure)
1562                              (get-char-attribute enc 'ideographic-structure@apparent))
1563                          )
1564                         ((consp enc)
1565                          (or (cdr (assq 'ideographic-structure enc))
1566                              (cdr (assq 'ideographic-structure@apparent enc)))
1567                          )))
1568         ;; (setq enc-str
1569         ;;       (mapcar (lambda (cell)
1570         ;;                 (or (and (listp cell)
1571         ;;                          (find-char cell))
1572         ;;                     cell))
1573         ;;               enc-str))
1574         (cond
1575          ((eq (car enc-str) ?⿱)
1576           (cond
1577            ((and (characterp (nth 1 enc-str))
1578                  (or (and (eq (char-ucs (nth 1 enc-str)) #x200CA)
1579                           (setq code 811))
1580                      (and (eq (char-feature (nth 1 enc-str) '=>iwds-1) 233)
1581                           (characterp (nth 2 structure))
1582                           (eq (char-ucs (nth 2 structure)) #x4E36)
1583                           (setq code 812))))
1584             (unless conversion-only
1585               (setq f-res (ids-find-chars-including-ids enc-str)))
1586             (setq new-str (list ?⿺
1587                                 (nth 1 enc-str)
1588                                 (nth 2 structure)))
1589             (setq new-str-c
1590                   (if (setq ret (ideographic-structure-find-chars new-str))
1591                       (car ret)
1592                     (list (cons 'ideographic-structure new-str))))
1593             (if conversion-only
1594                 (list ?⿱ new-str-c (nth 2 enc-str))
1595               (setq a-res (ids-find-chars-including-ids new-str))
1596               (list enc
1597                     f-res
1598                     new-str-c
1599                     a-res
1600                     (list ?⿱ new-str-c (nth 2 enc-str))
1601                     code))
1602             )
1603            ((and (characterp (nth 2 enc-str))
1604                  (memq (char-ucs (nth 2 enc-str))
1605                        '(#x4E00
1606                          #x706C
1607                          #x65E5 #x66F0 #x5FC3
1608                          #x2123C #x58EC #x738B #x7389)))
1609             (unless conversion-only
1610               (setq f-res (ids-find-chars-including-ids enc-str)))
1611             (setq new-str (list ?⿰
1612                                 (nth 1 enc-str)
1613                                 (nth 2 structure)))
1614             (setq new-str-c
1615                   (if (setq ret (ideographic-structure-find-chars new-str))
1616                       (car ret)
1617                     (list (cons 'ideographic-structure new-str))))
1618             (if conversion-only
1619                 (list ?⿱ new-str-c (nth 2 enc-str))
1620               (setq a-res (ids-find-chars-including-ids new-str))
1621               (list enc
1622                     f-res
1623                     new-str-c
1624                     a-res
1625                     (list ?⿱ new-str-c (nth 2 enc-str))
1626                     813))
1627             )
1628            ))))
1629       )
1630      ((eq (car structure) ?⿻)
1631       (setq enc (nth 1 structure))
1632       (when (setq enc-str
1633                   (cond ((characterp enc)
1634                          (get-char-attribute enc 'ideographic-structure)
1635                          )
1636                         ((consp enc)
1637                          (cdr (assq 'ideographic-structure enc))
1638                          )))
1639         (cond
1640          ((eq (car enc-str) ?⿱)
1641           (unless conversion-only
1642             (setq f-res (ids-find-chars-including-ids enc-str)))
1643           (if conversion-only
1644               (list ?⿳ (nth 1 enc-str) (nth 2 structure) (nth 2 enc-str))
1645             (list enc
1646                   f-res
1647                   new-str
1648                   nil
1649                   (list ?⿳
1650                         (nth 1 enc-str)
1651                         (nth 2 structure)
1652                         (nth 2 enc-str))
1653                   911))
1654           )))
1655       ))
1656     ))
1657
1658
1659 ;;; @ End.
1660 ;;;
1661
1662 (provide 'ids-find)
1663
1664 ;;; ids-find.el ends here