summaryrefslogtreecommitdiff
path: root/tex/context/base/mkxl/spac-ali.lmt
blob: 9fa024672929b46d366cbf4c45ccd9a45c6d5f14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
if not modules then modules = { } end modules ['spac-ali'] = {
    version   = 1.001,
    optimize  = true,
    comment   = "companion to spac-ali.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local div = math.div
local format = string.format

local tasks            = nodes.tasks
local enableaction     = tasks.enableaction

local nuts             = nodes.nuts

local setlist          = nuts.setlist
local setlink          = nuts.setlink
local getdirection     = nuts.getdirection
local takeattr         = nuts.takeattr
local getwidth         = nuts.getwidth
local findtail         = nuts.tail

local righttoleft_code = nodes.dirvalues.righttoleft
local linelist_code    = nodes.listcodes.line

local hpack_nodes      = nuts.hpack
local nextlist         = nuts.traversers.list

local new_stretch      = nuts.pool.stretch

local a_realign        = attributes.private("realign")
local c_realpageno     = tex.iscount("realpageno")

local texsetattribute  = tex.setattribute
local texgetcount      = tex.getcount

local isleftpage       = layouts.status.isleftpage

typesetters            = typesetters or { }
local alignments       = { }
typesetters.alignments = alignments

local report_realign   = logs.reporter("typesetters","margindata")
local trace_realign    = trackers.register("typesetters.margindata", function(v) trace_margindata = v end)

local nofrealigned     = 0

--                leftskip   rightskip parfillskip
-- raggedleft      0 +         0          -
-- raggedright     0           0         fil
-- raggedcenter    0 +         0 +        -

local function handler(head,leftpage,realpageno)
    for current, id, subtype, list in nextlist, head do
        if subtype == linelist_code then
            local a = takeattr(current,a_realign)
            if a and a > 0 then
                local pageno = div(a,10)
                if pageno ~= realpageno then
                    local align  = a % 10
                    local action = 0
                    if align == 1 then -- flushright
                        action = leftpage and 1 or 2
                    elseif align == 2 then -- flushleft
                        action = leftpage and 2 or 1
                    end
                    -- WS: watch this
                    local direction = getdirection(current)
                    -- or should this happen at the tex end:
                    if direction == righttoleft_code then
                        if action == 1 then
                            action = 2
                        elseif action == 2 then
                            action = 1
                        end
                    end
                    -- Currently we just prepend and append which kind of spoils the normalization unless
                    -- we extend our specs and also introduce left/right anchored stuff.
                    if action == 1 then
                        local head = list
                        setlink(findtail(list),new_stretch(3)) -- append
                        setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
                        if trace_realign then
                            report_realign("flushing left, align %a, page %a, realpage %a",align,pageno,realpageno)
                        end
                    elseif action == 2 then
                        local head = setlink(new_stretch(3),list) -- prepend
                        setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
                        if trace_realign then
                            report_realign("flushing right, align %a, page %a, realpage %a",align,pageno,realpageno)
                        end
                    elseif trace_realign then
                        report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno)
                    end
                    nofrealigned = nofrealigned + 1
                end
            end
        end
        handler(list,leftpage,realpageno)
    end
    return head
end

function alignments.handler(head)
    return handler(head,isleftpage(),texgetcount(c_realpageno))
end

local enabled = false

function alignments.set(n)
    if not enabled then
        enableaction("shipouts","typesetters.alignments.handler")
        enabled = true
        if trace_realign then
            report_realign("enabled")
        end
    end
    texsetattribute(a_realign,texgetcount(c_realpageno) * 10 + n)
end

interfaces.implement {
    name      = "setrealign",
    actions   = alignments.set,
    arguments = "integer",
}

statistics.register("realigning", function()
    if nofrealigned > 0 then
        return format("%s processed",nofrealigned)
    else
        return nil
    end
end)