mirror of
				https://github.com/smarty-php/smarty.git
				synced 2025-11-04 14:21:36 +01:00 
			
		
		
		
	
		
			
	
	
		
			1858 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			1858 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN">
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<style-sheet>
							 | 
						||
| 
								 | 
							
								<style-specification>
							 | 
						||
| 
								 | 
							
								<style-specification-body>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; $Id$
							 | 
						||
| 
								 | 
							
								;;
							 | 
						||
| 
								 | 
							
								;; This file is part of the Modular DocBook Stylesheet distribution.
							 | 
						||
| 
								 | 
							
								;; See ../README or http://nwalsh.com/docbook/dsssl/
							 | 
						||
| 
								 | 
							
								;;
							 | 
						||
| 
								 | 
							
								;; This file contains a general library of DSSSL functions.
							 | 
						||
| 
								 | 
							
								;;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; If **ANY** change is made to this file, you _MUST_ alter the
							 | 
						||
| 
								 | 
							
								;; following definition:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; REFERENCE Library Version
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define %library-version%
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY version
							 | 
						||
| 
								 | 
							
								  ;; PURP Defines the library version string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Defines the library version string.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  "Modular DocBook Stylesheet Library")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; === Book intro, for dsl2man ==========================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<![CDATA[
							 | 
						||
| 
								 | 
							
								;; DOCINFO
							 | 
						||
| 
								 | 
							
								;; <title>DSSSL Library</title>
							 | 
						||
| 
								 | 
							
								;; <subtitle>Part of the Modular DocBook Stylesheet distribution</subtitle>
							 | 
						||
| 
								 | 
							
								;; <author><firstname>Norman</firstname><surname>Walsh</surname>
							 | 
						||
| 
								 | 
							
								;; </author>
							 | 
						||
| 
								 | 
							
								;; <edition>$Revision$</edition>
							 | 
						||
| 
								 | 
							
								;; <copyright><year>1997</year><year>1998</year><year>1999</year>
							 | 
						||
| 
								 | 
							
								;; <holder>Norman Walsh</holder></copyright>
							 | 
						||
| 
								 | 
							
								;; <legalnotice>
							 | 
						||
| 
								 | 
							
								;; <para>
							 | 
						||
| 
								 | 
							
								;; This software may be distributed under the same terms as Jade:
							 | 
						||
| 
								 | 
							
								;; </para>
							 | 
						||
| 
								 | 
							
								;; <para>
							 | 
						||
| 
								 | 
							
								;; Permission is hereby granted, free of charge, to any person
							 | 
						||
| 
								 | 
							
								;; obtaining a copy of this software and associated documentation
							 | 
						||
| 
								 | 
							
								;; files (the “Software”), to deal in the Software without
							 | 
						||
| 
								 | 
							
								;; restriction, including without limitation the rights to use,
							 | 
						||
| 
								 | 
							
								;; copy, modify, merge, publish, distribute, sublicense, and/or
							 | 
						||
| 
								 | 
							
								;; sell copies of the Software, and to permit persons to whom the
							 | 
						||
| 
								 | 
							
								;; Software is furnished to do so, subject to the following
							 | 
						||
| 
								 | 
							
								;; conditions:
							 | 
						||
| 
								 | 
							
								;; </para>
							 | 
						||
| 
								 | 
							
								;; <para>
							 | 
						||
| 
								 | 
							
								;; The above copyright notice and this permission notice shall be
							 | 
						||
| 
								 | 
							
								;; included in all copies or substantial portions of the Software.
							 | 
						||
| 
								 | 
							
								;; </para>
							 | 
						||
| 
								 | 
							
								;; <para>
							 | 
						||
| 
								 | 
							
								;; Except as contained in this notice, the names of individuals
							 | 
						||
| 
								 | 
							
								;; credited with contribution to this software shall not be used in
							 | 
						||
| 
								 | 
							
								;; advertising or otherwise to promote the sale, use or other
							 | 
						||
| 
								 | 
							
								;; dealings in this Software without prior written authorization
							 | 
						||
| 
								 | 
							
								;; from the individuals in question.
							 | 
						||
| 
								 | 
							
								;; </para>
							 | 
						||
| 
								 | 
							
								;; <para>
							 | 
						||
| 
								 | 
							
								;; Any stylesheet derived from this Software that is publically
							 | 
						||
| 
								 | 
							
								;; distributed will be identified with a different name and the
							 | 
						||
| 
								 | 
							
								;; version strings in any derived Software will be changed so that
							 | 
						||
| 
								 | 
							
								;; no possibility of confusion between the derived package and this
							 | 
						||
| 
								 | 
							
								;; Software will exist.
							 | 
						||
| 
								 | 
							
								;; </para>
							 | 
						||
| 
								 | 
							
								;; </legalnotice>
							 | 
						||
| 
								 | 
							
								;; <legalnotice>
							 | 
						||
| 
								 | 
							
								;; <para>
							 | 
						||
| 
								 | 
							
								;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
							 | 
						||
| 
								 | 
							
								;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
							 | 
						||
| 
								 | 
							
								;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
							 | 
						||
| 
								 | 
							
								;; NONINFRINGEMENT.  IN NO EVENT SHALL NORMAN WALSH OR ANY OTHER
							 | 
						||
| 
								 | 
							
								;; CONTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
							 | 
						||
| 
								 | 
							
								;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
							 | 
						||
| 
								 | 
							
								;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
							 | 
						||
| 
								 | 
							
								;; OTHER DEALINGS IN THE SOFTWARE.
							 | 
						||
| 
								 | 
							
								;; </para>
							 | 
						||
| 
								 | 
							
								;; </legalnotice>
							 | 
						||
| 
								 | 
							
								;; <legalnotice>
							 | 
						||
| 
								 | 
							
								;; <para>Please direct all questions, bug reports, or suggestions for changes
							 | 
						||
| 
								 | 
							
								;; to Norman Walsh, <<literal>ndw@nwalsh.com</literal>>.
							 | 
						||
| 
								 | 
							
								;; </para>
							 | 
						||
| 
								 | 
							
								;; <para>
							 | 
						||
| 
								 | 
							
								;; See <ulink url="http://nwalsh.com/docbook/dsssl/">http://nwalsh.com/docbook/dsssl/</ulink> for more information.</para>
							 | 
						||
| 
								 | 
							
								;; </legalnotice>
							 | 
						||
| 
								 | 
							
								;; /DOCINFO
							 | 
						||
| 
								 | 
							
								]]>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; === Some additional units ============================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define-unit pi (/ 1in 6))
							 | 
						||
| 
								 | 
							
								(define-unit pt (/ 1in 72))
							 | 
						||
| 
								 | 
							
								(define-unit px (/ 1in 96))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; REFERENCE ISO/IEC 10179
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (node-list-reduce nl proc init)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY node-list-reduce
							 | 
						||
| 
								 | 
							
								  ;; PURP Implements node-list-reduce as per ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Implements 'node-list-reduce' as per ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR From ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (node-list-empty? nl)
							 | 
						||
| 
								 | 
							
								      init
							 | 
						||
| 
								 | 
							
								      (node-list-reduce (node-list-rest nl)
							 | 
						||
| 
								 | 
							
								                        proc
							 | 
						||
| 
								 | 
							
								                        (proc init (node-list-first nl)))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (node-list-last nl)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY node-list-last
							 | 
						||
