;;; dictionary-connection.el --- TCP-based client connection for dictionary ;; Author: Torsten Hilbrich ;; Keywords: network ;; Version: 1.11 ;; This file 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. ;; This file 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. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; dictionary-connection allows to handle TCP-based connections in ;; client mode where text-based information are exchanged. There is ;; special support for handling CR LF (and the usual CR LF . CR LF ;; terminater). ;;; Code: (defmacro dictionary-connection-p (connection) "Returns non-nil if `connection' is a connection object" (list 'get connection ''connection)) (defmacro dictionary-connection-read-point (connection) "Return the read point of the connection object." (list 'get connection ''dictionary-connection-read-point)) (defmacro dictionary-connection-process (connection) "Return the process of the connection object." (list 'get connection ''dictionary-connection-process)) (defmacro dictionary-connection-buffer (connection) "Return the buffer of the connection object." (list 'get connection ''dictionary-connection-buffer)) (defmacro dictionary-connection-set-read-point (connection point) "Set the read-point for `connection' to `point'." (list 'put connection ''dictionary-connection-read-point point)) (defmacro dictionary-connection-set-process (connection process) "Set the process for `connection' to `process'." (list 'put connection ''dictionary-connection-process process)) (defmacro dictionary-connection-set-buffer (connection buffer) "Set the buffer for `connection' to `buffer'." (list 'put connection ''dictionary-connection-buffer buffer)) (defun dictionary-connection-create-data (buffer process point) "Create a new connection data based on `buffer', `process', and `point'." (let ((connection (make-symbol "connection"))) (put connection 'connection t) (dictionary-connection-set-read-point connection point) (dictionary-connection-set-process connection process) (dictionary-connection-set-buffer connection buffer) connection)) (defun dictionary-connection-open (server port) "Open a connection to `server' and `port'. A data structure identifing the connection is returned" (let ((process-buffer (generate-new-buffer (format " connection to %s:%s" server port))) (process)) (with-current-buffer process-buffer (setq process (open-network-stream "connection" process-buffer server port)) (dictionary-connection-create-data process-buffer process (point-min))))) (defun dictionary-connection-status (connection) "Return the status of the connection. Possible return values are the symbols: nil: argument is no connection object 'none: argument has no connection 'up: connection is open and buffer is existing 'down: connection is closed 'alone: connection is not associated with a buffer" (if (dictionary-connection-p connection) (let ((process (dictionary-connection-process connection)) (buffer (dictionary-connection-buffer connection))) (if (not process) 'none (if (not (buffer-live-p buffer)) 'alone (if (not (eq (process-status process) 'open)) 'down 'up)))) nil)) (defun dictionary-connection-close (connection) "Force closing of the connection." (if (dictionary-connection-p connection) (progn (let ((buffer (dictionary-connection-buffer connection)) (process (dictionary-connection-process connection))) (if process (delete-process process)) (if buffer (kill-buffer buffer)) (dictionary-connection-set-process connection nil) (dictionary-connection-set-buffer connection nil))))) (defun dictionary-connection-send (connection data) "Send `data' to the process." (unless (eq (dictionary-connection-status connection) 'up) (error "Connection is not up")) (with-current-buffer (dictionary-connection-buffer connection) (goto-char (point-max)) (dictionary-connection-set-read-point connection (point)) (process-send-string (dictionary-connection-process connection) data))) (defun dictionary-connection-send-crlf (connection data) "Send `data' together with CRLF to the process." (dictionary-connection-send connection (concat data "\r\n"))) (defun dictionary-connection-read (connection delimiter) "Read data until `delimiter' is found inside the buffer." (unless (eq (dictionary-connection-status connection) 'up) (error "Connection is not up")) (let ((case-fold-search nil) match-end) (with-current-buffer (dictionary-connection-buffer connection) (goto-char (dictionary-connection-read-point connection)) ;; Wait until there is enough data (while (not (search-forward-regexp delimiter nil t)) (accept-process-output (dictionary-connection-process connection) 3) (goto-char (dictionary-connection-read-point connection))) (setq match-end (point)) ;; Return the result (let ((result (buffer-substring (dictionary-connection-read-point connection) match-end))) (dictionary-connection-set-read-point connection match-end) result)))) (defun dictionary-connection-read-crlf (connection) "Read until a line is completedx with CRLF" (dictionary-connection-read connection "\015?\012")) (defun dictionary-connection-read-to-point (connection) "Read until a line is consisting of a single point" (dictionary-connection-read connection "\015?\012[.]\015?\012")) (provide 'dictionary-connection) ;;; dictionary-connection.el ends here