2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4
;; MODULE : tmtable.scm
5
;; DESCRIPTION : tools for converting tables from and to other formats
6
;; COPYRIGHT : (C) 2002 David Allouche, Joris van der Hoeven
8
;; This software falls under the GNU general public license and comes WITHOUT
9
;; ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for details.
10
;; If you don't have this file, write to the Free Software Foundation, Inc.,
11
;; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
(texmacs-module (convert tools tmtable)
16
(:use (convert tools tmlength) (convert tools tmcolor))
20
tmtable-nrows tmtable-ncols tmtable-cell
22
tmformat-frame tmformat-table
23
tmformat-table-but-top tmformat-table-but-bottom
24
tmformat-table-but-left tmformat-table-but-right
30
tmtable-block-borders tmtable-cell-halign))
32
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
34
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
37
;; WARNING: not portable for long lists
40
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
41
;; Generic table abstraction
42
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
44
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47
(define tmtable-type (make-record-type "tmtable" '(nrows ncols cells formats)))
48
(define tmtable-record (record-constructor tmtable-type))
49
(define tmtable? (record-predicate tmtable-type))
50
(define tmtable-nrows (record-accessor tmtable-type 'nrows))
51
(define tmtable-ncols (record-accessor tmtable-type 'ncols))
52
(define tmtable-cells (record-accessor tmtable-type 'cells))
53
(define tmtable-formats (record-accessor tmtable-type 'formats))
55
(define (tmtable formats cells)
56
;; Public tmtable constructor
57
(tmtable-record (length cells)
58
(list-max (map length cells))
62
(define (tmtable-cell t i j)
63
;; Content of a given cell
64
(list-ref (list-ref (tmtable-cells t) i) j))
66
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
69
(define (tmformat-frame name value)
70
`(twith ,name ,value))
72
;; NOTE: if this list gets too long, we might define region arithmetic.
73
;; This might also be needed for format simplification.
74
(define (tmformat-table name value)
75
`(cwith 1 -1 1 -1 ,name ,value))
76
(define (tmformat-table-but-top name value)
77
`(cwith 2 -1 1 -1 ,name ,value))
78
(define (tmformat-table-but-bottom name value)
79
`(cwith 1 -2 1 -1 ,name ,value))
80
(define (tmformat-table-but-left name value)
81
`(cwith 1 -1 2 -1 ,name ,value))
82
(define (tmformat-table-but-right name value)
83
`(cwith 1 -1 1 -2 ,name ,value))
84
(define (tmformat-cell i j name value)
85
`(cwith ,i ,i ,j ,j ,name ,value))
87
(define (tmformat-frame? f) (func? f 'twith))
88
(define (tmformat-cell? f) (func? f 'cwith))
89
(define (tmformat-cell-name f) (sixth f))
90
(define (tmformat-cell-value f) (seventh f))
92
(define (tmtable-format-on-cell? t f i j)
93
(and (tmformat-cell? f)
94
(with (sym I1 I2 J1 J2 var val) f
95
(let ((i1 (decode-row t I1))
96
(i2 (decode-row t I2))
97
(j1 (decode-column t J1))
98
(j2 (decode-column t J2)))
99
(and (>= i i1) (<= i i2)
100
(>= j j2) (<= j j2))))))
102
(define (tmtable-format-on-row? t f i)
103
(and (tmformat-cell? f)
104
(with (sym I1 I2 J1 J2 var val) f
105
(and (== 1 J1) (== -1 J2)
106
(let ((i1 (decode-row t I1))
107
(i2 (decode-row t I2)))
108
(and (>= i i1) (<= i i2)))))))
110
(define (tmtable-format-on-column? t f j)
111
(and (tmformat-cell? f)
112
(with (sym I1 I2 J1 J2 var val) f
113
(and (== 1 I1) (== -1 I2)
114
(let ((j1 (decode-column t J1))
115
(j2 (decode-column t J2)))
116
(and (>= j j1) (<= j j2)))))))
118
(define (decode i n) (cond ((< i 0) (+ i n)) ((> i 0) (1- i)) (else 0)))
119
(define (decode-row t i) (decode i (tmtable-nrows t)))
120
(define (decode-column t j) (decode j (tmtable-ncols t)))
122
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
123
;; Table format partitioning
125
(define (tmtable-format-partition-by-column t fs)
128
fs (cut tmtable-format-on-column? t <> j)))
129
(iota (tmtable-ncols t))))
131
(define (tmtable-format-partition-by-row t fs)
134
fs (cut tmtable-format-on-row? t <> j)))
135
(iota (tmtable-nrows t))))
137
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
138
;; TODO: simplification of formats.
139
;; remove ignored formats
140
;; collect formats which apply to whole lines/rows/table
141
;; collect formats which apply to ranges of cells/lines/rows
142
;; (giving precedence to extensible boundaries in case of conflict)
144
(define (tmtable-simplify t) (noop t))
146
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
147
;; TeXmacs table parsing
148
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
150
;; A TeXmacs table is a TABLE primitive or a TFORMAT containing a number of
151
;; properties item and terminated by a TABLE or a TFORMAT.
153
;; The TFORMAT properties apply to arbitrary contiguous ranges of the table.
155
;; The properties defined in inner TFORMAT take precedence, so the TFORMAT must
156
;; be read in preorder. In a simple implementation, the TABLE would then be
159
(define (stm-table-cell-content x)
160
;; assert (func? x 'cell)
163
(define (stm-table-row->list x)
164
;; assert (func? x 'row)
165
(map stm-table-cell-content (cdr x)))
167
(define (stm-table-cells x)
168
;; @x must be a TFORMAT or TABLE element
169
;; Return a list of list of cell contents.
170
;; Each inner list correspond to a table row.
171
(map stm-table-row->list
173
((func? x 'table) (cdr x)))))
175
(define (stm-table-formats x)
176
(cond ((func? x 'table) '())
178
(append (map (lambda (f)
179
(with (sym i1 i2 j1 j2 name value) f
186
(stm-table-decode-format name value))))
187
(list-filter (cDdr x) (lambda (l) (= (length l) 7))))
188
(stm-table-formats (cAr x))))
191
(define (stm-table-length-name? name)
193
'("cell-width" "cell-height"
194
"cell-lsep" "cell-rsep" "cell-bsep" "cell-tsep"
195
"cell-lborder" "cell-rborder" "cell-bborder" "cell-tborder"
196
"table-width" "table-height"
197
"table-lsep" "table-rsep" "table-bsep" "table-tsep"
198
"table-lborder" "table-rborder" "table-bborder" "table-tborder")))
200
(define (stm-table-number-name? name)
202
'("cell-row-span" "cell-col-span"
203
"table-row-origin" "table-col-origin"
204
"table-min-rows" "table-min-cols"
205
"table-max-rows" "table-max-cols")))
207
(define (stm-table-color-name? name)
208
(string=? name "cell-background"))
210
(define (stm-table-decode-format name value)
211
((cond ((stm-table-length-name? name)
213
((stm-table-number-name? name)
215
((stm-table-color-name? name)
218
(force-string value)))
220
(define (stm->tmtable x)
221
(tmtable (reverse (stm-table-formats x))
222
(stm-table-cells x)))
224
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
225
;; TeXmacs table output
226
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
228
(define (stm-table-encode-format name value)
229
((cond ((stm-table-length-name? name)
231
((stm-table-number-name? name)
233
((stm-table-color-name? name)
238
(define (tmtable->stm t)
239
(receive (centered formats)
240
(list-partition (tmtable-formats t)
241
(cute == <> (tmformat-table "cell-halign" "c")))
242
`(,(if (null? centered) 'tabular 'tabular*)
246
(cond ((tmformat-cell? f)
247
(with (sym i1 i2 j1 j2 name value) f
249
(number->string i1) (number->string i2)
250
(number->string j1) (number->string j2)
252
(stm-table-encode-format name value))))
254
(with (sym name value) f
256
(stm-table-encode-format name value))))))
258
,(tmtable-cells->stm t)))))
260
(define (tmtable-cells->stm t)
262
(map (lambda (r) (cons 'row (map (cut list 'cell <>) r)))
265
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
266
;; Legacy table parser
267
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
269
(define (tmtable-parser x)
271
(let ((this (stm->tmtable x)))
274
(define (global name)
275
(cond ((eq? name 'border) (any-border?))
276
((eq? name 'nrcols) (tmtable-ncols this))))
278
(cond ((eq? name 'halign) (format-by :column "cell-halign" "l"))
279
((eq? name 'tborder) (length-non-zero-by :column "cell-tborder"))
280
((eq? name 'bborder) (length-non-zero-by :column "cell-bborder"))
281
((eq? name 'lborder) (length-non-zero-by :column "cell-lborder"))
282
((eq? name 'rborder) (length-non-zero-by :column "cell-rborder"))))
284
(cond ((eq? name 'content) (tmtable-cells this))
285
((eq? name 'tborder) (length-non-zero-by :row "cell-tborder"))
286
((eq? name 'bborder) (length-non-zero-by :row "cell-bborder"))
287
((eq? name 'lborder) (length-non-zero-by :row "cell-lborder"))
288
((eq? name 'rborder) (length-non-zero-by :row "cell-rborder"))))
291
(define (table-parser/dispatch scope . args)
292
(apply (cond ((eq? scope 'global) global)
293
((eq? scope 'cols) cols)
294
((eq? scope 'rows) rows)) args))
297
(define (any-border?)
299
(append (append-map cols '(tborder bborder lborder rborder))
300
(append-map rows '(tborder bborder lborder rborder)))))
302
(define (format-by axis name default)
303
(map (lambda (fs) (if (null? fs)
305
(tmformat-cell-value (first fs))))
306
((cond ((eq? axis :row) tmtable-format-partition-by-row)
307
((eq? axis :column) tmtable-format-partition-by-column))
309
(list-filter (tmtable-formats this)
311
(and (tmformat-cell? f)
312
(== name (tmformat-cell-name f))))))))
314
(define (length-non-zero-by axis name)
315
(map (lambda (len) (not (== 0 (tmlength-value len))))
316
(format-by axis name (tmlength))))
318
;; evaluate to dispatcher closure
319
table-parser/dispatch))
321
(define (tmtable-block-borders x)
322
(if x '((cwith "1" "-1" "1" "1" "cell-lborder" "1ln")
323
(cwith "1" "1" "1" "-1" "cell-tborder" "1ln")
324
(cwith "1" "-1" "1" "-1" "cell-bborder" "1ln")
325
(cwith "1" "-1" "1" "-1" "cell-rborder" "1ln"))
328
(define (tmtable-cell-halign x)
329
`((cwith "1" "-1" "1" "-1" "cell-halign" ,x)))