diff options
Diffstat (limited to 'tex/context/base/page-lin.lua')
| -rw-r--r-- | tex/context/base/page-lin.lua | 232 | 
1 files changed, 232 insertions, 0 deletions
| diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua new file mode 100644 index 000000000..91412d84f --- /dev/null +++ b/tex/context/base/page-lin.lua @@ -0,0 +1,232 @@ +if not modules then modules = { } end modules ['page-lin'] = { +    version   = 1.001, +    comment   = "companion to page-lin.mkiv", +    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL", +    copyright = "PRAGMA ADE / ConTeXt Development Team", +    license   = "see context related readme files" +} + +-- experimental + +nodes            = nodes            or { } +nodes.lines      = nodes.lines      or { } +nodes.lines.data = nodes.lines.data or { } -- start step tag + +do + +    -- if there is demand for it, we can support multiple numbering streams +    -- and use more than one attibute + +    local hlist, vlist, whatsit = node.id('hlist'), node.id('vlist'), node.id('whatsit') + +    local display_math     = attributes.numbers['display-math']   or 121 +    local line_number      = attributes.numbers['line-number']    or 131 +    local line_reference   = attributes.numbers['line-reference'] or 132 + +    local current_list     = { } +    local cross_references = { } +    local chunksize        = 250 -- not used in boxed + +    local has_attribute    = node.has_attribute +    local traverse_id      = node.traverse_id +    local copy             = node.copy +    local format           = string.format +    local sprint           = tex.sprint + +    local data = nodes.lines.data + +    nodes.lines.scratchbox = nodes.lines.scratchbox or 0 + +    -- cross referencing + +    function nodes.lines.number(n) +        local cr = cross_references[n] or 0 +        cross_references[n] = nil +        return cr +    end + +    local function resolve(n,m) +        while n do +            local id = n.id +            if id == whatsit then +                local a = has_attribute(n,line_reference) +                if a then +                    cross_references[a] = m +                end +            elseif id == hlist or id == vlist then +                resolve(n.list,m) +            end +            n = n.next +        end +    end + +    -- boxed variant + +    nodes.lines.boxed = { } + +    function nodes.lines.boxed.register(configuration) +        data[#data+1] = configuration +        return #data +    end +    function nodes.lines.boxed.setup(n,configuration) +        local d = data[n] +        if d then +            for k,v in pairs(configuration) do d[k] = v end +        else +            data[n] = configuration +        end +        return n +    end + +    local leftskip = nodes.leftskip + +    function nodes.lines.boxed.stage_one(n) +        current_list = { } +        local head = tex.box[n].list +        local function check_number(n,a) -- move inline +            local d = data[a] +            if d then +                local s = d.start +                current_list[#current_list+1] = { n, s } +                sprint(tex.ctxcatcodes, format("\\makenumber{%s}{%s}{%s}{%s}{%s}\\endgraf", d.tag or "", s, n.shift, n.width, leftskip(n.list))) +                d.start = s + (d.step or 1) +            end +        end +        for n in traverse_id(hlist,head) do -- attr test here and quit as soon as zero found +            if n.height == 0 and n.depth == 0 then +                -- skip funny hlists +            else +                local a = has_attribute(n.list,line_number) +                if a and a > 0 then +                    if has_attribute(n,display_math) then +                        if nodes.is_display_math(n) then +                            check_number(n,a) +                        end +                    else +                        if node.first_character(n.list) then +                            check_number(n,a) +                        end +                    end +                end +            end +        end +    end + +    function nodes.lines.boxed.stage_two(n,m) +        m = m or nodes.lines.scratchbox +        local t, i = { }, 0 +        for l in traverse_id(hlist,tex.box[m].list) do +            t[#t+1] = copy(l) +        end +        for _, l in ipairs(current_list) do +            local n, m = l[1], l[2] +            i = i + 1 +            t[i].next = n.list +            n.list = t[i] +            resolve(n,m) +       end +    end + +    -- flow variant +    -- +    -- it's too hard to make this one robust, so for the moment it's not +    -- available; todo: line refs + +    if false then + +        nodes.lines.flowed = { } + +        function nodes.lines.flowed.prepare() +            for i=1,#data do +                sprint(tex.ctxcatcodes,format("\\ctxlua{nodes.lines.flowed.prepare_a(%s)}\\ctxlua{nodes.lines.flowed.prepare_b(%s)}",i, i)) +            end +        end + +        function nodes.lines.flowed.prepare_a(i) +            local d = data[i] +            local p = d.present +            if p < chunksize then +                local b = nodes.lines.scratchbox +                sprint(tex.ctxcatcodes, format("{\\forgetall\\global\\setbox%s=\\vbox{\\unvbox%s\\relax\\offinterlineskip", b, b)) +                while p < chunksize do +                    sprint(tex.ctxcatcodes, format("\\mkmaketextlinenumber{%s}{%s}\\endgraf",d.start,1)) +                    p = p + 1 +                    d.start = d.start + d.step +                end +                d.present = p +                sprint(tex.ctxcatcodes, "}}") +            end +        end + +        function nodes.lines.flowed.prepare_b(i) +            local d = data[i] +            local b = nodes.lines.scratchbox +            local l = tex.box[b] +            if l then +                l = l.list +                local n = d.numbers +                while l do +                    if l.id == hlist then +                        local m = node.copy(l) +                        m.next = nil +                        if n then +                            n.next = m +                        else +                            d.numbers = m +                        end +                        n = m +                    end +                    l = l.next +                end +            end +            tex.box[b] = nil +        end + +        function nodes.lines.flowed.cleanup(i) +            if i then +                node.flush_list(data[i].numbers) +            else +                for i=1,#data do +                    node.flush_list(data[i].numbers) +                end +            end +        end + +        function nodes.lines.flowed.apply(head) +            local function check_number(n,a) +                local d = data[a] +                if d then +                    local m = d.numbers +                    if m then +                        d.numbers = m.next +                        m.next = n.list +                        n.list = m +                        d.present = d.present - 1 +                    end +                end +            end +            for n in node.traverse(head) do +                local id = n.id +                if id == hlist then +                    if n.height == 0 and n.depth == 0 then +                        -- skip funny hlists +                    else +                        local a = has_attribute(n,line_number) +                        if a and a > 0 then +                            if has_attribute(n,display_math) then +                                if nodes.is_display_math(n) then +                                    check_number(n,a) +                                end +                            else +                                check_number(n,a) +                            end +                        end +                    end +                end +            end +            return head, true +        end + +    end + +end | 
