* WL-ELS (ELMO-MODULES): Added elmo-signal.
authorhmurata <hmurata>
Fri, 18 Feb 2005 16:51:11 +0000 (16:51 +0000)
committerhmurata <hmurata>
Fri, 18 Feb 2005 16:51:11 +0000 (16:51 +0000)
* elmo-signal.el: New file.

* elmo.el (toplevel): Require elmo-signal.
(flag-changing, flag-changed, cache-changed): New signal.
(elmo-folder): Remove slog `handlers'.
(elmo-message-set-cached): Use `elmo-emit-signal' instead of
`elmo-folder-notify-event'.
(elmo-folder-set-flag): Likewise. Emit signal `flag-changing'.
(elmo-folder-unset-flag): Ditto.
(elmo-event-handler): Abolish.
(elmo-event-handler-flag-changed): Ditto.
(elmo-event-handler-cache-changed): Ditto.
(elmo-folder-add-handler): Ditto.
(elmo-folder-remove-handler): Ditto.
(elmo-folder-notify-event): Ditto.

* elmo-pipe.el (toplevel): Require elmo-signal.
(elmo-folder-initialize): Call `elmo-pipe-connect-signals'.
(elmo-pipe-connect-signals): New function.
(elmo-message-fetch): Does not call `elmo-folder-notify-event'.
(elmo-folder-set-flag): Ditto.
(elmo-folder-unset-flag): Ditto.
(elmo-message-set-cached): Ditto.

* elmo-multi.el (toplevel): Require elmo-signal.
(elmo-folder-initialize): Call `elmo-multi-connect-signals'.
(elmo-multi-connect-signals): New function.
(elmo-multi-map-numbers): Ditto.
(elmo-message-set-cached): Does not call `elmo-folder-notify-event'.
(elmo-message-fetch): Ditto.
(elmo-folder-set-flag): Ditto.
(elmo-folder-unset-flag): Ditto.

* elmo-filter.el (toplevel): Require elmo-signal.
(elmo-folder-initialize): Call `elmo-filter-connect-signals'.
(elmo-filter-connect-signals): New function.
(elmo-filter-add-flag-count): Ditto.
(elmo-message-fetch): Does not call
`elmo-filter-folder-countup-message-flags' and
`elmo-folder-notify-event'.
(elmo-message-set-cached): Ditto.
(elmo-folder-set-flag): Ditto.
(elmo-folder-unset-flag): Ditto.

* wl.el (wl-exit): Call `elmo-clear-signal-slots'.

