if not modules then modules = { } end modules ['node-ali'] = {
    version   = 1.001,
    comment   = "companion to node-ini.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

-- todo: new...

local aligncharacter_code = 0x1
local mathalign_code      = 0x2
local mathmatrix_code     = 0x4
local alignskip_code      = 0x8

local setmetatableindex  = table.setmetatableindex

local nuts               = nodes.nuts
local tonut              = nuts.tonut
local tonode             = nuts.tonode
local getwidth           = nuts.getwidth
local setwidth           = nuts.setwidth
local getid              = nuts.getid
----- getidsubtype       = nuts.getidsubtype
local getattr            = nuts.getattr
local setnext            = nuts.setnext
local getnext            = nuts.getnext
local getprev            = nuts.getprev
local getboth            = nuts.getboth
local getglue            = nuts.getglue
local setglue            = nuts.setglue
local getwhd             = nuts.getwhd
local gettotal           = nuts.gettotal
local setpenalty         = nuts.setpenalty
local getlist            = nuts.getlist
local setlist            = nuts.setlist
local getleader          = nuts.getleader
local setattrlist        = nuts.setattrlist
local setprop            = nuts.setprop
local getprop            = nuts.getprop
local getfont            = nuts.getfont
local getchar            = nuts.getchar
local addmargins         = nuts.addmargins
local findtail           = nuts.tail
local hasglyph           = nuts.hasglyph
local getwordrange       = nuts.getwordrange
local dimensions         = nuts.rangedimensions
local flushnode          = nuts.flush
local hpack              = nuts.hpack
local repack             = nuts.repack
local insertbefore       = nuts.insertbefore
local insertafter        = nuts.insertafter
local replacenode        = nuts.replace
local effectiveglue      = nuts.effectiveglue

local newkern            = nuts.pool.kern
local newrule            = nuts.pool.rule
local newglue            = nuts.pool.glue

local traversers         = nuts.traversers
local nextrecord         = traversers.alignrecord
local nextunset          = traversers.unset
local nextglyph          = traversers.glyph
local nextglue           = traversers.glue
local nextpenalty        = traversers.penalty
local nextboundary       = traversers.boundary
local nextnode           = traversers.node
local nextlist           = traversers.list
local nextrule           = traversers.rule

local nodecodes          = nodes.nodecodes
local hlist_code         <const> = nodecodes.hlist
local glyph_code         <const> = nodecodes.glyph
local glue_code          <const> = nodecodes.glue
local kern_code          <const> = nodecodes.kern
local disc_code          <const> = nodecodes.disc
local unset_code         <const> = nodecodes.unset
local alignrecord_code   <const> = nodecodes.alignrecord
local rule_code          <const> = nodecodes.rule
local temp_code          <const> = nodecodes.temp

local spaceskip_code        <const> = nodes.gluecodes.spaceskip
local xspaceskip_code       <const> = nodes.gluecodes.xspaceskip
local intermathskip_code    <const> = nodes.gluecodes.intermathskip
local fontkern_code         <const> = nodes.kerncodes.fontkern
local row_code              <const> = nodes.listcodes.alignment -- should be row
local cell_code             <const> = nodes.listcodes.cell
local line_code             <const> = nodes.listcodes.line
local linepenalty_code      <const> = nodes.penaltycodes.linepenalty
local linebreakpenalty_code <const> = nodes.penaltycodes.linebreakpenalty

-- local preamble_pass <const> = tex.alignmentcontextcodes.preamble
-- local preroll_pass  <const> = tex.alignmentcontextcodes.preroll
-- local wrapup_pass   <const> = tex.alignmentcontextcodes.wrapup

-- todo statistics and tracing

do


    local a_alignchar <const> = attributes.private("aligncharacter")

    local method      = 2
    local unislots    = fonts.hashes.unislots -- todo
    local chardata    = fonts.hashes.characters

    function nodes.handlers.aligncharacter(head,where,callback,attr,preamble) -- 0x1
        if (callback & aligncharacter_code == 0) then
            -- nothing to do here
        elseif where == "preroll" then
            local attr = getattr(attr,a_alignchar) -- 1 : value doesn't matter (for now)
            if attr then
                local widths = { }
                local data   = { }
                local rows   = 0
                local cols   = 0
                for col in nextrecord, preamble do
                    cols = cols + 1
                    local w, s = getwidth(col,true)
                    widths[cols] = { col, w, s }
                end
                --
                for row in nextunset, head do
                    rows = rows + 1
                    local c = 0
                    local d = { }
                    data[rows] = d
                    for col in nextunset, getlist(row) do
                        c = c + 1
                        if widths[c][2] then
                            local list = getlist(col)
                         -- if method == 1 then
                         --     local left   = nil
                         --     local right  = nil
                         --     local middle = nil
                         --     for g, char in nextglyph, list do
                         --         if not left then
                         --             left = g
                         --         end
                         --         if char == getattr(g,a_alignchar) then
                         --             middle = g
                         --         end
                         --         right = g
                         --     end
                         --     d[c] = middle and { col, left, middle, right, 0, 0, getwidth(middle) } or false
                         -- elseif method == 2 then
                                local middle = nil
                                -- we can either cache unislots or we can cache for this font
                                for g, char, font in nextglyph, list do
                                    local unicode = getattr(g,a_alignchar)
                                    if unicode then
                                        if char == unicode then
                                            middle = g
                                        elseif unislots[font][char] == unicode then
                                            middle = g
                                        end
                                    end
                                end
                                if middle then
                                    local left, right = getwordrange(middle) -- not real gain but handy anyway (less code too)
                                 -- local left  = middle
                                 -- local right = middle
                                 -- for g, id, subtype in nextnode, middle do
                                 --     if id == glyph_code or id == disc_code then
                                 --         right = g
                                 --     elseif id == kern_code and subtype == fontkern_code then
                                 --         right = g
                                 --     else
                                 --         break
                                 --     end
                                 -- end
                                 -- for g, id, subtype in prevnode, middle do
                                 --     if id == glyph_code or id == disc_code then
                                 --         left = g
                                 --     elseif id == kern_code and subtype == fontkern_code then
                                 --         left = g
                                 --     else
                                 --         break
                                 --     end
                                 -- end
                                    d[c] = { col, left, middle, right, 0, 0, getwidth(middle) }
                                else
                                    d[c] = false
                                end
                         -- else
                         --     local middle = nil
                         --     for g, char in nextglyph, list do
                         --         if char == getattr(g,a_alignchar) then
                         --             middle = g
                         --         end
                         --     end
                         --     if middle then
                         --         local left  = list
                         --         local right = findtail(list)
                         --         if getid(left) == glue_code then
                         --             left = getnext(left)
                         --         end
                         --         if getid(right) == glue_code then
                         --             right = getprev(right)
                         --         end
                         --         d[c] = { col, left, middle, right, 0, 0, getwidth(middle) }
                         --     else
                         --         d[c] = false
                         --     end
                         -- end
                        else
                            d[c] = false
                        end
                    end
                end
                --
                for col=1,cols do
                    local maxl = 0
                    local maxr = 0
                    local minm = 0
                    local maxm = 0
                    local colw = widths[col]
                    for row=1,rows do
                        local d = data[row][col]
                        if d then
                            local p = d[1]
                            local l = d[2]
                            local m = d[3]
                            local r = d[4]
                            if m then
                                local lw = l == m and 0 or dimensions(p,l,m)
                                local rw = m == r and 0 or dimensions(p,getnext(m),getnext(r))
                                d[5] = lw
                                d[6] = rw
                                if lw > maxl then
                                    maxl = lw
                                end
                                if rw > maxr then
                                    maxr = rw
                                end
                                local mw = d[7]
                                if maxm == 0 then
                                    minm = mw
                                    maxm = mw
                                else
                                    if mw > maxm then
                                        maxm = mw
                                    end
                                    if mw < minm then
                                        minm = mw
                                    end
                                end
                            end
                        end
                    end
                    --
                    local fixedwidth = colw[3] ~= 0
                    --
                    local old = colw[2]
                    local new = old
                    for row=1,rows do
                        local d = data[row][col]
                        if d then
                            local p = d[1]
                            local l = d[2]
                            local m = d[3]
                            local r = d[4]
                            if l and m and r then
                                local lw = d[5]
                                local rw = d[6]
                                local mw = d[7]
                                dl = maxl - lw
                                dr = maxr - rw
                                if dl ~= 0 or dr ~= 0 or mw ~= maxm then
                                    local lst = getlist(p)
                                    local wid = getwidth(p)
                                    if dl ~= 0 then
                                        local k = newkern(dl)
                                        lst = insertbefore(lst,l,k)
                                        setattrlist(k,m)
                                        setlist(p,lst)
                                        wid = wid + dl
                                    end
                                    if dr ~= 0 then
                                        local k = newkern(dr)
                                        insertafter(lst,r,k)
                                        setattrlist(k,m)
                                        wid = wid + dr
                                    end
                                    if mw ~= maxm then
                                        local dw = (maxm - mw)
                                        local dx = dw / 2
                                        addmargins(m,-dx,-dx)
                                        wid = wid + dw
                                    end
                                    setwidth(p,wid)
                                    if wid > new then
                                        new = wid
                                    end
                                    setlist(p,lst)
                                    -- somewhat fuzzy:
                                    if fixedwidth then
                                        local l = hpack(h,getwidth(p),"exactly")
                                        setglue(p,getglue(l))
                                        setlist(l)
                                        flushnode(l)
                                    else
                                        setglue(p)
                                    end
                                    --
                                end
                            end
                        end
                    end
                    if new > old then
                        if fixedwidth then
                            -- issue overflow warning
                        else
                            setwidth(colw[1],new)
                        end
                    end
                end
            end
        end
    end

    local enabled = false

    interfaces.implement {
        name      = "enablealignmentcharacter",
     -- onlyonce  = true,
        public    = true,
        protected = true,
        actions   = function()
            if not enabled then
                nodes.tasks.enableaction("alignments","nodes.handlers.aligncharacter") -- 0x1
                enabled = true
            end
        end,
    }

end

-- This will go to math-ali.lmt

do

    local getdata           = nuts.getdata
    local removenode        = nuts.remove
 -- local getwhd            = nuts.getwhd
    local getheight         = nuts.getheight
    local getdepth          = nuts.getdepth
    local setheight         = nuts.setheight
    local setdepth          = nuts.setdepth
    local getglue           = nuts.getglue
    local setoffsets        = nuts.setoffsets
    local setsubtype        = nuts.setsubtype

    local baselineskip_code <const> = nodes.gluecodes.baselineskip
    local lineskip_code     <const> = nodes.gluecodes.lineskip
    local userskip_code     <const> = nodes.gluecodes.userskip

    local alignrecord_code  <const> = nodecodes.alignrecord
    local hlist_code        <const> = nodecodes.hlist
    local unset_code        <const> = nodecodes.unset
 -- local rule_code         <const> = nodecodes.rule

    local nextnode          = nuts.traversers.node

    local texgetdimen       = tex.getdimen
    local texsetdimen       = tex.setdimen
    local texgetglue        = tex.getglue
    local texget            = tex.get

    local leftmarker        <const> = tex.boundaries.system("c_math_align_l_marker")
    local rightmarker       <const> = tex.boundaries.system("c_math_align_r_marker")

    local a_location        <const> = attributes.system("mathnumberlocation")
    local a_threshold       <const> = attributes.system("mathnumberthreshold")

    local v_first           <const> = interfaces.variables.first
    local v_last            <const> = interfaces.variables.last
    local v_both            <const> = interfaces.variables.both

    -- Here:

    local function openup(specification,head)
        local inbetween = specification.inbetween or 0
        local height    = specification.height or 0
        local depth     = specification.depth or 0
        local snapped   = specification.snapped
        local lines     = { }
        for n, id, subtype, list in nextlist, head do
            lines[#lines+1] = { n, subtype, getwhd(n) }
        end
        local noflines = #lines
        if noflines > 0 then
            local currentline = 1
            for n, subtype in nextglue, head do
                -- one day we can decide what to do with intertext stuff based on the
                -- subtype but not now ... on our agenda (intertext etc)
                if subtype == baselineskip_code or subtype == lineskip_code then
                    local nextline = currentline + 1
                    local amount, stretch, shrink = getglue(n)
                    local prevdp = lines[currentline][5]
                    local nextht = lines[nextline][4]
                    local delta  = 0
                    if prevdp < depth then
                        setdepth(lines[currentline][1],depth)
                        delta = delta + (depth - prevdp)
                    end
                    if nextht < height then
                        setheight(lines[nextline][1],height)
                        delta = delta + (height - nextht)
                    end
                    setsubtype(n,snapped and userskip_code or baselineskip_code)
                    setglue(n,amount+inbetween-delta,stretch,shrink)
                    currentline = nextline -- was curline
                end
            end
            local firstht = lines[1][4]
            local lastdp  = lines[noflines][5]
            if firstht < height then
                setheight(lines[1],height)
            end
            if lastdp < depth then
                setdepth(lines[noflines],depth)
            end
        end
    end

    nuts.openup = openup

    -- When present, the number is after the right marker. We need to move the
    -- number when we want it at the left.
    --
    -- Todo: set a flag in mathalignment and support atttibutes on it so that
    -- we can check if this is needed.

    -- [dummy] [left -2] [second -1] [number 0]

    -- In the end it makes more sense to just calculate the alignment in lua
    -- but it is kind of fun to see how we can control alignments. This code
    -- is (in the end) too complex.

    local totals     = { }
    local widths     = { }
    local records    = { }
    local deltas     = { }
    local cellwidths = { }

    local a_flushleft  <const> = 1
    local a_centered   <const> = 2
    local a_flushright <const> = 3

    local a_numberright <const> = 1
    local a_numberleft  <const> = 2

    local function first_pass(head,callback,attr,preamble,signal)
            --
        local width    = 0
        local hsize    = texget("hsize")
        local count    = 0
        local overflow = false
        totals   = { } -- maybe use one table
        widths   = { }
        records  = { }
        deltas   = { }
        for n in nextrecord, preamble do
            local wd = getwidth(n)
            count    = count + 1
            width    = width + wd
            totals [count] = width
            widths [count] = wd
            records[count] = n
            deltas [count] = 0
        end
        --
        local lindex   = 0
        local rindex   = 0
        local lwidth   = 0
        local rwidth   = 0
        local centered = false
        --
        for row in nextunset, head do
            local count      = 0
            local anchor     = nil
            local rochan     = nil
         -- local cellwidths = { }
            for cell in nextunset, getlist(row) do
                local list = getlist(cell)
                count = count + 1
                cellwidths[count] = getwidth(cell)
                for bound in nextboundary, list do
                    local marker = getdata(bound)
                    if marker == leftmarker then
                        lindex = count
                        anchor = bound
                        rochan = list
                    elseif marker == rightmarker then
                        local n = getnext(bound)
                        if n and getid(n) == hlist_code then
                            local wd, ht, dp = getwhd(n)
                            local lc = getattr(n,a_location)
                            if lc then
                                -- todo: just store align in the outer attribute so once ...
                             -- local align     = lc // 0x10
                             -- local location  = lc % 0x10
                                local packed    = (lc >> 8) & 0xF
                                local align     = (lc >> 4) & 0xF
                                local location  = (lc     ) & 0xF
                                local threshold = getattr(n,a_threshold)
                                if location == a_numberright then
                                    -- (more advanced than left)
                                    local m = 1
                                    local s = align == a_centered and 2 or 1
                                    if align == a_flushleft then
                                        rwidth = wd
                                    elseif align == a_flushright then
                                        rwidth = wd
                                    elseif wd > lwidth then
                                        lwidth = wd
                                        rwidth = wd
                                        centered = true
                                    end
                                    if packed > 0 then
                                        setprop(n,"mathalignshift","right")
                                        if packed == 2 then
                                            lwidth = 0
                                        else
                                            lwidth = 0
                                            rwidth = 0
                                        end
                                    end
                                    if totals[count-2] + cellwidths[count-1] + s*wd - s*threshold > hsize then
                                        local total = ht + dp
                                        setdepth(row,getdepth(row) + total)
                                        setoffsets(n,0,-total)
                                        local pr = records[count-1]
                                        local cw = getwidth(pr)
                                        if cw - wd > deltas[count-1] then
                                            deltas[count-1] = cw - wd
                                        end
                                        overflow = true
                                    end
                                elseif location == a_numberleft then
                                    if align == a_flushleft then
                                        lwidth = wd
                                    elseif align == a_flushright then
                                        lwidth = wd
                                    end
                                    if signal == 0x80 then
                                        lwidth = wd
                                    end
                                    if packed > 0 then
                                        setprop(n,"mathalignshift","left")
                                        if packed == 2 then
                                            rwidth = 0
                                        else
                                            lwidth = 0
                                            rwidth = 0
                                        end
                                    end
                                end
                                if location == a_numberleft and anchor then
                                    local l, l, n = removenode(list,n)
                                    if l ~= list then
                                        setlist(cell,l)
                                     -- setwidth(cell,0)
                                    end
                                    if signal == 0x80 then
                                        setwidth(cell,lwidth)
                                    end
                                    insertafter(rochan,anchor,n)
                                end
                            end
                        end
                        rindex = count
                    end
                end
            end
        end
        --
        if overflow then
            if deltas[rindex-1] ~= 0 then
                setwidth(records[rindex-1],deltas[rindex-1])
            end
        end
        --
        for count=1,#records do
            if count == lindex then
                if centered and overflow then
                    lwidth = lwidth - texgetdimen("d_math_eqalign_number_distance")
                end
                setwidth(records[count],lwidth)
            elseif count == rindex then
                setwidth(records[count],rwidth)
            end
        end
    end

    local function second_pass(head,callback,attr,preamble,signal)
        local done  = setmetatableindex("table")
        local glues = { }
        local okay  = false
        for row, id, subtype in nextlist, head do
            if id == hlist_code and subtype == row_code then
                for cell, id, subtype in nextlist, getlist(row) do
                    if id == hlist_code and subtype == cell_code then
                        for n, s in nextglue, getlist(cell) do
                            if s == intermathskip_code then
                                local e = effectiveglue(n,cell)
                                local g = getglue(n)
                                local f = getfont(n)
                                local a = done[f]
                                local d = a[g]
                                glues[n] = g
                                if not d then
                                    a[g] = e
                                elseif d > e then
                                    a[g] = e
                                    okay = true
                                end
                            end
                        end
                    end
                end
            end
        end
        if okay then
            for k, v in next, glues do
                local g = done[getfont(k)][v]
                if g then
                    setglue(k,g)
                    setprop(k,"fixedmathalign",true)
                end
            end
            for row, id, subtype in nextlist, head do
                if id == hlist_code and subtype == row_code then
                    for cell, id, subtype, list in nextlist, getlist(row) do
                        if list and id == hlist_code and subtype == cell_code then
                            local wd = getwidth(cell)
                            repack(cell,wd,"exactly")
                        end
                    end
                end
            end
        end
    end

    local function third_pass(head,callback,attr,preamble,signal)
        local inbetween, stretch, shrink = texgetglue("s_strc_math_alignment_inbetween")
        openup({ inbetween = inbetween }, head)
    end

    -- This will become a bit more pluggable so that we have less checking.

    -- maybe zero pass: preamble pass

    function nodes.handlers.mathalignrelocate(head,where,callback,attr,preamble) -- 0x2
        if (callback & mathalign_code == 0) then
            -- nothing to do here
        elseif where == "preroll" then
            local signal = getattr(attr,a_location)
            if signal == 0x20 or signal == 0x40 or signal == 0x80 then
                first_pass(head,callback,attr,preamble,signal)
            end
        elseif where == "wrapup" then
            local signal = getattr(attr,a_location)
            if signal == 0x40 or signal == 0x80 then
                second_pass(head,callback,attr,preamble,signal)
            end
            if signal then -- also 0x00
                third_pass(head,callback,attr,preamble,signal)
            end
        end
    end

do

    local a_mathalignmentvrule <const> = attributes.private("mathalignmentvrule")
    local a_mathalignmenthrule <const> = attributes.private("mathalignmenthrule")
    local a_mathalignmenttop   <const> = attributes.private("mathalignmenttop")
    local a_mathalignmentmid   <const> = attributes.private("mathalignmentmid")
    local a_mathalignmentbot   <const> = attributes.private("mathalignmentbot")

    local function hrule_pass(head,attr,preamble)
        local i = 0
        for row, id, subtype, list in nextlist, head do
            if id == hlist_code and subtype == row_code then
                local height = 0
                local depth  = 0
                local done   = false
                for cell, id, subtype, list in nextlist, list do
                    if list then
                        -- look for leaders
                        for n, id, subtype in nextglue, list do
                            -- here we can have the attribute on the glue (leader)
                            -- but more consistent is to have it on the rule
                            local rule = getleader(n)
                            if rule then
                                local signal = getattr(rule,a_mathalignmenthrule)
                                if signal then
                                    local w, h, d = getwhd(n)
                                    if h and d then
                                        if h > height then
                                            height = h
                                        end
                                        if d > depth then
                                            depth = d
                                        end
                                        done = true
                                    end
                                end
                            end
                        end
                    end
                end
                if done then
                    setheight(row,height)
                    setdepth(row,depth)
                end
            end
        end
    end

    -- todo  : cache
    -- maybe : change prev pointer of head (is now temp)

    ----- force_vrule  <const> = 1 -- a vrule (also serves a signal)
    local force_height <const> = 2 -- ht
    ----- force_both   <const> = 3 -- ht + dp
    local force_depth  <const> = 4 -- dp

    -- ht mid dp

    local function vrule_pass(head,attr,preamble)
        for row, id, subtype, list in nextlist, head do
            if id == hlist_code and subtype == row_code then
                local prv, nxt = getboth(row)
                for cell, id, subtype, list in nextlist, list do
                    if list then
                        -- look for vertical rules
                        local d = false
                        local h = false
                        for n, id, subtype in nextrule, list do
                            local signal = getattr(n,a_mathalignmentvrule)
                            if signal then
                                -- we found a vrule in row
                                if not d then
                                    if prv then
                                        local a = getattr(prv,a_mathalignmentvrule)
-- print("vrule preceded by force height")
                                        if a == force_depth then
                                            local p = prv
                                            while p do
                                                a = getattr(p,a_mathalignmentvrule)
                                                if not a then
                                                    break
                                                elseif a == force_height then
                                                    if not getprev(p) or getid(getprev(p)) == temp_code then
                                                        local h = getattr(p,a_mathalignmenttop) or 0
                                                        nuts.setheight(p,h)
                                                    end
                                                    break
                                                else
                                                    p = getprev(p)
                                                end
                                            end
                                        else
                                            prv = nil
                                        end
    --                                     if getid(prv) ~= rule_code or not getattr(prv,a_mathalignmentvrule) then
    --                                         prv = nil
    --                                     end
                                    end
                                    if nxt then
                                        local a = getattr(nxt,a_mathalignmentvrule)
-- print("vrule followed by force depth")
                                        if a == force_height then
                                            local p = nxt
                                            while p do
                                                a = getattr(p,a_mathalignmentvrule)
                                                if not a then
                                                    break
                                                elseif a == force_depth then
                                                    if not getnext(p) then
                                                        local d = getattr(p,a_mathalignmentbot) or 0
                                                        nuts.setdepth(p,d)
                                                    end
                                                    break
                                                else
                                                    p = getnext(p)
                                                end
                                            end
                                        else
                                            nxt = nil
                                        end
    --                                     if getid(nxt) ~= rule_code or not getattr(nxt,a_mathalignmentvrule) then
    --                                         nxt = nil
    --                                     end
                                    end
                                    d = prv and -(getdepth (prv) or 0) or 0
                                    h = nxt and -(getheight(nxt) or 0) or 0
                                    d = d - (getattr(prv,a_mathalignmentmid) or 0)
                                end
                                setoffsets(n,nil,nil,d,h)
                            end
                        end
                    end
                end
            end
        end
    end

    function nodes.handlers.mathmatrixrules(head,where,callback,attr,preamble) -- 0x3
        if (callback & mathmatrix_code == 0) then
            -- nothing to do here
        elseif where == "wrapup" then
            hrule_pass(head,attr,preamble)
            vrule_pass(head,attr,preamble)
        end
    end

    local enabled = false

    interfaces.implement {
        name      = "enablematrixrules",
     -- onlyonce  = true,
        public    = true,
        protected = true,
        actions   = function()
            if not enabled then
                nodes.tasks.enableaction("alignments","nodes.handlers.mathmatrixrules") -- 0x3
                enabled = true
            end
        end,
    }

end

    --

    local a_ornament     <const> = attributes.system("mathmatrixornament")

    local leftornament   <const> = tex.boundaries.system("c_math_matrix_ornament_l")
    local rightornament  <const> = tex.boundaries.system("c_math_matrix_ornament_r")
    local topornament    <const> = tex.boundaries.system("c_math_matrix_ornament_t")
    local bottomornament <const> = tex.boundaries.system("c_math_matrix_ornament_b")

    local verticalline   <const> = tex.boundaries.system("c_math_matrix_vl_boundary")

    local left     = 0
    local right    = 0
    local nofcells = 0
    local found    = false

    local lefts    = false
    local rights   = false
    local tops     = false
    local bottoms  = false

    local function first_pass(head,callback,attr,preamble,signal)
        nofcells = 0
        left     = 0
        right    = 0
        found    = false
        lefts   = { }
        rights  = { }
        tops    = { }
        bottoms = { }
        for n in nextrecord, preamble do
            nofcells = nofcells + 1
        end
        local cells = { }
        for row in nextunset, head do
            local c = 0
            for cell in nextunset, getlist(row) do
                local list = getlist(cell)
                c = c + 1
                for bound in nextboundary, list do
                    local ornament = getdata(bound)
                 -- if ornament == verticalline then
                 --     -- this hack is is beyond ugly as we omit and span
                 --     c = c + 1
                 --     break
                 -- else
                    if ornament == leftornament then
                        if c == 1 then
                            local w = getwidth(cell)
                            if w > left then
                                left = w
                            end
                            setwidth(cell,0)
--                             cells[c+1] = true
                            cells[c] = true
                            found = true
                            lefts[#lefts+1] = cell
                        end
                    elseif ornament == rightornament then
                        if c == nofcells then
                            local w = getwidth(cell)
                            if w > right then
                                right = w
                            end
                            setwidth(cell,0)
--                             cells[c-1] = true
                            cells[c] = true
                            found = true
                            rights[#rights+1] = cell
                        end
                    elseif ornament == topornament then
                        setheight(row,0)
                        setdepth(row,0)
                        found = true
                        tops[#tops+1] = cell
                    elseif ornament == bottomornament then
                        setheight(row,0)
                        setdepth(row,0)
                        found = true
                        bottoms[#bottoms+1] = cell
                    end
                end
            end
        end
        if next(cells) then
            local c = 0
            for n in nextrecord, preamble do
                c = c + 1
                if cells[c] then
                    setwidth(n)
                end
            end
        end
    end

    local function second_pass(box,callback,attr,preamble,signal)
        if found then
            local head = getlist(nuts.getbox(box))
            local leftmargin   = texgetdimen("d_math_matrix_margin_l")
            local rightmargin  = texgetdimen("d_math_matrix_margin_r")
            local topmargin    = texgetdimen("d_math_matrix_margin_t")
            local bottommargin = texgetdimen("d_math_matrix_margin_b")
            for i=1,#lefts do
                setoffsets(lefts[i],-(left+leftmargin),0)
            end
            for i=1,#rights do
                setoffsets(rights[i],rightmargin,0)
            end
            for i=1,#tops do
                setoffsets(tops[i],0,topmargin)
            end
            for i=1,#bottoms do
                setoffsets(bottoms[i],0,-bottommargin)
            end
            found   = false --safeguard
            lefts   = false
            rights  = false
            tops    = false
            bottoms = false
            texsetdimen("global","d_math_matrix_max_left", left)
            texsetdimen("global","d_math_matrix_max_right",right)
        end
    end

    function nodes.handlers.mathmatrixornaments(head,where,callback,attr,preamble) -- 0x3
        if (callback & mathmatrix_code == 0) then
            -- nothing to do here
        elseif where == "preroll" then
            first_pass(head,callback,attr,preamble,signal)
     -- elseif where == "wrapup" then
     --     second_pass(head,callback,attr,preamble,signal)
        end
    end

    interfaces.implement {
        name      = "shiftmatrixornaments",
        actions   = second_pass,
        arguments = "integer",
    }

    local enabled = false

    interfaces.implement {
        name      = "enablemathalignrelocate",
     -- onlyonce  = true,
        public    = true,
        protected = true,
        actions   = function()
            if not enabled then
                nodes.tasks.enableaction("alignments","nodes.handlers.mathalignrelocate")
                enabled = true
            end
        end,
    }

    local enabled = false

    interfaces.implement {
        name      = "enablematrixornaments",
     -- onlyonce  = true,
        public    = true,
        protected = true,
        actions   = function()
            if not enabled then
                nodes.tasks.enableaction("alignments","nodes.handlers.mathmatrixornaments")
                enabled = true
            end
        end,
    }

end

-- This only kicks in when we have a callback set.

local report = logs.reporter("alignment","preamble")
local trace    trackers.register("alignments.showstates",function(v) trace = v end)

function nodes.handlers.showpreamble(head,where,callback,attr,preamble)
    if trace then
        local c = 0
        for n, id in nextnode, preamble do
            if id == unset_code or id == alignrecord_code then
                c = c + 1
                report("stage %a, cell %i, width %p",where,c,getwidth(n))
            elseif id == glue_code then
                report("stage %a, tabskip %s",where,node.direct.gluetostring(n))
            else
                report("stage %a, node %a",where,nodecodes[id])
            end
        end
    end
end

-- Another one

do

    local a_alignskip <const> = attributes.private("alignskip")

    local findattribute = nuts.findattribute

    function nodes.handlers.tabulateskip(head,where,callback,attr,preamble)
        if callback & alignskip_code ~= 0 then
            -- we could loop with find_attribute and backtrack to the previous row
            if where == "wrapup" and findattribute(head,a_alignskip,hlist_code) then
                local previous = false
                for row, id, subtype, list in nextlist, head do
                    if id == hlist_code and subtype == row_code then
                        if previous and previous ~= head and getattr(row,a_alignskip) == 1 then
                            local glue = newglue(gettotal(previous))
                            setattrlist(glue,previous)
                            replacenode(head,previous,glue)
                            previous = false
                        else
                            previous = row
                        end
                    end
                end
            end
        end
    end

    local enabled = false

    interfaces.implement {
        name      = "enablealignskips",
     -- onlyonce  = true,
        public    = true,
        protected = true,
        actions   = function()
            if not enabled then
                nodes.tasks.enableaction("alignments","nodes.handlers.tabulateskip")
                enabled = true
            end
        end,
    }

end
