1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 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))))
|