summaryrefslogtreecommitdiff
path: root/tex/context/base/node-ini.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/node-ini.lua')
-rw-r--r--tex/context/base/node-ini.lua842
1 files changed, 421 insertions, 421 deletions
diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua
index 1de6fbddd..5a3986c3a 100644
--- a/tex/context/base/node-ini.lua
+++ b/tex/context/base/node-ini.lua
@@ -1,421 +1,421 @@
-if not modules then modules = { } end modules ['node-ini'] = {
- 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"
-}
-
---[[ldx--
-<p>Most of the code that had accumulated here is now separated in
-modules.</p>
---ldx]]--
-
--- this module is being reconstructed
-
-local next, type = next, type
-local format, match, gsub = string.format, string.match, string.gsub
-local concat, remove = table.concat, table.remove
-local sortedhash, sortedkeys, swapped, tohash = table.sortedhash, table.sortedkeys, table.swapped, table.tohash
-local utfchar = utf.char
-local lpegmatch = lpeg.match
-local formatcolumns = utilities.formatters.formatcolumns
-
---[[ldx--
-<p>Access to nodes is what gives <l n='luatex'/> its power. Here we
-implement a few helper functions. These functions are rather optimized.</p>
---ldx]]--
-
---[[ldx--
-<p>When manipulating node lists in <l n='context'/>, we will remove
-nodes and insert new ones. While node access was implemented, we did
-quite some experiments in order to find out if manipulating nodes
-in <l n='lua'/> was feasible from the perspective of performance.</p>
-
-<p>First of all, we noticed that the bottleneck is more with excessive
-callbacks (some gets called very often) and the conversion from and to
-<l n='tex'/>'s datastructures. However, at the <l n='lua'/> end, we
-found that inserting and deleting nodes in a table could become a
-bottleneck.</p>
-
-<p>This resulted in two special situations in passing nodes back to
-<l n='tex'/>: a table entry with value <type>false</type> is ignored,
-and when instead of a table <type>true</type> is returned, the
-original table is used.</p>
-
-<p>Insertion is handled (at least in <l n='context'/> as follows. When
-we need to insert a node at a certain position, we change the node at
-that position by a dummy node, tagged <type>inline</type> which itself
-has_attribute the original node and one or more new nodes. Before we pass
-back the list we collapse the list. Of course collapsing could be built
-into the <l n='tex'/> engine, but this is a not so natural extension.</p>
-
-<p>When we collapse (something that we only do when really needed), we
-also ignore the empty nodes. [This is obsolete!]</p>
---ldx]]--
-
-local traverse = node.traverse
-local traverse_id = node.traverse_id
-local free_node = node.free
-local remove_node = node.remove
-local insert_node_before = node.insert_before
-local insert_node_after = node.insert_after
-local node_fields = node.fields
-
-local allocate = utilities.storage.allocate
-
-nodes = nodes or { }
-local nodes = nodes
-
-nodes.handlers = nodes.handlers or { }
-
--- there will be more of this:
-
-local skipcodes = allocate {
- [ 0] = "userskip",
- [ 1] = "lineskip",
- [ 2] = "baselineskip",
- [ 3] = "parskip",
- [ 4] = "abovedisplayskip",
- [ 5] = "belowdisplayskip",
- [ 6] = "abovedisplayshortskip",
- [ 7] = "belowdisplayshortskip",
- [ 8] = "leftskip",
- [ 9] = "rightskip",
- [ 10] = "topskip",
- [ 11] = "splittopskip",
- [ 12] = "tabskip",
- [ 13] = "spaceskip",
- [ 14] = "xspaceskip",
- [ 15] = "parfillskip",
- [ 16] = "thinmuskip",
- [ 17] = "medmuskip",
- [ 18] = "thickmuskip",
- [100] = "leaders",
- [101] = "cleaders",
- [102] = "xleaders",
- [103] = "gleaders",
-}
-
-local penaltycodes = allocate { -- unfortunately not used
- [ 0] = "userpenalty",
-}
-
-table.setmetatableindex(penaltycodes,function(t,k) return "userpenalty" end) -- not used anyway
-
-local noadcodes = allocate {
- [ 0] = "ord",
- [ 1] = "opdisplaylimits",
- [ 2] = "oplimits",
- [ 3] = "opnolimits",
- [ 4] = "bin",
- [ 5] = "rel",
- [ 6] = "open",
- [ 7] = "close",
- [ 8] = "punct",
- [ 9] = "inner",
- [10] = "under",
- [11] = "over",
- [12] = "vcenter",
-}
-
-local listcodes = allocate {
- [ 0] = "unknown",
- [ 1] = "line",
- [ 2] = "box",
- [ 3] = "indent",
- [ 4] = "alignment", -- row or column
- [ 5] = "cell",
-}
-
-local glyphcodes = allocate {
- [0] = "character",
- [1] = "glyph",
- [2] = "ligature",
- [3] = "ghost",
- [4] = "left",
- [5] = "right",
-}
-
-local kerncodes = allocate {
- [0] = "fontkern",
- [1] = "userkern",
- [2] = "accentkern",
-}
-
-local mathcodes = allocate {
- [0] = "beginmath",
- [1] = "endmath",
-}
-
-local fillcodes = allocate {
- [0] = "stretch",
- [1] = "fi",
- [2] = "fil",
- [3] = "fill",
- [4] = "filll",
-}
-
-local margincodes = allocate {
- [0] = "left",
- [1] = "right",
-}
-
-local disccodes = allocate {
- [0] = "discretionary", -- \discretionary
- [1] = "explicit", -- \-
- [2] = "automatic", -- following a -
- [3] = "regular", -- simple
- [4] = "first", -- hard first item
- [5] = "second", -- hard second item
-}
-
-local function simplified(t)
- local r = { }
- for k, v in next, t do
- r[k] = gsub(v,"_","")
- end
- return r
-end
-
-local nodecodes = simplified(node.types())
-local whatcodes = simplified(node.whatsits())
-
-skipcodes = allocate(swapped(skipcodes,skipcodes))
-noadcodes = allocate(swapped(noadcodes,noadcodes))
-nodecodes = allocate(swapped(nodecodes,nodecodes))
-whatcodes = allocate(swapped(whatcodes,whatcodes))
-listcodes = allocate(swapped(listcodes,listcodes))
-glyphcodes = allocate(swapped(glyphcodes,glyphcodes))
-kerncodes = allocate(swapped(kerncodes,kerncodes))
-penaltycodes = allocate(swapped(penaltycodes,penaltycodes))
-mathcodes = allocate(swapped(mathcodes,mathcodes))
-fillcodes = allocate(swapped(fillcodes,fillcodes))
-margincodes = allocate(swapped(margincodes,margincodes))
-disccodes = allocate(swapped(disccodes,disccodes))
-
-nodes.skipcodes = skipcodes nodes.gluecodes = skipcodes -- more official
-nodes.noadcodes = noadcodes
-nodes.nodecodes = nodecodes
-nodes.whatcodes = whatcodes nodes.whatsitcodes = whatcodes -- more official
-nodes.listcodes = listcodes
-nodes.glyphcodes = glyphcodes
-nodes.kerncodes = kerncodes
-nodes.penaltycodes = kerncodes
-nodes.mathcodes = mathcodes
-nodes.fillcodes = fillcodes
-nodes.margincodes = margincodes
-nodes.disccodes = disccodes nodes.discretionarycodes = disccodes
-
-listcodes.row = listcodes.alignment
-listcodes.column = listcodes.alignment
-
-kerncodes.italiccorrection = kerncodes.userkern
-kerncodes.kerning = kerncodes.fontkern
-
-nodes.codes = allocate { -- mostly for listing
- glue = skipcodes,
- noad = noadcodes,
- node = nodecodes,
- hlist = listcodes,
- vlist = listcodes,
- glyph = glyphcodes,
- kern = kerncodes,
- penalty = penaltycodes,
- math = mathnodes,
- fill = fillcodes,
- margin = margincodes,
- disc = disccodes,
- whatsit = whatcodes,
-}
-
-local report_codes = logs.reporter("nodes","codes")
-
-function nodes.showcodes()
- local t = { }
- for name, codes in sortedhash(nodes.codes) do
- local sorted = sortedkeys(codes)
- for i=1,#sorted do
- local s = sorted[i]
- if type(s) ~= "number" then
- t[#t+1] = { name, s, codes[s] }
- end
- end
- end
- formatcolumns(t)
- for k=1,#t do
- report_codes (t[k])
- end
-end
-
-local whatsit_node = nodecodes.whatsit
-
-local messyhack = tohash { -- temporary solution
- nodecodes.attributelist,
- nodecodes.attribute,
- nodecodes.gluespec,
- nodecodes.action,
-}
-
-function nodes.fields(n)
- local id = n.id
- if id == whatsit_node then
- return node_fields(id,n.subtype)
- else
- local t = node_fields(id)
- if messyhack[id] then
- for i=1,#t do
- if t[i] == "subtype" then
- remove(t,i)
- break
- end
- end
- end
- return t
- end
-end
-
-trackers.register("system.showcodes", nodes.showcodes)
-
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local glue_code = nodecodes.glue
-
--- if t.id == glue_code then
--- local s = t.spec
--- print(t)
--- print(s,s and s.writable)
--- if s and s.writable then
--- free_node(s)
--- end
--- t.spec = nil
--- end
-
-local function remove(head, current, free_too)
- local t = current
- head, current = remove_node(head,current)
- if t then
- if free_too then
- free_node(t)
- t = nil
- else
- t.next = nil
- t.prev = nil
- end
- end
- return head, current, t
-end
-
-nodes.remove = remove
-
-function nodes.delete(head,current)
- return remove(head,current,true)
-end
-
-nodes.before = insert_node_before
-nodes.after = insert_node_after
-
--- we need to test this, as it might be fixed now
-
-function nodes.before(h,c,n)
- if c then
- if c == h then
- n.next = h
- n.prev = nil
- h.prev = n
- else
- local cp = c.prev
- n.next = c
- n.prev = cp
- if cp then
- cp.next = n
- end
- c.prev = n
- return h, n
- end
- end
- return n, n
-end
-
-function nodes.after(h,c,n)
- if c then
- local cn = c.next
- if cn then
- n.next = cn
- cn.prev = n
- else
- n.next = nil
- end
- c.next = n
- n.prev = c
- return h, n
- end
- return n, n
-end
-
--- local h, c = nodes.replace(head,current,new)
--- local c = nodes.replace(false,current,new)
--- local c = nodes.replace(current,new)
-
-function nodes.replace(head,current,new) -- no head returned if false
- if not new then
- head, current, new = false, head, current
- end
- local prev, next = current.prev, current.next
- if next then
- new.next = next
- next.prev = new
- end
- if prev then
- new.prev = prev
- prev.next = new
- end
- if head then
- if head == current then
- head = new
- end
- free_node(current)
- return head, new
- else
- free_node(current)
- return new
- end
-end
-
--- will move
-
-local function count(stack,flat)
- local n = 0
- while stack do
- local id = stack.id
- if not flat and id == hlist_code or id == vlist_code then
- local list = stack.list
- if list then
- n = n + 1 + count(list) -- self counts too
- else
- n = n + 1
- end
- else
- n = n + 1
- end
- stack = stack.next
- end
- return n
-end
-
-nodes.count = count
-
-local left, space = lpeg.P("<"), lpeg.P(" ")
-
-local reference = left * (1-left)^0 * left * space^0 * lpeg.C((1-space)^0)
-
-function nodes.reference(n)
- return lpegmatch(reference,tostring(n))
-end
-
-if not node.next then
-
- function node.next(n) return n and n.next end
- function node.prev(n) return n and n.prev end
-
-end
+if not modules then modules = { } end modules ['node-ini'] = {
+ 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"
+}
+
+--[[ldx--
+<p>Most of the code that had accumulated here is now separated in
+modules.</p>
+--ldx]]--
+
+-- this module is being reconstructed
+
+local next, type = next, type
+local format, match, gsub = string.format, string.match, string.gsub
+local concat, remove = table.concat, table.remove
+local sortedhash, sortedkeys, swapped, tohash = table.sortedhash, table.sortedkeys, table.swapped, table.tohash
+local utfchar = utf.char
+local lpegmatch = lpeg.match
+local formatcolumns = utilities.formatters.formatcolumns
+
+--[[ldx--
+<p>Access to nodes is what gives <l n='luatex'/> its power. Here we
+implement a few helper functions. These functions are rather optimized.</p>
+--ldx]]--
+
+--[[ldx--
+<p>When manipulating node lists in <l n='context'/>, we will remove
+nodes and insert new ones. While node access was implemented, we did
+quite some experiments in order to find out if manipulating nodes
+in <l n='lua'/> was feasible from the perspective of performance.</p>
+
+<p>First of all, we noticed that the bottleneck is more with excessive
+callbacks (some gets called very often) and the conversion from and to
+<l n='tex'/>'s datastructures. However, at the <l n='lua'/> end, we
+found that inserting and deleting nodes in a table could become a
+bottleneck.</p>
+
+<p>This resulted in two special situations in passing nodes back to
+<l n='tex'/>: a table entry with value <type>false</type> is ignored,
+and when instead of a table <type>true</type> is returned, the
+original table is used.</p>
+
+<p>Insertion is handled (at least in <l n='context'/> as follows. When
+we need to insert a node at a certain position, we change the node at
+that position by a dummy node, tagged <type>inline</type> which itself
+has_attribute the original node and one or more new nodes. Before we pass
+back the list we collapse the list. Of course collapsing could be built
+into the <l n='tex'/> engine, but this is a not so natural extension.</p>
+
+<p>When we collapse (something that we only do when really needed), we
+also ignore the empty nodes. [This is obsolete!]</p>
+--ldx]]--
+
+local traverse = node.traverse
+local traverse_id = node.traverse_id
+local free_node = node.free
+local remove_node = node.remove
+local insert_node_before = node.insert_before
+local insert_node_after = node.insert_after
+local node_fields = node.fields
+
+local allocate = utilities.storage.allocate
+
+nodes = nodes or { }
+local nodes = nodes
+
+nodes.handlers = nodes.handlers or { }
+
+-- there will be more of this:
+
+local skipcodes = allocate {
+ [ 0] = "userskip",
+ [ 1] = "lineskip",
+ [ 2] = "baselineskip",
+ [ 3] = "parskip",
+ [ 4] = "abovedisplayskip",
+ [ 5] = "belowdisplayskip",
+ [ 6] = "abovedisplayshortskip",
+ [ 7] = "belowdisplayshortskip",
+ [ 8] = "leftskip",
+ [ 9] = "rightskip",
+ [ 10] = "topskip",
+ [ 11] = "splittopskip",
+ [ 12] = "tabskip",
+ [ 13] = "spaceskip",
+ [ 14] = "xspaceskip",
+ [ 15] = "parfillskip",
+ [ 16] = "thinmuskip",
+ [ 17] = "medmuskip",
+ [ 18] = "thickmuskip",
+ [100] = "leaders",
+ [101] = "cleaders",
+ [102] = "xleaders",
+ [103] = "gleaders",
+}
+
+local penaltycodes = allocate { -- unfortunately not used
+ [ 0] = "userpenalty",
+}
+
+table.setmetatableindex(penaltycodes,function(t,k) return "userpenalty" end) -- not used anyway
+
+local noadcodes = allocate {
+ [ 0] = "ord",
+ [ 1] = "opdisplaylimits",
+ [ 2] = "oplimits",
+ [ 3] = "opnolimits",
+ [ 4] = "bin",
+ [ 5] = "rel",
+ [ 6] = "open",
+ [ 7] = "close",
+ [ 8] = "punct",
+ [ 9] = "inner",
+ [10] = "under",
+ [11] = "over",
+ [12] = "vcenter",
+}
+
+local listcodes = allocate {
+ [ 0] = "unknown",
+ [ 1] = "line",
+ [ 2] = "box",
+ [ 3] = "indent",
+ [ 4] = "alignment", -- row or column
+ [ 5] = "cell",
+}
+
+local glyphcodes = allocate {
+ [0] = "character",
+ [1] = "glyph",
+ [2] = "ligature",
+ [3] = "ghost",
+ [4] = "left",
+ [5] = "right",
+}
+
+local kerncodes = allocate {
+ [0] = "fontkern",
+ [1] = "userkern",
+ [2] = "accentkern",
+}
+
+local mathcodes = allocate {
+ [0] = "beginmath",
+ [1] = "endmath",
+}
+
+local fillcodes = allocate {
+ [0] = "stretch",
+ [1] = "fi",
+ [2] = "fil",
+ [3] = "fill",
+ [4] = "filll",
+}
+
+local margincodes = allocate {
+ [0] = "left",
+ [1] = "right",
+}
+
+local disccodes = allocate {
+ [0] = "discretionary", -- \discretionary
+ [1] = "explicit", -- \-
+ [2] = "automatic", -- following a -
+ [3] = "regular", -- simple
+ [4] = "first", -- hard first item
+ [5] = "second", -- hard second item
+}
+
+local function simplified(t)
+ local r = { }
+ for k, v in next, t do
+ r[k] = gsub(v,"_","")
+ end
+ return r
+end
+
+local nodecodes = simplified(node.types())
+local whatcodes = simplified(node.whatsits())
+
+skipcodes = allocate(swapped(skipcodes,skipcodes))
+noadcodes = allocate(swapped(noadcodes,noadcodes))
+nodecodes = allocate(swapped(nodecodes,nodecodes))
+whatcodes = allocate(swapped(whatcodes,whatcodes))
+listcodes = allocate(swapped(listcodes,listcodes))
+glyphcodes = allocate(swapped(glyphcodes,glyphcodes))
+kerncodes = allocate(swapped(kerncodes,kerncodes))
+penaltycodes = allocate(swapped(penaltycodes,penaltycodes))
+mathcodes = allocate(swapped(mathcodes,mathcodes))
+fillcodes = allocate(swapped(fillcodes,fillcodes))
+margincodes = allocate(swapped(margincodes,margincodes))
+disccodes = allocate(swapped(disccodes,disccodes))
+
+nodes.skipcodes = skipcodes nodes.gluecodes = skipcodes -- more official
+nodes.noadcodes = noadcodes
+nodes.nodecodes = nodecodes
+nodes.whatcodes = whatcodes nodes.whatsitcodes = whatcodes -- more official
+nodes.listcodes = listcodes
+nodes.glyphcodes = glyphcodes
+nodes.kerncodes = kerncodes
+nodes.penaltycodes = kerncodes
+nodes.mathcodes = mathcodes
+nodes.fillcodes = fillcodes
+nodes.margincodes = margincodes
+nodes.disccodes = disccodes nodes.discretionarycodes = disccodes
+
+listcodes.row = listcodes.alignment
+listcodes.column = listcodes.alignment
+
+kerncodes.italiccorrection = kerncodes.userkern
+kerncodes.kerning = kerncodes.fontkern
+
+nodes.codes = allocate { -- mostly for listing
+ glue = skipcodes,
+ noad = noadcodes,
+ node = nodecodes,
+ hlist = listcodes,
+ vlist = listcodes,
+ glyph = glyphcodes,
+ kern = kerncodes,
+ penalty = penaltycodes,
+ math = mathnodes,
+ fill = fillcodes,
+ margin = margincodes,
+ disc = disccodes,
+ whatsit = whatcodes,
+}
+
+local report_codes = logs.reporter("nodes","codes")
+
+function nodes.showcodes()
+ local t = { }
+ for name, codes in sortedhash(nodes.codes) do
+ local sorted = sortedkeys(codes)
+ for i=1,#sorted do
+ local s = sorted[i]
+ if type(s) ~= "number" then
+ t[#t+1] = { name, s, codes[s] }
+ end
+ end
+ end
+ formatcolumns(t)
+ for k=1,#t do
+ report_codes (t[k])
+ end
+end
+
+local whatsit_node = nodecodes.whatsit
+
+local messyhack = tohash { -- temporary solution
+ nodecodes.attributelist,
+ nodecodes.attribute,
+ nodecodes.gluespec,
+ nodecodes.action,
+}
+
+function nodes.fields(n)
+ local id = n.id
+ if id == whatsit_node then
+ return node_fields(id,n.subtype)
+ else
+ local t = node_fields(id)
+ if messyhack[id] then
+ for i=1,#t do
+ if t[i] == "subtype" then
+ remove(t,i)
+ break
+ end
+ end
+ end
+ return t
+ end
+end
+
+trackers.register("system.showcodes", nodes.showcodes)
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+
+-- if t.id == glue_code then
+-- local s = t.spec
+-- print(t)
+-- print(s,s and s.writable)
+-- if s and s.writable then
+-- free_node(s)
+-- end
+-- t.spec = nil
+-- end
+
+local function remove(head, current, free_too)
+ local t = current
+ head, current = remove_node(head,current)
+ if t then
+ if free_too then
+ free_node(t)
+ t = nil
+ else
+ t.next = nil
+ t.prev = nil
+ end
+ end
+ return head, current, t
+end
+
+nodes.remove = remove
+
+function nodes.delete(head,current)
+ return remove(head,current,true)
+end
+
+nodes.before = insert_node_before
+nodes.after = insert_node_after
+
+-- we need to test this, as it might be fixed now
+
+function nodes.before(h,c,n)
+ if c then
+ if c == h then
+ n.next = h
+ n.prev = nil
+ h.prev = n
+ else
+ local cp = c.prev
+ n.next = c
+ n.prev = cp
+ if cp then
+ cp.next = n
+ end
+ c.prev = n
+ return h, n
+ end
+ end
+ return n, n
+end
+
+function nodes.after(h,c,n)
+ if c then
+ local cn = c.next
+ if cn then
+ n.next = cn
+ cn.prev = n
+ else
+ n.next = nil
+ end
+ c.next = n
+ n.prev = c
+ return h, n
+ end
+ return n, n
+end
+
+-- local h, c = nodes.replace(head,current,new)
+-- local c = nodes.replace(false,current,new)
+-- local c = nodes.replace(current,new)
+
+function nodes.replace(head,current,new) -- no head returned if false
+ if not new then
+ head, current, new = false, head, current
+ end
+ local prev, next = current.prev, current.next
+ if next then
+ new.next = next
+ next.prev = new
+ end
+ if prev then
+ new.prev = prev
+ prev.next = new
+ end
+ if head then
+ if head == current then
+ head = new
+ end
+ free_node(current)
+ return head, new
+ else
+ free_node(current)
+ return new
+ end
+end
+
+-- will move
+
+local function count(stack,flat)
+ local n = 0
+ while stack do
+ local id = stack.id
+ if not flat and id == hlist_code or id == vlist_code then
+ local list = stack.list
+ if list then
+ n = n + 1 + count(list) -- self counts too
+ else
+ n = n + 1
+ end
+ else
+ n = n + 1
+ end
+ stack = stack.next
+ end
+ return n
+end
+
+nodes.count = count
+
+local left, space = lpeg.P("<"), lpeg.P(" ")
+
+local reference = left * (1-left)^0 * left * space^0 * lpeg.C((1-space)^0)
+
+function nodes.reference(n)
+ return lpegmatch(reference,tostring(n))
+end
+
+if not node.next then
+
+ function node.next(n) return n and n.next end
+ function node.prev(n) return n and n.prev end
+
+end