1 ;;; elmo-signal.el --- "signal-slot" abstraction for routing events
3 ;; Copyright (C) 1998-2003 Daiki Ueno <ueno@unixuser.org>
5 ;; Author: Daiki Ueno <ueno@unixuser.org>
6 ;; Hiroya Murata <lapis-lazuli@pop06.odn.ne.jp>
7 ;; Keywords: mail, net news
9 ;; This file is part of ELMO (Elisp Library for Message Orchestration).
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
29 ;;; This module implements Qt like "signal-slot" abstraction for
32 ;;; Based on riece-signal.el.
36 (eval-when-compile (require 'cl
))
38 (defvar elmo-signal-slot-obarray
41 (defun elmo-make-slot (source listener function
&optional filter handback
)
42 "Make an instance of slot object.
43 Arguments are corresponding to callback function, filter function, and
44 a handback object, respectively.
45 This function is for internal use only."
46 (vector source listener function filter handback
))
48 (defun elmo-slot-source (slot)
49 "Return the source of SLOT.
50 This function is for internal use only."
53 (defun elmo-slot-listener (slot)
54 "Return the listener of SLOT.
55 This function is for internal use only."
58 (defun elmo-slot-function (slot)
59 "Return the callback function of SLOT.
60 This function is for internal use only."
63 (defun elmo-slot-filter (slot)
64 "Return the filter function of SLOT.
65 This function is for internal use only."
68 (defun elmo-slot-handback (slot)
69 "Return the handback object of SLOT.
70 This function is for internal use only."
73 (put 'elmo-define-signal
'lisp-indent-function
'defun
)
74 (defmacro elmo-define-signal
(name args
&optional doc
)
75 `(setplist ',name
(list 'elmo-signal-args
',args
76 'elmo-signal-docstring
,doc
)))
78 (defun elmo-signal-name (signal)
79 "Return the name of SIGNAL."
82 (defun elmo-signal-args (signal)
83 "Return the argument list of SIGNAL."
84 (get signal
'elmo-signal-args
))
86 (defun elmo-signal-docstring (signal)
87 "Return the docment string of SIGNAL."
88 (get signal
'elmo-signal-docstring
))
90 (defun elmo-signal-bindings (source listener args handback arg-list
)
94 (setq bindings
(cons (list (car arg-list
) listener
) bindings
)))
95 (when (setq arg-list
(cdr arg-list
))
96 (setq bindings
(cons (list (car arg-list
) source
) bindings
)))
97 (while (and (setq arg-list
(cdr arg-list
))
98 (not (eq (car arg-list
) '&optional
)))
99 (setq bindings
(cons (list (car arg-list
) (list 'nth i args
)) bindings
)
102 (setq arg-list
(cdr arg-list
)))
103 (setq bindings
(cons (list (car arg-list
) handback
) bindings
)))
106 (defmacro elmo-define-signal-handler
(args &rest body
)
107 "Define a signal handler.
108 ARGS is a symbol list as (LISTENER SOURCE ARG... &optional HANDBACK)."
109 (let ((source (make-symbol "--source--"))
110 (listener (make-symbol "--listener--"))
111 (argument (make-symbol "--argument--"))
112 (handback (make-symbol "--handback--")))
113 `(lambda (,listener
,source
,argument
,handback
)
114 (let ,(elmo-signal-bindings source listener argument handback args
)
117 (put 'elmo-define-signal-handler
'lisp-indent-function
'defun
)
118 (def-edebug-spec elmo-define-signal-handler
119 (&define
(arg [&rest arg
] [&optional
["&optional" arg
&rest arg
]])
122 (defmacro elmo-define-signal-filter
(args &rest body
)
123 "Define a signal filter.
124 ARGS is a symbol list as (LISTENER SOURCE ARG...)."
125 (let ((source (make-symbol "--source--"))
126 (listener (make-symbol "--listener--"))
127 (argument (make-symbol "--argument--")))
128 `(lambda (,listener
,source
,argument
)
129 (let ,(elmo-signal-bindings source listener argument nil args
)
132 (put 'elmo-define-signal-filter
'lisp-indent-function
'defun
)
133 (def-edebug-spec elmo-define-signal-filter
134 (&define
(arg [&rest arg
])
137 (defun elmo-connect-signal (source signal-name listener handler
138 &optional filter handback
)
139 "Add HANDLER as a callback function for signal identified by SIGNAL-NAME.
140 If SOURCE has non-nil value, HANDLER will be invoked only if SOURCE is same as
141 source argument of `elmo-emit-signal'. Comparison is done with `eq'. If SOURCE
142 is nil, react on signals from any sources.
143 You can specify further filter function by FILTER."
144 (let ((symbol (intern (symbol-name signal-name
) elmo-signal-slot-obarray
)))
145 (set symbol
(cons (elmo-make-slot source listener handler filter handback
)
147 (symbol-value symbol
))))))
149 (defun elmo-disconnect-signal (signal-name listener
&optional function
)
150 "Remove FUNCTION from the listener of the signal identified by SIGNAL-NAME."
151 (let* ((symbol (intern-soft (symbol-name signal-name
)
152 elmo-signal-slot-obarray
))
153 (slots (symbol-value symbol
)))
155 (when (and (eq (elmo-slot-listener (car slots
)) listener
)
157 (eq (elmo-slot-function (car slots
)) function
)))
158 (set symbol
(delq (car slots
) (symbol-value symbol
))))
159 (setq slots
(cdr slots
)))))
161 (defun elmo-clear-signal-slots ()
162 "Remove all functions from listeners list."
163 (fillarray elmo-signal-slot-obarray
0))
165 (defun elmo-emit-signal (signal-name source
&rest args
)
166 "Emit signal with SIGNAL-NAME."
167 (let ((symbol (intern-soft (symbol-name signal-name
)
168 elmo-signal-slot-obarray
))
171 (dolist (slot (symbol-value symbol
))
173 (when (and (or (null (elmo-slot-source slot
))
174 (eq (elmo-slot-source slot
) source
))
175 (or (null (elmo-slot-filter slot
))
177 (funcall (elmo-slot-filter slot
)
178 (elmo-slot-listener slot
)
181 (funcall (elmo-slot-function slot
)
182 (elmo-slot-listener slot
)
185 (elmo-slot-handback slot
))))))))
188 (product-provide (provide 'elmo-signal
) (require 'elmo-version
))
190 ;;; elmo-signal.el ends here