[uim-commit] r938 - in trunk: scm uim

ekato at freedesktop.org ekato at freedesktop.org
Wed Jul 6 03:01:08 PDT 2005


Author: ekato
Date: 2005-07-06 03:01:05 -0700 (Wed, 06 Jul 2005)
New Revision: 938

Added:
   trunk/scm/skk-dialog.scm
Modified:
   trunk/scm/Makefile.am
   trunk/scm/skk-editor.scm
   trunk/scm/skk-key-custom.scm
   trunk/scm/skk.scm
   trunk/uim/skk.c
Log:
* scm/skk.scm : Add ddskk's skk-purge-from-jisyo equivalent.
(skk-style-spec) : Add skk-preedit-attr-dialog.
(skk-style-uim) : Use preedit-none for skk-preedit-attr-dialog.
(skk-style-ddskk-like) : Ditto.
(skk-child-type-editor) : New.
(skk-child-type-dialog) : Ditto.
(skk-context-rec-spec) : Add child-type and dialog.
(skk-flush) : Flush dialog.
(skk-context-new) : Set dialog.
(skk-commit-raw) : Check child type.
(skk-commit) : Ditto.
(skk-prepare-commit-string) : Remove redundant code.
(skk-purge-candidate) : New procedure.
(skk-begin-conversion) : Set child type as editor when going to
  recursive learning.
(skk-do-update-preedit) : Check child type.
(skk-commit-editor-context) : Simplify and set child-context and
  child-type as nil.