| 
								 | 
							
								  ;; PURP Implements node-list-last as per ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Implements 'node-list-last' as per ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR From ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (node-list-ref nl
							 | 
						||
| 
								 | 
							
										 (- (node-list-length nl) 1)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (node-list-first-element nodelist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY node-list-first-element
							 | 
						||
| 
								 | 
							
								  ;; PURP Return the first element node in a node list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; This function returns the first node in a node list which is
							 | 
						||
| 
								 | 
							
								  ;; an element (as opposed to a PI or anything else that might appear
							 | 
						||
| 
								 | 
							
								  ;; in a node list).
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((nl nodelist))
							 | 
						||
| 
								 | 
							
								    (if (node-list-empty? nl)
							 | 
						||
| 
								 | 
							
									(empty-node-list)
							 | 
						||
| 
								 | 
							
									(if (gi (node-list-first nl))
							 | 
						||
| 
								 | 
							
									    (node-list-first nl)
							 | 
						||
| 
								 | 
							
									    (loop (node-list-rest nl))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (node-list-last-element nodelist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY node-list-last-element
							 | 
						||
| 
								 | 
							
								  ;; PURP Return the last element node in a node list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; This function returns the last node in a node list which is
							 | 
						||
| 
								 | 
							
								  ;; an element (as opposed to a PI or anything else that might appear
							 | 
						||
| 
								 | 
							
								  ;; in a node list).
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((el (empty-node-list)) (nl nodelist))
							 | 
						||
| 
								 | 
							
								    (if (node-list-empty? nl)
							 | 
						||
| 
								 | 
							
									el
							 | 
						||
| 
								 | 
							
									(if (gi (node-list-first nl))
							 | 
						||
| 
								 | 
							
									    (loop (node-list-first nl) (node-list-rest nl))
							 | 
						||
| 
								 | 
							
									    (loop el (node-list-rest nl))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (ipreced nl)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY ipreced
							 | 
						||
| 
								 | 
							
								  ;; PURP Implements ipreced as per ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Implements 'ipreced' as per ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR From ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (node-list-map (lambda (snl)
							 | 
						||
| 
								 | 
							
										 (let loop ((prev (empty-node-list))
							 | 
						||
| 
								 | 
							
											    (rest (siblings snl)))
							 | 
						||
| 
								 | 
							
										   (cond ((node-list-empty? rest)
							 | 
						||
| 
								 | 
							
											  (empty-node-list))
							 | 
						||
| 
								 | 
							
											 ((node-list=? (node-list-first rest) snl)
							 | 
						||
| 
								 | 
							
											  prev)
							 | 
						||
| 
								 | 
							
											 (else
							 | 
						||
| 
								 | 
							
											  (loop (node-list-first rest)
							 | 
						||
| 
								 | 
							
												(node-list-rest rest))))))
							 | 
						||
| 
								 | 
							
										 nl))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (ifollow nl)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY ifollow
							 | 
						||
| 
								 | 
							
								  ;; PURP Implements ifollow as per ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Implements 'ifollow' as per ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR From ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (node-list-map (lambda (snl)
							 | 
						||
| 
								 | 
							
										   (let loop ((rest (siblings snl)))
							 | 
						||
| 
								 | 
							
										     (cond ((node-list-empty? rest)
							 | 
						||
| 
								 | 
							
											    (empty-node-list))
							 | 
						||
| 
								 | 
							
											   ((node-list=? (node-list-first rest) snl)
							 | 
						||
| 
								 | 
							
											    (node-list-first (node-list-rest rest)))
							 | 
						||
| 
								 | 
							
											   (else
							 | 
						||
| 
								 | 
							
											    (loop (node-list-rest rest))))))
							 | 
						||
| 
								 | 
							
										 nl))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (siblings snl)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY siblings
							 | 
						||
| 
								 | 
							
								  ;; PURP Implements siblings as per ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Implements 'siblings' as per ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR From ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (children (parent snl)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (string->list str)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY string-2-list
							 | 
						||
| 
								 | 
							
								  ;; PURP Converts a string into a list of characters.
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Implements 'string->list' as per ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; (clause 8.5.9.9).
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR David Megginson
							 | 
						||
| 
								 | 
							
								  ;; EMAIL dmeggins@uottawa.ca
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((chars '())
							 | 
						||
| 
								 | 
							
									     (k (- (string-length str) 1)))
							 | 
						||
| 
								 | 
							
								    (if (< k 0)
							 | 
						||
| 
								 | 
							
									chars
							 | 
						||
| 
								 | 
							
									(loop (cons (string-ref str k) chars) (- k 1)))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (list->string chars)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY list-2-string
							 | 
						||
| 
								 | 
							
								  ;; PURP Converts a list of characters into a string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Implements 'list->string' as per ISO/IEC 10179:1996
							 | 
						||
| 
								 | 
							
								  ;; (clause 8.5.9.9).
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR David Megginson
							 | 
						||
| 
								 | 
							
								  ;; EMAIL dmeggins@uottawa.ca
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((cl chars)
							 | 
						||
| 
								 | 
							
									     (str ""))
							 | 
						||
| 
								 | 
							
								    (if (null? cl)
							 | 
						||
| 
								 | 
							
									str
							 | 
						||
| 
								 | 
							
									(loop (cdr cl)
							 | 
						||
| 
								 | 
							
									      (string-append str (string (car cl)))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (map f #!rest xs)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY map
							 | 
						||
| 
								 | 
							
								  ;; PURP Implements map
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Implements map
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR From Mulberry Tech. site (need better attribution)
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let ((map1 (lambda (f xs)           ; bootstrap version for unary F
							 | 
						||
| 
								 | 
							
										(let loop ((xs xs))
							 | 
						||
| 
								 | 
							
										  (if (null? xs)
							 | 
						||
| 
								 | 
							
										      '()
							 | 
						||
| 
								 | 
							
										      (cons (f (car xs))
							 | 
						||
| 
								 | 
							
											    (loop (cdr xs))))))))
							 | 
						||
| 
								 | 
							
								    (cond ((null? xs)
							 | 
						||
| 
								 | 
							
									   '())
							 | 
						||
| 
								 | 
							
									  ((null? (cdr xs))
							 | 
						||
| 
								 | 
							
									   (map1 f (car xs)))
							 | 
						||
| 
								 | 
							
									  (else
							 | 
						||
| 
								 | 
							
									   (let loop ((xs xs))
							 | 
						||
| 
								 | 
							
									     (if (null? (car xs))
							 | 
						||
| 
								 | 
							
										 '()
							 | 
						||
| 
								 | 
							
										 (cons (apply f (map1 car xs))
							 | 
						||
| 
								 | 
							
										       (loop (map1 cdr xs)))))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (absolute-child-number #!optional (nd (current-node)))
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY absolute-child-number
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns the absolute child number of the specified node
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the child number, regardless of gi, of 'snl' within its
							 | 
						||
| 
								 | 
							
								  ;; parent.
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; Isn't there a better way to get this?
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG snl
							 | 
						||
| 
								 | 
							
								  ;; The node (singleton node list) whose child number is desired.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (+ (node-list-length (preced nd)) 1))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; REFERENCE Debug
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (my-debug x #!optional return-value)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY my-debug
							 | 
						||
| 
								 | 
							
								  ;; PURP A debugging function more helpful than (debug)
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; A version of debug that tries to print information more helpful
							 | 
						||
| 
								 | 
							
								  ;; than "unknown object ...".  Will need extending for any further
							 | 
						||
| 
								 | 
							
								  ;; types added to Jade which don't have useful print methods.
							 | 
						||
| 
								 | 
							
								  ;; (Should yield more information extracted from each type.)
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG x
							 | 
						||
| 
								 | 
							
								  ;; The object about which debugging information is desired.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR Tony Graham
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let ((msg (debug (cond ((node-list? x)
							 | 
						||
| 
								 | 
							
											   (if (node-list-empty? x)
							 | 
						||
| 
								 | 
							
											       (list 'empty-node-list x)
							 | 
						||
| 
								 | 
							
											       (list (if (named-node-list? x)
							 | 
						||
| 
								 | 
							
													 'named-node-list
							 | 
						||
| 
								 | 
							
													 'node-list)
							 | 
						||
| 
								 | 
							
												     (node-list-length x) x)))
							 | 
						||
| 
								 | 
							
											  ((sosofo? x)
							 | 
						||
| 
								 | 
							
											   (list 'sosofo x))
							 | 
						||
| 
								 | 
							
											  ((procedure? x)
							 | 
						||
| 
								 | 
							
											   (list 'procedure x))
							 | 
						||
| 
								 | 
							
											  ((style? x)
							 | 
						||
| 
								 | 
							
											   (list 'style x))
							 | 
						||
| 
								 | 
							
											  ((address? x)
							 | 
						||
| 
								 | 
							
											   (list 'address x))
							 | 
						||
| 
								 | 
							
											  ((color? x)
							 | 
						||
| 
								 | 
							
											   (list 'color x))
							 | 
						||
| 
								 | 
							
											  ((color-space? x)
							 | 
						||
| 
								 | 
							
											   (list 'color-space x))
							 | 
						||
| 
								 | 
							
											  ((display-space? x)
							 | 
						||
| 
								 | 
							
											   (list 'display-space x))
							 | 
						||
| 
								 | 
							
											  ((inline-space? x)
							 | 
						||
| 
								 | 
							
											   (list 'inline-space x))
							 | 
						||
| 
								 | 
							
											  ((glyph-id? x)
							 | 
						||
| 
								 | 
							
											   (list 'glyph-id x))
							 | 
						||
| 
								 | 
							
											  ((glyph-subst-table? x)
							 | 
						||
| 
								 | 
							
											   (list 'glyph-subst-table x))
							 | 
						||
| 
								 | 
							
											  (else x)))))
							 | 
						||
| 
								 | 
							
								    x))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; REFERENCE Miscellaneous
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (string-with-space string #!optional (space " ")) 
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY string-with-space
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns string with a space appended or the empty string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; If 'string' is not the empty string, returns 'string' with a
							 | 
						||
| 
								 | 
							
								  ;; 'space' appended.  If 'string' is empty, or is not a '(string?)',
							 | 
						||
| 
								 | 
							
								  ;; returns 'string' unmodified.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG 'string'
							 | 
						||
| 
								 | 
							
								  ;; The string onto which a space should be appended.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'space' o
							 | 
						||
| 
								 | 
							
								  ;; If specified, the space to append.  Defaults to a single space.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (string? string)
							 | 
						||
| 
								 | 
							
								      (if (equal? string "")
							 | 
						||
| 
								 | 
							
									  string
							 | 
						||
| 
								 | 
							
									  (string-append string space))
							 | 
						||
| 
								 | 
							
								      string))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (split str #!optional (whitespace '(#\space)))
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY split
							 | 
						||
| 
								 | 
							
								  ;; PURP Splits string at whitespace and returns the resulting list of tokens
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Given a string containing delimited tokens, return a list
							 | 
						||
| 
								 | 
							
								  ;; of the tokens in string form.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG 'str'
							 | 
						||
| 
								 | 
							
								  ;; The string to split.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'whitespace' o
							 | 
						||
| 
								 | 
							
								  ;; A list of characters that should
							 | 
						||
| 
								 | 
							
								  ;; be treated as whitespace.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR David Megginson
							 | 
						||
| 
								 | 
							
								  ;; EMAIL dmeggins@uottawa.ca
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((characters (string->list str)) ; Top-level recursive loop.
							 | 
						||
| 
								 | 
							
									     (current-word '())
							 | 
						||
| 
								 | 
							
									     (tokens '()))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ; If there are no characters left,
							 | 
						||
| 
								 | 
							
								    ; then we're done!
							 | 
						||
| 
								 | 
							
								    (cond ((null? characters)
							 | 
						||
| 
								 | 
							
									   ; Is there a token in progress?
							 | 
						||
| 
								 | 
							
									   (if (null? current-word)
							 | 
						||
| 
								 | 
							
									       (reverse tokens)
							 | 
						||
| 
								 | 
							
									       (reverse (cons (list->string (reverse current-word))
							 | 
						||
| 
								 | 
							
											      tokens))))
							 | 
						||
| 
								 | 
							
									  ; If there are characters left,
							 | 
						||
| 
								 | 
							
									  ; then keep going.
							 | 
						||
| 
								 | 
							
									  (#t
							 | 
						||
| 
								 | 
							
									   (let ((c (car characters))
							 | 
						||
| 
								 | 
							
										 (rest (cdr characters)))
							 | 
						||
| 
								 | 
							
									     ; Are we reading a space?
							 | 
						||
| 
								 | 
							
									     (cond ((member c whitespace)
							 | 
						||
| 
								 | 
							
										    (if (null? current-word)
							 | 
						||
| 
								 | 
							
											(loop rest '() tokens)
							 | 
						||
| 
								 | 
							
											(loop rest
							 | 
						||
| 
								 | 
							
											      '()
							 | 
						||
| 
								 | 
							
											      (cons (list->string (reverse current-word))
							 | 
						||
| 
								 | 
							
												    tokens))))
							 | 
						||
| 
								 | 
							
										   ; We are reading a non-space
							 | 
						||
| 
								 | 
							
										   (#t
							 | 
						||
| 
								 | 
							
										    (loop rest (cons c current-word) tokens))))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (strip str #!optional (stripchars '(#\space #\&#RE #\U-0009)))
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY strip
							 | 
						||
| 
								 | 
							
								  ;; PURP Strip leading and trailing characters off of a string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Strips leading and trailing characters in the 'stripchars' list
							 | 
						||
| 
								 | 
							
								  ;; off of a string and returns the stripped string.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG 'str'
							 | 
						||
| 
								 | 
							
								  ;; The string to strip
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'stripchars' o
							 | 
						||
| 
								 | 
							
								  ;; A list of characters that should
							 | 
						||
| 
								 | 
							
								  ;; be stripped.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let* ((startpos (let loop ((count 0))
							 | 
						||
| 
								 | 
							
										     (if (>= count (string-length str))
							 | 
						||
| 
								 | 
							
											 (string-length str)
							 | 
						||
| 
								 | 
							
											 (if (member (string-ref str count) stripchars)
							 | 
						||
| 
								 | 
							
											     (loop (+ count 1))
							 | 
						||
| 
								 | 
							
											     count))))
							 | 
						||
| 
								 | 
							
									 (tailstr  (substring str startpos (string-length str)))
							 | 
						||
| 
								 | 
							
									 (endpos   (let loop ((count (- (string-length tailstr) 1)))
							 | 
						||
| 
								 | 
							
										     (if (< count 1)
							 | 
						||
| 
								 | 
							
											 0
							 | 
						||
| 
								 | 
							
											 (if (member (string-ref tailstr count) stripchars)
							 | 
						||
| 
								 | 
							
											     (loop (- count 1))
							 | 
						||
| 
								 | 
							
											     count)))))
							 | 
						||
| 
								 | 
							
								    (if (or (< endpos 0)
							 | 
						||
| 
								 | 
							
									    (string=? tailstr ""))
							 | 
						||
| 
								 | 
							
									""
							 | 
						||
| 
								 | 
							
									(substring tailstr 0 (+ endpos 1)))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (join slist #!optional (space " "))
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY join
							 | 
						||
| 
								 | 
							
								  ;; PURP Joins a list of strings together
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Given a list of strings and a space string, returns the string
							 | 
						||
| 
								 | 
							
								  ;; that results from joining all the strings in the list together,
							 | 
						||
| 
								 | 
							
								  ;; separated by space.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG 'slist'
							 | 
						||
| 
								 | 
							
								  ;; The list of strings.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'space' o
							 | 
						||
| 
								 | 
							
								  ;; The string to place between each member of the list.  Defaults to
							 | 
						||
| 
								 | 
							
								  ;; a single space.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR David Carlisle
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (letrec ((loop (lambda (l result)
							 | 
						||
| 
								 | 
							
										   (if (null? l) 
							 | 
						||
| 
								 | 
							
										       result
							 | 
						||
| 
								 | 
							
										       (loop (cdr l) (cons space (cons (car l) result)))))))
							 | 
						||
| 
								 | 
							
								    (if (null? slist)
							 | 
						||
| 
								 | 
							
									""
							 | 
						||
| 
								 | 
							
									(apply string-append (cons (car slist) 
							 | 
						||
| 
								 | 
							
												   (loop (reverse (cdr slist)) '() ))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (pad-string string length padchar)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY pad-string
							 | 
						||
| 
								 | 
							
								  ;; PURP Pads a string, in front, to the specified length
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns 'string', padded in front with 'padchar' to at least 'length'
							 | 
						||
| 
								 | 
							
								  ;; Returns 'string' unmodified if 'string' is not a '(string?)',
							 | 
						||
| 
								 | 
							
								  ;; 'padchar' is not a '(string?)', 'padchar' is the empty string, or if
							 | 
						||
| 
								 | 
							
								  ;; 'string' is already greater than or equal to 'length' in length.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG 'string'
							 | 
						||
| 
								 | 
							
								  ;; The string to pad.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'length'
							 | 
						||
| 
								 | 
							
								  ;; The desired length.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'padchar'
							 | 
						||
| 
								 | 
							
								  ;; The character (string, actually) to use as padding.  If 'padchar' is
							 | 
						||
| 
								 | 
							
								  ;; longer than 1 character, the resulting string may be longer than
							 | 
						||
| 
								 | 
							
								  ;; 'length' when returned.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (and (string? string) 
							 | 
						||
| 
								 | 
							
									   (string? padchar) 
							 | 
						||
| 
								 | 
							
									   (> (string-length padchar) 0))
							 | 
						||
| 
								 | 
							
								      (let loop ((s string) (count (- length (string-length string))))
							 | 
						||
| 
								 | 
							
									(if (<= count 0)
							 | 
						||
| 
								 | 
							
									    s
							 | 
						||
| 
								 | 
							
									    (loop (string-append padchar s) 
							 | 
						||
| 
								 | 
							
										  (- count (string-length padchar)))))
							 | 
						||
| 
								 | 
							
								      string))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (match-split string target)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY match-split
							 | 
						||
| 
								 | 
							
								  ;; PURP Splits string at target and returns the resulting list of tokens
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Splits string at every occurance of target and returns the result
							 | 
						||
| 
								 | 
							
								  ;; as a list.  Note that 'match-split' returns the occurances of 'target'
							 | 
						||
| 
								 | 
							
								  ;; in the list of tokens.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG 'string'
							 | 
						||
| 
								 | 
							
								  ;; The string to split.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'target'
							 | 
						||
| 
								 | 
							
								  ;; The string which is a delimiter between tokens
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; '"this is a test"' split at '"is"' returns
							 | 
						||
| 
								 | 
							
								  ;; '("th" "is" " " "is" " a test")'
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (string? string)
							 | 
						||
| 
								 | 
							
								      (let loop ((result '()) (current "") (rest string))
							 | 
						||
| 
								 | 
							
									(if (< (string-length rest) (string-length target))
							 | 
						||
| 
								 | 
							
									    (append result (if (equal? (string-append current rest) "")
							 | 
						||
| 
								 | 
							
											       '()
							 | 
						||
| 
								 | 
							
											       (list (string-append current rest))))
							 | 
						||
| 
								 | 
							
									    (if (equal? target (substring rest 0 (string-length target)))
							 | 
						||
| 
								 | 
							
										(loop (append result 
							 | 
						||
| 
								 | 
							
											      (if (equal? current "")
							 | 
						||
| 
								 | 
							
												  '()
							 | 
						||
| 
								 | 
							
												  (list current))
							 | 
						||
| 
								 | 
							
											      (list target))
							 | 
						||
| 
								 | 
							
										      ""
							 | 
						||
| 
								 | 
							
										      (substring rest (string-length target) 
							 | 
						||
| 
								 | 
							
												 (string-length rest)))
							 | 
						||
| 
								 | 
							
										(loop result
							 | 
						||
| 
								 | 
							
										      (string-append current (substring rest 0 1))
							 | 
						||
| 
								 | 
							
										      (substring rest 1 (string-length rest))))))
							 | 
						||
| 
								 | 
							
								      (list string)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (match-split-string-list string-list target)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY match-split-string-list
							 | 
						||
| 
								 | 
							
								  ;; PURP Splits each string in a list of strings and returns the concatenated result list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Splits each string in 'string-list' at 'target' with '(match-split)',
							 | 
						||
| 
								 | 
							
								  ;; concatenates the results, and returns a single list of tokens.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG string-list
							 | 
						||
| 
								 | 
							
								  ;; The list of strings to split.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG target
							 | 
						||
| 
								 | 
							
								  ;; The string which is a delimiter between tokens.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((result '()) (sl string-list))
							 | 
						||
| 
								 | 
							
								    (if (null? sl)
							 | 
						||
| 
								 | 
							
									result
							 | 
						||
| 
								 | 
							
									(loop (append result (match-split (car sl) target))
							 | 
						||
| 
								 | 
							
									      (cdr sl)))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (match-split-list string target-list)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY match-split-list
							 | 
						||
| 
								 | 
							
								  ;; PURP Splits a string at a list of targets and returns the resulting list of tokens
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Splits 'string' at every target in 'target-list' with '(match-split)',
							 | 
						||
| 
								 | 
							
								  ;; returning the whole collection of tokens as a list.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG string
							 | 
						||
| 
								 | 
							
								  ;; The string to split.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG target-list
							 | 
						||
| 
								 | 
							
								  ;; A list of target strings which are the delimters between tokens.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((result (list string)) (tlist target-list))
							 | 
						||
| 
								 | 
							
								    (if (null? tlist)
							 | 
						||
| 
								 | 
							
									result
							 | 
						||
| 
								 | 
							
									(loop (match-split-string-list result (car tlist))
							 | 
						||
| 
								 | 
							
									      (cdr tlist)))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (assoc-objs alist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY assoc-objs
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns a list of the objects in an associative list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns a list of the objects in an associative list.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG alist
							 | 
						||
| 
								 | 
							
								  ;; The associative list. An associative list is a list of lists
							 | 
						||
| 
								 | 
							
								  ;; where each interior list is a pair of elements.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; '(assoc-objs (("a" "b") ("c" "d")))' returns '("a" "c")'
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((result '()) (al alist))
							 | 
						||
| 
								 | 
							
								    (if (null? al)
							 | 
						||
| 
								 | 
							
									result
							 | 
						||
| 
								 | 
							
									(loop (append result (list (car (car al)))) (cdr al)))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (assoc obj alist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY assoc
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns the association of an object in an associative list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Given an associative list, returns the pair that has 'obj' as a 'car'
							 | 
						||
| 
								 | 
							
								  ;; or '#f' if no such pair exists.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG obj
							 | 
						||
| 
								 | 
							
								  ;; The associative key to locate.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG alist
							 | 
						||
| 
								 | 
							
								  ;; The associative list.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; '(assoc "a" (("a" "b") ("c" "d")))' returns  '("a" "b")'
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((al alist))
							 | 
						||
| 
								 | 
							
								    (if (null? al)
							 | 
						||
| 
								 | 
							
									#f
							 | 
						||
| 
								 | 
							
									(if (equal? obj (car (car al)))
							 | 
						||
| 
								 | 
							
									    (car al)
							 | 
						||
| 
								 | 
							
									    (loop (cdr al))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (match-substitute-sosofo string assoc-list)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY match-substitute-sosofo
							 | 
						||
| 
								 | 
							
								  ;; PURP Return matching sosofo from associative list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Given a string and an associative list of strings and sosofos,
							 | 
						||
| 
								 | 
							
								  ;; return the sosofo of the matching string, or return the literal
							 | 
						||
| 
								 | 
							
								  ;; string as a sosofo.
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; (This function is used for a particular task in the DocBook stylesheets.
							 | 
						||
| 
								 | 
							
								  ;; It may not be particularly general, but it's in 'dblib.dsl' because
							 | 
						||
| 
								 | 
							
								  ;; there is nothing DTD-specific about it.)
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (assoc string assoc-list)
							 | 
						||
| 
								 | 
							
								      (car (cdr (assoc string assoc-list)))
							 | 
						||
| 
								 | 
							
								      (literal string)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (string-list-sosofo string-list assoc-list)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY string-list-sosofo
							 | 
						||
| 
								 | 
							
								  ;; PURP Build sosofo from a list of strings and an associative list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Take a list of strings and an associative list that maps strings
							 | 
						||
| 
								 | 
							
								  ;; to sosofos and return an appended sosofo.
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; (This function is used for a particular task in the DocBook stylesheets.
							 | 
						||
| 
								 | 
							
								  ;; It may not be particularly general, but it's in 'dblib.dsl' because
							 | 
						||
| 
								 | 
							
								  ;; there is nothing DTD-specific about it.)
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; Given the string list '("what is " "1" " " "+" " " "1")'
							 | 
						||
| 
								 | 
							
								  ;; and the associative list 
							 | 
						||
| 
								 | 
							
								  ;; '(("1" (literal "one")) ("2" (literal "two")) ("+" (literal "plus")))',
							 | 
						||
| 
								 | 
							
								  ;; '(string-list-sosofo)' returns the sequence of sosofos
							 | 
						||
| 
								 | 
							
								  ;; equivalent to '(literal "what is one plus one")'.
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (null? string-list)
							 | 
						||
| 
								 | 
							
								      (empty-sosofo)
							 | 
						||
| 
								 | 
							
								      (sosofo-append (match-substitute-sosofo (car string-list) assoc-list)
							 | 
						||
| 
								 | 
							
										     (string-list-sosofo (cdr string-list) assoc-list))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (repl-substring? string target pos)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY repl-substring-p
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns true if the specified substring can be replaced
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns '#t' if 'target' occurs at 'pos' in 'string'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let* ((could-match (<= (+ pos (string-length target)) 
							 | 
						||
| 
								 | 
							
											 (string-length string)))
							 | 
						||
| 
								 | 
							
									 (match (if could-match 
							 | 
						||
| 
								 | 
							
										    (substring string pos (+ pos (string-length target))) "")))
							 | 
						||
| 
								 | 
							
								    (and could-match (string=? match target))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (repl-substring string target repl pos)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY repl-substring
							 | 
						||
| 
								 | 
							
								  ;; PURP Replace substring in a string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Replaces 'target' with 'repl' in 'string' at 'pos'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let ((matches (repl-substring? string target pos)))
							 | 
						||
| 
								 | 
							
								    (if matches
							 | 
						||
| 
								 | 
							
									(string-append
							 | 
						||
| 
								 | 
							
									 (substring string 0 pos)
							 | 
						||
| 
								 | 
							
									 repl
							 | 
						||
| 
								 | 
							
									 (substring string 
							 | 
						||
| 
								 | 
							
										    (+ pos (string-length target)) 
							 | 
						||
| 
								 | 
							
										    (string-length string)))
							 | 
						||
| 
								 | 
							
									string)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (repl-substring-list? string replace-list pos)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY repl-substring-list-p
							 | 
						||
| 
								 | 
							
								  ;; PURP Perform repl-substring? with a list of target/replacement pairs
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns '#t' if any target in 'replace-list' occurs at 'pos' in 'string'.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG 'string'
							 | 
						||
| 
								 | 
							
								  ;; The string in which replacement should be tested.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'replace-list'
							 | 
						||
| 
								 | 
							
								  ;; A list of target/replacement pairs.  This list is just a list of
							 | 
						||
| 
								 | 
							
								  ;; strings, treated as pairs.  For example, '("was" "x" "is" "y")'.
							 | 
						||
| 
								 | 
							
								  ;; In this example, 'was' may be replaced by 'x' and 'is' may be
							 | 
						||
| 
								 | 
							
								  ;; replaced by 'y'.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'pos'
							 | 
						||
| 
								 | 
							
								  ;; The location within 'string' where the test will occur.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; '(repl-substring-list? "this is it" ("was" "x" "is" "y") 2)'
							 | 
						||
| 
								 | 
							
								  ;; returns '#t': "is" could be replaced by "y".
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((list replace-list))
							 | 
						||
| 
								 | 
							
								    (let ((target (car list))
							 | 
						||
| 
								 | 
							
									  (repl   (car (cdr list)))
							 | 
						||
| 
								 | 
							
									  (rest   (cdr (cdr list))))
							 | 
						||
| 
								 | 
							
								      (if (repl-substring? string target pos)
							 | 
						||
| 
								 | 
							
									  #t
							 | 
						||
| 
								 | 
							
									  (if (null? rest)
							 | 
						||
| 
								 | 
							
									      #f
							 | 
						||
| 
								 | 
							
									      (loop rest))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (repl-substring-list-target string replace-list pos)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY repl-substring-list-target
							 | 
						||
| 
								 | 
							
								  ;; PURP Return the target that matches in a string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the target in 'replace-list' that matches in 'string' at 'pos'
							 | 
						||
| 
								 | 
							
								  ;; See also 'repl-substring-list?'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((list replace-list))
							 | 
						||
| 
								 | 
							
								    (let ((target (car list))
							 | 
						||
| 
								 | 
							
									  (repl   (car (cdr list)))
							 | 
						||
| 
								 | 
							
									  (rest   (cdr (cdr list))))
							 | 
						||
| 
								 | 
							
								      (if (repl-substring? string target pos)
							 | 
						||
| 
								 | 
							
									  target
							 | 
						||
| 
								 | 
							
									  (if (null? rest)
							 | 
						||
| 
								 | 
							
									      #f
							 | 
						||
| 
								 | 
							
									      (loop rest))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (repl-substring-list-repl string replace-list pos)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY repl-substring-list-repl
							 | 
						||
| 
								 | 
							
								  ;; PURP Return the replacement that would be used in the string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the replacement in 'replace-list' that would be used for the
							 | 
						||
| 
								 | 
							
								  ;; target that matches in 'string' at 'pos'
							 | 
						||
| 
								 | 
							
								  ;; See also 'repl-substring-list?'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((list replace-list))
							 | 
						||
| 
								 | 
							
								    (let ((target (car list))
							 | 
						||
| 
								 | 
							
									  (repl   (car (cdr list)))
							 | 
						||
| 
								 | 
							
									  (rest   (cdr (cdr list))))
							 | 
						||
| 
								 | 
							
								      (if (repl-substring? string target pos)
							 | 
						||
| 
								 | 
							
									  repl
							 | 
						||
| 
								 | 
							
									  (if (null? rest)
							 | 
						||
| 
								 | 
							
									      #f
							 | 
						||
| 
								 | 
							
									      (loop rest))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (repl-substring-list string replace-list pos)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY repl-substring-list
							 | 
						||
| 
								 | 
							
								  ;; PURP Replace the first target in the replacement list that matches
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Replaces the first target in 'replace-list' that matches in 'string'
							 | 
						||
| 
								 | 
							
								  ;; at 'pos' with its replacement.
							 | 
						||
| 
								 | 
							
								  ;; See also 'repl-substring-list?'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (repl-substring-list? string replace-list pos)
							 | 
						||
| 
								 | 
							
								      (let ((target (repl-substring-list-target string replace-list pos))
							 | 
						||
| 
								 | 
							
									    (repl   (repl-substring-list-repl string replace-list pos)))
							 | 
						||
| 
								 | 
							
									(repl-substring string target repl pos))
							 | 
						||
| 
								 | 
							
								      string))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (string-replace string target repl)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY string-replace
							 | 
						||
| 
								 | 
							
								  ;; PURP Replace all occurances of a target substring in a string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Replaces all occurances of 'target' in 'string' with 'repl'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((str string) (pos 0))
							 | 
						||
| 
								 | 
							
								    (if (>= pos (string-length str))
							 | 
						||
| 
								 | 
							
									str
							 | 
						||
| 
								 | 
							
									(loop (repl-substring str target repl pos) 
							 | 
						||
| 
								 | 
							
									      (if (repl-substring? str target pos)
							 | 
						||
| 
								 | 
							
										  (+ (string-length repl) pos)
							 | 
						||
| 
								 | 
							
										  (+ 1 pos))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (string-replace-list string replace-list)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY string-replace-list
							 | 
						||
| 
								 | 
							
								  ;; PURP Replace a list of target substrings in a string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Replaces, in 'string', all occurances of each target in
							 | 
						||
| 
								 | 
							
								  ;; 'replace-list' with its replacement.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((str string) (pos 0))
							 | 
						||
| 
								 | 
							
								    (if (>= pos (string-length str))
							 | 
						||
| 
								 | 
							
									str
							 | 
						||
| 
								 | 
							
									(loop (repl-substring-list str replace-list pos) 
							 | 
						||
| 
								 | 
							
									      (if (repl-substring-list? str replace-list pos)
							 | 
						||
| 
								 | 
							
										  (+ (string-length 
							 | 
						||
| 
								 | 
							
										      (repl-substring-list-repl str replace-list pos)) 
							 | 
						||
| 
								 | 
							
										     pos)
							 | 
						||
| 
								 | 
							
										  (+ 1 pos))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (ancestor-member nd gilist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY ancestor-member
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns the first ancestor in a list of GIs
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the first ancestor of 'nd' whose GI that is a member of 'gilist'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (node-list-empty? nd)
							 | 
						||
| 
								 | 
							
								      (empty-node-list)
							 | 
						||
| 
								 | 
							
								      (if (member (gi nd) gilist)
							 | 
						||
| 
								 | 
							
									  nd
							 | 
						||
| 
								 | 
							
									  (ancestor-member (parent nd) gilist))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (has-ancestor-member? nd gilist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY has-ancestor-member-p
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns true if the specified node has one of a set of GIs as an ancestor
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns '#t' if 'nd' has an ancestor whose GI is a member of 'gilist'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (not (node-list-empty? (ancestor-member nd gilist))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (descendant-of? ancestor child)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY descendant-of-p
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns true if the child is some descendant of the specified node
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns '#t' if 'child' is a descendant of 'ancestor'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((c child))
							 | 
						||
| 
								 | 
							
								    (if (node-list-empty? c)
							 | 
						||
| 
								 | 
							
									#f
							 | 
						||
| 
								 | 
							
									(if (node-list=? ancestor c)
							 | 
						||
| 
								 | 
							
									    #t
							 | 
						||
| 
								 | 
							
									    (loop (parent c))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (expand-children nodelist gilist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY expand-children
							 | 
						||
| 
								 | 
							
								  ;; PURP Expand selected nodes in a node list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Given a node-list, 'expand-children' replaces all of the members
							 | 
						||
| 
								 | 
							
								  ;; of the node-list whose GIs are members of 'gilist' with 
							 | 
						||
| 
								 | 
							
								  ;; '(children)'.
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; This function can be used to selectively 
							 | 
						||
| 
								 | 
							
								  ;; flatten the hierarchy of a document.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; Suppose that the node list is '(BOOKINFO PREFACE PART APPENDIX)'.
							 | 
						||
| 
								 | 
							
								  ;; '(expand-children nl ("PART"))' might return
							 | 
						||
| 
								 | 
							
								  ;; '(BOOKINFO PREFACE CHAPTER CHAPTER APPENDIX)'.
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((nl nodelist) (result (empty-node-list)))
							 | 
						||
| 
								 | 
							
								    (if (node-list-empty? nl)
							 | 
						||
| 
								 | 
							
									result
							 | 
						||
| 
								 | 
							
									(if (member (gi (node-list-first nl)) gilist)
							 | 
						||
| 
								 | 
							
									    (loop (node-list-rest nl) 
							 | 
						||
| 
								 | 
							
										  (node-list result (children (node-list-first nl))))
							 | 
						||
| 
								 | 
							
									    (loop (node-list-rest nl)
							 | 
						||
| 
								 | 
							
										  (node-list result (node-list-first nl)))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (directory-depth pathname)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY directory-depth
							 | 
						||
| 
								 | 
							
								  ;; PURP Count the directory depth of a path name
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the number of directory levels in 'pathname'
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; The pathname must end in a filename.
							 | 
						||
| 
								 | 
							
								  ;; Further, this function assumes that directories in a pathname are 
							 | 
						||
| 
								 | 
							
								  ;; separated by forward slashes ("/").
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; "filename" => 0, 
							 | 
						||
| 
								 | 
							
								  ;; "foo/filename" => 1, 
							 | 
						||
| 
								 | 
							
								  ;; "foo/bar/filename => 2, 
							 | 
						||
| 
								 | 
							
								  ;; "foo/bar/../filename => 1.
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((count 0) (pathlist (match-split pathname "/")))
							 | 
						||
| 
								 | 
							
								    (if (null? pathlist)
							 | 
						||
| 
								 | 
							
									(- count 1) ;; pathname should always end in a filename
							 | 
						||
| 
								 | 
							
									(if (or (equal? (car pathlist) "/") (equal? (car pathlist) "."))
							 | 
						||
| 
								 | 
							
									    (loop count (cdr pathlist))
							 | 
						||
| 
								 | 
							
									    (if (equal? (car pathlist) "..")
							 | 
						||
| 
								 | 
							
										(loop (- count 1) (cdr pathlist))
							 | 
						||
| 
								 | 
							
										(loop (+ count 1) (cdr pathlist)))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (file-extension filespec) 
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY file-extension
							 | 
						||
| 
								 | 
							
								  ;; PURP Return the extension of a filename
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the extension of a filename.  The extension is the last
							 | 
						||
| 
								 | 
							
								  ;; "."-delimited part of the name.  Returns "" if there is no period
							 | 
						||
| 
								 | 
							
								  ;; in the filename.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (string? filespec)
							 | 
						||
| 
								 | 
							
								      (let* ((pathparts (match-split filespec "/"))
							 | 
						||
| 
								 | 
							
									     (filename  (list-ref pathparts (- (length pathparts) 1)))
							 | 
						||
| 
								 | 
							
									     (fileparts (match-split filename "."))
							 | 
						||
| 
								 | 
							
									     (extension (list-ref fileparts (- (length fileparts) 1))))
							 | 
						||
| 
								 | 
							
									(if (> (length fileparts) 1)
							 | 
						||
| 
								 | 
							
									    extension
							 | 
						||
| 
								 | 
							
									    ""))
							 | 
						||
| 
								 | 
							
								      ""))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (copy-string string num)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY copy-string
							 | 
						||
| 
								 | 
							
								  ;; PURP Return a string duplicated a specified number of times
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Copies 'string' 'num' times and returns the result.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; (copy-string "x" 3) returns "xxx"
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (<= num 0)
							 | 
						||
| 
								 | 
							
								      ""
							 | 
						||
| 
								 | 
							
								      (let loop ((str string) (count (- num 1)))
							 | 
						||
| 
								 | 
							
									(if (<= count 0)
							 | 
						||
| 
								 | 
							
									    str
							 | 
						||
| 
								 | 
							
									    (loop (string-append str string) (- count 1))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (node-list-filter-by-gi nodelist gilist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY node-list-filter-by-gi
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns selected elements from a node list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns a node list containing all the nodes from 'nodelist' whose
							 | 
						||
| 
								 | 
							
								  ;; GIs are members of 'gilist'.  The order of nodes in the node list
							 | 
						||
| 
								 | 
							
								  ;; is preserved.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((result (empty-node-list)) (nl nodelist))
							 | 
						||
| 
								 | 
							
								    (if (node-list-empty? nl)
							 | 
						||
| 
								 | 
							
									result
							 | 
						||
| 
								 | 
							
									(if (member (gi (node-list-first nl)) gilist)
							 | 
						||
| 
								 | 
							
									    (loop (node-list result (node-list-first nl)) 
							 | 
						||
| 
								 | 
							
										  (node-list-rest nl))
							 | 
						||
| 
								 | 
							
									    (loop result (node-list-rest nl))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (node-list-filter-by-not-gi nodelist gilist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY node-list-filter-by-not-gi
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns selected elements from a node list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns a node list containing all the nodes from 'nodelist' whose
							 | 
						||
| 
								 | 
							
								  ;; GIs are NOT members of 'gilist'.  The order of nodes in the node list
							 | 
						||
| 
								 | 
							
								  ;; is preserved.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((result (empty-node-list)) (nl nodelist))
							 | 
						||
| 
								 | 
							
								    (if (node-list-empty? nl)
							 | 
						||
| 
								 | 
							
									result
							 | 
						||
| 
								 | 
							
									(if (member (gi (node-list-first nl)) gilist)
							 | 
						||
| 
								 | 
							
									    (loop result (node-list-rest nl))
							 | 
						||
| 
								 | 
							
									    (loop (node-list result (node-list-first nl))
							 | 
						||
| 
								 | 
							
										  (node-list-rest nl))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (node-list-filter-out-pis nodelist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY node-list-filter-out-pis
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns the nodelist with all PIs removed
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns a node list containing all the nodes from 'nodelist' that
							 | 
						||
| 
								 | 
							
								  ;; are not PIs.  The order of nodes in the node list is preserved.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((result (empty-node-list)) (nl nodelist))
							 | 
						||
| 
								 | 
							
								    (if (node-list-empty? nl)
							 | 
						||
| 
								 | 
							
									result
							 | 
						||
| 
								 | 
							
									(if (equal? (node-property 'class-name (node-list-first nl)) 'pi)
							 | 
						||
| 
								 | 
							
									    (loop result (node-list-rest nl))
							 | 
						||
| 
								 | 
							
									    (loop (node-list result (node-list-first nl))
							 | 
						||
| 
								 | 
							
										  (node-list-rest nl))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (node-list-filter-elements nodelist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY node-list-filter-elements
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns the elements in 'nodelist'
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the elements in 'nodelist'
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((result (empty-node-list)) (nl nodelist))
							 | 
						||
| 
								 | 
							
								    (if (node-list-empty? nl)
							 | 
						||
| 
								 | 
							
									result
							 | 
						||
| 
								 | 
							
									(if (equal? (node-property 'class-name (node-list-first nl)) 'element)
							 | 
						||
| 
								 | 
							
									    (loop (node-list result (node-list-first nl))
							 | 
						||
| 
								 | 
							
										  (node-list-rest nl))
							 | 
						||
| 
								 | 
							
									    (loop result (node-list-rest nl))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (component-descendant-node-list inputnd complist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY component-descendant-node-list
							 | 
						||
| 
								 | 
							
								  ;; PURP Find all 'inputnd's within an ancestor element
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Finds the first ancestor of 'inputnd' in 'complist' and then returns
							 | 
						||
| 
								 | 
							
								  ;; a node list of all the 'inputnd's within (that are descendants of) 
							 | 
						||
| 
								 | 
							
								  ;; that ancestor.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let ((nd (ancestor-member inputnd complist)))
							 | 
						||
| 
								 | 
							
								    (select-elements (descendants nd) (gi inputnd))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (component-child-number inputnd complist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY component-child-number
							 | 
						||
| 
								 | 
							
								  ;; PURP Find child-number within a component
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Finds the first ancestor of 'inputnd' in 'complist' and then counts 
							 | 
						||
| 
								 | 
							
								  ;; all the elements of type 'inputnd' from that point on and returns
							 | 
						||
| 
								 | 
							
								  ;; the number of 'inputnd'.  (This is like a 'recursive-child-number'
							 | 
						||
| 
								 | 
							
								  ;; starting at the first parent of 'inputnd' in 'complist'.)
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((nl (component-descendant-node-list inputnd complist))
							 | 
						||
| 
								 | 
							
									     (num 1))
							 | 
						||
| 
								 | 
							
								    (if (node-list-empty? nl)
							 | 
						||
| 
								 | 
							
									0
							 | 
						||
| 
								 | 
							
									(if (node-list=? (node-list-first nl) inputnd)
							 | 
						||
| 
								 | 
							
									    num
							 | 
						||
| 
								 | 
							
									    (if (string=? (gi (node-list-first nl)) (gi inputnd))
							 | 
						||
| 
								 | 
							
										(loop (node-list-rest nl) (+ num 1))
							 | 
						||
| 
								 | 
							
										(loop (node-list-rest nl) num))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (component-list-descendant-node-list inputnd inputlist complist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY component-descendant-list-node-list
							 | 
						||
| 
								 | 
							
								  ;; PURP Find all elements of a list of elements in a component
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Finds the first ancestor of 'inputnd' in 'complist' and
							 | 
						||
| 
								 | 
							
								  ;; then returns a list of all the elements in 'inputlist' 
							 | 
						||
| 
								 | 
							
								  ;; within that component.
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; WARNING: this requires walking over *all* the descendants
							 | 
						||
| 
								 | 
							
								  ;; of the ancestor node. This may be *slow*.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let ((nd (ancestor-member inputnd complist)))
							 | 
						||
| 
								 | 
							
								    (let loop ((nl (descendants nd)) (result (empty-node-list)))
							 | 
						||
| 
								 | 
							
								      (if (node-list-empty? nl)
							 | 
						||
| 
								 | 
							
									  result
							 | 
						||
| 
								 | 
							
									  (if (member (gi (node-list-first nl)) inputlist)
							 | 
						||
| 
								 | 
							
									      (loop (node-list-rest nl) 
							 | 
						||
| 
								 | 
							
										    (node-list result (node-list-first nl)))
							 | 
						||
| 
								 | 
							
									      (loop (node-list-rest nl) 
							 | 
						||
| 
								 | 
							
										    result))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (component-list-child-number inputnd inputlist complist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY component-list-child-number
							 | 
						||
| 
								 | 
							
								  ;; PURP Find child-number of a list of children within a component
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Finds the first ancestor of 'inputnd' in 'complist' and
							 | 
						||
| 
								 | 
							
								  ;; then counts all the elements of the types in 'inputlist'
							 | 
						||
| 
								 | 
							
								  ;; from that point on and returns the number of 'inputnd'.
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; If the node is not found, 0 is returned.
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; WARNING: this requires walking over *all* the descendants
							 | 
						||
| 
								 | 
							
								  ;; of the ancestor node. This may be *slow*.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								    (let loop ((nl (component-list-descendant-node-list
							 | 
						||
| 
								 | 
							
										    inputnd inputlist complist))
							 | 
						||
| 
								 | 
							
									       (num 1))
							 | 
						||
| 
								 | 
							
								      (if (node-list-empty? nl)
							 | 
						||
| 
								 | 
							
									  0
							 | 
						||
| 
								 | 
							
									  (if (node-list=? (node-list-first nl) inputnd)
							 | 
						||
| 
								 | 
							
									      num
							 | 
						||
| 
								 | 
							
									      (loop (node-list-rest nl) (+ num 1))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (expt b n)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY expt
							 | 
						||
| 
								 | 
							
								  ;; PURP Exponentiation
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns 'b' raised to the 'n'th power for integer 'n' >= 0.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  ;; 
							 | 
						||
| 
								 | 
							
								  (if (<= n 0)
							 | 
						||
| 
								 | 
							
								      1
							 | 
						||
| 
								 | 
							
								      (* b (expt b (- n 1)))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (list-member-find element elementlist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY list-member-find
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns the index of an element in a list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the index of 'element' in the list 'elementlist'. The
							 | 
						||
| 
								 | 
							
								  ;; first element in a list has index 0.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((elemlist elementlist) (count 0))
							 | 
						||
| 
								 | 
							
								    (if (null? elemlist)
							 | 
						||
| 
								 | 
							
									-1
							 | 
						||
| 
								 | 
							
									(if (equal? element (car elemlist))
							 | 
						||
| 
								 | 
							
									    count
							 | 
						||
| 
								 | 
							
									    (loop (cdr elemlist) (+ count 1))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define default-uppercase-list
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY
							 | 
						||
| 
								 | 
							
								  ;; PURP The default list of uppercase characters
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; The default list of uppercase characters.  The order and sequence
							 | 
						||
| 
								 | 
							
								  ;; of characters
							 | 
						||
| 
								 | 
							
								  ;; in this list must match the order and sequence in 
							 | 
						||
| 
								 | 
							
								  ;; 'default-lowercase-list'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  '(#\A #\B #\C #\D #\E #\F #\G #\H #\I #\J #\K #\L #\M
							 | 
						||
| 
								 | 
							
								    #\N #\O #\P #\Q #\R #\S #\T #\U #\V #\W #\X #\Y #\Z))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define default-lowercase-list
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY
							 | 
						||
| 
								 | 
							
								  ;; PURP The default list of lowercase characters
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; The default list of lowercase characters.  The order and sequence
							 | 
						||
| 
								 | 
							
								  ;; of characters
							 | 
						||
| 
								 | 
							
								  ;; in this list must match the order and sequence in 
							 | 
						||
| 
								 | 
							
								  ;; 'default-uppercase-list'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  '(#\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k #\l #\m
							 | 
						||
| 
								 | 
							
								    #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (case-fold-down-char ch #!optional (uc-list default-uppercase-list)
							 | 
						||
| 
								 | 
							
													   (lc-list default-lowercase-list))
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY
							 | 
						||
| 
								 | 
							
								  ;; PURP Return the lowercase form of a single character
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the lowercase form of 'ch' if 'ch' is a member of
							 | 
						||
| 
								 | 
							
								  ;; the uppercase list, otherwise return 'ch'.
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; The implied mapping from uppercase to lowercase in the two lists is
							 | 
						||
| 
								 | 
							
								  ;; one-to-one.  The first element of the uppercase list is the uppercase
							 | 
						||
| 
								 | 
							
								  ;; form of the first element of the lowercase list, and vice versa.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG 'ch'
							 | 
						||
| 
								 | 
							
								  ;; The character to fold down.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'uc-list' o
							 | 
						||
| 
								 | 
							
								  ;; The list of uppercase letters. The default is the list of English 
							 | 
						||
| 
								 | 
							
								  ;; uppercase letters.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'lc-list' o
							 | 
						||
| 
								 | 
							
								  ;; The list of lowercase letters. The default is the list of English 
							 | 
						||
| 
								 | 
							
								  ;; lowercase letters.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let ((idx (list-member-find ch uc-list)))
							 | 
						||
| 
								 | 
							
								    (if (>= idx 0)
							 | 
						||
| 
								 | 
							
									(list-ref lc-list idx)
							 | 
						||
| 
								 | 
							
									ch)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (case-fold-up-char ch #!optional (uc-list default-uppercase-list)
							 | 
						||
| 
								 | 
							
													 (lc-list default-lowercase-list))
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY
							 | 
						||
| 
								 | 
							
								  ;; PURP Return the uppercase form of a single character
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the uppercase form of 'ch' if 'ch' is a member of
							 | 
						||
| 
								 | 
							
								  ;; 'lowercase-list', otherwise return 'ch'.
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; The implied mapping from uppercase to lowercase in the two lists is
							 | 
						||
| 
								 | 
							
								  ;; one-to-one.  The first element of the uppercase list is the uppercase
							 | 
						||
| 
								 | 
							
								  ;; form of the first element of the lowercase list, and vice versa.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG 'ch'
							 | 
						||
| 
								 | 
							
								  ;; The character to fold down.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'uc-list' o
							 | 
						||
| 
								 | 
							
								  ;; The list of uppercase letters. The default is the list of English 
							 | 
						||
| 
								 | 
							
								  ;; uppercase letters.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'lc-list' o
							 | 
						||
| 
								 | 
							
								  ;; The list of lowercase letters. The default is the list of English 
							 | 
						||
| 
								 | 
							
								  ;; lowercase letters.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let ((idx (list-member-find ch lc-list)))
							 | 
						||
| 
								 | 
							
								    (if (>= idx 0)
							 | 
						||
| 
								 | 
							
									(list-ref uc-list idx)
							 | 
						||
| 
								 | 
							
									ch)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (case-fold-down-charlist charlist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY case-fold-down-charlist
							 | 
						||
| 
								 | 
							
								  ;; PURP Return the list of characters, shifted to lowercase
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Shifts all of the characters in 'charlist' to lowercase with
							 | 
						||
| 
								 | 
							
								  ;; 'case-fold-down-char'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (null? charlist)
							 | 
						||
| 
								 | 
							
								      '()
							 | 
						||
| 
								 | 
							
								      (cons (case-fold-down-char (car charlist)) 
							 | 
						||
| 
								 | 
							
									    (case-fold-down-charlist (cdr charlist)))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (case-fold-up-charlist charlist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY case-fold-up-charlist
							 | 
						||
| 
								 | 
							
								  ;; PURP Return the list of characters, shifted to uppercase
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Shifts all of the characters in 'charlist' to uppercase with
							 | 
						||
| 
								 | 
							
								  ;; 'case-fold-up-char'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (null? charlist)
							 | 
						||
| 
								 | 
							
								      '()
							 | 
						||
| 
								 | 
							
								      (cons (case-fold-up-char (car charlist)) 
							 | 
						||
| 
								 | 
							
									    (case-fold-up-charlist (cdr charlist)))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (case-fold-down str)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY case-fold-down
							 | 
						||
| 
								 | 
							
								  ;; PURP Shift a string to lowercase
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns 'str' in lowercase.
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (string? str)
							 | 
						||
| 
								 | 
							
								      (apply string (case-fold-down-charlist (string->list str)))
							 | 
						||
| 
								 | 
							
								      str))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (case-fold-up str)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY case-fold-up
							 | 
						||
| 
								 | 
							
								  ;; PURP Shift a string to uppercase
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns 'str' in uppercase.
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (string? str)
							 | 
						||
| 
								 | 
							
								      (apply string (case-fold-up-charlist (string->list str)))
							 | 
						||
| 
								 | 
							
								      str))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (find-first-char string skipchars findchars #!optional (pos 0))
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY find-first-char
							 | 
						||
| 
								 | 
							
								  ;; PURP Find the first occurance of a character in a string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Finds first character in 'string' that is in 'findchars', skipping all
							 | 
						||
| 
								 | 
							
								  ;; occurances of characters in 'skipchars'.  Search begins at 'pos'.  If
							 | 
						||
| 
								 | 
							
								  ;; no such characters are found, returns -1.
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; If skipchars is empty, skip anything not in findchars
							 | 
						||
| 
								 | 
							
								  ;; If skipchars is #f, skip nothing
							 | 
						||
| 
								 | 
							
								  ;; If findchars is empty, the first character not in skipchars is matched
							 | 
						||
| 
								 | 
							
								  ;; It is an error if findchars is not a string.
							 | 
						||
| 
								 | 
							
								  ;; It is an error if findchars is empty and skipchars is not a non-empty
							 | 
						||
| 
								 | 
							
								  ;; string.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let ((skiplist (if (string? skipchars)
							 | 
						||
| 
								 | 
							
										      (string->list skipchars)
							 | 
						||
| 
								 | 
							
										      '()))
							 | 
						||
| 
								 | 
							
									(findlist (string->list findchars)))
							 | 
						||
| 
								 | 
							
								    (if (and (null? skiplist) (null? findlist))
							 | 
						||
| 
								 | 
							
									;; this is an error
							 | 
						||
| 
								 | 
							
									-2
							 | 
						||
| 
								 | 
							
									(if (or (>= pos (string-length string)) (< pos 0))
							 | 
						||
| 
								 | 
							
									    -1
							 | 
						||
| 
								 | 
							
									    (let ((ch (string-ref string pos)))
							 | 
						||
| 
								 | 
							
									      (if (null? skiplist) 
							 | 
						||
| 
								 | 
							
										  ;; try to find first
							 | 
						||
| 
								 | 
							
										  (if (member ch findlist)
							 | 
						||
| 
								 | 
							
										      pos
							 | 
						||
| 
								 | 
							
										      (if (string? skipchars)
							 | 
						||
| 
								 | 
							
											  (find-first-char string 
							 | 
						||
| 
								 | 
							
													   skipchars findchars (+ 1 pos))
							 | 
						||
| 
								 | 
							
											  -1))
							 | 
						||
| 
								 | 
							
										  ;; try to skip first
							 | 
						||
| 
								 | 
							
										  (if (member ch skiplist)
							 | 
						||
| 
								 | 
							
										      (find-first-char string skipchars findchars (+ 1 pos))
							 | 
						||
| 
								 | 
							
										      (if (or (member ch findlist) (null? findlist))
							 | 
						||
| 
								 | 
							
											  pos
							 | 
						||
| 
								 | 
							
											  -1))))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (parse-measurement measure)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY parse-measurement
							 | 
						||
| 
								 | 
							
								  ;; PURP Parse a string containing a measurement and return the magnitude and units
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Parse a string containing a measurement, e.g., '"3pi"' or '"2.5in"',
							 | 
						||
| 
								 | 
							
								  ;; and return the magnitude and units: '(3 "pi")' or '(2.5 "in")'.
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; Either element of the list may be '#f' if the string cannot reasonably
							 | 
						||
| 
								 | 
							
								  ;; be parsed as a measurement.  Leading and trailing spaces are ignored.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let* ((magstart  (find-first-char measure " " "0123456789."))
							 | 
						||
| 
								 | 
							
									 (unitstart (find-first-char measure " 0123456789." ""))
							 | 
						||
| 
								 | 
							
									 (unitend   (find-first-char measure "" " " unitstart))
							 | 
						||
| 
								 | 
							
									 (magnitude (if (< magstart 0)
							 | 
						||
| 
								 | 
							
											#f
							 | 
						||
| 
								 | 
							
											(if (< unitstart 0)
							 | 
						||
| 
								 | 
							
											    (substring measure 
							 | 
						||
| 
								 | 
							
												       magstart 
							 | 
						||
| 
								 | 
							
												       (string-length measure))
							 | 
						||
| 
								 | 
							
											    (substring measure magstart unitstart))))
							 | 
						||
| 
								 | 
							
									 (unit      (if (< unitstart 0)
							 | 
						||
| 
								 | 
							
											#f
							 | 
						||
| 
								 | 
							
											(if (< unitend 0)
							 | 
						||
| 
								 | 
							
											    (substring measure 
							 | 
						||
| 
								 | 
							
												       unitstart 
							 | 
						||
| 
								 | 
							
												       (string-length measure))
							 | 
						||
| 
								 | 
							
											    (substring measure unitstart unitend)))))
							 | 
						||
| 
								 | 
							
								  (list magnitude unit)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define unit-conversion-alist
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY
							 | 
						||
| 
								 | 
							
								  ;; PURP Defines the base length of specific unit names
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; This list identifies the length of each unit.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (list
							 | 
						||
| 
								 | 
							
								   '("default" 1pi)
							 | 
						||
| 
								 | 
							
								   '("mm" 1mm)
							 | 
						||
| 
								 | 
							
								   '("cm" 1cm)
							 | 
						||
| 
								 | 
							
								   '("in" 1in)
							 | 
						||
| 
								 | 
							
								   '("pi" 1pi)
							 | 
						||
| 
								 | 
							
								   '("pc" 1pi)
							 | 
						||
| 
								 | 
							
								   '("pt" 1pt)
							 | 
						||
| 
								 | 
							
								   '("px" 1px)
							 | 
						||
| 
								 | 
							
								   '("barleycorn" 2pi)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (measurement-to-length measure)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY measurement-to-length
							 | 
						||
| 
								 | 
							
								  ;; PURP Convert a measurement to a length
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Given a string containing a measurement, return that measurement
							 | 
						||
| 
								 | 
							
								  ;; as a length.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLES
							 | 
						||
| 
								 | 
							
								  ;; '"2.5cm"' returns 2.5cm as a length.  '"3.4barleycorn"' returns
							 | 
						||
| 
								 | 
							
								  ;; 6.8pi.
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLES
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let* ((pm (car (parse-measurement measure)))
							 | 
						||
| 
								 | 
							
									 (pu (car (cdr (parse-measurement measure))))
							 | 
						||
| 
								 | 
							
									 (magnitude (if pm pm "1"))
							 | 
						||
| 
								 | 
							
									 (units     (if pu pu (if pm "pt" "default")))
							 | 
						||
| 
								 | 
							
									 (unitconv  (assoc units unit-conversion-alist))
							 | 
						||
| 
								 | 
							
									 (factor    (if unitconv (car (cdr unitconv)) 1pt)))
							 | 
						||
| 
								 | 
							
								    (* (string->number magnitude) factor)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (dingbat usrname)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY dingbat
							 | 
						||
| 
								 | 
							
								  ;; PURP Map dingbat names to Unicode characters
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Map a dingbat name to the appropriate Unicode character.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  ;; Print dingbats and other characters selected by name
							 | 
						||
| 
								 | 
							
								  (let ((name (case-fold-down usrname)))
							 | 
						||
| 
								 | 
							
								    (case name
							 | 
						||
| 
								 | 
							
								      ;; For backward compatibility
							 | 
						||
| 
								 | 
							
								      (("box") 			"\white-square;")
							 | 
						||
| 
								 | 
							
								      (("checkbox")		"\white-square;")
							 | 
						||
| 
								 | 
							
								      ;; \check-mark prints the wrong symbol (in Jade 0.8 RTF backend)
							 | 
						||
| 
								 | 
							
								      (("check")		"\heavy-check-mark;") 
							 | 
						||
| 
								 | 
							
								      (("checkedbox")		"\ballot-box-with-check;")
							 | 
						||
| 
								 | 
							
								      (("dash")			"\em-dash;")
							 | 
						||
| 
								 | 
							
								      (("copyright")		"\copyright-sign")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      ;; Straight out of Unicode
							 | 
						||
| 
								 | 
							
								      (("raquo")                "\U-00BB;")
							 | 
						||
| 
								 | 
							
								      (("laquo")                "\U-00AB;")
							 | 
						||
| 
								 | 
							
								      (("rsaquo")               "\U-203A;")
							 | 
						||
| 
								 | 
							
								      (("lsaquo")               "\U-2039;")
							 | 
						||
| 
								 | 
							
								      (("lsquo")		"\U-2018;")
							 | 
						||
| 
								 | 
							
								      (("rsquo")		"\U-2019;")
							 | 
						||
| 
								 | 
							
								      (("ldquo")		"\U-201C;")
							 | 
						||
| 
								 | 
							
								      (("rdquo")		"\U-201D;")
							 | 
						||
| 
								 | 
							
								      (("ldquor")		"\U-201E;")
							 | 
						||
| 
								 | 
							
								      (("rdquor")		"\U-201D;")
							 | 
						||
| 
								 | 
							
								      (("en-dash")		"\en-dash;")
							 | 
						||
| 
								 | 
							
								      (("em-dash")		"\em-dash;")
							 | 
						||
| 
								 | 
							
								      (("en-space")		"\U-2002;")
							 | 
						||
| 
								 | 
							
								      (("em-space")		"\U-2003;")
							 | 
						||
| 
								 | 
							
								      (("bullet")		"\bullet;")
							 | 
						||
| 
								 | 
							
								      (("black-square")		"\black-square;")
							 | 
						||
| 
								 | 
							
								      (("white-square")		"\white-square;")
							 | 
						||
| 
								 | 
							
								      ;; \ballot-box name doesn't work (in Jade 0.8 RTF backend)
							 | 
						||
| 
								 | 
							
								      ;; and \white-square looks better than \U-2610; anyway
							 | 
						||
| 
								 | 
							
								      (("ballot-box")		"\white-square;")
							 | 
						||
| 
								 | 
							
								      (("ballot-box-with-check")	"\ballot-box-with-check;")
							 | 
						||
| 
								 | 
							
								      (("ballot-box-with-x")	"\ballot-box-with-x;")
							 | 
						||
| 
								 | 
							
								      ;; \check-mark prints the wrong symbol (in Jade 0.8 RTF backend)
							 | 
						||
| 
								 | 
							
								      (("check-mark")		"\heavy-check-mark;") 
							 | 
						||
| 
								 | 
							
								      ;; \ballot-x prints out the wrong symbol (in Jade 0.8 RTF backend)
							 | 
						||
| 
								 | 
							
								      (("ballot-x")		"\heavy-check-mark;")
							 | 
						||
| 
								 | 
							
								      (("copyright-sign")	"\copyright-sign;")
							 | 
						||
| 
								 | 
							
								      (("registered-sign")	"\registered-sign;")
							 | 
						||
| 
								 | 
							
								      (else "\bullet;"))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (nth-node nl k)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY nth-node
							 | 
						||
| 
								 | 
							
								  ;; PURP Return a specific node in a node list (by numeric index)
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the 'k'th node in 'nl'.  The first node in the node list
							 | 
						||
| 
								 | 
							
								  ;; has the index "1".
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (equal? k 1)
							 | 
						||
| 
								 | 
							
								      (node-list-first nl)
							 | 
						||
| 
								 | 
							
								      (nth-node (node-list-rest nl) (- k 1))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (constant-list value length)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY constant-list
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns a list of the specified value
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Return a list containing 'length' elements, each of 'value'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR David Carlisle
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; '(constant-list 0 4)' returns '(0 0 0 0)'
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								   (let loop ((count (abs length)) (result '()))
							 | 
						||
| 
								 | 
							
								     (if (equal? count 0)
							 | 
						||
| 
								 | 
							
								         result
							 | 
						||
| 
								 | 
							
								         (loop (- count 1) (cons value  result)))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (list-head inputlist k)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY list-head
							 | 
						||
| 
								 | 
							
								  ;; PURP Return the head of a list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the list that contains the first 'k' elements of 'inputlist'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; '(list-head (1 2 3 4) 2)' returns '(1 2)'.
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((l inputlist) (count k) (result '()))
							 | 
						||
| 
								 | 
							
								    (if (<= count 0)
							 | 
						||
| 
								 | 
							
									result
							 | 
						||
| 
								 | 
							
									(loop (cdr l) (- count 1) (append result (list (car l)))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (list-put vlist ordinal value #!optional (span 1))
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY list-put
							 | 
						||
| 
								 | 
							
								  ;; PURP Replace a specific member of a list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Replaces the 'ordinal'th value of 'vlist' with 'value'.  If 'span' > 1,
							 | 
						||
| 
								 | 
							
								  ;; replaces 'ordinal' to 'ordinal+span-1' values starting at 'ordinal'.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; '(list-put (1 2 3 4 5) 2 0 2)' returns '(1 0 0 4 5)'.
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((result vlist) (count span) (k ordinal))
							 | 
						||
| 
								 | 
							
								    (if (equal? count 0)
							 | 
						||
| 
								 | 
							
									result
							 | 
						||
| 
								 | 
							
									(let ((head (list-head result (- k 1)))
							 | 
						||
| 
								 | 
							
									      (tail (list-tail result k)))
							 | 
						||
| 
								 | 
							
									  (loop (append head (list value) tail) (- count 1) (+ k 1))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (decrement-list-members vlist #!optional (decr 1) (floor 0))
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY decrement-list-members
							 | 
						||
| 
								 | 
							
								  ;; PURP Decrement each member of a list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Decrement all the values of a list by 'decr', not to fall below 'floor'.
							 | 
						||
| 
								 | 
							
								  ;; ARGS
							 | 
						||
| 
								 | 
							
								  ;; ARG 'vlist'
							 | 
						||
| 
								 | 
							
								  ;; The list of values.  All the values of this list should be numeric.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'decr' o
							 | 
						||
| 
								 | 
							
								  ;; The amount by which each element of the list should be decremented.
							 | 
						||
| 
								 | 
							
								  ;; The default is 1.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; ARG 'floor' o
							 | 
						||
| 
								 | 
							
								  ;; The value below which each member of the list is not allowed to fall.
							 | 
						||
| 
								 | 
							
								  ;; The default is 0.
							 | 
						||
| 
								 | 
							
								  ;; /ARG
							 | 
						||
| 
								 | 
							
								  ;; /ARGS
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR David Carlisle
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; '(decrement-list-members (0 1 2 3 4 5))' => '(0 0 1 2 3 4)'.
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (map (lambda (a) 
							 | 
						||
| 
								 | 
							
									 (if (<= a (+ decr floor))
							 | 
						||
| 
								 | 
							
									     floor
							 | 
						||
| 
								 | 
							
									     (- a decr)))
							 | 
						||
| 
								 | 
							
								       vlist))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (sgml-root-element #!optional (grove-node (current-node)))
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns the node that is the root element of the current document
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the node that is the root element of the current document
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (node-property 'document-element (node-property 'grove-root grove-node)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (sgml-root-element? node)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY
							 | 
						||
| 
								 | 
							
								  ;; PURP Test if a node is the root element
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns '#t' if node is the root element of the current document.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (node-list=? node (sgml-root-element node)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (length-string-number-part lenstr)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY length-string-number-part
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns the numeric part of a length string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Given a length as a string, return the numeric part.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; '"100pt"' returns '"100"'. '"30"' returns '"30"'.  
							 | 
						||
| 
								 | 
							
								  ;; '"in"' returns '""'.
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let ((digits '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\.)))
							 | 
						||
| 
								 | 
							
								    (let loop ((chars (string->list lenstr))
							 | 
						||
| 
								 | 
							
									       (number-part ""))
							 | 
						||
| 
								 | 
							
								      (if (or (null? chars) (not (member (car chars) digits)))
							 | 
						||
| 
								 | 
							
									  number-part
							 | 
						||
| 
								 | 
							
									  (loop (cdr chars) (string-append number-part 
							 | 
						||
| 
								 | 
							
													   (string (car chars))))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (length-string-unit-part lenstr)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY length-string-unit-part
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns the unit part of a length string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Given a length as a string, return the units part.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; '"100pt"' returns '"pt"'. '"30"' returns '""'.  
							 | 
						||
| 
								 | 
							
								  ;; '"in"' returns '"in"'.
							 | 
						||
| 
								 | 
							
								  ;; /EXAMPLE
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let ((number-part (length-string-number-part lenstr))
							 | 
						||
| 
								 | 
							
									(strlen (string-length lenstr)))
							 | 
						||
| 
								 | 
							
								    (if (equal? (string-length number-part) strlen)
							 | 
						||
| 
								 | 
							
									""
							 | 
						||
| 
								 | 
							
									(substring lenstr (string-length number-part) strlen))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (normalize str)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY normalize
							 | 
						||
| 
								 | 
							
								  ;; PURP Normalize the str according to the SGML declaration in effect
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Performs SGML general name normalization on the string;
							 | 
						||
| 
								 | 
							
								  ;; used to compare attribute names and generic identifiers correctly
							 | 
						||
| 
								 | 
							
								  ;; according to the SGML declaration in effect; this is necessary
							 | 
						||
| 
								 | 
							
								  ;; since XML is case-sensitive but the reference concrete syntax and
							 | 
						||
| 
								 | 
							
								  ;; many SGML DTDs are not.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; AUTHOR Chris Maden
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (string? str)
							 | 
						||
| 
								 | 
							
								      (general-name-normalize str
							 | 
						||
| 
								 | 
							
											      (current-node))
							 | 
						||
| 
								 | 
							
								      str))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (node-list->string nodelist)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY node-2-string
							 | 
						||
| 
								 | 
							
								  ;; PURP Return a string representation of the node list
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Builds a string representation of the node list and returns it.
							 | 
						||
| 
								 | 
							
								  ;; The representation is 
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; "gi(firstchildgi()secondchildgi(firstgrandchildgi())) secondgi()..."
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; This is a debugging function, in case that wasn't obvious...
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((nl nodelist) (res ""))
							 | 
						||
| 
								 | 
							
								    (if (node-list-empty? nl)
							 | 
						||
| 
								 | 
							
									res
							 | 
						||
| 
								 | 
							
									(loop (node-list-rest nl)
							 | 
						||
| 
								 | 
							
									      (string-append res 
							 | 
						||
| 
								 | 
							
											     (if (gi (node-list-first nl))
							 | 
						||
| 
								 | 
							
												 (string-append
							 | 
						||
| 
								 | 
							
												  (gi (node-list-first nl))
							 | 
						||
| 
								 | 
							
												  "("
							 | 
						||
| 
								 | 
							
												  (node-list->string 
							 | 
						||
| 
								 | 
							
												   (children (node-list-first nl)))
							 | 
						||
| 
								 | 
							
												  ")")
							 | 
						||
| 
								 | 
							
												 ""))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (include-file fileref)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY include-file
							 | 
						||
| 
								 | 
							
								  ;; PURP Return the literal content of fileref
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Opens and loads fileref with (read-entity); returns the content
							 | 
						||
| 
								 | 
							
								  ;; of fileref as a (literal).  Trims the last trailing newline off
							 | 
						||
| 
								 | 
							
								  ;; the file so that "the right thing" happens in asis environments.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (literal (include-characters fileref)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (include-characters fileref)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY include-characters
							 | 
						||
| 
								 | 
							
								  ;; PURP Return the character content of fileref
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Opens and loads fileref with (read-entity); returns the content
							 | 
						||
| 
								 | 
							
								  ;; of fileref as characters.  Trims the last trailing newline off
							 | 
						||
| 
								 | 
							
								  ;; the file so that "the right thing" happens in asis environments.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let* ((newline #\U-000D)
							 | 
						||
| 
								 | 
							
									 (file-content  (read-entity fileref))
							 | 
						||
| 
								 | 
							
									 (file-length   (string-length file-content))
							 | 
						||
| 
								 | 
							
									 ;; If the last char is a newline, drop it, otherwise print it...
							 | 
						||
| 
								 | 
							
									 (content       (if (equal? newline (string-ref file-content
							 | 
						||
| 
								 | 
							
															(- file-length 1)))
							 | 
						||
| 
								 | 
							
											    (substring file-content 0 (- file-length 1))
							 | 
						||
| 
								 | 
							
											    file-content)))
							 | 
						||
| 
								 | 
							
								    content))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (url-encode-char ch)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY url-encode-char
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns the url-encoded equivalent of a character
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Converts 'ch' to a properly encoded URL character.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (cond ((char=? ch #\space)  "%20") ; space
							 | 
						||
| 
								 | 
							
									((char=? ch #\U-0026) "%26") ; ampersand
							 | 
						||
| 
								 | 
							
									((char=? ch #\?)      "%3F") ; question
							 | 
						||
| 
								 | 
							
									((char=? ch #\{)      "%7B") ; open curly
							 | 
						||
| 
								 | 
							
									((char=? ch #\})      "%7D") ; close curly
							 | 
						||
| 
								 | 
							
									((char=? ch #\|)      "%7C") ; vertical bar
							 | 
						||
| 
								 | 
							
									((char=? ch #\\)      "%5C") ; backslash
							 | 
						||
| 
								 | 
							
									((char=? ch #\/)      "%2F") ; slash
							 | 
						||
| 
								 | 
							
									((char=? ch #\^)      "%5E") ; caret
							 | 
						||
| 
								 | 
							
									((char=? ch #\~)      "%7E") ; tilde
							 | 
						||
| 
								 | 
							
									((char=? ch #\[)      "%5B") ; open square
							 | 
						||
| 
								 | 
							
									((char=? ch #\])      "%5D") ; close square
							 | 
						||
| 
								 | 
							
									((char=? ch #\`)      "%60") ; backtick
							 | 
						||
| 
								 | 
							
									((char=? ch #\%)      "%25") ; percent
							 | 
						||
| 
								 | 
							
									((char=? ch #\+)      "%2B") ; plus
							 | 
						||
| 
								 | 
							
									(else (string ch))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (url-encode-string str)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY url-encode-string
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns str with all special characters %-encoded
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Converts 'str' to a properly encoded URL string.  Returns str unchanged
							 | 
						||
| 
								 | 
							
								  ;; if it is not a string.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (if (string? str)
							 | 
						||
| 
								 | 
							
								      (let loop ((charlist (string->list str)) (url ""))
							 | 
						||
| 
								 | 
							
									(if (null? charlist)
							 | 
						||
| 
								 | 
							
									    url
							 | 
						||
| 
								 | 
							
									    (loop (cdr charlist) 
							 | 
						||
| 
								 | 
							
										  (string-append url (url-encode-char (car charlist))))))
							 | 
						||
| 
								 | 
							
								      str))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (system-id-filename target)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY system-id-filename
							 | 
						||
| 
								 | 
							
								  ;; PURP Returns the filename part of the system id of target
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; The entity-generated-system-id of target seems to begin with a
							 | 
						||
| 
								 | 
							
								  ;; keyword, usually OSFILE on my system, in angle brackets.
							 | 
						||
| 
								 | 
							
								  ;; This function removes the leading OSFILE bit.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let* ((sysid  (entity-generated-system-id target))
							 | 
						||
| 
								 | 
							
									 (fnbits (split sysid '(#\>)))
							 | 
						||
| 
								 | 
							
									 (fntail (cdr fnbits)))
							 | 
						||
| 
								 | 
							
								    (join fntail "\U-0061;")))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (trim-string str string-list)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY trim-string
							 | 
						||
| 
								 | 
							
								  ;; PURP Trims the tail off of a string
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; If 'str' ends with any of the strings in 'string-list', trim that
							 | 
						||
| 
								 | 
							
								  ;; string off and return the base string.
							 | 
						||
| 
								 | 
							
								  ;; E.g., '(trim-string "filename.sgm" '(".sgm" ".xml" ".sgml"))
							 | 
						||
| 
								 | 
							
								  ;; returns "filename".
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let ((strlen (string-length str)))
							 | 
						||
| 
								 | 
							
								    (let loop ((sl string-list))
							 | 
						||
| 
								 | 
							
								      (if (null? sl)
							 | 
						||
| 
								 | 
							
									  str
							 | 
						||
| 
								 | 
							
									  (if (equal? 
							 | 
						||
| 
								 | 
							
									       (substring str (- strlen (string-length (car sl))) strlen)
							 | 
						||
| 
								 | 
							
									       (car sl))
							 | 
						||
| 
								 | 
							
									      (substring str 0 (- strlen (string-length (car sl))))
							 | 
						||
| 
								 | 
							
									      (loop (cdr sl)))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (string-index source target)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY string-index
							 | 
						||
| 
								 | 
							
								  ;; PURP Finds first occurance of 'target' in 'source'
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; Returns the position of the first occurance of 'target' in 'source',
							 | 
						||
| 
								 | 
							
								  ;; or -1 if it does not occur.
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let loop ((str source) (pos 0))
							 | 
						||
| 
								 | 
							
								    (if (< (string-length str) (string-length target))
							 | 
						||
| 
								 | 
							
									-1
							 | 
						||
| 
								 | 
							
									(if (string=? (substring str 0 (string-length target)) target)
							 | 
						||
| 
								 | 
							
									    pos
							 | 
						||
| 
								 | 
							
									    (loop (substring str 1 (string-length str))
							 | 
						||
| 
								 | 
							
										  (+ pos 1))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (parse-pi-attribute pivalues #!optional (skip #f))
							 | 
						||
| 
								 | 
							
								  (let* ((equalpos (string-index pivalues "="))
							 | 
						||
| 
								 | 
							
									 (name     (substring pivalues 0 equalpos))
							 | 
						||
| 
								 | 
							
									 (quotchar (substring pivalues (+ equalpos 1) (+ equalpos 2)))
							 | 
						||
| 
								 | 
							
									 (rest     (substring pivalues 
							 | 
						||
| 
								 | 
							
											      (+ equalpos 2) 
							 | 
						||
| 
								 | 
							
											      (string-length pivalues)))
							 | 
						||
| 
								 | 
							
									 (quotpos  (string-index rest quotchar))
							 | 
						||
| 
								 | 
							
									 (value    (substring rest 0 quotpos))
							 | 
						||
| 
								 | 
							
									 (morevals (strip (substring rest 
							 | 
						||
| 
								 | 
							
												     (+ quotpos 1) 
							 | 
						||
| 
								 | 
							
												     (string-length rest)))))
							 | 
						||
| 
								 | 
							
								    (if skip
							 | 
						||
| 
								 | 
							
									morevals
							 | 
						||
| 
								 | 
							
									(list name value))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (parse-skip-pi-attribute pivalues)
							 | 
						||
| 
								 | 
							
								  (parse-pi-attribute pivalues #t))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (parse-starttag-pi pi)
							 | 
						||
| 
								 | 
							
								  ;; REFENTRY parse-starttag-pi
							 | 
						||
| 
								 | 
							
								  ;; PURP Parses a structured PI and returns a list of values
							 | 
						||
| 
								 | 
							
								  ;; DESC
							 | 
						||
| 
								 | 
							
								  ;; It has become common practice to give PIs structured values.  The
							 | 
						||
| 
								 | 
							
								  ;; resultis a PI that looks a lot like a start tag with attributes:
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; <?pitarget name1="value1" name2='value2' name3="value '3'">
							 | 
						||
| 
								 | 
							
								  ;; 
							 | 
						||
| 
								 | 
							
								  ;; This function parses a PI with this form and returns a list. The
							 | 
						||
| 
								 | 
							
								  ;; list contains the pitarget and each of the name/value pairs:
							 | 
						||
| 
								 | 
							
								  ;;
							 | 
						||
| 
								 | 
							
								  ;; ("pitarget" "name1" "value1" "name2" "value2" "name3" "value '3'")
							 | 
						||
| 
								 | 
							
								  ;; /DESC
							 | 
						||
| 
								 | 
							
								  ;; /REFENTRY
							 | 
						||
| 
								 | 
							
								  (let* ((strippi (strip pi))
							 | 
						||
| 
								 | 
							
									 (spacepos (string-index strippi " ")))
							 | 
						||
| 
								 | 
							
								    (if (< spacepos 0)
							 | 
						||
| 
								 | 
							
									(list strippi)
							 | 
						||
| 
								 | 
							
									(let* ((pitarget (substring strippi 0 spacepos))
							 | 
						||
| 
								 | 
							
									       (pivalues (strip (substring strippi 
							 | 
						||
| 
								 | 
							
													   (+ spacepos 1)
							 | 
						||
| 
								 | 
							
													   (string-length strippi)))))
							 | 
						||
| 
								 | 
							
									  (let loop ((values pivalues) (result (list pitarget)))
							 | 
						||
| 
								 | 
							
									    (if (string=? values "")
							 | 
						||
| 
								 | 
							
										result
							 | 
						||
| 
								 | 
							
										(loop (parse-skip-pi-attribute values)
							 | 
						||
| 
								 | 
							
										      (append result (parse-pi-attribute values)))))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(define (string->nodes s)
							 | 
						||
| 
								 | 
							
								  ;; Escape XML characters...
							 | 
						||
| 
								 | 
							
								  (let* ((achars (string-replace s "&" "&#38;#38;"))
							 | 
						||
| 
								 | 
							
									 (bchars (string-replace achars "<" "&#38;#60;"))
							 | 
						||
| 
								 | 
							
									 (cchars (string-replace bchars ">" "&#38;#62;")))
							 | 
						||
| 
								 | 
							
								    (let ((doc (string-append "<literal><!DOCTYPE doc [ <!ELEMENT "
							 | 
						||
| 
								 | 
							
											      "doc - - (#PCDATA)> ]><doc>" cchars ";</doc>")))
							 | 
						||
| 
								 | 
							
								      (children (node-property 'docelem (sgml-parse doc))))))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								;; ======================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								</style-specification-body>
							 | 
						||
| 
								 | 
							
								</style-specification>
							 | 
						||
| 
								 | 
							
								</style-sheet>
							 |