* gnus-range.el (gnus-inverse-list-range-intersection): Off-by-one
[gnus] / lisp / gnus-range.el
index 5e0dc13..8e3c097 100644 (file)
@@ -1,5 +1,7 @@
 ;;; gnus-range.el --- range and sequence functions for Gnus
-;; Copyright (C) 1996,97,98,99 Free Software Foundation, Inc.
+
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+;;        Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
 
 ;;; List and range functions
 
+(defsubst gnus-range-normalize (range)
+  "Normalize RANGE.
+If RANGE is a single range, return (RANGE). Otherwise, return RANGE."
+  (if (listp (cdr range)) (list range) range))
+
 (defun gnus-last-element (list)
   "Return last element of LIST."
   (while (cdr list)
@@ -318,6 +325,40 @@ modified."
        (setq ranges (cdr ranges)))
       (not not-stop))))
 
+(defun gnus-list-range-intersection (list ranges)
+  "Return a list of numbers in LIST that are members of RANGES.
+LIST is a sorted list."
+  (let (number result)
+    (while (setq number (pop list))
+      (while (and ranges
+                 (if (numberp (car ranges))
+                     (< (car ranges) number)
+                   (< (cdar ranges) number)))
+       (setq ranges (cdr ranges)))
+      (when (and ranges
+                (if (numberp (car ranges))
+                     (= (car ranges) number)
+                   (< number (cdar ranges))))
+       (push number result)))
+    (nreverse result)))
+
+(defun gnus-inverse-list-range-intersection (list ranges)
+  "Return a list of numbers in LIST that are not members of RANGES.
+LIST is a sorted list."
+  (let (number result)
+    (while (setq number (pop list))
+      (while (and ranges
+                 (if (numberp (car ranges))
+                     (< (car ranges) number)
+                   (< (cdar ranges) number)))
+       (setq ranges (cdr ranges)))
+      (when (or (not ranges)
+               (if (numberp (car ranges))
+                   (not (= (car ranges) number))
+                 (not (<= number (cdar ranges)))))
+       (push number result)))
+    (nreverse result)))
+
 (defun gnus-range-length (range)
   "Return the length RANGE would have if uncompressed."
   (length (gnus-uncompress-range range)))
@@ -342,7 +383,7 @@ modified."
        range item selector)
     (while (or item1 item2)
       (setq selector
-           (cond 
+           (cond
             ((null item1) nil)
             ((null item2) t)
             ((and (numberp item1) (numberp item2)) (< item1 item2))
@@ -352,30 +393,30 @@ modified."
       (setq item
            (or
             (let ((tmp1 item) (tmp2 (if selector item1 item2)))
-              (cond 
+              (cond
                ((null tmp1) tmp2)
                ((null tmp2) tmp1)
                ((and (numberp tmp1) (numberp tmp2))
-                (cond 
+                (cond
                  ((eq tmp1 tmp2) tmp1)
                  ((eq (1+ tmp1) tmp2) (cons tmp1 tmp2))
                  ((eq (1+ tmp2) tmp1) (cons tmp2 tmp1))
                  (t nil)))
                ((numberp tmp1)
-                (cond 
+                (cond
                  ((and (>= tmp1 (car tmp2)) (<= tmp1 (cdr tmp2))) tmp2)
                  ((eq (1+ tmp1) (car tmp2)) (cons tmp1 (cdr tmp2)))
                  ((eq (1- tmp1) (cdr tmp2)) (cons (car tmp2) tmp1))
                  (t nil)))
                ((numberp tmp2)
-                (cond 
+                (cond
                  ((and (>= tmp2 (car tmp1)) (<= tmp2 (cdr tmp1))) tmp1)
                  ((eq (1+ tmp2) (car tmp1)) (cons tmp2 (cdr tmp1)))
                  ((eq (1- tmp2) (cdr tmp1)) (cons (car tmp1) tmp2))
                  (t nil)))
                ((< (1+ (cdr tmp1)) (car tmp2)) nil)
                ((< (1+ (cdr tmp2)) (car tmp1)) nil)
-               (t (cons (min (car tmp1) (car tmp2)) 
+               (t (cons (min (car tmp1) (car tmp2))
                         (max (cdr tmp1) (cdr tmp2))))))
             (progn
               (if item (push item range))