#lang racket/base (require racket/class racket/match (prefix-in text: "text-render.rkt") "base-render.rkt" "core.rkt" file/convertible racket/serialize) (provide override-render-mixin-single override-render-mixin-multi) (define (override-render-mixin multi?) (mixin (render<%>) () (super-new) (define/override (render srcs dests ri) (super render srcs dests ri) (for ([part (in-list srcs)] [dest (in-list dests)]) (define p (open-output-string)) (define index-table (make-hash)) (port-count-lines! p) (parameterize ([the-renderer text-renderer] [the-part part] [the-ri ri] [the-text-p p]) (r-part part 'block index-table)) (define table-str (format "~s\n" (serialize index-table))) (define cb.rktd (cond [multi? (build-path dest "blueboxes.rktd")] [else (define-values (base name dir?) (split-path dest)) (build-path base "blueboxes.rktd")])) (call-with-output-file cb.rktd (λ (port) (fprintf port "~a\n" (string-utf-8-length table-str)) (display table-str port) (display (get-output-string p) port)) #:exists 'truncate))) (inherit get-dest-directory) (define text-renderer (new (text:render-mixin render%) [dest-dir (get-dest-directory)])))) (define the-renderer (make-parameter #f)) (define the-part (make-parameter #f)) (define the-ri (make-parameter #f)) (define the-text-p (make-parameter #f)) ;; mode is either ;; 'block -- search for the blue blocks ;; or (cons number number) -- search for tags in a block (define (r-parts parts mode index-table) (for ([part (in-list parts)]) (r-part part mode index-table))) (define (r-part part mode index-table) (r-blocks (part-blocks part) mode index-table) (r-parts (part-parts part) mode index-table)) (define (r-blocks blocks mode index-table) (for ([block (in-list blocks)]) (r-block block mode index-table))) (define (r-block block mode index-table) (match block [(struct nested-flow (style blocks)) (check-and-continue style block mode index-table r-blocks blocks)] [(struct compound-paragraph (style blocks)) (check-and-continue style block mode index-table r-blocks blocks)] [(paragraph style content) (check-and-continue style block mode index-table r-content content)] [(itemization style blockss) (check-and-continue style block mode index-table r-blockss blockss)] [(table style cells) (check-and-continue style block mode index-table r-blockss+cont cells)] [(delayed-block resolve) (r-block (delayed-block-blocks block (the-ri)) mode index-table)] [(traverse-block _) (r-block (traverse-block-block block (the-ri)) mode index-table)])) (define (check-and-continue style block mode index-table sub-f sub-p) (cond [(and (pair? mode) (equal? (style-name style) "RBackgroundLabelInner")) (define background-label-port (car mode)) (parameterize ([current-output-port background-label-port]) (send (the-renderer) render-block block (the-part) (the-ri) #f)) (sub-f sub-p mode index-table)] [(and (eq? mode 'block) (eq? (style-name style) 'boxed) (table? block)) (cond [(for/and ([cells (in-list (table-blockss block))]) (and (not (null? cells)) (null? (cdr cells)) (let ([fst (car cells)]) (and (table? fst) (equal? (style-name (table-style fst)) "together"))))) (for ([cells (in-list (table-blockss block))]) (handle-one-block style (car cells) mode index-table r-block (car cells)))] [else (handle-one-block style block mode index-table sub-f sub-p)])] [else (sub-f sub-p mode index-table)])) (define (handle-one-block style block mode index-table sub-f sub-p) ;(printf "-----\n") ((dynamic-require 'racket/pretty 'pretty-write) block) (define block-port (open-output-string)) (define background-label-port (open-output-string)) (define ents (make-hash)) (define new-mode (cons background-label-port ents)) (port-count-lines! block-port) (port-count-lines! background-label-port) (parameterize ([current-output-port block-port]) (send (the-renderer) render-block block (the-part) (the-ri) #f)) (sub-f sub-p new-mode index-table) ;; we just take the first one here (define background-label-p (open-input-string (get-output-string background-label-port))) (define background-label-line (read-line background-label-p)) (define text-p (the-text-p)) (define-values (before-line _1 _2) (port-next-location text-p)) (define before-position (file-position text-p)) (fprintf text-p "~a\n" (if (eof-object? background-label-line) "" background-label-line)) ;; dump content of block-port into text-p, but first trim ;; the spaces that appear at the ends of the lines (let ([p (open-input-string (get-output-string block-port))]) (let loop () (define l (read-line p)) (unless (eof-object? l) (display (regexp-replace #rx" *$" l "") text-p) (newline text-p) (loop)))) (define-values (after-line _3 _4) (port-next-location text-p)) (define txt-loc (cons before-position (- after-line before-line))) (define ri (the-ri)) (for ([(k v) (in-hash ents)]) (let ([k (tag-key k ri)]) (hash-set! index-table k (cons txt-loc (hash-ref index-table k '())))))) (define (r-blockss+cont blockss mode index-table) (for ([blocks (in-list blockss)]) (for ([block (in-list blocks)]) (unless (eq? block 'cont) (r-block block mode index-table))))) (define (r-blockss blockss mode index-table) (for ([blocks (in-list blockss)]) (r-blocks blocks mode index-table))) (define (r-content content mode index-table) (cond [(element? content) (r-element content mode index-table)] [(list? content) (for ([content (in-list content)]) (r-content content mode index-table))] [(string? content) (void)] [(symbol? content) (void)] [(convertible? content) (void)] [(delayed-element? content) (r-content (delayed-element-content content (the-ri)) mode index-table)] [(traverse-element? content) (r-content (traverse-element-content content (the-ri)) mode index-table)] [(part-relative-element? content) (r-content (part-relative-element-content content (the-ri)) mode index-table)] [(multiarg-element? content) (r-content (multiarg-element-contents content) mode index-table)] [else (error 'r-content "unknown content: ~s\n" content)])) (define (r-element element mode index-table) (when (index-element? element) (when (pair? mode) (define ents (cdr mode)) (define key (index-element-tag element)) (hash-set! ents (tag-key key (the-ri)) #t))) (r-content (element-content element) mode index-table)) (define override-render-mixin-multi (override-render-mixin #t)) (define override-render-mixin-single (override-render-mixin #f))