egg-980315.
[elisp/egg.git] / egg-cnv.el
index 267213b..b85cd04 100644 (file)
 
 ;;; Code:
 
+(defvar egg-current-language)
+(make-variable-buffer-local 'egg-current-language)
+(put 'egg-current-language 'permanent-local t)
+
 (defsubst egg-bunsetsu-info () 'intangible)
 
 (defun egg-get-bunsetsu-info (p)
-  (let ((info (get-text-property p (egg-bunsetsu-info))))
-    (cond
-     ((consp info)
-      (setq egg-conversion-backend (car info))
-      (cdr info)))))
+  (let ((bunsetsu-info (get-text-property p (egg-bunsetsu-info))))
+    (if bunsetsu-info
+       (setq egg-conversion-backend (get-text-property p 'egg-backend)
+             egg-current-language (get-text-property p 'egg-lang)))
+    bunsetsu-info))
 ;;
 
+(defconst egg-conversion-backend-other-languages
+  [ egg-init-other-languages
+
+        egg-start-conversion-other-languages
+      egg-get-bunsetsu-converted-other-languages
+      egg-get-bunsetsu-source-other-languages
+      egg-list-candidates-other-languages
+          egg-get-number-of-candidates-other-languages
+          egg-get-current-candidate-number-other-languages
+          egg-get-all-candidates-other-languages
+          egg-decide-candidate-other-languages
+      egg-change-bunsetsu-length-other-languages
+    egg-end-conversion-other-languages
+    nil
+
+    egg-fini-other-languages
+ ])
+
+(defun egg-init-other-languages ()
+  )
+
+(defun egg-start-conversion-other-languages (yomi-string language)
+  (list yomi-string))
+(defun egg-get-bunsetsu-converted-other-languages (bunsetsu-info)
+  bunsetsu-info)
+(defun egg-get-bunsetsu-source-other-languages (bunsetsu-info)
+  bunsetsu-info)
+(defun egg-list-candidates-other-languages (bunsetsu-info prev-bunsetsu-info)
+  1)
+(defun egg-get-number-of-candidates-other-languages (bunsetsu-info)
+  1)
+(defun egg-get-current-candidate-number-other-languages (bunsetsu-info)
+  0)
+(defun egg-get-all-candidates-other-languages (bunsetsu-info)
+  (list bunsetsu-info))
+(defun egg-decide-candidate-other-languages (bunsetsu-info candidate-pos)
+  bunsetsu-info)
+(defun egg-change-bunsetsu-length-other-languages (b0 b1 b2 len)
+  (let ((s (concat b1 b2)))
+    (set-text-properties 0 (length s) nil s)
+    (if (= len (length s))
+       (list s)
+      (list (substring s 0 len) (substring s len)))))
+(defun egg-end-conversion-other-languages (bunsetsu-info-list)
+  nil)
+(defun egg-fini-other-languages (language)
+  nil)
+
 (defvar egg-conversion-backend-alist nil)
 (make-variable-buffer-local 'egg-conversion-backend-alist)
 (defvar egg-conversion-backend nil)
 (defvar egg-finalize-backend-alist nil)
 
 (defun egg-set-current-backend (language)
-  (let ((backend (assoc lang  egg-conversion-backend-alist)))
-    (if (null backend)
-       (error "%S is not supported" lang)
-      (setq egg-conversion-backend (cdr backend)))))
+  (setq egg-conversion-backend
+       (cdr (assoc language egg-conversion-backend-alist)))
+  (if (null egg-conversion-backend)
+      (setq egg-conversion-backend egg-conversion-backend-other-languages)))
 
 (defun egg-initialize-backend (language)
   (egg-set-current-backend language)
   (funcall (aref egg-conversion-backend 9) b0 b1 b2 len))
 (defun egg-end-conversion (bunsetsu-info-list)
   (funcall (aref egg-conversion-backend 10) bunsetsu-info-list))
+(defun egg-start-reverse-conversion (yomi-string language)
+  (egg-set-current-backend language)
+  (if (aref egg-conversion-backend 11)
+      (funcall (aref egg-conversion-backend 11) yomi-string language)
+    (beep)))
 
 (defun egg-finalize-backend ()
   (let ((alist egg-finalize-backend-alist))
       (funcall (car (car (car alist))) (cdr (car (car alist))))
       (setq alist (cdr alist)))))
 
-(defmacro egg-set-conversion-backend-internal (backend langs &optional force)
-  `(let ((l ,langs) pair)
-     (while l
-       (setq pair (assoc (car l) egg-conversion-backend-alist))
-       (if (null pair)
-          (setq egg-conversion-backend-alist 
-                (cons (cons (car l) ,backend)
-                      egg-conversion-backend-alist))
-        ,(if force `(setcdr pair ,backend)))
-       (setq pair (cons (aref ,backend 11) (car l)))
-       (if (null (assoc pair egg-finalize-backend-alist))
-          (setq egg-finalize-backend-alist
-                (cons (list pair) egg-finalize-backend-alist)))
-       (setq l (cdr l)))))
-
-(defun egg-set-conversion-backend (backend curent-langs other-langs)
-  (egg-set-conversion-backend-internal backend curent-langs t)
-  (egg-set-conversion-backend-internal backend other-langs))
+(defun egg-set-conversion-backend (backend langs &optional force)
+  (let (pair)
+    (if backend
+       (setq egg-conversion-backend backend)
+      (setq backend egg-conversion-backend))
+    (while langs
+      (setq pair (assoc (car langs) egg-conversion-backend-alist))
+      (cond
+       ((null pair)
+       (setq egg-conversion-backend-alist
+             (cons (cons (car langs) backend) egg-conversion-backend-alist)))
+       (force
+       (setcdr pair backend)))
+      (setq pair (cons (aref backend (1- (length backend))) (car langs)))
+      (if (null (assoc pair egg-finalize-backend-alist))
+         (setq egg-finalize-backend-alist
+               (cons (list pair) egg-finalize-backend-alist)))
+      (setq langs (cdr langs)))))
 \f
