if not modules then modules = { } end modules['s-math-characters-renewed'] = {
    version   = 1.001,
    comment   = "companion to s-math-characters-renewed.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL.  Renewed by Julius Ross",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

moduledata.math            = moduledata.math            or { }
moduledata.math.characters = moduledata.math.characters or { }

local concat = table.concat
local lower = string.lower
local utfchar = utf.char
local round = math.round
local setmetatableindex = table.setmetatableindex
local sortedhash = table.sortedhash

local context        = context

local fontdata       = fonts.hashes.identifiers
local chardata       = characters.data
local blocks         = characters.blocks

local no_description = "no description, private to font"

local limited        = true
local fillinthegaps  = true
local upperlimit     = 0x0007F
local upperlimit     = 0xF0000

local f_unicode      = string.formatters["%U"]
local f_slot         = string.formatters["%s/%0X"]


function moduledata.math.characters.showlist(specification)
    specification      = interfaces.checkedspecification(specification)
    local id           = specification.number -- or specification.id
    local list         = specification.list
    local showvirtual  = specification.virtual == "all"
    local method       = specification.method
    local togglelist   = specification.togglelist
    local showfeatures = specification.showfeatures

    if not id then
        id = font.current()
    end
    if list == "" then
        list = nil
    end
    local blocks       = characters.blocks
    local tfmdata      = fontdata[id]
    local characters   = tfmdata.characters
    local descriptions = tfmdata.descriptions
    local resources    = tfmdata.resources
    local lookuptypes  = resources.lookuptypes
    local virtual      = tfmdata.properties.virtualized
    local names        = { }
    local gaps         = mathematics.gaps
    local sorted       = { }

    if type(togglelist) == "string" then
        local parsed = {}
        for s in togglelist:gmatch("[^,]+") do
            parsed[#parsed+1] = s:match("^%s*(.-)%s*$")
        end
        togglelist = parsed
    end

    if type(list) == "string" then
        local tokens = utilities.parsers.settings_to_array(list)
        sorted = { }
        for i=1,#tokens do
            local token = tokens[i]
            local b = blocks[token]
            if b then
                -- it's a named block, expand its range
                for j=b.first,b.last do
                    sorted[#sorted+1] = gaps[j] or j
                end
            else
                -- fall back to treating it as a numeric codepoint
                sorted[#sorted+1] = tonumber(token)
            end
        end
    elseif type(list) == "table" then
        sorted = list
        for i=1,#sorted do
            sorted[i] = tonumber(sorted[i])
        end
    elseif fillinthegaps then
        sorted = table.keys(characters)
        for k, v in next, gaps do
            if characters[v] then
                sorted[#sorted+1] = k
            end
        end
        table.sort(sorted)
    else
        sorted = table.sortedkeys(characters)
    end

    if virtual then
        local fonts = tfmdata.fonts
        for i=1,#fonts do
            local id = fonts[i].id
            local name = fontdata[id].properties.name
            names[i] = (name and file.basename(name)) or id
        end
    end
    if check then
        for k, v in sortedhash(blocks) do
            if v.math then
                local first = v.first
                local last  = v.last
                local f, l  = 0, 0
                if first and last then
                    for unicode=first,last do
                        local code = gaps[unicode] or unicode
                        local char = characters[code]
                        if char and not (char.commands and not showvirtual) then
                            f = unicode
                            break
                        end
                    end
                    for unicode=last,first,-1 do
                        local code = gaps[unicode] or unicode
                        local char = characters[code]
                        if char and not (char.commands and not showvirtual) then
                            l = unicode
                            break
                        end
                    end
                    context.showmathcharacterssetrange(k,f,l)
                end
            end
        end
    else
        local function collectalllookups(tfmdata,script,language)
            local all     = setmetatableindex(function(t,k) local v = setmetatableindex("table") t[k] = v return v end)
            local shared  = tfmdata.shared
            local rawdata = shared and shared.rawdata
            if rawdata then
                local features = rawdata.resources.features
                if features.gsub then
                    local filter = {}
                    for kind, feature in next, features.gsub do
                        filter[kind] = (showfeatures ~= "none")
                    end
                    if togglelist then
                        for _, kind in ipairs(togglelist) do
                            if filter[kind] ~= nil then
                            filter[kind] = not filter[kind]
                            end
                        end
                    end
                    for kind, feature in next, features.gsub do
                        if not filter or filter[kind] ~= false then
                            local validlookups, lookuplist = fonts.handlers.otf.collectlookups(rawdata,kind,script,language)
                            if validlookups then
                                for i=1,#lookuplist do
                                    local lookup = lookuplist[i]
                                    local steps  = lookup.steps
                                    for i=1,lookup.nofsteps do
                                        local coverage = steps[i].coverage
                                        if coverage then
                                            for k, v in next, coverage do
                                                all[k][lookup.type][kind] = v
                                            end
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end
            return all
        end

        local alllookups = collectalllookups(tfmdata,"math","dflt")

        local luametatex = LUATEXENGINE == "luametatex"

        -- todo: first create sparser table so no test needed

if method == "manual" then
        context.starttabulate { "|T||||pl|" }
        for _, unicode in next, sorted do
            if not limited or unicode < upperlimit then
                local code = gaps[unicode] or unicode -- move up
                local char = characters[code]
                local desc = descriptions[code]
                local info = chardata[unicode] or chardata[code]
                if char then
                    local mathclass   = info.mathclass
                    local mathspec    = info.mathspec
                    local mathsymbol  = info.mathsymbol
                    local description = lower(info.description or no_description)
                    local names       = { }
                    if mathclass or mathspec then
                        if mathclass then
                            names[info.mathname or ""] = mathclass
                        end
                        if mathspec then
                            for i=1,#mathspec do
                                local mi = mathspec[i]
                                names[mi.name or ""] = mi.class
                            end
                        end
                    end
--                     print(description,fakename(description))
                    if next(names) then
                        local doit = true
                        for k, v in sortedhash(names) do
                            context.NC() if doit then context("%U",unicode) end
                            context.NC() if doit then context.char(unicode) end
                            context.NC() if k ~= "" then context.tex(k) end
                            context.NC() context.ex(v)
                            context.NC() if doit then context(description) end
                            context.NC() context.NR()
                            doit = false
                        end
                    else
                        local mathname = info.mathname
                        context.NC() context("%U",unicode)
                        context.NC() context.char(unicode)
                        context.NC() if mathname then context.tex(mathname) end
                        context.NC() context("ordinary")
                        context.NC() context(lower(description))
                        context.NC() context.NR()
                    end
                end
            end
        end
        context.stoptabulate()
else
        context.showmathcharactersstart()
        for _, unicode in next, sorted do
            if not limited or unicode < upperlimit then
                local code = gaps[unicode] or unicode -- move up
                local char = characters[code]
                local desc = descriptions[code]
                local info = chardata[code]
                if char then
-- context(utf.char(char.smaller))
                    local commands = char.commands
                    if commands and not showvirtual then
                        -- skip
                    else
                        local next_sizes  = char.next
                        local vparts      = char.vparts or char.vert_variants
                        local hparts      = char.hparts or char.horiz_variants
                        local mathclass   = info.mathclass
                        local mathspec    = info.mathspec
                        local mathsymbol  = info.mathsymbol
                        local description = info.description or no_description
                        context.showmathcharactersdefinemathsymbol(
                           f_unicode(code),
                           code,
                           mathclass or 0
                       )
                        context.showmathcharactersstartentry(
                       )
                        context.showmathcharactersstartentry(
                        )
                        context.showmathcharactersreference(
                            f_unicode(unicode)
                        )
                        context.showmathcharactersentryhexdectit(
                            f_unicode(code),
                            code,
                            lower(description)
                        )
                        if luametatex then
                            context.showmathcharactersentrywdhtdpicta(
                                code
                            )
                        else
                            context.showmathcharactersentrywdhtdpicta(
                                round(char.width     or 0),
                                round(char.height    or 0),
                                round(char.depth     or 0),
                                round(char.italic    or 0),
                                round(char.topanchor or char.topaccent or 0)
                            )
                        end
                        if virtual and commands then
                            local t = { }
                            for i=1,#commands do
                                local ci = commands[i]
                                if ci[1] == "slot" then
                                    local fnt, idx = ci[2], ci[3]
                                    t[#t+1] = f_slot(names[fnt] or fnt,idx)
                                end
                            end
                            if #t > 0 then
                                context.showmathcharactersentryresource(concat(t,", "))
                            end
                        end
                        if mathclass or mathspec then
                            context.showmathcharactersstartentryclassspec()
                            if mathclass then
                                context.showmathcharactersentryclassname(mathclass,info.mathname or "no name")
                            end
                            if mathspec then
                                for i=1,#mathspec do
                                    local mi = mathspec[i]
                                    context.showmathcharactersentryclassname(mi.class,mi.name or "no name")
                                end
                            end
                            context.showmathcharactersstopentryclassspec()
                        end
                        if mathsymbol then
                            context.showmathcharactersentrysymbol(f_unicode(mathsymbol),mathsymbol)
                        end
                        if next_sizes then
                            local n, done = 0, { }
                            context.showmathcharactersstartnext()
                            while next_sizes do
                                n = n + 1
                                if done[next_sizes] then
                                    context.showmathcharactersdefinesizesymbol(
                                        f_unicode(next_sizes),
                                        next_sizes,
                                        mathclass or 0
                                    )
                                    context.showmathcharactersnextcycle(n)
                                    break
                                else
                                    done[next_sizes] = true
                                    context.showmathcharactersdefinesizesymbol(
                                        f_unicode(next_sizes),
                                        next_sizes,
                                        mathclass or 0
                                    )
                                    context.showmathcharactersnextentry(n,f_unicode(next_sizes),next_sizes)
                                    next_sizes = characters[next_sizes]
                                    vparts = next_sizes.vparts or next_sizes.vert_variants  or vparts
                                    hparts = next_sizes.hparts or next_sizes.horiz_variants or hparts
                                    if next_sizes then
                                        next_sizes = next_sizes.next
                                    end
                                end
                            end
                            context.showmathcharactersstopnext()
                            if vparts or hparts then
                                context.showmathcharactersbetweennextandvariants()
                            end
                        end
                        if vparts then
                            context.showmathcharactersstartvparts()
                            for i=1,#vparts do -- we might go top-down in the original
                                local vi = vparts[i]
                                context.showmathcharactersvpartsentry(i,f_unicode(vi.glyph),vi.glyph)
                            end
                            context.showmathcharactersstopvparts()
                        end
                        if hparts then
                            context.showmathcharactersstarthparts()
                            for i=1,#hparts do
                                local hi = hparts[#hparts-i+1]
                                context.showmathcharactershpartsentry(i,f_unicode(hi.glyph),hi.glyph)
                            end
                            context.showmathcharactersstophparts()
                        end
                        local lookups = alllookups[unicode]
                        if lookups then
                            local variants   = { }
                            local singles    = lookups.gsub_single
                            local alternates = lookups.gsub_alternate
                            if singles then
                                for lookupname, code in next, singles do
                                    variants[code] = lookupname
                                end
                            end
                            if singles then
                                for lookupname, codes in next, alternates do
                                    for i=1,#codes do
                                        variants[codes[i]] = lookupname .. " : " .. i
                                    end
                                end
                            end
                            if next(variants) then
                                context.showmathcharactersstartlookupvariants()
                                local i = 0
                                for variant, lookuptype in sortedhash(variants) do
                                    i = i + 1
                                    context.showmathcharactersdefinevariantsymbol(
                                    f_unicode(variant),
                                    variant,
                                    mathclass or 0 -- this is the mathclass of the base which I think is all we have
                                    )
                                    context.showmathcharacterslookupvariant(i,f_unicode(variant),variant,lookuptype)


                                    local variantchar = characters[variant]
                                    local next_sizes =  variantchar.next
                                    if next_sizes then
                                    local n, done = 0, { }
                                    context.showmathcharactersstartnext()
                                    while next_sizes do --we are repeating code here from above, so better have a function
                                        n = n + 1
                                        if done[next_sizes] then
                                            context.showmathcharactersdefinesizesymbol(
                                                f_unicode(next_sizes),
                                                next_sizes,
                                                mathclass or 0
                                            )
                                            context.showmathcharactersnextcycle(n)
                                            break
                                        else
                                            done[next_sizes] = true
                                            context.showmathcharactersdefinesizesymbol(
                                            f_unicode(next_sizes),
                                            next_sizes,
                                            mathclass or 0-- this is the mathclass of the base which I think is all we have
                                            )
                                            context.showmathcharactersnextentry(n,f_unicode(next_sizes),next_sizes)
                                            next_sizes = characters[next_sizes]
                                            vparts = next_sizes.vparts or next_sizes.vert_variants  or vparts
                                            hparts = next_sizes.hparts or next_sizes.horiz_variants or hparts
                                            if next_sizes then
                                                next_sizes = next_sizes.next
                                            end
                                        end
                                    end
                                end



                                    
                                end
                                context.showmathcharactersstoplookupvariants()
                            end
                        end
                        context.showmathcharactersstopentry()
                    end
                end
            end
        end
        context.showmathcharactersstop()

end

    end
end
