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