1if not modules then modules = { } end modules ["page-cst"] = {
2 version = 1.001,
3 comment = "companion to page-cst.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9local next, type, tonumber, rawget = next, type, tonumber, rawget
10local ceil, odd, round, abs = math.ceil, math.odd, math.round, math.abs
11local lower = string.lower
12local copy = table.copy
13
14local trace_state = false trackers.register("columnsets.trace", function(v) trace_state = v end)
15local trace_details = false trackers.register("columnsets.details", function(v) trace_details = v end)
16local trace_cells = false trackers.register("columnsets.cells", function(v) trace_cells = v end)
17
18local report = logs.reporter("column sets")
19
20local setmetatableindex = table.setmetatableindex
21
22local properties = nodes.properties.data
23
24local nuts = nodes.nuts
25local tonode = nuts.tonode
26local tonut = nuts.tonut
27
28local setlink = nuts.setlink
29local setbox = nuts.setbox
30local getwhd = nuts.getwhd
31local setwhd = nuts.setwhd
32
33local getlist = nuts.getlist
34local takebox = nuts.takebox
35local splitbox = nuts.splitbox
36local vpack = nuts.vpack
37
38local getbox = nuts.getbox
39
40local texgetcount = tex.getcount
41local texgetdimen = tex.getdimen
42local texsetcount = tex.setcount
43local texsetdimen = tex.setdimen
44
45local theprop = nuts.theprop
46
47local nodepool = nuts.pool
48local new_vlist = nodepool.vlist
49local new_trace_rule = nodepool.rule
50local new_empty_rule = nodepool.emptyrule
51
52local context = context
53local implement = interfaces.implement
54
55local variables = interfaces.variables
56local v_here = variables.here
57local v_fixed = variables.fixed
58local v_top = variables.top
59local v_bottom = variables.bottom
60local v_repeat = variables["repeat"]
61local v_yes = variables.yes
62local v_page = variables.page
63local v_first = variables.first
64local v_last = variables.last
65
66
67pagebuilders = pagebuilders or { }
68local columnsets = pagebuilders.columnsets or { }
69
70pagebuilders.columnsets = columnsets
71
72local data = { [""] = { } }
73
74
75
76local function setstate(t,start)
77 if start or not t.firstcolumn then
78 t.firstcolumn = odd(texgetcount("realpageno")) and 1 or 2
79 end
80 if t.firstcolumn > 1 then
81 t.firstcolumn = 1
82 t.lastcolumn = t.nofleft
83 t.state = "left"
84 else
85 t.firstcolumn = t.nofleft + 1
86 t.lastcolumn = t.firstcolumn + t.nofright - 1
87 t.state = "right"
88 end
89 t.currentcolumn = t.firstcolumn
90 t.currentrow = 1
91end
92
93function columnsets.define(t)
94 local name = t.name
95 local nofleft = t.nofleft or 1
96 local nofright = t.nofright or 1
97 local nofcolumns = nofleft + nofright
98 local dataset = data[name] or { }
99 data[name] = dataset
100 dataset.nofleft = nofleft
101 dataset.nofright = nofright
102 dataset.nofcolumns = nofcolumns
103 dataset.nofrows = t.nofrows or 1
104 dataset.distance = t.distance or texgetdimen("bodyfontsize")
105 dataset.maxwidth = t.maxwidth or texgetdimen("makeupwidth")
106 dataset.lineheight = t.lineheight or texgetdimen("globalbodyfontstrutheight")
107 dataset.linedepth = t.linedepth or texgetdimen("globalbodyfontstrutdepth")
108
109 dataset.cells = { }
110 dataset.currentcolumn = 1
111 dataset.currentrow = 1
112
113 dataset.lines = dataset.lines or setmetatableindex("table")
114 dataset.start = dataset.start or setmetatableindex("table")
115
116 dataset.page = 1
117
118 local distances = dataset.distances or setmetatableindex(function(t,k)
119 return dataset.distance
120 end)
121 dataset.distances = distances
122
123 local widths = dataset.widths or setmetatableindex(function(t,k)
124 return dataset.width
125 end)
126 dataset.widths = widths
127
128 local width = t.width
129 if not width or width == 0 then
130 local dl = 0
131 local dr = 0
132 for i=1,nofleft-1 do
133 dl = dl + distances[i]
134 end
135 for i=1,nofright-1 do
136 dr = dr + distances[nofleft+i]
137 end
138 local nl = nofleft
139 local nr = nofright
140 local wl = dataset.maxwidth
141 local wr = wl
142 for i=1,nofleft do
143 local w = rawget(widths,i)
144 if w then
145 nl = nl - 1
146 wl = wl - w
147 end
148 end
149 for i=1,nofright do
150 local w = rawget(widths,nofleft+i)
151 if w then
152 nr = nr - 1
153 wr = wr - w
154 end
155 end
156 dl = (wl - dl) / nl
157 dr = (wr - dr) / nr
158 if dl > dr then
159 report("using %s page column width %p in columnset %a","right",dr,name)
160 width = dr
161 elseif dl < dr then
162 report("using %s page column width %p in columnset %a","left",dl,name)
163 width = dl
164 else
165 width = dl
166 end
167 end
168
169 width = round(width)
170 dataset.width = width
171 local spans = { }
172 dataset.spans = spans
173 for i=1,nofleft do
174 local s = { }
175 local d = 0
176 for j=1,nofleft-i+1 do
177 d = d + width
178 s[j] = round(d)
179 d = d + distances[j]
180 end
181 spans[i] = s
182 end
183 for i=1,nofright do
184 local s = { }
185 local d = 0
186 for j=1,nofright-i+1 do
187 d = d + width
188 s[j] = round(d)
189 d = d + distances[j]
190 end
191 spans[nofleft+i] = s
192 end
193
194 local spreads = copy(spans)
195 dataset.spreads = spreads
196 local gap = 2 * texgetdimen("backspace")
197 for l=1,nofleft do
198 local s = spreads[l]
199 local n = #s
200 local o = s[n] + gap
201 for r=1,nofright do
202 n = n + 1
203 s[n] = s[r] + o
204 end
205 end
206
207 texsetdimen("d_page_grd_column_width",dataset.width)
208
209 setstate(dataset,true)
210
211 return dataset
212end
213
214local function check(dataset)
215 local cells = dataset.cells
216 local page = dataset.page
217 local offset = odd(page) and dataset.nofleft or 0
218 local start = dataset.start
219 local list = rawget(start,page)
220 if list then
221 for c, n in next, list do
222 local column = cells[offset + c]
223 if column then
224 for r=1,n do
225 column[r] = true
226 end
227 end
228 end
229 start[page] = nil
230 end
231 local lines = dataset.lines
232 local list = rawget(lines,page)
233 local rows = dataset.nofrows
234 if list then
235 for c, n in next, list do
236 local column = cells[offset + c]
237 if column then
238 if n > 0 then
239 for r=n+1,rows do
240 column[r] = true
241 end
242 elseif n < 0 then
243 for r=rows,rows+n+1,-1 do
244 column[r] = true
245 end
246 end
247 end
248 end
249 lines[page] = nil
250 end
251end
252
253local function erase(dataset,all)
254 local cells = dataset.cells
255 local nofrows = dataset.nofrows
256 local first = 1
257 local last = dataset.nofcolumns
258
259 if not all then
260 first = dataset.firstcolumn or first
261 last = dataset.lastcolumn or last
262 end
263 for c=first,last do
264 local column = { }
265 for r=1,nofrows do
266 if column[r] then
267 report("slot (%i,%i) is not empty",c,r)
268 end
269 column[r] = false
270 end
271 cells[c] = column
272 end
273end
274
275function columnsets.reset(t)
276 local dataset = columnsets.define(t)
277 erase(dataset,true)
278 check(dataset)
279end
280
281function columnsets.prepareflush(name)
282 local dataset = data[name]
283 local cells = dataset.cells
284 local firstcolumn = dataset.firstcolumn
285 local lastcolumn = dataset.lastcolumn
286 local nofrows = dataset.nofrows
287 local lineheight = dataset.lineheight
288 local linedepth = dataset.linedepth
289 local widths = dataset.widths
290 local height = (lineheight+linedepth)*nofrows
291
292 local columns = { }
293 dataset.columns = columns
294
295 for c=firstcolumn,lastcolumn do
296 local column = cells[c]
297 for r=1,nofrows do
298 local cell = column[r]
299 if (cell == false) or (cell == true) then
300 if trace_cells then
301 column[r] = new_trace_rule(65536*2,lineheight,linedepth)
302 else
303 column[r] = new_empty_rule(0,lineheight,linedepth)
304 end
305 end
306 end
307 for r=1,nofrows-1 do
308 setlink(column[r],column[r+1])
309 end
310 columns[c] = new_vlist(column[1],widths[c],height,0)
311 end
312
313 texsetcount("c_page_grd_first_column",firstcolumn)
314 texsetcount("c_page_grd_last_column",lastcolumn)
315end
316
317function columnsets.flushcolumn(name,column)
318 local dataset = data[name]
319 local columns = dataset.columns
320 local packed = columns[column]
321 setbox("b_page_grd_column",packed)
322 columns[column] = nil
323end
324
325function columnsets.finishflush(name)
326 local dataset = data[name]
327 local cells = dataset.cells
328 local firstcolumn = dataset.firstcolumn
329 local lastcolumn = dataset.lastcolumn
330 local nofrows = dataset.nofrows
331 for c=firstcolumn,lastcolumn do
332 local column = { }
333 for r=1,nofrows do
334 column[r] = false
335 end
336 cells[c] = column
337 end
338 dataset.page = dataset.page + 1
339 check(dataset)
340 setstate(dataset)
341end
342
343function columnsets.block(t)
344 local dataset = data[t.name]
345 local cells = dataset.cells
346 local nofcolumns = dataset.nofcolumns
347 local nofrows = dataset.nofrows
348
349 local c = t.c or 0
350 local r = t.r or 0
351 if c == 0 or r == 0 or c > nofcolumns or r > nofrows then
352 return
353 end
354 local nc = t.nc or 0
355 local nr = t.nr or 0
356 if nc == 0 then
357 return
358 end
359 if nr == 0 then
360 return
361 end
362 local rr = r + nr - 1
363 local cc = c + nc - 1
364 if rr > nofrows then
365 rr = nofrows
366 end
367 if cc > nofcolumns then
368 cc = nofcolumns
369 end
370 for i=c,cc do
371 local column = cells[i]
372 for j=r,rr do
373 column[j] = true
374 end
375 end
376end
377
378local function here(c,r,nr,nofcolumns,nofrows,cells,width,spans)
379 local rr = r + nr - 1
380 if rr > nofrows then
381 report("%i rows needed, %i rows available, no slots free at (%i,%i), discarding",rr,nofrows,c,r)
382 return false
383 end
384 local cc = 0
385 local wd = spans[c]
386 local wc = 0
387 local nc = 0
388 for i=c,nofcolumns do
389 nc = nc + 1
390 wc = wd[nc]
391 if not wc then
392 break
393 elseif wc >= width then
394 cc = i
395 break
396 end
397 end
398 if cc == 0 or cc > nofcolumns then
399 report("needed %p, no slot free at (%i,%i), discarding",width,c,r)
400 return false
401 end
402 for i=c,cc do
403 local column = cells[i]
404 for j=r,rr do
405 if column[j] then
406 report("width %p, needed %p, checking (%i,%i) x (%i,%i), %s",width,wc,c,r,nc,nr,"quit")
407 return false
408 end
409 end
410 end
411
412 return c, r, nc
413end
414
415
416
417local methods = {
418 [v_here] = here,
419 [v_fixed] = here,
420 tblr = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
421 for j=r,nofrows-nr+1 do
422 for i=c,nofcolumns do
423 if not cells[i][j] then
424 local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
425 if c then
426 return c, r, cc
427 end
428 end
429 end
430 end
431 end,
432 lrtb = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
433 for i=c,nofcolumns do
434 for j=r,nofrows-nr+1 do
435 if not cells[i][j] then
436 local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
437 if c then
438 return c, r, cc
439 end
440 end
441 end
442 end
443 end,
444 tbrl = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
445 for j=r,nofrows-nr+1 do
446 for i=nofcolumns,c,-1 do
447 if not cells[i][j] then
448 local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
449 if c then
450 return c, r, cc
451 end
452 end
453 end
454 end
455 end,
456 rltb = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
457 for i=nofcolumns,c,-1 do
458 for j=r,nofrows-nr+1 do
459 if not cells[i][j] then
460 local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
461 if c then
462 return c, r, cc
463 end
464 end
465 end
466 end
467 end,
468 btlr = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
469
470 for j=nofrows-nr+1-r+1,1,-1 do
471 for i=c,nofcolumns do
472 if not cells[i][j] then
473 local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
474 if c then
475 return c, r, cc
476 end
477 end
478 end
479 end
480 end,
481 lrbt = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
482 for i=c,nofcolumns do
483
484 for j=nofrows-nr+1-r+1,1,-1 do
485 if not cells[i][j] then
486 local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
487 if c then
488 return c, r, cc
489 end
490 end
491 end
492 end
493 end,
494 btrl = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
495
496 for j=nofrows-nr+1-r+1,1,-1 do
497 for i=nofcolumns,c,-1 do
498 if not cells[i][j] then
499 local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
500 if c then
501 return c, r, cc
502 end
503 end
504 end
505 end
506 end,
507 rlbt = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
508 for i=nofcolumns,c,-1 do
509
510 for j=nofrows-nr+1-r+1,1,-1 do
511 if not cells[i][j] then
512 local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
513 if c then
514 return c, r, cc
515 end
516 end
517 end
518 end
519 end,
520 fxtb = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
521 for i=c,nofcolumns do
522 for j=r,nofrows-nr+1 do
523 if not cells[i][j] then
524 local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
525 if c then
526 return c, r, cc
527 end
528 end
529 r = 1
530 end
531 end
532 end,
533 fxbt = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
534 for i=c,nofcolumns do
535 for j=nofrows-nr+1,r,-1 do
536 if not cells[i][j] then
537 local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
538 if c then
539 return c, r, cc
540 end
541 end
542 end
543 r = 1
544 end
545 end,
546 [v_top] = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
547 for i=c,nofcolumns do
548 for j=1,nofrows-nr+1 do
549 if cells[i][j] then
550 break
551 else
552 local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
553 if c then
554 return c, r, cc
555 end
556 end
557 end
558 end
559 end,
560 [v_bottom] = function(c,r,nr,nofcolumns,nofrows,cells,width,spans)
561 for i=c,nofcolumns do
562 for j=1,nofrows-nr+1 do
563 if cells[i][j] then
564 break
565 else
566 local c, r, cc = here(i,j,nr,nofcolumns,nofrows,cells,width,spans)
567 if c then
568 return c, r, cc
569 end
570 end
571 end
572 end
573 end,
574}
575
576local threshold = 50
577
578function columnsets.check(t)
579 local dataset = data[t.name]
580 local cells = dataset.cells
581 local nofcolumns = dataset.nofcolumns
582 local nofrows = dataset.nofrows
583 local widths = dataset.widths
584 local lineheight = dataset.lineheight
585 local linedepth = dataset.linedepth
586 local distances = dataset.distances
587 local spans = dataset.spans
588
589 local method = lower(t.method or "tblr")
590 local boxwidth = t.width or 0
591 local boxheight = t.height or 0
592 local boxnumber = t.box
593 local box = boxnumber and getbox(boxnumber)
594
595 if boxwidth > 0 and boxheight > 0 then
596
597 elseif box then
598 local wd, ht, dp = getwhd(box)
599 boxwidth = wd
600 boxheight = ht + dp
601 else
602 report("empty box")
603 return
604 end
605
606 local c = t.c or 0
607 local r = t.r or 0
608 if c == 0 then
609 c = dataset.currentcolumn
610 end
611 if r == 0 then
612 r = dataset.currentrow
613 end
614 if c == 0 or r == 0 or c > nofcolumns or r > nofrows then
615 texsetcount("c_page_grd_reserved_state",5)
616 return
617 end
618
619 local nr = ceil(boxheight/(lineheight+linedepth))
620
621 local action = methods[method]
622 local cfound = false
623 local rfound = false
624 local lastcolumn = dataset.lastcolumn
625
626
627
628
629 if action then
630 cfound, rfound, nc = action(c,r,nr,lastcolumn,nofrows,cells,boxwidth-threshold,spans)
631 end
632 if not cfound and method ~= v_here then
633
634 cfound, rfound, nc = here(c,r,nr,lastcolumn,nofrows,cells,boxwidth-threshold,spans)
635 end
636 if cfound then
637 local ht = nr*(lineheight+linedepth)
638 local wd = spans[cfound][nc]
639 dataset.reserved_ht = ht
640 dataset.reserved_wd = wd
641 dataset.reserved_c = cfound
642 dataset.reserved_r = rfound
643 dataset.reserved_nc = nc
644 dataset.reserved_nr = nr
645 texsetcount("c_page_grd_reserved_state",0)
646 texsetdimen("d_page_grd_reserved_height",ht)
647 texsetdimen("d_page_grd_reserved_width",wd)
648
649 else
650 dataset.reserved_ht = false
651 dataset.reserved_wd = false
652 dataset.reserved_c = false
653 dataset.reserved_r = false
654 dataset.reserved_nc = false
655 dataset.reserved_nr = false
656 texsetcount("c_page_grd_reserved_state",4)
657
658
659
660 end
661end
662
663function columnsets.put(t)
664 local dataset = data[t.name]
665 local cells = dataset.cells
666 local widths = dataset.widths
667 local lineheight = dataset.lineheight
668 local linedepth = dataset.linedepth
669 local boxnumber = t.box
670 local box = boxnumber and takebox(boxnumber)
671
672 local c = t.c or dataset.reserved_c
673 local r = t.r or dataset.reserved_r
674 if not c or not r then
675
676 return
677 end
678 local lastc = c + dataset.reserved_nc - 1
679 local lastr = r + dataset.reserved_nr - 1
680
681 for i=c,lastc do
682 local column = cells[i]
683 for j=r,lastr do
684 column[j] = true
685 end
686 end
687 cells[c][r] = box
688 setwhd(box,widths[c],lineheight,linedepth)
689 dataset.reserved_c = false
690 dataset.reserved_r = false
691 dataset.reserved_nc = false
692 dataset.reserved_nr = false
693
694end
695
696local function findgap(dataset)
697 local cells = dataset.cells
698 local nofcolumns = dataset.nofcolumns
699 local nofrows = dataset.nofrows
700 local currentrow = dataset.currentrow
701 local currentcolumn = dataset.currentcolumn
702
703 local foundc = 0
704 local foundr = 0
705 local foundn = 0
706 for c=currentcolumn,dataset.lastcolumn do
707 local column = cells[c]
708 foundn = 0
709 for r=currentrow,nofrows do
710 if not column[r] then
711 if foundc == 0 then
712 foundc = c
713 foundr = r
714 end
715 foundn = foundn + 1
716 elseif foundn > 0 then
717 return foundc, foundr, foundn
718 end
719 end
720 if foundn > 0 then
721 return foundc, foundr, foundn
722 end
723 currentrow = 1
724 end
725end
726
727
728
729local nofcolumngaps = 0
730
731function columnsets.add(name,box)
732 local dataset = data[name]
733 local cells = dataset.cells
734 local nofcolumns = dataset.nofcolumns
735 local nofrows = dataset.nofrows
736 local currentrow = dataset.currentrow
737 local currentcolumn = dataset.currentcolumn
738 local lineheight = dataset.lineheight
739 local linedepth = dataset.linedepth
740 local widths = dataset.widths
741
742 local b = getbox(box)
743 local l = b and getlist(b)
744 if l then
745 local hd = lineheight + linedepth
746 while l do
747 local foundc, foundr, foundn = findgap(dataset)
748 if foundc then
749 local available = foundn * hd
750
751 if available < hd then
752 local column = cells[foundc]
753 for i=foundr,foundr+foundn-1 do
754 column[i] = true
755 end
756
757
758 else
759 local first = splitbox(box,available,"additional")
760 if first then
761
762 local used = nuts.gettotal(first)
763 local foundm = ceil(used/hd)
764 if abs(foundm-foundn) == 1 then
765 first = vpack(getlist(first),available,"exactly")
766 used = nuts.gettotal(first)
767 foundm = ceil(used/hd)
768 else
769 foundn = foundm
770 end
771
772 local v = first
773 nofcolumngaps = nofcolumngaps + 1
774
775 properties[v] = { columngap = nofcolumngaps }
776
777 setwhd(v,widths[currentcolumn],lineheight,linedepth)
778 local column = cells[foundc]
779
780 column[foundr] = v
781 used = used - hd
782 if used > 0 then
783 for r=foundr+1,foundr+foundn-1 do
784 used = used - hd
785 foundr = foundr + 1
786 column[r] = true
787 if used <= 0 then
788 break
789 end
790 end
791 end
792 currentcolumn = foundc
793 currentrow = foundr
794 dataset.currentcolumn = currentcolumn
795 dataset.currentrow = currentrow
796 b = getbox(box)
797 l = b and getlist(b)
798 else
799 local column = cells[foundc]
800 for i=foundr,foundr+foundn-1 do
801 column[i] = true
802 end
803 b = getbox(box)
804 l = b and getlist(b)
805 end
806 end
807 else
808 b = getbox(box)
809 l = b and getlist(b)
810 break
811 end
812 end
813 end
814end
815
816do
817
818
819
820
821 local followup = nil
822 local splitter = lpeg.splitter("*",tonumber)
823
824 columnsets["noto"] = function(t)
825 return followup()
826 end
827
828 columnsets["goto"] = function(name,target)
829 local dataset = data[name]
830 local nofcolumns = dataset.nofcolumns
831 if target == v_yes or target == "" then
832 local currentcolumn = dataset.currentcolumn
833 followup = function()
834 context(dataset.currentcolumn == currentcolumn and 1 or 0)
835 end
836 return followup()
837 end
838 if target == v_first then
839 if dataset.currentcolumn > 1 then
840 target = v_page
841 else
842 return context(0)
843 end
844 end
845 if target == v_page then
846 if dataset.currentcolumn == 1 and dataset.currentrow == 1 then
847 return context(0)
848 else
849 local currentpage = dataset.page
850 followup = function()
851 context(dataset.page == currentpage and 1 or 0)
852 end
853 return followup()
854 end
855 end
856 if target == v_last then
857 target = dataset.nofcolumns
858 if dataset.currentcolumn ~= target then
859 followup = function()
860 context(dataset.currentcolumn ~= target and 1 or 0)
861 end
862 return followup()
863 end
864 return
865 end
866 local targetpage = tonumber(target)
867 if targetpage then
868 followup = function()
869 context(dataset.currentcolumn ~= targetpage and 1 or 0)
870 end
871 return followup()
872 end
873 local targetcolumn, targetrow = lpeg.match(splitter,target)
874 if targetcolumn and targetrow then
875 if dataset.currentcolumn ~= targetcolumn and dataset.currentrow ~= targetrow then
876 followup = function()
877 if dataset.currentcolumn ~= targetcolumn then
878 context(1)
879 return
880 end
881 if dataset.currentcolumn == targetcolumn then
882 context(dataset.currentrow ~= targetrow and 1 or 0)
883 else
884 context(0)
885 end
886 end
887 return followup()
888 end
889 end
890 end
891
892end
893
894function columnsets.currentcolumn(name)
895 local dataset = data[name]
896 context(dataset.currentcolumn)
897end
898
899function columnsets.flushrest(name,box)
900 local dataset = data[name]
901 local rest = dataset.rest
902 if rest then
903 dataset.rest = nil
904 setbox("global",box,new_vlist(rest))
905 end
906end
907
908function columnsets.setvsize(name)
909 local dataset = data[name]
910 local c, r, n = findgap(dataset)
911 if n then
912 dataset.currentcolumn = c
913 dataset.currentrow = r
914 else
915 dataset.currentcolumn = 1
916 dataset.currentrow = 1
917 n = 0
918 end
919 local gap = n*(dataset.lineheight+dataset.linedepth)
920 texsetdimen("d_page_grd_gap_height",gap)
921
922
923end
924
925function columnsets.sethsize(name)
926 local dataset = data[name]
927 texsetdimen("d_page_grd_column_width",dataset.widths[dataset.currentcolumn])
928end
929
930function columnsets.sethspan(name,span)
931
932
933 local dataset = data[name]
934 local column = dataset.currentcolumn
935 local available = dataset.lastcolumn - column + 1
936 if span > available then
937 span = available
938 end
939 local width = dataset.spans[column][span]
940 texsetdimen("d_page_grd_span_width",width)
941end
942
943function columnsets.setlines(t)
944 local dataset = data[t.name]
945 dataset.lines[t.page][t.column] = t.value
946end
947
948function columnsets.setstart(t)
949 local dataset = data[t.name]
950 dataset.start[t.page][t.column] = t.value
951end
952
953function columnsets.setproperties(t)
954 local dataset = data[t.name]
955 local column = t.column
956 dataset.distances[column] = t.distance
957 dataset.widths[column] = t.width
958end
959
960local areas = { }
961
962function columnsets.registerarea(t)
963
964 areas[#areas+1] = t
965end
966
967
968
969
970local ctx_page_grd_set_area = context.page_grd_set_area
971
972function columnsets.flushareas(name)
973 local nofareas = #areas
974 if nofareas == 0 then
975 return
976 end
977 local dataset = data[name]
978 local page = dataset.page
979 if odd(page) then
980
981 local kept = { }
982 for i=1,nofareas do
983 local area = areas[i]
984
985
986 local okay = false
987
988 local nofcolumns = area.nc
989 local nofrows = area.nr
990 local column = area.c
991 local row = area.r
992 columnsets.block {
993 name = name,
994 c = column,
995 r = row,
996 nc = nofcolumns,
997 nr = nofrows,
998 }
999 local left = 0
1000 local start = dataset.nofleft + 1
1001 local overflow = (column + nofcolumns - 1) - dataset.nofleft
1002 local height = nofrows * (dataset.lineheight + dataset.linedepth)
1003 local width = dataset.spreads[column][nofcolumns]
1004
1005 if overflow > 0 then
1006 local used = nofcolumns - overflow
1007 left = dataset.spreads[column][used] + texgetdimen("backspace")
1008 end
1009 ctx_page_grd_set_area(name,area.name,column,row,width,height,start,left)
1010 if area.state ~= v_repeat then
1011 area = nil
1012 end
1013 if area then
1014 kept[#kept+1] = area
1015 end
1016 end
1017 areas = kept
1018 end
1019end
1020
1021function columnsets.setarea(t)
1022 local dataset = data[t.name]
1023 local cells = dataset.cells
1024 local box = takebox(t.box)
1025 local column = t.c
1026 local row = t.r
1027 if column and row then
1028 setwhd(box,dataset.widths[column],dataset.lineheight,dataset.linedepth)
1029 cells[column][row] = box
1030 end
1031end
1032
1033
1034
1035implement {
1036 name = "definecolumnset",
1037 actions = columnsets.define,
1038 arguments = { {
1039 { "name", "string" },
1040 } }
1041}
1042
1043implement {
1044 name = "resetcolumnset",
1045 actions = columnsets.reset,
1046 arguments = { {
1047 { "name", "string" },
1048 { "nofleft", "integer" },
1049 { "nofright", "integer" },
1050 { "nofrows", "integer" },
1051 { "lineheight", "dimension" },
1052 { "linedepth", "dimension" },
1053 { "width", "dimension" },
1054 { "distance", "dimension" },
1055 { "maxwidth", "dimension" },
1056 } }
1057}
1058
1059implement {
1060 name = "preparecolumnsetflush",
1061 actions = columnsets.prepareflush,
1062 arguments = "string",
1063}
1064
1065implement {
1066 name = "finishcolumnsetflush",
1067 actions = columnsets.finishflush,
1068 arguments = "string",
1069}
1070
1071implement {
1072 name = "flushcolumnsetcolumn",
1073 actions = columnsets.flushcolumn,
1074 arguments = { "string" ,"integer" },
1075}
1076
1077implement {
1078 name = "setvsizecolumnset",
1079 actions = columnsets.setvsize,
1080 arguments = "string",
1081}
1082
1083implement {
1084 name = "sethsizecolumnset",
1085 actions = columnsets.sethsize,
1086 arguments = "string",
1087}
1088
1089implement {
1090 name = "sethsizecolumnspan",
1091 actions = columnsets.sethspan,
1092 arguments = { "string" ,"integer" },
1093}
1094
1095implement {
1096 name = "flushcolumnsetrest",
1097 actions = columnsets.flushrest,
1098 arguments = { "string", "integer" },
1099}
1100
1101implement {
1102 name = "blockcolumnset",
1103 actions = columnsets.block,
1104 arguments = { {
1105 { "name", "string" },
1106 { "c", "integer" },
1107 { "r", "integer" },
1108 { "nc", "integer" },
1109 { "nr", "integer" },
1110 { "method", "string" },
1111 { "box", "integer" },
1112 } }
1113}
1114
1115implement {
1116 name = "checkcolumnset",
1117 actions = columnsets.check,
1118 arguments = { {
1119 { "name", "string" },
1120 { "method", "string" },
1121 { "c", "integer" },
1122 { "r", "integer" },
1123 { "method", "string" },
1124 { "box", "integer" },
1125 { "width", "dimension" },
1126 { "height", "dimension" },
1127 { "option", "string" },
1128 } }
1129}
1130
1131implement {
1132 name = "putincolumnset",
1133 actions = columnsets.put,
1134 arguments = { {
1135 { "name", "string" },
1136 { "c", "integer" },
1137 { "r", "integer" },
1138 { "method", "string" },
1139 { "box", "integer" },
1140 } }
1141}
1142
1143implement {
1144 name = "addtocolumnset",
1145 actions = columnsets.add,
1146 arguments = { "string", "integer" },
1147}
1148
1149implement {
1150 name = "setcolumnsetlines",
1151 actions = columnsets.setlines,
1152 arguments = { {
1153 { "name", "string" },
1154 { "page", "integer" },
1155 { "column", "integer" },
1156 { "value", "integer" },
1157 } }
1158}
1159
1160implement {
1161 name = "setcolumnsetstart",
1162 actions = columnsets.setstart,
1163 arguments = { {
1164 { "name", "string" },
1165 { "page", "integer" },
1166 { "column", "integer" },
1167 { "value", "integer" },
1168 } }
1169}
1170
1171implement {
1172 name = "setcolumnsetproperties",
1173 actions = columnsets.setproperties,
1174 arguments = { {
1175 { "name", "string" },
1176 { "column", "integer" },
1177 { "distance", "dimension" },
1178 { "width", "dimension" },
1179 } }
1180}
1181
1182implement {
1183 name = "registercolumnsetarea",
1184 actions = columnsets.registerarea,
1185 arguments = { {
1186 { "name", "string" },
1187 { "type", "string" },
1188 { "page", "integer" },
1189 { "state", "string" },
1190 { "c", "integer" },
1191 { "r", "integer" },
1192 { "nc", "integer" },
1193 { "nr", "integer" },
1194 } }
1195}
1196
1197implement {
1198 name = "flushcolumnsetareas",
1199 actions = columnsets.flushareas,
1200 arguments = "string",
1201}
1202
1203implement {
1204 name = "setcolumnsetarea",
1205 actions = columnsets.setarea,
1206 arguments = { {
1207 { "name", "string" },
1208 { "c", "integer" },
1209 { "r", "integer" },
1210 { "method", "string" },
1211 { "box", "integer" },
1212 } }
1213}
1214
1215implement {
1216 name = "columnsetgoto",
1217 actions = columnsets["goto"],
1218 arguments = "2 strings",
1219}
1220
1221implement {
1222 name = "columnsetnoto",
1223 actions = columnsets["noto"],
1224}
1225
1226implement {
1227 name = "columnsetcurrentcolumn",
1228 actions = columnsets.currentcolumn,
1229 arguments = "string",
1230}
1231 |