[Anthy-dev 919] Re: skk.scm preedit

Back to archive index

Etsushi Kato ekato****@ees*****
2004年 7月 14日 (水) 21:55:34 JST


さきほど昨日のコードを少し変更したので、もういちど新しいパッチを送りま
す (何度もすみません…)。

On Tue, Jul 13, 2004 at 08:54:02PM +0900,
Etsushi Kato <ekato****@ees*****> wrote:

> skk.scm のいじりのついでに、見出し語の補完機能を試しに追加してみました。
> とりあえず使えればいいという感じのプログラムなのではずかしいですが、
> uim-0.4.1 の skk.scm と skk-dic.c に対するパッチを添付しておきます。
> 
> 今作ったばかりなのでバグがあるかもしれませんし、変なところもおもいっき
> りあると思いますが、改善点がありましたら教えてください。

昨日のコードだと、次の補完候補を選んだりするときに毎回候補を作り直して
しまっていたので、それを止め、skk-proc-state-completion にいる間は補完
候補を維持するように変更しました。たぶんメモリーリークがなくなって、補
完候補選択の速度も速くなったと思います。ということで、もう一度 0.4.1 
に対するパッチです。もしよろしければ、お試し下さい。

-- 
Etsushi Kato
ekato****@ees*****
-------------- next part --------------
--- skk-dic.c.orig	Fri May 14 16:04:17 2004
+++ skk-dic.c	Wed Jul 14 21:31:33 2004
@@ -87,6 +87,12 @@
   struct skk_line head;
 } *skk_dic;
 
+/* completion */
+struct skk_comp_array {
+  int nr_comps;
+  char **comps;
+} *skk_comp;
+
 static int
 calc_line_len(char *s)
 {
@@ -437,12 +443,48 @@
 }
 
 static void
-add_line_to_cache(struct dic_info *di, struct skk_line *sl)
+add_line_to_cache_head(struct dic_info *di, struct skk_line *sl)
 {
   sl->next = di->head.next;
   di->head.next = sl;
 }
 
+static void
+move_line_to_cache_head(struct dic_info *di, struct skk_line *sl)
+{
+  struct skk_line *head, *prev;
+
+  if (di->head.next == sl)
+    return;
+
+  head = di->head.next;
+  prev = head;
+  while (prev->next != sl) {
+    prev = prev->next;
+  }
+  prev->next = sl->next;
+  sl->next = di->head.next;
+  di->head.next = sl;
+}
+
+static void
+add_line_to_cache_last(struct dic_info *di, struct skk_line *sl)
+{
+  struct skk_line *head, *prev;
+
+  if (di->head.next == NULL)
+    di->head.next = sl;
+  else {
+    head = di->head.next;
+    prev = head;
+    while (prev->next) {
+      prev = prev->next;
+    }	
+    prev->next = sl;
+  }
+  sl->next = NULL;
+}
+
 static struct skk_line *
 skk_search_line_from_file(struct dic_info *di, char *s, char okuri_head)
 {
@@ -515,7 +557,7 @@
       sl = alloc_skk_line(s, okuri_head);
     }
     from_file = 1;
-    add_line_to_cache(di, sl);
+    add_line_to_cache_head(di, sl);
   }
 
   ca = find_candidate_array_from_line(sl, okuri, create_if_not_found);
@@ -602,6 +644,98 @@
   return intcons(n);
 }
 
+static struct skk_comp_array *
+skk_make_comp_array_from_cache(struct dic_info *di, char *s)
+{
+  struct skk_line *sl;
+  struct skk_comp_array *ca;
+
+  if (!di) {
+    return NULL;
+  }
+  ca = malloc(sizeof(struct skk_comp_array));
+  ca->nr_comps = 0;
+  ca->comps = 0;
+  /* search from cache */
+  for (sl = di->head.next; sl; sl = sl->next) {
+    if (!strncmp(sl->head, s, strlen(s)) && strcmp(sl->head, s) &&
+        (sl->okuri_head == NULL)) {
+      ca->nr_comps++;
+      ca->comps = realloc(ca->comps, sizeof(char *) * ca->nr_comps);
+      ca->comps[ca->nr_comps - 1] = strdup(sl->head);
+    }
+  }
+  if (ca->nr_comps == 0) {
+    free(ca);
+    ca = NULL;
+  }
+  return ca;
+}
+
+static struct skk_comp_array *
+find_comp_array(struct dic_info *di, char *s)
+{
+  struct skk_comp_array *ca;
+  ca = skk_make_comp_array_from_cache(skk_dic, s);
+  return ca;
+}
+
+static struct skk_comp_array *
+find_comp_array_lisp(LISP head_)
+{
+  char *hs;
+  struct skk_comp_array *ca;
+  
+  hs = get_c_string(head_);
+  ca = find_comp_array(skk_dic, hs);
+  return ca;
+}
+
+static LISP
+skk_get_completion(LISP head_)
+{
+  skk_comp = find_comp_array_lisp(head_);
+  if (skk_comp)
+	  return siod_true_value();
+  return NIL;
+}
+
+static LISP
+skk_get_nth_completion(LISP nth_, LISP head_)
+{
+  int n;
+  char *str;
+
+  n = get_c_int(nth_);
+  if (skk_comp && skk_comp->nr_comps > n) {
+    str = skk_comp->comps[n];
+    return strcons(strlen(str), str);
+  }
+  return NIL;
+}
+
+static LISP
+skk_get_nr_completions(LISP head_)
+{
+  int n = 0;
+
+  if (skk_comp) {
+    n = skk_comp->nr_comps;
+  }
+  return intcons(n);
+}
+
+static LISP
+skk_clear_completions(void)
+{
+  if (skk_comp) {
+    free(skk_comp->comps);
+    free(skk_comp);
+    skk_comp = NULL;
+  }
+  return siod_true_value();
+}
+
 static void
 reorder_candidate(struct skk_cand_array *ca, char *str)
 {
@@ -639,6 +773,8 @@
 
   nth = get_c_int(nth_);
   if (nth == 0) {
+    ca = find_cand_array_lisp(head_, okuri_head_, okuri_, 0);
+    move_line_to_cache_head(skk_dic, ca->line);
     return NIL;
   }
 
@@ -659,6 +795,7 @@
   }
 
   ca->line->need_save = 1;
