summaryrefslogtreecommitdiff
path: root/tex/context/base/spac-ali.lua
blob: 25cc6cd6686da4224d9245e34a0061c9d6a8af62 (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
if not modules then modules = { } end modules ['spac-ali'] = {
    version   = 1.001,
    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 appendaction     = tasks.appendaction
local prependaction    = tasks.prependaction
local disableaction    = tasks.disableaction
local enableaction     = tasks.enableaction

local slide_nodes      = node.slide
local hpack_nodes      = node.hpack -- nodes.fasthpack not really faster here

local unsetvalue       = attributes.unsetvalue

local nodecodes        = nodes.nodecodes
local listcodes        = nodes.listcodes

local hlist_code       = nodecodes.hlist
local vlist_code       = nodecodes.vlist
local line_code        = listcodes.line

local nodepool         = nodes.pool

local new_stretch      = nodepool.stretch

local a_realign        = attributes.private("realign")

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)
    local current = head
    local done = false
    while current do
        local id = current.id
        if id == hlist_code then
            if current.subtype == line_code then
                local a = current[a_realign]
                if not a or a == 0 then
                    -- skip
                else
                    local align = a % 10
                    local pageno = div(a,10)
                    if pageno == realpageno then
                        -- already ok
                    else
                        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
                        if action == 1 then
                            current.list = hpack_nodes(current.list .. new_stretch(3),current.width,"exactly")
                            if trace_realign then
                                report_realign("flushing left, align %a, page %a, realpage %a",align,pageno,realpageno)
                            end
                        elseif action == 2 then
                            current.list = hpack_nodes(new_stretch(3) .. current.list,current.width,"exactly")
                            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
                        done = true
                        nofrealigned = nofrealigned + 1
                    end
                    current[a_realign] = unsetvalue
                end
            end
            handler(current.list,leftpage,realpageno)
        elseif id == vlist_code then
            handler(current.list,leftpage,realpageno)
        end
        current = current.next
    end
    return head, done
end

function alignments.handler(head)
    local leftpage = isleftpage(true,false)
    local realpageno = texgetcount("realpageno")
    return handler(head,leftpage,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("realpageno") * 10 + n)
end

commands.setrealign = alignments.set

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