980314 version
[elisp/egg.git] / egg / sj3.el
1 ;;; egg/sj3.el --- SJ3 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 ;; EGG 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 ;; EGG 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 (defconst sj3-support-languages '("Japanese"))
33
34 (defconst sj3-conversion-backend
35   [ sj3-init
36
37     sj3-start-conversion
38       sj3-get-bunsetsu-converted
39       sj3-get-bunsetsu-source
40       sj3-list-candidates
41           sj3-get-number-of-candidates
42           sj3-get-current-candidate-number
43           sj3-get-all-candidates
44           sj3-decide-candidate
45       sj3-change-bunsetsu-length
46     sj3-end-conversion
47     nil
48
49     sj3-fini
50  ])
51
52 (defvar sj3-server-port 3000 "Port number of SJ3 server")
53 (defvar sj3-stdy-size 0 "STDYSIZE of SJ3 server")
54 (defvar sj3-hostname "localhost"
55   "Hostname of SJ3 server")
56
57 (defvar sj3-open-message)
58
59 (defun sj3-open (hostname-list)
60   "Establish the connection to SJ3 server.  Return process object."
61   (let* ((buf (generate-new-buffer " *SJ3*"))
62          (msg-form "SJ3: connecting to sj3serv at %s...")
63          hostname proc result msg)
64     (save-excursion
65       (set-buffer buf)
66       (erase-buffer)
67       (buffer-disable-undo)
68       (setq enable-multibyte-characters nil))
69     (cond
70      ((null hostname-list)
71       (setq hostname-list '("localhost")))
72      ((null (listp hostname-list))
73       (setq hostname-list (list hostname-list))))
74     (while (and hostname-list (null proc))
75       (setq hostname (car hostname-list)
76             hostname-list (cdr hostname-list))
77       (message msg-form hostname)
78       (sit-for 0)
79       (condition-case result
80           (setq proc (open-network-stream "SJ3" buf hostname sj3-server-port))
81         (error nil))
82       (if proc
83           (progn
84             (process-kill-without-query proc)
85             (set-process-coding-system proc 'no-conversion 'no-conversion)
86             (set-marker-insertion-type (process-mark proc) t)
87             ;; Initialize dictionaries
88             (setq sj3-sys-dict-list nil)
89             (setq sj3-user-dict-list nil)
90             (setq result (sj3rpc-open proc (system-name) (user-login-name)))
91             (if (< result 0)
92                 (progn
93                   (delete-process proc)
94                   (setq proc nil
95                         msg (format "Can't open SJ3 session (%s): %s"
96                                     hostname msg)))
97               (setq result (sj3rpc-get-stdy-size proc))
98               (if (< result 0)
99                   (progn
100                     (delete-process proc)
101                     (setq proc nil
102                           msg (format "Can't get SJ3 STDYSIZE: %s"
103                                       (sj3rpc-get-error-message (- result)))))
104                 (setq sj3-stdy-size result))))))
105     (if proc
106         (progn
107           (setq sj3-open-message (format (concat msg-form "done") hostname))
108           proc)
109       (kill-buffer buf)
110       (error "%s" (or msg "no sj3serv available")))))
111
112 ;; <env> ::= [ <proc> <dictionary-list> ]
113 (defvar sj3-environment nil
114   "Environment for SJ3 kana-kanji conversion")
115
116 (defsubst sj3env-get-proc (env)
117   (aref env 0))
118 (defsubst sj3env-get-dictionary-list (env)
119   (aref env 1))
120
121 ;; <bunsetsu> ::=
122 ;;  [ <env> <source> <converted> <rest>
123 ;;    <stdy> <zenkouho> <zenkouho-pos> <stdy-down> ]
124 (defsubst sj3-make-bunsetsu (env source converted rest stdy)
125   (vector env source converted rest stdy nil nil nil))
126
127 (defsubst sj3bunsetsu-get-env (b)
128   (aref b 0))
129 (defsubst sj3bunsetsu-get-source (b)
130   (aref b 1))
131 (defsubst sj3bunsetsu-get-converted (b)
132   (aref b 2))
133 (defsubst sj3bunsetsu-get-rest (b)
134   (aref b 3))
135 (defsubst sj3bunsetsu-get-stdy (b)
136   (aref b 4))
137 (defsubst sj3bunsetsu-get-zenkouho (b)
138   (aref b 5))
139 (defsubst sj3bunsetsu-set-zenkouho (b z)
140   (aset b 5 z))
141 (defsubst sj3bunsetsu-get-zenkouho-pos (b)
142   (aref b 6))
143 (defsubst sj3bunsetsu-set-zenkouho-pos (b p)
144   (aset b 6 p))
145 (defsubst sj3bunsetsu-get-stdydown (b)
146   (aref b 7))
147 (defsubst sj3bunsetsu-set-stdydown (b s)
148   (aset b 7 s))
149
150 (defun sj3-get-bunsetsu-source (b)
151   (sj3bunsetsu-get-source b))
152 (defun sj3-get-bunsetsu-converted (b)
153   (concat (sj3bunsetsu-get-converted b)
154           (sj3bunsetsu-get-rest b)))
155 (defun sj3-get-bunsetsu-stdy (b)
156   (sj3bunsetsu-get-stdy b))
157
158 (defvar sj3-dictionary-specification
159   '(("study.dat")
160     ["sj3main.dic" ""]
161     [("private.dic") ""])
162   "Dictionary specification of SJ3.")
163
164 (defvar sj3-usr-dic-dir (concat "user/" (user-login-name))
165   "*Directory of user dictionary for SJ3.")
166
167 (defun sj3-filename (p)
168   ""
169   (cond ((consp p) (concat sj3-usr-dic-dir "/" (car p)))
170         (t p)))
171
172 (defun sj3-get-environment ()
173   (if sj3-environment
174       sj3-environment
175     (let* ((proc (sj3-open sj3-hostname))
176            (stdy (sj3-filename (car sj3-dictionary-specification)))
177            (l (cdr sj3-dictionary-specification))
178            dict-list)
179       (if (/= (sj3rpc-open-stdy proc stdy) 0)
180           (error "Dame1")               ; XXX
181         (while l
182           (let ((dic (car l))
183                 dic-id)
184             (setq dic-id
185                   (sj3rpc-open-dictionary proc (sj3-filename (aref dic 0))
186                                           (aref dic 1)))
187             (if (< dic-id 0)
188                 (error "Dame2")         ; XXX
189               (setq dict-list (cons dic-id dict-list)
190                     l (cdr l)))))
191         (message "%s" sj3-open-message)
192         (setq sj3-environment (vector proc dict-list))))))
193
194 (defun sj3-init ()
195   )
196
197 (defun sj3-start-conversion (yomi &optional lang)
198   "Convert YOMI string to kanji, and enter conversion mode.
199 Return the list of bunsetsu."
200   (let ((env (sj3-get-environment)))
201     (sj3rpc-begin env yomi)))
202
203 ;; XXX: not implemented yet
204 (defun sj3-end-conversion (bunsetsu-list)
205   )
206
207 (defun sj3-list-candidates (bunsetsu prev-bunsetsu)
208   (let* ((env (sj3bunsetsu-get-env bunsetsu))
209          (yomi (sj3bunsetsu-get-source bunsetsu))
210          (z (sj3rpc-get-bunsetsu-candidates env yomi)))
211     (sj3bunsetsu-set-zenkouho bunsetsu z)
212     (sj3bunsetsu-set-zenkouho-pos bunsetsu 0)
213     0))
214
215 (defun sj3-get-number-of-candidates (bunsetsu)
216   (let ((l (sj3bunsetsu-get-zenkouho bunsetsu)))
217     (if l
218         (length l)
219       nil)))
220
221 (defun sj3-decide-candidate (bunsetsu candidate-pos)
222   (let* ((candidate-list (sj3bunsetsu-get-zenkouho bunsetsu))
223          (candidate (nth candidate-pos candidate-list)))
224     (sj3bunsetsu-set-zenkouho candidate candidate-list)
225     (sj3bunsetsu-set-zenkouho-pos candidate candidate-pos)
226     candidate))
227
228 (defun sj3-get-current-candidate-number (bunsetsu)
229   (sj3bunsetsu-get-zenkouho-pos bunsetsu))
230
231 (defun sj3-get-all-candidates (bunsetsu)
232   (let* ((l (sj3bunsetsu-get-zenkouho bunsetsu))
233          (result (cons nil nil))
234          (r result))
235     (catch 'break
236       (while t
237         (let ((candidate (car l)))
238           (setcar r (sj3bunsetsu-get-converted candidate))
239           (if (null (setq l (cdr l)))
240               (throw 'break nil)
241             (setq r (setcdr r (cons nil nil)))))))
242     result))
243
244 (defun sj3-change-bunsetsu-length (b0 b1 b2 len)
245   (let ((yomi (concat
246                (sj3bunsetsu-get-source b1)
247                (if b2 (sj3bunsetsu-get-source b2))))
248         (env (sj3bunsetsu-get-env b1))
249         yomi1 yomi2
250         bunsetsu1 bunsetsu2)
251     (setq yomi1 (substring yomi 0 len)
252           yomi2 (substring yomi len))
253     (setq bunsetsu1
254           (sj3rpc-tanbunsetsu-conversion env yomi1))
255     ;; Only set once.
256     (sj3bunsetsu-set-stdydown bunsetsu1
257                               (or (sj3bunsetsu-get-stdydown b1)
258                                   (if b2
259                                       (list b1 b2)
260                                     (list b1))))
261     (if (< 0 (length yomi2))
262         (setq bunsetsu2 (sj3rpc-tanbunsetsu-conversion env yomi2))
263       (setq bunsetsu2 nil))
264     (if bunsetsu2
265         (list bunsetsu1 bunsetsu2)
266       (list bunsetsu1))))
267
268 ;; XXX: Not implemented yet
269 (defun sj3-fini (lang)
270   )
271
272 ;;; setup
273
274 (require 'egg)
275 (load "egg/sj3rpc")
276
277 ;;;###autoload
278 (defun egg-activate-sj3 (&rest arg)
279   "Activate SJ3 backend of Tamagotchy."
280   (egg-set-support-languages sj3-support-languages)
281   (egg-set-conversion-backend sj3-conversion-backend 
282                               sj3-support-languages)
283   (apply 'egg-mode arg))
284
285 ;;; egg/sj3.el ends here.