Function: nnvirtual-create-mapping

nnvirtual-create-mapping is a byte-compiled function defined in nnvirtual.el.gz.

Signature

(nnvirtual-create-mapping DONT-CHECK)

Documentation

Build tables to map between component (group, article) to virtual article.

Generate the set of read messages and marks for the virtual group based on the marks on the component groups.

Source Code

;; Defined in /usr/src/emacs/lisp/gnus/nnvirtual.el.gz
(defun nnvirtual-create-mapping (dont-check)
  "Build tables to map between component (group, article) to virtual article.
Generate the set of read messages and marks for the virtual group
based on the marks on the component groups."
  (let ((cnt 0)
	(tot 0)
	(M 0)
	(i 0)
	actives all-unreads all-marks
	active min max size unreads marks
	next-M next-tot
	reads beg)
    ;; Ok, we loop over all component groups and collect a lot of
    ;; information:
    ;; Into actives we place (g size max), where size is max-min+1.
    ;; Into all-unreads we put (g unreads).
    ;; Into all-marks we put (g marks).
    ;; We also increment cnt and tot here, and compute M (max of sizes).
    (mapc (lambda (g)
	    (setq active (or (and dont-check
				  (gnus-active g))
			     (gnus-activate-group g))
		  min (car active)
		  max (cdr active))
	    (when (and active (>= max min) (not (zerop max)))
	      ;; store active information
	      (push (list g (- max min -1) max) actives)
	      ;; collect unread/mark info for later
	      (setq unreads (gnus-list-of-unread-articles g))
	      (setq marks (gnus-info-marks (gnus-get-info g)))
	      (when gnus-use-cache
		(push (cons 'cache
			    (gnus-cache-articles-in-group g))
		      marks))
	      (push (cons g unreads) all-unreads)
	      (push (cons g marks) all-marks)
	      ;; count groups, total #articles, and max size
	      (setq size (- max min -1))
	      (setq cnt (1+ cnt)
		    tot (+ tot size)
		    M (max M size))))
	  nnvirtual-component-groups)

    ;; Number of articles in the virtual group.
    (setq nnvirtual-mapping-len tot)


    ;; We want the actives list sorted by size, to build the tables.
    (setq actives (sort actives (lambda (g1 g2) (< (nth 1 g1) (nth 1 g2)))))

    ;; Build the offset table.  Largest sized groups are at the front.
    (setq nnvirtual-mapping-offsets
	  (vconcat
	   (nreverse
	    (mapcar (lambda (entry)
		      (cons (nth 0 entry)
			    (- (nth 2 entry) M)))
		    actives))))

    ;; Build the mapping table.
    (setq nnvirtual-mapping-table nil)
    (setq actives (mapcar (lambda (entry) (nth 1 entry)) actives))
    (while actives
      (setq size (car actives))
      (setq next-M (- M size))
      (setq next-tot (- tot (* cnt size)))
      ;; make current row in table
      (push (vector M next-M cnt tot (- next-tot cnt))
	    nnvirtual-mapping-table)
      ;; update M and tot
      (setq M next-M)
      (setq tot next-tot)
      ;; subtract the current size from all entries.
      (setq actives (mapcar (lambda (x) (- x size)) actives))
      ;; remove anything that went to 0.
      (while (and actives
		  (= (car actives) 0))
	(pop actives)
	(setq cnt (- cnt 1))))


    ;; Now that the mapping tables are generated, we can convert
    ;; and combine the separate component unreads and marks lists
    ;; into single lists of virtual article numbers.
    (setq unreads (apply #'nnvirtual-merge-sorted-lists
			 (mapcar (lambda (x)
				   (nnvirtual-reverse-map-sequence
				    (car x) (cdr x)))
				 all-unreads)))
    (setq marks (mapcar
		 (lambda (type)
		   (cons (cdr type)
			 (gnus-compress-sequence
			  (apply
			   #'nnvirtual-merge-sorted-lists
			   (mapcar (lambda (x)
				     (nnvirtual-reverse-map-sequence
				      (car x)
				      (cdr (assq (cdr type) (cdr x)))))
				   all-marks)))))
		 gnus-article-mark-lists))

    ;; Remove any empty marks lists, and store.
    (setq nnvirtual-mapping-marks nil)
    (dolist (mark marks)
      (when (cdr mark)
	(push mark nnvirtual-mapping-marks)))

    ;; We need to convert the unreads to reads.  We compress the
    ;; sequence as we go, otherwise it could be huge.
    (while (and (<= (incf i) nnvirtual-mapping-len)
		unreads)
      (if (= i (car unreads))
	  (setq unreads (cdr unreads))
	;; try to get a range.
	(setq beg i)
        (while (and (<= (incf i) nnvirtual-mapping-len)
		    (not (= i (car unreads)))))
	(setq i (- i 1))
	(if (= i beg)
	    (push i reads)
	  (push (cons beg i) reads))
	))
    (when (<= i nnvirtual-mapping-len)
      (if (= i nnvirtual-mapping-len)
	  (push i reads)
	(push (cons i nnvirtual-mapping-len) reads)))

    ;; Store the reads list for later use.
    (setq nnvirtual-mapping-reads (nreverse reads))

    ;; Throw flag to show we changed the info.
    (setq nnvirtual-info-installed nil)
    ))