Tamagotchy snapshot.
[elisp/egg.git] / egg / wnn.el
1 ;;; egg/wnn.el --- WNN Support (high level interface) in Egg
2 ;;;                Input Method Architecture
3
4 ;; Copyright (C) 1997 Mule Project, Powered by Electrotechnical
5 ;; Laboratory, JAPAN.
6 ;; Project Leader: Satoru Tomura <tomura@etl.go.jp>
7
8 ;; Author: NIIBE Yutaka <gniibe@mri.co.jp>
9 ;; Maintainer: NIIBE Yutaka <gniibe@mri.co.jp>
10
11 ;; This file will be part of GNU Emacs (in future).
12
13 ;; GNU Emacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; any later version.
17
18 ;; GNU Emacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 ;; GNU General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
25 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 ;; Boston, MA 02111-1307, USA.
27
28 ;;; Commentary:
29
30 ;;; Code:
31
32 (eval-when-compile
33   (defmacro WNN-const (c)
34     (cond ((eq c 'BUN_SENTOU) -1)
35           ((eq c 'NO_EXIST)  1)
36           ((eq c 'NO_MATCH) 10)
37           ((eq c 'IMA_OFF)   -4)
38           ((eq c 'IMA_ON)    -3)
39           ((eq c 'HINDO_NOP) -2)
40           ((eq c 'HINDO_INC) -3))))
41
42 (defconst wnn-conversion-backend
43   [ wnn-init
44
45     wnn-start-conversion
46       wnn-get-bunsetsu-converted
47       wnn-get-bunsetsu-source
48       wnn-list-candidates
49           wnn-get-number-of-candidates
50           wnn-get-current-candidate-number
51           wnn-get-all-candidates
52           wnn-decide-candidate
53       wnn-change-bunsetsu-length
54     wnn-end-conversion
55
56     wnn-fini
57  ])
58
59 ;; <env> ::= [ <proc> <env-id> <daibunsetsu-info> ]
60
61 (defsubst wnnenv-create (proc env-id)
62   (vector proc env-id nil))
63
64 (defsubst wnnenv-get-proc (env)
65   (aref env 0))
66
67 (defsubst wnnenv-get-env-id (env)
68   (aref env 1))
69
70 (defsubst wnnenv-get-daibunsetsu-info (env)
71   (aref env 2))
72 (defsubst wnnenv-set-daibunsetsu-info (env d)
73   (aset env 2 d))
74
75 ;; <bunsetsu> ::= [ <env> <end> <start> <jiritsugo-end> <dic-no>
76 ;;                  <entry> <freq> <right-now> <hinshi> <status>
77 ;;                  <status-backward> <kangovect> <evaluation>
78 ;;
79 ;;                  <converted> <yomi> <fuzokugo>
80 ;;                  <zenkouho> <freq-down>
81 ;;                  <zenkouho-pos> ]
82 ;;
83 (defsubst wnn-bunsetsu-create (e end start jiritsugo-end dic-no entry freq
84                                right-now hinshi status status-backward
85                                kangovect evaluation)
86   (vector e end start jiritsugo-end dic-no entry freq right-now
87           hinshi status status-backward kangovect evaluation
88           nil nil nil nil nil nil))
89
90 (defsubst wnn-bunsetsu-get-env (bunsetsu)
91   (aref bunsetsu 0))
92
93 (defsubst wnn-bunsetsu-get-converted (bunsetsu)
94   (aref bunsetsu 13))
95 (defsubst wnn-bunsetsu-set-converted (bunsetsu converted)
96   (aset bunsetsu 13 converted))
97
98 (defsubst wnn-bunsetsu-get-hinshi (bunsetsu)
99   (aref bunsetsu 8))
100
101 (defsubst wnn-bunsetsu-get-dic-no (bunsetsu)
102   (aref bunsetsu 4))
103
104 (defsubst wnn-bunsetsu-get-entry (bunsetsu)
105   (aref bunsetsu 5))
106
107 (defsubst wnn-bunsetsu-get-right-now (bunsetsu)
108   (aref bunsetsu 7))
109
110 (defsubst wnn-bunsetsu-get-yomi (bunsetsu)
111   (aref bunsetsu 14))
112 (defsubst wnn-bunsetsu-set-yomi (bunsetsu yomi)
113   (aset bunsetsu 14 yomi))
114
115 (defsubst wnn-bunsetsu-get-fuzokugo (bunsetsu)
116   (aref bunsetsu 15))
117 (defsubst wnn-bunsetsu-set-fuzokugo (bunsetsu fuzokugo)
118   (aset bunsetsu 15 fuzokugo))
119
120 (defsubst wnn-bunsetsu-get-zenkouho (bunsetsu)
121   (aref bunsetsu 16))
122 (defsubst wnn-bunsetsu-set-zenkouho (bunsetsu z)
123   (aset bunsetsu 16 z))
124
125 (defsubst wnn-bunsetsu-get-freq-down (bunsetsu)
126   (aref bunsetsu 17))
127 (defsubst wnn-bunsetsu-set-freq-down (bunsetsu d)
128   (aset bunsetsu 17 d))
129
130 (defsubst wnn-bunsetsu-get-zenkouho-pos (bunsetsu)
131   (aref bunsetsu 18))
132 (defsubst wnn-bunsetsu-set-zenkouho-pos (bunsetsu zp)
133   (aset bunsetsu 18 zp))
134 \f
135 (defvar wnn-server "localhost"
136   "Hostname of wnn server")
137
138 (defvar wnn-environment nil
139   "Environment for WNN kana-kanji conversion")
140
141 (defun wnn-init ()
142   )
143
144 (defun wnn-start-conversion (yomi)
145   "Convert YOMI string to kanji, and enter conversion mode.
146 Return the list of bunsetsu."
147   (let* ((env (wnn-get-environment wnn-dictionary-specification))
148          (result (wnnrpc-renbunsetsu-conversion env yomi
149                                                 (WNN-const BUN_SENTOU) "")))
150     (wnnenv-set-daibunsetsu-info env (car result))
151     (cdr result)))
152
153 (defun wnn-get-bunsetsu-converted (bunsetsu)
154   (concat (wnn-bunsetsu-get-converted bunsetsu)
155           (wnn-bunsetsu-get-fuzokugo  bunsetsu)))
156
157 ;; WNN-UNIQ-CANDIDATES
158 ;;
159 ;; Here, IMNSHO, WNN is broken.
160 ;; WNN must/should return unique one.  The word is representative
161 ;; among possible words with same string literal.
162 ;;
163 ;; With no bunsetsu information to users, users have to chose
164 ;; the word based on the string literal only.
165 ;; How we could update frequency?
166 ;;
167 ;; We'll modify WNN in future.
168 ;;
169 ;; 
170 (defun wnn-uniq-candidates (bunsetsu bunsetsu-list)
171   (let ((hash-table (make-vector 31 0)) ; XXX why 31?
172         (l bunsetsu-list)
173         (i 0)
174         n sym0 result p b sym)
175     (setq sym0 (intern (wnn-get-bunsetsu-converted bunsetsu) hash-table))
176     (while l
177       (setq b (car l)
178             l (cdr l)
179             sym (intern (wnn-get-bunsetsu-converted b) hash-table))
180       (if (null (boundp sym))           ; new one
181           (let ((bl (cons b nil)))
182             (set sym b)
183             (if (eq sym0 sym)
184                 (wnn-bunsetsu-set-zenkouho-pos bunsetsu (setq n i)))
185             (if p
186                 (setq p (setcdr p bl))
187               (setq result (setq p bl)))
188             (setq i (1+ i)))))
189     (wnn-bunsetsu-set-zenkouho bunsetsu result)
190     n))
191
192 (defun wnn-list-candidates (bunsetsu prev-bunsetsu)
193   (let* ((candidates (wnn-bunsetsu-get-zenkouho bunsetsu))
194          (yomi (concat (wnn-bunsetsu-get-yomi bunsetsu)
195                        (wnn-bunsetsu-get-fuzokugo bunsetsu)))
196          (converted (concat (wnn-bunsetsu-get-converted bunsetsu)
197                             (wnn-bunsetsu-get-fuzokugo bunsetsu)))
198          (env (wnn-bunsetsu-get-env bunsetsu))
199          prev-hinshi
200          prev-fuzokugo)
201     (if candidates
202         ;; We have the candidates already.  Return the current position.
203         (wnn-bunsetsu-get-zenkouho-pos bunsetsu)
204       (if (null prev-bunsetsu)
205           (setq prev-hinshi -1
206                 prev-fuzokugo "")
207         (setq prev-hinshi (wnn-bunsetsu-get-hinshi prev-bunsetsu)
208               prev-fuzokugo (wnn-bunsetsu-get-fuzokugo prev-bunsetsu)))
209       (setq candidates
210             (wnnrpc-get-bunsetsu-candidates env yomi
211                                             prev-hinshi prev-fuzokugo))
212       (wnn-uniq-candidates bunsetsu candidates))))
213
214 (defun wnn-get-number-of-candidates (bunsetsu)
215   (let ((l (wnn-bunsetsu-get-zenkouho bunsetsu)))
216     (if l
217         (length l)
218       nil)))
219
220 (defun wnn-get-current-candidate-number (bunsetsu)
221   (wnn-bunsetsu-get-zenkouho-pos bunsetsu))
222
223 (defun wnn-get-all-candidates (bunsetsu)
224   (let* ((l (wnn-bunsetsu-get-zenkouho bunsetsu))
225          (result (cons nil nil))
226          (r result))
227     (catch 'break
228       (while t
229         (let ((candidate (car l)))
230           (setcar r (concat (wnn-bunsetsu-get-converted candidate)
231                             (wnn-bunsetsu-get-fuzokugo candidate)))
232           (if (null (setq l (cdr l)))
233               (throw 'break nil)
234             (setq r (setcdr r (cons nil nil)))))))
235     result))
236
237 (defun wnn-decide-candidate (bunsetsu candidate-pos)
238   (let* ((candidate-list (wnn-bunsetsu-get-zenkouho bunsetsu))
239          (candidate (nth candidate-pos candidate-list)))
240     (wnn-bunsetsu-set-zenkouho candidate candidate-list)
241     (wnn-bunsetsu-set-zenkouho-pos candidate candidate-pos)
242     candidate))
243
244 ;;
245 ;;
246 (defun wnn-change-bunsetsu-length (b0 b1 b2 len)
247   (let ((yomi (concat
248                (wnn-get-bunsetsu-source b1)
249                (if b2 (wnn-get-bunsetsu-source b2))))
250         (env (wnn-bunsetsu-get-env b1))
251         yomi1 yomi2 prev-hinshi prev-fuzokugo
252         bunsetsu1 bunsetsu2)
253     (if (null b0)
254         (setq prev-hinshi -1
255               prev-fuzokugo "")
256       (setq prev-hinshi (wnn-bunsetsu-get-hinshi b0)
257             prev-fuzokugo (wnn-bunsetsu-get-fuzokugo b0)))
258     (save-match-data
259       (string-match (concat "^\\(" (make-string len ?.) "\\)\\(.*$\\)") yomi)
260       (setq yomi1 (match-string 1 yomi))
261       (setq yomi2 (match-string 2 yomi)))
262     (setq bunsetsu1
263           (car (wnnrpc-tanbunsetsu-conversion env yomi1
264                                               prev-hinshi prev-fuzokugo)))
265     ;; Only set once.
266     (wnn-bunsetsu-set-freq-down bunsetsu1
267                                 (or (wnn-bunsetsu-get-freq-down b1)
268                                     (if b2
269                                         (list b1 b2)
270                                       (list b1))))
271     (if (< 0 (length yomi2))
272         ;; RENBUNSETSU? XXX
273         (setq bunsetsu2
274               (car (wnnrpc-tanbunsetsu-conversion
275                     env yomi2
276                     (wnn-bunsetsu-get-hinshi bunsetsu1)
277                     (wnn-bunsetsu-get-fuzokugo bunsetsu1))))
278       (setq bunsetsu2 nil))
279     (if bunsetsu2
280         (list bunsetsu1 bunsetsu2)
281       (list bunsetsu1))))
282
283
284 (defun wnn-get-bunsetsu-source (bunsetsu)
285   (concat (wnn-bunsetsu-get-yomi bunsetsu)
286           (wnn-bunsetsu-get-fuzokugo bunsetsu)))
287
288 (defun wnn-end-conversion (bunsetsu-info-list)
289   (let ((env (wnn-bunsetsu-get-env (car bunsetsu-info-list))))
290     (wnn-update-frequency env bunsetsu-info-list)
291     (wnnenv-set-daibunsetsu-info env nil)))
292
293 (defvar wnn-sticky-environment-flag nil
294   "*Flag which specifies sticky environment.")
295
296 (defun wnn-fini ()                      ; XXX
297   (if (null wnn-environment)
298       nil
299     (condition-case nil
300         (progn
301           (if wnn-sticky-environment-flag
302               (wnnrpc-make-env-sticky wnn-environment)
303             (wnnrpc-make-env-unsticky wnn-environment))
304           (wnnrpc-disconnect wnn-environment))
305       (error nil))
306     (let ((proc (wnnenv-get-proc wnn-environment)))
307       (if (eq (process-status proc) 'open)
308           (progn
309             (wnnrpc-close proc)
310             (kill-buffer (process-buffer proc))
311             (delete-process proc))))
312     (setq wnn-environment nil)))
313 \f
314 ;; XXX should be array (index: server) of {C,J,K}server
315 (defconst wnn-jserver-port 22273)
316 ;;
317 (defun wnn-comm-sentinel (proc reason)  ; assume it is close
318   (kill-buffer (process-buffer proc))
319   (delete-process proc)
320   (setq wnn-environment nil)
321   (message "WNN: connection closed"))
322
323 ;;
324 (defun wnn-open (hostname language)
325   "Establish the connection to WNN server.  Return process object."
326   ;; Specifying language (jserver/cserver/kserver),
327   ;; open the session to WNN server, 
328   (let ((buf (generate-new-buffer " *WNN*"))
329         proc result)
330     (condition-case result
331         (setq proc (open-network-stream "WNN" buf hostname wnn-jserver-port))
332       (error (progn
333                (kill-buffer buf)
334                (signal (car result) (cdr result)))))
335     (process-kill-without-query proc)
336     (set-process-coding-system proc 'no-conversion 'no-conversion)
337     (set-process-sentinel proc 'wnn-comm-sentinel)
338     (set-marker-insertion-type (process-mark proc) t)
339     (save-excursion
340       (set-buffer buf)
341       (erase-buffer)
342       (buffer-disable-undo)
343       (setq enable-multibyte-characters nil))
344     (setq result (wnnrpc-open proc (system-name) (user-login-name)))
345     (if (< result 0)
346         (let ((msg (wnnrpc-get-error-message (- result))))
347           (delete-process proc)
348           (kill-buffer buf)
349           (error "Can't open WNN session (%s %s): %s" hostname language msg))
350       proc)))
351
352 (defvar wnn-dictionary-specification
353   '([2 10 2 45 100 200 5 1 40 0 -100 200 -100  200 80 200 200]
354     "pubdic/full.fzk"
355     ["pubdic/kihon.dic"     ("kihon.h")    5 nil t]
356     ["pubdic/setsuji.dic"   ("setsuji.h")  5 nil t]
357     ["pubdic/koyuu.dic"     ("koyuu.h")    1 nil t]
358     ["pubdic/chimei.dic"    ("chimei.h")   1 nil t]
359     ["pubdic/jinmei.dic"    ("jinmei.h")   1 nil t]
360     ["pubdic/special.dic"   ("special.h")  5 nil t]
361     ["pubdic/computer.dic"  ("computer.h") 5 nil t]
362     ["pubdic/symbol.dic"    ("symbol.h")   1 nil t]
363     ["pubdic/tankan.dic"    ("tankan.h")   1 nil t]
364     ["pubdic/bio.dic"       ("bio.h")      1 nil t]
365     ["gerodic/g-jinmei.dic" ("g-jinmei.h") 1 nil t]
366     ["wnncons/tankan2.dic"  ("tankan2.h")  1 nil t]
367     ["wnncons/tankan3.dic"  ("tankan3.h")  1 nil t]
368     [("ud")                 nil            5 t t])
369   "")
370
371 (defvar wnn-usr-dic-dir (concat "usr/" (user-login-name))
372   "*Directory of user dictionary for Wnn.")
373
374 (defun wnn-filename (p)
375   ""
376   (cond ((consp p) (concat wnn-usr-dic-dir "/" (car p)))
377         (t p)))
378
379 (defun wnn-open-file (proc env-id filename)
380   "Open the file FILENAME on the environment ENV-ID on server process PROC.
381 Return file descripter.  NIL means NO-file.
382 On failure, return negate-encoded error code."
383   (if filename
384       (wnnrpc-open-file proc env-id filename)
385     nil))
386
387 (defun wnn-create-directory (proc env-id path)
388   "Create directory to the path."
389   (let ((dir (directory-file-name path))
390         create-list)
391     (while (and dir (/= (wnnrpc-access proc env-id 0 dir) 0))
392       (setq create-list (cons dir create-list)
393             dir (file-name-directory dir))
394       (if dir
395           (setq dir (directory-file-name dir))))
396     (if (null create-list)
397         t                               ; Already exist.
398       ;; Only query once.
399       (if (y-or-n-p (format "\e$B%G%#%l%/%H%j\e(B(%s)\e$B$,M-$j$^$;$s!#:n$j$^$9$+\e(B? " path))
400           (catch 'return
401             (while create-list
402               (let* ((dir (car create-list))
403                      (ret (wnnrpc-mkdir proc env-id dir)))
404                 (if (< ret 0)
405                     (progn
406                       (message "\e$B%G%#%l%/%H%j\e(B(%s)\e$B$N:n@.$K<:GT$7$^$7$?\e(B" dir)
407                       (throw 'return nil))))
408               (setq create-list (cdr create-list)))
409             ;; Success
410             (message "\e$B%G%#%l%/%H%j\e(B(%s)\e$B$r:n$j$^$7$?\e(B" path)
411             t)
412         ;; Failure
413         nil))))
414
415 (defun wnn-open-dictionary (proc env-id dicname mode)
416   (let ((dictionary (wnn-open-file proc env-id dicname)))
417     (if (null dictionary)
418         (throw 'wnn-set-dictionary-tag nil)
419       (while (< dictionary 0)
420         (let ((err-code (- dictionary)))
421           (if (or (null mode) (/= err-code (WNN-const NO_EXIST)))
422               (let ((msg (wnnrpc-get-error-message err-code)))
423                 (message "\e$B<-=q%U%!%$%k\e(B(%s)\e$B$,$"$j$^$;$s\e(B: %s" dicname msg)
424                 (throw 'wnn-set-dictionary-tag nil)) ; Failure
425             ;; Try to create new one
426             (if (and (y-or-n-p
427                       (format "\e$B<-=q%U%!%$%k\e(B(%s)\e$B$,$"$j$^$;$s!#:n$j$^$9$+\e(B? "
428                               dicname))
429                      (wnn-create-directory proc env-id
430                                            (file-name-directory dicname))
431                      (= (wnnrpc-create-dictionary proc env-id dicname) 0))
432                 (progn
433                   (message "\e$B<-=q%U%!%$%k\e(B(%s)\e$B$r:n$j$^$7$?\e(B" dicname)
434                   (setq dictionary
435                         (wnnrpc-open-file proc env-id dicname)))
436               (throw 'wnn-set-dictionary-tag nil)))))
437       dictionary)))
438
439 (defun wnn-open-frequency (proc env-id freqname mode dic)
440   (let ((frequency (wnn-open-file proc env-id freqname)))
441     (if (null frequency)
442         (setq frequency -1)
443       (while (< frequency 0)
444         (let ((err-code (- frequency)))
445           (if (or (null mode) (/= err-code (WNN-const NO_EXIST)))
446               (let ((msg (wnnrpc-get-error-message err-code)))
447                 (message "\e$BIQEY%U%!%$%k\e(B(%s)\e$B$,$"$j$^$;$s\e(B: %s" freqname msg)
448                 (throw 'wnn-set-dictionary-tag nil)) ; Failure
449             ;; Try to create new one
450             (if (and (y-or-n-p
451                       (format "\e$BIQEY%U%!%$%k\e(B(%s)\e$B$,$"$j$^$;$s!#:n$j$^$9$+\e(B? "
452                               freqname))
453                      (wnn-create-directory proc env-id
454                                            (file-name-directory freqname))
455                      (= (wnnrpc-create-frequency proc env-id freqname dic) 0))
456                 (progn
457                   (message "\e$BIQEY%U%!%$%k\e(B(%s)\e$B$r:n$j$^$7$?\e(B" freqname)
458                   (setq frequency
459                         (wnnrpc-open-file proc env-id freqname)))
460               (throw 'wnn-set-dictionary-tag nil))))))
461       frequency))
462
463 ;; Using local file (uploading/downloading) is not supported yet.
464 ;; Password is not supported (Password is questionable feature, anyway)
465 (defun wnn-set-dictionary (proc env-id reverse-flag dic-spec)
466   ""
467   (catch 'wnn-set-dictionary-tag
468     (let ((dicname (wnn-filename (aref dic-spec 0)))
469           (freqname (wnn-filename (aref dic-spec 1)))
470           (priority  (aref dic-spec 2))
471           (dic-mode  (aref dic-spec 3))
472           (freq-mode (aref dic-spec 4))
473           dictionary frequency)
474       (setq dictionary (wnn-open-dictionary proc env-id dicname dic-mode))
475       (setq frequency
476             (wnn-open-frequency proc env-id freqname freq-mode dictionary))
477       (wnn-set-dictionary-sub proc env-id reverse-flag
478                               dictionary frequency priority dic-mode
479                               freq-mode dicname freqname))))
480
481 (defun wnn-set-dictionary-sub (proc env-id reverse-flag
482                                dictionary frequency priority dic-mode
483                                freq-mode dicname freqname)
484   (let ((trying t))
485     (while trying
486       (let ((ret (wnnrpc-set-dictionary proc env-id reverse-flag
487                                         dictionary frequency
488                                         priority dic-mode freq-mode)))
489         (if (< ret 0)
490             (let ((err-code (- ret)))
491               (if (or (null freq-mode) (/= err-code (WNN-const NO_MATCH)))
492                   (let ((msg (wnnrpc-get-error-message (- ret))))
493                     (message "WNN: Error on setting dictionary (%s, %s): %s"
494                              dicname freqname msg)
495                     (setq trying nil))  ; done
496                 ;; No-match: Create new frequency and try it again
497                 (wnnrpc-discard-file proc env-id frequency) ; XXX: error?
498                 (setq frequency
499                       (wnn-query-del/create-frequency proc env-id freqname
500                                                       dictionary))))
501           ;; done sucessfully
502           (setq trying nil))))))
503
504 (defun wnn-query-del/create-frequency (proc env-id freqname dictionary)
505   (if (y-or-n-p
506        (format "\e$B<-=q$HIQEY\e(B(%s)\e$B$N@09g@-$,$"$j$^$;$s!#:n$jD>$7$^$9$+\e(B? "
507                freqname))
508       (progn
509         (wnnrpc-remove-file proc freqname) ; XXX: error?
510         (wnnrpc-create-frequency proc env-id freqname dictionary) ; XXX: error?
511         (message "\e$BIQEY%U%!%$%k\e(B(%s)\e$B$r:n$j$^$7$?\e(B" freqname)
512         (wnnrpc-open-file proc env-id freqname)) ; XXX: error?
513     -1))
514
515 (defun wnn-get-environment (dic-spec)
516   "Return WNN Environemt.  If none, create new environment.
517 Take one argument DIC-SPEC for dictionary specification."
518   (if wnn-environment
519       wnn-environment
520     (let ((username (user-login-name))
521           (proc (wnn-open wnn-server "ja_JP")))
522       (setq wnn-environment
523             (wnn-create-environment proc username nil dic-spec)))))
524
525 (defun wnn-create-environment (proc username reverse-flag spec)
526   ""
527   ;; Create new data structure: something like wnn_buf
528   ;; Process, Environment-ID and Daibunsetsu-info.
529   (let (env env-id parameters)
530     (setq env-id (wnnrpc-connect proc username))
531     (if (< env-id 0)
532         (let ((msg (wnnrpc-get-error-message (- env-id))))
533           (error "Can't connect new WNN environment: %s" msg)))
534     (setq parameters (car spec))
535     (setq spec (cdr spec))
536     (let ((filename (wnn-filename (car spec)))
537           fuzokugo-fid ret)
538       (setq fuzokugo-fid (wnn-open-file proc env-id filename))
539       (if (null fuzokugo-fid)
540           (setq fuzokugo-fid -1)
541         (if (< fuzokugo-fid 0)
542             (let ((msg (wnnrpc-get-error-message (- fuzokugo-fid))))
543               (message "WNN: Can't open fuzokugo file (%s): %s" filename msg)
544               (setq fuzokugo-fid -1))))
545       (setq ret (wnnrpc-set-fuzokugo-file proc env-id fuzokugo-fid))
546       (if (< ret 0)
547           (let ((msg (wnnrpc-get-error-message (- ret))))
548             (message "WNN: Error on setting fuzokugo (%s): %s" filename msg))))
549     (setq spec (cdr spec))
550     (while spec
551       (let ((dic-spec (car spec)))
552         (wnn-set-dictionary proc env-id reverse-flag dic-spec)
553         (setq spec (cdr spec))))
554     (wnnrpc-set-conversion-parameters proc env-id parameters)
555     (setq env (wnnenv-create proc env-id))
556     env))
557
558 (defun wnn-update-frequency (env bunsetsu-info-list)
559   (let ((l bunsetsu-info-list))
560     (while l
561       (let* ((b (car l))
562              (fd (wnn-bunsetsu-get-freq-down b))
563              (z (wnn-bunsetsu-get-zenkouho b)))
564         (while fd
565           (let* ((fdb (car fd))
566                  (dic-no (wnn-bunsetsu-get-dic-no fdb))
567                  (entry (wnn-bunsetsu-get-entry fdb)))
568             (wnnrpc-set-frequency env dic-no entry
569                                   (WNN-const IMA_OFF) (WNN-const HINDO_NOP))
570             (setq fd (cdr fd))))
571         (while z
572           (let* ((zb (car z))
573                  (right-now (wnn-bunsetsu-get-right-now zb))
574                  (dic-no (wnn-bunsetsu-get-dic-no zb))
575                  (entry (wnn-bunsetsu-get-entry zb)))
576             (if (and (/= right-now 0) (/= dic-no -1))
577                 (wnnrpc-set-frequency env dic-no entry (WNN-const IMA_OFF)
578                                       (WNN-const HINDO_NOP)))
579             (setq z (cdr z))))
580         (let ((dic-no (wnn-bunsetsu-get-dic-no b))
581               (entry (wnn-bunsetsu-get-entry b)))
582           (if (/= dic-no -1)
583               (wnnrpc-set-frequency env dic-no entry 
584                                     (WNN-const IMA_ON)
585                                     (WNN-const HINDO_INC))))
586         (setq l (cdr l))))))
587 \f
588 ;;; XXX Need alternative implementation
589 ;(defun wnn-set-conversion-mode ()
590 ;  (jl-set-environment))
591
592 (defun wnn-save-dictionaries ()
593   (for-each-environment
594    js-dic-list
595    (while (< i count)
596      dic => id
597      js-file-write
598      hindo => id
599      js-file-write)))
600
601 (defun wnn-version (proc)
602   "Return version number string of WNN server."
603   (format "%x" (wnnrpc-version proc)))
604
605 (defun wnn-dai-bunsetsu-p ()
606   (jl-dai-top ))
607
608 (defun wnn-next-dai-bunsetsu-pos ()
609   XXX)
610 \f
611 ;;; not implemented yet (NIY)
612 (defun wnn-delete-dictionary ()
613   (dj-delete-dic XXX))
614
615 ;;; NIY, might never be implemented
616 (defun wnn-server-inspect ())
617
618 ;;; NIY
619 (defun wnn-list-dictionaries ()
620   (jl-dic-list))
621
622 ;;; NIY
623 (defun wnn-get-conversion-parameters ()
624   (js-get-parameters))
625
626 ;;; Dictionary management (word registration) is not implemented yet.
627
628 ;; XXX: local file loaded into the server: Not supported yet
629 ;(defun wnn-list-dictionaries (env)
630 ;  (wnnrpc-get-dictionary-list-with-environment env))
631
632 (defun wnn-find-dictionary-by-id (id dic-list)
633   (catch 'return
634     (while dic-list
635       (let ((dic (car dic-list)))
636         (if (= (wnndic-get-id dic) id)
637             (throw 'return dic)
638           (setq dic-list (cdr dic-list)))))))
639
640 (defun wnn-dict-name (dic)
641   (let ((name (wnndic-get-comment dic)))
642     (if (string= name "")
643         (file-name-nondirectory (wnndic-get-dictname dic))
644       name)))
645
646 (defun wnn-list-writable-dictionaries-byname (env)
647   (let ((dic-list (wnnrpc-get-dictionary-list-with-environment env))
648         (w-id-list (wnnrpc-get-writable-dictionary-id-list env)))
649     (mapcar (function (lambda (id)
650                         (let ((dic (wnn-find-dictionary-by-id id dic-list)))
651                           (cons (wnn-dict-name dic) dic))))
652             w-id-list)))
653
654 (defun wnn-hinshi-list (env dic name)
655   (let ((dic-number (wnndic-get-id dic)))
656     (wnnrpc-get-hinshi-list env dic-number name)))
657
658 (defun wnn-hinshi-number (env hinshi-name)
659   (wnnrpc-hinshi-number (wnnenv-get-proc env) hinshi-name))
660
661 (defun wnn-add-word (env dic yomi kanji comment hinshi-id initial-freq)
662   (let ((dic-number (wnndic-get-id dic)))
663     (wnnrpc-add-word env dic-number yomi kanji comment
664                      hinshi-id initial-freq)))
665
666 ;;; egg/wnn.el ends here.