+  move_line_to_cache_head(skk_dic, ca->line);
 
   return NIL;
 }
@@ -757,7 +894,7 @@
     sl->cands[i].nr_real_cands = sl->cands[i].nr_cands;
   }
   /**/
-  add_line_to_cache(skk_dic, sl);
+  add_line_to_cache_last(skk_dic, sl);
 }
 
 static void
@@ -878,6 +1015,10 @@
   init_subr_4("skk-lib-commit-candidate", skk_commit_candidate);
   init_subr_4("skk-lib-learn-word", skk_learn_word);
   init_subr_1("skk-lib-remove-annotation", skk_lib_remove_annotation);
+  init_subr_1("skk-lib-get-completion", skk_get_completion);
+  init_subr_2("skk-lib-get-nth-completion", skk_get_nth_completion);
+  init_subr_1("skk-lib-get-nr-completions", skk_get_nr_completions);
+  init_subr_0("skk-lib-clear-completions", skk_clear_completions);
 }
 
 void
-------------- next part --------------
--- skk.scm.orig	Tue Jul  6 03:57:34 2004
+++ skk.scm	Wed Jul 14 21:34:41 2004
@@ -36,6 +36,7 @@
 ;; Following is list of SKK input state
 ;;  直接入力 direct
 ;;  漢字入力 kanji
+;;  見出し語補完 completion
 ;;  変換中 converting
 ;;  送りがな okuri
 ;;  英数 latin
