]> git.donarmstrong.com Git - lilypond.git/blob - scripts/as2text.scm
patch::: 1.3.25.jcn2
[lilypond.git] / scripts / as2text.scm
1 #!@GUILE@ \
2 -e main -s
3 !#
4 ;;;; as2text.scm -- Translate AsciiScript to Text
5 ;;;;
6 ;;;; source file of the GNU LilyPond music typesetter
7 ;;;; 
8 ;;;; (c) 2000 Jan Nieuwenhuizen <janneke@gnu.org>
9
10 ;;;; library funtions
11 (use-modules
12    (ice-9 debug)
13   (ice-9 getopt-long)
14   (ice-9 string-fun)
15   (ice-9 regex))
16
17 ;;; Script stuff
18 (define program-name "as2text")
19
20 (define lily-home "/usr/share/lilypond")
21 (define cur-output-name "-")
22 (define cur-output-file '())
23
24 (define subst-version "@TOPLEVEL_VERSION@")
25
26 (define program-version         
27   (if (eq? subst-version (string-append "@" "TOPLEVEL_VERSION" "@"))
28       "unknown"
29       subst-version))
30
31 (define (show-version port)
32   (display (string-append 
33             program-name " - LilyPond version " program-version "\n")
34            port))
35
36 (define (show-help)
37   (display "Convert AsciiScript to text.
38
39
40 Usage: as2text [OPTION]... AS-FILE
41
42 Options:
43   -h,--help          this help
44   -o,--output=FILE   set output file
45   -v,--version       show version
46 "))
47
48 (define (gulp-file name)
49   (let ((port (if (equal? name "-")
50                   (current-input-port)
51                   (catch 'system-error (lambda () (open-file name "r"))
52                          (lambda args #f)))))
53         (if port 
54             (begin
55              (display (string-append "[" name) (current-error-port))
56              (let ((content (let loop ((text ""))
57                                  (let ((line (read-line port)))
58                                       (if (or (eof-object? line)
59                                               (not line)) 
60                                           text
61                                           (loop (string-append text line "\n")))))))
62                   (close port)
63                   (display "]" (current-error-port))
64                   content))
65             (begin
66              (display 
67               (string-append "warning: no such file: " name "\n")
68               (current-error-port))
69              "")))) 
70
71 (define (with-extention name ext)
72   (if (or (equal? name "-") 
73           (equal? ext (substring name (max 0 (- (string-length name) 
74                                                 (string-length ext))))))
75       name 
76       (string-append name ext)))
77
78 (define (do-file file-name output-name)
79   (let ((ascii-script (gulp-file (with-extention file-name ".as"))))
80        ;; urg
81        (set! cur-output-name output-name)
82        (eval-string ascii-script)))
83
84 ;;; Script entry point
85 (define (main args)
86   (set! lily-home (string-append 
87                      (dirname (dirname (car args))) 
88                      "/share/lilypond"))
89   (let ((options (getopt-long args
90                               `((output (single-char #\o)
91                                           (value #t))
92                                 (help (single-char #\h))
93                                 (version (single-char #\v))))))
94     (define (opt tag default)
95       (let ((pair (assq tag options)))
96         (if pair (cdr pair) default)))
97
98     (if (assq 'help options)
99         (begin (show-version (current-output-port)) (show-help) (exit 0)))
100
101     (if (assq 'version options)
102         (begin (show-version (current-output-port)) (exit 0)))
103
104     (show-version (current-error-port))
105     (let ((output-name (opt 'output "-"))
106           (files (let ((foo (opt '() '())))
107                       (if (null? foo) 
108                           (list "-")
109                           foo))))
110          (do-file (car files) output-name))))
111
112 ;;;;
113 ;;;; Ascii Script plotting
114 ;;;;
115
116 ;;; Global variables
117
118 ;; Ascii-Art signature
119 (define tag-line "lily")
120
121 (define first-line #t)
122
123 ;; cursor
124 (define cur-x 0)
125 (define cur-y 0)
126
127 ;; canvas dimensions
128 (define canvas-width 65)
129 (define canvas-height 20)
130
131 ;; font database
132 (define fonts '())
133
134 ;; current font
135 (define cur-font "")
136
137 ;; 
138 (define line-char "-")
139
140 ;; the plotting fields
141 (define canvas 0)
142 ;; urg: 
143 ;; make-uniform array of characters,
144 ;; or 1-dim array of strings?
145 ;; (set! canvas (make-array " " canvas-height canvas-width))
146
147 ;; urg, this kind of naming costs too much indenting
148 (define (split c s r)
149   (separate-fields-discarding-char c s r))
150
151 (define (strip s)
152   (sans-surrounding-whitespace s))
153
154
155 ;;; Helper functions
156
157 (define (af-gulp-file name)
158   ;; urg
159   (let ((old-load-path %load-path))
160        (set! %load-path 
161              (cons (string-append 
162                     (or (getenv 'LILYPONDPREFIX) ".") "/mf")
163                    (cons (string-append lily-home "/mf") %load-path)))
164        (let* ((path (%search-load-path name)) 
165               (text (if path
166                         (gulp-file path)
167                         (gulp-file name))))
168              (set! %load-path old-load-path)
169              text)))
170
171 (define (char-width c)
172   (let ((bbox (car c)))
173        (inexact->exact (* .001 (caddr bbox)))))
174
175 ;; urg: use smart table
176 (define (xmerge-chars old new)
177   (cond ((equal? new " ") old)
178         ((and (equal? old "|") (equal? new "-")) "+")
179         ((and (equal? old "-") (equal? new "|")) "+")
180         (else new)))
181
182 (define (merge-chars old new)
183   (cond ((equal? new " ") old)
184         (else new)))
185
186 (define (plot x y c)
187   (let ((ny (- (* -1 y) 1)))
188        (if (array-in-bounds? canvas ny x)
189            (array-set! canvas (merge-chars (array-ref canvas ny x) c) ny x)
190            (display (string-append "ouch: " (number->string x)  ","
191                                    (number->string ny) "\n")))))
192
193 (define (plot-char c)
194   (let ((bbox (car c))
195         (glyph (cadr c))) 
196        ;; BBox: (llx lly urx ury) * 1000
197        (let ((dx (inexact->exact (* .001 (car bbox))))
198              ;(dy (inexact->exact (* .001 (cadr bbox))))
199              (dy (inexact->exact (- (* .001 (cadddr bbox)) 1)))
200              (len (length glyph)))
201             ;;(display "Bbox: ") (display bbox) (newline)
202             ;;(display "dy: ") (display dy) (newline)
203             (do ((line glyph (cdr line))
204                  (i 0 (+ i 1)))
205                 ((= i len))
206                 (plot-string (+ cur-x dx) (+ (- cur-y i) dy) (car line))))))
207
208 (define (plot-string x y s)
209   (do ((i 0 (+ i 1)))
210       ((= i (string-length s)))
211       (plot (+ x i) y (substring s i (+ i 1)))))
212
213 (define (show-char char)
214   (display char))
215
216 (define (show-font name)
217         (let ((font (assoc name fonts)))
218              (map (lambda (x) (show-char x)) font)))
219
220 (define (sign x)
221   (if (= x 0)
222       1
223       (inexact->exact (/ x (abs x)))))
224
225 (define (generate-default-font)
226   (let loop ((chars '()) (i 0))
227        (if (= 256 i) 
228            chars 
229            (loop 
230             (cons (list i '(0 0 1000 1000) 
231                         (list (make-string 1 (integer->char i)))) 
232                   chars) 
233             (+ i 1)))))
234
235 (define (get-font name)
236   ;; urg
237   (if (equal? name "as-dummy")
238       (get-font "default")
239       (let ((entry (assoc name fonts)))
240            (if entry
241                (cdr entry)
242                (begin
243                 (display 
244                  (string-append "warning: no such font: " name "\n")
245                  (current-error-port))
246                 (get-font "default"))))))
247
248 (define (get-char font n)
249   (let ((entry (assoc n font)))
250        (if entry
251            (cdr entry)
252            (begin
253             (display 
254              (string-append "warning: no such char: (" 
255                             cur-font
256                             ", "
257                             (number->string n ) ")\n")
258              (current-error-port))
259             '()))))
260
261
262 ;;; AsciiScript commands
263
264 (define (char n)
265   (let* ((font (get-font cur-font))
266          (c (get-char font n)))
267         (if c
268             (plot-char c))))
269
270 (define (end-output) 
271   (display (string-append 
272             (make-string 
273              (- canvas-width (string-length tag-line)) #\space)
274             tag-line "\n")
275            cur-output-file)
276   (close cur-output-file)
277   (set! cur-output-file '()))
278
279 (define (h-line len)
280   (let ((step (sign len)))
281        (do ((i 0 (+ i step)))
282            ((= i len))
283            (plot (+ cur-x i) cur-y line-char))))
284
285 (define (v-line len)
286   (let ((step (sign len)))
287        (do ((i 0 (+ i step)))
288            ((= i len)) (plot cur-x (+ cur-y i) line-char))))
289
290 (define (header x y)
291   ;(display (string-append x y "\n") (current-error-port))
292   "")
293
294 (define (header-end) "")
295
296 (define (rline-to dx dy)
297   (plot (inexact->exact cur-x) (inexact->exact cur-y) line-char)
298   (plot (inexact->exact (+ cur-x dx)) (inexact->exact (+ cur-y dy)) line-char)
299   (if (or (> (abs dx) 1) (> (abs dy) 1))
300       (let ((x cur-x)
301             (y cur-y)
302             (hx (/ dx 2))
303             (hy (/ dy 2))
304             )
305            (plot (inexact->exact (+ cur-x hx)) (inexact->exact (+ cur-y hy)) line-char)
306            (rline-to hx hy)
307            (move-to x y)
308            (rmove-to hx hy)
309            (rline-to hx hy)
310            )))
311
312 (define (dissect-char text)
313   (let* ((char (split #\nl text list))
314          (id (car char))
315          (code (string->number 
316                 (strip 
317                  (substring id 
318                             (+ (string-index id #\C) 1)
319                             (string-index id #\;)))))
320          (bbox (map string->number 
321                     (split #\space (strip (substring
322                                            id 
323                                            (+ (string-rindex id #\B) 1)
324                                            (string-rindex id #\;)))
325                            list))))
326         (list (list code bbox (cdr char)))))
327
328 (define (load-font name mag)
329   ;; urg: don't load dummy font
330   (if (not (equal? name "as-dummy"))
331       (let ((text (af-gulp-file (string-append name ".af"))))
332            (if (< 0 (string-length text))
333                (let* ((char-list (cdr 
334                                   (split #\np 
335                                          (regexp-substitute/global 
336                                           #f "\t[^\n]*\n" text 'pre "" 'post) 
337                                          list)))
338                       (font (apply append (map dissect-char char-list))))
339                      (if (< 0 (length font))
340                          (set! fonts (cons (cons name font) fonts))))))))
341
342 (define (move-to x y)
343   (set! cur-x x)
344   (set! cur-y y))
345
346 (define (put c)
347   (plot cur-x cur-y c))
348
349 (define (rmove-to dx dy)
350   (set! cur-x (+ cur-x dx))
351   (set! cur-y (+ cur-y dy)))
352
353 (define (select-font name)
354   (set! cur-font name))
355
356 (define (set-line-char c)
357   (set! line-char c))
358
359 (define (start-line height)
360   (if first-line 
361       (begin
362        (set! fonts (cons (cons "default" (generate-default-font)) fonts))
363        (display "\n" (current-error-port))
364        (if (defined? 'mudelapaperlinewidth)
365            (set! canvas-width 
366                  (inexact->exact (string->number mudelapaperlinewidth))))))
367   (set! canvas-height height)
368   (set! canvas (make-array " " canvas-height canvas-width)))
369
370 (define (stop-line)
371   (if first-line
372       (let ((output-file (if (equal? cur-output-name "-")
373                               (current-output-port)
374                               (open-file cur-output-name "w")))
375              (output-name (if (equal? cur-output-name "-")
376                               "<stdout>"
377                               cur-output-name)))
378             (set! first-line #f)
379             (set! cur-output-file output-file)
380             (display (string-append "text output to " output-name "...\n")
381                      (current-error-port))))
382   (display 
383    (apply string-append 
384           (map (lambda (x) (string-append (apply string-append x) "\n")) 
385                (array->list canvas)))
386    cur-output-file))
387
388 (define (text s)
389   (let ((n (string-length s))
390         (font (get-font cur-font)))
391        (do ((i 0 (+ i 1)))
392            ((= i n)) 
393             (let* ((n (char->integer (string-ref s i)))
394                    (c (get-char font n)))
395                   (plot-char c)
396                   (rmove-to (char-width c) 0)))))
397