* wl-summary.el (wl-summary-buffer-event-handler): Abolish.
(wl-summary-event-handler): Ditto.
(wl-summary-update-persistent-mark-on-event): New
function (renamed from `elmo-event-handler-flag-changed').
(wl-summary-buffer-attach): New function.
(wl-summary-buffer-detach): Rewrite by `elmo-signal'.
(wl-summary-buffer-set-folder): Use `wl-summary-buffer-attach'
instead of `elmo-folder-add-handler'.

ChangeLog
WL-ELS
elmo/ChangeLog
elmo/elmo-filter.el
elmo/elmo-multi.el
elmo/elmo-pipe.el
elmo/elmo-signal.el [new file with mode: 0644]
elmo/elmo.el
wl/ChangeLog
wl/wl-summary.el
wl/wl.el

index 137f353..7f313f6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2005-02-18  Hiroya Murata  <lapis-lazuli@pop06.odn.ne.jp>
+
+       * WL-ELS (ELMO-MODULES): Added elmo-signal.
+
 2005-01-23  Hiroya Murata  <lapis-lazuli@pop06.odn.ne.jp>
 
        * Makefile (compile-strict): New target.
diff --git a/WL-ELS b/WL-ELS
index b7f8269..2b15946 100644 (file)
--- a/WL-ELS
+++ b/WL-ELS
@@ -16,7 +16,8 @@
 
 (defconst ELMO-MODULES '(
    utf7 pldap acap slp mmimap
-   elmo-date elmo-util elmo-version elmo-vars elmo elmo-msgdb
+   elmo-signal elmo-date elmo-util elmo-version
+   elmo-vars elmo elmo-msgdb
    elmo-net elmo-imap4 elmo-pop3 elmo-nntp
    elmo-localdir elmo-localnews elmo-map elmo-maildir
    elmo-multi elmo-access elmo-filter
index 4e39628..f2d13ac 100644 (file)
@@ -1,5 +1,49 @@
 2005-02-18  Hiroya Murata  <lapis-lazuli@pop06.odn.ne.jp>
 
+       * elmo-signal.el: New file.
+
+       * elmo.el (toplevel): Require elmo-signal.
+       (flag-changing, flag-changed, cache-changed): New signal.
+       (elmo-folder): Remove slog `handlers'.
+       (elmo-message-set-cached): Use `elmo-emit-signal' instead of
+       `elmo-folder-notify-event'.
+       (elmo-folder-set-flag): Likewise. Emit signal `flag-changing'.
+       (elmo-folder-unset-flag): Ditto.
+       (elmo-event-handler): Abolish.
+       (elmo-event-handler-flag-changed): Ditto.
+       (elmo-event-handler-cache-changed): Ditto.
+       (elmo-folder-add-handler): Ditto.
+       (elmo-folder-remove-handler): Ditto.
+       (elmo-folder-notify-event): Ditto.
+
+       * elmo-pipe.el (toplevel): Require elmo-signal.
+       (elmo-folder-initialize): Call `elmo-pipe-connect-signals'.
+       (elmo-pipe-connect-signals): New function.
+       (elmo-message-fetch): Does not call `elmo-folder-notify-event'.
+       (elmo-folder-set-flag): Ditto.
+       (elmo-folder-unset-flag): Ditto.
+       (elmo-message-set-cached): Ditto.
+
+       * elmo-multi.el (toplevel): Require elmo-signal.
+       (elmo-folder-initialize): Call `elmo-multi-connect-signals'.
+       (elmo-multi-connect-signals): New function.
+       (elmo-multi-map-numbers): Ditto.
+       (elmo-message-set-cached): Does not call `elmo-folder-notify-event'.
+       (elmo-message-fetch): Ditto.
+       (elmo-folder-set-flag): Ditto.
+       (elmo-folder-unset-flag): Ditto.
+
+       * elmo-filter.el (toplevel): Require elmo-signal.
+       (elmo-folder-initialize): Call `elmo-filter-connect-signals'.
+       (elmo-filter-connect-signals): New function.
+       (elmo-filter-add-flag-count): Ditto.
+       (elmo-message-fetch): Does not call
+       `elmo-filter-folder-countup-message-flags' and
+       `elmo-folder-notify-event'.
+       (elmo-message-set-cached): Ditto.
+       (elmo-folder-set-flag): Ditto.
+       (elmo-folder-unset-flag): Ditto.
+
        * elmo-version.el (elmo-version): Up to 2.13.2.
 
 2005-02-17  Hiroya Murata  <lapis-lazuli@pop06.odn.ne.jp>
index efaa0b4..632b095 100644 (file)
@@ -30,6 +30,7 @@
 ;;; Code:
 ;;
 (require 'elmo)
+(require 'elmo-signal)
 (require 'elmo-msgdb)
 
 (defvar elmo-filter-number-filename "number-list"
@@ -45,8 +46,7 @@
                                            name)
   (let (pair)
     (setq pair (elmo-parse-search-condition name))
-    (elmo-filter-folder-set-condition-internal folder
-                                              (car pair))
+    (elmo-filter-folder-set-condition-internal folder (car pair))
     (if (string-match "^ */\\(.*\\)$" (cdr pair))
        (elmo-filter-folder-set-target-internal
         folder
      (elmo-folder-search-requires-msgdb-p
       (elmo-filter-folder-target-internal folder)
       (elmo-filter-folder-condition-internal folder)))
+    (elmo-filter-connect-signals
+     folder
+     (elmo-filter-folder-target-internal folder))
     folder))
 
+(defun elmo-filter-connect-signals (folder target)
+  (elmo-connect-signal
+   target 'flag-changing folder
+   (elmo-define-signal-handler (folder target number old-flags new-flags)
+     (elmo-filter-add-flag-count folder number old-flags -1)
+     (elmo-filter-add-flag-count folder number new-flags)
+     (elmo-emit-signal 'flag-changing folder number old-flags new-flags))
+   (elmo-define-signal-filter (folder target number)
+     (memq number (elmo-folder-list-messages folder nil t))))
+  (elmo-connect-signal
+   target 'flag-changed folder
+   (elmo-define-signal-handler (folder target numbers)
+     (let ((filterd (elmo-list-filter
+                    (elmo-folder-list-messages folder nil t)
+                    numbers)))
+       (when filterd
+        (elmo-emit-signal 'flag-changed folder filterd)))))
+  (elmo-connect-signal
+   target 'cache-changed folder
+   (elmo-define-signal-handler (folder target number)
+     (elmo-emit-signal 'cache-changed folder number))
+   (elmo-define-signal-filter (folder target number)
+     (memq number (elmo-folder-list-messages folder nil t)))))
+
 (defun elmo-filter-number-list-load (dir)
   (elmo-object-load
    (expand-file-name elmo-filter-number-filename dir)))
          (setq flag-count (cons (cons flag delta) flag-count)))))
     (elmo-filter-folder-set-flag-count-internal folder flag-count)))
 
+(defun elmo-filter-add-flag-count (folder number flags &optional delta)
+  (let ((flag-count (elmo-filter-folder-flag-count-internal folder))
+       (delta (or delta 1))
+       elem)
+    (dolist (flag flags)
+      (if (setq elem (assq flag flag-count))
+         (setcdr elem (+ (cdr elem) delta))
+       (setq flag-count (cons (cons flag delta) flag-count))))
+    (elmo-filter-folder-set-flag-count-internal folder flag-count)))
+
 (defun elmo-filter-folder-flag-count (folder)
   (or (elmo-filter-folder-flag-count-internal folder)
       (elmo-filter-folder-countup-message-flags
 (luna-define-method elmo-message-fetch ((folder elmo-filter-folder)
                                        number strategy
                                        &optional unseen section)
-  (unless unseen
-    (elmo-filter-folder-countup-message-flags folder (list number) -1))
-  (when (elmo-message-fetch (elmo-filter-folder-target-internal folder)
-                           number strategy unseen section)
-    (unless unseen
-      (elmo-filter-folder-countup-message-flags folder (list number))
-      (elmo-folder-notify-event folder 'flag-changed (list number)))
-    t))
+  (elmo-message-fetch (elmo-filter-folder-target-internal folder)
+                     number strategy unseen section))
 
 (luna-define-method elmo-folder-delete-messages ((folder elmo-filter-folder)
                                                 numbers)
 (luna-define-method elmo-message-set-cached ((folder elmo-filter-folder)
                                             number cached)
   (elmo-message-set-cached
-   (elmo-filter-folder-target-internal folder) number cached)
-  (elmo-folder-notify-event folder 'cache-changed number))
+   (elmo-filter-folder-target-internal folder) number cached))
 
 (luna-define-method elmo-message-number ((folder elmo-filter-folder)
                                         message-id)
                                          numbers
                                          flag
                                          &optional is-local)
-  (elmo-filter-folder-countup-message-flags folder numbers -1)
   (elmo-folder-set-flag (elmo-filter-folder-target-internal folder)
-                       numbers flag is-local)
-  (elmo-filter-folder-countup-message-flags folder numbers)
-  (elmo-folder-notify-event folder 'flag-changed numbers))
+                       numbers flag is-local))
 
 (luna-define-method elmo-folder-unset-flag ((folder elmo-filter-folder)
                                            numbers
                                            flag
                                            &optional is-local)
-  (elmo-filter-folder-countup-message-flags folder numbers -1)
   (elmo-folder-unset-flag (elmo-filter-folder-target-internal folder)
-                         numbers flag is-local)
-  (elmo-filter-folder-countup-message-flags folder numbers)
-  (elmo-folder-notify-event folder 'flag-changed numbers))
+                         numbers flag is-local))
 
 (luna-define-method elmo-message-folder ((folder elmo-filter-folder)
                                         number)
index 2a13b79..bfa4259 100644 (file)
@@ -31,6 +31,7 @@
 (eval-when-compile (require 'cl))
 
 (require 'elmo)
+(require 'elmo-signal)
 (require 'luna)
 
 (defvar elmo-multi-divide-number 100000
   (elmo-multi-folder-set-divide-number-internal
    folder
    elmo-multi-divide-number)
+  (elmo-multi-connect-signals folder)
   folder)
 
+(defun elmo-multi-connect-signals (folder)
+  (elmo-connect-signal
+   nil 'flag-changing folder
+   (elmo-define-signal-handler (folder child number old-flags new-flags)
+     (elmo-emit-signal 'flag-changing folder
+                      (car (elmo-multi-map-numbers folder child (list number)))
+                      old-flags new-flags))
+   (elmo-define-signal-filter (folder sender)
+     (memq sender (elmo-multi-folder-children-internal folder))))
+  (elmo-connect-signal
+   nil 'flag-changed folder
+   (elmo-define-signal-handler (folder child numbers)
+     (elmo-emit-signal 'flag-changed folder
+                      (elmo-multi-map-numbers folder child numbers)))
+   (elmo-define-signal-filter (folder sender)
+     (memq sender (elmo-multi-folder-children-internal folder))))
+  (elmo-connect-signal
+   nil 'cache-changed folder
+   (elmo-define-signal-handler (folder child number)
+     (elmo-emit-signal
+      'flag-changed folder
+      (car (elmo-multi-map-numbers folder child (list number)))))
+   (elmo-define-signal-filter (folder sender)
+     (memq sender (elmo-multi-folder-children-internal folder)))))
+
+(defun elmo-multi-map-numbers (folder child numbers)
+  (let ((multi (catch 'found
+                (let ((children (elmo-multi-folder-children-internal folder))
+                      (index 0))
+                  (while children
+                    (setq index (1+ index))
+                    (when (eq (car children) child)
+                      (throw 'found index))
+                    (setq children (cdr children)))))))
+    (when multi
+      (let ((offset (* (elmo-multi-folder-divide-number-internal folder)
+                      multi)))
+      (mapcar (lambda (number) (+ offset number))
+             numbers)))))
+
+
 (luna-define-method elmo-folder-open-internal ((folder elmo-multi-folder))
   (dolist (fld (elmo-multi-folder-children-internal folder))
     (elmo-folder-open-internal fld)))
 (luna-define-method elmo-message-set-cached ((folder elmo-multi-folder)
                                             number cached)
   (let ((pair (elmo-multi-real-folder-number folder number)))
-    (elmo-message-set-cached (car pair) (cdr pair) cached))
-  (elmo-folder-notify-event folder 'cache-changed number))
+    (elmo-message-set-cached (car pair) (cdr pair) cached)))
 
 (luna-define-method elmo-find-fetch-strategy ((folder elmo-multi-folder)
                                              number
                                        number strategy
                                        &optional unseen section)
   (let ((pair (elmo-multi-real-folder-number folder number)))
-    (when (elmo-message-fetch (car pair) (cdr pair)
-                             strategy unseen section)
-      (unless unseen
-       (elmo-folder-notify-event folder 'flag-changed (list number)))
-      t)))
+    (elmo-message-fetch (car pair) (cdr pair) strategy unseen section)))
 
 (luna-define-method elmo-folder-delete-messages ((folder elmo-multi-folder)
                                                 numbers)
                                          flag
                                          &optional is-local)
   (dolist (pair (elmo-multi-make-folder-numbers-list folder numbers))
-    (elmo-folder-set-flag (car pair) (cdr pair) flag is-local))
-  (elmo-folder-notify-event folder 'flag-changed numbers))
+    (elmo-folder-set-flag (car pair) (cdr pair) flag is-local)))
 
 (luna-define-method elmo-folder-unset-flag ((folder elmo-multi-folder)
                                            numbers
                                            &optional is-local)
   (dolist (pair (elmo-multi-make-folder-numbers-list folder numbers))
     (ignore-errors
-     (elmo-folder-unset-flag (car pair) (cdr pair) flag is-local)))
-  (elmo-folder-notify-event folder 'flag-changed numbers))
+     (elmo-folder-unset-flag (car pair) (cdr pair) flag is-local))))
 
 (luna-define-method elmo-folder-list-flagged ((folder elmo-multi-folder)
                                              flag
index ca07964..1a499e3 100644 (file)
@@ -30,6 +30,7 @@
 ;;
 
 (require 'elmo)
+(require 'elmo-signal)
 
 (defvar elmo-pipe-folder-copied-filename "copied"
   "Copied messages number set.")
     (elmo-pipe-folder-set-copy-internal folder
                                        (string= ":"
                                                 (elmo-match-string 2 name))))
+  (elmo-pipe-connect-signals folder (elmo-pipe-folder-dst-internal folder))
   folder)
 
+(defun elmo-pipe-connect-signals (folder destination)
+  (elmo-connect-signal
+   destination 'flag-changing folder
+   (elmo-define-signal-handler (folder dst number old-flags new-flags)
+     (elmo-emit-signal 'flag-changing folder number old-flags new-flags)))
+  (elmo-connect-signal
+   destination 'flag-changed folder
+   (elmo-define-signal-handler (folder dst numbers)
+     (elmo-emit-signal 'flag-changed folder numbers)))
+  (elmo-connect-signal
+   destination 'cache-changed folder
+   (elmo-define-signal-handler (folder dst number)
+     (elmo-emit-signal 'cache-changed folder number))))
+
 (luna-define-method elmo-folder-get-primitive-list ((folder elmo-pipe-folder))
   (nconc
    (elmo-folder-get-primitive-list (elmo-pipe-folder-src-internal folder))
 (luna-define-method elmo-message-fetch ((folder elmo-pipe-folder)
                                        number strategy
                                        &optional unseen section)
-  (when (elmo-message-fetch (elmo-pipe-folder-dst-internal folder)
-                           number strategy unseen section)
-    (unless unseen
-      (elmo-folder-notify-event folder 'flag-changed (list number)))
-    t))
+  (elmo-message-fetch (elmo-pipe-folder-dst-internal folder)
+                     number strategy unseen section))
 
 (luna-define-method elmo-folder-clear :after ((folder elmo-pipe-folder)
                                              &optional keep-killed)
                                          flag
                                          &optional is-local)
   (elmo-folder-set-flag (elmo-pipe-folder-dst-internal folder)
-                       numbers flag is-local)
-  (elmo-folder-notify-event folder 'flag-changed numbers))
+                       numbers flag is-local))
 
 (luna-define-method elmo-folder-unset-flag ((folder elmo-pipe-folder)
                                            numbers
                                            flag
                                            &optional is-local)
   (elmo-folder-unset-flag (elmo-pipe-folder-dst-internal folder)
-                         numbers flag is-local)
-  (elmo-folder-notify-event folder 'flag-changed numbers))
+                         numbers flag is-local))
 
 (luna-define-method elmo-folder-pack-numbers ((folder elmo-pipe-folder))
   (elmo-folder-pack-numbers (elmo-pipe-folder-dst-internal folder)))
 (luna-define-method elmo-message-set-cached ((folder elmo-pipe-folder)
                                             number cached)
   (elmo-message-set-cached (elmo-pipe-folder-dst-internal folder)
-                          number cached)
-  (elmo-folder-notify-event folder 'cache-changed number))
+                          number cached))
 
 (luna-define-method elmo-find-fetch-strategy ((folder elmo-pipe-folder)
                                              number
diff --git a/elmo/elmo-signal.el b/elmo/elmo-signal.el
new file mode 100644 (file)
index 0000000..afb8af4
--- /dev/null
@@ -0,0 +1,185 @@
+;;; elmo-signal.el --- "signal-slot" abstraction for routing events
+
+;; Copyright (C) 1998-2003 Daiki Ueno <ueno@unixuser.org>
+
+;; Author: Daiki Ueno <ueno@unixuser.org>
+;;     Hiroya Murata <lapis-lazuli@pop06.odn.ne.jp>
+;; Keywords: mail, net news
+
+;; This file is part of ELMO (Elisp Library for Message Orchestration).
+
+;; This program 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 program 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:
+
+;;; This module implements Qt like "signal-slot" abstraction for
+;;; routing events.
+
+;;; Based on riece-signal.el.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(defvar elmo-signal-slot-obarray
+  (make-vector 31 0))
+
+(defun elmo-make-slot (source listener function &optional filter handback)
+  "Make an instance of slot object.
+Arguments are corresponding to callback function, filter function, and
+a handback object, respectively.
+This function is for internal use only."
+  (vector source listener function filter handback))
+
+(defun elmo-slot-source (slot)
+  "Return the source of SLOT.
+This function is for internal use only."
+  (aref slot 0))
+
+(defun elmo-slot-listener (slot)
+  "Return the listener of SLOT.
+This function is for internal use only."
+  (aref slot 1))
+
+(defun elmo-slot-function (slot)
+  "Return the callback function of SLOT.
+This function is for internal use only."
+  (aref slot 2))
+
+(defun elmo-slot-filter (slot)
+  "Return the filter function of SLOT.
+This function is for internal use only."
+  (aref slot 3))
+
+(defun elmo-slot-handback (slot)
+  "Return the handback object of SLOT.
+This function is for internal use only."
+  (aref slot 4))
+
+(put 'elmo-define-signal 'lisp-indent-function 'defun)
+(defmacro elmo-define-signal (name args &optional doc)
+  `(setplist ',name (list 'elmo-signal-args ',args
+                         'elmo-signal-docstring ,doc)))
+
+(defun elmo-signal-name (signal)
+  "Return the name of SIGNAL."
+  signal)
+
+(defun elmo-signal-args (signal)
+  "Return the argument list of SIGNAL."
+  (get signal 'elmo-signal-args))
+
+(defun elmo-signal-docstring (signal)
+  "Return the docment string of SIGNAL."
+  (get signal 'elmo-signal-docstring))
+
+(defun elmo-signal-bindings (source listener args handback arg-list)
+  (let ((i 0)
+       bindings)
+    (when (car arg-list)
+      (setq bindings (list (list (car arg-list) listener))))
+    (when (setq arg-list (cdr arg-list))
+      (setq bindings (nconc bindings
+                           (list (list (car arg-list) source)))))
+    (while (and (setq arg-list (cdr arg-list))
+               (not (eq (car arg-list) '&optional)))
+      (setq bindings (nconc bindings
+                           (list (list (car arg-list) (list 'nth i args))))
+           i (1+ i)))
+    (when (and handback
+              (setq arg-list (cdr arg-list)))
+      (setq bindings (nconc bindings
+                           (list (list (car arg-list) handback)))))
+    bindings))
+
+(defmacro elmo-define-signal-handler (args &rest body)
+  (let ((source   (make-symbol "--source--"))
+       (listener (make-symbol "--listener--"))
+       (argument (make-symbol "--argument--"))
+       (handback (make-symbol "--handback--")))
+    `(lambda (,listener ,source ,argument ,handback)
+       (let ,(elmo-signal-bindings source listener argument handback args)
+        ,@body))))
+
+(put 'elmo-define-signal-handler 'lisp-indent-function 'defun)
+(def-edebug-spec elmo-define-signal-handler
+  (&define (arg [&rest arg] [&optional ["&optional" arg &rest arg]])
+          def-body))
+
+(defmacro elmo-define-signal-filter (args &rest body)
+  (let ((source   (make-symbol "--source--"))
+       (listener (make-symbol "--listener--"))
+       (argument (make-symbol "--argument--")))
+    `(lambda (,listener ,source ,argument)
+       (let ,(elmo-signal-bindings source listener argument nil args)
+        ,@body))))
+
+(put 'elmo-define-signal-filter 'lisp-indent-function 'defun)
+(def-edebug-spec elmo-define-signal-filter
+  (&define (arg [&rest arg])
+          def-body))
+
+(defun elmo-connect-signal (source signal-name listener function
+                                  &optional filter handback)
+  "Add FUNCTION as a listener of a signal identified by SIGNAL-NAME."
+  (let ((symbol (intern (symbol-name signal-name) elmo-signal-slot-obarray)))
+    (set symbol (cons (elmo-make-slot source listener function filter handback)
+                     (if (boundp symbol)
+                         (symbol-value symbol))))))
+
+(defun elmo-disconnect-signal (signal-name listener &optional function)
+  "Remove FUNCTION from the listener of the signal identified by SIGNAL-NAME."
+  (let* ((symbol (intern-soft (symbol-name signal-name)
+                            elmo-signal-slot-obarray))
+        (slots (symbol-value symbol)))
+    (while slots
+      (when (and (eq (elmo-slot-listener (car slots)) listener)
+                (or (null function)
+                    (eq (elmo-slot-function (car slots)) function)))
+       (set symbol (delq (car slots) (symbol-value symbol))))
+      (setq slots (cdr slots)))))
+
+(defun elmo-clear-signal-slots ()
+  "Remove all functions from listeners list."
+  (fillarray elmo-signal-slot-obarray 0))
+
+(defun elmo-emit-signal (signal-name source &rest args)
+  "Emit SIGNAL."
+  (let ((symbol (intern-soft (symbol-name signal-name)
+                            elmo-signal-slot-obarray))
+       signal)
+    (when symbol
+      (dolist (slot (symbol-value symbol))
+       (ignore-errors
+         (when (and (or (null (elmo-slot-source slot))
+                        (eq (elmo-slot-source slot) source))
+                    (or (null (elmo-slot-filter slot))
+                        (ignore-errors
+                         (funcall (elmo-slot-filter slot)
+                                  (elmo-slot-listener slot)
+                                  (elmo-slot-source slot)
+                                  args))))
+           (funcall (elmo-slot-function slot)
+                    (elmo-slot-listener slot)
+                    (elmo-slot-source slot)
+                    args
+                    (elmo-slot-handback slot))))))))
+
+(require 'product)
+(product-provide (provide 'elmo-signal) (require 'elmo-version))
+
+;;; elmo-signal.el ends here
index 3b57f45..df61b7f 100644 (file)
@@ -35,6 +35,7 @@
 (require 'elmo-vars)
 (require 'elmo-util)
 (require 'elmo-msgdb)
+(require 'elmo-signal)
 
 (eval-when-compile (require 'cl))
 
@@ -87,6 +88,16 @@ Otherwise, entire fetching of the message is aborted without confirmation."
 (elmo-define-error 'elmo-authenticate-error "Login failed" 'elmo-open-error)
 (elmo-define-error 'elmo-imap4-bye-error "IMAP4 session was terminated" 'elmo-open-error)
 
+;; Event declarations
+(elmo-define-signal flag-changing (number old-flags new-flags)
+  "Notify the changing flag of the messages with NUMBER.")
+
+(elmo-define-signal flag-changed (numbers)
+  "Notify the change flag of the messages with NUMBERS.")
+
+(elmo-define-signal cache-changed (number)
+  "Notify the change cache status of the message with NUMBER.")
+
 ;; autoloads
 (eval-and-compile
   (autoload 'md5 "md5")
@@ -131,7 +142,6 @@ If a folder name begins with PREFIX, use BACKEND."
                                     persistent   ; non-nil if persistent.
                                     process-duplicates  ; read or hide
                                     biff   ; folder for biff
-                                    handlers     ; list of event handler.
                                     ))
   (luna-define-internal-accessors 'elmo-folder))
 
@@ -1167,7 +1177,7 @@ If CACHED is t, message is set as cached.")
   (if cached
       (elmo-msgdb-set-flag (elmo-folder-msgdb folder) number 'cached)
     (elmo-msgdb-unset-flag (elmo-folder-msgdb folder) number 'cached))
-  (elmo-folder-notify-event folder 'cache-changed number))
+  (elmo-emit-signal 'cache-changed folder number))
 
 (defun elmo-message-copy-entity (entity)
   (elmo-msgdb-copy-message-entity (elmo-message-entity-handler entity)
@@ -1287,13 +1297,17 @@ VALUE is a value to set.")
                                          &optional is-local)
   (when (elmo-folder-msgdb-internal folder)
     (dolist (number numbers)
-      (when (elmo-global-flag-p flag)
-       (let ((message-id (elmo-message-field folder number 'message-id)))
-         (elmo-global-flag-set flag folder number message-id)))
-      (elmo-msgdb-set-flag (elmo-folder-msgdb folder)
-                          number
-                          flag))
-    (elmo-folder-notify-event folder 'flag-changed numbers)))
+      (let ((old-flags (elmo-message-flags folder number)))
+       (when (elmo-global-flag-p flag)
+         (let ((message-id (elmo-message-field folder number 'message-id)))
+           (elmo-global-flag-set flag folder number message-id)))
+       (elmo-msgdb-set-flag (elmo-folder-msgdb folder) number flag)
+       (elmo-emit-signal 'flag-changing
+                         folder
+                         number
+                         old-flags
+                         (elmo-message-flags folder number))))
+    (elmo-emit-signal 'flag-changed folder numbers)))
 
 (defun elmo-message-has-global-flag-p (folder number)
   "Return non-nil when the message in the FOLDER with NUMBER has global flag."
@@ -1327,12 +1341,16 @@ If Optional LOCAL is non-nil, don't update server flag."
                                            &optional is-local)
   (when (elmo-folder-msgdb-internal folder)
     (dolist (number numbers)
-      (when (elmo-global-flag-p flag)
-       (elmo-global-flag-detach flag folder number 'always))
-      (elmo-msgdb-unset-flag (elmo-folder-msgdb folder)
-                            number
-                            flag))
-    (elmo-folder-notify-event folder 'flag-changed numbers)))
+      (let ((old-flags (elmo-message-flags folder number)))
+       (when (elmo-global-flag-p flag)
+         (elmo-global-flag-detach flag folder number 'always))
+       (elmo-msgdb-unset-flag (elmo-folder-msgdb folder) number flag)
+       (elmo-emit-signal 'flag-changing
+                         folder
+                         number
+                         old-flags
+                         (elmo-message-flags folder number))))
+    (elmo-emit-signal 'flag-changed folder numbers)))
 
 (luna-define-method elmo-folder-process-crosspost ((folder elmo-folder))
   ;; Do nothing.
@@ -1661,33 +1679,6 @@ Return a hashtable for newsgroups."
     (elmo-make-directory temp-dir)
     temp-dir))
 
-;; Event notification/observer framework
-(eval-and-compile
-  (luna-define-class elmo-event-handler ()))
-
-(luna-define-generic elmo-event-handler-flag-changed (handler numbers)
-  "Notify flag of the messages with NUMBERS is changed.")
-
-(luna-define-generic elmo-event-handler-cache-changed (handler number)
-  "Called when cache status of the message with NUMBER is changed.")
-
-(defun elmo-folder-add-handler (folder handler)
-  (unless (memq handler (elmo-folder-handlers-internal folder))
-    (elmo-folder-set-handlers-internal
-     folder
-     (cons handler (elmo-folder-handlers-internal folder)))))
-
-(defun elmo-folder-remove-handler (folder handler)
-  (elmo-folder-set-handlers-internal
-   folder
-   (delq handler (elmo-folder-handlers-internal folder))))
-
-(defun elmo-folder-notify-event (folder event &rest args)
-  (when (elmo-folder-handlers-internal folder)
-    (let ((message (format "elmo-event-handler-%s" event)))
-      (dolist (handler (elmo-folder-handlers-internal folder))
-       (apply #'luna-send handler message handler args)))))
-
 ;;;
 (defun elmo-init ()
   "Initialize ELMO module."
index b7c5b36..49810e8 100644 (file)
@@ -1,5 +1,16 @@
 2005-02-18  Hiroya Murata  <lapis-lazuli@pop06.odn.ne.jp>
 
+       * wl.el (wl-exit): Call `elmo-clear-signal-slots'.
+
+       * wl-summary.el (wl-summary-buffer-event-handler): Abolish.
+       (wl-summary-event-handler): Ditto.
+       (wl-summary-update-persistent-mark-on-event): New
+       function (renamed from `elmo-event-handler-flag-changed').
+       (wl-summary-buffer-attach): New function.
+       (wl-summary-buffer-detach): Rewrite by `elmo-signal'.
+       (wl-summary-buffer-set-folder): Use `wl-summary-buffer-attach'
+       instead of `elmo-folder-add-handler'.
+
        * Version number is increased to 2.13.2.
 
 2005-02-14  Hiroya Murata  <lapis-lazuli@pop06.odn.ne.jp>
index 755d1e0..dc066c9 100644 (file)
 (defvar wl-summary-buffer-mode-line nil)
 (defvar wl-summary-buffer-display-mime-mode 'mime)
 (defvar wl-summary-buffer-display-header-mode 'partial)
-(defvar wl-summary-buffer-event-handler nil)
 
 (defvar wl-thread-indent-level-internal nil)
 (defvar wl-thread-have-younger-brother-str-internal nil)
 (make-variable-buffer-local 'wl-summary-buffer-mode-line)
 (make-variable-buffer-local 'wl-summary-buffer-display-mime-mode)
 (make-variable-buffer-local 'wl-summary-buffer-display-header-mode)
-(make-variable-buffer-local 'wl-summary-buffer-event-handler)
 
 (defvar wl-datevec)
 (defvar wl-thr-indent-string)
@@ -649,16 +647,9 @@ See also variable `wl-use-petname'."
        'nomini frame))))
 
 ;; Handler of event from elmo-folder
-(eval-and-compile
-  (luna-define-class wl-summary-event-handler (elmo-event-handler)
-                    (buffer))
-  (luna-define-internal-accessors 'wl-summary-event-handler))
-
-(luna-define-method elmo-event-handler-flag-changed ((handler
-                                                     wl-summary-event-handler)
-                                                    numbers)
+(defun wl-summary-update-persistent-mark-on-event (buffer numbers)
   (save-excursion
-    (set-buffer (wl-summary-event-handler-buffer-internal handler))
+    (set-buffer buffer)
     (if wl-summary-lazy-update-mark
        (let ((window-list (get-buffer-window-list (current-buffer) 'nomini t))
              invalidate)
@@ -686,38 +677,26 @@ See also variable `wl-use-petname'."
                   (wl-summary-jump-to-msg number))
          (wl-summary-update-persistent-mark number))))))
 
-(luna-define-method elmo-event-handler-cache-changed
-  ((handler wl-summary-event-handler) number)
-  (save-excursion
-    (set-buffer (wl-summary-event-handler-buffer-internal handler))
-    (if wl-summary-lazy-update-mark
-       (let ((window-list (get-buffer-window-list (current-buffer) 'nomini t)))
-         (when (wl-summary-message-visible-p number)
-           (if (catch 'visible
-                 (let ((window-list window-list)
-                       win)
-                   (while (setq win (car window-list))
-                     (when (wl-summary-jump-to-msg number
-                                                   (window-start win)
-                                                   (window-end win))
-                       (throw 'visible t))
-                     (setq window-list (cdr window-list)))))
-               (wl-summary-update-persistent-mark number)
-             (wl-summary-invalidate-persistent-mark)
-             (dolist (win window-list)
-               (wl-summary-validate-persistent-mark
-                (window-start win)
-                (window-end win))))))
-      (when (and (wl-summary-message-visible-p number)
-                (wl-summary-jump-to-msg number))
-       (wl-summary-update-persistent-mark number)))))
+(defun wl-summary-buffer-attach ()
+  (when wl-summary-buffer-elmo-folder
+    (elmo-connect-signal
+     wl-summary-buffer-elmo-folder
+     'flag-changed
+     (current-buffer)
+     (elmo-define-signal-handler (buffer folder numbers)
+       (wl-summary-update-persistent-mark-on-event buffer numbers)))
+    (elmo-connect-signal
+     wl-summary-buffer-elmo-folder
+     'cache-changed
+     (current-buffer)
+     (elmo-define-signal-handler (buffer folder number)
+       (wl-summary-update-persistent-mark-on-event buffer (list number))))))
 
 (defun wl-summary-buffer-detach ()
   (when (and (eq major-mode 'wl-summary-mode)
-            wl-summary-buffer-elmo-folder
-            wl-summary-buffer-event-handler)
-    (elmo-folder-remove-handler wl-summary-buffer-elmo-folder
-                               wl-summary-buffer-event-handler)))
+            wl-summary-buffer-elmo-folder)
+    (elmo-disconnect-signal 'flag-changed (current-buffer))
+    (elmo-disconnect-signal 'cache-changed (current-buffer))))
 
 (defun wl-status-update ()
   (interactive)
@@ -900,11 +879,7 @@ you."
   (setq wl-summary-buffer-persistent
        (wl-folder-persistent-p (elmo-folder-name-internal folder)))
   (elmo-folder-set-persistent-internal folder wl-summary-buffer-persistent)
-  (elmo-folder-add-handler folder
-                          (setq wl-summary-buffer-event-handler
-                                (luna-make-entity
-                                 'wl-summary-event-handler
-                                 :buffer (current-buffer))))
+  (wl-summary-buffer-attach)
   ;; process duplicates.
   (elmo-folder-set-process-duplicates-internal
    folder (cdr (elmo-string-matched-assoc
index 209e08f..6098d77 100644 (file)
--- a/wl/wl.el
+++ b/wl/wl.el
@@ -672,6 +672,7 @@ Entering Plugged mode calls the value of `wl-plugged-mode-hook'."
     (elmo-quit)
     (when wl-use-acap (funcall (symbol-function 'wl-acap-exit)))
     (wl-biff-stop)
+    (elmo-clear-signal-slots)
     (elmo-passwd-alist-clear)
     (run-hooks 'wl-exit-hook)
     (wl-save-status)