-(defvar egg-conversion-open "|")
-(defvar egg-conversion-close "|")
+(defvar egg-conversion-open  "|"  "*\e$B%U%'%s%9$N;OE@$r<($9J8;zNs\e(B (1 \e$BJ8;z0J>e\e(B)")
+(defvar egg-conversion-close "|"  "*\e$B%U%'%s%9$N=*E@$r<($9J8;zNs\e(B (1 \e$BJ8;z0J>e\e(B)")
+(defvar egg-conversion-face  nil  "*\e$B%U%'%s%9I=<($KMQ$$$k\e(B face \e$B$^$?$O\e(B nil")
 (defvar egg-conversion-separator " ")
 
+(defun egg-get-conversion-face ()
+  (let ((face (and (listp egg-conversion-face)
+                  (or (assoc egg-current-language egg-conversion-face)
+                      (assoc t egg-conversion-face)))))
+    (if face (cdr face) egg-conversion-face)))
+
 ;;
 (defun egg-convert-region (start end)
   (interactive "r")
-  (let (bunsetsu-info-list lang contin p s e)
-    (save-restriction
-      (narrow-to-region start end)
-      (goto-char start)
-      (insert egg-conversion-open)
-      (add-text-properties start (point)
+  (if (>= start end)
+      ;; nothing to do
+      nil
+    (remove-text-properties start end '(read-only nil intangible nil))
+    (goto-char start)
+    (insert egg-conversion-open)
+    (let ((inhibit-read-only t)
+         (max (make-marker))
+         bunsetsu-info-list contin p s e result)
+      (setq p (+ (point) (- end start)))
+      (set-text-properties start (point)
                           (list
+                           'read-only t
                            'egg-start t
-                           'egg-source (buffer-substring (point)
-                                                         (point-max))))
+                           'egg-source (buffer-substring (point) p)))
       (if egg-conversion-face
-          (put-text-property start (point) 'invisible t))
+         (put-text-property start (point) 'invisible t))
       (setq start (point))
-      (egg-separate-languages start (point-max))
+      (goto-char p)
+      (insert egg-conversion-close)
+      (set-text-properties p (point) '(read-only t rear-nonsticky t egg-end t))
+      (if egg-conversion-face
+         (put-text-property p (point) 'invisible t))
+      (set-marker max p)
+      (egg-separate-languages start max)
       (goto-char start)
-      (while (< (point) (point-max))
-       (setq lang (get-text-property (point) 'egg-lang)
+      (while (< (point) max)
+       (setq egg-current-language (get-text-property (point) 'egg-lang)
              s (point)
              e (point))
-        (while (and (< e (point-max))
-                    (equal lang (get-text-property e 'egg-lang)))
-          (setq e (next-single-property-change e 'egg-lang nil (point-max))))
-       (setq bunsetsu-info-list
-             (egg-start-conversion (buffer-substring s e) lang))
-       (setq contin (< e (point-max)))
+       (while (and (< e max)
+                   (equal egg-current-language
+                          (get-text-property e 'egg-lang)))
+         (setq e (next-single-property-change e 'egg-lang nil max)))
+       (condition-case result
+           (setq bunsetsu-info-list
+                 (egg-start-conversion
+                  (buffer-substring-no-properties s e)
+                  egg-current-language))
+         (error
+          (setq egg-conversion-backend egg-conversion-backend-other-languages
+                bunsetsu-info-list (egg-start-conversion-other-languages
+                                    (buffer-substring-no-properties s e)
+                                    egg-current-language))
+          (message "egg %s backend: %s" egg-current-language (cadr result))))
+       (setq contin (< e max))
        (delete-region s e)
        (egg-insert-bunsetsu-list bunsetsu-info-list
-                                 (if (< (point) (point-max)) 'contine t))))
-    (setq p (point))
-    (insert egg-conversion-close)
-    (put-text-property p (point) 'egg-end t)
-    (if egg-conversion-face
-       (put-text-property p (point) 'invisible t))
-    (goto-char start)))
+                                 (if (< (point) max) 'contine t)))
+      (set-marker max nil)
+      (goto-char start))))
 
-(defun egg-separate-languages (start end)
-  (let (lang last-lang last-chinese p l c cset)
+(defun egg-separate-languages (start end &optional use-context)
+  (let (lang last-lang last-chinese p pe l c cset)
     ;; 1st pass -- mark undefined Chinese part
     (goto-char start)
+    (and use-context
+        (setq last-lang (get-text-property (1- (point)) 'egg-lang))
+        (or (equal last-lang "Chinese-GB") (equal last-lang "Chinese-CNS"))
+        (setq last-chinese last-lang))
     (while (< (point) end)
-      (setq p (next-single-property-change (point) 'its-lang nil end))
+      (setq p (point)
+           pe (next-single-property-change (point) 'egg-lang nil end))
       (cond
-       ((get-text-property (point) 'its-lang)
-       (goto-char p))
-       ((setq l (egg-chinese-syllable (buffer-substring (point) p)))
-       (setq p (point))
-       (goto-char (+ (point) l))
-       (put-text-property p (point) 'its-lang "Chinese"))
+       ((get-text-property (point) 'egg-lang)
+       (goto-char pe)
+       (setq lang nil))
+       ((setq l (egg-chinese-syllable (buffer-substring p pe)))
+       (goto-char (+ p l))
+       (setq lang "Chinese"))
        ((progn
          (setq c (following-char)
                cset (char-charset c))
          (eq cset 'chinese-sisheng))
-       (setq p (point))
        (forward-char)
-       (put-text-property p (point) 'its-lang "Chinese"))
+       (setq lang "Chinese"))
        ((eq cset 'ascii)
-       (forward-char))
-       (t
-       (setq p (point))
+       (skip-chars-forward "\0-\177" pe)
+       (if (eq (char-charset (following-char)) 'chinese-sisheng)
+           (goto-char (max (1+ pp) (- (point) 6))))
+       (setq lang nil))
+       ((eq cset 'composition)
        (forward-char)
-       (put-text-property p (point) 'its-lang (egg-char-to-language c)))))
+       (setq lang (egg-charset-to-language
+                   (char-charset (car (decompose-composite-char c 'list))))))
+       (t
+       (skip-chars-forward (concat (vector (make-char cset 33 33))
+                                   "-"
+                                   (vector (make-char cset 127 127)))
+                           pe)
+       (setq lang (egg-charset-to-language cset))))
+      (if lang
+         (put-text-property p (point) 'egg-lang lang)))
     ;; 2nd pass -- set language property
     (goto-char start)
     (while (< (point) end)
-      (setq lang (get-text-property (point) 'its-lang))
+      (setq lang (get-text-property (point) 'egg-lang))
       (cond
        ((null lang)
        (setq lang (or last-lang
       (if (or (equal lang "Chinese-GB") (equal lang "Chinese-CNS"))
          (setq last-chinese lang))
       (setq p (point))
-      (goto-char (next-single-property-change (point) 'its-lang nil end))
+      (goto-char (next-single-property-change (point) 'egg-lang nil end))
       (set-text-properties p (point) (list 'egg-lang lang)))))
 
-(defun egg-char-to-language (c)
-  (let ((charset (char-charset c))
-       (list language-info-alist))
+(defun egg-charset-to-language (charset)
+  (let ((list language-info-alist))
     (while (and list
                (null (memq charset (assq 'charset (car list)))))
       (setq list (cdr list)))
     (car (car list))))
 
 (defun egg-next-part-lang (end)
-  (let* ((p (next-single-property-change (point) 'its-lang nil end))
-        (lang (get-text-property p 'its-lang)))
+  (let* ((p (next-single-property-change (point) 'egg-lang nil end))
+        (lang (get-text-property p 'egg-lang)))
     (if (equal lang "Chinese")
        (egg-next-chinese-lang end)
       (or lang
   (let (p lang)
     (setq p (point))
     (while (and (< p end) (null lang))
-      (setq p (next-single-property-change p 'its-lang nil end))
-      (setq lang (get-text-property p 'its-lang))
+      (setq p (next-single-property-change p 'egg-lang nil end))
+      (setq lang (get-text-property p 'egg-lang))
       (if (null (or (equal lang "Chinese-GB")
                    (equal lang "Chinese-CNS")))
          (setq lang nil)))
       egg-default-language)
      (t "Chinese-GB"))))
 \f
-(defvar egg-conversion-face nil)
+(require 'its-keydef)
+
 (defvar egg-conversion-map
   (let ((map (make-sparse-keymap))
        (i 33))
     (define-key map "\C-n"   'egg-next-candidate)
     (define-key map "\C-o"   'egg-enlarge-bunsetsu)
     (define-key map "\C-p"   'egg-previous-candidate)
+    (define-key map "\C-r"   'egg-reverse-convert-bunsetu)
+    (define-key map "\M-r"   'egg-reconvert-bunsetsu)
     (define-key map "\M-s"   'egg-select-candidate)
     (define-key map [return] 'egg-exit-conversion)
-;;    (define-key map "\C-\\"  'egg-exit-mode-no-egg)
     (define-key map [right]  'egg-forward-bunsetsu)
     (define-key map [left]   'egg-backward-bunsetsu)
     (define-key map " "      'egg-next-candidate)
-    (define-key map "/"      'egg-exit-conversion)
+    (its-define-select-keys map)
     map)
   "Keymap for EGG Conversion mode.")
 
 
 (defun egg-insert-bunsetsu (bunsetsu-info last)
   (let ((bunsetsu (egg-get-bunsetsu-converted bunsetsu-info))
-       (p (point)))
+       (p (point)) p1)
     (insert bunsetsu)
+    (setq p1 (point))
     (if (null (eq last t))
        (insert egg-conversion-separator))
-    (add-text-properties p (point)
-                        (list 'face      egg-conversion-face
-                              'local-map egg-conversion-map
-                              (egg-bunsetsu-info) (cons egg-conversion-backend
-                                                        bunsetsu-info)
-                              'egg-bunsetsu-last last))))
+    (set-text-properties p (point)
+                        (list 'read-only          t
+                              (egg-bunsetsu-info) bunsetsu-info
+                              'egg-backend        egg-conversion-backend
+                              'egg-lang           egg-current-language
+                              'egg-bunsetsu-last  last
+                              'local-map          egg-conversion-map))
+    (if egg-conversion-face
+       (put-text-property p p1 'face (egg-get-conversion-face)))))
 
 (defun egg-insert-bunsetsu-list (bunsetsu-info-list &optional last)
   (let ((l bunsetsu-info-list)
-       bunsetsu-info bunsetsu p)
+       bunsetsu-info)
     (while l
       (setq bunsetsu-info (car l)
-           l (cdr l)
-           p (point))
+           l (cdr l))
       (egg-insert-bunsetsu bunsetsu-info (and (null l) last)))))
 
+(defun egg-beginning-of-conversion-buffer (n)
+  (interactive "p")
+  (cond
+   ((<= n 0)
+    (egg-end-of-conversion-buffer 1))
+   ((null (get-text-property (1- (point)) 'egg-start))
+    (goto-char (previous-single-property-change (1- (point)) 'egg-start)))))
+
+(defun egg-end-of-conversion-buffer(n)
+  (interactive "p")
+  (cond
+   ((<= n 0)
+    (egg-beginning-of-conversion-buffer 1))
+   (t
+    (goto-char (next-single-property-change (point) 'egg-end))
+    (backward-char))))
+
 (defun egg-backward-bunsetsu (n)
   (interactive "p")
   (let (start)
 
 (defun egg-enlarge-bunsetsu (n)
   (interactive "p")
-  (let* ((b0 (egg-get-previous-bunsetsu (point)))
+  (let* ((inhibit-read-only t)
+        (b0 (egg-get-previous-bunsetsu (point)))
         (b1 (egg-get-bunsetsu-info (point)))
         (s1 (egg-get-bunsetsu-source b1))
         (s1len (egg-separate-characters s1))
 
 (defun egg-next-candidate (n)
   (interactive "p")
-  (let ((last (get-text-property (point) 'egg-bunsetsu-last))
+  (let ((inhibit-read-only t)
+       (last (get-text-property (point) 'egg-bunsetsu-last))
        (b (egg-get-bunsetsu-info (point)))
        new i max+ p beep)
     (setq max+ (egg-get-number-of-candidates b))
          (setq max+ (egg-get-number-of-candidates b)))
       (setq i (egg-get-current-candidate-number b))
       (setq i (+ n i)))
-    (if (< i 0)                                ; go backward as if it is ring
-       (while (< i 0)
-         (setq i (+ i max+))))
-    (if (>= i max+)                    ; don't go forward 
-       (setq i (1- max+)
-             beep t))
-    (setq new (egg-decide-candidate b i))
-    (setq p (point))
-    (delete-region p (progn (forward-char) (point)))
-    (egg-insert-bunsetsu new last)
-    (goto-char p)
+    (if (null max+)
+       (setq beep t)
+      (if (< i 0)                      ; go backward as if it is ring
+         (while (< i 0)
+           (setq i (+ i max+))))
+      (if (>= i max+)                  ; don't go forward 
+         (setq i (1- max+)
+               beep t))
+      (setq new (egg-decide-candidate b i))
+      (setq p (point))
+      (delete-region p (progn (forward-char) (point)))
+      (egg-insert-bunsetsu new last)
+      (goto-char p))
     (if beep
        (ding))))
 
   (interactive "p")
   (egg-next-candidate (- n)))
 
+(defun egg-reconvert-bunsetsu-internal (n func)
+  (let ((inhibit-read-only t)
+       (p (point))
+       source last bunsetsu-list)
+    (if (<= n 0)
+       (beep)
+      (while (and (null last) (> n 0))
+       (setq source (concat source
+                            (egg-get-bunsetsu-converted
+                             (egg-get-bunsetsu-info (point))))
+             last (get-text-property (point) 'egg-bunsetsu-last)
+             n (1- n))
+       (forward-char))
+      (cond
+       ((> n 0)
+       (beep))
+       ((setq bunsetsu-list (funcall func source egg-current-language))
+       (delete-region p (point))
+       (egg-insert-bunsetsu-list bunsetsu-list (if (eq last t) t 'contine))
+       (goto-char p)
+       (if (egg-get-previous-bunsetsu p)
+           (progn
+             (backward-char)
+             (put-text-property (point) p 'egg-bunsetsu-last 'contine)
+             (forward-char))))))))
+
+(defun egg-reverse-convert-bunsetu (n)
+  (interactive "p")
+  (egg-reconvert-bunsetsu-internal n 'egg-start-reverse-conversion))
+
+(defun egg-reconvert-bunsetsu (n)
+  (interactive "p")
+  (egg-reconvert-bunsetsu-internal n 'egg-start-conversion))
+
 (defun egg-decide-before-point ()
   (interactive)
-  (let (bunsetsu-list bl (p (point)) source (dlen 0) l s)
+  (let ((inhibit-read-only t)
+       (len (length egg-conversion-open))
+       bunsetsu-list bl (p (point)) source lang s)
     (save-restriction
       (if (null (get-text-property (1- (point)) 'egg-start))
          (goto-char (previous-single-property-change (point) 'egg-start)))
-      (narrow-to-region (1- (point)) p)
-      (setq source (get-text-property (1- (point)) 'egg-source))
+      (narrow-to-region (- (point) len) p)
       (setq bunsetsu-list (setq bl (list nil)))
       (while (< (point) (point-max))
        ;; delete sparator/open marker
-       (delete-region (1- (point)) (point))
-       (setq bl (setcdr bl (list (egg-get-bunsetsu-info (point)))))
-       (setq dlen (+ dlen (length (egg-get-bunsetsu-source (car bl)))))
+       (delete-region (- (point) len) (point))
+       (setq len 1
+             bl (setcdr bl (list (egg-get-bunsetsu-info (point)))))
        (if (get-text-property (point) 'egg-bunsetsu-last)
            (progn
              (egg-end-conversion (cdr bunsetsu-list))
              (setq bunsetsu-list (setq bl (list nil)))))
        (setq p (point))
        (forward-char)
-       (remove-text-properties p (point) '(face nil
-                                                intangible nil
-                                                local-map nil
-                                                egg-bunsetsu-last nil))))
+       (set-text-properties p (point) nil)))
+    (if (cdr bunsetsu-list)
+       (egg-end-conversion (cdr bunsetsu-list)))
     (if (get-text-property (point) 'egg-end)
        (progn
          ;; delete close marker
-         (delete-region (point) (1+ (point)))
+         (delete-region (point) (+ (point) (length egg-conversion-close)))
          (egg-do-auto-fill)
          (run-hooks 'input-method-after-insert-chunk-hook))
-      ;; delete last from speparater to close marker
-      (delete-region (1- (point))
-                    (1+ (next-single-property-change (point) 'egg-end)))
-      ;; rebuild fence mode string
-      (setq p 0)
-      (while (< p dlen)
-       (setq s (car (get-text-property p 'its-syl source))
-             l (length s)
-             p (+ p l))
-       (if (> p dlen)
-           (put-text-property dlen p
-                              'its-syl (list (substring s (- dlen p)))
-                              source)))
-      (its-restart (substring source dlen)))))
+      ;; delete from last speparater
+      (delete-region (1- (point)) (point))
+      (setq source "")
+      (while (null (get-text-property (point) 'egg-end))
+       (setq s (egg-get-bunsetsu-source (egg-get-bunsetsu-info (point))))
+       (put-text-property 0 (length s) 'egg-lang egg-current-language s)
+       (setq source (concat source s))
+       (setq p (point))
+       (forward-char)
+       (delete-region p (point)))
+      ;; delete close marker
+      (delete-region (point) (+ (point) (length egg-conversion-close)))
+      (its-restart source t))))
 
 (defun egg-exit-conversion ()
   (interactive)
 
 (defun egg-abort-conversion ()
   (interactive)
-  (if (null (get-text-property (1- (point)) 'egg-start))
-      (goto-char (previous-single-property-change (point) 'egg-start)))
-  (egg-decide-before-point))
+  (let ((inhibit-read-only t) source)
+    (goto-char (- (if (get-text-property (1- (point)) 'egg-start)
+                     (point)
+                   (previous-single-property-change (point) 'egg-start))
+                 (length egg-conversion-open)))
+    (setq source (get-text-property (point) 'egg-source))
+    (delete-region (point) (+ (next-single-property-change (point) 'egg-end)
+                             (length egg-conversion-close)))
+    (its-restart source)))
 
 (defun egg-select-candidate ()
   (interactive)
-  (let ((last (get-text-property (point) 'egg-bunsetsu-last))
+  (let ((inhibit-read-only t)
+       (last (get-text-property (point) 'egg-bunsetsu-last))
        (b (egg-get-bunsetsu-info (point)))
        (in-loop t)
        new i max+ p)
          (setq i (egg-list-candidates b prev-b))
          (setq max+ (egg-get-number-of-candidates b)))
       (setq i (egg-get-current-candidate-number b)))
-    (let* ((candidate-list (egg-get-all-candidates b))
-          (l candidate-list)
-          (candidate (menudiag-select (list 'menu "\e$B8uJd\e(B:" l) (list (nth i l)))))
-      (setq i 0)
-      (while in-loop
-       (if (eq candidate (car l))
-           (setq in-loop nil)
-         (setq l (cdr l)
-               i (1+ i))))
-      (setq new (egg-decide-candidate b i))
-      (setq p (point))
-      (delete-region p (progn (forward-char) (point)))
-      (egg-insert-bunsetsu new last)
-      (goto-char p))))
+    (let (candidate-list candidate l)
+      (if (null max+)
+         ;; fake 1 candidate
+         (menudiag-select (list 'menu "\e$B8uJd\e(B:"
+                                (list (egg-get-bunsetsu-converted b))
+                                (list (egg-get-bunsetsu-converted b))))
+       (setq candidate-list (egg-get-all-candidates b)
+             l candidate-list
+             candidate (menudiag-select (list 'menu "\e$B8uJd\e(B:" l)
+                                        (list (nth i l))))
+       (setq i 0)
+       (while in-loop
+         (if (eq candidate (car l))
+             (setq in-loop nil)
+           (setq l (cdr l)
+                 i (1+ i))))
+       (setq new (egg-decide-candidate b i))
+       (setq p (point))
+       (delete-region p (progn (forward-char) (point)))
+       (egg-insert-bunsetsu new last)
+       (goto-char p)))))
 
 (provide 'egg-cnv)
 ;;; egg-cnv.el ends here.