diff lisp/tooltalk/tooltalk-init.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/tooltalk/tooltalk-init.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,215 @@
+;;; -*- Mode: Emacs-Lisp -*-
+;;;
+;;; Registration of the default Tooltalk patterns and handlers.
+;;;
+;;; @(#)tooltalk-init.el 1.8 94/02/22
+
+
+(defvar tooltalk-eval-pattern
+  '(category TT_HANDLE
+       scope TT_SESSION
+          op "emacs-eval"
+    callback tooltalk-eval-handler))
+
+(defvar tooltalk-load-file-pattern
+  '(category TT_HANDLE
+       scope TT_SESSION
+          op "emacs-load-file"
+	args ((TT_IN "file" "string"))
+    callback tooltalk-load-file-handler))
+
+(defvar tooltalk-make-client-frame-pattern 
+  '(category TT_HANDLE
+       scope TT_SESSION
+          op "emacs-make-client-screen"
+    callback tooltalk-make-client-frame-handler))
+
+(defvar tooltalk-status-pattern 
+  '(category TT_HANDLE
+       scope TT_SESSION
+          op "emacs-status"
+    callback tooltalk-status-handler))
+
+
+(defvar initial-tooltalk-patterns ())
+
+(defun dispatch-initial-tooltalk-message (m)
+  (let ((op (get-tooltalk-message-attribute m 'op))
+	(patterns initial-tooltalk-patterns))
+    (if (stringp op)
+        (while patterns
+          (let ((p (car patterns)))
+            (if (eq (intern op) (tooltalk-pattern-prop-get p 'opsym))
+                (let ((callback (tooltalk-pattern-prop-get p 'callback)))
+                  (if callback (funcall callback m p))
+                  (setq patterns '()))
+              (setq patterns (cdr patterns))))))))
+
+(defun make-initial-tooltalk-pattern (args)
+  (let ((opcdr (cdr (memq 'op args)))
+	(cbcdr (cdr (memq 'callback args))))
+    (if (and (consp opcdr) (consp cbcdr))
+	(let ((plist (list 'opsym (intern (car opcdr)) 'callback (car cbcdr))))
+	  (make-tooltalk-pattern (append args (list 'plist plist))))
+      (make-tooltalk-pattern args))))
+
+(defun register-initial-tooltalk-patterns ()
+  (mapcar #'register-tooltalk-pattern 
+	  (setq initial-tooltalk-patterns
+		(mapcar #'make-initial-tooltalk-pattern
+			(list tooltalk-eval-pattern
+			      tooltalk-load-file-pattern
+			      tooltalk-make-client-frame-pattern
+			      tooltalk-status-pattern))))
+  (add-hook 'tooltalk-unprocessed-message-hook 'dispatch-initial-tooltalk-message))
+
+
+(defun unregister-initial-tooltalk-patterns ()
+  (mapcar 'destroy-tooltalk-pattern initial-tooltalk-patterns)
+  (setq initial-tooltalk-patterns ())
+  (remove-hook 'tooltalk-unprocessed-message-hook 'dispatch-initial-tooltalk-message))
+
+
+(defun tooltalk:prin1-to-string (form)
+  "Like prin1-to-string except: if the string contains embedded nulls (unlikely
+but possible) then replace each one with \"\\000\"."
+  (let ((string (prin1-to-string form)))
+    (let ((parts '())
+	  index)
+      (while (setq index (string-match "\0" string))
+	(setq parts 
+	      (apply 'list "\\000" (substring string 0 index) parts))
+	(setq string (substring string (1+ index))))
+      (if (not parts)
+	  string
+	(setq parts (apply 'list string parts))
+	(apply 'concat (nreverse parts))))))
+
+;; Backwards compatibility
+(fset 'tooltalk::prin1-to-string-carefully 'tooltalk:prin1-to-string)
+
+
+(defun tooltalk:read-from-string (str)
+  "Like read-from-string except: an error is signalled if the entire 
+string can't be parsed."
+  (let ((res (read-from-string str)))
+    (if (< (cdr res) (length str))
+	(error "Parse of input string ended prematurely."
+	       str))
+    (car res)))
+
+
+(defun tooltalk::eval-string (str)
+  (let ((result (eval (car (read-from-string str)))))
+    (tooltalk:prin1-to-string result)))
+
+
+(defun tooltalk-eval-handler (msg pat)
+  (let ((str (get-tooltalk-message-attribute msg 'arg_val 0))
+	(result-str nil)
+	(failp t))
+    (unwind-protect
+	(cond
+	 ;; Assume That the emacs debugger will handle errors.
+	 ;; If the user throws from the debugger to the cleanup
+	 ;; form below, failp will remain t.
+	 (debug-on-error   
+	  (setq result-str (tooltalk::eval-string str)
+		failp nil))
+
+	 ;; If an error occurs as a result of evaluating
+	 ;; the string or printing the result, then we'll return 
+	 ;; a string version of error-info.
+	 (t
+	  (condition-case error-info
+	      (setq result-str (tooltalk::eval-string str)
+		    failp nil)
+	    (error 
+	     (let ((error-str (tooltalk:prin1-to-string error-info)))
+	       (setq result-str error-str
+		     failp t))))))
+
+      ;; If we get to this point and result-str is still nil, the
+      ;; user must have thrown out of the debuggger
+      (let ((reply-type (if failp 'fail 'reply))
+	    (reply-value (or result-str "(debugger exit)")))
+	(set-tooltalk-message-attribute reply-value msg 'arg_val 0)
+	(return-tooltalk-message msg reply-type)))))
+
+
+(defun tooltalk-make-client-frame-handler (m p)
+  (let ((nargs (get-tooltalk-message-attribute m 'args_count)))
+    (if (not (= 3 nargs))
+	(progn
+	  (set-tooltalk-message-attribute "wrong number of arguments" m 'status_string)
+	  (return-tooltalk-message m 'fail))))
+
+  ;; Note: relying on the fact that arg_ival is returned as a string
+
+  (let* ((name   (get-tooltalk-message-attribute m 'arg_val 0))
+	 (window (get-tooltalk-message-attribute m 'arg_ival 1))
+	 (args (list (cons 'name name) (cons 'window-id window)))
+	 (frame (make-frame args)))
+    (set-tooltalk-message-attribute (frame-name frame) m 'arg_val 2)
+    (return-tooltalk-message m 'reply)))
+
+
+
+(defun tooltalk-load-file-handler (m p)
+  (let ((path (get-tooltalk-message-attribute m 'file)))
+    (condition-case error-info 
+	(progn
+	  (load-file path)
+	  (return-tooltalk-message m 'reply))
+      (error 
+       (let ((error-string (tooltalk:prin1-to-string error-info)))
+	(set-tooltalk-message-attribute error-string m 'status_string)
+	(return-tooltalk-message m 'fail))))))
+
+
+(defun tooltalk-status-handler (m p)
+  (return-tooltalk-message m 'reply))
+
+
+;; Hack the command-line.
+
+(defun command-line-do-tooltalk (arg)
+  "Connect to the ToolTalk server."
+;  (setq command-line-args-left
+;	(cdr (tooltalk-open-connection (cons (car command-line-args)
+;					     command-line-args-left))))
+  (if (tooltalk-open-connection)
+      (register-initial-tooltalk-patterns)
+    (display-warning 'tooltalk "Warning: unable to connect to a ToolTalk server.")))
+
+(setq command-switch-alist
+      (append command-switch-alist
+	      '(("-tooltalk" . command-line-do-tooltalk))))
+
+;; Add some selection converters.
+
+(defun xselect-convert-to-ttprocid (selection type value)
+  (let* ((msg (create-tooltalk-message))
+	 (ttprocid (get-tooltalk-message-attribute msg 'sender)))
+    (destroy-tooltalk-message msg)
+    ttprocid
+    ))
+
+(defun xselect-convert-to-ttsession (selection type value)
+  (let* ((msg (create-tooltalk-message))
+	 (ttsession (get-tooltalk-message-attribute msg 'session)))
+    (destroy-tooltalk-message msg)
+    ttsession
+    ))
+
+(if (boundp 'selection-converter-alist)
+    (setq selection-converter-alist
+	  (append
+	   selection-converter-alist
+	   '((SPRO_PROCID . xselect-convert-to-ttprocid)
+	     (SPRO_SESSION . xselect-convert-to-ttsession)
+	     )))
+  (setq selection-converter-alist
+	'((SPRO_PROCID . xselect-convert-to-ttprocid)
+	  (SPRO_SESSION . xselect-convert-to-ttsession))))
+