summaryrefslogtreecommitdiff
path: root/tex/context/base/mkxl/math-spa.lmt
blob: 487d9e4a48cbd42b2717c77dcfbcfe30cdf7dab9 (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
136
137
138
139
140
141
142
143
144
145
146
if not modules then modules = { } end modules ['math-spa'] = {
    version   = 1.001,
    comment   = "companion to math-ini.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

-- for the moment (when testing) we use a penalty 1

local setmetatableindex = table.setmetatableindex

local boundary_code     = nodes.nodecodes.boundary
local hlist_code        = nodes.nodecodes.hlist
local glue_code         = nodes.nodecodes.glue
local line_code         = nodes.listcodes.line
local ghost_code        = nodes.listcodes.ghost

local nuts              = nodes.nuts
local tonut             = nodes.tonut
local tonode            = nodes.tonode

local getid             = nuts.getid
local getsubtype        = nuts.getsubtype
local getnext           = nuts.getnext
local getwidth          = nuts.getwidth
local getdata           = nuts.getdata
local getdepth          = nuts.getdepth
local getlist           = nuts.getlist
local setglue           = nuts.setglue
local getdimensions     = nuts.dimensions
local getnormalizedline = node.direct.getnormalizedline
local getbox            = nuts.getbox
local setoffsets        = nuts.setoffsets

local nextglue          = nuts.traversers.glue
local nextlist          = nuts.traversers.list
local nextboundary      = nuts.traversers.boundary

local texgetdimen       = tex.getdimen
local texsetdimen       = tex.setdimen
local texsetcount       = tex.setcount

local boundary          = tex.boundaries.system("mathalign")
local stages            = { }
local initial           = { }

stages[1] = function(specification,stage)
    local box      = getbox(specification.box)
    local head     = getlist(box)
    local align    = specification.alignstate
    local distance = specification.distance
    for s in nextboundary, head do
        if getdata(s) == boundary then
            -- todo: skip over ghost, maybe penalty, maybe glues all in one loop
            local n = getnext(s)
            while n and getid(n) == hlist_code and getsubtype(n) == ghost_code do
                n = getnext(n)
            end
         -- while n and getid(n) == glue_code do
            if n and getid(n) == glue_code then
                n = getnext(n)
            end
            distance = distance + getdimensions(head,n)
            break
        end
    end
    texsetdimen("global","d_strc_math_indent",distance)
    if align == 2 then
        for n in nextglue, head do
            setglue(n,getwidth(n),0,0,0,0)
        end
    end
end

stages[2] = function(specification,stage)
    local head  = getlist(getbox(specification.box))
    local align = specification.alignstate
    local max   = false
    local cnt   = 0
    local width = 0
    local depth = 0
    for n, id, subtype, list in nextlist, head do
        if subtype == line_code then
            local t = getnormalizedline(n)
            local m = t.rightskip + t.parfillrightskip
            if not max then
                max = m
            elseif m < max then
                max = m
            end
            cnt   = cnt + 1
            width = m
            depth = getdepth(n)
        end
    end
    if stage == 2 and (align == 2 or align == 3) then
        for n, id, subtype, list in nextlist, head do
            if subtype == line_code then
                if align == 1 then -- flushleft
                elseif align == 2 then -- middle
                    setoffsets(n,max/2,0)
                elseif align == 3 then -- flushright
                    setoffsets(n,max,0)
                end
            end
        end
    end
    texsetcount("global","c_strc_math_n_of_lines",cnt)
    texsetdimen("global","d_strc_math_max_width",max)
    texsetdimen("global","d_strc_math_last_width",width)
    texsetdimen("global","d_strc_math_last_depth",depth)
end

stages[3] = stages[2]

stages[4] = function(specification,stage)
    nuts.openup(specification,getlist(getbox(specification.box)))
end

interfaces.implement {
    name      = "handlemathhang",
    arguments = {
        {
            { "stage", "integer" },
         -- { "method" },
            { "alignstate", "integer" },
            { "box", "integer" },
            { "distance", "dimension" },
            { "inbetween", "dimension" },
            { "height", "dimension" },
            { "depth", "dimension" },
        }
    },
    actions   = function(specification)
        local stage = specification.stage
        if stage == 1 then
            initial = specification
        else
            setmetatableindex(specification,initial)
        end
        if stage > 0 and stage <= #stages then
            stages[stage](specification,stage)
        end
    end
}