if not modules then modules = { } end modules ['math-fnt'] = {
    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"
}

-- It is a pitty that we don't have a unicode character that can be used but that never
-- gets copied when we cut and paste. Not all pdf viewers ignore 0xFFFD for instance.

local round = math.round
local setmetatableindex = table.setmetatableindex

local nuts            = nodes.nuts
local tonut           = nodes.tonut
local nodepool        = nuts.pool

local vlist_code      <const> = nodes.nodecodes.vlist

local new_hlist       = nodepool.hlist
local new_vlist       = nodepool.vlist
----- new_glyph       = nodepool.glyph
local new_glyph       = nuts.newmathglyph

local getattrlst      = nuts.getattributelist
local setattrlst      = nuts.setattributelist
local setwhd          = nuts.setwhd
local getwhd          = nuts.getwhd
local getid           = nuts.getid
local setlist         = nuts.setlist
local flushlist       = nuts.flushlist

local chardata        = fonts.hashes.characters
local addcharacters   = font.addcharacters

local texconditionals = tex.conditionals

-- not yet ok for compact fonts .. needs checking .. or just make this non-compact only
-- there's also an inaccuracy creeping in: \sqrt{\quad\blackrule[height=25pt,depth=25pt]}

local cache = setmetatableindex(function(t,width)
    local v = setmetatableindex(function(t,height)
        local v = setmetatableindex(function(t,depth)
            local v = setmetatableindex(function(t,font)
                local v = setmetatableindex(function(t,char)
                    t[char] = v
                    return v
                end)
                t[font] = v
                return v
            end)
            t[depth] = v
            return v
        end)
        t[height] = v
        return v
    end)
    t[width] = v
    return v
end)

local enabled = "both"  directives.register("math.extensibles", function(v) enabled = v end) -- default per 2022-08-25

-- updaters.register("tagging.state.enable", function() enabled = "both" end) -- for now

local function register_extensible_callback(font,char,style,att,box)
    if enabled and texconditionals["c_math_extensibles"] then
        -- We don't share (yet)!
        local fontdata = chardata[font]
        local oldchar  = fontdata[char]
        if oldchar and not oldchar.keepvirtual then
            if enabled == true or enabled == "both" or oldchar.partsorientation == enabled then
                -- we're okay
            else
                return
            end
            -- actually we don't want colors and such so if we do finalize we
            -- should be more selective:
         -- updaters.apply("tagging.state.disable")
         -- nodes.handlers.finalizelist(box)
         -- updaters.apply("tagging.state.enable")
         -- updaters.apply("tagging.state.disable")
            local id = getid(box)
            local al = att
            local wd, ht, dp = getwhd(box)
            local unicode = oldchar.unicode or char
            -- we cannot have self referencing t3 fonts .. see devirtualize code
            local oldcommands = oldchar.oldcommands
            local newcommands = oldchar.commands
            if oldcommands then
                oldchar.commands = oldcommands
            end
            -- these need to be applied here
            local p  = fonts.hashes.parameters[font]
            local sx = round(1000/(p.extendfactor  or 1)) or 1000
            local sy = round(1000/(p.squeezefactor or 1)) or 1000
         -- -- we saved a scaled glyph stream so we now use an unscaled one ... horrible hack:
         -- if sx ~= 1000 then
         --     wd = wd * 7200/7227
         -- end
         -- if sy ~= 1000 then
         --     ht = ht * 7200/7227
         --     dp = dp * 7200/7227
         -- end
            local private = cache[wd][ht][dp][font][unicode]
            if private then
                flushlist(box)
                setlist(box) -- added, needs checking
            else
                private = fonts.helpers.setboxdirectly(font,unicode,box,true) -- expose=true so we get color
                cache[wd][ht][dp][font][unicode] = private
            end
            local glyph = new_glyph(font,private,al)
            setattrlst(glyph,al)
            nuts.setscales(glyph,1000,sx,sy)
            --
         -- if fonts.hashes.properties[font].compactmath then
         --     nuts.setscales(g,1000,1000,1000)
         -- end
            --
            -- nasty, testcase: bold math sqrt extensible
            --
            local n = new_hlist(glyph)
            --
            if newcommands then
                oldchar.commands = newcommands
            end
            --
         -- local newchar = {
         --     unicode = unicode,
         --     width   = wd,
         --     height  = ht,
         --     depth  =  dp,
         -- }
         -- local p = oldchar.parts
         -- if p then
         --     local first = fontdata[p[#p].glyph]
         --     local last  = fontdata[p[ 1].glyph]
         --     if first then
         --         newchar.topleft  = first.topleft
         --         newchar.topright = first.topright
         --     end
         --     if last then
         --         newchar.bottomleft  = last.bottomleft
         --         newchar.bottomright = last.bottomright
         --     end
         -- end
         -- addcharacters(font, { [private] = newchar })
            -- so the dimensions of the box don't match the glyph scale!
            setwhd(n,wd,ht,dp)
            setattrlst(n,al)
            if id == vlist_code then
                n = new_vlist(n)
                setwhd(n,wd,ht,dp)
                setattrlst(n,al)
            end
            return n
        end
    end
end

callbacks.register {
    name    = "register_extensible",
    action  = register_extensible_callback,
    comment = "register math extensible construct",
    frozen  = true,
}
