summary refs log tree commit diff
diff options
context:
space:
mode:
authorLudovic Courtès2008-10-09 00:15:43 +0200
committerLudovic Courtès2008-10-09 00:15:43 +0200
commit28b6cdaca669977b7ae69c4272f4c121372cb776 (patch)
tree1c959c30957f2c6ad474b74aa8615a5fa42c0d4a
parent5208cd3632a4b6b7da75060e891e81820f35ca1a (diff)
downloadskribilo-28b6cdaca669977b7ae69c4272f4c121372cb776.tar.gz
skribilo-28b6cdaca669977b7ae69c4272f4c121372cb776.tar.lz
skribilo-28b6cdaca669977b7ae69c4272f4c121372cb776.zip
Separate `justify' module from Info engine.
-rw-r--r--src/guile/skribilo/engine/info.scm428
-rw-r--r--src/guile/skribilo/utils/justify.scm425
2 files changed, 426 insertions, 427 deletions
diff --git a/src/guile/skribilo/engine/info.scm b/src/guile/skribilo/engine/info.scm
index de2cab6..e4d3ceb 100644
--- a/src/guile/skribilo/engine/info.scm
+++ b/src/guile/skribilo/engine/info.scm
@@ -32,6 +32,7 @@
   :autoload   (skribilo evaluator)     (evaluate-document)
   :autoload   (skribilo output)        (output)
   :autoload   (skribilo debug)         (*debug*)
+  :autoload   (skribilo utils justify) (make-justifier)
   :use-module (srfi srfi-8)
   :use-module (srfi srfi-13)
 
@@ -701,430 +702,3 @@
               (output label e)
               (output ")" e))))
 
-
-
-;=============== ~/prgm/project/scribe/scribetext/justify.scm ================
-
-;-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----
-;*=====================================================================*/
-;*    serrano/prgm/project/scribe/scribetext/justify.scm               */
-;*    -------------------------------------------------------------    */
-;*    Author      :  Manuel Serrano                                    */
-;*    Creation    :  Thu Nov  1 09:21:20 2001                          */
-;*    Last change :  Sun Dec  9 14:59:11 2001 (serrano)                */
-;*    Copyright   :  2001 Manuel Serrano                               */
-;*    -------------------------------------------------------------    */
-;*    The justifiers                                                   */
-;*=====================================================================*/
-
-;*---------------------------------------------------------------------*/
-;*    The module                                                       */
-;*---------------------------------------------------------------------*/
-(module __scribetext_justify
-   
-   (export (make-justifier::procedure ::int ::symbol)
-	   (output-flush ::int)
-	   
-	   *text-column-width*
-	   *text-justification*
-	   *margin*
-	   
-	   (output ::bstring)
-	   (output-token ::bstring)
-	   (output-center ::bstring)
-	   (output-newline)
-	   (justification-width::int)
-	   (with-justification ::procedure ::procedure . margin)
-	   (with-justification/noflush ::procedure ::procedure . margin))
-   
-   (eval   (export *text-column-width*)
-	   (export *text-justification*)))
-
-;*---------------------------------------------------------------------*/
-;*    *text-column-width* ...                                          */
-;*---------------------------------------------------------------------*/
-(define *text-column-width* 79)
-(define *text-justification* 'left)
-
-;*---------------------------------------------------------------------*/
-;*    text-string ...                                                  */
-;*---------------------------------------------------------------------*/
-(define (text-string str)
-   (let ((len (string-length str)))
-      (let loop ((r 0))
-	 (cond
-	    ((=fx r len)
-	     str)
-	    ((char=? (string-ref str r) #a008)
-	     (string-set! str r #\Space)
-	     (loop (+fx r 1)))
-	    (else
-	     (loop (+fx r 1)))))))
-
-;*---------------------------------------------------------------------*/
-;*    string-replace ...                                               */
-;*---------------------------------------------------------------------*/
-(define (string-replace str1 c1 c2)
-   (let* ((len (string-length str1))
-	  (str2 (make-string len)))
-      (let loop ((r 0))
-	 (if (=fx r len)
-	     str2
-	     (let ((c (string-ref str1 r)))
-		(if (char=? c c1)
-		    (string-set! str2 r c2)
-		    (string-set! str2 r c))
-		(loop (+fx r 1)))))))
-
-;*---------------------------------------------------------------------*/
-;*    output-center ...                                                */
-;*---------------------------------------------------------------------*/
-(define (output-center str)
-   (let ((justifier (make-justifier (justification-width) 'center)))
-      (with-justification justifier
-			  (lambda ()
-			     (output str)))))
-
-;*---------------------------------------------------------------------*/
-;*    *justifiers* ...                                                 */
-;*---------------------------------------------------------------------*/
-(define *justifiers* (list (make-justifier *text-column-width*
-					   *text-justification*)))
-(define *margin* 0)
-
-;*---------------------------------------------------------------------*/
-;*    output ...                                                       */
-;*---------------------------------------------------------------------*/
-(define (output str)
-   ((car *justifiers*) 'output str))
-
-;*---------------------------------------------------------------------*/
-;*    output-token ...                                                 */
-;*    -------------------------------------------------------------    */
-;*    Display one string as if it is one token. No matter if it        */
-;*    contains #\spaces.                                               */
-;*---------------------------------------------------------------------*/
-(define (output-token str)
-   ((car *justifiers*) 'output (string-replace str #\space #a008)))
-
-;*---------------------------------------------------------------------*/
-;*    output-newline ...                                               */
-;*---------------------------------------------------------------------*/
-(define (output-newline)
-   ((car *justifiers*) 'newline))
-   
-;*---------------------------------------------------------------------*/
-;*    pre-output ...                                                   */
-;*---------------------------------------------------------------------*/
-(define (pre-output val)
-   ((car *justifiers*) 'pre val))
-   
-;*---------------------------------------------------------------------*/
-;*    post-output ...                                                  */
-;*---------------------------------------------------------------------*/
-(define (post-output val)
-   ((car *justifiers*) 'post val))
-   
-;*---------------------------------------------------------------------*/
-;*    output-flush ...                                                 */
-;*---------------------------------------------------------------------*/
-(define (output-flush margin)
-   (for-each (if (>fx margin 0)
-		 (let ((m (make-string margin #\space)))
-		    (lambda (x) (print m (text-string x))))
-		 (lambda (x) (print (text-string x))))
-	     ((car *justifiers*) 'flush)))
-
-;*---------------------------------------------------------------------*/
-;*    justification-width ...                                          */
-;*---------------------------------------------------------------------*/
-(define (justification-width)
-   ((car *justifiers*) 'width))
-
-;*---------------------------------------------------------------------*/
-;*    with-justification ...                                           */
-;*---------------------------------------------------------------------*/
-(define (with-justification justifier thunk . margin)
-   (output-flush *margin*)
-   (let ((old-margin *margin*))
-      (if (pair? margin) (set! *margin* (+fx *margin* (car margin))))
-      (set! *justifiers* (cons justifier *justifiers*))
-      (thunk)
-      (output-flush *margin*)
-      (set! *justifiers* (cdr *justifiers*))
-      (set! *margin* old-margin)))
-
-;*---------------------------------------------------------------------*/
-;*    with-justification/noflush ...                                   */
-;*---------------------------------------------------------------------*/
-(define (with-justification/noflush justifier thunk . margin)
-   (let ((old-margin *margin*))
-      (if (pair? margin) (set! *margin* (+fx *margin* (car margin))))
-      (set! *justifiers* (cons justifier *justifiers*))
-      (thunk)
-      (let ((res ((car *justifiers*) 'flush)))
-	 (set! *justifiers* (cdr *justifiers*))
-	 (set! *margin* old-margin)
-	 res)))
-
-;*---------------------------------------------------------------------*/
-;*    *spaces* ...                                                     */
-;*---------------------------------------------------------------------*/
-(define *spaces* '(#\Space #\Tab #\Newline))
-
-;*---------------------------------------------------------------------*/
-;*    strtok ...                                                       */
-;*---------------------------------------------------------------------*/
-(define (strtok str delims)
-   (reverse (kotrts str delims)))
-
-;*---------------------------------------------------------------------*/
-;*    kotrts ...                                                       */
-;*---------------------------------------------------------------------*/
-(define (kotrts str::bstring delims::pair)
-   (let ((stop (string-length str)))
-      (let loop ((cur  0)
-                 (mark #f)
-                 (acc  '()))
-         (cond
-            ((= cur stop)
-             (if (number? mark)
-		 (cons (substring str mark cur) acc)
-                 acc))
-            ((memq (string-ref str cur) delims)
-             (loop (+ cur 1)
-                   #f
-                   (if (number? mark)
-                       (cons (substring str mark cur)
-                             acc)
-                       acc)))
-            (else
-             (loop (+ cur 1)
-                   (if (number? mark) mark cur)
-                   acc))))))
-
-;*---------------------------------------------------------------------*/
-;*    string-insert! ...                                               */
-;*---------------------------------------------------------------------*/
-(define (string-insert! str-to::bstring str-from::bstring offset::int)
-   (let ((len1 (string-length str-to))
-         (len2 (string-length str-from)))
-      (if (> (+ len2 offset) len1)
-          (error "string-insert!" "String too long" str-from)
-          (let loop ((i 0))
-             (if (= i len2)
-                 str-to
-                 (begin
-                    (string-set! str-to
-                                 (+ i offset)
-                                 (string-ref str-from i))
-                    (loop (+ i 1))))))))
-
-;*---------------------------------------------------------------------*/
-;*    make-justified-line ...                                          */
-;*---------------------------------------------------------------------*/
-(define (make-justified-line tokens::pair-nil width::int)
-   (let ((result (make-string width #\space)))
-      (cond
-         ((null? tokens)
-          result)
-         ((null? (cdr tokens))
-          (string-insert! result (car tokens) 0))
-         (else
-          (let* ((nb-tokens  (length tokens))
-                 (nb-chars   (apply + (map string-length
-                                           tokens)))
-                 (all-spaces (- width nb-chars))
-                 (one-spaces (/ all-spaces
-                                (- nb-tokens 1)))
-                 (cursor     (string-length (car tokens))))
-             (string-insert! result (car tokens) 0)
-             (let loop ((tokens (cdr tokens))
-                        (cursor cursor))
-                (if (null? (cdr tokens))
-                    (let* ((len (string-length
-                                 (car tokens)))
-                           (cursor (- width len)))
-                       (string-insert! result
-                                       (car tokens)
-                                       cursor)
-                       result)
-                    (let* ((token    (car tokens))
-                           (token-ln (string-length token))
-                           (n-cursor (+ cursor
-                                        token-ln
-                                        one-spaces))
-                           (offset   (inexact->exact
-                                      (round
-                                       (+ cursor
-                                          one-spaces)))))
-                       (string-insert! result token offset)
-                       (loop (cdr tokens) n-cursor)))))))))
-
-;*---------------------------------------------------------------------*/
-;*    make-formated-line ...                                           */
-;*---------------------------------------------------------------------*/
-(define (make-formated-line tokens::pair-nil width::int cursor::int)
-   (let ((result (make-string width #\space)))
-      (if (null? tokens)
-          result
-          (let loop ((toks tokens)
-                     (cur cursor))
-             (if (null? toks)
-                 result
-                 (begin
-                    (string-insert! result (car toks) cur)
-                    (loop (cdr toks)
-                          (+ 1
-                             cur
-                             (string-length
-			      (car toks))))))))))
-
-;*---------------------------------------------------------------------*/
-;*    make-centered-line ...                                           */
-;*---------------------------------------------------------------------*/
-(define (make-centered-line tokens::pair-nil width::int)
-   (make-formated-line tokens
-		       width
-		       (quotient (- width
-				    (+ (apply + (map string-length tokens))
-				       (- (length tokens) 1)))
-				 2)))
-
-;*---------------------------------------------------------------------*/
-;*    make-flushleft-line ...                                          */
-;*---------------------------------------------------------------------*/
-(define (make-flushleft-line tokens::pair-nil width::int)
-   (make-formated-line tokens width 0))
-
-;*---------------------------------------------------------------------*/
-;*    make-flushright-line ...                                         */
-;*---------------------------------------------------------------------*/
-(define (make-flushright-line tokens::pair-nil width::int)
-   (make-formated-line tokens
-		       width
-		       (- width
-			  (+ (apply + (map string-length tokens))
-			     (- (length tokens) 1)))))
-
-;*---------------------------------------------------------------------*/
-;*    tokens-justify ...                                               */
-;*---------------------------------------------------------------------*/
-(define (tokens-justify justifier::procedure tokens::pair-nil width::int)
-   (define (reverse-line lines)
-      (let ((nl (string #\Newline)))
-         (let loop ((ls lines)
-                    (acc ""))
-            (if (null? ls)
-                acc
-                (loop (cdr ls) (string-append (car ls) nl acc))))))
-   (let loop ((tokens    tokens)
-              (line-len  0)
-              (line     '())
-              (acc      '()))
-      (if (null? tokens)
-          (reverse! (cons (justifier (reverse line) width) acc))
-          (let ((tok (car tokens)))
-	     (cond
-		((eq? tok 'NEWLINE)
-		 (loop (cdr tokens)
-		       0
-		       '()
-		       (cons (justifier (reverse line) width) acc)))
-		(else
-		 (let ((toklen (string-length tok)))
-		    (cond
-		       ((>= toklen width)
-			(let ((jl (justifier (list (substring tok 0 width))
-					     width))
-			      (ll (if (pair? line)
-				      (cons (justifier (reverse line) width)
-					    acc)
-				      acc)))
-			   (loop (cdr tokens)
-				 0
-				 '()
-				 (cons jl ll))))
-		       ((>= (+ toklen line-len) width)
-			(loop tokens
-			      0
-			      '()
-			      (cons (justifier (reverse line) width) acc)))
-		       (else
-			(loop (cdr tokens)
-			      (+ line-len toklen 1)
-			      (cons tok line)
-			      acc))))))))))
- 
-;*---------------------------------------------------------------------*/
-;*    make-justifier ...                                               */
-;*---------------------------------------------------------------------*/
-(define (make-justifier width policy)
-   (let ((tokens '()))
-      (if (eq? policy 'verbatim)
-	  (lambda (cmd . vals)
-	     (case cmd
-		((output)
-		 (set! tokens (append (reverse vals) tokens)))
-		((newline)
-		 (set! tokens (cons "\n" tokens)))
-		((flush)
-		 (let ((str (apply string-append (reverse! tokens))))
-		    (set! tokens '())
-		    (list str)))
-		((width)
-		 width)))
-	  (let ((justifier (case policy
-			      ((center)
-			       make-centered-line)
-			      ((flushleft left)
-			       make-flushleft-line)
-			      ((flushright right)
-			       make-flushright-line)
-			      ((justify)
-			       make-justified-line)
-			      (else
-			       make-justified-line)))
-		(last ""))
-	     (lambda (cmd . vals)
-		(case cmd
-		   ((newline)
-		    (set! tokens (cons 'NEWLINE
-				       (append (kotrts last *spaces*) tokens)))
-		    (set! last ""))
-		   ((output)
-		    (if (pair? vals)
-			(let* ((val0 (string-append last (car vals)))
-			       (vals (cons val0 (cdr vals))))
-			   (let loop ((vals vals)
-				      (toks tokens))
-			      (cond
-				 ((null? vals)
-				  (set! last "")
-				  (set! tokens toks))
-				 ((and (null? (cdr vals))
-				       (string? (car vals)))
-				  (set! last (car vals))
-				  (set! tokens toks))
-				 (else
-				  (loop (cdr vals)
-					(append (kotrts (car vals) *spaces*)
-						toks))))))))
-		   ((flush)
-		    (let ((ntokens (append (kotrts last *spaces*) tokens)))
-		       (set! last "")
-		       (if (pair? ntokens)
-			   (let ((toks (reverse! ntokens)))
-			      (set! tokens '())
-			      (tokens-justify justifier toks width))
-			   '())))
-		   ((width)
-		    width)
-		   (else
-		    (error "justifier" "Illegal command" cmd))))))))
-
-(define (my-string-append . s)
-   (newline (current-error-port))
-   (fprint (current-error-port) "s: " s)
-   (apply string-append s))
-
diff --git a/src/guile/skribilo/utils/justify.scm b/src/guile/skribilo/utils/justify.scm
new file mode 100644
index 0000000..8e069af
--- /dev/null
+++ b/src/guile/skribilo/utils/justify.scm
@@ -0,0 +1,425 @@
+;=============== ~/prgm/project/scribe/scribetext/justify.scm ================
+
+;-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----
+;*=====================================================================*/
+;*    serrano/prgm/project/scribe/scribetext/justify.scm               */
+;*    -------------------------------------------------------------    */
+;*    Author      :  Manuel Serrano                                    */
+;*    Creation    :  Thu Nov  1 09:21:20 2001                          */
+;*    Last change :  Sun Dec  9 14:59:11 2001 (serrano)                */
+;*    Copyright   :  2001 Manuel Serrano                               */
+;*    -------------------------------------------------------------    */
+;*    The justifiers                                                   */
+;*=====================================================================*/
+
+;*---------------------------------------------------------------------*/
+;*    The module                                                       */
+;*---------------------------------------------------------------------*/
+(module __scribetext_justify
+   
+   (export (make-justifier::procedure ::int ::symbol)
+	   (output-flush ::int)
+	   
+	   *text-column-width*
+	   *text-justification*
+	   *margin*
+	   
+	   (output ::bstring)
+	   (output-token ::bstring)
+	   (output-center ::bstring)
+	   (output-newline)
+	   (justification-width::int)
+	   (with-justification ::procedure ::procedure . margin)
+	   (with-justification/noflush ::procedure ::procedure . margin))
+   
+   (eval   (export *text-column-width*)
+	   (export *text-justification*)))
+
+;*---------------------------------------------------------------------*/
+;*    *text-column-width* ...                                          */
+;*---------------------------------------------------------------------*/
+(define *text-column-width* 79)
+(define *text-justification* 'left)
+
+;*---------------------------------------------------------------------*/
+;*    text-string ...                                                  */
+;*---------------------------------------------------------------------*/
+(define (text-string str)
+   (let ((len (string-length str)))
+      (let loop ((r 0))
+	 (cond
+	    ((=fx r len)
+	     str)
+	    ((char=? (string-ref str r) #a008)
+	     (string-set! str r #\Space)
+	     (loop (+fx r 1)))
+	    (else
+	     (loop (+fx r 1)))))))
+
+;*---------------------------------------------------------------------*/
+;*    string-replace ...                                               */
+;*---------------------------------------------------------------------*/
+(define (string-replace str1 c1 c2)
+   (let* ((len (string-length str1))
+	  (str2 (make-string len)))
+      (let loop ((r 0))
+	 (if (=fx r len)
+	     str2
+	     (let ((c (string-ref str1 r)))
+		(if (char=? c c1)
+		    (string-set! str2 r c2)
+		    (string-set! str2 r c))
+		(loop (+fx r 1)))))))
+
+;*---------------------------------------------------------------------*/
+;*    output-center ...                                                */
+;*---------------------------------------------------------------------*/
+(define (output-center str)
+   (let ((justifier (make-justifier (justification-width) 'center)))
+      (with-justification justifier
+			  (lambda ()
+			     (output str)))))
+
+;*---------------------------------------------------------------------*/
+;*    *justifiers* ...                                                 */
+;*---------------------------------------------------------------------*/
+(define *justifiers* (list (make-justifier *text-column-width*
+					   *text-justification*)))
+(define *margin* 0)
+
+;*---------------------------------------------------------------------*/
+;*    output ...                                                       */
+;*---------------------------------------------------------------------*/
+(define (output str)
+   ((car *justifiers*) 'output str))
+
+;*---------------------------------------------------------------------*/
+;*    output-token ...                                                 */
+;*    -------------------------------------------------------------    */
+;*    Display one string as if it is one token. No matter if it        */
+;*    contains #\spaces.                                               */
+;*---------------------------------------------------------------------*/
+(define (output-token str)
+   ((car *justifiers*) 'output (string-replace str #\space #a008)))
+
+;*---------------------------------------------------------------------*/
+;*    output-newline ...                                               */
+;*---------------------------------------------------------------------*/
+(define (output-newline)
+   ((car *justifiers*) 'newline))
+   
+;*---------------------------------------------------------------------*/
+;*    pre-output ...                                                   */
+;*---------------------------------------------------------------------*/
+(define (pre-output val)
+   ((car *justifiers*) 'pre val))
+   
+;*---------------------------------------------------------------------*/
+;*    post-output ...                                                  */
+;*---------------------------------------------------------------------*/
+(define (post-output val)
+   ((car *justifiers*) 'post val))
+   
+;*---------------------------------------------------------------------*/
+;*    output-flush ...                                                 */
+;*---------------------------------------------------------------------*/
+(define (output-flush margin)
+   (for-each (if (>fx margin 0)
+		 (let ((m (make-string margin #\space)))
+		    (lambda (x) (print m (text-string x))))
+		 (lambda (x) (print (text-string x))))
+	     ((car *justifiers*) 'flush)))
+
+;*---------------------------------------------------------------------*/
+;*    justification-width ...                                          */
+;*---------------------------------------------------------------------*/
+(define (justification-width)
+   ((car *justifiers*) 'width))
+
+;*---------------------------------------------------------------------*/
+;*    with-justification ...                                           */
+;*---------------------------------------------------------------------*/
+(define (with-justification justifier thunk . margin)
+   (output-flush *margin*)
+   (let ((old-margin *margin*))
+      (if (pair? margin) (set! *margin* (+fx *margin* (car margin))))
+      (set! *justifiers* (cons justifier *justifiers*))
+      (thunk)
+      (output-flush *margin*)
+      (set! *justifiers* (cdr *justifiers*))
+      (set! *margin* old-margin)))
+
+;*---------------------------------------------------------------------*/
+;*    with-justification/noflush ...                                   */
+;*---------------------------------------------------------------------*/
+(define (with-justification/noflush justifier thunk . margin)
+   (let ((old-margin *margin*))
+      (if (pair? margin) (set! *margin* (+fx *margin* (car margin))))
+      (set! *justifiers* (cons justifier *justifiers*))
+      (thunk)
+      (let ((res ((car *justifiers*) 'flush)))
+	 (set! *justifiers* (cdr *justifiers*))
+	 (set! *margin* old-margin)
+	 res)))
+
+;*---------------------------------------------------------------------*/
+;*    *spaces* ...                                                     */
+;*---------------------------------------------------------------------*/
+(define *spaces* '(#\Space #\Tab #\Newline))
+
+;*---------------------------------------------------------------------*/
+;*    strtok ...                                                       */
+;*---------------------------------------------------------------------*/
+(define (strtok str delims)
+   (reverse (kotrts str delims)))
+
+;*---------------------------------------------------------------------*/
+;*    kotrts ...                                                       */
+;*---------------------------------------------------------------------*/
+(define (kotrts str::bstring delims::pair)
+   (let ((stop (string-length str)))
+      (let loop ((cur  0)
+                 (mark #f)
+                 (acc  '()))
+         (cond
+            ((= cur stop)
+             (if (number? mark)
+		 (cons (substring str mark cur) acc)
+                 acc))
+            ((memq (string-ref str cur) delims)
+             (loop (+ cur 1)
+                   #f
+                   (if (number? mark)
+                       (cons (substring str mark cur)
+                             acc)
+                       acc)))
+            (else
+             (loop (+ cur 1)
+                   (if (number? mark) mark cur)
+                   acc))))))
+
+;*---------------------------------------------------------------------*/
+;*    string-insert! ...                                               */
+;*---------------------------------------------------------------------*/
+(define (string-insert! str-to::bstring str-from::bstring offset::int)
+   (let ((len1 (string-length str-to))
+         (len2 (string-length str-from)))
+      (if (> (+ len2 offset) len1)
+          (error "string-insert!" "String too long" str-from)
+          (let loop ((i 0))
+             (if (= i len2)
+                 str-to
+                 (begin
+                    (string-set! str-to
+                                 (+ i offset)
+                                 (string-ref str-from i))
+                    (loop (+ i 1))))))))
+
+;*---------------------------------------------------------------------*/
+;*    make-justified-line ...                                          */
+;*---------------------------------------------------------------------*/
+(define (make-justified-line tokens::pair-nil width::int)
+   (let ((result (make-string width #\space)))
+      (cond
+         ((null? tokens)
+          result)
+         ((null? (cdr tokens))
+          (string-insert! result (car tokens) 0))
+         (else
+          (let* ((nb-tokens  (length tokens))
+                 (nb-chars   (apply + (map string-length
+                                           tokens)))
+                 (all-spaces (- width nb-chars))
+                 (one-spaces (/ all-spaces
+                                (- nb-tokens 1)))
+                 (cursor     (string-length (car tokens))))
+             (string-insert! result (car tokens) 0)
+             (let loop ((tokens (cdr tokens))
+                        (cursor cursor))
+                (if (null? (cdr tokens))
+                    (let* ((len (string-length
+                                 (car tokens)))
+                           (cursor (- width len)))
+                       (string-insert! result
+                                       (car tokens)
+                                       cursor)
+                       result)
+                    (let* ((token    (car tokens))
+                           (token-ln (string-length token))
+                           (n-cursor (+ cursor
+                                        token-ln
+                                        one-spaces))
+                           (offset   (inexact->exact
+                                      (round
+                                       (+ cursor
+                                          one-spaces)))))
+                       (string-insert! result token offset)
+                       (loop (cdr tokens) n-cursor)))))))))
+
+;*---------------------------------------------------------------------*/
+;*    make-formated-line ...                                           */
+;*---------------------------------------------------------------------*/
+(define (make-formated-line tokens::pair-nil width::int cursor::int)
+   (let ((result (make-string width #\space)))
+      (if (null? tokens)
+          result
+          (let loop ((toks tokens)
+                     (cur cursor))
+             (if (null? toks)
+                 result
+                 (begin
+                    (string-insert! result (car toks) cur)
+                    (loop (cdr toks)
+                          (+ 1
+                             cur
+                             (string-length
+			      (car toks))))))))))
+
+;*---------------------------------------------------------------------*/
+;*    make-centered-line ...                                           */
+;*---------------------------------------------------------------------*/
+(define (make-centered-line tokens::pair-nil width::int)
+   (make-formated-line tokens
+		       width
+		       (quotient (- width
+				    (+ (apply + (map string-length tokens))
+				       (- (length tokens) 1)))
+				 2)))
+
+;*---------------------------------------------------------------------*/
+;*    make-flushleft-line ...                                          */
+;*---------------------------------------------------------------------*/
+(define (make-flushleft-line tokens::pair-nil width::int)
+   (make-formated-line tokens width 0))
+
+;*---------------------------------------------------------------------*/
+;*    make-flushright-line ...                                         */
+;*---------------------------------------------------------------------*/
+(define (make-flushright-line tokens::pair-nil width::int)
+   (make-formated-line tokens
+		       width
+		       (- width
+			  (+ (apply + (map string-length tokens))
+			     (- (length tokens) 1)))))
+
+;*---------------------------------------------------------------------*/
+;*    tokens-justify ...                                               */
+;*---------------------------------------------------------------------*/
+(define (tokens-justify justifier::procedure tokens::pair-nil width::int)
+   (define (reverse-line lines)
+      (let ((nl (string #\Newline)))
+         (let loop ((ls lines)
+                    (acc ""))
+            (if (null? ls)
+                acc
+                (loop (cdr ls) (string-append (car ls) nl acc))))))
+   (let loop ((tokens    tokens)
+              (line-len  0)
+              (line     '())
+              (acc      '()))
+      (if (null? tokens)
+          (reverse! (cons (justifier (reverse line) width) acc))
+          (let ((tok (car tokens)))
+	     (cond
+		((eq? tok 'NEWLINE)
+		 (loop (cdr tokens)
+		       0
+		       '()
+		       (cons (justifier (reverse line) width) acc)))
+		(else
+		 (let ((toklen (string-length tok)))
+		    (cond
+		       ((>= toklen width)
+			(let ((jl (justifier (list (substring tok 0 width))
+					     width))
+			      (ll (if (pair? line)
+				      (cons (justifier (reverse line) width)
+					    acc)
+				      acc)))
+			   (loop (cdr tokens)
+				 0
+				 '()
+				 (cons jl ll))))
+		       ((>= (+ toklen line-len) width)
+			(loop tokens
+			      0
+			      '()
+			      (cons (justifier (reverse line) width) acc)))
+		       (else
+			(loop (cdr tokens)
+			      (+ line-len toklen 1)
+			      (cons tok line)
+			      acc))))))))))
+ 
+;*---------------------------------------------------------------------*/
+;*    make-justifier ...                                               */
+;*---------------------------------------------------------------------*/
+(define (make-justifier width policy)
+   (let ((tokens '()))
+      (if (eq? policy 'verbatim)
+	  (lambda (cmd . vals)
+	     (case cmd
+		((output)
+		 (set! tokens (append (reverse vals) tokens)))
+		((newline)
+		 (set! tokens (cons "\n" tokens)))
+		((flush)
+		 (let ((str (apply string-append (reverse! tokens))))
+		    (set! tokens '())
+		    (list str)))
+		((width)
+		 width)))
+	  (let ((justifier (case policy
+			      ((center)
+			       make-centered-line)
+			      ((flushleft left)
+			       make-flushleft-line)
+			      ((flushright right)
+			       make-flushright-line)
+			      ((justify)
+			       make-justified-line)
+			      (else
+			       make-justified-line)))
+		(last ""))
+	     (lambda (cmd . vals)
+		(case cmd
+		   ((newline)
+		    (set! tokens (cons 'NEWLINE
+				       (append (kotrts last *spaces*) tokens)))
+		    (set! last ""))
+		   ((output)
+		    (if (pair? vals)
+			(let* ((val0 (string-append last (car vals)))
+			       (vals (cons val0 (cdr vals))))
+			   (let loop ((vals vals)
+				      (toks tokens))
+			      (cond
+				 ((null? vals)
+				  (set! last "")
+				  (set! tokens toks))
+				 ((and (null? (cdr vals))
+				       (string? (car vals)))
+				  (set! last (car vals))
+				  (set! tokens toks))
+				 (else
+				  (loop (cdr vals)
+					(append (kotrts (car vals) *spaces*)
+						toks))))))))
+		   ((flush)
+		    (let ((ntokens (append (kotrts last *spaces*) tokens)))
+		       (set! last "")
+		       (if (pair? ntokens)
+			   (let ((toks (reverse! ntokens)))
+			      (set! tokens '())
+			      (tokens-justify justifier toks width))
+			   '())))
+		   ((width)
+		    width)
+		   (else
+		    (error "justifier" "Illegal command" cmd))))))))
+
+(define (my-string-append . s)
+   (newline (current-error-port))
+   (fprint (current-error-port) "s: " s)
+   (apply string-append s))
+