Merge egg-980316.
[elisp/egg.git] / egg / sj3.el
index b332f08..b011f05 100644 (file)
@@ -1,21 +1,21 @@
 ;;; egg/sj3.el --- SJ3 Support (high level interface) in Egg
 ;;;                Input Method Architecture
 
-;; Copyright (C) 1997 Mule Project, Powered by Electrotechnical
-;; Laboratory, JAPAN.
+;; Copyright (C) 1997, 1998 Mule Project,
+;; Powered by Electrotechnical Laboratory, JAPAN.
 ;; Project Leader: Satoru Tomura <tomura@etl.go.jp>
 
 ;; Author: NIIBE Yutaka <gniibe@mri.co.jp>
 ;; Maintainer: NIIBE Yutaka <gniibe@mri.co.jp>
 
-;; This file will be part of GNU Emacs (in future).
+;; This file is part of EGG.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; EGG is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation; either version 2, or (at your option)
 ;; any later version.
 
-;; GNU Emacs is distributed in the hope that it will be useful,
+;; EGG is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
 
 ;;; Code:
 
+(defconst sj3-support-languages '("Japanese"))
+
+(eval-when-compile
+  (defmacro SJ3-const (c)
+    (cond ((eq c 'FileNotExist) 35)
+         )))
+
 (defconst sj3-conversion-backend
   [ sj3-init
 
           sj3-decide-candidate
       sj3-change-bunsetsu-length
     sj3-end-conversion
+    nil
 
     sj3-fini
  ])
 
-(defconst sj3-server-port 3000 "Port number of SJ3 server")
+(defvar sj3-server-port 3000 "Port number of SJ3 server")
 (defvar sj3-stdy-size 0 "STDYSIZE of SJ3 server")
 (defvar sj3-hostname "localhost"
   "Hostname of SJ3 server")
 
+(defvar sj3-open-message)
+
 (defun sj3-open (hostname)
   "Establish the connection to SJ3 server.  Return process object."
   (let* ((buf (generate-new-buffer " *SJ3*"))
     (setq sj3-stdy-size result)
     proc))
 
+;; (defun sj3-open (hostname-list)
+;;   "Establish the connection to SJ3 server.  Return process object."
+;;   (let* ((buf (generate-new-buffer " *SJ3*"))
+;;      (msg-form "SJ3: connecting to sj3serv at %s...")
+;;      hostname proc result msg)
+;;     (save-excursion
+;;       (set-buffer buf)
+;;       (erase-buffer)
+;;       (buffer-disable-undo)
+;;       (setq enable-multibyte-characters nil))
+;;     (cond
+;;      ((null hostname-list)
+;;       (setq hostname-list '("localhost")))
+;;      ((null (listp hostname-list))
+;;       (setq hostname-list (list hostname-list))))
+;;     (while (and hostname-list (null proc))
+;;       (setq hostname (car hostname-list)
+;;         hostname-list (cdr hostname-list))
+;;       (message msg-form hostname)
+;;       (sit-for 0)
+;;       (condition-case result
+;;       (setq proc (open-network-stream "SJ3" buf hostname sj3-server-port))
+;;     (error nil))
+;;       (if proc
+;;       (progn
+;;         (process-kill-without-query proc)
+;;         (set-process-coding-system proc 'no-conversion 'no-conversion)
+;;         (set-marker-insertion-type (process-mark proc) t)
+;;         ;; Initialize dictionaries
+;;         (setq sj3-sys-dict-list nil)
+;;         (setq sj3-user-dict-list nil)
+;;         (setq result (sj3rpc-open proc (system-name) (user-login-name)))
+;;         (if (< result 0)
+;;             (progn
+;;               (delete-process proc)
+;;               (setq proc nil
+;;                     msg (format "Can't open SJ3 session (%s): %s"
+;;                                 hostname msg)))
+;;           (setq result (sj3rpc-get-stdy-size proc))
+;;           (if (< result 0)
+;;               (progn
+;;                 (delete-process proc)
+;;                 (setq proc nil
+;;                       msg (format "Can't get SJ3 STDYSIZE: %s"
+;;                                   (sj3rpc-get-error-message (- result)))))
+;;             (setq sj3-stdy-size result))))))
+;;     (if proc
+;;     (progn
+;;       (setq sj3-open-message (format (concat msg-form "done") hostname))
+;;       proc)
+;;       (kill-buffer buf)
+;;       (error "%s" (or msg "no sj3serv available")))))
+
 ;; <env> ::= [ <proc> <dictionary-list> ]
 (defvar sj3-environment nil
   "Environment for SJ3 kana-kanji conversion")
 
 ;; <bunsetsu> ::=
 ;;  [ <env> <source> <converted> <rest>
-;;    <stdy> <zenkouho> <zenkouho-pos> <stdy-down> ]
+;;    <stdy> <zenkouho> <zenkouho-pos> <kugiri-changed> ]
 (defsubst sj3-make-bunsetsu (env source converted rest stdy)
   (vector env source converted rest stdy nil nil nil))
 
   (aref b 6))
 (defsubst sj3bunsetsu-set-zenkouho-pos (b p)
   (aset b 6 p))
-(defsubst sj3bunsetsu-get-stdydown (b)
+(defsubst sj3bunsetsu-get-kugiri-changed (b)
   (aref b 7))
-(defsubst sj3bunsetsu-set-stdydown (b s)
+(defsubst sj3bunsetsu-set-kugiri-changed (b s)
   (aset b 7 s))
 
 (defun sj3-get-bunsetsu-source (b)
        (t p)))
 
 (defun sj3-get-environment ()
+  "Return the backend of SJ3 environment."
   (if sj3-environment
       sj3-environment
     (let* ((proc (sj3-open sj3-hostname))
-          (stdy (sj3-filename (car sj3-dictionary-specification)))
+          (freq-info-name (sj3-filename (car sj3-dictionary-specification)))
           (l (cdr sj3-dictionary-specification))
           dict-list)
-      (if (/= (sj3rpc-open-stdy proc stdy) 0)
-         (error "Dame1")               ; XXX
-       (while l
-         (let ((dic (car l))
-               dic-id)
-           (setq dic-id
-                 (sj3rpc-open-dictionary proc (sj3-filename (aref dic 0))
-                                         (aref dic 1)))
-           (if (< dic-id 0)
-               (error "Dame2")         ; XXX
-             (setq dict-list (cons dic-id dict-list)
-                   l (cdr l))))))
-       (setq sj3-environment (vector proc dict-list)))))
+      (sj3-open-freq-info proc freq-info-name)
+      (while l
+       (let ((dic (car l))
+             dic-id)
+         (setq dic-id
+               (sj3-open-dictionary proc (sj3-filename (aref dic 0))
+                                    (aref dic 1)))
+         (if (< dic-id 0)
+             (error "Dame2")           ; XXX
+           (setq dict-list (cons dic-id dict-list)
+                 l (cdr l)))))
+      (setq sj3-environment (vector proc dict-list)))))
+
+(defun sj3-open-freq-info (proc name)
+  (let ((trying t)
+       ret)
+    (while trying
+      (setq ret (sj3rpc-open-stdy proc name))
+      (if (= ret 0)
+         (setq trying nil)
+       (message "\92\81³Ø\92\81½¬\92\81¥Õ\92\81¥¡\92\81¥¤\92\81¥ë(%s)\92\81¤¬\92\81¤¢\92\81¤ê\92\81¤Þ\92\81¤»\92\81¤ó" name)
+       (if (/= ret (SJ3-const FileNotExist))
+           (error "Fatal1")            ; XXX
+         (if (and (y-or-n-p
+                   (format "\92\81³Ø\92\81½¬\92\81¥Õ\92\81¥¡\92\81¥¤\92\81¥ë(%s)\92\81¤¬\92\81¤¢\92\81¤ê\92\81¤Þ\92\81¤»\92\81¤ó\92\81¡£\92\81ºî\92\81¤ê\92\81¤Þ\92\81¤¹\92\81¤«? "
+                           name))
+                  (sj3rpc-make-directory proc
+                                         (file-name-directory name))
+                  ;; ignore error
+                  (= (sj3rpc-make-stdy proc name) 0))
+             (message "\92\81³Ø\92\81½¬\92\81¥Õ\92\81¥¡\92\81¥¤\92\81¥ë(%s)\92\81¤ò\92\81ºî\92\81¤ê\92\81¤Þ\92\81¤·\92\81¤¿" name)
+           (error "Fatal2")))))))      ; XXX
+
+(defun sj3-open-dictionary (proc name passwd)
+  (let ((trying t)
+       ret)
+    (while trying
+      (setq ret (sj3rpc-open-dictionary proc name passwd))
+      (if (>= ret 0)
+         (setq trying nil)
+       (message "\92\81¼­\92\81½ñ\92\81¥Õ\92\81¥¡\92\81¥¤\92\81¥ë(%s)\92\81¤¬\92\81¤¢\92\81¤ê\92\81¤Þ\92\81¤»\92\81¤ó" name)
+       (setq ret (- ret))              ; Get error code.
+       (if (/= ret (SJ3-const FileNotExist))
+           (error "Fatal3 %d" ret)             ; XXX
+         (if (and (y-or-n-p
+                   (format "\92\81¼­\92\81½ñ\92\81¥Õ\92\81¥¡\92\81¥¤\92\81¥ë(%s)\92\81¤¬\92\81¤¢\92\81¤ê\92\81¤Þ\92\81¤»\92\81¤ó\92\81¡£\92\81ºî\92\81¤ê\92\81¤Þ\92\81¤¹\92\81¤«? "
+                           name))
+                  (= (sj3rpc-make-dictionary proc name) 0))
+             (message "\92\81¼­\92\81½ñ\92\81¥Õ\92\81¥¡\92\81¥¤\92\81¥ë(%s)\92\81¤ò\92\81ºî\92\81¤ê\92\81¤Þ\92\81¤·\92\81¤¿" name)
+           (error "Fatal4")))))        ; XXX
+    ret))
 
 (defun sj3-init ()
   )
 
-(defun sj3-start-conversion (yomi)
+(defun sj3-start-conversion (yomi &optional lang)
   "Convert YOMI string to kanji, and enter conversion mode.
 Return the list of bunsetsu."
   (let ((env (sj3-get-environment)))
     (sj3rpc-begin env yomi)))
 
-;; XXX: not implemented yet
-(defun sj3-end-conversion (bunsetsu-list)
-  )
+(defun sj3-end-conversion (bunsetsu-list abort)
+  (if abort
+      ()
+    (let ((env (sj3bunsetsu-get-env (car bunsetsu-list)))
+         (l bunsetsu-list)
+         bunsetsu stdy kugiri-changed)
+      (while l
+       (setq bunsetsu (car l))
+       (setq l (cdr l))
+       (setq stdy (sj3bunsetsu-get-stdy bunsetsu))
+       (if stdy
+           (sj3rpc-bunsetsu-stdy env stdy))
+       (if (setq kugiri-changed (sj3bunsetsu-get-kugiri-changed bunsetsu))
+           (let ((yomi1 (sj3bunsetsu-get-source bunsetsu))
+                 (yomi2 (sj3bunsetsu-get-source (car l))))
+             (if (/= kugiri-changed (length yomi1))
+                 (sj3rpc-kugiri-stdy env yomi1 yomi2
+                                     (sj3bunsetsu-get-stdy (car l))))))))))
 
 (defun sj3-list-candidates (bunsetsu prev-bunsetsu)
   (let* ((env (sj3bunsetsu-get-env bunsetsu))
@@ -220,18 +337,14 @@ Return the list of bunsetsu."
        (env (sj3bunsetsu-get-env b1))
        yomi1 yomi2
        bunsetsu1 bunsetsu2)
-    (save-match-data
-      (string-match (concat "^\\(" (make-string len ?.) "\\)\\(.*$\\)") yomi)
-      (setq yomi1 (match-string 1 yomi))
-      (setq yomi2 (match-string 2 yomi)))
+    (setq yomi1 (substring yomi 0 len)
+         yomi2 (substring yomi len))
     (setq bunsetsu1
          (sj3rpc-tanbunsetsu-conversion env yomi1))
-    ;; Only set once.
-    (sj3bunsetsu-set-stdydown bunsetsu1
-                             (or (sj3bunsetsu-get-stdydown b1)
-                                 (if b2
-                                     (list b1 b2)
-                                   (list b1))))
+    ;; Only set once (memory original length of the bunsetsu).
+    (sj3bunsetsu-set-kugiri-changed bunsetsu1
+                                   (or (sj3bunsetsu-get-kugiri-changed b1)
+                                       (length (sj3bunsetsu-get-source b1))))
     (if (< 0 (length yomi2))
        (setq bunsetsu2 (sj3rpc-tanbunsetsu-conversion env yomi2))
       (setq bunsetsu2 nil))
@@ -239,9 +352,17 @@ Return the list of bunsetsu."
        (list bunsetsu1 bunsetsu2)
       (list bunsetsu1))))
 
-;; XXX: Not implemented yet
-(defun sj3-fini ()
-  )
+(defun sj3-fini (lang)
+  (let ((proc (sj3env-get-proc sj3-environment))
+       (dict-list (sj3env-get-dictionary-list sj3-environment))
+       dict)
+    (while dict-list
+      (setq dict (car dict-list))
+      (setq dict-list (cdr dict-list))
+      (sj3rpc-close-dictionary proc dict)) ; XXX: check error
+    (sj3rpc-close-stdy proc)
+    (sj3rpc-close proc))
+  (setq sj3-environment nil))
 
 ;;; setup
 
@@ -249,12 +370,11 @@ Return the list of bunsetsu."
 (load "egg/sj3rpc")
 
 ;;;###autoload
-(defun egg-activate-sj3 (&optional arg)
+(defun egg-activate-sj3 (&rest arg)
   "Activate SJ3 backend of Tamagotchy."
-  (setq egg-conversion-backend sj3-conversion-backend)
-  (egg-mode arg)
-  )
-
-(provide 'egg/sj3)
+  (egg-set-support-languages sj3-support-languages)
+  (egg-set-conversion-backend sj3-conversion-backend 
+                             sj3-support-languages)
+  (apply 'egg-mode arg))
 
 ;;; egg/sj3.el ends here.