(skk-commit-dialog-context) : New.
(skk-setup-child-context) : Check child type (editor or dialog).
(skk-change-candidate-index) : Setup child as editor.
(skk-proc-state-converting) : Handle skk-purge-candidate-key?.
* scm/skk-key-custom.scm (skk-purge-candidate-key) : New.
* scm/skk-editor.scm (skk-editor-commit-raw) : Reset child-context
  and child-type as nil (not #f).
* scm/skk-dialog.scm : New file for dialog context.  Mostly copied
  from skk-editor.scm.

* scm/Makefile.am : Add skk-dialog.scm as SCM_FILES.

* uim/skk.c : Remove "skk_" prefix from function used on
  internally, and use "skk_" prefix only for function with scheme
  API.  Many cosmetic changes about parentheses.  Add support for
  purge of unwanted candidate words.
(merge_base_candidate_to_array) : Check purged words while
  merging.
(is_purged_cand) : New function.  Return 1 if the candidate word
  is purged one (e.g. (skk-ignore-dic-word "foo")).
(get_purged_words) : New function.  Create an array of purged
  words from purged candidate.
(nr_purged_words) : New function.  Return the number of words in
  the array of purged words.
(free_allocated_purged_words) : New function.  Free storage
  allocated with get_purged_words().
(is_purged_only) : New function.  Return 1 when candidate array
  contains only purged words.  Used in skk_get_entry().
(match_to_discarding_index) : New function.  Return 1 if nth in
  the candidate array is needed to be ignored.
(skk_get_entry) : Check purged entry.
(get_purged_cand_index) : New function.  Return index of purged
  candidate in the candidate array.  Returns -1 if there is no
  such candidate.
(get_ignoring_indices) : New function.  Return the number of
  candidates needed to be ignored in the candidate array, and set
  these indices.
(skk_get_nth_candidate) : Don't count purged candidates.
(skk_get_nr_candidates) : Ditto.
(push_purged_word) : New function.  Add a word to the candidate
  array as a purged word at nth position in the array.
(remove_candidate_from_array) : New function.
(merge_word_to_real_cand_array) : Renamed from
  merge_word_to_cand_array().  Don't check the existence of word
  in the destination array.
(exist_in_purged_cand) : Return 1 if the word is already existed
  in a purged candidate in the array.
(index_in_real_cands) : Return index of the word in a candidate
  array within nr_real_cands scope.  If the doesn't exist return
  -1.
(remove_purged_words_from_dst_cand_array) : New function.  Remove
  candidate words within nr_real_cands scope if the words is
  matched with the one in a supplied purged candidate.
(merge_purged_cands) : New function.
(merge_purged_cand_to_dst_array) : New function.
(merge_word_to_dst_cand_array_with_purged_words) : New function.
(merge_real_candidate_array) : Add check for purged words.
(skk_commit_candidate) : Don't count purged words.
(purge_candidate) : New function.  Purge a candidate word at the
  nth in the candidate array.
(skk_purge_candidate) : New function corresponding to API for
  scheme.
(quote_word) : Use prefix characters.
(sanitize_word) : Ditto.
(compare_and_merge_skk_line) : Merge all real candidate array
  since purged words may exist.
(uim_plugin_instance_init) : Add new API for scheme
  skk-lib-purge-candidate.


Modified: trunk/scm/Makefile.am
===================================================================
--- trunk/scm/Makefile.am	2005-07-06 01:35:06 UTC (rev 937)
+++ trunk/scm/Makefile.am	2005-07-06 10:01:05 UTC (rev 938)
@@ -17,7 +17,7 @@
  anthy.scm anthy-custom.scm anthy-key-custom.scm \
  canna.scm canna-custom.scm canna-key-custom.scm \
  prime.scm prime-custom.scm prime-key-custom.scm \
- skk.scm skk-editor.scm skk-custom.scm skk-key-custom.scm \
+ skk.scm skk-editor.scm skk-custom.scm skk-key-custom.scm skk-dialog.scm \
  tcode.scm \
  tutcode.scm tutcode-key-custom.scm \
  hangul.scm hangul2.scm hangul3.scm romaja.scm \

Added: trunk/scm/skk-dialog.scm
===================================================================
--- trunk/scm/skk-dialog.scm	2005-07-06 01:35:06 UTC (rev 937)
+++ trunk/scm/skk-dialog.scm	2005-07-06 10:01:05 UTC (rev 938)
@@ -0,0 +1,130 @@
+;;;
+;;; Copyright (c) 2005 uim Project http://uim.freedesktop.org/
+;;;
+;;; All rights reserved.
+;;;
+;;; Redistribution and use in source and binary forms, with or without
+;;; modification, are permitted provided that the following conditions
+;;; are met:
+;;; 1. Redistributions of source code must retain the above copyright
+;;;    notice, this list of conditions and the following disclaimer.
+;;; 2. Redistributions in binary form must reproduce the above copyright
+;;;    notice, this list of conditions and the following disclaimer in the
+;;;    documentation and/or other materials provided with the distribution.
+;;; 3. Neither the name of authors nor the names of its contributors
+;;;    may be used to endorse or promote products derived from this software
+;;;    without specific prior written permission.
+;;;
+;;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
+;;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+;;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+;;; ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
+;;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+;;; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+;;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+;;; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+;;; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+;;; SUCH DAMAGE.
+;;;;
+
+;; yes/no dialog for skk-purge-from-jisyo
+;; this is just a quick hack derived from skk-editor.scm
+
+(define-record 'skk-dialog
+  '((context      '())
+    (left-string  '())
+    (right-string '())))
+(define skk-dialog-new-internal skk-dialog-new)
+
+(define skk-dialog-new
+  (lambda (sc)
+    (let ((dc (skk-dialog-new-internal)))
+      (skk-dialog-set-context! dc sc)
+      dc)))
+
+(define skk-dialog-flush
+  (lambda (dc)
+    (skk-dialog-set-left-string! dc '())
+    (skk-dialog-set-right-string! dc '())))
+
+(define skk-dialog-make-string
+  (lambda (sl dir)
+    (if sl
+	(if dir
+	    (string-append (skk-dialog-make-string (cdr sl) dir)
+			   (car sl))
+	    (string-append (car sl)
+			   (skk-dialog-make-string (cdr sl) dir)))
+	(if dir
+	    "Really purge? (yes/no) " 
+	    ""))))
+
+(define skk-dialog-get-left-string
+  (lambda (dc)
+    (skk-dialog-make-string
+     (skk-dialog-left-string dc) #t)))
+
+(define skk-dialog-get-right-string
+  (lambda (dc)
+    (skk-dialog-make-string
+     (skk-dialog-right-string dc) #f)))
+
+(define skk-dialog-commit-char-list
+  (lambda (dc sl)
+    (if sl
+	(begin
+	  (skk-dialog-set-left-string!
+	   dc
+	   (cons (car sl)
+		 (skk-dialog-left-string dc)))
+	  (skk-dialog-commit-char-list
+	   dc (cdr sl))))))
+
+(define skk-dialog-commit
+  (lambda (dc str)
+    (skk-dialog-commit-char-list
+     dc (reverse (string-to-list str)))))
+				 
+(define skk-dialog-commit-raw
+  (lambda (dc key key-state)
+    (let ((raw-str (im-get-raw-key-str key key-state))
+	  (sc (skk-dialog-context dc))
+	  (str
+	   (string-append
+	    (skk-dialog-get-left-string dc)
+	    (skk-dialog-get-right-string dc))))
+      (if raw-str
+	  (skk-dialog-commit dc raw-str)
+	  ;; not a string
+	  (and
+	   (if (skk-backspace-key? key key-state)
+	       (let ((cur (skk-dialog-left-string dc)))
+		 (if cur
+		     (skk-dialog-set-left-string!
+		      dc (cdr cur)))
+		 #f)
+	       #t)
+	   (if (skk-return-key? key key-state)
+	       (begin
+		 (if (string=? str "Really purge? (yes/no) yes")
+		     (begin
+		       (skk-purge-candidate sc)
+		 	(skk-dialog-flush dc)
+		 	(skk-context-set-child-context! sc '())
+		 	(skk-context-set-child-type! sc '())))
+		 (if (string=? str "Really purge? (yes/no) no")
+		     (begin
+		 	(skk-dialog-flush dc)
+		 	(skk-context-set-child-context! sc '())
+		 	(skk-context-set-child-type! sc '())))
+		 #f)
+	       #t)
+	   (if (skk-cancel-key? key key-state)
+	       (begin
+		 (skk-dialog-flush dc)
+		 (skk-context-set-child-context! sc '())
+		 (skk-context-set-child-type! sc '())
+		 #f)
+	       #t)
+	   )))))

Modified: trunk/scm/skk-editor.scm
===================================================================
--- trunk/scm/skk-editor.scm	2005-07-06 01:35:06 UTC (rev 937)
+++ trunk/scm/skk-editor.scm	2005-07-06 10:01:05 UTC (rev 938)
@@ -154,7 +154,8 @@
 		       (skk-commit-editor-context sc str))
 		     (begin
 		       (skk-editor-flush ec)
-		       (skk-context-set-child-context! sc #f)
+		       (skk-context-set-child-context! sc '())
+		       (skk-context-set-child-type! sc '())
 		       (if (> (skk-context-nr-candidates sc) 0)
 			   (skk-back-to-converting-state sc)
 			   (skk-back-to-kanji-state sc))))
@@ -163,7 +164,8 @@
 	   (if (skk-cancel-key? key key-state)
 	       (begin
 		 (skk-editor-flush ec)
-		 (skk-context-set-child-context! sc #f)
+		 (skk-context-set-child-context! sc '())
+		 (skk-context-set-child-type! sc '())
 		 (if (> (skk-context-nr-candidates sc) 0)
 		     (skk-back-to-converting-state sc)
 		     (skk-back-to-kanji-state sc))

Modified: trunk/scm/skk-key-custom.scm
===================================================================
--- trunk/scm/skk-key-custom.scm	2005-07-06 01:35:06 UTC (rev 937)
+++ trunk/scm/skk-key-custom.scm	2005-07-06 10:01:05 UTC (rev 938)
@@ -190,6 +190,12 @@
 	       (_ "[SKK] skk-state-direct-no-preedit-nop-key?")
 	       (_ "long description will be here"))
 
+(define-custom 'skk-purge-candidate-key '("<IgnoreCase><Shift>x")  ;; "X"
+	       '(skk-keys2)
+	       '(key)
+	       (_ "[SKK] skk-purge-candidate-key?")
+	       (_ "long description will be here"))
+
 ;; should not be changed
 (define-key skk-plain-space-key? '(" "))
 ;;(define-custom 'skk-plain-space-key '(" ")

Modified: trunk/scm/skk.scm
===================================================================
--- trunk/scm/skk.scm	2005-07-06 01:35:06 UTC (rev 937)
+++ trunk/scm/skk.scm	2005-07-06 10:01:05 UTC (rev 938)
@@ -72,6 +72,7 @@
     (skk-preedit-attr-child-beginning-mark . preedit-attr?)
     (skk-preedit-attr-child-end-mark       . preedit-attr?)
     (skk-preedit-attr-child-committed      . preedit-attr?)
+    (skk-preedit-attr-child-dialog	   . preedit-attr?)
     (skk-child-context-beginning-mark      . string?)
     (skk-child-context-end-mark		   . string?)
     (skk-show-cursor-on-preedit?	   . boolean?)
@@ -89,6 +90,7 @@
     (skk-preedit-attr-child-beginning-mark . preedit-reverse)
     (skk-preedit-attr-child-end-mark       . preedit-reverse)
     (skk-preedit-attr-child-committed      . preedit-reverse)
+    (skk-preedit-attr-child-dialog	   . preedit-none)
     (skk-child-context-beginning-mark      . "[")
     (skk-child-context-end-mark		   . "]")
     (skk-show-cursor-on-preedit?	   . #f)
@@ -105,6 +107,7 @@
     (skk-preedit-attr-child-beginning-mark . preedit-underline)
     (skk-preedit-attr-child-end-mark       . preedit-underline)
     (skk-preedit-attr-child-committed      . preedit-underline)
+    (skk-preedit-attr-child-dialog	   . preedit-none)
     (skk-child-context-beginning-mark      . "¡Ú")
     (skk-child-context-end-mark		   . "¡Û")
     (skk-show-cursor-on-preedit?	   . #t)
@@ -119,6 +122,9 @@
 (define skk-input-rule-roma 0)
 (define skk-input-rule-azik 1)
 
+(define skk-child-type-editor 0)
+(define skk-child-type-dialog 1)
+
 ;; style elements
 (define skk-preedit-attr-mode-mark #f)
 (define skk-preedit-attr-head #f)
@@ -130,6 +136,7 @@
 (define skk-preedit-attr-child-beginning-mark #f)
 (define skk-preedit-attr-child-end-mark #f)
 (define skk-preedit-attr-child-committed #f)
+(define skk-preedit-attr-child-dialog #f)
 (define skk-child-context-beginning-mark #f)
 (define skk-child-context-end-mark #f)
 (define skk-show-cursor-on-preedit? #f)
@@ -285,8 +292,10 @@
     (list 'candidate-op-count 0)
     (list 'candidate-window   #f)
     (list 'child-context      '())
+    (list 'child-type	      '())
     (list 'parent-context     '())
     (list 'editor	      '())
+    (list 'dialog	      '())
     (list 'latin-conv	      #f)
     (list 'commit-raw	      #f)
     (list 'completion-nth     0))))
@@ -335,6 +344,7 @@
     (rk-flush (skk-context-rk-context sc))
     (if skk-use-recursive-learning?
 	(skk-editor-flush (skk-context-editor sc)))
+    (skk-dialog-flush (skk-context-dialog sc))
     (if (not (skk-latin-state? sc))
 	(skk-context-set-state! sc 'skk-state-direct))
     (skk-context-set-head! sc '())
@@ -351,8 +361,9 @@
 	(begin
 	  (set! skk-dic-init #t)
 	  (if skk-use-recursive-learning?
-	   (require "skk-editor.scm"))
-	   (skk-lib-dic-open
+	      (require "skk-editor.scm"))
+	  (require "skk-dialog.scm")
+	  (skk-lib-dic-open
 	     skk-dic-file-name skk-use-skkserv? skk-skkserv-portnum)
 	  (skk-read-personal-dictionary)))
     (let ((sc (skk-context-new-internal id im))
@@ -364,6 +375,7 @@
       (skk-context-set-parent-context! sc '())
       (if skk-use-recursive-learning?
 	  (skk-context-set-editor! sc (skk-editor-new sc)))
+      (skk-context-set-dialog! sc (skk-dialog-new sc))
       (skk-flush sc)
       (skk-context-set-state! sc 'skk-state-latin)
       sc)))
@@ -501,8 +513,12 @@
   (lambda (sc key key-state)
     (let ((psc (skk-context-parent-context sc)))
       (if (not (null? psc))
-	  (skk-editor-commit-raw (skk-context-editor psc) key key-state)
 	  (begin
+	    (if (= (skk-context-child-type psc)
+		   skk-child-type-editor)
+		(skk-editor-commit-raw (skk-context-editor psc) key key-state)
+		(skk-dialog-commit-raw (skk-context-dialog psc) key key-state)))
+	  (begin
 	    (skk-context-set-commit-raw! sc #t)
 	    (im-commit-raw sc))))))
 
@@ -510,10 +526,12 @@
   (lambda (sc key key-state)
     (let ((psc (skk-context-parent-context sc)))
       (if (not (null? psc))
-	  (skk-editor-commit-raw
-	   (skk-context-editor psc)
-	   key key-state)
 	  (begin
+	    (if (= (skk-context-child-type psc)
+	    	   skk-child-type-editor)
+		(skk-editor-commit-raw (skk-context-editor psc) key key-state)
+		(skk-dialog-commit-raw (skk-context-dialog psc) key key-state)))
+	  (begin
 	    (skk-context-set-commit-raw! sc #f)
 	    (im-commit-raw sc))))))
 
@@ -522,7 +540,11 @@
   (lambda (sc str)
     (let ((psc (skk-context-parent-context sc)))
       (if (not (null? psc))
-	  (skk-editor-commit (skk-context-editor psc) str)
+	  (begin
+	    (if (= (skk-context-child-type psc)
+	    	   skk-child-type-editor)
+		(skk-editor-commit (skk-context-editor psc) str)
+		(skk-dialog-commit (skk-context-dialog psc) str)))
 	  (im-commit sc str)))))
 
 (define skk-prepare-commit-string
@@ -532,7 +554,7 @@
 				   (skk-context-kana-mode sc)))
 	   (appendix (skk-make-string (skk-context-appendix sc)
 				   (skk-context-kana-mode sc)))
-	   (res (string-append (string-append cand okuri) appendix))
+	   (res (string-append cand okuri appendix))
 	   (head (skk-context-head sc)))
       (if skk-use-numeric-conversion?
 	  ;; store original number for numeric conversion #4
@@ -544,19 +566,49 @@
 	     (skk-make-string (skk-context-okuri sc) skk-type-hiragana)
 	     (skk-context-nth sc)
 	     numlst))
-	  (begin
-	    (skk-lib-commit-candidate
-	     (skk-make-string head skk-type-hiragana)
-	     (skk-context-okuri-head sc)
-	     (skk-make-string (skk-context-okuri sc) skk-type-hiragana)
-	     (skk-context-nth sc)
-	     '())))
+	  (skk-lib-commit-candidate
+	   (skk-make-string head skk-type-hiragana)
+	   (skk-context-okuri-head sc)
+	   (skk-make-string (skk-context-okuri sc) skk-type-hiragana)
+	   (skk-context-nth sc)
+	   '()))
       (if (> (skk-context-nth sc) 0)
 	  (skk-save-personal-dictionary))
       (skk-reset-candidate-window sc)
       (skk-flush sc)
       res)))
 
+(define skk-purge-candidate
+  (lambda (sc)
+    (let* ((okuri (skk-make-string (skk-context-okuri sc)
+				   (skk-context-kana-mode sc)))
+	   (appendix (skk-make-string (skk-context-appendix sc)
+				   (skk-context-kana-mode sc)))
+	   (head (skk-context-head sc))
+	   (res #f))
+      (if skk-use-numeric-conversion?
+	  ;; store original number for numeric conversion #4
+	  (let ((numlst (skk-lib-store-replaced-numstr
+			 (skk-make-string head skk-type-hiragana))))
+	    (set! res (skk-lib-purge-candidate
+		       (skk-lib-replace-numeric
+			(skk-make-string head skk-type-hiragana))
+		       (skk-context-okuri-head sc)
+		       (skk-make-string (skk-context-okuri sc)
+					skk-type-hiragana)
+		       (skk-context-nth sc)
+		       numlst)))
+	  (set! res (skk-lib-purge-candidate
+		     (skk-make-string head skk-type-hiragana)
+		     (skk-context-okuri-head sc)
+		     (skk-make-string (skk-context-okuri sc) skk-type-hiragana)
+		     (skk-context-nth sc)
+		     '())))
+      (if res
+	  (skk-save-personal-dictionary))
+      (skk-reset-candidate-window sc)
+      (skk-flush sc)
+      res)))
 
 (define skk-append-string
   (lambda (sc str)
@@ -619,7 +671,7 @@
 		(im-select-candidate sc 0))
 	    (skk-context-set-state! sc 'skk-state-converting))
 	  (if skk-use-recursive-learning?
-	      (skk-setup-child-context sc)
+	      (skk-setup-child-context sc skk-child-type-editor)
 	      (skk-flush sc))))))
 
 (define skk-begin-completion
@@ -668,7 +720,11 @@
 		 h))))
       (if (and
 	   (= stat 'skk-state-converting)
-	   (null? csc))
+	   (or
+	    (null? csc)
+	    (and
+	     (not (null? csc))
+	     (= (skk-context-child-type sc) skk-child-type-dialog))))
 	  (begin
 	    (if (or
 		 (= skk-candidate-selection-style 'uim)
@@ -697,10 +753,12 @@
 			      (skk-context-kana-mode sc)))))
       (if (and
 	   (not (null? csc))
-	    (or
+	   (or
 	     (= stat 'skk-state-kanji)
 	     (= stat 'skk-state-okuri)
-	     (= stat 'skk-state-converting)))
+	     (and
+	      (= stat 'skk-state-converting)
+	      (= (skk-context-child-type sc) skk-child-type-editor))))
 	  (let ((h '()))
 	    (if skk-use-numeric-conversion?
 	      ;; replace numeric string with #
@@ -728,7 +786,8 @@
 	   (and
 	    (not (null? csc))
 	    (= stat 'skk-state-converting)
-	    (skk-context-okuri sc)))
+	    (skk-context-okuri sc)
+	    (= (skk-context-child-type sc) skk-child-type-editor)))
 	  (begin
 	    (im-pushback-preedit 
 	     sc skk-preedit-attr-okuri
@@ -757,17 +816,40 @@
 
       ;; child context's preedit
       (if (not (null? csc))
-	  (let ((editor (skk-context-editor sc)))
-	    (im-pushback-preedit sc skk-preedit-attr-child-beginning-mark
-				 skk-child-context-beginning-mark)
-	    (im-pushback-preedit sc skk-preedit-attr-child-committed
-				 (skk-editor-get-left-string editor))
+	  (let ((editor (skk-context-editor sc))
+		(dialog (skk-context-dialog sc)))
+	    (if (= (skk-context-child-type sc) skk-child-type-editor)
+		(begin
+		  (im-pushback-preedit sc
+		  		       skk-preedit-attr-child-beginning-mark
+				       skk-child-context-beginning-mark)
+		  (im-pushback-preedit sc
+				       skk-preedit-attr-child-committed
+				       (skk-editor-get-left-string editor)))
+		(begin
+		  (im-pushback-preedit sc
+				       skk-preedit-attr-child-dialog
+				       skk-child-context-beginning-mark)
+		  (im-pushback-preedit sc
+		  		       skk-preedit-attr-child-dialog
+				       (skk-dialog-get-left-string dialog))))
 	    (skk-do-update-preedit csc)
-	    (im-pushback-preedit sc skk-preedit-attr-child-committed
-				 (skk-editor-get-right-string editor))
-	    (im-pushback-preedit sc skk-preedit-attr-child-end-mark
-				 skk-child-context-end-mark)
-	    )))))
+	    (if (= (skk-context-child-type sc) skk-child-type-editor)
+	    	(begin
+		  (im-pushback-preedit sc
+				     skk-preedit-attr-child-committed
+				     (skk-editor-get-right-string editor))
+		  (im-pushback-preedit sc
+		  		       skk-preedit-attr-child-end-mark
+				       skk-child-context-end-mark))
+		(begin
+		  (im-pushback-preedit sc
+				       skk-preedit-attr-child-dialog
+				       (skk-dialog-get-right-string dialog))
+		  (im-pushback-preedit sc
+		  		       skk-preedit-attr-child-dialog
+				       skk-child-context-end-mark)))))
+	    )))
 
 (define skk-update-preedit
   (lambda (sc)
@@ -789,11 +871,27 @@
 				   (skk-context-kana-mode sc)))
 	   (str (if (not (null? psc))
 		    str
-		    (string-append (string-append str okuri) appendix))))
+		    (string-append str okuri appendix))))
       (skk-flush sc)
-      (skk-context-set-child-context! sc #f)
+      (skk-context-set-child-context! sc '())
+      (skk-context-set-child-type! sc '())
       (skk-commit sc str))))
 
+(define skk-commit-dialog-context
+  (lambda (sc str)
+    (let* ((psc (skk-context-parent-context sc))
+	   (okuri (skk-make-string (skk-context-okuri sc)
+				   (skk-context-kana-mode sc)))
+	   (appendix (skk-make-string (skk-context-appendix sc)
+				   (skk-context-kana-mode sc)))
+	   (str (if (not (null? psc))
+		    str
+		    (string-append str okuri appendix))))
+      (skk-flush sc)
+      (skk-context-set-child-context! sc '())
+      (skk-context-set-child-type! sc '())
+      (skk-commit sc str))))
+
 ;; experimental coding style. discussions are welcome -- YamaKen
 (define skk-proc-state-direct-no-preedit
   (lambda (key key-state sc rkc)
@@ -1216,13 +1314,16 @@
       #f)))
 
 (define skk-setup-child-context
-  (lambda (sc)
+  (lambda (sc type)
     (let ((csc (skk-context-new (skk-context-id sc)
 				(skk-context-im sc)))
 	  (input-rule (skk-context-input-rule sc)))
       (skk-context-set-child-context! sc csc)
+      (skk-context-set-child-type! sc type)
       (skk-context-set-parent-context! csc sc)
-      (skk-context-set-state! csc 'skk-state-direct)
+      (if (= type skk-child-type-editor)
+	  (skk-context-set-state! csc 'skk-state-direct)
+	  (skk-context-set-state! csc 'skk-state-latin))
       (skk-set-rule! csc input-rule))))
 
 (define skk-check-candidate-window-begin
@@ -1384,7 +1485,7 @@
 	     (if skk-use-recursive-learning?
 		 (begin
 		   (skk-reset-candidate-window sc)
-		   (skk-setup-child-context sc)))
+		   (skk-setup-child-context sc skk-child-type-editor)))
 	     #t)
 	   #t)
        (if (null? (skk-context-child-context sc))
@@ -1577,6 +1678,15 @@
 		 #f
 		 #t))
 	   #t)
+       (if (skk-purge-candidate-key? key key-state)
+	   (if (not
+		(and (= skk-candidate-selection-style 'ddskk-like)
+		     (skk-context-candidate-window sc)))
+	       (begin
+		 (skk-reset-candidate-window sc)
+		 (skk-setup-child-context sc skk-child-type-dialog)
+		 #f))
+	   #t)
        (begin
 	 (skk-context-set-state! sc 'skk-state-direct)
 	 (set! res (skk-prepare-commit-string sc))

Modified: trunk/uim/skk.c
===================================================================
--- trunk/uim/skk.c	2005-07-06 01:35:06 UTC (rev 937)
+++ trunk/uim/skk.c	2005-07-06 10:01:05 UTC (rev 938)
@@ -74,8 +74,8 @@
   /* okurigana string */
   char *okuri;
 
-  int nr_cands;/* length of cands array allocated */
-  int nr_real_cands;/* length of read from file part */
+  int nr_cands; /* length of cands array allocated */
+  int nr_real_cands; /* length of read from file part */
   /* candidate string */
   char **cands;
 
@@ -138,6 +138,13 @@
   struct skk_comp_array *next;
 } *skk_comp;
 
+static char *sanitize_word(const char *str, const char *prefix);
+static int is_purged_cand(const char *str);
+static void merge_purged_cands(struct skk_cand_array *src_ca,
+		struct skk_cand_array *dst_ca, int src_nth, int dst_nth);
+static void merge_purged_cand_to_dst_array(struct skk_cand_array *src_ca,
+		struct skk_cand_array *dst_ca, char *purged_cand);
+
 /* skkserv connection */
 #define SKK_SERVICENAME	"skkserv"
 #define SKK_SERVER_HOST	"localhost"
@@ -147,8 +154,8 @@
 static FILE *rserv, *wserv;
 static char *SKKServerHost = NULL;
 /* prototype */
-static int skk_open_skkserv(int portnum);
-static void skk_close_skkserv(void);
+static int open_skkserv(int portnum);
+static void close_skkserv(void);
 
 static int
 calc_line_len(const char *s)
@@ -164,24 +171,22 @@
   const char *b;
   /* find first white space */
   b = strchr(line_str, ' ');
-  if (!b) {
+  if (!b)
     return 0;
-  }
   /* check previous character */
   b--;
-  if (skk_isalpha(*b)) {
+  if (skk_isalpha(*b))
     return 1;
-  }
   return 0;
 }
 
-
 static int
 find_first_line(struct dic_info *di)
 {
   char *s = di->addr;
   int off = 0;
-  while ( off < di->size && s[off] == ';' ) {
+
+  while (off < di->size && s[off] == ';') {
     int l = calc_line_len(&s[off]);
     off += l + 1;
   }
@@ -199,9 +204,8 @@
       off += l + 1;
       continue;
     }
-    if (!is_okuri(&s[off])) {
+    if (!is_okuri(&s[off]))
       return off;
-    }
     off += l + 1;
   }
   /* every entry is okuri-ari, it may not happen. */
@@ -222,7 +226,7 @@
 
   di->skkserv_portnum = skkserv_portnum;
   if (use_skkserv)
-    di->skkserv_ok = skk_open_skkserv(skkserv_portnum);
+    di->skkserv_ok = open_skkserv(skkserv_portnum);
   else {
     di->skkserv_ok = 0;
     fd = open(fn, O_RDONLY);
@@ -254,12 +258,12 @@
 find_line(struct dic_info *di, int off)
 {
   char *ptr = di->addr;
-  while (off > 0 && (ptr[off] != '\n' || ptr[off + 1] == ';')) {
+  while (off > 0 && (ptr[off] != '\n' || ptr[off + 1] == ';'))
     off--;
-  }
-  if (off) {
+
+  if (off)
     off++;
-  }
+
   return &ptr[off];
 }
 
@@ -268,13 +272,13 @@
 {
   const char *p = find_line(di, off);
   int i;
-  if (p[0] == ';') {
+  if (p[0] == ';')
     return NULL;
-  }
-  for (i = 0; i < len && p[i] != ' '; i++) {
+
+  for (i = 0; i < len && p[i] != ' '; i++)
     buf[i] = p[i];
-  }
   buf[i] = '\0';
+
   return buf;
 }
 
@@ -287,24 +291,23 @@
   int idx = (min + max) / 2;
   int c = 0;
 
-  if (abs(max - min) < 4) {
+  if (abs(max - min) < 4)
     return -1;
-  }
+
   r = extract_line_index(di, idx, buf, 256);
-  if (r) {
+  if (r)
     c = strcmp(s, r);
-  } else {
+  else
     return -1;
-  }
 
-  if (!c) {
+  if (!c)
     return idx;
-  }
-  if (c * d > 0) {
+
+  if (c * d > 0)
     return do_search_line(di, s, idx, max, d);
-  } else {
+  else
     return do_search_line(di, s, min, idx, d);
-  }
+
   return -1;
 }
 
@@ -312,24 +315,25 @@
 static char *
 first_space(char *str)
 {
-  while (*str && (*str != ' ')) {
+  while (*str && (*str != ' '))
     str++;
-  }
+
   return str;
 }
 
+/* This function returns a pointer with '/' or '\0' */
 static char *
 next_cand_slash(char *str)
 {
-  int p = 0;
   int i = 0;
-  while (*str && (*str != '/' || p == 1)) {
-    if (*str == '[' && i == 0) {
-      p = 1;
-    }
-    if (p == 1 && *str == ']' && *(str + 1) == '/') {
-      p = 0;
-    }
+  int open_bracket = 0;
+
+  while (*str && (*str != '/' || open_bracket == 1)) {
+    if (*str == '[' && i == 0)
+      open_bracket = 1;
+
+    if (open_bracket == 1 && *str == ']' && *(str + 1) == '/')
+      open_bracket = 0;
     str++;
     i++;
   }
@@ -366,19 +370,22 @@
   int i;
 
   str = first_space(str);
-  
   for (i = 0; i <= nth; i++) {
     str = next_cand_slash(str);
-    if (*str == '/') {
+    if (*str == '/')
       str++;
-    }
+    /*
+     * we don't need sanity check here since argument nth is limited
+     * by caller
+     *
+     * if (*str == '\0')
+     *  return NULL;
+     */ 
   }
-  if (*str == '\0') {
+
+  if (*str == '\0')
     return NULL;
-  }
-  if (*str == '/') {
-    str++;
-  }
+
   p = strdup(str);
   term = next_cand_slash(p);
   *term = '\0';
@@ -423,19 +430,20 @@
 {
   int i;
   struct skk_cand_array *ca;
-  if (!okuri || !strlen(okuri)) {
+
+  if (!okuri || !strlen(okuri))
     return &sl->cands[0];
-  }
+
   for (i = 1; i < sl->nr_cand_array; i++) {
-    if (okuri && !strcmp(okuri, sl->cands[i].okuri)) {
+    if (okuri && !strcmp(okuri, sl->cands[i].okuri))
       return &sl->cands[i];
-    }
   }
-  if (!create_if_notfound) {
+
+  if (!create_if_notfound)
     return &sl->cands[0];
-  }
+
   /* allocate now */
-  sl->nr_cand_array ++;
+  sl->nr_cand_array++;
   sl->cands = realloc(sl->cands,
 		      sizeof(struct skk_cand_array) * sl->nr_cand_array);
   ca = &sl->cands[sl->nr_cand_array - 1];
@@ -449,7 +457,7 @@
 }
 
 static void
-push_back_candidate_to_array(struct skk_cand_array *ca, char *cand)
+push_back_candidate_to_array(struct skk_cand_array *ca, const char *cand)
 {
   ca->nr_cands++;
   if (ca->cands)
@@ -465,22 +473,47 @@
 {
   int i, j;
   struct skk_cand_array *src_ca;
-  if (!sl) {
+
+  if (!sl)
     return ;
-  }
+
   src_ca = &sl->cands[0];
-  if (src_ca == dst_ca) {
+  if (src_ca == dst_ca)
     return ;
-  }
+
   for (i = 0; i < src_ca->nr_cands; i++) {
     int dup = 0;
+    int src_purged_cand_index = -1;
+    int dst_purged_cand_index = -1;
+
+    if (i < src_ca->nr_real_cands && is_purged_cand(src_ca->cands[i]))
+      src_purged_cand_index = i;
+
     for (j = 0; j < dst_ca->nr_cands; j++) {
+      if (dst_purged_cand_index == -1 && is_purged_cand(dst_ca->cands[j]))
+	dst_purged_cand_index = j;
       if (!strcmp(src_ca->cands[i], dst_ca->cands[j])) {
 	dup = 1;
       }
     }
     if (!dup) {
-      push_back_candidate_to_array(dst_ca, src_ca->cands[i]);
+      if (src_purged_cand_index != -1 && dst_purged_cand_index != -1)
+	merge_purged_cands(src_ca, dst_ca, src_purged_cand_index,
+			dst_purged_cand_index);
+      else if (src_purged_cand_index != -1 && dst_purged_cand_index == -1)
+	merge_purged_cand_to_dst_array(src_ca, dst_ca,
+			src_ca->cands[src_purged_cand_index]);
+#if 0
+      /*
+       * Just adding words subsequent to real_cands
+       * (push_back_candidate_to_array) is enough.
+       */
+      else if (src_purged_cand_index == -1 && dst_purged_cand_index != -1)
+	merge_word_to_dst_cand_array_with_purged_words(dst_ca,
+			src_ca, src_ca->cands[i]);
+#endif
+      else
+	push_back_candidate_to_array(dst_ca, src_ca->cands[i]);
     }
   }
 }
@@ -555,9 +588,8 @@
     ca->nr_cands = q->nr_cands;
     ca->nr_real_cands = q->nr_real_cands;
     ca->cands = malloc(sizeof(char *) * ca->nr_cands);
-    for (j = 0; j < ca->nr_cands; j++) {
+    for (j = 0; j < ca->nr_cands; j++)
       ca->cands[j] = strdup(q->cands[j]);
-    }
     ca->is_used = q->is_used;
     ca->line = sl;
   }
@@ -574,7 +606,6 @@
   struct skk_line *sl;
 
   sl = alloc_skk_line(word, okuri_head);
-
   /* parse */
   compose_line_parts(di, sl, NULL, entry);
 
@@ -633,7 +664,7 @@
 #endif
 
 static struct skk_line *
-skk_search_line_from_server(struct dic_info *di, const char *s, char okuri_head)
+search_line_from_server(struct dic_info *di, const char *s, char okuri_head)
 {
   char r;
   struct skk_line *sl;
@@ -647,7 +678,7 @@
   fprintf(wserv, "1%s \n", idx);
   ret = fflush(wserv);
   if (ret != 0 && errno == EPIPE) {
-    di->skkserv_ok = skk_open_skkserv(di->skkserv_portnum);
+    di->skkserv_ok = open_skkserv(di->skkserv_portnum);
     return NULL;
   }
 
@@ -687,7 +718,7 @@
 }
 	
 static struct skk_line *
-skk_search_line_from_file(struct dic_info *di, const char *s, char okuri_head)
+search_line_from_file(struct dic_info *di, const char *s, char okuri_head)
 {
   int n;
   const char *p;
@@ -696,18 +727,17 @@
   char *idx = alloca(strlen(s) + 2);
   struct skk_line *sl;
 
-  if (!di->addr) {
+  if (!di->addr)
     return NULL;
-  }
+
   sprintf(idx, "%s%c", s, okuri_head);
-  if (okuri_head) {
+  if (okuri_head)
     n = do_search_line(di, idx, di->first, di->border - 1, -1);
-  } else {
+  else
     n = do_search_line(di, idx, di->border, di->size - 1, 1);
-  }
-  if (n == -1) {
+
+  if (n == -1)
     return NULL;
-  }
 
   p = find_line(di, n);
   len = calc_line_len(p);
@@ -720,18 +750,17 @@
 }
 
 static struct skk_line *
-skk_search_line_from_cache(struct dic_info *di, const char *s, char okuri_head)
+search_line_from_cache(struct dic_info *di, const char *s, char okuri_head)
 {
   struct skk_line *sl;
 
-  if (!di) {
+  if (!di)
     return NULL;
-  }
+
   /* search from cache */
   for (sl = di->head.next; sl; sl = sl->next) {
-    if (!strcmp(sl->head, s) && sl->okuri_head == okuri_head) {
+    if (!strcmp(sl->head, s) && sl->okuri_head == okuri_head)
       return sl;
-    }
   }
   return NULL;
 }
@@ -749,17 +778,15 @@
   if (!di)
     return NULL;
 
-  sl = skk_search_line_from_cache(di, s, okuri_head);
+  sl = search_line_from_cache(di, s, okuri_head);
   if (!sl) {
     if (di->skkserv_ok)
-      sl = skk_search_line_from_server(di, s, okuri_head);
+      sl = search_line_from_server(di, s, okuri_head);
     else
-      sl = skk_search_line_from_file(di, s, okuri_head);
+      sl = search_line_from_file(di, s, okuri_head);
     if (!sl) {
-      if (!create_if_not_found) {
+      if (!create_if_not_found)
 	return NULL;
-      }
-      /**/
       sl = alloc_skk_line(s, okuri_head);
     }
     from_file = 1;
@@ -773,9 +800,9 @@
     ca->is_used = 1;
     if (!from_file) {
       if (di->skkserv_ok)
-	sl_file = skk_search_line_from_server(di, s, okuri_head);
+	sl_file = search_line_from_server(di, s, okuri_head);
       else
-	sl_file = skk_search_line_from_file(di, s, okuri_head);
+	sl_file = search_line_from_file(di, s, okuri_head);
       merge_base_candidates_to_array(sl_file, ca);
       free_skk_line(sl_file);
     }
@@ -808,14 +835,160 @@
   return ca;
 }
 
+/*
+ * purged_cand: /(skk-ignore-dic-word "foo" "bar" ...)/
+ * purged_words: {"foo", "bar", ..., NULL}
+ */
+static int
+is_purged_cand(const char *str)
+{
+  char *p;
 
+  p = strstr(str, "(skk-ignore-dic-word ");
+  if (p == str)
+    return 1;
+
+  return 0;
+}
+
+static char **
+get_purged_words(const char *str)
+{
+  char *p;
+  char **words = NULL;
+  char *word = NULL;
+  const char *evaluated_word;
+  int nr = 0;
+  int open = 0;
+  int len = 0, word_len;
+  uim_lisp return_val;
+
+  p = strstr(str, "(skk-ignore-dic-word");
+  if (!p)
+    return NULL;
+
+  p = first_space(p);
+  if (*p == '\0')
+    return NULL;
+  p++;
+
+  while (*p != '\0') {
+    if (*p == '"') {
+      open = open ? 0 : 1;
+      if (open) {
+	p++;
+	word = p;
+	len = 0;
+      } else {
+	char *orig = malloc(len + 1);
+	nr++;
+	if (words)
+	  words = realloc(words, sizeof(char *) * nr);
+	else {
+	  words = malloc(sizeof(char *));
+	}
+	strncpy(orig, word, len);
+	orig[len] = '\0';
+
+	/* need to eval word. siod dependent like \073 -> ';' */
+	UIM_EVAL_FSTRING1(NULL, "(string-append \"%s\")", orig);
+	return_val = uim_scm_return_value();
+	if (return_val == uim_scm_null_list()) {
+	  words[nr - 1] = malloc(len + 1);
+	  strncpy(words[nr - 1], orig, len);
+	  words[nr - 1][len] = '\0';
+	} else {
+	  evaluated_word = uim_scm_refer_c_str(return_val);
+	  word_len = strlen(evaluated_word);
+	  words[nr - 1] = malloc(word_len + 1);
+	  strncpy(words[nr - 1], evaluated_word, word_len);
+	  words[nr - 1][word_len] = '\0';
+	}
+	free(orig);
+      }
+    }
+    p++;
+    len++;
+  }
+  if (words) {
+    words = realloc(words, sizeof(char *) * (nr + 1));
+    words[nr] = NULL;
+  }
+  return words;
+}
+
+static int
+nr_purged_words(char **p)
+{
+  int i = 0;
+
+  while (p && p[i])
+    i++;
+  return i;
+}
+
+static void
+free_allocated_purged_words(char **p)
+{
+  int i = 0;
+
+  if (!p)
+    return;
+
+  while (p[i]) {
+    free(p[i]);
+    i++;
+  }
+  free(p);
+}
+
+static int
+is_purged_only(struct skk_cand_array *ca)
+{
+  int i, j;
+  char **purged_words;
+
+  if (ca->nr_real_cands > 1)
+    return 0;
+
+  if ((purged_words = get_purged_words(ca->cands[0])) != NULL) {
+    int nr_purged = nr_purged_words(purged_words);
+    /* going to compare words beyond nr_real_cands */
+    for (i = ca->nr_real_cands; i < ca->nr_cands; i++) {
+      for (j = 0; j < nr_purged; j++) {
+	/* return false if there is any different candidate */
+	if (strcmp(ca->cands[i], purged_words[j])) {
+	  free_allocated_purged_words(purged_words);
+	  return 0;
+	}
+      }
+    }
+    free_allocated_purged_words(purged_words);
+    return 1;
+  }
+  return 0;
+}
+
+static int
+match_to_discarding_index(int indices[], int n)
+{
+  int i = 0;
+  while (indices[i] != -1) {
+    if (indices[i] == n)
+      return 1;
+    i++;
+  }
+  return 0;
+}
+
 static uim_lisp
 skk_get_entry(uim_lisp head_, uim_lisp okuri_head_, uim_lisp okuri_)
 {
   struct skk_cand_array *ca;
   ca = find_cand_array_lisp(head_, okuri_head_, okuri_, 0);
   if (ca) {
-    return uim_scm_t();
+    if (!is_purged_only(ca))
+      return uim_scm_t();
   }
   return uim_scm_f();
 }
@@ -1250,6 +1423,7 @@
 get_nth(int nth, uim_lisp lst_)
 {
   int i;
+  /* nth start from 1 */
   for (i = 1; i < nth; i++) {
     if (uim_scm_nullp(lst_)) {
       return uim_scm_null_list();
@@ -1259,6 +1433,54 @@
   return uim_scm_car(lst_);
 }
 
+static int
+get_purged_cand_index(struct skk_cand_array *ca)
+{
+  int i, n = -1;
+
+  if (!ca)
+    return -1;
+
+  for (i = 0; i < ca->nr_real_cands; i++) {
+    if (is_purged_cand(ca->cands[i])) {
+      n = i;
+      break;
+    }
+  }
+  return n;
+}
+
+static int
+get_ignoring_indices(struct skk_cand_array *ca, int indices[])
+{
+  int i, j, k = 0;
+  int purged_cand_index;
+  
+  purged_cand_index= get_purged_cand_index(ca);
+
+  if (purged_cand_index != -1) {
+    char **purged_words = get_purged_words(ca->cands[purged_cand_index]);
+    int nr_purged = nr_purged_words(purged_words);
+
+    indices[k] = purged_cand_index;
+    k++;
+
+    for (i = ca->nr_real_cands; i < ca->nr_cands; i++) {
+      for (j = 0; j < nr_purged; j++) {
+	if (!strcmp(ca->cands[i], purged_words[j])) {
+	  indices[k] = i;
+	  k++;
+	}
+      }
+    }
+    indices[k] = -1;
+    free_allocated_purged_words(purged_words);
+  } else {
+    indices[0] = -1;
+  }
+  return k;
+}
+
 static uim_lisp
 skk_get_nth_candidate(uim_lisp nth_, uim_lisp head_, uim_lisp okuri_head_, uim_lisp okuri_, uim_lisp numlst_)
 {
@@ -1273,13 +1495,19 @@
   int mark;
   uim_lisp str_ = uim_scm_null_list();
 
+  int ignoring_indices[64]; /* XXX is it enough? */
+
   n = uim_scm_c_int(nth_);
   ca = find_cand_array_lisp(head_, okuri_head_, okuri_, 0);
+  get_ignoring_indices(ca, ignoring_indices);
 
   if (ca) {
     /* handle #4 method of numeric conversion */
     if (!uim_scm_nullp(numlst_)) {
       for (i = 0; i < ca->nr_cands; i++) {
+	if (match_to_discarding_index(ignoring_indices, i))
+	  continue;
+
 	if ((p = find_numeric_conv_method4_mark(ca->cands[i], &method_place))) {
 	  numstr = uim_scm_refer_c_str(get_nth(method_place, numlst_));
 	  subca = find_cand_array(skk_dic, numstr, 0, NULL, 0);
@@ -1313,10 +1541,16 @@
 	}
       }
     } else {
-	if (ca->nr_cands > n)
-	  cands = ca->cands[n];
+      for (i = 0; i < ca->nr_cands; i++) {
+	if (match_to_discarding_index(ignoring_indices, i))
+	  continue;
+	if (k == n) {
+	  cands = ca->cands[i];
+	  break;
+	}
+	k++;
+      }
     }
-
   }
 
   if (cands)
@@ -1333,15 +1567,20 @@
   const char *numstr;
   int method_place = 0;
 
+  int ignoring_indices[64]; /* XXX is it enough? */
+
   ca = find_cand_array_lisp(head_, okuri_head_, okuri_, 0);
-  if (ca) {
+  if (ca)
     n = ca->nr_cands;
-  }
   nr_cands = n;
+  nr_cands -= get_ignoring_indices(ca, ignoring_indices);
 
   /* handle #4 method of numeric conversion */
   if (!uim_scm_nullp(numlst_)) {
     for (i = 0; i < n; i++) {
+      if (match_to_discarding_index(ignoring_indices, i))
+	continue;
+
       if (find_numeric_conv_method4_mark(ca->cands[i], &method_place)) {
 	numstr = uim_scm_refer_c_str(get_nth(method_place, numlst_));
 	nr_cands--;
@@ -1356,7 +1595,7 @@
 }
 
 static struct skk_comp_array *
-skk_make_comp_array_from_cache(struct dic_info *di, const char *s)
+make_comp_array_from_cache(struct dic_info *di, const char *s)
 {
   struct skk_line *sl;
   struct skk_comp_array *ca;
@@ -1407,7 +1646,7 @@
       break;
   }
   if (ca == NULL) {
-    ca = skk_make_comp_array_from_cache(di, s);
+    ca = make_comp_array_from_cache(di, s);
   }
 
   return ca;
@@ -1503,7 +1742,7 @@
 }
 
 static void
-reorder_candidate(struct skk_cand_array *ca, char *str)
+reorder_candidate(struct skk_cand_array *ca, const char *str)
 {
   int i;
   int nth = 0;
@@ -1512,66 +1751,263 @@
   for (i = 0; i < ca->nr_cands; i++) {
     if (!strcmp(str, ca->cands[i])) {
       nth = i;
+      break;
     }
   }
 
   /* shift array */
   tmp = ca->cands[nth];
   if (nth) {
-    for (i = nth; i > 0; i--) {
+    for (i = nth; i > 0; i--)
       ca->cands[i] = ca->cands[i - 1];
-    }
     ca->cands[0] = tmp;
     skk_dic->cache_modified = 1;
   }
-  /**/
-  if (nth >= ca->nr_real_cands) {
-    ca->nr_real_cands ++;
+  /* */
+  if (nth >= ca->nr_real_cands)
+    ca->nr_real_cands++;
+}
+
+static void push_purged_word(struct skk_cand_array *ca, int nth, int append, char *word)
+{
+  char *cand = ca->cands[nth];
+  int len, oldlen = strlen(cand);
+  char *p = sanitize_word(word, NULL);
+
+  if (!p)
+    return;
+
+  if (append) {
+    /* check whether the word is already registerd */
+    char **purged_words = get_purged_words(cand);
+    int nr_purged = nr_purged_words(purged_words);
+    int j;
+    for (j = 0; j < nr_purged; j++) {
+      if (!strcmp(purged_words[j], word)) {
+	free_allocated_purged_words(purged_words);
+	return;
+      }
+    }
+    free_allocated_purged_words(purged_words);
+
+    len = oldlen + strlen(p) + 3;
+    cand = realloc(cand, len + 1);
+    if (cand) {
+      cand[oldlen - 1] = '\0';
+      strcat(cand, " \"");
+      strcat(cand, p);
+      strcat(cand, "\")");
+      ca->cands[nth] = cand;
+      skk_dic->cache_modified = 1;
+    }
+  } else {
+    cand = realloc(cand, strlen("(skk-ignore-dic-word \"\")") + strlen(p) + 1);
+    if (cand) {
+      sprintf(cand, "(skk-ignore-dic-word \"%s\")", p);
+      ca->cands[nth] = cand;
+      skk_dic->cache_modified = 1;
+    }
   }
 }
 
+static void remove_candidate_from_array(struct skk_cand_array *ca, int nth)
+{
+  int i;
+
+  free(ca->cands[nth]);
+  for (i = nth; i < ca->nr_cands - 1; i++)
+    ca->cands[i] = ca->cands[i + 1];
+  if (nth < ca->nr_real_cands)
+    ca->nr_real_cands--;
+  ca->nr_cands--;
+  skk_dic->cache_modified = 1;
+}
+
 static void
-merge_word_to_cand_array(struct skk_cand_array *ca, char *word)
+merge_word_to_real_cand_array(struct skk_cand_array *ca, const char *word)
 {
   int i, nth = -1;
   char *tmp;
-  for (i = 0; i < ca->nr_cands; i++) {
-    if (!strcmp(word, ca->cands[i])) {
-      nth = i;
-    }
-  }
-  if (nth == -1) {
-    push_back_candidate_to_array(ca, word);
-    nth = ca->nr_cands - 1;
-  }
 
+  push_back_candidate_to_array(ca, word);
+  nth = ca->nr_cands - 1;
+
   /* move word at the end of real cand array */
   tmp = ca->cands[nth];
   if (nth >= ca->nr_real_cands) {
-    for (i = nth; i > ca->nr_real_cands; i--) {
+    for (i = nth; i > ca->nr_real_cands; i--)
       ca->cands[i] = ca->cands[i - 1];
-    }
     ca->cands[ca->nr_real_cands] = tmp;
     ca->nr_real_cands++;
   }
 }
 
+static int exist_in_purged_cand(struct skk_cand_array *ca,
+		const char *word)
+{
+  int i, purged_cand_index;
+  char **purged_words;
+  int nr_purged;
+
+  purged_cand_index = get_purged_cand_index(ca);
+  if (purged_cand_index == -1)
+    return 0;
+
+  purged_words = get_purged_words(ca->cands[purged_cand_index]);
+  nr_purged = nr_purged_words(purged_words);
+
+  for (i = 0; i < nr_purged; i++) {
+    if (!strcmp(purged_words[i], word)) {
+      free_allocated_purged_words(purged_words);
+      return 1;
+    }
+  }
+  free_allocated_purged_words(purged_words);
+  return 0;
+}
+
+static int index_in_real_cands(struct skk_cand_array *ca, const char *str)
+{
+  int i;
+  for (i = 0; i < ca->nr_real_cands; i++) {
+    if (!strcmp(ca->cands[i], str))
+      return i;
+  }
+  return -1;
+}
+
 static void
+remove_purged_words_from_dst_cand_array(struct skk_cand_array *src_ca,
+		struct skk_cand_array *dst_ca, const char *purged_cand)
+{
+  char **purged_words;
+  int nr_words;
+  int i, j;
+
+  purged_words = get_purged_words(purged_cand);
+  nr_words = nr_purged_words(purged_words);
+
+  for (i = 0; i < nr_words; i++) {
+    int dup = 0;
+
+    if (index_in_real_cands(src_ca, purged_words[i]) != -1)
+      continue;
+
+    for (j = 0; j < dst_ca->nr_real_cands; j++) {
+       if (!strcmp(purged_words[i], dst_ca->cands[j])) {
+	 dup = 1;
+	 break;
+       }
+    }
+    if (dup)
+      remove_candidate_from_array(dst_ca, j);
+  }
+  free_allocated_purged_words(purged_words);
+}
+
+static void
+merge_purged_cands(struct skk_cand_array *src_ca, struct skk_cand_array *dst_ca,
+		int src_nth, int dst_nth)
+{
+  char *src_cand = src_ca->cands[src_nth];
+  char *dst_cand = dst_ca->cands[dst_nth];
+  char **dst_purged_words, **src_purged_words;
+  int nr_dst_purged_words, nr_src_purged_words;
+  int i, j;
+
+  src_purged_words = get_purged_words(src_cand);
+  dst_purged_words = get_purged_words(dst_cand);
+  nr_src_purged_words = nr_purged_words(src_purged_words);
+  nr_dst_purged_words = nr_purged_words(dst_purged_words);
+
+  for (i = 0; i < nr_src_purged_words; i++) {
+    int dup = 0;
+    for (j = 0; j < nr_dst_purged_words; j++) {
+      if (!strcmp(src_purged_words[i], dst_purged_words[j])) {
+	dup = 1;
+	break;
+      }
+    }
+    if (!dup) {
+      push_purged_word(dst_ca, dst_nth, 1, src_purged_words[i]);
+      remove_purged_words_from_dst_cand_array(src_ca, dst_ca, src_ca->cands[src_nth]);
+    }
+  }
+  free_allocated_purged_words(dst_purged_words);
+  free_allocated_purged_words(src_purged_words);
+}
+
+static void
+merge_purged_cand_to_dst_array(struct skk_cand_array *src_ca,
+		struct skk_cand_array *dst_ca, char *purged_cand)
+{
+  remove_purged_words_from_dst_cand_array(src_ca, dst_ca, purged_cand);
+  merge_word_to_real_cand_array(dst_ca, purged_cand);
+}
+
+static void
+merge_word_to_dst_cand_array_with_purged_words(struct skk_cand_array *dst_ca,
+		struct skk_cand_array *src_ca, const char *src_cand)
+{
+  int i, nth;
+  char *tmp;
+
+  if (exist_in_purged_cand(dst_ca, src_cand) && !exist_in_purged_cand(src_ca, src_cand))
+    return;
+
+  push_back_candidate_to_array(dst_ca, src_cand);
+  nth = dst_ca->nr_cands - 1;
+
+  /* move word at the end of real cand array */
+  tmp = dst_ca->cands[nth];
+  if (nth >= dst_ca->nr_real_cands) {
+    for (i = nth; i > dst_ca->nr_real_cands; i--)
+      dst_ca->cands[i] = dst_ca->cands[i - 1];
+    dst_ca->cands[dst_ca->nr_real_cands] = tmp;
+    dst_ca->nr_real_cands++;
+  }
+}
+
+static void
 merge_real_candidate_array(struct skk_cand_array *src_ca,
 			   struct skk_cand_array *dst_ca)
 {
   int i, j;
-  if (!src_ca || !dst_ca) {
+  int src_nr_real_cands = src_ca->nr_real_cands;
+  int dst_nr_real_cands = dst_ca->nr_real_cands;
+
+  if (!src_ca || !dst_ca)
     return ;
-  }
-  for (i = 0; i < src_ca->nr_real_cands; i++) {
+
+  for (i = 0; i < src_nr_real_cands; i++) {
     int dup = 0;
-    for (j = 0; j < dst_ca->nr_real_cands; j++) {
+    int src_purged_cand_index = -1;
+    int dst_purged_cand_index = -1;
+
+    if (is_purged_cand(src_ca->cands[i]))
+      src_purged_cand_index = i;
+
+    for (j = 0; j < dst_nr_real_cands; j++) {
+      if (dst_purged_cand_index == -1 && is_purged_cand(dst_ca->cands[j]))
+	dst_purged_cand_index = j;
       if (!strcmp(src_ca->cands[i], dst_ca->cands[j]))
 	dup = 1;
     }
-    if (!dup)
-      merge_word_to_cand_array(dst_ca, src_ca->cands[i]);
+
+    if (!dup) {
+      /* be careful! */
+      if (src_purged_cand_index != -1 && dst_purged_cand_index != -1)
+	merge_purged_cands(src_ca, dst_ca, src_purged_cand_index,
+			dst_purged_cand_index);
+      else if (src_purged_cand_index != -1 && dst_purged_cand_index == -1)
+	merge_purged_cand_to_dst_array(src_ca, dst_ca,
+			src_ca->cands[src_purged_cand_index]);
+      else if (src_purged_cand_index == -1 && dst_purged_cand_index != -1)
+	merge_word_to_dst_cand_array_with_purged_words(dst_ca, src_ca,
+			src_ca->cands[i]);
+      else
+	merge_word_to_real_cand_array(dst_ca, src_ca->cands[i]);
+    }
   }
 }
 
@@ -1583,29 +2019,30 @@
   struct skk_cand_array *ca, *subca;
   char *str = NULL;
   int i, j, k = 0;
-  int nr_cands = 0;
   uim_lisp numstr_;
   const char *numstr;
   int method_place = 0;
 
+  int ignoring_indices[64]; /* XXX is it enough? */
+
   nth = uim_scm_c_int(nth_);
+  ca = find_cand_array_lisp(head_, okuri_head_, okuri_, 0);
 
-  ca = find_cand_array_lisp(head_, okuri_head_, okuri_, 0);
-  if (!ca) {
+  if (!ca)
     return uim_scm_f();
-  }
+  get_ignoring_indices(ca, ignoring_indices);
 
-  nr_cands = ca->nr_cands;
-
   /* handle #4 method of numeric conversion */
   if (!uim_scm_nullp(numlst_)) {
     for (i = 0; i < ca->nr_cands; i++) {
+      if (match_to_discarding_index(ignoring_indices, i))
+	continue;
+
       if (find_numeric_conv_method4_mark(ca->cands[i], &method_place)) {
 	numstr_ = get_nth(method_place, numlst_);
 	numstr = uim_scm_refer_c_str(numstr_);
 	subca = find_cand_array(skk_dic, numstr, 0, NULL, 0);
 	if (subca) {
-	  nr_cands += subca->nr_cands;
 	  for (j = 0; j < subca->nr_cands; j++) {
 	    if (k == nth) {
 	      str = ca->cands[i];
@@ -1629,9 +2066,17 @@
     if (!str)
       return uim_scm_f();
   } else {
-    if (nr_cands <= nth)
+    for (i = 0; i < ca->nr_cands; i++) {
+      if (match_to_discarding_index(ignoring_indices, i))
+	continue;
+      if (k == nth) {
+	str = ca->cands[i];
+	break;
+      }
+      k++;
+    }
+    if (!str)
       return uim_scm_f();
-    str = ca->cands[nth];
   }
   reorder_candidate(ca, str);
 
@@ -1663,30 +2108,132 @@
   return uim_scm_f();
 }
 
+static void purge_candidate(struct skk_cand_array *ca, int nth)
+{
+    char *str;
+    int i;
+    
+    if (nth == -1)
+      return;
+
+    str = strdup(ca->cands[nth]);
+
+    if ((i = get_purged_cand_index(ca)) == -1) {
+      /* new purged cand in the array */
+      push_purged_word(ca, nth, 0, str);
+    } else {
+      /* append the word to already existing purged cand and remove it own */
+      push_purged_word(ca, i, 1, str);
+      remove_candidate_from_array(ca, nth);
+    }
+    
+    if (ca->okuri) {
+      /* also purge the word in the base cand array */
+      int index = index_in_real_cands(&ca->line->cands[0], str);
+      if (index != -1)
+	purge_candidate(&ca->line->cands[0], index);
+    }
+    free(str);
+}
+
+static uim_lisp
+skk_purge_candidate(uim_lisp head_, uim_lisp okuri_head_,
+		    uim_lisp okuri_, uim_lisp nth_, uim_lisp numlst_)
+{
+  int nth = uim_scm_c_int(nth_);
+  struct skk_cand_array *ca, *subca;
+  char *str = NULL;
+  int i, j, k = 0;
+  uim_lisp numstr_;
+  const char *numstr;
+  int method_place = 0;
+
+  int ignoring_indices[64]; /* XXX is it enough? */
+
+  ca = find_cand_array_lisp(head_, okuri_head_, okuri_, 0);
+  if (!ca)
+    return uim_scm_f(); /* shouldn't happen */
+  get_ignoring_indices(ca, ignoring_indices);
+
+  /* handle #4 method of numeric conversion */
+  if (!uim_scm_nullp(numlst_)) {
+    for (i = 0; i < ca->nr_cands; i++) {
+      if (match_to_discarding_index(ignoring_indices, i))
+	continue;
+
+      if (find_numeric_conv_method4_mark(ca->cands[i], &method_place)) {
+	numstr_ = get_nth(method_place, numlst_);
+	numstr = uim_scm_refer_c_str(numstr_);
+	subca = find_cand_array(skk_dic, numstr, 0, NULL, 0);
+	if (subca) {
+	  for (j = 0; j < subca->nr_cands; j++) {
+	    if (k == nth) {
+	      str = ca->cands[i];
+	      /*
+	       * don't purge word in sub candidate array
+	       * skk_purge_candidate(numstr_, uim_scm_null_list(), uim_scm_null_list(), uim_scm_make_int(j), uim_scm_null_list());
+	       */
+	      break;
+	    }
+	    k++;
+	  }
+	}
+	if (str)
+	  break;
+      } else {
+	if (k == nth) {
+	   str = ca->cands[i];
+	   break;
+	}
+	k++;
+      }
+    }
+    if (!str)
+      return uim_scm_f();
+  } else {
+    for (i = 0; i < ca->nr_cands; i++) {
+      if (match_to_discarding_index(ignoring_indices, i))
+	continue;
+      if (k == nth)
+	break;
+      k++;
+    }
+  }
+  if (i < ca->nr_real_cands)
+    purge_candidate(ca, i);
+
+  return uim_scm_t();
+}
+
 static void
-learn_word_to_cand_array(struct skk_cand_array *ca, char *word)
+learn_word_to_cand_array(struct skk_cand_array *ca, const char *word)
 {
   int i, nth = -1;
   for (i = 0; i < ca->nr_cands; i++) {
     if (!strcmp(word, ca->cands[i])) {
       nth = i;
+      break;
     }
   }
-  if (nth == -1) {
+  if (nth == -1)
     push_back_candidate_to_array(ca, word);
-  }
+
   reorder_candidate(ca, word);
   ca->line->need_save = 1;
 }
 
 static char *
-quote_word(const char *word)
+quote_word(const char *word, const char *prefix)
 {
   char *str;
   const char *p;
   int len;
 
-  str= strdup("(concat \"");
+  if (prefix)
+    str = strdup(prefix);
+  else
+    str = strdup("");
+
   for (p = word; *p; p++) {
     len = strlen(str);
 
@@ -1731,22 +2278,24 @@
     }
   }
   len = strlen(str);
-  str = realloc(str, len + strlen("\")") + 1);
-  strcat(str, "\")");
+  if (prefix) {
+    str = realloc(str, len + strlen("\")") + 1);
+    strcat(str, "\")");
+  }
 
   return str;
 }
 
 static char *
-sanitize_word(const char *arg)
+sanitize_word(const char *str, const char *prefix)
 {
   const char *p;
   int is_space_only = 1;
 
-  if (!arg || !strlen(arg)) {
+  if (!str || !strlen(str)) {
     return NULL;
   }
-  for (p = arg; *p; p++) {
+  for (p = str; *p; p++) {
     switch (*p) {
     case '/':
     case '[':
@@ -1756,7 +2305,7 @@
     case '\\':
     case ';':
     case '"':
-      return quote_word(arg);
+      return quote_word(str, prefix);
     case ' ':
       break;
     default:
@@ -1767,7 +2316,7 @@
   if (is_space_only)
     return NULL;
 
-  return strdup(arg);
+  return strdup(str);
 }
 
 static uim_lisp
@@ -1778,10 +2327,9 @@
   const char *tmp;
 
   tmp = uim_scm_refer_c_str(word_);
-  word = sanitize_word(tmp);
-  if (!word) {
+  word = sanitize_word(tmp, "(concat \"");
+  if (!word)
     return uim_scm_f();
-  }
 
   ca = find_cand_array_lisp(head_, okuri_head_, okuri_, 1);
   if (ca) {
@@ -1825,12 +2373,10 @@
   buf = alloca(strlen(line) + 1);
   strcpy(buf, line);
   sep = strchr(buf, ' ');
-  if (!sep) {
+
+  if (!sep || (sep == buf))
     return;
-  }
-  if (sep == buf) {
-    return;
-  }
+
   *sep = '\0';
   if (!skk_isascii(buf[0]) && skk_islower(sep[-1])) { /* okuri-ari entry */
     char okuri_head = sep[-1];
@@ -1840,11 +2386,9 @@
     sl = compose_line(di, buf, 0, line);
   }
   sl->need_save = 1;
-  /**/
-  for (i = 0; i < sl->nr_cand_array; i++) {
+  /* set nr_real_cands for the candidate array from personal dictionaly */
+  for (i = 0; i < sl->nr_cand_array; i++)
     sl->cands[i].nr_real_cands = sl->cands[i].nr_cands;
-  }
-  /**/
   add_line_to_cache_head(di, sl);
 }
 
@@ -1854,14 +2398,12 @@
   int i;
   if (ca->okuri) {
     fprintf(fp, "[%s/", ca->okuri);
-    for (i = 0; i < ca->nr_real_cands; i++) {
+    for (i = 0; i < ca->nr_real_cands; i++)
       fprintf(fp, "%s/", ca->cands[i]);
-    }
     fprintf(fp, "]/");
   } else {
-    for (i = 0; i < ca->nr_real_cands; i++) {
+    for (i = 0; i < ca->nr_real_cands; i++)
       fprintf(fp, "%s/", ca->cands[i]);
-    }
   }
 }
 
@@ -1933,11 +2475,11 @@
 }
 
 static uim_lisp
-skk_read_personal_dictionary(struct dic_info *di, const char *fn)
+read_personal_dictionary(struct dic_info *di, const char *fn)
 {
   struct stat st;
   FILE *fp;
-  char buf[4096];
+  char buf[4096]; /* XXX */
   int err_flag = 0;
   int lock_fd;
 
@@ -1959,7 +2501,7 @@
 
   di->personal_dic_timestamp = st.st_mtime;
 
-  while (fgets(buf, 4096, fp)) {
+  while (fgets(buf, 4096, fp)) { /* XXX */
     int len = strlen(buf);
     if (buf[len - 1] == '\n') {
       if (err_flag == 0) {
@@ -1982,10 +2524,10 @@
 }
 
 static uim_lisp
-skk_lib_read_personal_dictionary(uim_lisp fn_)
+skk_read_personal_dictionary(uim_lisp fn_)
 {
   const char *fn = uim_scm_refer_c_str(fn_);
-  return skk_read_personal_dictionary(skk_dic, fn);
+  return read_personal_dictionary(skk_dic, fn);
 }
 
 static void push_back_candidate_array_to_sl(struct skk_line *sl,
@@ -2001,9 +2543,8 @@
   ca->is_used = src_ca->is_used;
   ca->nr_cands = src_ca->nr_cands;
   ca->cands = malloc(sizeof(char *) * src_ca->nr_cands);
-  for (i = 0; i < ca->nr_cands; i++) {
+  for (i = 0; i < ca->nr_cands; i++)
     ca->cands[i] = strdup(src_ca->cands[i]);
-  }
 
   ca->nr_real_cands = src_ca->nr_real_cands;
   ca->okuri = strdup(src_ca->okuri);
@@ -2021,7 +2562,10 @@
 
   src_ca = &src_sl->cands[0];
   dst_ca = &dst_sl->cands[0];
-  if (src_ca->nr_real_cands >= dst_ca->nr_real_cands)
+  /*
+   * check all candidate array since purged words may exist.
+   */
+  /* if (src_ca->nr_real_cands >= dst_ca->nr_real_cands) */
     merge_real_candidate_array(src_ca, dst_ca);
 
   for (i = 1; i < src_sl->nr_cand_array; i++) {
@@ -2032,7 +2576,7 @@
       dst_ca = &dst_sl->cands[j];
       if (!strcmp(src_ca->okuri, dst_ca->okuri)) {
 	dup = 1;
-	if (src_ca->nr_real_cands >= dst_ca->nr_real_cands)
+      /* if (src_ca->nr_real_cands >= dst_ca->nr_real_cands) */
 	  merge_real_candidate_array(src_ca, dst_ca);
       }
     }
@@ -2142,7 +2686,7 @@
   if (di == NULL)
     return;
   di->head.next = NULL;
-  skk_read_personal_dictionary(di, fn);
+  read_personal_dictionary(di, fn);
   di->head.next = lsort(di->head.next);
 
   /* keep original sequence of cache */
@@ -2196,7 +2740,7 @@
 }
 
 static uim_lisp
-skk_lib_save_personal_dictionary(uim_lisp fn_)
+skk_save_personal_dictionary(uim_lisp fn_)
 {
   FILE *fp;
   const char *fn = uim_scm_refer_c_str(fn_);
@@ -2250,7 +2794,7 @@
 }
 
 static uim_lisp
-skk_lib_get_annotation(uim_lisp str_)
+skk_get_annotation(uim_lisp str_)
 {
   const char *str, *sep;
   uim_lisp res;
@@ -2269,7 +2813,7 @@
 }
 
 static uim_lisp
-skk_lib_remove_annotation(uim_lisp str_)
+skk_remove_annotation(uim_lisp str_)
 {
   char *str, *sep;
   uim_lisp res;
@@ -2319,6 +2863,7 @@
   strcpy(str, "(string-append");
   strncat(str, p + strlen("(concat"), q - (p + strlen("(concat")) + 1);
 
+  /* XXX string expansion like \073 -> ';' is siod dependent */
   UIM_EVAL_FSTRING1(NULL, "%s", str);
   return_val = uim_scm_return_value();
   if (return_val == uim_scm_null_list()) {
@@ -2350,8 +2895,8 @@
 uim_plugin_instance_init(void)
 {
   uim_scm_init_subr_3("skk-lib-dic-open", skk_dic_open);
-  uim_scm_init_subr_1("skk-lib-read-personal-dictionary", skk_lib_read_personal_dictionary);
-  uim_scm_init_subr_1("skk-lib-save-personal-dictionary", skk_lib_save_personal_dictionary);
+  uim_scm_init_subr_1("skk-lib-read-personal-dictionary", skk_read_personal_dictionary);
+  uim_scm_init_subr_1("skk-lib-save-personal-dictionary", skk_save_personal_dictionary);
   uim_scm_init_subr_3("skk-lib-get-entry", skk_get_entry);
   uim_scm_init_subr_1("skk-lib-store-replaced-numstr", skk_store_replaced_numeric_str);
   uim_scm_init_subr_2("skk-lib-merge-replaced-numstr", skk_merge_replaced_numeric_str);
@@ -2359,9 +2904,10 @@
   uim_scm_init_subr_5("skk-lib-get-nth-candidate", skk_get_nth_candidate);
   uim_scm_init_subr_4("skk-lib-get-nr-candidates", skk_get_nr_candidates);
   uim_scm_init_subr_5("skk-lib-commit-candidate", skk_commit_candidate);
+  uim_scm_init_subr_5("skk-lib-purge-candidate", skk_purge_candidate);
   uim_scm_init_subr_4("skk-lib-learn-word", skk_learn_word);
-  uim_scm_init_subr_1("skk-lib-get-annotation", skk_lib_get_annotation);
-  uim_scm_init_subr_1("skk-lib-remove-annotation", skk_lib_remove_annotation);
+  uim_scm_init_subr_1("skk-lib-get-annotation", skk_get_annotation);
+  uim_scm_init_subr_1("skk-lib-remove-annotation", skk_remove_annotation);
   uim_scm_init_subr_1("skk-lib-get-completion", skk_get_completion);
   uim_scm_init_subr_2("skk-lib-get-nth-completion", skk_get_nth_completion);
   uim_scm_init_subr_1("skk-lib-get-nr-completions", skk_get_nr_completions);
@@ -2388,7 +2934,7 @@
   }
 
   if (skk_dic->skkserv_ok)
-    skk_close_skkserv();
+    close_skkserv();
 
   free(skk_dic);
   skk_dic = NULL;
@@ -2396,7 +2942,7 @@
 
 /* skkserv related */
 static int
-skk_open_skkserv(int portnum)
+open_skkserv(int portnum)
 {
   int sock;
   struct sockaddr_in hostaddr;
@@ -2453,7 +2999,7 @@
 }
 
 static void
-skk_close_skkserv()
+close_skkserv()
 {
   if (skkservsock >= 0) {
     fprintf(wserv, "0\n");



More information about the uim-commit mailing list