1 ;;; -*- Mode: Emacs-Lisp -*-
3 ;;; Registration of the default Tooltalk patterns and handlers.
5 ;;; @(#)tooltalk-init.el 1.8 94/02/22
8 (defvar tooltalk-eval-pattern
12 callback tooltalk-eval-handler))
14 (defvar tooltalk-load-file-pattern
18 args ((TT_IN "file" "string"))
19 callback tooltalk-load-file-handler))
21 (defvar tooltalk-make-client-frame-pattern
24 op "emacs-make-client-screen"
25 callback tooltalk-make-client-frame-handler))
27 (defvar tooltalk-status-pattern
31 callback tooltalk-status-handler))
34 (defvar initial-tooltalk-patterns ())
36 (defun dispatch-initial-tooltalk-message (m)
37 (let ((op (get-tooltalk-message-attribute m 'op))
38 (patterns initial-tooltalk-patterns))
41 (let ((p (car patterns)))
42 (if (eq (intern op) (tooltalk-pattern-prop-get p 'opsym))
43 (let ((callback (tooltalk-pattern-prop-get p 'callback)))
44 (if callback (funcall callback m p))
46 (setq patterns (cdr patterns))))))))
48 (defun make-initial-tooltalk-pattern (args)
49 (let ((opcdr (cdr (memq 'op args)))
50 (cbcdr (cdr (memq 'callback args))))
51 (if (and (consp opcdr) (consp cbcdr))
52 (let ((plist (list 'opsym (intern (car opcdr)) 'callback (car cbcdr))))
53 (make-tooltalk-pattern (append args (list 'plist plist))))
54 (make-tooltalk-pattern args))))
56 (defun register-initial-tooltalk-patterns ()
57 (mapcar #'register-tooltalk-pattern
58 (setq initial-tooltalk-patterns
59 (mapcar #'make-initial-tooltalk-pattern
60 (list tooltalk-eval-pattern
61 tooltalk-load-file-pattern
62 tooltalk-make-client-frame-pattern
63 tooltalk-status-pattern))))
64 (add-hook 'tooltalk-unprocessed-message-hook 'dispatch-initial-tooltalk-message))
67 (defun unregister-initial-tooltalk-patterns ()
68 (mapcar 'destroy-tooltalk-pattern initial-tooltalk-patterns)
69 (setq initial-tooltalk-patterns ())
70 (remove-hook 'tooltalk-unprocessed-message-hook 'dispatch-initial-tooltalk-message))
73 (defun tooltalk:prin1-to-string (form)
74 "Like prin1-to-string except: if the string contains embedded nulls (unlikely
75 but possible) then replace each one with \"\\000\"."
76 (let ((string (prin1-to-string form)))
79 (while (setq index (string-match "\0" string))
81 (apply 'list "\\000" (substring string 0 index) parts))
82 (setq string (substring string (1+ index))))
85 (setq parts (apply 'list string parts))
86 (apply 'concat (nreverse parts))))))
88 ;; Backwards compatibility
89 (fset 'tooltalk::prin1-to-string-carefully 'tooltalk:prin1-to-string)
92 (defun tooltalk:read-from-string (str)
93 "Like read-from-string except: an error is signalled if the entire
94 string can't be parsed."
95 (let ((res (read-from-string str)))
96 (if (< (cdr res) (length str))
97 (error "Parse of input string ended prematurely."
102 (defun tooltalk::eval-string (str)
103 (let ((result (eval (car (read-from-string str)))))
104 (tooltalk:prin1-to-string result)))
107 (defun tooltalk-eval-handler (msg pat)
108 (let ((str (get-tooltalk-message-attribute msg 'arg_val 0))
113 ;; Assume That the emacs debugger will handle errors.
114 ;; If the user throws from the debugger to the cleanup
115 ;; form below, failp will remain t.
117 (setq result-str (tooltalk::eval-string str)
120 ;; If an error occurs as a result of evaluating
121 ;; the string or printing the result, then we'll return
122 ;; a string version of error-info.
124 (condition-case error-info
125 (setq result-str (tooltalk::eval-string str)
128 (let ((error-str (tooltalk:prin1-to-string error-info)))
129 (setq result-str error-str
132 ;; If we get to this point and result-str is still nil, the
133 ;; user must have thrown out of the debugger
134 (let ((reply-type (if failp 'fail 'reply))
135 (reply-value (or result-str "(debugger exit)")))
136 (set-tooltalk-message-attribute reply-value msg 'arg_val 0)
137 (return-tooltalk-message msg reply-type)))))
140 (defun tooltalk-make-client-frame-handler (m p)
141 (let ((nargs (get-tooltalk-message-attribute m 'args_count)))
142 (if (not (= 3 nargs))
144 (set-tooltalk-message-attribute "wrong number of arguments" m 'status_string)
145 (return-tooltalk-message m 'fail))))
147 ;; Note: relying on the fact that arg_ival is returned as a string
149 (let* ((name (get-tooltalk-message-attribute m 'arg_val 0))
150 (window (get-tooltalk-message-attribute m 'arg_ival 1))
151 (args (list (cons 'name name) (cons 'window-id window)))
152 (frame (make-frame args)))
153 (set-tooltalk-message-attribute (frame-name frame) m 'arg_val 2)
154 (return-tooltalk-message m 'reply)))
158 (defun tooltalk-load-file-handler (m p)
159 (let ((path (get-tooltalk-message-attribute m 'file)))
160 (condition-case error-info
163 (return-tooltalk-message m 'reply))
165 (let ((error-string (tooltalk:prin1-to-string error-info)))
166 (set-tooltalk-message-attribute error-string m 'status_string)
167 (return-tooltalk-message m 'fail))))))
170 (defun tooltalk-status-handler (m p)
171 (return-tooltalk-message m 'reply))
174 ;; Hack the command-line.
176 (defun command-line-do-tooltalk (arg)
177 "Connect to the ToolTalk server."
178 ; (setq command-line-args-left
179 ; (cdr (tooltalk-open-connection (cons (car command-line-args)
180 ; command-line-args-left))))
181 (if (tooltalk-open-connection)
182 (register-initial-tooltalk-patterns)
183 (display-warning 'tooltalk "Warning: unable to connect to a ToolTalk server.")))
185 (setq command-switch-alist
186 (append command-switch-alist
187 '(("-tooltalk" . command-line-do-tooltalk))))
189 ;; Add some selection converters.
191 (defun xselect-convert-to-ttprocid (selection type value)
192 (let* ((msg (create-tooltalk-message))
193 (ttprocid (get-tooltalk-message-attribute msg 'sender)))
194 (destroy-tooltalk-message msg)
198 (defun xselect-convert-to-ttsession (selection type value)
199 (let* ((msg (create-tooltalk-message))
200 (ttsession (get-tooltalk-message-attribute msg 'session)))
201 (destroy-tooltalk-message msg)
205 (if (boundp 'selection-converter-alist)
206 (setq selection-converter-alist
208 selection-converter-alist
209 '((SPRO_PROCID . xselect-convert-to-ttprocid)
210 (SPRO_SESSION . xselect-convert-to-ttsession)
212 (setq selection-converter-alist
213 '((SPRO_PROCID . xselect-convert-to-ttprocid)
214 (SPRO_SESSION . xselect-convert-to-ttsession))))