Re: Preceding list function

Subject: Re: Preceding list function
From: Norman Walsh <ndw@xxxxxxxxxx>
Date: 08 Aug 2000 07:54:32 -0400
/ Brandon Ibach <bibach@xxxxxxxxxxxxxx> was heard to say:
|    Well, here's a possible solution (untested, mind you).  I know I
| don't have your most recent stylesheets, so I'll just quote the
| relevant function from the ones I have, with the parts that I changed
| commented.

Thanks, Brandon. In considering your solution, I couldn't convince myself
that it handled all of the various nesting cases correctly.

[...]
|    Now... the changes.  By adding orderedlist to the list of gis to
| match in the call to ancestor-member, we can narrow our search to only
| the other lists within the parent orderedlist, if there is one.  Of
| course, we need to start with the parent of the current list, to avoid
| matching the list we're in.

I wasn't, for example, sure that simply parent was looking far enough
back, since we could be nested arbitrarily deep.

Anyway, I decided to just start over. Here's what I came up with, and
it seems to work.

(define (orderedlist-listitem-number listitem)
  ;; return the number of listitem, taking continuation into account
  (let* ((orderedlist (parent listitem))
	 (listitems (select-elements (children orderedlist)
				     (normalize "listitem")))
	 (continue? (equal? (attribute-string (normalize "continuation")
					      orderedlist)
			    (normalize "continues")))

;; If a list is the continuation of a previous list, we must find the
;; list that is continued in order to calculate the starting
;; item number of this list.
;;
;; Of all the lists in this component, only the following are candidates:
;; 1. Lists which precede this list
;; 2. Lists which are not ancestors of this list
;; 3. Lists that do not have ancestors that are lists which precede this one
;;
;; Of the candidates, the last one, in document order, is the preceding
;; list
	 (all-lists (select-elements
		     (descendants (ancestor-member orderedlist
						   (component-element-list)))
		     (normalize "orderedlist")))

	 (cand1     (if continue?
			(let loop ((nl all-lists)
				   (prec (empty-node-list)))
			  (if (node-list-empty? nl)
			      prec
			      (if (node-list=? (node-list-first nl)
					       orderedlist)
				  prec
				  (loop (node-list-rest nl)
					(node-list prec
						   (node-list-first nl))))))
			(empty-node-list)))

	 (cand2     (let loop ((nl cand1)
			       (cand2lists (empty-node-list)))
		      (if (node-list-empty? nl)
			  cand2lists
			  (loop (node-list-rest nl)
				(if (descendant-of? (node-list-first nl)
						    orderedlist)
				    cand2lists
				    (node-list cand2lists
					       (node-list-first nl)))))))

	 ;; now find the last item of cand2 that is not a descendant
	 ;; of some other element of the cand2 list.
	 (preclist  (let loop ((nl (node-list-reverse cand2)))
		      (if (node-list-empty? nl)
			  (empty-node-list)
			  (if (descendant-member-of?
			       (node-list-first nl)
			       (node-list-rest nl))
			      (loop (node-list-rest nl))
			      (node-list-first nl)))))

	 (precitem (if (node-list-empty? preclist)
		       (empty-node-list)
		       (node-list-last (children preclist))))
	 (precitem-number (if (and continue? (not (node-list-empty? precitem)))
			      (orderedlist-listitem-number precitem)
			      0)))

    (+ precitem-number (child-number listitem))))

(define (descendant-member-of? node node-list)
  ;; return true if node is a descedant of any member of node-list
  (let loop ((nl node-list))
    (if (node-list-empty? nl)
	#f
	(if (descendant-of? (node-list-first nl) node)
	    #t
	    (loop (node-list-rest nl))))))


                                        Be seeing you,
                                          norm

-- 
Norman Walsh <ndw@xxxxxxxxxx> | The truest wild beasts live in the most
http://nwalsh.com/            | populous places.--Graci\'an


 DSSSList info and archive:  http://www.mulberrytech.com/dsssl/dssslist


Current Thread