This commit was generated by cvs2svn to compensate for changes in r5323,
[elisp/gnus.git-] / lisp / gnus-topic.el
index 249367d..3f2b2af 100644 (file)
@@ -31,6 +31,7 @@
 (require 'gnus)
 (require 'gnus-group)
 (require 'gnus-start)
+(require 'gnus-util)
 
 (defgroup gnus-topic nil
   "Group topics."
@@ -73,6 +74,7 @@ with some simple extensions.
 
 (defvar gnus-topic-active-topology nil)
 (defvar gnus-topic-active-alist nil)
+(defvar gnus-topic-unreads nil)
 
 (defvar gnus-topology-checked-p nil
   "Whether the topology has been checked in this session.")
@@ -108,9 +110,7 @@ with some simple extensions.
 
 (defun gnus-topic-unread (topic)
   "Return the number of unread articles in TOPIC."
-  (or (save-excursion
-       (and (gnus-topic-goto-topic topic)
-            (gnus-group-topic-unread)))
+  (or (cdr (assoc topic gnus-topic-unreads))
       0))
 
 (defun gnus-group-topic-p ()
@@ -166,9 +166,10 @@ with some simple extensions.
     (when result
       (symbol-name result))))
 
-(defun gnus-current-topics ()
-  "Return a list of all current topics, lowest in hierarchy first."
-  (let ((topic (gnus-current-topic))
+(defun gnus-current-topics (&optional topic)
+  "Return a list of all current topics, lowest in hierarchy first.
+If TOPIC, start with that topic."
+  (let ((topic (or topic (gnus-current-topic)))
        topics)
     (while topic
       (push topic topics)
@@ -199,7 +200,8 @@ with some simple extensions.
                              active
                              (- (1+ (cdr active)) (car active))))
              clevel (or (gnus-info-level info)
-                        (if (member group gnus-zombie-list) gnus-level-zombie gnus-level-killed))))
+                        (if (member group gnus-zombie-list)
+                            gnus-level-zombie gnus-level-killed))))
       (and
        unread                          ; nil means that the group is dead.
        (<= clevel level)
@@ -324,27 +326,32 @@ with some simple extensions.
 
 (defun gnus-group-topic-parameters (group)
   "Compute the group parameters for GROUP taking into account inheritance from topics."
-  (let ((params-list (list (gnus-group-get-parameter group)))
-       topics params param out)
+  (let ((params-list (copy-sequence (gnus-group-get-parameter group))))
     (save-excursion
       (gnus-group-goto-group group)
-      (setq topics (gnus-current-topics))
-      (while topics
-       (push (gnus-topic-parameters (pop topics)) params-list))
-      ;; We probably have lots of nil elements here, so
-      ;; we remove them.  Probably faster than doing this "properly".
-      (setq params-list (delq nil params-list))
-      ;; Now we have all the parameters, so we go through them
-      ;; and do inheritance in the obvious way.
-      (while (setq params (pop params-list))
-       (while (setq param (pop params))
-         (when (atom param)
-           (setq param (cons param t)))
-         ;; Override any old versions of this param.
-         (setq out (delq (assq (car param) out) out))
-         (push param out)))
-      ;; Return the resulting parameter list.
-      out)))
+      (nconc params-list
+            (gnus-topic-hierarchical-parameters (gnus-current-topic))))))
+
+(defun gnus-topic-hierarchical-parameters (topic)
+  "Return a topic list computed for TOPIC."
+  (let ((topics (gnus-current-topics topic))
+       params-list param out params)
+    (while topics
+      (push (gnus-topic-parameters (pop topics)) params-list))
+    ;; We probably have lots of nil elements here, so
+    ;; we remove them.  Probably faster than doing this "properly".
+    (setq params-list (delq nil params-list))
+    ;; Now we have all the parameters, so we go through them
+    ;; and do inheritance in the obvious way.
+    (while (setq params (pop params-list))
+      (while (setq param (pop params))
+       (when (atom param)
+         (setq param (cons param t)))
+       ;; Override any old versions of this param.
+       (gnus-pull (car param) out)
+       (push param out)))
+    ;; Return the resulting parameter list.
+    out))
 
 ;;; General utility functions
 
@@ -406,7 +413,13 @@ If LOWEST is non-nil, list all newsgroups of level LOWEST or higher."
 If SILENT, don't insert anything.  Return the number of unread
 articles in the topic and its subtopics."
   (let* ((type (pop topicl))
-        (entries (gnus-topic-find-groups (car type) list-level all lowest))
+        (entries (gnus-topic-find-groups
+                  (car type) list-level
+                  (or all
+                      (cdr (assq 'visible 
+                                 (gnus-topic-hierarchical-parameters
+                                  (car type)))))
+                  lowest))
         (visiblep (and (eq (nth 1 type) 'visible) (not silent)))
         (gnus-group-indentation
          (make-string (* gnus-topic-indent-level level) ? ))
@@ -458,6 +471,7 @@ articles in the topic and its subtopics."
        (car type) visiblep
        (not (eq (nth 2 type) 'hidden))
        level all-entries unread))
+    (gnus-topic-update-unreads (car type) unread)
     (goto-char end)
     unread))
 
@@ -514,6 +528,7 @@ articles in the topic and its subtopics."
         (number-of-groups (length entries))
         (active-topic (eq gnus-topic-alist gnus-topic-active-alist))
         gnus-tmp-header)
+    (gnus-topic-update-unreads name unread)
     (beginning-of-line)
     ;; Insert the text.
     (gnus-add-text-properties
@@ -526,6 +541,11 @@ articles in the topic and its subtopics."
           'gnus-active active-topic
           'gnus-topic-visible visiblep))))
 
+(defun gnus-topic-update-unreads (topic unreads)
+  (setq gnus-topic-unreads (delq (assoc topic gnus-topic-unreads)
+                                gnus-topic-unreads))
+  (push (cons topic unreads) gnus-topic-unreads))
+
 (defun gnus-topic-update-topics-containing-group (group)
   "Update all topics that have GROUP as a member."
   (when (and (eq major-mode 'gnus-group-mode)
@@ -607,7 +627,7 @@ articles in the topic and its subtopics."
         (parent (gnus-topic-parent-topic topic-name))
         (all-entries entries)
         (unread 0)
-        old-unread entry)
+        old-unread entry new-unread)
     (when (gnus-topic-goto-topic (car type))
       ;; Tally all the groups that belong in this topic.
       (if reads
@@ -623,11 +643,14 @@ articles in the topic and its subtopics."
        (car type) (gnus-topic-visible-p)
        (not (eq (nth 2 type) 'hidden))
        (gnus-group-topic-level) all-entries unread)
-      (gnus-delete-line))
+      (gnus-delete-line)
+      (forward-line -1)
+      (setq new-unread (gnus-group-topic-unread)))
     (when parent
       (forward-line -1)
       (gnus-topic-update-topic-line
-       parent (- (or old-unread 0) (or (gnus-group-topic-unread) 0))))
+       parent
+       (- (or old-unread 0) (or new-unread 0))))
     unread))
 
 (defun gnus-topic-group-indentation ()
@@ -890,6 +913,10 @@ articles in the topic and its subtopics."
     "Gp" gnus-topic-edit-parameters
     "#" gnus-topic-mark-topic
     "\M-#" gnus-topic-unmark-topic
+    [tab] gnus-topic-indent
+    [(meta tab)] gnus-topic-unindent
+    "\C-i" gnus-topic-indent
+    "\M-\C-i" gnus-topic-unindent
     gnus-mouse-2 gnus-mouse-pick-topic)
 
   ;; Define a new submap.
@@ -909,7 +936,7 @@ articles in the topic and its subtopics."
     "r" gnus-topic-rename
     "\177" gnus-topic-delete
     [delete] gnus-topic-delete
-    "h" gnus-topic-toggle-display-empty-topics)
+    "H" gnus-topic-toggle-display-empty-topics)
 
   (gnus-define-keys (gnus-topic-sort-map "S" gnus-group-topic-map)
     "s" gnus-topic-sort-groups
@@ -959,7 +986,6 @@ articles in the topic and its subtopics."
        (gnus-topic-make-menu-bar))
       (gnus-set-format 'topic t)
       (gnus-add-minor-mode 'gnus-topic-mode " Topic" gnus-topic-mode-map)
-      (add-hook 'gnus-summary-exit-hook 'gnus-topic-update-topic)
       (add-hook 'gnus-group-catchup-group-hook 'gnus-topic-update-topic)
       (set (make-local-variable 'gnus-group-prepare-function)
           'gnus-group-prepare-topics)
@@ -1253,7 +1279,11 @@ If COPYP, copy the groups instead."
           (read-string (format "Rename %s to: " topic)))))
   ;; Check whether the new name exists.
   (when (gnus-topic-find-topology new-name)
-    (error "Topic '%s' already exists"))
+    (error "Topic '%s' already exists" new-name))
+  ;; "nil" is an invalid name, for reasons I'd rather not go
+  ;; into here.  Trust me.
+  (when (equal new-name "nil")
+    (error "Invalid name: %s" nil))
   ;; Do the renaming.
   (let ((top (gnus-topic-find-topology old-name))
        (entry (assoc old-name gnus-topic-alist)))
@@ -1263,7 +1293,8 @@ If COPYP, copy the groups instead."
       (setcar entry new-name))
     (forward-line -1)
     (gnus-dribble-touch)
-    (gnus-group-list-groups)))
+    (gnus-group-list-groups)
+    (forward-line 1)))
 
 (defun gnus-topic-indent (&optional unindent)
   "Indent a topic -- make it a sub-topic of the previous topic.