spac-ali.lmt /size: 4870 b    last modification: 2023-12-21 09:44
1if not modules then modules = { } end modules ['spac-ali'] = {
2    version   = 1.001,
3    optimize  = true,
4    comment   = "companion to spac-ali.mkiv",
5    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
6    copyright = "PRAGMA ADE / ConTeXt Development Team",
7    license   = "see context related readme files"
8}
9
10local div = math.div
11local format = string.format
12
13local tasks            = nodes.tasks
14local enableaction     = tasks.enableaction
15
16local nuts             = nodes.nuts
17
18local setlist          = nuts.setlist
19local setlink          = nuts.setlink
20local getdirection     = nuts.getdirection
21local takeattr         = nuts.takeattr
22local getwidth         = nuts.getwidth
23local findtail         = nuts.tail
24
25local righttoleft_code = tex.directioncodes.righttoleft
26
27local linelist_code    = nodes.listcodes.line
28
29local hpack_nodes      = nuts.hpack
30local nextlist         = nuts.traversers.list
31
32local new_stretch      = nuts.pool.stretch
33
34local a_realign        = attributes.private("realign")
35local c_realpageno     = tex.iscount("realpageno")
36
37local texsetattribute  = tex.setattribute
38local texgetcount      = tex.getcount
39
40local isleftpage       = layouts.status.isleftpage
41
42typesetters            = typesetters or { }
43local alignments       = { }
44typesetters.alignments = alignments
45
46local report_realign   = logs.reporter("typesetters","margindata")
47local trace_realign    = trackers.register("typesetters.margindata", function(v) trace_margindata = v end)
48
49local nofrealigned     = 0
50
51--                leftskip   rightskip parfillskip
52-- raggedleft      0 +         0          -
53-- raggedright     0           0         fil
54-- raggedcenter    0 +         0 +        -
55
56local function handler(head,leftpage,realpageno)
57    for current, id, subtype, list in nextlist, head do
58        if subtype == linelist_code then
59            local a = takeattr(current,a_realign)
60            if a and a > 0 then
61                local pageno = div(a,10)
62                if pageno ~= realpageno then
63                    local align  = a % 10
64                    local action = 0
65                    if align == 1 then -- flushright
66                        action = leftpage and 1 or 2
67                    elseif align == 2 then -- flushleft
68                        action = leftpage and 2 or 1
69                    end
70                    -- WS: watch this
71                    local direction = getdirection(current)
72                    -- or should this happen at the tex end:
73                    if direction == righttoleft_code then
74                        if action == 1 then
75                            action = 2
76                        elseif action == 2 then
77                            action = 1
78                        end
79                    end
80                    -- Currently we just prepend and append which kind of spoils the normalization unless
81                    -- we extend our specs and also introduce left/right anchored stuff.
82                    if action == 1 then
83                        local head = list
84                        setlink(findtail(list),new_stretch(3)) -- append
85                        setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
86                        if trace_realign then
87                            report_realign("flushing left, align %a, page %a, realpage %a",align,pageno,realpageno)
88                        end
89                    elseif action == 2 then
90                        local head = setlink(new_stretch(3),list) -- prepend
91                        setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
92                        if trace_realign then
93                            report_realign("flushing right, align %a, page %a, realpage %a",align,pageno,realpageno)
94                        end
95                    elseif trace_realign then
96                        report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno)
97                    end
98                    nofrealigned = nofrealigned + 1
99                end
100            end
101        end
102        handler(list,leftpage,realpageno)
103    end
104    return head
105end
106
107function alignments.handler(head)
108    return handler(head,isleftpage(),texgetcount(c_realpageno))
109end
110
111local enabled = false
112
113function alignments.set(n)
114    if not enabled then
115        enableaction("shipouts","typesetters.alignments.handler")
116        enabled = true
117        if trace_realign then
118            report_realign("enabled")
119        end
120    end
121    texsetattribute(a_realign,texgetcount(c_realpageno) * 10 + n)
122end
123
124interfaces.implement {
125    name      = "setrealign",
126    actions   = alignments.set,
127    arguments = "integer",
128}
129
130statistics.register("realigning", function()
131    if nofrealigned > 0 then
132        return format("%s processed",nofrealigned)
133    else
134        return nil
135    end
136end)
137