@@ -65,6 +66,9 @@
 (define-key skk-latin-key? '("l" generic-off-key?))
 (define-key skk-wide-latin-key? "L")
 (define-key skk-begin-conv-key? 'generic-begin-conv-key?)
+(define-key skk-begin-completion-key? "tab")
+(define-key skk-next-completion-key? '("tab" "."))
+(define-key skk-prev-completion-key? ",")
 (define-key skk-on-key? '("<Control>j" "<Control>J" generic-on-key?))
 (define-key skk-hankaku-kana-key? '("<Control>q" "<Control>Q"))
 (define-key skk-return-key? 'generic-return-key?)
@@ -144,6 +148,12 @@
 
 ;; access
 
+(define skk-context-completion-nth
+  (lambda (c)
+    (car (nthcdr 15 c))))
+(define skk-context-set-completion-nth!
+  (lambda (c nth)
+    (set-car! (nthcdr 15 c) nth)))
 (define skk-context-commit-raw
   (lambda (c)
     (car (nthcdr 14 c))))
@@ -291,7 +301,7 @@
 	  (skk-read-personal-dictionary)))
     (let ((sc 
 	   (copy-list 
-	    '(skk-state-latin 0 "" "" "" () () () () () () () () () #f))))
+	    '(skk-state-latin 0 "" "" "" () () () () () () () () () #f ()))))
       (skk-context-set-head! sc ())
       (skk-context-set-rk-context! sc
 				   (rk-context-new ja-rk-rule #t #f))
@@ -385,6 +395,18 @@
      sc
      (skk-context-nth sc))))
 
+(define skk-get-nth-completion
+  (lambda (sc n)
+    (skk-lib-get-nth-completion
+     n
+     (skk-make-string (skk-context-head sc) skk-type-hiragana))))
+
+(define skk-get-current-completion
+  (lambda (sc)
+    (skk-get-nth-completion
+     sc
+     (skk-context-completion-nth sc))))
+
 (define skk-commit-raw
   (lambda (sc id key key-state)
     (let ((psc (skk-context-parent-context sc)))
@@ -450,6 +472,15 @@
       sc
       (cons str (skk-context-head sc))))))
 
+(define skk-list-to-context-head
+  (lambda (sc lst len n)
+    (and
+     lst 
+     (> len n)
+     (skk-context-set-head! sc (cons (nthcdr n lst) (skk-context-head sc)))
+     (set! n (+ n 1))
+     (skk-list-to-context-head sc lst len n))))
+
 (define skk-append-residual-kana
   (lambda (sc)
     (let* ((rkc (skk-context-rk-context sc))
@@ -479,6 +510,22 @@
 	      (skk-flush sc)))
       ())))
 
+(define skk-begin-completion
+  (lambda (sc id)
+    (let ((res))
+      ;; get residual 'n'
+      (if (= (skk-context-state sc) 'skk-state-kanji)
+	  (skk-append-residual-kana sc))
+      ;;
+      (set! res
+	    (skk-lib-get-completion
+	     (skk-make-string (skk-context-head sc) skk-type-hiragana)))
+      (if res
+	  (begin
+	    (skk-context-set-completion-nth! sc 0)
+	    (skk-context-set-state! sc 'skk-state-completion)))
+      )))
+
 (define skk-do-update-preedit
   (lambda (id sc)
     (let ((rkc (skk-context-rk-context sc))
@@ -488,6 +535,7 @@
 	   (not csc)
 	   (or
 	    (= stat 'skk-state-kanji)
+	    (= stat 'skk-state-completion)
 	    (= stat 'skk-state-okuri)))
 	  (im-pushback-preedit id skk-preedit-attr-mode-mark "▽"))
       (if (or
@@ -520,6 +568,13 @@
 	     id skk-preedit-attr-conv-okuri
 	     (skk-make-string (skk-context-okuri sc)
 			      (skk-context-kana-mode sc)))))
+      (if (and
+	   (= stat 'skk-state-completion)
+	   (not csc))
+	  (begin
+	    (im-pushback-preedit
+	     id skk-preedit-attr-head
+	     (skk-get-current-completion sc))))
 
       (if (or
 	   (= stat 'skk-state-okuri)
@@ -548,6 +603,7 @@
 	    (if (and
 		 (or
 		  (= stat 'skk-state-kanji)
+		  (= stat 'skk-state-completion)
 		  (= stat 'skk-state-okuri))
 		 skk-show-cursor-on-preedit?)
 		(im-pushback-preedit id preedit-cursor ""))))
@@ -791,6 +847,11 @@
 	     (skk-begin-conversion sc id)
 	     #f)
 	   #t)
+       (if (skk-begin-completion-key? key key-state)
+	   (begin
+	     (skk-begin-completion sc id)
+	     #f)
+	   #t)
        (if (skk-cancel-key? key key-state)
 	   (begin
 	     (skk-flush sc)
@@ -961,6 +1022,53 @@
 				       (skk-context-head sc))))
     (skk-context-set-okuri! sc ())))
 
+(define skk-change-completion-index
+  (lambda (sc id incr)
+    (if incr
+	(begin
+	  (if (> (- (skk-lib-get-nr-completions
+		  (skk-make-string (skk-context-head sc) skk-type-hiragana)) 1)
+		 (skk-context-completion-nth sc))
+	      (skk-context-set-completion-nth!
+	       sc
+	       (+ 1 (skk-context-completion-nth sc)))))
+	(begin
+	  (if (> (skk-context-completion-nth sc) 0)
+	      (skk-context-set-completion-nth!
+	       sc
+	       (- (skk-context-completion-nth sc) 1)))))
+    #f))
+
+(define skk-proc-state-completion
+  (lambda (c key key-state)
+    (let ((sc (skk-current-context c))
+	  (id (context-id c))
+	  (res)
+	  (len))
+      (and
+       (if (skk-next-completion-key? key key-state)
+	   (skk-change-completion-index sc id #t)
+	   #t)
+       (if (skk-prev-completion-key? key key-state)
+	   (skk-change-completion-index sc id #f)
+	   #t)
+       (if (skk-cancel-key? key key-state)
+	   (begin
+	     (skk-lib-clear-completions)
+	     (skk-context-set-state! sc 'skk-state-kanji)
+	     #f)
+	   #t)
+       (begin
+	 (set! res
+	       (reverse (string-to-list (skk-get-current-completion sc))))
+	 (set! len (length res))
+	 (skk-context-set-head! sc '())
+	 (skk-list-to-context-head sc res len 0)
+	 (skk-lib-clear-completions)
+	 (skk-context-set-state! sc 'skk-state-kanji)
+	 (set! res (skk-proc-state-kanji c key key-state))))
+      #f)))
+
 (define skk-proc-state-converting
   (lambda (c key key-state)
     (let ((sc (skk-current-context c))
@@ -1010,6 +1118,7 @@
 	 (skk-prepare-commit-string sc id)
 	 (skk-commit sc id res)
 	 (skk-flush sc)
+	 (skk-update-preedit id sc)
 	 (set! res (skk-proc-state-direct c key key-state))))
       res)))
 
@@ -1112,6 +1221,8 @@
 		  skk-proc-state-direct)
 		 ((= state 'skk-state-kanji)
 		  skk-proc-state-kanji)
+		 ((= state 'skk-state-completion)
+		  skk-proc-state-completion)
 		 ((= state 'skk-state-converting)
 		  skk-proc-state-converting)
 		 ((= state 'skk-state-okuri)


Anthy-dev メーリングリストの案内
Back to archive index