summaryrefslogtreecommitdiff
path: root/tex
diff options
context:
space:
mode:
Diffstat (limited to 'tex')
-rw-r--r--tex/context/base/anch-pos.lua45
-rw-r--r--tex/context/base/attr-eff.lua4
-rw-r--r--tex/context/base/attr-ini.lua9
-rw-r--r--tex/context/base/back-exp.lua17
-rw-r--r--tex/context/base/back-pdf.mkiv4
-rw-r--r--tex/context/base/blob-ini.lua110
-rw-r--r--tex/context/base/blob-ini.mkiv14
-rw-r--r--tex/context/base/chem-str.lua31
-rw-r--r--tex/context/base/cldf-bas.lua9
-rw-r--r--tex/context/base/cldf-ini.lua8
-rw-r--r--tex/context/base/cont-new.mkiv2
-rw-r--r--tex/context/base/context-version.pdfbin4103 -> 4097 bytes
-rw-r--r--tex/context/base/context.mkiv2
-rw-r--r--tex/context/base/core-dat.lua28
-rw-r--r--tex/context/base/core-env.lua18
-rw-r--r--tex/context/base/core-uti.lua15
-rw-r--r--tex/context/base/data-met.lua12
-rw-r--r--tex/context/base/data-res.lua2
-rw-r--r--tex/context/base/file-ini.lua6
-rw-r--r--tex/context/base/font-chk.lua7
-rw-r--r--tex/context/base/font-col.lua7
-rw-r--r--tex/context/base/font-con.lua10
-rw-r--r--tex/context/base/font-ctx.lua67
-rw-r--r--tex/context/base/font-ext.lua2
-rw-r--r--tex/context/base/font-gds.lua104
-rw-r--r--tex/context/base/font-nod.lua13
-rw-r--r--tex/context/base/font-ota.lua5
-rw-r--r--tex/context/base/font-otn.lua4
-rw-r--r--tex/context/base/font-otx.lua3
-rw-r--r--tex/context/base/font-pre.mkiv41
-rw-r--r--tex/context/base/font-syn.lua46
-rw-r--r--tex/context/base/grph-inc.lua16
-rw-r--r--tex/context/base/grph-inc.mkiv3
-rw-r--r--tex/context/base/l-file.lua26
-rw-r--r--tex/context/base/l-io.lua1
-rw-r--r--tex/context/base/l-lpeg.lua15
-rw-r--r--tex/context/base/l-pdfview.lua133
-rw-r--r--tex/context/base/l-table.lua1
-rw-r--r--tex/context/base/lang-rep.lua198
-rw-r--r--tex/context/base/lang-wrd.lua18
-rw-r--r--tex/context/base/layo-ini.lua25
-rw-r--r--tex/context/base/lpdf-ano.lua5
-rw-r--r--tex/context/base/lpdf-fmt.lua2
-rw-r--r--tex/context/base/lpdf-nod.lua12
-rw-r--r--tex/context/base/lpdf-tag.lua11
-rw-r--r--tex/context/base/lpdf-wid.lua65
-rw-r--r--tex/context/base/luat-env.lua6
-rw-r--r--tex/context/base/luat-fio.lua20
-rw-r--r--tex/context/base/lxml-css.lua15
-rw-r--r--tex/context/base/lxml-tab.lua2
-rw-r--r--tex/context/base/m-nodechart.lua175
-rw-r--r--tex/context/base/m-nodechart.mkvi192
-rw-r--r--tex/context/base/m-r.mkii (renamed from tex/context/base/m-r.tex)2
-rw-r--r--tex/context/base/m-spreadsheet.lua2
-rw-r--r--tex/context/base/m-translate.mkiv1
-rw-r--r--tex/context/base/m-zint.mkiv33
-rw-r--r--tex/context/base/math-act.lua179
-rw-r--r--tex/context/base/math-def.mkiv27
-rw-r--r--tex/context/base/math-fbk.lua146
-rw-r--r--tex/context/base/math-ini.lua18
-rw-r--r--tex/context/base/math-map.lua18
-rw-r--r--tex/context/base/math-noa.lua147
-rw-r--r--tex/context/base/math-ren.lua4
-rw-r--r--tex/context/base/math-stc.mkvi108
-rw-r--r--tex/context/base/meta-pdf.lua6
-rw-r--r--tex/context/base/meta-pdf.mkiv2
-rw-r--r--tex/context/base/mlib-pps.lua15
-rw-r--r--tex/context/base/mult-de.mkii2
-rw-r--r--tex/context/base/mult-def.lua6
-rw-r--r--tex/context/base/mult-def.mkiv3
-rw-r--r--tex/context/base/mult-en.mkii2
-rw-r--r--tex/context/base/mult-fr.mkii2
-rw-r--r--tex/context/base/mult-it.mkii2
-rw-r--r--tex/context/base/mult-nl.mkii2
-rw-r--r--tex/context/base/mult-pe.mkii2
-rw-r--r--tex/context/base/mult-ro.mkii2
-rw-r--r--tex/context/base/mult-sys.mkiv3
-rw-r--r--tex/context/base/node-acc.lua114
-rw-r--r--tex/context/base/node-aux.lua22
-rw-r--r--tex/context/base/node-fnt.lua283
-rw-r--r--tex/context/base/node-ini.lua197
-rw-r--r--tex/context/base/node-ini.mkiv4
-rw-r--r--tex/context/base/node-inj.lua2
-rw-r--r--tex/context/base/node-ltp.lua3207
-rw-r--r--tex/context/base/node-met.lua616
-rw-r--r--tex/context/base/node-pro.lua30
-rw-r--r--tex/context/base/node-ref.lua106
-rw-r--r--tex/context/base/node-res.lua44
-rw-r--r--tex/context/base/node-rul.lua28
-rw-r--r--tex/context/base/node-ser.lua4
-rw-r--r--tex/context/base/node-shp.lua8
-rw-r--r--tex/context/base/node-tra.lua50
-rw-r--r--tex/context/base/node-typ.lua58
-rw-r--r--tex/context/base/pack-obj.lua3
-rw-r--r--tex/context/base/pack-rul.lua37
-rw-r--r--tex/context/base/pack-rul.mkiv30
-rw-r--r--tex/context/base/page-app.mkiv4
-rw-r--r--tex/context/base/page-flt.lua29
-rw-r--r--tex/context/base/page-inj.lua10
-rw-r--r--tex/context/base/page-lin.lua14
-rw-r--r--tex/context/base/page-lin.mkiv48
-rw-r--r--tex/context/base/page-mix.lua21
-rw-r--r--tex/context/base/page-mix.mkiv48
-rw-r--r--tex/context/base/page-pst.lua10
-rw-r--r--tex/context/base/page-str.lua30
-rw-r--r--tex/context/base/s-inf-03.pdfbin0 -> 1971 bytes
-rw-r--r--tex/context/base/scrn-fld.lua4
-rw-r--r--tex/context/base/scrn-hlp.lua6
-rw-r--r--tex/context/base/scrn-wid.lua10
-rw-r--r--tex/context/base/scrn-wid.mkvi32
-rw-r--r--tex/context/base/spac-ali.lua14
-rw-r--r--tex/context/base/spac-chr.lua3
-rw-r--r--tex/context/base/spac-ver.lua187
-rw-r--r--tex/context/base/status-files.pdfbin24635 -> 24573 bytes
-rw-r--r--tex/context/base/status-lua.log78
-rw-r--r--tex/context/base/status-lua.pdfbin213195 -> 0 bytes
-rw-r--r--tex/context/base/status-mkiv.lua14
-rw-r--r--tex/context/base/strc-ini.lua9
-rw-r--r--tex/context/base/strc-itm.lua14
-rw-r--r--tex/context/base/strc-lnt.mkvi9
-rw-r--r--tex/context/base/strc-lst.lua5
-rw-r--r--tex/context/base/strc-mar.lua18
-rw-r--r--tex/context/base/strc-not.lua12
-rw-r--r--tex/context/base/strc-num.lua2
-rw-r--r--tex/context/base/strc-pag.lua20
-rw-r--r--tex/context/base/strc-ref.lua27
-rw-r--r--tex/context/base/strc-reg.lua7
-rw-r--r--tex/context/base/supp-box.lua16
-rw-r--r--tex/context/base/tabl-tbl.lua8
-rw-r--r--tex/context/base/tabl-xtb.lua69
-rw-r--r--tex/context/base/task-ini.lua2
-rw-r--r--tex/context/base/trac-deb.lua25
-rw-r--r--tex/context/base/trac-inf.lua29
-rw-r--r--tex/context/base/trac-jus.lua71
-rw-r--r--tex/context/base/trac-log.lua41
-rw-r--r--tex/context/base/trac-vis.lua129
-rw-r--r--tex/context/base/typo-bld.lua70
-rw-r--r--tex/context/base/typo-brk.lua6
-rw-r--r--tex/context/base/typo-cap.lua6
-rw-r--r--tex/context/base/typo-cln.lua8
-rw-r--r--tex/context/base/typo-dig.lua4
-rw-r--r--tex/context/base/typo-dir.lua6
-rw-r--r--tex/context/base/typo-itc.lua17
-rw-r--r--tex/context/base/typo-krn.lua4
-rw-r--r--tex/context/base/typo-mar.lua42
-rw-r--r--tex/context/base/typo-par.lua21
-rw-r--r--tex/context/base/typo-rep.lua28
-rw-r--r--tex/context/base/typo-spa.lua6
-rw-r--r--tex/context/base/util-dim.lua32
-rw-r--r--tex/context/base/util-jsn.lua16
-rw-r--r--tex/context/base/util-lua.lua22
-rw-r--r--tex/context/base/util-prs.lua2
-rw-r--r--tex/context/base/util-seq.lua2
-rw-r--r--tex/context/base/util-str.lua2
-rw-r--r--tex/context/base/util-tab.lua13
-rw-r--r--tex/context/base/util-tpl.lua8
-rw-r--r--tex/context/base/x-asciimath.lua2
-rw-r--r--tex/context/fonts/ebgaramond.lfg53
-rw-r--r--tex/context/fonts/lm.lfg2
-rw-r--r--tex/context/interface/keys-cs.xml2
-rw-r--r--tex/context/interface/keys-de.xml2
-rw-r--r--tex/context/interface/keys-en.xml2
-rw-r--r--tex/context/interface/keys-fr.xml2
-rw-r--r--tex/context/interface/keys-it.xml2
-rw-r--r--tex/context/interface/keys-nl.xml2
-rw-r--r--tex/context/interface/keys-pe.xml2
-rw-r--r--tex/context/interface/keys-ro.xml2
-rw-r--r--tex/generic/context/luatex/luatex-basics-gen.lua22
-rw-r--r--tex/generic/context/luatex/luatex-basics-nod.lua31
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua730
-rw-r--r--tex/generic/context/luatex/luatex-fonts.lua3
171 files changed, 7133 insertions, 2279 deletions
diff --git a/tex/context/base/anch-pos.lua b/tex/context/base/anch-pos.lua
index 7321d7d99..9cc9fb128 100644
--- a/tex/context/base/anch-pos.lua
+++ b/tex/context/base/anch-pos.lua
@@ -26,9 +26,14 @@ local rawget = rawget
local lpegmatch = lpeg.match
local insert, remove = table.insert, table.remove
local allocate, mark = utilities.storage.allocate, utilities.storage.mark
-local texsp, texcount, texbox, texdimen, texsetcount = tex.sp, tex.count, tex.box, tex.dimen, tex.setcount
+local texsp = tex.sp
----- texsp = string.todimen -- because we cache this is much faster but no rounding
+local texgetcount = tex.getcount
+local texgetbox = tex.getbox
+local texsetcount = tex.setcount
+local texget = tex.get
+
local pdf = pdf -- h and v are variables
local setmetatableindex = table.setmetatableindex
@@ -170,7 +175,7 @@ local function setdim(name,w,h,d,extra) -- will be used when we move to sp allov
if extra == "" then extra = nil end
-- todo: sparse
tobesaved[name] = {
- p = texcount.realpageno,
+ p = texgetcount("realpageno"),
x = x,
y = y,
w = w,
@@ -217,7 +222,7 @@ local function enhance(data)
data.y = pdf.v
end
if data.p == true then
- data.p = texcount.realpageno
+ data.p = texgetcount("realpageno")
end
if data.c == true then
data.c = column
@@ -315,16 +320,16 @@ function jobpositions.b_region(tag)
local last = tobesaved[tag]
last.x = pdf.h
last.y = pdf.v
- last.p = texcount.realpageno
+ last.p = texgetcount("realpageno")
insert(regions,tag)
region = tag
end
function jobpositions.e_region(correct)
local last = tobesaved[region]
-if correct then
- last.h = last.y - pdf.v
-end
+ if correct then
+ last.h = last.y - pdf.v
+ end
last.y = pdf.v
remove(regions)
region = regions[#regions]
@@ -335,7 +340,7 @@ function jobpositions.markregionbox(n,tag,correct)
nofregions = nofregions + 1
tag = f_region(nofregions)
end
- local box = texbox[n]
+ local box = texgetbox(n)
local w = box.width
local h = box.height
local d = box.depth
@@ -378,7 +383,7 @@ local nofparagraphs = 0
function commands.parpos() -- todo: relate to localpar (so this is an intermediate variant)
nofparagraphs = nofparagraphs + 1
texsetcount("global","c_anch_positions_paragraph",nofparagraphs)
- local strutbox = texbox.strutbox
+ local strutbox = texgetbox("strutbox")
local t = {
p = true,
c = true,
@@ -387,14 +392,14 @@ function commands.parpos() -- todo: relate to localpar (so this is an intermedia
y = true,
h = strutbox.height,
d = strutbox.depth,
- hs = tex.hsize,
+ hs = texget("hsize"),
}
- local leftskip = tex.leftskip.width
- local rightskip = tex.rightskip.width
- local hangindent = tex.hangindent
- local hangafter = tex.hangafter
- local parindent = tex.parindent
- local parshape = tex.parshape
+ local leftskip = texget("leftskip").width
+ local rightskip = texget("rightskip").width
+ local hangindent = texget("hangindent")
+ local hangafter = texget("hangafter")
+ local parindent = texget("parindent")
+ local parshape = texget("parshape")
if leftskip ~= 0 then
t.ls = leftskip
end
@@ -462,7 +467,7 @@ function commands.posplus(name,w,h,d,extra)
end
function commands.posstrut(name,w,h,d)
- local strutbox = texbox.strutbox
+ local strutbox = texgetbox("strutbox")
tobesaved[name] = {
p = true,
c = column,
@@ -478,7 +483,7 @@ end
function jobpositions.getreserved(tag,n)
if tag == v_column then
- local fulltag = f_tag_three(tag,texcount.realpageno,n or 1)
+ local fulltag = f_tag_three(tag,texgetcount("realpageno"),n or 1)
local data = collected[fulltag]
if data then
return data, fulltag
@@ -486,7 +491,7 @@ function jobpositions.getreserved(tag,n)
tag = v_text
end
if tag == v_text then
- local fulltag = f_tag_two(tag,texcount.realpageno)
+ local fulltag = f_tag_two(tag,texgetcount("realpageno"))
return collected[fulltag] or false, fulltag
end
return collected[tag] or false, tag
@@ -1015,7 +1020,7 @@ function commands.doifpositionsonsamepageelse(list,page)
end
function commands.doifpositionsonthispageelse(list)
- doifelse(onsamepage(list,tostring(tex.count.realpageno)))
+ doifelse(onsamepage(list,tostring(texgetcount("realpageno"))))
end
function commands.doifelsepositionsused()
diff --git a/tex/context/base/attr-eff.lua b/tex/context/base/attr-eff.lua
index 4dce5419a..b187b64c7 100644
--- a/tex/context/base/attr-eff.lua
+++ b/tex/context/base/attr-eff.lua
@@ -13,7 +13,7 @@ local tex = tex
local states = attributes.states
local tasks = nodes.tasks
local nodeinjections = backends.nodeinjections
-local settexattribute = tex.setattribute
+local texsetattribute = tex.setattribute
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
local formatters = string.formatters
@@ -107,5 +107,5 @@ function commands.triggereffect(specification)
enable()
enabled = true
end
- settexattribute(a_effect,register(specification))
+ texsetattribute(a_effect,register(specification))
end
diff --git a/tex/context/base/attr-ini.lua b/tex/context/base/attr-ini.lua
index 206a86d79..ad4081681 100644
--- a/tex/context/base/attr-ini.lua
+++ b/tex/context/base/attr-ini.lua
@@ -20,6 +20,9 @@ local attributes = attributes
local sharedstorage = storage.shared
+local texgetcount = tex.getcount
+local texsetattribute = tex.setattribute
+
attributes.names = attributes.names or { }
attributes.numbers = attributes.numbers or { }
attributes.list = attributes.list or { }
@@ -64,7 +67,7 @@ sharedstorage.attributes_last_private = sharedstorage.attributes_last_private or
-- setmetatable(private, {
-- __index = function(t,name)
-- local number = sharedstorage.attributes_last_private
--- if number < 1023 then -- tex.count.minallocatedattribute - 1
+-- if number < 1023 then -- texgetcount("minallocatedattribute") - 1
-- number = number + 1
-- sharedstorage.attributes_last_private = number
-- end
@@ -81,7 +84,7 @@ function attributes.private(name) -- at the lua end (hidden from user)
local number = numbers[name]
if not number then
local last = sharedstorage.attributes_last_private
- if last < 1023 then -- tex.count.minallocatedattribute - 1
+ if last < 1023 then -- texgetcount("minallocatedattribute") - 1
last = last + 1
sharedstorage.attributes_last_private = last
else
@@ -155,7 +158,7 @@ function commands.restorecurrentattributes(name)
local font = t.font
if attr then
for k, v in next, attr do
- tex.attribute[k] = v
+ texsetattribute(k,v)
end
end
if font then
diff --git a/tex/context/base/back-exp.lua b/tex/context/base/back-exp.lua
index 4d219a18b..1ff1cd7a0 100644
--- a/tex/context/base/back-exp.lua
+++ b/tex/context/base/back-exp.lua
@@ -81,6 +81,8 @@ local xspaceskip_code = skipcodes.xspaceskip
local line_code = listcodes.line
+local texgetcount = tex.getcount
+
local a_characters = attributes.private('characters')
local a_exportstatus = attributes.private('exportstatus')
@@ -94,9 +96,6 @@ local a_textblock = attributes.private("textblock")
local traverse_id = node.traverse_id
local traverse_nodes = node.traverse
local slide_nodelist = node.slide
-local texattribute = tex.attribute
-local texdimen = tex.dimen
-local texcount = tex.count
local locate_node = nodes.locate
local references = structures.references
@@ -454,7 +453,7 @@ local function checkdocument(root)
end
function extras.document(result,element,detail,n,fulltag,di)
- result[#result+1] = format(" language=%q",languagenames[tex.count.mainlanguagenumber])
+ result[#result+1] = format(" language=%q",languagenames[texgetcount("mainlanguagenumber")])
if not less_state then
result[#result+1] = format(" file=%q",tex.jobname)
result[#result+1] = format(" date=%q",os.date())
@@ -2353,7 +2352,7 @@ local function stopexport(v)
images = uniqueusedimages(),
root = xhtmlfile,
files = files,
- language = languagenames[tex.count.mainlanguagenumber],
+ language = languagenames[texgetcount("mainlanguagenumber")],
title = validstring(finetuning.title) or validstring(identity.title),
subtitle = validstring(finetuning.subtitle) or validstring(identity.subtitle),
author = validstring(finetuning.author) or validstring(identity.author),
@@ -2377,13 +2376,13 @@ end
local function startexport(v)
if v and not exporting then
report_export("enabling export to xml")
--- not yet known in task-ini
+ -- not yet known in task-ini
appendaction("shipouts","normalizers", "nodes.handlers.export")
--- enableaction("shipouts","nodes.handlers.export")
+ -- enableaction("shipouts","nodes.handlers.export")
enableaction("shipouts","nodes.handlers.accessibility")
enableaction("math", "noads.handlers.tags")
---~ appendaction("finalizers","lists","builders.paragraphs.tag")
---~ enableaction("finalizers","builders.paragraphs.tag")
+ -- appendaction("finalizers","lists","builders.paragraphs.tag")
+ -- enableaction("finalizers","builders.paragraphs.tag")
luatex.registerstopactions(function() stopexport(v) end)
exporting = true
end
diff --git a/tex/context/base/back-pdf.mkiv b/tex/context/base/back-pdf.mkiv
index 1cf7a3703..3be1c4ec1 100644
--- a/tex/context/base/back-pdf.mkiv
+++ b/tex/context/base/back-pdf.mkiv
@@ -195,14 +195,14 @@
\pdfrestore
\advance\backendtransformlevel\minusone}}}
-\unexpanded\def\dostartclipping#1#2#3%
+\unexpanded\def\dostartclipping#1#2#3% we can move this to lua and only set a box here
{\PointsToBigPoints{#2}\width
\PointsToBigPoints{#3}\height
\meta_grab_clip_path{#1}\width\height{0 0 m \width\space 0 l \width \height l 0 \height l}%
\pdfliteral{q 0 w \MPclippath\space W n}}
\unexpanded\def\dostopclipping
- {\pdfliteral{Q n}}
+ {\pdfliteral{Q}}
%D The following will move to the backend \LUA\ code:
diff --git a/tex/context/base/blob-ini.lua b/tex/context/base/blob-ini.lua
index 4debaf94c..32fac7662 100644
--- a/tex/context/base/blob-ini.lua
+++ b/tex/context/base/blob-ini.lua
@@ -31,30 +31,37 @@ if not modules then modules = { } end modules ['blob-ini'] = {
local type, tostring = type, tostring
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-local report_blobs = logs.reporter("blobs")
+local report_blobs = logs.reporter("blobs")
-local t_tonodes = typesetters.tonodes
-local t_hpack = typesetters.hpack
+local flush_node_list = node.flush_list
+local hpack_node_list = node.hpack
+local vpack_node_list = node.vpack
+local write_node = node.write
-local flush_node_list = node.flush_list
-local hpack_node_list = node.hpack
-local vpack_node_list = node.vpack
-local write_node = node.write
+local typesetters = nodes.typesetters
+local tonodes = typesetters.tonodes
+local tohpack = typesetters.tohpack
+local tohpackfast = typesetters.tohpackfast
+local tovpack = typesetters.tovpack
+local tovpackfast = typesetters.tovpackfast
blobs = blobs or { }
-local newline = lpegpatterns.newline
-local space = lpegpatterns.spacer
-local spacing = newline * space^0
-local content = (space^1)/" " + (1-spacing)
+-- provide copies here (nicer for manuals)
-local ctxtextcapture = lpeg.Ct ( ( -- needs checking (see elsewhere)
- space^0 * (
- newline^2 * space^0 * lpeg.Cc("")
- + newline * space^0 * lpeg.Cc(" ")
- + lpeg.Cs(content^1)
- )
-)^0)
+blobs.tonodes = tonodes
+blobs.tohpack = tohpack
+blobs.tohpackfast = tohpackfast
+blobs.tovpack = tovpack
+blobs.tovpackfast = tovpackfast
+
+-- end of helpers
+
+local newline = lpeg.patterns.newline
+local space = lpeg.patterns.spacer
+local newpar = (space^0*newline*space^0)^2
+
+local ctxtextcapture = lpeg.Ct ( ( space^0 * ( newpar + lpeg.Cs(((space^1/" " + 1)-newpar)^1) ) )^0)
function blobs.new()
return {
@@ -81,33 +88,12 @@ function blobs.append(t,str) -- compare concat and link
str = tostring(str)
typ = "string"
end
- local list = t.list
if typ == "string" then
local pars = lpegmatch(ctxtextcapture,str)
- local noflist = #list
+ local list = t.list
for p=1,#pars do
- local str = pars[p]
- if #str == 0 then
- noflist = noflist + 1
- list[noflist] = { head = nil, tail = nil }
- else
- local l = list[noflist]
- if not l then
- l = { head = nil, tail = nil }
- noflist = noflist + 1
- list[noflist] = l
- end
- local head, tail = t_tonodes(str,nil,nil)
- if head then
- if l.head then
- l.tail.next = head
- head.prev = l.tail
- l.tail = tail
- else
- l.head, l.tail = head, tail
- end
- end
- end
+ local head, tail = tonodes(pars[p],nil,nil)
+ list[#list+1] = { head = head, tail = tail }
end
end
end
@@ -121,7 +107,7 @@ function blobs.pack(t,how)
end
if how == "vertical" then
-- we need to prepend a local par node
- -- list[i].pack = node.vpack(list[i].head,"exactly")
+ -- list[i].pack = vpack_node_list(list[i].head,"exactly")
report_blobs("vpack not yet supported")
else
list[i].pack = hpack_node_list(list[i].head,"exactly")
@@ -176,12 +162,44 @@ end
-- for the moment here:
-function commands.widthofstring(str)
- local l = t_hpack(str)
- context(number.todimen(l.width))
+local function strwd(str)
+ local l = tohpack(str)
+ local w = l.width
flush_node_list(l)
+ return w
end
+local function strht(str)
+ local l = tohpack(str)
+ local h = l.height
+ flush_node_list(l)
+ return h
+end
+
+local function strdp(str)
+ local l = tohpack(str)
+ local d = l.depth
+ flush_node_list(l)
+ return d
+end
+
+local function strhd(str)
+ local l = tohpack(str)
+ local s = l.height + l.depth
+ flush_node_list(l)
+ return s
+end
+
+blobs.strwd = strwd
+blobs.strht = strht
+blobs.strdp = strdp
+blobs.strhd = strhd
+
+function commands.strwd(str) context(strwd(str)) end
+function commands.strht(str) context(strht(str)) end
+function commands.strdp(str) context(strdp(str)) end
+function commands.strhd(str) context(strhd(str)) end
+
-- less efficient:
--
-- function commands.widthof(str)
diff --git a/tex/context/base/blob-ini.mkiv b/tex/context/base/blob-ini.mkiv
index 4fdb9e4b6..1dfb766f4 100644
--- a/tex/context/base/blob-ini.mkiv
+++ b/tex/context/base/blob-ini.mkiv
@@ -27,7 +27,19 @@
% this one takes simple (utf) strings
-\def\widthofstring#1{\ctxcommand{widthofstring(\!!bs#1\!!es)}}
+\def\wdofstring#1{\dimexpr\ctxcommand{strwd(\!!bs#1\!!es)}\scaledpoint\relax}
+\def\htofstring#1{\dimexpr\ctxcommand{strht(\!!bs#1\!!es)}\scaledpoint\relax}
+\def\dpofstring#1{\dimexpr\ctxcommand{strdp(\!!bs#1\!!es)}\scaledpoint\relax}
+\def\hdofstring#1{\dimexpr\ctxcommand{strhd(\!!bs#1\!!es)}\scaledpoint\relax}
+
+\def\widthofstring {\the\wdofstring}
+\def\heightofstring {\the\htofstring}
+\def\depthofstring {\the\dpofstring}
+\def\heightanddepthofstring{\the\hdofstring}
+
+\let\htdpofstring \hdofstring
+
+\let\hd\htdp % if yes then move this
% this one takes anything that can be typeset
diff --git a/tex/context/base/chem-str.lua b/tex/context/base/chem-str.lua
index 8c1bf38fc..347363345 100644
--- a/tex/context/base/chem-str.lua
+++ b/tex/context/base/chem-str.lua
@@ -37,25 +37,24 @@ local concat, insert, remove, unique, sorted = table.concat, table.insert, table
local processor_tostring = typesetters and typesetters.processors.tostring
local settings_to_array = utilities.parsers.settings_to_array
local settings_to_array_with_repeat = utilities.parsers.settings_to_array_with_repeat
-local formatters = string.formatters
local lpegmatch = lpeg.match
local P, R, S, C, Cs, Ct, Cc, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cmt
-local variables = interfaces and interfaces.variables
-local commands = commands
-local context = context
-local formatters = string.formatters
-local texcount = tex.count
-
-local v_default = variables.default
-local v_small = variables.small
-local v_medium = variables.medium
-local v_big = variables.big
-local v_normal = variables.normal
-local v_fit = variables.fit
-local v_on = variables.on
-local v_none = variables.none
+local variables = interfaces and interfaces.variables
+local commands = commands
+local context = context
+local formatters = string.formatters
+local texgetcount = tex.getcount
+
+local v_default = variables.default
+local v_small = variables.small
+local v_medium = variables.medium
+local v_big = variables.big
+local v_normal = variables.normal
+local v_fit = variables.fit
+local v_on = variables.on
+local v_none = variables.none
local mpnamedcolor = attributes.colors.mpnamedcolor
local topoints = number.topoints
@@ -717,7 +716,7 @@ function chemistry.start(settings)
width, left, right, sp_width = calculated(width, left, right,factor,unit,scale)
height, bottom, top, sp_height = calculated(height,bottom,top, factor,unit,scale)
--
- if width ~= "true" and height ~= "true" and texcount["@@trialtypesetting"] ~= 0 then
+ if width ~= "true" and height ~= "true" and texgetcount("@@trialtypesetting") ~= 0 then
if trace_structure then
report_chemistry("skipping trial run")
end
diff --git a/tex/context/base/cldf-bas.lua b/tex/context/base/cldf-bas.lua
index 6adeb2272..b982fc364 100644
--- a/tex/context/base/cldf-bas.lua
+++ b/tex/context/base/cldf-bas.lua
@@ -38,7 +38,8 @@ local new_rule = nodepool.rule
local new_glyph = nodepool.glyph
local current_font = font.current
-local texcount = tex.count
+local texgetcount = tex.getcount
+local texsetcount = tex.setcount
function context.char(k) -- used as escape too, so don't change to utf
if type(k) == "table" then
@@ -163,9 +164,9 @@ context.endhbox = context.egroup
local function allocate(name,what,cmd)
local a = format("c_syst_last_allocated_%s",what)
- local n = texcount[a] + 1
- if n <= texcount.c_syst_max_allocated_register then
- texcount[a] = n
+ local n = texgetcount(a) + 1
+ if n <= texgetcount("c_syst_max_allocated_register") then
+ texsetcount(a,n)
end
context("\\global\\expandafter\\%sdef\\csname %s\\endcsname %s\\relax",cmd or what,name,n)
return n
diff --git a/tex/context/base/cldf-ini.lua b/tex/context/base/cldf-ini.lua
index 2272c05ea..44bf522d3 100644
--- a/tex/context/base/cldf-ini.lua
+++ b/tex/context/base/cldf-ini.lua
@@ -38,7 +38,7 @@ local texsprint = tex.sprint
local textprint = tex.tprint
local texprint = tex.print
local texwrite = tex.write
-local texcount = tex.count
+local texgetcount = tex.getcount
local isnode = node.is_node -- after 0.65 just node.type
local writenode = node.write
@@ -86,13 +86,13 @@ local function _flush_f_(n)
else
local tn = type(sn)
if tn == "function" then
- if not sn() and texcount["@@trialtypesetting"] == 0 then -- @@trialtypesetting is private!
+ if not sn() and texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private!
_stack_f_[n] = nil
else
-- keep, beware, that way the stack can grow
end
else
- if texcount["@@trialtypesetting"] == 0 then -- @@trialtypesetting is private!
+ if texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private!
writenode(sn)
_stack_f_[n] = nil
else
@@ -107,7 +107,7 @@ local function _flush_n_(n)
local sn = _stack_n_[n]
if not sn then
report_cld("data with id %a cannot be found on stack",n)
- elseif texcount["@@trialtypesetting"] == 0 then -- @@trialtypesetting is private!
+ elseif texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private!
writenode(sn)
_stack_n_[n] = nil
else
diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index 0e3ff6cf6..283e924cc 100644
--- a/tex/context/base/cont-new.mkiv
+++ b/tex/context/base/cont-new.mkiv
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2013.06.10 22:51}
+\newcontextversion{2013.07.12 19:10}
%D This file is loaded at runtime, thereby providing an excellent place for
%D hacks, patches, extensions and new features.
diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf
index f08b763d1..3bf5f1c53 100644
--- a/tex/context/base/context-version.pdf
+++ b/tex/context/base/context-version.pdf
Binary files differ
diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv
index 2d018984d..e6cc65a9d 100644
--- a/tex/context/base/context.mkiv
+++ b/tex/context/base/context.mkiv
@@ -25,7 +25,7 @@
%D up and the dependencies are more consistent.
\edef\contextformat {\jobname}
-\edef\contextversion{2013.06.10 22:51}
+\edef\contextversion{2013.07.12 19:10}
\edef\contextkind {beta}
%D For those who want to use this:
diff --git a/tex/context/base/core-dat.lua b/tex/context/base/core-dat.lua
index 826d3a675..242d362d0 100644
--- a/tex/context/base/core-dat.lua
+++ b/tex/context/base/core-dat.lua
@@ -21,13 +21,17 @@ local trace_pagestates = false trackers.register("job.pagestates", function(v)
local report_dataset = logs.reporter("dataset")
local report_pagestate = logs.reporter("pagestate")
-local allocate = utilities.storage.allocate
+local allocate = utilities.storage.allocate
local settings_to_hash = utilities.parsers.settings_to_hash
-local texcount = tex.count
-local formatters = string.formatters
-local v_yes = interfaces.variables.yes
-local new_latelua = nodes.pool.latelua
+local texgetcount = tex.getcount
+local texsetcount = tex.setcount
+
+local formatters = string.formatters
+
+local v_yes = interfaces.variables.yes
+
+local new_latelua = nodes.pool.latelua
local collected = allocate()
local tobesaved = allocate()
@@ -86,7 +90,7 @@ local function setdata(settings)
set.index = index
data.index = index
data.order = index
- data.realpage = texcount.realpageno
+ data.realpage = texgetcount("realpageno")
if trace_datasets then
report_dataset("action %a, name %a, tag %a, index %a","assign delayed",name,tag,index)
end
@@ -101,7 +105,7 @@ datasets.setdata = setdata
function datasets.extend(name,tag)
local set = sets[name]
local order = set.order + 1
- local realpage = texcount.realpageno
+ local realpage = texgetcount("realpageno")
set.order = order
local t = tobesaved[name][tag]
t.realpage = realpage
@@ -207,7 +211,7 @@ local function setstate(settings)
else
tag = tonumber(tag) or tag -- autonumber saves keys
end
- local realpage = texcount.realpageno
+ local realpage = texgetcount("realpageno")
local data = realpage
list[tag] = data
if trace_pagestates then
@@ -219,7 +223,7 @@ end
pagestates.setstate = setstate
function pagestates.extend(name,tag)
- local realpage = texcount.realpageno
+ local realpage = texgetcount("realpageno")
if trace_pagestates then
report_pagestate("action %a, name %a, tag %a, preset %a","synchronize",name,tag,realpage)
end
@@ -261,9 +265,5 @@ end
function commands.setpagestaterealpageno(name,tag)
local t = collected[name]
t = t and (t[tag] or t[tonumber(tag)])
- if t then
- texcount.realpagestateno = t
- else
- texcount.realpagestateno = texcount.realpageno
- end
+ texsetcount("realpagestateno",t or texgetcount("realpageno"))
end
diff --git a/tex/context/base/core-env.lua b/tex/context/base/core-env.lua
index de977d0bb..a4d1fdd92 100644
--- a/tex/context/base/core-env.lua
+++ b/tex/context/base/core-env.lua
@@ -15,7 +15,7 @@ local P, C, S, Cc, lpegmatch, patterns = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc, lpeg.m
local csname_id = token.csname_id
local create = token.create
-local texcount = tex.count
+local texgetcount = tex.getcount
local texsetcount = tex.setcount
local allocate = utilities.storage.allocate
@@ -44,8 +44,8 @@ setmetatableindex(tex.modes, function(t,k)
if csname_id(n) == undefined then
return false
else
- modes[k] = function() return texcount[n] >= 1 end
- return texcount[n] >= 1
+ modes[k] = function() return texgetcount(n) >= 1 end
+ return texgetcount(n) >= 1
end
end
end)
@@ -59,18 +59,18 @@ setmetatableindex(tex.systemmodes, function(t,k)
if csname_id(n) == undefined then
return false
else
- systemmodes[k] = function() return texcount[n] >= 1 end
- return texcount[n] >= 1
+ systemmodes[k] = function() return texgetcount(n) >= 1 end
+ return texgetcount(n) >= 1
end
end
end)
setmetatableindex(tex.constants, function(t,k)
- return csname_id(k) ~= undefined and texcount[k] or 0
+ return csname_id(k) ~= undefined and texgetcount(k) or 0
end)
setmetatableindex(tex.conditionals, function(t,k) -- 0 == true
- return csname_id(k) ~= undefined and texcount[k] == 0
+ return csname_id(k) ~= undefined and texgetcount(k) == 0
end)
setmetatableindex(tex.ifs, function(t,k)
@@ -86,7 +86,7 @@ end)
-- if glob then
-- texsetcount("global",name,0)
-- else
--- texcount[name] = 0
+-- texsetcount(name,0)
-- end
-- end
--
@@ -94,7 +94,7 @@ end)
-- if glob then
-- texsetcount("global",name,1)
-- else
--- texcount[name] = 1
+-- texsetcount(name,1)
-- end
-- end
diff --git a/tex/context/base/core-uti.lua b/tex/context/base/core-uti.lua
index 53ff891e2..4e3c839bd 100644
--- a/tex/context/base/core-uti.lua
+++ b/tex/context/base/core-uti.lua
@@ -20,7 +20,6 @@ saves much runtime but at the cost of more memory usage.</p>
local format, match = string.format, string.match
local next, type, tostring = next, type, tostring
local concat = table.concat
-local texcount = tex.count
local definetable = utilities.tables.definetable
local accesstable = utilities.tables.accesstable
@@ -30,6 +29,8 @@ local packers = utilities.packers
local allocate = utilities.storage.allocate
local mark = utilities.storage.mark
+local texgetcount = tex.getcount
+
local report_passes = logs.reporter("job","passes")
job = job or { }
@@ -149,7 +150,7 @@ function job.save(filename) -- we could return a table but it can get pretty lar
local f = io.open(filename,'w')
if f then
f:write("local utilitydata = { }\n\n")
- f:write(serialize(comment,"utilitydata.comment",true,true),"\n\n")
+ f:write(serialize(comment,"utilitydata.comment",true),"\n\n")
for l=1,#savelist do
local list = savelist[l]
local target = format("utilitydata.%s",list[1])
@@ -162,11 +163,11 @@ function job.save(filename) -- we could return a table but it can get pretty lar
packers.pack(data,jobpacker,true)
end
local definer, name = definetable(target,true,true) -- no first and no last
- f:write(definer,"\n\n",serialize(data,name,true,true),"\n\n")
+ f:write(definer,"\n\n",serialize(data,name,true),"\n\n")
end
if job.pack then
packers.strip(jobpacker)
- f:write(serialize(jobpacker,"utilitydata.job.packed",true,true),"\n\n")
+ f:write(serialize(jobpacker,"utilitydata.job.packed",true),"\n\n")
end
f:write("return utilitydata")
f:close()
@@ -264,7 +265,7 @@ end)
statistics.register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
- local pages = texcount['realpageno'] - 1
+ local pages = texgetcount('realpageno') - 1
if pages > 1 then
return format("direct: %s, indirect: %s, total: %s (%i per page)", total-indirect, indirect, total, total/pages)
else
@@ -280,8 +281,8 @@ end)
function statistics.formatruntime(runtime)
if not environment.initex then -- else error when testing as not counters yet
- local shipped = texcount['nofshipouts']
- local pages = texcount['realpageno']
+ local shipped = texgetcount('nofshipouts')
+ local pages = texgetcount('realpageno')
if pages > shipped then
pages = shipped
end
diff --git a/tex/context/base/data-met.lua b/tex/context/base/data-met.lua
index 96da70bfd..ee9de3fd9 100644
--- a/tex/context/base/data-met.lua
+++ b/tex/context/base/data-met.lua
@@ -36,7 +36,7 @@ local function splitmethod(filename) -- todo: filetype in specification
end
filename = file.collapsepath(filename,".") -- hm, we should keep ./ in some cases
--- filename = gsub(filename,"^%./",getcurrentdir().."/") -- we will merge dir.expandname and collapse some day
+ -- filename = gsub(filename,"^%./",getcurrentdir().."/") -- we will merge dir.expandname and collapse some day
if not find(filename,"://") then
return { scheme = "file", path = filename, original = filename, filename = filename }
@@ -49,6 +49,16 @@ local function splitmethod(filename) -- todo: filetype in specification
end
end
+-- local function splitmethod(filename) -- todo: filetype in specification
+-- if not filename then
+-- return { scheme = "unknown", original = filename }
+-- end
+-- if type(filename) == "table" then
+-- return filename -- already split
+-- end
+-- return url.hashed(filename)
+-- end
+
resolvers.splitmethod = splitmethod -- bad name but ok
-- the second argument is always analyzed (saves time later on) and the original
diff --git a/tex/context/base/data-res.lua b/tex/context/base/data-res.lua
index 532b6261f..f1ddb62aa 100644
--- a/tex/context/base/data-res.lua
+++ b/tex/context/base/data-res.lua
@@ -1303,7 +1303,7 @@ local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other
end
-- we could have a loop over the 6 functions but then we'd have to
--- always analyze
+-- always analyze .. todo: use url split
collect_instance_files = function(filename,askedformat,allresults) -- uses nested
askedformat = askedformat or ""
diff --git a/tex/context/base/file-ini.lua b/tex/context/base/file-ini.lua
index 1872ed3d3..2bc742a1f 100644
--- a/tex/context/base/file-ini.lua
+++ b/tex/context/base/file-ini.lua
@@ -13,13 +13,13 @@ if not modules then modules = { } end modules ['file-ini'] = {
resolvers.jobs = resolvers.jobs or { }
-local texcount = tex.count
-local setvalue = context.setvalue
+local texsetcount = tex.setcount
+local setvalue = context.setvalue
function commands.splitfilename(fullname)
local t = file.nametotable(fullname)
local path = t.path
- texcount.splitoffkind = (path == "" and 0) or (path == '.' and 1) or 2
+ texsetcount("splitoffkind",(path == "" and 0) or (path == '.' and 1) or 2)
setvalue("splitofffull",fullname)
setvalue("splitoffpath",path)
setvalue("splitoffname",t.name)
diff --git a/tex/context/base/font-chk.lua b/tex/context/base/font-chk.lua
index 467afae9b..6dc1667bb 100644
--- a/tex/context/base/font-chk.lua
+++ b/tex/context/base/font-chk.lua
@@ -68,7 +68,7 @@ local function onetimemessage(font,char,message) -- char == false returns table
if char == false then
return table.sortedkeys(category)
elseif not category[char] then
- report_fonts("char %U in font %a with id %a: %s",char,tfmdata.properties.fullname,font,message)
+ report_fonts("char %C in font %a with id %a: %s",char,tfmdata.properties.fullname,font,message)
category[char] = true
end
end
@@ -210,6 +210,7 @@ function checkers.missing(head)
local char = n.char
if font ~= lastfont then
characters = fontcharacters[font]
+ lastfont = font
end
if not characters[char] and is_character[chardata[char].category] then
if action == "remove" then
@@ -363,7 +364,7 @@ end)
-- for the moment here
-function helpers.expandglyph(characters,index,done)
+local function expandglyph(characters,index,done)
done = done or { }
if not done[index] then
local data = characters[index]
@@ -390,3 +391,5 @@ function helpers.expandglyph(characters,index,done)
end
end
end
+
+helpers.expandglyph = expandglyph
diff --git a/tex/context/base/font-col.lua b/tex/context/base/font-col.lua
index 20c99c9b4..d461d60b4 100644
--- a/tex/context/base/font-col.lua
+++ b/tex/context/base/font-col.lua
@@ -15,9 +15,9 @@ local file, lpeg, table, string = file, lpeg, table, string
local type, next, toboolean = type, next, toboolean
local gmatch = string.gmatch
local fastcopy = table.fastcopy
------ P, Cc, lpegmatch = lpeg.P, lpeg.Cc, lpeg.match
-local traverse_id = node.traverse_id
+local traverse_id = nodes.traverse_id
+
local settings_to_hash = utilities.parsers.settings_to_hash
local trace_collecting = false trackers.register("fonts.collecting", function(v) trace_collecting = v end)
@@ -215,7 +215,8 @@ function collections.process(head) -- this way we keep feature processing
if trace_collecting then
report_fonts("remapping character %a in font %a to character %a in font %a",n.char,n.font,newchar,newid)
end
- n.font, n.char = newid, newchar
+ n.font = newid
+ n.char = newchar
else
if trace_collecting then
report_fonts("remapping font %a to %a for character %a",n.font,id,n.char)
diff --git a/tex/context/base/font-con.lua b/tex/context/base/font-con.lua
index 790d4877a..6a466a027 100644
--- a/tex/context/base/font-con.lua
+++ b/tex/context/base/font-con.lua
@@ -1278,7 +1278,8 @@ function constructors.collectprocessors(what,tfmdata,features,trace,report)
local whathandler = handlers[what]
local whatfeatures = whathandler.features
local whatprocessors = whatfeatures.processors
- local processors = whatprocessors[properties.mode]
+ local mode = properties.mode
+ local processors = whatprocessors[mode]
if processors then
for i=1,#processors do
local step = processors[i]
@@ -1295,7 +1296,7 @@ function constructors.collectprocessors(what,tfmdata,features,trace,report)
end
end
elseif trace then
- report("no feature processors for mode %a for font %a",mode,tfmdata.properties.fullname)
+ report("no feature processors for mode %a for font %a",mode,properties.fullname)
end
end
return processes
@@ -1309,7 +1310,8 @@ function constructors.applymanipulators(what,tfmdata,features,trace,report)
local whathandler = handlers[what]
local whatfeatures = whathandler.features
local whatmanipulators = whatfeatures.manipulators
- local manipulators = whatmanipulators[properties.mode]
+ local mode = properties.mode
+ local manipulators = whatmanipulators[mode]
if manipulators then
for i=1,#manipulators do
local step = manipulators[i]
@@ -1318,7 +1320,7 @@ function constructors.applymanipulators(what,tfmdata,features,trace,report)
if value then
local action = step.action
if trace then
- report("applying feature manipulator %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname)
+ report("applying feature manipulator %a for mode %a for font %a",feature,mode,properties.fullname)
end
if action then
action(tfmdata,feature,value)
diff --git a/tex/context/base/font-ctx.lua b/tex/context/base/font-ctx.lua
index 31de74578..7388a49ca 100644
--- a/tex/context/base/font-ctx.lua
+++ b/tex/context/base/font-ctx.lua
@@ -14,7 +14,6 @@ if not modules then modules = { } end modules ['font-ctx'] = {
local context, commands = context, commands
-local texcount, texsetcount = tex.count, tex.setcount
local format, gmatch, match, find, lower, gsub, byte = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub, string.byte
local concat, serialize, sort, fastcopy, mergedtable = table.concat, table.serialize, table.sort, table.fastcopy, table.merged
local sortedhash, sortedkeys, sequenced = table.sortedhash, table.sortedkeys, table.sequenced
@@ -56,8 +55,15 @@ local fontgoodies = fonts.goodies
local helpers = fonts.helpers
local hashes = fonts.hashes
local currentfont = font.current
-local texattribute = tex.attribute
-local texdimen = tex.dimen
+
+local texgetattribute = tex.getattribute
+local texsetattribute = tex.setattribute
+local texgetdimen = tex.getdimen
+local texsetcount = tex.setcount
+local texget = tex.get
+
+local texdefinefont = tex.definefont
+local texsp = tex.sp
local fontdata = hashes.identifiers
local characters = hashes.chardata
@@ -659,14 +665,14 @@ end
-- local withcache = { } -- concat might be less efficient than nested tables
--
-- local function withset(name,what)
--- local zero = texattribute[0]
+-- local zero = texgetattribute(0)
-- local hash = zero .. "+" .. name .. "*" .. what
-- local done = withcache[hash]
-- if not done then
-- done = mergecontext(zero,name,what)
-- withcache[hash] = done
-- end
--- texattribute[0] = done
+-- texsetattribute(0,done)
-- end
--
-- local function withfnt(name,what,font)
@@ -677,7 +683,7 @@ end
-- done = registercontext(font,name,what)
-- withcache[hash] = done
-- end
--- texattribute[0] = done
+-- texsetattribute(0,done)
-- end
function specifiers.showcontext(name)
@@ -848,18 +854,18 @@ function commands.definefont_one(str)
if size and size ~= "" then
local mode, size = lpegmatch(sizepattern,size)
if size and mode then
- texcount.scaledfontmode = mode
+ texsetcount("scaledfontmode",mode)
setsomefontsize(size)
else
- texcount.scaledfontmode = 0
+ texsetcount("scaledfontmode",0)
setemptyfontsize()
end
elseif true then
-- so we don't need to check in tex
- texcount.scaledfontmode = 2
+ texsetcount("scaledfontmode",2)
setemptyfontsize()
else
- texcount.scaledfontmode = 0
+ texsetcount("scaledfontmode",0)
setemptyfontsize()
end
specification = definers.makespecification(str,lookup,name,sub,method,detail,size)
@@ -983,7 +989,7 @@ function commands.definefont_two(global,cs,str,size,inheritancemode,classfeature
name,tfmdata,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,classgoodies,goodies,classdesignsize,fontdesignsize)
end
csnames[tfmdata] = specification.cs
- tex.definefont(global,cs,tfmdata)
+ texdefinefont(global,cs,tfmdata)
-- resolved (when designsize is used):
setsomefontsize((fontdata[tfmdata].parameters.size or 0) .. "sp")
lastfontid = tfmdata
@@ -1001,7 +1007,7 @@ function commands.definefont_two(global,cs,str,size,inheritancemode,classfeature
csnames[id] = specification.cs
tfmdata.properties.id = id
definers.register(tfmdata,id) -- to be sure, normally already done
- tex.definefont(global,cs,id)
+ texdefinefont(global,cs,id)
constructors.cleanuptable(tfmdata)
constructors.finalize(tfmdata)
if trace_defining then
@@ -1050,7 +1056,7 @@ function definers.define(specification)
specification.detail = specification.detail or (detail ~= "" and detail) or ""
--
if type(specification.size) == "string" then
- specification.size = tex.sp(specification.size) or 655260
+ specification.size = texsp(specification.size) or 655260
end
--
specification.specification = "" -- not used
@@ -1074,7 +1080,7 @@ function definers.define(specification)
return -1, nil
elseif type(tfmdata) == "number" then
if cs then
- tex.definefont(specification.global,cs,tfmdata)
+ texdefinefont(specification.global,cs,tfmdata)
csnames[tfmdata] = cs
end
return tfmdata, fontdata[tfmdata]
@@ -1083,7 +1089,7 @@ function definers.define(specification)
tfmdata.properties.id = id
definers.register(tfmdata,id)
if cs then
- tex.definefont(specification.global,cs,id)
+ texdefinefont(specification.global,cs,id)
csnames[id] = cs
end
constructors.cleanuptable(tfmdata)
@@ -1103,7 +1109,7 @@ local n = 0
function definers.internal(specification,cs)
specification = specification or { }
local name = specification.name
- local size = specification.size and number.todimen(specification.size) or texdimen.bodyfontsize
+ local size = specification.size and number.todimen(specification.size) or texgetdimen("bodyfontsize")
local number = tonumber(specification.number)
local id = nil
if number then
@@ -1423,11 +1429,11 @@ function commands.featureattribute(tag)
end
function commands.setfontfeature(tag)
- texattribute[0] = contextnumber(tag)
+ texsetattribute(0,contextnumber(tag))
end
function commands.resetfontfeature()
- texattribute[0] = 0
+ texsetattribute(0,0)
end
-- function commands.addfs(tag) withset(tag, 1) end
@@ -1578,19 +1584,24 @@ end
local quads = hashes.quads
local xheights = hashes.xheights
-setmetatableindex(number.dimenfactors, function(t,k)
+setmetatableindex(dimenfactors, function(t,k)
if k == "ex" then
- return xheigths[currentfont()]
+ return 1/xheights[currentfont()]
elseif k == "em" then
- return quads[currentfont()]
- elseif k == "%" then
- return dimen.hsize/100
+ return 1/quads[currentfont()]
+ elseif k == "pct" or k == "%" then
+ return 1/(texget("hsize")/100)
else
-- error("wrong dimension: " .. (s or "?")) -- better a message
return false
end
end)
+dimenfactors.ex = nil
+dimenfactors.em = nil
+dimenfactors["%"] = nil
+dimenfactors.pct = nil
+
--[[ldx--
<p>Before a font is passed to <l n='tex'/> we scale it. Here we also need
to scale virtual characters.</p>
@@ -1668,17 +1679,17 @@ local hows = {
function commands.feature(how,parent,name,font) -- 0/1 test temporary for testing
if not how or how == 0 then
- if trace_features and texattribute[0] ~= 0 then
+ if trace_features and texgetattribute(0) ~= 0 then
report_cummulative("font %!font:name!, reset",fontdata[font or true])
end
- texattribute[0] = 0
+ texsetattribute(0,0)
elseif how == true or how == 1 then
local hash = "feature > " .. parent
local done = cache[hash]
if trace_features and done then
report_cummulative("font %!font:name!, revive %a : %!font:features!",fontdata[font or true],parent,setups[numbers[done]])
end
- texattribute[0] = done or 0
+ texsetattribute(0,done or 0)
else
local full = parent .. how .. name
local hash = "feature > " .. full
@@ -1696,7 +1707,7 @@ function commands.feature(how,parent,name,font) -- 0/1 test temporary for testin
report_cummulative("font %!font:name!, %s %a : %!font:features!",fontdata[font or true],hows[how],full,setups[numbers[done]])
end
end
- texattribute[0] = done
+ texsetattribute(0,done)
end
end
@@ -1823,7 +1834,7 @@ local function analyzeprocessor(head,font,attr)
end
registerotffeature { -- adapts
- name = "analyze",
+ name = "analyze",
processors = {
node = analyzeprocessor,
}
diff --git a/tex/context/base/font-ext.lua b/tex/context/base/font-ext.lua
index 89d5927d4..3d78b0a3c 100644
--- a/tex/context/base/font-ext.lua
+++ b/tex/context/base/font-ext.lua
@@ -469,7 +469,7 @@ end
registerotffeature {
name = "protrusion",
- description = "shift characters into the left and or right margin",
+ description = "l/r margin character protrusion",
initializers = {
base = initializeprotrusion,
node = initializeprotrusion,
diff --git a/tex/context/base/font-gds.lua b/tex/context/base/font-gds.lua
index 6332f40b0..1b2ac0009 100644
--- a/tex/context/base/font-gds.lua
+++ b/tex/context/base/font-gds.lua
@@ -18,6 +18,7 @@ local trace_goodies = false trackers.register("fonts.goodies", function(v)
local report_goodies = logs.reporter("fonts","goodies")
local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
local otf = fonts.handlers.otf
local afm = fonts.handlers.afm
@@ -43,6 +44,10 @@ local addotffeature = otf.enhancers.addfeature
local findfile = resolvers.findfile
+local glyph_code = nodes.nodecodes.glyph
+
+local traverse_id = nodes.traverse_id
+
function fontgoodies.report(what,trace,goodies)
if trace_goodies or trace then
local whatever = goodies[what]
@@ -298,27 +303,104 @@ local function setcolorscheme(tfmdata,scheme)
tfmdata.properties.colorscheme = false
end
-local fontdata = fonts.hashes.identifiers
-local setnodecolor = nodes.tracers.colors.set
-local traverse_id = node.traverse_id
-local a_colorscheme = attributes.private('colorscheme')
-local glyph = node.id("glyph")
+local fontproperties = fonts.hashes.properties
+
+local a_colorscheme = attributes.private('colorscheme')
+local setnodecolor = nodes.tracers.colors.set
+
+-- function colorschemes.coloring(head)
+-- local lastfont, lastscheme
+-- local done = false
+-- for n in traverse_id(glyph_code,head) do
+-- local a = n[a_colorscheme]
+-- if a then
+-- local f = n.font
+-- if f ~= lastfont then
+-- lastscheme = fontproperties[f].colorscheme
+-- lastfont = f
+-- end
+-- if lastscheme then
+-- local sc = lastscheme[n.char]
+-- if sc then
+-- done = true
+-- setnodecolor(n,"colorscheme:"..a..":"..sc) -- slow
+-- end
+-- end
+-- end
+-- end
+-- return head, done
+-- end
+
+-- seldom used, mostly in manuals, so non critical .. anyhow, somewhat faster:
+
+-- function colorschemes.coloring(head)
+-- local lastfont = nil
+-- local lastattr = nil
+-- local lastscheme = nil
+-- local lastprefix = nil
+-- local done = nil
+-- for n in traverse_id(glyph_code,head) do
+-- local a = n[a_colorscheme]
+-- if a then
+-- if a ~= lastattr then
+-- lastattr = a
+-- lastprefix = "colorscheme:" .. a .. ":"
+-- end
+-- local f = n.font
+-- if f ~= lastfont then
+-- lastfont = f
+-- lastscheme = fontproperties[f].colorscheme
+-- end
+-- if lastscheme then
+-- local sc = lastscheme[n.char]
+-- if sc then
+-- setnodecolor(n,lastprefix .. sc) -- slow
+-- done = true
+-- end
+-- end
+-- end
+-- end
+-- return head, done
+-- end
+
+-- ok, in case we have hundreds of pages colored:
+
+local cache = { } -- this could be a weak table
+
+setmetatableindex(cache,function(t,a)
+ local v = { }
+ setmetatableindex(v,function(t,c)
+ local v = "colorscheme:" .. a .. ":" .. c
+ t[c] = v
+ return c
+ end)
+ t[a]= v
+ return v
+end)
function colorschemes.coloring(head)
- local lastfont, lastscheme
- local done = false
- for n in traverse_id(glyph,head) do
+ local lastfont = nil
+ local lastattr = nil
+ local lastcache = nil
+ local lastscheme = nil
+ local done = nil
+ for n in traverse_id(glyph_code,head) do
local a = n[a_colorscheme]
if a then
local f = n.font
if f ~= lastfont then
- lastscheme, lastfont = fontdata[f].properties.colorscheme, f
+ lastfont = f
+ lastscheme = fontproperties[f].colorscheme
+ end
+ if a ~= lastattr then
+ lastattr = a
+ lastcache = cache[a]
end
if lastscheme then
local sc = lastscheme[n.char]
if sc then
+ setnodecolor(n,lastcache[sc]) -- we could inline this one
done = true
- setnodecolor(n,"colorscheme:"..a..":"..sc) -- slow
end
end
end
@@ -691,7 +773,7 @@ function fontgoodies.designsizes.register(name,size,specification)
d.default = specification
else
if type(size) == "string" then
- size = texsp(size)
+ size = texsp(size) -- hm
end
local ranges = d.ranges
ranges[#ranges+1] = { size, specification }
diff --git a/tex/context/base/font-nod.lua b/tex/context/base/font-nod.lua
index f99130279..7fa3297d4 100644
--- a/tex/context/base/font-nod.lua
+++ b/tex/context/base/font-nod.lua
@@ -41,10 +41,12 @@ tracers.characters = char_tracers
local step_tracers = tracers.steppers or { }
tracers.steppers = step_tracers
-local copy_node_list = node.copy_list
-local hpack_node_list = node.hpack
-local free_node_list = node.flush_list
-local traverse_nodes = node.traverse
+local texsetbox = tex.setbox
+
+local copy_node_list = nodes.copy_list
+local hpack_node_list = nodes.hpack
+local free_node_list = nodes.flush_list
+local traverse_nodes = nodes.traverse
local nodecodes = nodes.nodecodes
local whatcodes = nodes.whatcodes
@@ -232,7 +234,8 @@ end
function step_tracers.glyphs(n,i)
local c = collection[i]
if c then
- tex.box[n] = hpack_node_list(copy_node_list(c))
+ local b = hpack_node_list(copy_node_list(c)) -- multiple arguments
+ texsetbox(n,b)
end
end
diff --git a/tex/context/base/font-ota.lua b/tex/context/base/font-ota.lua
index 79fcf3fa2..295452cce 100644
--- a/tex/context/base/font-ota.lua
+++ b/tex/context/base/font-ota.lua
@@ -32,6 +32,7 @@ local a_state = attributes.private('state')
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
local math_code = nodecodes.math
local traverse_id = node.traverse_id
@@ -118,7 +119,7 @@ function analyzers.setstate(head,font)
end
elseif id == disc_code then
-- always in the middle
- current[a_state] = s_midi
+ current[a_state] = s_medi
last = current
else -- finish
if first and first == last then
@@ -179,7 +180,7 @@ end
registerotffeature {
name = "analyze",
- description = "analysis of (for instance) character classes",
+ description = "analysis of character classes",
default = true,
initializers = {
node = analyzeinitializer,
diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua
index e0cb9acbc..dbec53ca3 100644
--- a/tex/context/base/font-otn.lua
+++ b/tex/context/base/font-otn.lua
@@ -530,7 +530,7 @@ local function multiple_glyphs(head,start,multiple) -- marks ?
end
function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence)
- local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
+ local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
local choice, comment = get_alternative_glyph(start,alternative,value,trace_alternatives)
if choice then
if trace_alternatives then
@@ -648,7 +648,7 @@ function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence
if marks[basechar] then
while true do
base = base.prev
- if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then
+ if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then
basechar = base.char
if not marks[basechar] then
break
diff --git a/tex/context/base/font-otx.lua b/tex/context/base/font-otx.lua
index 5c41ad66f..e3f680c22 100644
--- a/tex/context/base/font-otx.lua
+++ b/tex/context/base/font-otx.lua
@@ -32,6 +32,7 @@ local a_state = attributes.private('state')
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
local math_code = nodecodes.math
local traverse_id = node.traverse_id
@@ -123,7 +124,7 @@ function analyzers.setstate(head,font)
end
elseif id == disc_code then
-- always in the middle
- current[a_state] = s_midi
+ current[a_state] = s_medi
last = current
else -- finish
if first and first == last then
diff --git a/tex/context/base/font-pre.mkiv b/tex/context/base/font-pre.mkiv
index ef3694c2b..919a40805 100644
--- a/tex/context/base/font-pre.mkiv
+++ b/tex/context/base/font-pre.mkiv
@@ -72,28 +72,38 @@
[mode=none,
features=no]
-\definefontfeature % might move
- [arabic]
- [mode=node,language=dflt,script=arab,ccmp=yes,
+\definefontfeature
+ [semetic-complete]
+ [mode=node,analyze=yes,language=dflt,ccmp=yes,
init=yes,medi=yes,fina=yes,isol=yes,
- liga=yes,dlig=yes,rlig=yes,clig=yes,calt=yes,
- mark=yes,mkmk=yes,kern=yes,curs=yes]
+ mark=yes,mkmk=yes,kern=yes,curs=yes,
+ liga=yes,dlig=yes,rlig=yes,clig=yes,calt=yes]
+
+\definefontfeature
+ [semetic-simple]
+ [mode=node,analyze=yes,language=dflt,ccmp=yes,
+ init=yes,medi=yes,fina=yes,isol=yes,
+ mark=yes,mkmk=yes,kern=yes,curs=yes,
+ rlig=yes,calt=yes]
\definefontfeature
- [hebrew]
[arabic]
+ [semetic-complete]
+ [script=arab]
+
+\definefontfeature
+ [hebrew]
+ [semetic-complete]
[script=hebr]
-\definefontfeature % might move
+\definefontfeature
[simplearabic]
- [mode=node,language=dflt,script=arab,
- init=yes,medi=yes,fina=yes,
- rlig=yes,calt=yes,
- mark=yes,mkmk=yes,curs=yes]
+ [semetic-simple]
+ [script=arab]
\definefontfeature
[simplehebrew]
- [simplearabic]
+ [semetic-simple]
[script=hebr]
% \definefont [DevaOne] [file:chandas.ttf*devanagari-one at 12pt]
@@ -195,6 +205,13 @@
[missing]
[missing=yes]
+%D Nice to have too:
+
+\definefontfeature
+ [quality]
+ [expansion=quality,
+ protrusion=quality]
+
%D We define some colors that are used in tracing (for instance \OPENTYPE\
%D features). We cannot yet inherit because no colors are predefined.
diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua
index eb420e5be..7e62771a3 100644
--- a/tex/context/base/font-syn.lua
+++ b/tex/context/base/font-syn.lua
@@ -1722,3 +1722,49 @@ function names.resolvespec(askedname,sub) -- overloads previous definition
report_names("unresolved: %s",askedname)
end
end
+
+-- We could generate typescripts with designsize info from the name database but
+-- it's not worth the trouble as font names remain a mess: for instance how do we
+-- idenfity a font? Names, families, subfamilies or whatever snippet can contain
+-- a number related to the design size and so we end up with fuzzy logic again. So,
+-- instead it's easier to make a few goody files.
+--
+-- local hash = { }
+--
+-- for i=1,#specifications do
+-- local s = specifications[i]
+-- local min = s.minsize
+-- local max = s.maxsize
+-- if min ~= 0 or max ~= 0 then
+-- -- the usual name mess:
+-- -- antykwa has modifiers so we need to take these into account, otherwise we get weird combinations
+-- -- ebgaramond has modifiers with the size encoded, so we need to strip this in order to recognized similar styles
+-- -- lm has 'slanted appended in some names so how to choose that one
+-- --
+-- local modifier = string.gsub(s.modifiers or "normal","%d","")
+-- -- print funny modifier
+-- local instance = string.formatters["%s-%s-%s-%s-%s-%s"](s.familyname,s.width,s.style,s.weight,s.variant,modifier)
+-- local h = hash[instance]
+-- if not h then
+-- h = { }
+-- hash[instance] = h
+-- end
+-- size = string.formatters["%0.1fpt"]((min)/10)
+-- h[size] = s.filename
+-- end
+-- end
+--
+-- local newhash = { }
+--
+-- for k, v in next, hash do
+-- if next(v,next(v)) then
+-- -- local instance = string.match(k,"(.+)%-.+%-.+%-.+$")
+-- local instance = string.match(k,"(.+)%-.+%-.+$")
+-- local instance = string.gsub(instance,"%-normal$","")
+-- if not newhash[instance] then
+-- newhash[instance] = v
+-- end
+-- end
+-- end
+--
+-- inspect(newhash)
diff --git a/tex/context/base/grph-inc.lua b/tex/context/base/grph-inc.lua
index be1b7f45a..4f9d7fd92 100644
--- a/tex/context/base/grph-inc.lua
+++ b/tex/context/base/grph-inc.lua
@@ -38,7 +38,6 @@ run TeX code from within Lua. Some more functionality will move to Lua.
]]--
local format, lower, find, match, gsub, gmatch = string.format, string.lower, string.find, string.match, string.gsub, string.gmatch
-local texbox = tex.box
local contains = table.contains
local concat, insert, remove = table.concat, table.insert, table.remove
local todimen = string.todimen
@@ -57,6 +56,11 @@ local replacetemplate = utilities.templates.replace
local images = img
+local texgetbox = tex.getbox
+local texsetbox = tex.setbox
+
+local hpack = node.hpack
+
local context = context
local variables = interfaces.variables
@@ -975,7 +979,7 @@ function figures.done(data)
figures.nofprocessed = figures.nofprocessed + 1
data = data or callstack[#callstack] or lastfiguredata
local dr, du, ds, nr = data.request, data.used, data.status, figures.boxnumber
- local box = texbox[nr]
+ local box = texgetbox(nr)
ds.width = box.width
ds.height = box.height
ds.xscale = ds.width /(du.width or 1)
@@ -987,7 +991,7 @@ end
function figures.dummy(data)
data = data or callstack[#callstack] or lastfiguredata
local dr, du, nr = data.request, data.used, figures.boxnumber
- local box = node.hpack(node.new("hlist")) -- we need to set the dir (luatex 0.60 buglet)
+ local box = hpack(node.new("hlist")) -- we need to set the dir (luatex 0.60 buglet)
du.width = du.width or figures.defaultwidth
du.height = du.height or figures.defaultheight
du.depth = du.depth or figures.defaultdepth
@@ -995,7 +999,7 @@ function figures.dummy(data)
box.width = du.width
box.height = du.height
box.depth = du.depth
- texbox[nr] = box -- hm, should be global (to be checked for consistency)
+ texsetbox(nr,box) -- hm, should be global (to be checked for consistency)
end
-- -- -- generic -- -- --
@@ -1096,10 +1100,10 @@ function includers.generic(data)
if figure then
local nr = figures.boxnumber
-- it looks like we have a leak in attributes here .. todo
- local box = node.hpack(images.node(figure)) -- images.node(figure) not longer valid
+ local box = hpack(images.node(figure)) -- images.node(figure) not longer valid
indexed[figure.index] = figure
box.width, box.height, box.depth = figure.width, figure.height, 0 -- new, hm, tricky, we need to do that in tex (yet)
- texbox[nr] = box
+ texsetbox(nr,box)
ds.objectnumber = figure.objnum
context.relocateexternalfigure()
end
diff --git a/tex/context/base/grph-inc.mkiv b/tex/context/base/grph-inc.mkiv
index 8557bbb0b..4e2f8da93 100644
--- a/tex/context/base/grph-inc.mkiv
+++ b/tex/context/base/grph-inc.mkiv
@@ -297,11 +297,12 @@
%
\edef\p_width {\externalfigureparameter\c!width}%
\edef\p_height{\externalfigureparameter\c!height}%
+ \edef\p_label {\externalfigureparameter\c!label}%
%
\dostarttagged\t!image\empty
\ctxlua{figures.push {
name = "\p_grph_include_name",
- label = "\p_grph_include_label",
+ label = "\ifx\p_label\empty\p_grph_include_label\else\p_label\fi",
page = "\externalfigureparameter\c!page",
size = "\externalfigureparameter\c!size",
object = "\externalfigureparameter\c!object",
diff --git a/tex/context/base/l-file.lua b/tex/context/base/l-file.lua
index a64ee8656..ebb2b39f4 100644
--- a/tex/context/base/l-file.lua
+++ b/tex/context/base/l-file.lua
@@ -368,11 +368,14 @@ function file.joinpath(tab,separator) -- table
return tab and concat(tab,separator or io.pathseparator) -- can have trailing //
end
+local someslash = S("\\/")
local stripper = Cs(P(fwslash)^0/"" * reslasher)
-local isnetwork = fwslash * fwslash * (1-fwslash) + (1-fwslash-colon)^1 * colon
+local isnetwork = someslash * someslash * (1-someslash)
+ + (1-fwslash-colon)^1 * colon
local isroot = fwslash^1 * -1
local hasroot = fwslash^1
+local reslasher = lpeg.replacer(S("\\/"),"/")
local deslasher = lpeg.replacer(S("\\/")^1,"/")
-- If we have a network or prefix then there is a change that we end up with two
@@ -386,8 +389,13 @@ function file.join(...)
local lst = { ... }
local one = lst[1]
if lpegmatch(isnetwork,one) then
+ local one = lpegmatch(reslasher,one)
local two = lpegmatch(deslasher,concat(lst,"/",2))
- return one .. "/" .. two
+ if lpegmatch(hasroot,two) then
+ return one .. two
+ else
+ return one .. "/" .. two
+ end
elseif lpegmatch(isroot,one) then
local two = lpegmatch(deslasher,concat(lst,"/",2))
if lpegmatch(hasroot,two) then
@@ -412,6 +420,8 @@ end
-- print(file.join("http://a","/y"))
-- print(file.join("http:///a","/y"))
-- print(file.join("//nas-1","/y"))
+-- print(file.join("//nas-1/a/b/c","/y"))
+-- print(file.join("\\\\nas-1\\a\\b\\c","\\y"))
-- The previous one fails on "a.b/c" so Taco came up with a split based
-- variant. After some skyping we got it sort of compatible with the old
@@ -421,9 +431,14 @@ end
-- finds were replaced by lpegs.
local drivespec = R("az","AZ")^1 * colon
-local anchors = fwslash + drivespec
-local untouched = periods + (1-period)^1 * P(-1)
-local splitstarter = (Cs(drivespec * (bwslash/"/" + fwslash)^0) + Cc(false)) * Ct(lpeg.splitat(S("/\\")^1))
+local anchors = fwslash
+ + drivespec
+local untouched = periods
+ + (1-period)^1 * P(-1)
+local mswindrive = Cs(drivespec * (bwslash/"/" + fwslash)^0)
+local mswinuncpath = (bwslash + fwslash) * (bwslash + fwslash) * Cc("//")
+local splitstarter = (mswindrive + mswinuncpath + Cc(false))
+ * Ct(lpeg.splitat(S("/\\")^1))
local absolute = fwslash
function file.collapsepath(str,anchor) -- anchor: false|nil, true, "."
@@ -490,6 +505,7 @@ end
-- test("a/./b/..") test("a/aa/../b/bb") test("a/.././././b/..") test("a/./././b/..")
-- test("a/b/c/../..") test("./a/b/c/../..") test("a/b/c/../..")
-- test("./a")
+-- test([[\\a.b.c\d\e]])
local validchars = R("az","09","AZ","--","..")
local pattern_a = lpeg.replacer(1-validchars)
diff --git a/tex/context/base/l-io.lua b/tex/context/base/l-io.lua
index 06e1fb5ef..e3a443be8 100644
--- a/tex/context/base/l-io.lua
+++ b/tex/context/base/l-io.lua
@@ -35,6 +35,7 @@ local function readall(f)
return f:read('*all')
else
local done = f:seek("set",0)
+ local step
if size < 1024*1024 then
step = 1024 * 1024
elseif size > 16*1024*1024 then
diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua
index 7be86d38f..b33df96b7 100644
--- a/tex/context/base/l-lpeg.lua
+++ b/tex/context/base/l-lpeg.lua
@@ -13,6 +13,19 @@ if not modules then modules = { } end modules ['l-lpeg'] = {
lpeg = require("lpeg")
+-- The latest lpeg doesn't have print any more, and even the new ones are not
+-- available by default (only when debug mode is enabled), which is a pitty as
+-- as it helps bailign down bottlenecks. Performance seems comparable, although
+--
+-- local p = lpeg.C(lpeg.P(1)^0 * lpeg.P(-1))
+-- local a = string.rep("123",10)
+-- lpeg.match(p,a)
+--
+-- is nearly 20% slower and also still suboptimal (i.e. a match that runs from
+-- begin to end, one of the cases where string matchers win).
+
+if not lpeg.print then function lpeg.print(...) print(lpeg.pcode(...)) end end
+
-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
-- some code will move to unicode and string
@@ -212,7 +225,7 @@ patterns.propername = (uppercase + lowercase + underscore) * (uppercase + low
patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
patterns.beginline = #(1-newline)
-patterns.longtostring = Cs(whitespace^0/"" * nonwhitespace^0 * ((whitespace^0/" " * (patterns.quoted + nonwhitespace)^1)^0))
+patterns.longtostring = Cs(whitespace^0/"" * ((patterns.quoted + nonwhitespace^1 + whitespace^1/"" * (P(-1) + Cc(" ")))^0))
local function anywhere(pattern) --slightly adapted from website
return P { P(pattern) + 1 * V(1) }
diff --git a/tex/context/base/l-pdfview.lua b/tex/context/base/l-pdfview.lua
index fc3875ef4..6302fd6f6 100644
--- a/tex/context/base/l-pdfview.lua
+++ b/tex/context/base/l-pdfview.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['l-pdfview'] = {
license = "see context related readme files"
}
+-- Todo: add options in cnf file
+
-- Todo: figure out pdfopen/pdfclose on linux. Calling e.g. okular directly
-- doesn't work in linux when issued from scite as it blocks the editor (no
-- & possible or so). Unfortunately pdfopen keeps changing with not keeping
@@ -15,66 +17,107 @@ if not modules then modules = { } end modules ['l-pdfview'] = {
local format, concat = string.format, table.concat
+local report = logs.reporter("pdfview")
+local replace = utilities.templates.replace
+
pdfview = pdfview or { }
-local opencalls, closecalls, allcalls, runner
+local opencalls -- a table with templates that open a given pdf document
+local closecalls -- a table with templates that close a given pdf document
+local allcalls -- a table with templates that close all open pdf documents
+local runner -- runner function
+local expander -- filename cleanup function
--- this might become template based
+-- maybe spawn/execute spec in calls
if os.type == "windows" then
+ -- os.setenv("path",os.getenv("path") .. ";" .. "c:/data/system/pdf-xchange")
+ -- os.setenv("path",os.getenv("path") .. ";" .. "c:/data/system/sumatrapdf")
+
+ -- start is more flexible as it locates binaries in more places and doesn't lock
+
opencalls = {
- ['default'] = "pdfopen --rxi --file",
- ['acrobat'] = "pdfopen --rxi --file",
- ['fullacrobat'] = "pdfopen --axi --file",
- ['okular'] = 'start "test" "c:/data/system/kde/bin/okular.exe" --unique', -- todo!
- ['sumatra'] = 'start "test" "c:/data/system/sumatrapdf/sumatrapdf.exe" -reuse-instance',
- ['okular'] = 'start "test" "okular.exe" --unique',
- ['sumatra'] = 'start "test" "sumatrapdf.exe" -reuse-instance -bg-color 0xCCCCCC',
+ ['default'] = [[pdfopen --rxi --file "%filename%"]],
+ ['acrobat'] = [[pdfopen --rxi --file "%filename%"]],
+ ['fullacrobat'] = [[pdfopen --axi --file "%filename%"]],
+ ['okular'] = [[start "test" okular.exe --unique "%filename%"]],
+ ['pdfxcview'] = [[start "test" pdfxcview.exe /A "nolock=yes=OpenParameters" "%filename%"]],
+ ['sumatra'] = [[start "test" sumatrapdf.exe -reuse-instance -bg-color 0xCCCCCC "%filename%"]],
+ ['auto'] = [[start "%filename%"]],
}
closecalls= {
- ['default'] = "pdfclose --file",
- ['acrobat'] = "pdfclose --file",
- ['okular'] = false,
- ['sumatra'] = false,
+ ['default'] = [[pdfclose --file "%filename%"]],
+ ['acrobat'] = [[pdfclose --file "%filename%"]],
+ ['okular'] = false,
+ ['pdfxcview'] = false, -- [[pdfxcview.exe /close:discard "%filename%"]],
+ ['sumatra'] = false,
+ ['auto'] = false,
}
allcalls = {
- ['default'] = "pdfclose --all",
- ['acrobat'] = "pdfclose --all",
- ['okular'] = false,
- ['sumatra'] = false,
+ ['default'] = [[pdfclose --all]],
+ ['acrobat'] = [[pdfclose --all]],
+ ['okular'] = false,
+ ['pdfxcview'] = false,
+ ['sumatra'] = false,
+ ['auto'] = false,
}
- pdfview.method = "acrobat" -- no longer useful due to green pop up line and clasing reader/full
+ pdfview.method = "acrobat" -- no longer useful due to green pop up line and clashing reader/full
+ -- pdfview.method = "pdfxcview"
pdfview.method = "sumatra"
- runner = function(cmd)
- os.execute(cmd) -- .. " > /null"
+ runner = function(template,variables)
+ local cmd = replace(template,variables)
+ -- cmd = cmd .. " > /null"
+ report("command: %s",cmd)
+ os.execute(cmd)
+ end
+
+ expander = function(name)
+ -- We need to avoid issues with chdir to UNC paths and therefore expand
+ -- the path when we're current. (We could use one of the helpers instead)
+ if file.pathpart(name) == "" then
+ return file.collapsepath(file.join(lfs.currentdir(),name))
+ else
+ return name
+ end
end
else
opencalls = {
- ['default'] = "pdfopen", -- we could pass the default here
- ['okular'] = 'okular --unique',
- ['sumatra'] = 'wine "sumatrapdf.exe" -reuse-instance -bg-color 0xCCCCCC',
+ ['default'] = [[pdfopen "%filename%"]],
+ ['okular'] = [[okular --unique "%filename%"]],
+ ['sumatra'] = [[wine "sumatrapdf.exe" -reuse-instance -bg-color 0xCCCCCC "%filename%"]],
+ ['pdfxcview'] = [[wine "pdfxcview.exe" /A "nolock=yes=OpenParameters" "%filename%"]],
+ ['auto'] = [[open "%filename%"]],
}
closecalls= {
- ['default'] = "pdfclose --file",
- ['okular'] = false,
- ['sumatra'] = false,
+ ['default'] = [[pdfclose --file "%filename%"]],
+ ['okular'] = false,
+ ['sumatra'] = false,
+ ['auto'] = false,
}
allcalls = {
- ['default'] = "pdfclose --all",
- ['okular'] = false,
- ['sumatra'] = false,
+ ['default'] = [[pdfclose --all]],
+ ['okular'] = false,
+ ['sumatra'] = false,
+ ['auto'] = false,
}
pdfview.method = "okular"
- pdfview.method = "sumatra"
+ pdfview.method = "sumatra" -- faster and more complete
+
+ runner = function(template,variables)
+ local cmd = replace(template,variables)
+ cmd = cmd .. " 1>/dev/null 2>/dev/null &"
+ report("command: %s",cmd)
+ os.execute(cmd)
+ end
- runner = function(cmd)
- os.execute(cmd .. " 1>/dev/null 2>/dev/null &")
+ expander = function(name)
+ return name
end
end
@@ -97,8 +140,6 @@ function pdfview.status()
return format("pdfview methods: %s, current method: %s (directives_pdfview_method)",pdfview.methods(),tostring(pdfview.method))
end
--- local openedfiles = { }
-
local function fullname(name)
return file.addsuffix(name,"pdf")
end
@@ -108,10 +149,9 @@ function pdfview.open(...)
if opencall then
local t = { ... }
for i=1,#t do
- local name = fullname(t[i])
+ local name = expander(fullname(t[i]))
if io.exists(name) then
- runner(format('%s "%s"', opencall, name))
- -- openedfiles[name] = true
+ runner(opencall,{ filename = name })
end
end
end
@@ -122,14 +162,10 @@ function pdfview.close(...)
if closecall then
local t = { ... }
for i=1,#t do
- local name = fullname(t[i])
- -- if openedfiles[name] then
- runner(format('%s "%s"', closecall, name))
- -- openedfiles[name] = nil
- -- else
- -- pdfview.closeall()
- -- break
- -- end
+ local name = expander(fullname(t[i]))
+ if io.exists(name) then
+ replace(closecall,{ filename = name })
+ end
end
end
end
@@ -137,13 +173,8 @@ end
function pdfview.closeall()
local allcall = allcalls[pdfview.method]
if allcall then
- runner(format('%s', allcall))
+ runner(allcall)
end
- -- openedfiles = { }
end
---~ pdfview.open("t:/document/show-exa.pdf")
---~ os.sleep(3)
---~ pdfview.close("t:/document/show-exa.pdf")
-
return pdfview
diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua
index 4f6b9b4ed..11cb66bef 100644
--- a/tex/context/base/l-table.lua
+++ b/tex/context/base/l-table.lua
@@ -346,6 +346,7 @@ local noquotes, hexify, handle, reduce, compact, inline, functions
local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key
'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if',
'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while',
+ 'NaN', 'goto',
}
local function simple_table(t)
diff --git a/tex/context/base/lang-rep.lua b/tex/context/base/lang-rep.lua
new file mode 100644
index 000000000..16cd93e4a
--- /dev/null
+++ b/tex/context/base/lang-rep.lua
@@ -0,0 +1,198 @@
+if not modules then modules = { } end modules ['lang-rep'] = {
+ version = 1.001,
+ comment = "companion to lang-rep.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- A BachoTeX 2013 experiment, probably not that useful. Eventually I used a simpler
+-- more generic example.
+
+local utfbyte, utfsplit = utf.byte, utf.split
+
+local trace_replacements = false trackers.register("languages.replacements", function(v) trace_replacements = v end)
+local trace_detail = false trackers.register("languages.replacements.detail", function(v) trace_detail = v end)
+
+local report_replacement = logs.reporter("languages","replacements")
+
+local glyph_code = nodes.nodecodes.glyph
+
+local insert_node_before = nodes.insert_before
+local remove_node = nodes.remove
+local copy_node = nodes.copy
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local v_reset = interfaces.variables.reset
+
+local replacements = languages.replacements or { }
+languages.replacements = replacements
+
+local a_replacements = attributes.private("replacements")
+
+local lists = { }
+local last = 0
+local trees = { }
+
+table.setmetatableindex(lists,function(lists,name)
+ last = last + 1
+ local list = { }
+ local data = { name = name, list = list, attribute = last }
+ lists[last] = data
+ lists[name] = data
+ trees[last] = list
+ return data
+end)
+
+local function add(root,word,replacement)
+ local list = utfsplit(word,true)
+ for i=1,#list do
+ local l = utfbyte(list[i])
+ if not root[l] then
+ root[l] = { }
+ end
+ if i == #list then
+ local newlist = utfsplit(replacement,true)
+ for i=1,#newlist do
+ newlist[i] = utfbyte(newlist[i])
+ end
+ root[l].final = {
+ word = word,
+ replacement = replacement,
+ oldlength = #list,
+ newcodes = newlist,
+ }
+ end
+ root = root[l]
+ end
+end
+
+function replacements.add(category,word,replacement)
+ local root = lists[category].list
+ if type(word) == "table" then
+ for word, replacement in next, word do
+ add(root,word,replacement)
+ end
+ else
+ add(root,word,replacement or "")
+ end
+end
+
+local function hit(a,head)
+ local tree = trees[a]
+ if tree then
+ local root = tree[head.char]
+ if root then
+ local current = head.next
+ local lastrun = false
+ local lastfinal = false
+ while current and current.id == glyph_code do
+ local newroot = root[current.char]
+ if not newroot then
+ return lastrun, lastfinal
+ else
+ local final = newroot.final
+ if final then
+ if trace_detail then
+ report_replacement("hitting word %a, replacement %a",final.word,final.replacement)
+ end
+ lastrun = current
+ lastfinal = final
+ else
+ root = newroot
+ end
+ end
+ current = current.next
+ end
+ if lastrun then
+ return lastrun, lastfinal
+ end
+ end
+ end
+end
+
+local function process(namespace,attribute,head)
+ -- we could avoid this wrapper and use:
+ -- local function process(head)
+ local current = head
+ local done = false
+ while current do
+ if current.id == glyph_code then
+ -- local a = current[a_replacements]
+ local a = current[attribute]
+ if a then
+ local last, final = hit(a,current)
+ if last then
+ local oldlength = final.oldlength
+ local newcodes = final.newcodes
+ local newlength = #newcodes
+ if report_replacement then
+ report_replacement("replacing word %a by %a",final.word,final.replacement)
+ end
+ if oldlength == newlength then -- #old == #new
+ for i=1,newlength do
+ current.char = newcodes[i]
+ current = current.next
+ end
+ elseif oldlength < newlength then -- #old < #new
+ for i=1,newlength-oldlength do
+ local n = copy_node(current)
+ n.char = newcodes[i]
+ head, current = insert_node_before(head,current,n)
+ current = current.next
+ end
+ for i=newlength-oldlength+1,newlength do
+ current.char = newcodes[i]
+ current = current.next
+ end
+ else -- #old > #new
+ for i=1,oldlength-newlength do
+ head, current = remove_node(head,current,true)
+ end
+ for i=1,newlength do
+ current.char = newcodes[i]
+ current = current.next
+ end
+ end
+ done = true
+ end
+ end
+ end
+ current = current.next
+ end
+ return head, done
+end
+
+local enabled = false
+
+function replacements.set(n) -- number or 'reset'
+ if n == v_reset then
+ n = unsetvalue
+ else
+ n = lists[n].attribute
+ if not enabled then
+ nodes.tasks.enableaction("processors","languages.replacements.handler")
+ if trace_replacements then
+ report_replacement("enabling replacement handler")
+ end
+ enabled = true
+ end
+ end
+ texsetattribute(a_replacements,n)
+end
+
+replacements.handler = nodes.installattributehandler {
+ name = "replacements",
+ namespace = replacements,
+ processor = process,
+}
+
+-- interface
+
+commands.setreplacements = replacements.set
+commands.addreplacements = replacements.add
+
+nodes.tasks.prependaction("processors","words","languages.replacements.handler")
+nodes.tasks.disableaction("processors","languages.replacements.handler")
diff --git a/tex/context/base/lang-wrd.lua b/tex/context/base/lang-wrd.lua
index 06a2311a6..bf066fc09 100644
--- a/tex/context/base/lang-wrd.lua
+++ b/tex/context/base/lang-wrd.lua
@@ -334,17 +334,17 @@ end
-- for the moment we hook it into the attribute handler
---~ languagehacks = { }
+-- languagehacks = { }
---~ function languagehacks.process(namespace,attribute,head)
---~ return languages.check(head)
---~ end
+-- function languagehacks.process(namespace,attribute,head)
+-- return languages.check(head)
+-- end
---~ chars.plugins[chars.plugins+1] = {
---~ name = "language",
---~ namespace = languagehacks,
---~ processor = languagehacks.process
---~ }
+-- chars.plugins[chars.plugins+1] = {
+-- name = "language",
+-- namespace = languagehacks,
+-- processor = languagehacks.process
+-- }
-- interface
diff --git a/tex/context/base/layo-ini.lua b/tex/context/base/layo-ini.lua
index 56ced2c0b..d35d7ef69 100644
--- a/tex/context/base/layo-ini.lua
+++ b/tex/context/base/layo-ini.lua
@@ -6,17 +6,10 @@ if not modules then modules = { } end modules ['layo-ini'] = {
license = "see context related readme files"
}
--- We need to share information between the TeX and Lua end
--- about the typographical model. This happens here.
---
--- Code might move.
+-- We need to share information between the TeX and Lua end about the typographical
+-- model. This happens here. This code might move.
--- conditionals.layoutisdoublesided
--- conditionals.layoutissinglesided
--- texcount.pagenoshift
--- texcount.realpageno
-
-local texcount = tex.count
+local texgetcount = tex.getcount
local conditionals = tex.conditionals
layouts = {
@@ -33,14 +26,14 @@ function status.leftorrightpagection(left,right)
return left, right
elseif conditionals.layoutissinglesided then
return left, right
- elseif texcount.pagenoshift % 2 == 0 then
- if texcount.realpageno % 2 == 0 then
+ elseif texgetcount("pagenoshift") % 2 == 0 then
+ if texgetcount("realpageno") % 2 == 0 then
return right, left
else
return left, right
end
else
- if texcount.realpageno % 2 == 0 then
+ if texgetcount("realpageno") % 2 == 0 then
return left, right
else
return right, left
@@ -53,9 +46,9 @@ function status.isleftpage()
return false
elseif conditionals.layoutissinglesided then
return false
- elseif texcount.pagenoshift % 2 == 0 then
- return texcount.realpageno % 2 == 0
+ elseif texgetcount("pagenoshift") % 2 == 0 then
+ return texgetcount("realpageno") % 2 == 0
else
- return not texcount.realpageno % 2 == 0
+ return not texgetcount("realpageno") % 2 == 0
end
end
diff --git a/tex/context/base/lpdf-ano.lua b/tex/context/base/lpdf-ano.lua
index 990e87abd..3f0e718b3 100644
--- a/tex/context/base/lpdf-ano.lua
+++ b/tex/context/base/lpdf-ano.lua
@@ -12,7 +12,6 @@ if not modules then modules = { } end modules ['lpdf-ano'] = {
local next, tostring = next, tostring
local rep, format = string.rep, string.format
-local texcount = tex.count
local lpegmatch = lpeg.match
local formatters = string.formatters
@@ -52,6 +51,8 @@ local pdfannotation_node = nodepool.pdfannotation
local pdfdestination_node = nodepool.pdfdestination
local latelua_node = nodepool.latelua
+local texgetcount = tex.getcount
+
local pdfdictionary = lpdf.dictionary
local pdfarray = lpdf.array
local pdfreference = lpdf.reference
@@ -512,7 +513,7 @@ end
function specials.deltapage(var,actions)
local p = tonumber(var.operation)
if p then
- p = references.checkedrealpage(p + texcount.realpageno)
+ p = references.checkedrealpage(p + texgetcount("realpageno"))
return link(nil,nil,nil,p,actions)
end
end
diff --git a/tex/context/base/lpdf-fmt.lua b/tex/context/base/lpdf-fmt.lua
index 94c005f65..b444f03c3 100644
--- a/tex/context/base/lpdf-fmt.lua
+++ b/tex/context/base/lpdf-fmt.lua
@@ -36,7 +36,7 @@ local pdfstring = lpdf.string
local pdfverbose = lpdf.verbose
local pdfflushstreamfileobject = lpdf.flushstreamfileobject
-local texset = tex.set -- we could make tex.setglobal
+local texset = tex.set
local addtoinfo = lpdf.addtoinfo
local injectxmpinfo = lpdf.injectxmpinfo
diff --git a/tex/context/base/lpdf-nod.lua b/tex/context/base/lpdf-nod.lua
index 60d3fcd5b..d90ca1612 100644
--- a/tex/context/base/lpdf-nod.lua
+++ b/tex/context/base/lpdf-nod.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['lpdf-nod'] = {
license = "see context related readme files"
}
-local format = string.format
+local formatters = string.formatters
local copy_node = node.copy
local new_node = node.new
@@ -59,7 +59,7 @@ end
function nodepool.pdfsetmatrix(rx,sx,sy,ry,tx,ty)
local t = copy_node(pdfsetmatrix)
- t.data = format("%s %s %s %s",rx or 0,sx or 0,sy or 0,ry or 0) -- todo: tx ty
+ t.data = formatters["%s %s %s %s"](rx or 0,sx or 0,sy or 0,ry or 0) -- todo: tx ty
return t
end
@@ -127,8 +127,12 @@ function nodepool.pdfdestination(w,h,d,name,view,n)
local m = copy_node(pdfsetmatrix)
local r = copy_node(pdfrestore)
m.data = "1 0 0 1"
- s.next = m m.next = t t.next = r
- m.prev = s t.prev = m r.prev = t
+ s.next = m
+ m.next = t
+ t.next = r
+ m.prev = s
+ t.prev = m
+ r.prev = t
return s -- a list
else
return t
diff --git a/tex/context/base/lpdf-tag.lua b/tex/context/base/lpdf-tag.lua
index 8cdb5f6a4..29ffcd207 100644
--- a/tex/context/base/lpdf-tag.lua
+++ b/tex/context/base/lpdf-tag.lua
@@ -32,6 +32,8 @@ local pdfflushobject = lpdf.flushobject
local pdfreserveobject = lpdf.reserveobject
local pdfpagereference = lpdf.pagereference
+local texgetcount = tex.getcount
+
local nodepool = nodes.pool
local pdfliteral = nodepool.pdfliteral
@@ -69,10 +71,9 @@ local dashsplitter = lpeg.splitat("-")
local add_ids = false -- true
-
---~ function codeinjections.maptag(original,target,kind)
---~ mapping[original] = { target, kind or "inline" }
---~ end
+-- function codeinjections.maptag(original,target,kind)
+-- mapping[original] = { target, kind or "inline" }
+-- end
local function finishstructure()
if #structure_kids > 0 then
@@ -133,7 +134,7 @@ local pdf_struct_element = pdfconstant("StructElem")
local function initializepage()
index = 0
- pagenum = tex.count.realpageno
+ pagenum = texgetcount("realpageno")
pageref = pdfreference(pdfpagereference(pagenum))
list = pdfarray()
tree[pagenum] = list -- we can flush after done, todo
diff --git a/tex/context/base/lpdf-wid.lua b/tex/context/base/lpdf-wid.lua
index 5bb809327..30bd3572b 100644
--- a/tex/context/base/lpdf-wid.lua
+++ b/tex/context/base/lpdf-wid.lua
@@ -8,7 +8,6 @@ if not modules then modules = { } end modules ['lpdf-wid'] = {
local gmatch, gsub, find, lower, format = string.gmatch, string.gsub, string.find, string.lower, string.format
local stripstring = string.strip
-local texbox, texcount = tex.box, tex.count
local settings_to_array = utilities.parsers.settings_to_array
local settings_to_hash = utilities.parsers.settings_to_hash
@@ -20,6 +19,8 @@ local lpdf = lpdf
local nodes = nodes
local context = context
+local texgetcount = tex.getcount
+
local nodeinjections = backends.pdf.nodeinjections
local codeinjections = backends.pdf.codeinjections
local registrations = backends.pdf.registrations
@@ -490,8 +491,8 @@ end
local function insertrenderingwindow(specification)
local label = specification.label
---~ local openpage = specification.openpage
---~ local closepage = specification.closepage
+ -- local openpage = specification.openpage
+ -- local closepage = specification.closepage
if specification.option == v_auto then
if openpageaction then
-- \handlereferenceactions{\v!StartRendering{#2}}
@@ -507,7 +508,7 @@ local function insertrenderingwindow(specification)
PC = (closepage and lpdf.action(closepage)) or nil,
}
end
- local page = tonumber(specification.page) or texcount.realpageno -- todo
+ local page = tonumber(specification.page) or texgetcount("realpageno") -- todo
local r = mu[label] or pdfreserveannotation() -- why the reserve here?
local a = pdfdictionary {
S = pdfconstant("Rendition"),
@@ -539,34 +540,34 @@ local function insertrendering(specification)
if not mf[label] then
local filename = specification.filename
local isurl = find(filename,"://")
- --~ local start = pdfdictionary {
- --~ Type = pdfconstant("MediaOffset"),
- --~ S = pdfconstant("T"), -- time
- --~ T = pdfdictionary { -- time
- --~ Type = pdfconstant("Timespan"),
- --~ S = pdfconstant("S"),
- --~ V = 3, -- time in seconds
- --~ },
- --~ }
- --~ local start = pdfdictionary {
- --~ Type = pdfconstant("MediaOffset"),
- --~ S = pdfconstant("F"), -- frame
- --~ F = 100 -- framenumber
- --~ }
- --~ local start = pdfdictionary {
- --~ Type = pdfconstant("MediaOffset"),
- --~ S = pdfconstant("M"), -- mark
- --~ M = "somemark",
- --~ }
- --~ local parameters = pdfdictionary {
- --~ BE = pdfdictionary {
- --~ B = start,
- --~ }
- --~ }
- --~ local parameters = pdfdictionary {
- --~ Type = pdfconstant(MediaPermissions),
- --~ TF = pdfstring("TEMPALWAYS") }, -- TEMPNEVER TEMPEXTRACT TEMPACCESS TEMPALWAYS
- --~ }
+ -- local start = pdfdictionary {
+ -- Type = pdfconstant("MediaOffset"),
+ -- S = pdfconstant("T"), -- time
+ -- T = pdfdictionary { -- time
+ -- Type = pdfconstant("Timespan"),
+ -- S = pdfconstant("S"),
+ -- V = 3, -- time in seconds
+ -- },
+ -- }
+ -- local start = pdfdictionary {
+ -- Type = pdfconstant("MediaOffset"),
+ -- S = pdfconstant("F"), -- frame
+ -- F = 100 -- framenumber
+ -- }
+ -- local start = pdfdictionary {
+ -- Type = pdfconstant("MediaOffset"),
+ -- S = pdfconstant("M"), -- mark
+ -- M = "somemark",
+ -- }
+ -- local parameters = pdfdictionary {
+ -- BE = pdfdictionary {
+ -- B = start,
+ -- }
+ -- }
+ -- local parameters = pdfdictionary {
+ -- Type = pdfconstant(MediaPermissions),
+ -- TF = pdfstring("TEMPALWAYS") }, -- TEMPNEVER TEMPEXTRACT TEMPACCESS TEMPALWAYS
+ -- }
local descriptor = pdfdictionary {
Type = pdfconstant("Filespec"),
F = filename,
diff --git a/tex/context/base/luat-env.lua b/tex/context/base/luat-env.lua
index 8753972c6..5558e0303 100644
--- a/tex/context/base/luat-env.lua
+++ b/tex/context/base/luat-env.lua
@@ -20,6 +20,8 @@ local report_lua = logs.reporter("resolvers","lua")
local luautilities = utilities.lua
local luasuffixes = luautilities.suffixes
+local texgettoks = tex and tex.gettoks
+
environment = environment or { }
local environment = environment
@@ -28,7 +30,7 @@ local environment = environment
local mt = {
__index = function(_,k)
if k == "version" then
- local version = tex.toks and tex.toks.contextversiontoks
+ local version = texgettoks and texgettoks("contextversiontoks")
if version and version ~= "" then
rawset(environment,"version",version)
return version
@@ -36,7 +38,7 @@ local mt = {
return "unknown"
end
elseif k == "kind" then
- local kind = tex.toks and tex.toks.contextkindtoks
+ local kind = texgettoks and texgettoks("contextkindtoks")
if kind and kind ~= "" then
rawset(environment,"kind",kind)
return kind
diff --git a/tex/context/base/luat-fio.lua b/tex/context/base/luat-fio.lua
index d61c6f142..dcc183167 100644
--- a/tex/context/base/luat-fio.lua
+++ b/tex/context/base/luat-fio.lua
@@ -84,26 +84,6 @@ if not resolvers.instance then
end
-local report_system = logs.reporter("system","files")
-local report_files = logs.reporter("used files")
-
-luatex.registerstopactions(function()
- local foundintrees = resolvers.instance.foundintrees
- if #foundintrees > 0 then
- logs.pushtarget("logfile")
- logs.newline()
- report_system("start used files")
- logs.newline()
- for i=1,#foundintrees do
- report_files("%4i: % T",i,foundintrees[i])
- end
- logs.newline()
- report_system("stop used files")
- logs.newline()
- logs.poptarget()
- end
-end)
-
statistics.register("resource resolver", function()
local scandata = resolvers.scandata()
return format("loadtime %s seconds, %s scans with scantime %s seconds, %s shared scans, %s found files, scanned paths: %s",
diff --git a/tex/context/base/lxml-css.lua b/tex/context/base/lxml-css.lua
index c5a85c2bd..5b389626c 100644
--- a/tex/context/base/lxml-css.lua
+++ b/tex/context/base/lxml-css.lua
@@ -30,8 +30,9 @@ if tex then
local exheights = fonts.hashes.exheights
local emwidths = fonts.hashes.emwidths
+ local texget = tex.get
- percentage = function(s,pcf) return tonumber(s) * (pcf or tex.hsize) end
+ percentage = function(s,pcf) return tonumber(s) * (pcf or texget("hsize") end
exheight = function(s,exf) return tonumber(s) * (exf or exheights[true]) end
emwidth = function(s,emf) return tonumber(s) * (emf or emwidths[true]) end
pixels = function(s,pxf) return tonumber(s) * (pxf or emwidths[true]/300) end
@@ -109,17 +110,17 @@ css.padding = padding
-- print(padding("0",pixel,hsize,exheight,emwidth))
--- local currentfont = font.current
--- local texdimen = tex.dimen
--- local hashes = fonts.hashes
--- local quads = hashes.quads
--- local xheights = hashes.xheights
+-- local currentfont = font.current
+-- local texget = tex.get
+-- local hashes = fonts.hashes
+-- local quads = hashes.quads
+-- local xheights = hashes.xheights
--
-- local function padding(str)
-- local font = currentfont()
-- local exheight = xheights[font]
-- local emwidth = quads[font]
--- local hsize = texdimen.hsize/100
+-- local hsize = texget("hsize")/100
-- local pixel = emwidth/100
-- return padding(str,pixel,hsize,exheight,emwidth)
-- end
diff --git a/tex/context/base/lxml-tab.lua b/tex/context/base/lxml-tab.lua
index 9d2266886..3e10eb96d 100644
--- a/tex/context/base/lxml-tab.lua
+++ b/tex/context/base/lxml-tab.lua
@@ -34,7 +34,7 @@ as the current variant was written when <l n='lpeg'/> showed up and it's easier
build tables in one go.</p>
--ldx]]--
-lpeg.setmaxstack(1000) -- deeply nested xml files
+if lpeg.setmaxstack then lpeg.setmaxstack(1000) end -- deeply nested xml files
xml = xml or { }
local xml = xml
diff --git a/tex/context/base/m-nodechart.lua b/tex/context/base/m-nodechart.lua
new file mode 100644
index 000000000..612b73767
--- /dev/null
+++ b/tex/context/base/m-nodechart.lua
@@ -0,0 +1,175 @@
+if not modules then modules = { } end modules ['m-nodechart'] = {
+ version = 1.001,
+ comment = "companion to m-nodechart.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+local points = number.nopts
+local ptfactor = number.dimenfactors.pt
+
+local nodecodes = nodes.nodecodes
+local kerncodes = nodes.kerncodes
+local penaltycodes = nodes.penaltycodes
+local gluecodes = nodes.gluecodes
+local whatsitcodes = nodes.whatsitcodes
+
+moduledata.charts = moduledata.charts or { }
+moduledata.charts.nodes = moduledata.charts.nodes or { }
+
+local formatters = { }
+
+-- subtype font char lang left right uchyph components xoffset yoffset width height depth
+
+function formatters.glyph(n,comment)
+ return format("\\doFLOWglyphnode{%s}{%s}{%s}{%s}{U+%05X}",comment,n.subtype,n.font,n.char,n.char)
+end
+
+-- pre post replace
+
+function formatters.disc(n,comment)
+ return format("\\doFLOWdiscnode{%s}{%s}",comment,n.subtype)
+end
+
+-- subtype kern
+
+function formatters.kern(n,comment)
+ -- return format("\\doFLOWkernnode{%s}{%s}{%s}",comment,kerncodes[n.subtype],points(n.kern))
+ return format("\\doFLOWkernnode{%s}{%s}{%.4f}",comment,kerncodes[n.subtype],n.kern*ptfactor)
+end
+
+-- subtype penalty
+
+function formatters.penalty(n,comment)
+ return format("\\doFLOWpenaltynode{%s}{%s}{%s}",comment,"penalty",n.penalty)
+end
+
+-- subtype width leader spec (stretch shrink ...
+
+function formatters.glue(n,comment)
+ local s = n.spec
+ -- return format("\\doFLOWgluenode{%s}{%s}{%s}{%s}{%s}",comment,gluecodes[n.subtype],points(s.width),points(s.stretch),points(s.shrink))
+ return format("\\doFLOWgluenode{%s}{%s}{%.4f}{%.4f}{%.4f}",comment,gluecodes[n.subtype],s.width*ptfactor,s.stretch*ptfactor,s.shrink*ptfactor)
+end
+
+-- subtype width leader spec (stretch shrink ...
+
+function formatters.whatsit(n,comment)
+ local subtype = n.subtype
+ local whatsit = whatsitcodes[subtype]
+ if whatsit == "dir" or whatsit == "localpar" then
+ return format("\\doFLOWdirnode{%s}{%s}{%s}",comment,whatsit,n.dir)
+ else
+ return nodecodes[n.id]
+ end
+end
+
+-- I will make a dedicated set of shapes for this.
+
+local shapes = {
+ glyph = "procedure",
+ disc = "procedure",
+ kern = "action",
+ penalty = "action",
+ glue = "action",
+}
+
+local function flow_nodes_to_chart(specification)
+ local head = specification.head
+ local box = specification.box
+ local comment = specification.comment or ""
+ local x = specification.x or 1
+ local y = specification.y or 0
+ --
+ if box then
+ box = tex.getbox(tonumber(box))
+ head = box and box.list
+ end
+ --
+ local current = head
+ --
+ while current do
+ local nodecode = nodecodes[current.id]
+ local formatter = formatters[nodecode]
+ local shape = shapes[nodecode]
+ y = y + 1
+ local next = current.next
+ commands.flow_start_cell { shape = { framecolor = "nodechart:" .. nodecode } }
+ commands.flow_set_name(tostring(current))
+ commands.flow_set_location(x,y)
+ if shape then
+ commands.flow_set_shape(shape)
+ end
+ if formatter then
+ commands.flow_set_text("node",formatter(current,comment))
+ else
+ commands.flow_set_text("node",nodecode)
+ end
+ if next then
+ commands.flow_set_connection("bt","",tostring(next))
+ end
+ if nodecode == "glyph" then
+ local components = current.components
+ if components then
+ commands.flow_set_connection("rl","",tostring(components))
+ commands.flow_stop_cell()
+ n = flow_nodes_to_chart { head = components, comment = "component",x = x+2, y = y-1 }
+ else
+ commands.flow_stop_cell()
+ end
+ elseif nodecode == "disc" then
+ local pre = current.pre
+ local pos = current.post
+ local rep = current.replace
+ if pre and not rep and not rep then
+ if pre then
+ commands.flow_set_connection("rl","",tostring(pre))
+ end
+ commands.flow_stop_cell()
+ if pre then
+ n = flow_nodes_to_chart { head = pre, comment = "prebreak", x = x+1, y = y-1 }
+ end
+ else
+ if pre then
+ commands.flow_set_connection("+rl","",tostring(pre))
+ end
+ if rep then
+ commands.flow_set_connection("rl","",tostring(rep))
+ end
+ if pos then
+ commands.flow_set_connection("-rl","",tostring(pos))
+ end
+ commands.flow_stop_cell()
+ if pre then
+ n = flow_nodes_to_chart{ head = pre, comment = "prebreak", x = x+1, y = y-2 }
+ end
+ if rep then
+ n = flow_nodes_to_chart{ head = rep, comment = "replacement", x = x+1, y = y-1 }
+ end
+ if pos then
+ n = flow_nodes_to_chart{ head = pos, comment = "postbreak", x = x+1, y = y }
+ end
+ end
+ elseif nodecode == "hlist" then
+ local list = current.list
+ if list then
+ commands.flow_set_connection("rl","",tostring(list))
+ commands.flow_stop_cell()
+ n = flow_nodes_to_chart { head = list, comment = "list", x = x+2, y = y-1 }
+ else
+ commands.flow_stop_cell()
+ end
+ else
+ commands.flow_stop_cell()
+ end
+ current = next
+ end
+end
+
+function moduledata.charts.nodes.chart(specification)
+ commands.flow_start_chart(specification.name)
+ flow_nodes_to_chart(specification)
+ commands.flow_stop_chart()
+end
diff --git a/tex/context/base/m-nodechart.mkvi b/tex/context/base/m-nodechart.mkvi
index 359d598ce..c9d985850 100644
--- a/tex/context/base/m-nodechart.mkvi
+++ b/tex/context/base/m-nodechart.mkvi
@@ -1,154 +1,19 @@
-\usemodule[chart]
+%D \module
+%D [ file=m-nodechart,
+%D version=2011.11.11, % nos sure when it started, needed for fonts-mkiv
+%D title=\CONTEXT\ Modules,
+%D subtitle=Node Visualization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
-\startluacode
-
-local format = string.format
-local points = number.nopts
-local ptfactor = number.dimenfactors.pt
-
-local nodecodes = nodes.nodecodes
-local kerncodes = nodes.kerncodes
-local penaltycodes = nodes.penaltycodes
-local gluecodes = nodes.gluecodes
-local whatsitcodes = nodes.whatsitcodes
-
-local formatters = { }
-
-function formatters.glyph(n,comment)
- -- subtype font char lang left right uchyph components xoffset yoffset width height depth
- return format("\\doFLOWglyphnode{%s}{%s}{%s}{%s}{U+%05X}",comment,n.subtype,n.font,n.char,n.char)
-end
-
-function formatters.disc(n,comment)
- -- pre post replace
- return format("\\doFLOWdiscnode{%s}{%s}",comment,n.subtype)
-end
-
-function formatters.kern(n,comment)
- -- subtype kern
- -- return format("\\doFLOWkernnode{%s}{%s}{%s}",comment,kerncodes[n.subtype],points(n.kern))
- return format("\\doFLOWkernnode{%s}{%s}{%.4f}",comment,kerncodes[n.subtype],n.kern*ptfactor)
-end
-
-function formatters.penalty(n,comment)
- -- subtype penalty
- return format("\\doFLOWpenaltynode{%s}{%s}{%s}",comment,"penalty",n.penalty)
-end
-
-function formatters.glue(n,comment)
- -- subtype width leader spec (stretch shrink ...
- local s = n.spec
- -- return format("\\doFLOWgluenode{%s}{%s}{%s}{%s}{%s}",comment,gluecodes[n.subtype],points(s.width),points(s.stretch),points(s.shrink))
- return format("\\doFLOWgluenode{%s}{%s}{%.4f}{%.4f}{%.4f}",comment,gluecodes[n.subtype],s.width*ptfactor,s.stretch*ptfactor,s.shrink*ptfactor)
-end
-
-function formatters.whatsit(n,comment)
- -- subtype width leader spec (stretch shrink ...
- local subtype = n.subtype
- local whatsit = whatsitcodes[subtype]
- if whatsit == "dir" or whatsit == "localpar" then
- return format("\\doFLOWdirnode{%s}{%s}{%s}",comment,whatsit,n.dir)
- else
- return nodecodes[n.id]
- end
-end
-
-local shapes = { -- I will make a dedicated set of shapes for this.
- glyph = "procedure",
- disc = "procedure",
- kern = "action",
- penalty = "action",
- glue = "action",
-}
-
-local function flow_nodes_to_chart(head,comment,x,y,how)
- local current = head
- while current do
- local nodecode = nodecodes[current.id]
- local formatter = formatters[nodecode]
- local shape = shapes[nodecode]
- y = y + 1
- local next = current.next
- commands.flow_start_cell { shape = { framecolor = "nodechart:" .. nodecode } }
- commands.flow_set_name(tostring(current))
- commands.flow_set_location(x,y)
- if shape then
- commands.flow_set_shape(shape)
- end
- if formatter then
- commands.flow_set_text("node",formatter(current,comment))
- else
- commands.flow_set_text("node",nodecode)
- end
- if next then
- commands.flow_set_connection("bt","",tostring(next))
- end
- if nodecode == "glyph" then
- local components = current.components
- if components then
- commands.flow_set_connection("rl","",tostring(components))
- commands.flow_stop_cell()
- n = flow_nodes_to_chart(components,"component",x+2,y-1)
- else
- commands.flow_stop_cell()
- end
- elseif nodecode == "disc" then
- local pre = current.pre
- local pos = current.post
- local rep = current.replace
- if pre and not rep and not rep then
- if pre then
- commands.flow_set_connection("rl","",tostring(pre))
- end
- commands.flow_stop_cell()
- if pre then
- n = flow_nodes_to_chart(pre,"prebreak",x+1,y-1)
- end
- else
- if pre then
- commands.flow_set_connection("+rl","",tostring(pre))
- end
- if rep then
- commands.flow_set_connection("rl","",tostring(rep))
- end
- if pos then
- commands.flow_set_connection("-rl","",tostring(pos))
- end
- commands.flow_stop_cell()
- if pre then
- n = flow_nodes_to_chart(pre,"prebreak",x+1,y-2)
- end
- if rep then
- n = flow_nodes_to_chart(rep,"replacement",x+1,y-1)
- end
- if pos then
- n = flow_nodes_to_chart(pos,"postbreak",x+1,y)
- end
- end
- elseif nodecode == "hlist" then
- local list = current.list
- if list then
- commands.flow_set_connection("rl","",tostring(list))
- commands.flow_stop_cell()
- n = flow_nodes_to_chart(list,"list",x+2,y-1)
- else
- commands.flow_stop_cell()
- end
- else
- commands.flow_stop_cell()
- end
- current = next
- end
- return n
-end
-
-function commands.flow_nodes_to_chart(name,head,max)
- commands.flow_start_chart(name)
- flow_nodes_to_chart(head,"",1,0)
- commands.flow_stop_chart()
-end
-
-\stopluacode
+\registerctxluafile{m-nodechart}{1.001}
+
+\usemodule[chart]
\unprotect
@@ -200,17 +65,20 @@ end
% this is a temporary interface ... we will have instances and optional settings
-\unexpanded\def\boxtoFLOWchart#name#max#box%
- {\ctxcommand{flow_nodes_to_chart("#name",tex.box[\number#box].list,\number#max)}}
+\unexpanded\def\boxtoFLOWchart[#name]#box%
+ {\ctxlua{moduledata.charts.nodes.chart {
+ name = "#name",
+ box = \number#box,
+ }}}
-\unexpanded\def\nextboxtoFLOWchart#name#max%
- {\dowithnextbox{\boxtoFLOWchart{#name}{#max}\nextbox}}
+\unexpanded\def\nextboxtoFLOWchart[#name]%
+ {\dowithnextbox{\boxtoFLOWchart[#name]\nextbox}}
-\unexpanded\def\hboxtoFLOWchart#name#max%
- {\nextboxtoFLOWchart{#name}{#max}\hbox}
+\unexpanded\def\hboxtoFLOWchart[#name]%
+ {\nextboxtoFLOWchart[#name]\hbox}
-\unexpanded\def\vboxtoFLOWchart#name#max%
- {\nextboxtoFLOWchart{#name}{#max}\vbox}
+\unexpanded\def\vboxtoFLOWchart[#name]%
+ {\nextboxtoFLOWchart[#name]\vbox}
\protect
@@ -224,7 +92,7 @@ end
\startTEXpage[offset=10pt]
- \hboxtoFLOWchart{dummy}{3}{an affil\discretionary{-}{-}{!}iation}
+ \hboxtoFLOWchart[dummy]{an affil\discretionary{-}{-}{!}iation}
\FLOWchart[dummy][width=14em,height=3em,dx=1em,dy=.75em,hcompact=yes]
@@ -232,7 +100,7 @@ end
\startTEXpage[offset=10pt]
- \hboxtoFLOWchart{dummy}{3}{an affiliation}
+ \hboxtoFLOWchart[dummy]{an affiliation}
\FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,hcompact=yes]
@@ -240,7 +108,7 @@ end
\startTEXpage[offset=10pt]
- \hboxtoFLOWchart{dummy}{3}{\nl effe fijn fietsen}
+ \hboxtoFLOWchart[dummy]{\nl effe fijn fietsen}
\FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,hcompact=yes]
@@ -248,7 +116,7 @@ end
\startTEXpage[offset=10pt]
- \hboxtoFLOWchart{dummy}{3}{\righttoleft t\kern 1pt est}
+ \hboxtoFLOWchart[dummy]{\righttoleft t\kern 1pt est}
\FLOWchart[dummy][width=14em,height=3em,dx=.5em,dy=.75em,hcompact=yes]
diff --git a/tex/context/base/m-r.tex b/tex/context/base/m-r.mkii
index ac895905c..c2cb7ba88 100644
--- a/tex/context/base/m-r.tex
+++ b/tex/context/base/m-r.mkii
@@ -30,7 +30,7 @@
\newcounter\nofRfiles
-\def\Rfile{\TEXbufferfile{\Rbufferprefix\nofRfiles}}%
+\def\Rfile{\TEXbufferfile{\Rbufferprefix\nofRfiles}}
\def\startR
{\doglobal\increment\nofRfiles
diff --git a/tex/context/base/m-spreadsheet.lua b/tex/context/base/m-spreadsheet.lua
index 9d5106e35..f329acf9a 100644
--- a/tex/context/base/m-spreadsheet.lua
+++ b/tex/context/base/m-spreadsheet.lua
@@ -172,7 +172,7 @@ function functions._s_(row,col,c,f,t)
for i=f,t do
local ci = c[i]
if type(ci) == "number" then
- r = r + c[i]
+ r = r + ci
end
end
return r
diff --git a/tex/context/base/m-translate.mkiv b/tex/context/base/m-translate.mkiv
index 363f115cb..f36f9a9fb 100644
--- a/tex/context/base/m-translate.mkiv
+++ b/tex/context/base/m-translate.mkiv
@@ -89,7 +89,6 @@
\continueifinputfile{m-translate.mkiv}
-
\starttext
\translateinput[Moica][Mojca]
diff --git a/tex/context/base/m-zint.mkiv b/tex/context/base/m-zint.mkiv
index 95b265c57..4957c8461 100644
--- a/tex/context/base/m-zint.mkiv
+++ b/tex/context/base/m-zint.mkiv
@@ -29,17 +29,21 @@ moduledata.zint = { }
local format, lower, gsub = string.format, string.lower, string.gsub
local patterns = lpeg.patterns
-local zint = "zint" -- '"c:/program files/zint/zint.exe"'
+local zint = "zint" -- '"c:/program files/zint/zint.exe"'
+local defaultcode = "PDF417"
-local whitespace = patterns.whitespace
-local spaces = whitespace^0
-local key = (spaces / "") * patterns.digit^0 * (patterns.colon * spaces / "")
-local value = (whitespace / "" + (1 - key))^1
-local pattern = lpeg.Cf(lpeg.Ct("") * (lpeg.Cg((lpeg.Cs(key) / tonumber) * (lpeg.Cs(value) / lower)) + patterns.anything)^0,rawset)
+local whitespace = patterns.whitespace
+local spaces = whitespace^0
+local key = (spaces / "") * patterns.digit^0 * (patterns.colon * spaces / "")
+local value = (whitespace / "" + (1 - key))^1
+local pattern = lpeg.Cf(lpeg.Ct("") * (lpeg.Cg((lpeg.Cs(key) / tonumber) * (lpeg.Cs(value) / lower)) + patterns.anything)^0,rawset)
local reverse
local function cleancode(code)
+ if not code or code == "" then
+ code = defaultcode
+ end
return lower(gsub(code," ",""))
end
@@ -76,6 +80,19 @@ end
\stopluacode
+\unprotect
+
+\unexpanded\def\barcode[#1]% [alternative=,text=]
+ {\bgroup
+ \getdummyparameters
+ [\c!alternative=,\c!text=,#1]%
+ \externalfigure
+ [\cldcontext{moduledata.zint.generate("\dummyparameter\c!alternative",\!!bs\dummyparameter\c!text\!!es)}]%
+ [#1,\c!alternative=,\c!text=]%
+ \egroup}
+
+\protect
+
\continueifinputfile{m-zint.mkiv}
\starttext
@@ -85,6 +102,10 @@ end
\externalfigure[\cldcontext{moduledata.zint.generate("PDF417","Ton Otten")}]
\blank
\externalfigure[\cldcontext{moduledata.zint.generate("ISBN","9789490688011")}]
+ \blank
+ \barcode[text=Does It Work?,width=\textwidth]
+ \blank
+ \barcode[alternative=isbn,text=9789490688011,width=3cm]
\stoptext
diff --git a/tex/context/base/math-act.lua b/tex/context/base/math-act.lua
index 7c75dc56e..a03542b3e 100644
--- a/tex/context/base/math-act.lua
+++ b/tex/context/base/math-act.lua
@@ -18,7 +18,7 @@ local report_math = logs.reporter("mathematics","initializing")
local context = context
local commands = commands
local mathematics = mathematics
-local texdimen = tex.dimen
+local texsetdimen = tex.setdimen
local abs = math.abs
local sequencers = utilities.sequencers
@@ -296,78 +296,95 @@ function tweaks.fixbadprime(target,original)
target.characters[0xFE325] = target.characters[0x2032]
end
-local function accent_to_extensible(target,newchr,original,oldchr,height,depth)
- local characters = target.characters
- -- if not characters[newchr] then -- xits needs an enforce
- local olddata = characters[oldchr]
- if olddata then
- height = height or 0
- depth = depth or 0
- local addprivate = fonts.helpers.addprivate
- local correction = { "down", olddata.height }
- local newdata = {
- commands = { correction, { "slot", 1, oldchr } },
- width = olddata.width,
- height = height,
- depth = depth,
- }
- characters[newchr] = newdata
- local nextglyph = olddata.next
- while nextglyph do
- local oldnextdata = characters[nextglyph]
- local newnextdata = {
- commands = { correction, { "slot", 1, nextglyph } },
- width = oldnextdata.width,
- height = height,
- depth = depth,
- }
- local newnextglyph = addprivate(target,formatters["overline-%H"](nextglyph),newnextdata)
- newdata.next = newnextglyph
- local nextnextglyph = oldnextdata.next
- if nextnextglyph == nextglyph then
- break
- else
- olddata = oldnextdata
- newdata = newnextdata
- nextglyph = nextnextglyph
- end
- end
- local hv = olddata.horiz_variants
- if hv then
- hv = fastcopy(hv)
- newdata.horiz_variants = hv
- for i=1,#hv do
- local hvi = hv[i]
- local oldglyph = hvi.glyph
- local olddata = characters[oldglyph]
- local newdata = {
- commands = { correction, { "slot", 1, oldglyph } },
- width = olddata.width,
- height = height,
- depth = depth,
- }
- hvi.glyph = addprivate(target,formatters["overline-%H"](oldglyph),newdata)
- end
- end
- end
- -- end
-end
-
-function tweaks.fixoverline(target,original)
- local height, depth = 0, 0
- local mathparameters = target.mathparameters
- if mathparameters then
- height = mathparameters.OverbarVerticalGap
- depth = mathparameters.UnderbarVerticalGap
- else
- height = target.parameters.xheight/4
- depth = height
- end
- accent_to_extensible(target,0x203E,original,0x0305,height,depth)
--- inspect(fonts.helpers.expandglyph(target.characters,0x203E))
-end
-
-sequencers.appendaction("aftercopyingcharacters", "system","mathematics.tweaks.fixoverline") -- for the moment always
+-- these could go to math-fbk
+
+-- local function accent_to_extensible(target,newchr,original,oldchr,height,depth,swap)
+-- local characters = target.characters
+-- -- if not characters[newchr] then -- xits needs an enforce
+-- local addprivate = fonts.helpers.addprivate
+-- local olddata = characters[oldchr]
+-- if olddata then
+-- if swap then
+-- swap = characters[swap]
+-- height = swap.depth
+-- depth = 0
+-- else
+-- height = height or 0
+-- depth = depth or 0
+-- end
+-- local correction = swap and { "down", (olddata.height or 0) - height } or { "down", olddata.height }
+-- local newdata = {
+-- commands = { correction, { "slot", 1, oldchr } },
+-- width = olddata.width,
+-- height = height,
+-- depth = depth,
+-- }
+-- characters[newchr] = newdata
+-- local nextglyph = olddata.next
+-- while nextglyph do
+-- local oldnextdata = characters[nextglyph]
+-- local newnextdata = {
+-- commands = { correction, { "slot", 1, nextglyph } },
+-- width = oldnextdata.width,
+-- height = height,
+-- depth = depth,
+-- }
+-- local newnextglyph = addprivate(target,formatters["original-%H"](nextglyph),newnextdata)
+-- newdata.next = newnextglyph
+-- local nextnextglyph = oldnextdata.next
+-- if nextnextglyph == nextglyph then
+-- break
+-- else
+-- olddata = oldnextdata
+-- newdata = newnextdata
+-- nextglyph = nextnextglyph
+-- end
+-- end
+-- local hv = olddata.horiz_variants
+-- if hv then
+-- hv = fastcopy(hv)
+-- newdata.horiz_variants = hv
+-- for i=1,#hv do
+-- local hvi = hv[i]
+-- local oldglyph = hvi.glyph
+-- local olddata = characters[oldglyph]
+-- local newdata = {
+-- commands = { correction, { "slot", 1, oldglyph } },
+-- width = olddata.width,
+-- height = height,
+-- depth = depth,
+-- }
+-- hvi.glyph = addprivate(target,formatters["original-%H"](oldglyph),newdata)
+-- end
+-- end
+-- end
+-- -- end
+-- end
+
+-- function tweaks.fixoverline(target,original)
+-- local height, depth = 0, 0
+-- local mathparameters = target.mathparameters
+-- if mathparameters then
+-- height = mathparameters.OverbarVerticalGap
+-- depth = mathparameters.UnderbarVerticalGap
+-- else
+-- height = target.parameters.xheight/4
+-- depth = height
+-- end
+-- accent_to_extensible(target,0x203E,original,0x0305,height,depth)
+-- -- also crappy spacing for our purpose: push to top of baseline
+-- accent_to_extensible(target,0xFE3DE,original,0x23DE,height,depth,0x23DF)
+-- accent_to_extensible(target,0xFE3DC,original,0x23DC,height,depth,0x23DD)
+-- accent_to_extensible(target,0xFE3B4,original,0x23B4,height,depth,0x23B5)
+-- -- for symmetry
+-- target.characters[0xFE3DF] = original.characters[0x23DF]
+-- target.characters[0xFE3DD] = original.characters[0x23DD]
+-- target.characters[0xFE3B5] = original.characters[0x23B5]
+-- -- inspect(fonts.helpers.expandglyph(target.characters,0x203E))
+-- -- inspect(fonts.helpers.expandglyph(target.characters,0x23DE))
+-- end
+
+-- sequencers.appendaction("aftercopyingcharacters", "system","mathematics.tweaks.fixoverline") -- for the moment always
-- helpers
@@ -455,24 +472,24 @@ function commands.horizontalcode(family,unicode)
local charlist = data[3].horiz_variants
local characters = fontcharacters[font]
local left = charlist[1]
- texdimen.scratchleftoffset = abs((left["start"] or 0) - (left["end"] or 0))
- texdimen.scratchrightoffset = 0
+ texsetdimen("scratchleftoffset",abs((left["start"] or 0) - (left["end"] or 0)))
+ texsetdimen("scratchrightoffset",0)
elseif kind == e_right then
local charlist = data[3].horiz_variants
local characters = fontcharacters[font]
local right = charlist[#charlist]
- texdimen.scratchleftoffset = 0
- texdimen.scratchrightoffset = abs((right["start"] or 0) - (right["end"] or 0))
+ texsetdimen("scratchleftoffset",0)
+ texsetdimen("scratchrightoffset",abs((right["start"] or 0) - (right["end"] or 0)))
elseif kind == e_horizontal then
local charlist = data[3].horiz_variants
local characters = fontcharacters[font]
local left = charlist[1]
local right = charlist[#charlist]
- texdimen.scratchleftoffset = abs((left["start"] or 0) - (left["end"] or 0))
- texdimen.scratchrightoffset = abs((right["start"] or 0) - (right["end"] or 0))
+ texsetdimen("scratchleftoffset", abs((left ["start"] or 0) - (left ["end"] or 0)))
+ texsetdimen("scratchrightoffset",abs((right["start"] or 0) - (right["end"] or 0)))
else
- texdimen.scratchleftoffset = 0
- texdimen.scratchrightoffset = 0
+ texsetdimen("scratchleftoffset",0)
+ texsetdimen("scratchrightoffset",0)
end
context(kind)
end
diff --git a/tex/context/base/math-def.mkiv b/tex/context/base/math-def.mkiv
index 9201fc540..99e6a8a18 100644
--- a/tex/context/base/math-def.mkiv
+++ b/tex/context/base/math-def.mkiv
@@ -348,18 +348,21 @@
\unexpanded\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits}
\unexpanded\def\stackrel #1#2{\mathrel{\mathop{#2}\limits^{#1}}}
-\unexpanded\def\overbrace {\mathopwithlimits\normaloverbrace }
-\unexpanded\def\underbrace {\mathopwithlimits\normalunderbrace }
-\unexpanded\def\doublebrace {\mathopwithlimits\normaldoublebrace }
-\unexpanded\def\overparent {\mathopwithlimits\normaloverparent }
-\unexpanded\def\underparent {\mathopwithlimits\normalunderparent }
-\unexpanded\def\overbracket {\mathopwithlimits\normaloverbracket }
-\unexpanded\def\underbracket {\mathopwithlimits\normalunderbracket }
-\unexpanded\def\doubleparent {\mathopwithlimits\normaldoubleparent }
-\unexpanded\def\underleftarrow {\mathopwithlimits\normalunderleftarrow }
-\unexpanded\def\overleftarrow {\mathopwithlimits\normaloverleftarrow }
-\unexpanded\def\underrightarrow{\mathopwithlimits\normalunderrightarrow}
-\unexpanded\def\overrightarrow {\mathopwithlimits\normaloverrightarrow }
+% these are stackers now
+
+%\unexpanded\def\overbrace {\mathopwithlimits\normaloverbrace }
+%\unexpanded\def\underbrace {\mathopwithlimits\normalunderbrace }
+%\unexpanded\def\doublebrace {\mathopwithlimits\normaldoublebrace }
+%\unexpanded\def\overparent {\mathopwithlimits\normaloverparent }
+%\unexpanded\def\underparent {\mathopwithlimits\normalunderparent }
+%\unexpanded\def\overbracket {\mathopwithlimits\normaloverbracket }
+%\unexpanded\def\underbracket {\mathopwithlimits\normalunderbracket }
+%\unexpanded\def\doubleparent {\mathopwithlimits\normaldoubleparent }
+
+%unexpanded\def\underleftarrow {\mathopwithlimits\normalunderleftarrow }
+%unexpanded\def\overleftarrow {\mathopwithlimits\normaloverleftarrow }
+%unexpanded\def\underrightarrow{\mathopwithlimits\normalunderrightarrow}
+%unexpanded\def\overrightarrow {\mathopwithlimits\normaloverrightarrow }
\let\lceil \lceiling
\let\rceil \rceiling
diff --git a/tex/context/base/math-fbk.lua b/tex/context/base/math-fbk.lua
index eebc4e4e7..0800f3007 100644
--- a/tex/context/base/math-fbk.lua
+++ b/tex/context/base/math-fbk.lua
@@ -10,6 +10,9 @@ local trace_fallbacks = false trackers.register("math.fallbacks", function(v) t
local report_fallbacks = logs.reporter("math","fallbacks")
+local formatters = string.formatters
+local fastcopy = table.fastcopy
+
local fallbacks = { }
mathematics.fallbacks = fallbacks
@@ -39,7 +42,7 @@ function fallbacks.apply(target,original)
end
-- This is not okay yet ... we have no proper way to refer to 'self'
-- otherwise I will make my own id allocator).
-local self = #usedfonts == 0 and font.nextid() or nil -- will be true
+ local self = #usedfonts == 0 and font.nextid() or nil -- will be true
local textid, scriptid, scriptscriptid
local textindex, scriptindex, scriptscriptindex
local textdata, scriptdata, scriptscriptdata
@@ -48,19 +51,19 @@ local self = #usedfonts == 0 and font.nextid() or nil -- will be true
-- textid = nil -- self
-- scriptid = nil -- no smaller
-- scriptscriptid = nil -- no smaller
-textid = self
-scriptid = self
-scriptscriptid = self
+ textid = self
+ scriptid = self
+ scriptscriptid = self
elseif mathsize == 2 then
-- scriptsize
-- textid = nil -- self
-textid = self
+ textid = self
scriptid = lastmathids[3]
scriptscriptid = lastmathids[3]
else
-- textsize
-- textid = nil -- self
-textid = self
+ textid = self
scriptid = lastmathids[2]
scriptscriptid = lastmathids[3]
end
@@ -87,8 +90,7 @@ textid = self
scriptscriptindex = scriptindex
scriptscriptdata = scriptdata
end
--- report_fallbacks("used textid: %s, used script id: %s, used scriptscript id: %s",
--- tostring(textid),tostring(scriptid),tostring(scriptscriptid))
+ -- report_fallbacks("used textid: %S, used script id: %S, used scriptscript id: %S",textid,scriptid,scriptscriptid)
local data = {
textdata = textdata,
scriptdata = scriptdata,
@@ -103,7 +105,7 @@ textid = self
size = size,
mathsize = mathsize,
}
--- inspect(usedfonts)
+ -- inspect(usedfonts)
for k, v in next, virtualcharacters do
if not characters[k] then
local tv = type(v)
@@ -310,3 +312,129 @@ virtualcharacters[0xFE352] = function(data)
end
end
+-- we could move the defs from math-act here
+
+addextra(0xFE3DE, { description="EXTENSIBLE OF 0x03DE", unicodeslot=0xFE3DE, mathextensible = "r", mathstretch = "h" } )
+addextra(0xFE3DF, { description="EXTENSIBLE OF 0x03DF", unicodeslot=0xFE3DF, mathextensible = "r", mathstretch = "h" } )
+addextra(0xFE3DC, { description="EXTENSIBLE OF 0x03DC", unicodeslot=0xFE3DC, mathextensible = "r", mathstretch = "h" } )
+addextra(0xFE3DD, { description="EXTENSIBLE OF 0x03DD", unicodeslot=0xFE3DD, mathextensible = "r", mathstretch = "h" } )
+addextra(0xFE3B4, { description="EXTENSIBLE OF 0x03B4", unicodeslot=0xFE3B4, mathextensible = "r", mathstretch = "h" } )
+addextra(0xFE3B5, { description="EXTENSIBLE OF 0x03B5", unicodeslot=0xFE3B5, mathextensible = "r", mathstretch = "h" } )
+
+local function accent_to_extensible(target,newchr,original,oldchr,height,depth,swap)
+ local characters = target.characters
+ local addprivate = fonts.helpers.addprivate
+ local olddata = characters[oldchr]
+ if olddata then
+ if swap then
+ swap = characters[swap]
+ height = swap.depth
+ depth = 0
+ else
+ height = height or 0
+ depth = depth or 0
+ end
+ local correction = swap and { "down", (olddata.height or 0) - height } or { "down", olddata.height }
+ local newdata = {
+ commands = { correction, { "slot", 1, oldchr } },
+ width = olddata.width,
+ height = height,
+ depth = depth,
+ }
+ local glyphdata = newdata
+ local nextglyph = olddata.next
+ while nextglyph do
+ local oldnextdata = characters[nextglyph]
+ local newnextdata = {
+ commands = { correction, { "slot", 1, nextglyph } },
+ width = oldnextdata.width,
+ height = height,
+ depth = depth,
+ }
+ local newnextglyph = addprivate(target,formatters["original-%H"](nextglyph),newnextdata)
+ newdata.next = newnextglyph
+ local nextnextglyph = oldnextdata.next
+ if nextnextglyph == nextglyph then
+ break
+ else
+ olddata = oldnextdata
+ newdata = newnextdata
+ nextglyph = nextnextglyph
+ end
+ end
+ local hv = olddata.horiz_variants
+ if hv then
+ hv = fastcopy(hv)
+ newdata.horiz_variants = hv
+ for i=1,#hv do
+ local hvi = hv[i]
+ local oldglyph = hvi.glyph
+ local olddata = characters[oldglyph]
+ local newdata = {
+ commands = { correction, { "slot", 1, oldglyph } },
+ width = olddata.width,
+ height = height,
+ depth = depth,
+ }
+ hvi.glyph = addprivate(target,formatters["original-%H"](oldglyph),newdata)
+ end
+ end
+ return glyphdata
+ end
+end
+
+virtualcharacters[0x203E] = function(data) -- could be FE33E instead
+ local target = data.target
+ local height, depth = 0, 0
+ local mathparameters = target.mathparameters
+ if mathparameters then
+ height = mathparameters.OverbarVerticalGap
+ depth = mathparameters.UnderbarVerticalGap
+ else
+ height = target.parameters.xheight/4
+ depth = height
+ end
+ return accent_to_extensible(target,0x203E,data.original,0x0305,height,depth)
+end
+
+virtualcharacters[0xFE3DE] = function(data)
+ local target, original = data.target, data.original
+ local chardata = target.characters[0x23DE]
+ if chardata and chardata.height > target.parameters.xheight then
+ return accent_to_extensible(target,0xFE3DE,original,0x23DE,0,0,0x23DF)
+ else
+ return original.characters[0x23DE]
+ end
+end
+
+virtualcharacters[0xFE3DC] = function(data)
+ local target, original = data.target, data.original
+ local chardata = target.characters[0x23DC]
+ if chardata and chardata.height > target.parameters.xheight then
+ return accent_to_extensible(target,0xFE3DC,original,0x23DC,0,0,0x23DD)
+ else
+ return original.characters[0x23DC]
+ end
+end
+
+virtualcharacters[0xFE3B4] = function(data)
+ local target, original = data.target, data.original
+ local chardata = target.characters[0x23B4]
+ if chardata and chardata.height > target.parameters.xheight then
+ return accent_to_extensible(target,0xFE3B4,original,0x23B4,0,0,0x23B5)
+ else
+ return original.characters[0x23B4]
+ end
+end
+
+virtualcharacters[0xFE3DF] = function(data)
+ return data.original.characters[0x23DF]
+end
+
+virtualcharacters[0xFE3DD] = function(data)
+ return data.original.characters[0x23DD]
+end
+
+virtualcharacters[0xFE3B5] = function(data)
+ return data.original.characters[0x23B5]
+end
diff --git a/tex/context/base/math-ini.lua b/tex/context/base/math-ini.lua
index 6e667d083..dc1e9f29a 100644
--- a/tex/context/base/math-ini.lua
+++ b/tex/context/base/math-ini.lua
@@ -17,8 +17,6 @@ if not modules then modules = { } end modules ['math-ini'] = {
local formatters, find = string.formatters, string.find
local utfchar, utfbyte = utf.char, utf.byte
-local setmathcode, setdelcode = tex.setmathcode, tex.setdelcode
-local settexattribute = tex.setattribute
local floor = math.floor
local context = context
@@ -41,6 +39,10 @@ local unsetvalue = attributes.unsetvalue
local allocate = utilities.storage.allocate
local chardata = characters.data
+local texsetattribute = tex.setattribute
+local setmathcode = tex.setmathcode
+local setdelcode = tex.setdelcode
+
local families = allocate {
mr = 0,
mb = 1,
@@ -503,10 +505,10 @@ end
--
-- function commands.taggedmathfunction(tag,label)
-- if label then
--- settexattribute(a_mathcategory,registercategory(1,tag,tag))
+-- texsetattribute(a_mathcategory,registercategory(1,tag,tag))
-- context.mathlabeltext(tag)
-- else
--- settexattribute(a_mathcategory,1)
+-- texsetattribute(a_mathcategory,1)
-- context(tag)
-- end
-- end
@@ -529,13 +531,13 @@ function commands.taggedmathfunction(tag,label,apply)
noffunctions = noffunctions + 1
functions[noffunctions] = tag
functions[tag] = noffunctions
- settexattribute(a_mathcategory,noffunctions + delta)
+ texsetattribute(a_mathcategory,noffunctions + delta)
else
- settexattribute(a_mathcategory,n + delta)
+ texsetattribute(a_mathcategory,n + delta)
end
context.mathlabeltext(tag)
else
- settexattribute(a_mathcategory,1000 + delta)
+ texsetattribute(a_mathcategory,1000 + delta)
context(tag)
end
end
@@ -554,6 +556,6 @@ function commands.resetmathattributes()
end
end
for i=1,#list do
- settexattribute(list[i],unsetvalue)
+ texsetattribute(list[i],unsetvalue)
end
end
diff --git a/tex/context/base/math-map.lua b/tex/context/base/math-map.lua
index a0d7457d1..9158d945a 100644
--- a/tex/context/base/math-map.lua
+++ b/tex/context/base/math-map.lua
@@ -36,11 +36,15 @@ local merged = table.merged
local extract = bit32.extract
local allocate = utilities.storage.allocate
-local texattribute = tex.attribute
+
local otffeatures = fonts.constructors.newfeatures("otf")
local registerotffeature = otffeatures.register
+
local setmetatableindex = table.setmetatableindex
+local texgetattribute = tex.getattribute
+local texsetattribute = tex.setattribute
+
local trace_greek = false trackers.register("math.greek", function(v) trace_greek = v end)
local report_remapping = logs.reporter("mathematics","remapping")
@@ -524,7 +528,7 @@ function mathematics.getboth(alphabet,style)
end
function mathematics.getstyle(style)
- local r = mathremap[texattribute[mathalphabet]]
+ local r = mathremap[texgetattribute(mathalphabet)]
local alphabet = r and r.alphabet or "regular"
local data = alphabets[alphabet][style]
return data and data.attribute
@@ -533,22 +537,22 @@ end
function mathematics.syncboth(alphabet,style)
local data = alphabet and alphabets[alphabet] or regular
data = style and data[style] or data.tf
- texattribute[mathalphabet] = data and data.attribute or texattribute[mathalphabet]
+ texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
end
function mathematics.syncstyle(style)
- local r = mathremap[texattribute[mathalphabet]]
+ local r = mathremap[texgetattribute(mathalphabet)]
local alphabet = r and r.alphabet or "regular"
local data = alphabets[alphabet][style]
- texattribute[mathalphabet] = data and data.attribute or texattribute[mathalphabet]
+ texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
end
function mathematics.syncname(alphabet)
-- local r = mathremap[mathalphabet]
- local r = mathremap[texattribute[mathalphabet]]
+ local r = mathremap[texgetattribute(mathalphabet)]
local style = r and r.style or "tf"
local data = alphabets[alphabet][style]
- texattribute[mathalphabet] = data and data.attribute or texattribute[mathalphabet]
+ texsetattribute(mathalphabet,data and data.attribute or texattribute[mathalphabet])
end
local islcgreek = regular_tf.lcgreek
diff --git a/tex/context/base/math-noa.lua b/tex/context/base/math-noa.lua
index b309ba077..903c91f34 100644
--- a/tex/context/base/math-noa.lua
+++ b/tex/context/base/math-noa.lua
@@ -62,7 +62,6 @@ local new_node = node.new -- todo: pool: math_noad math_sub
local new_kern = nodes.pool.kern
local new_rule = nodes.pool.rule
-local concat_nodes = nodes.concat
local topoints = number.points
@@ -75,7 +74,8 @@ local fontemwidths = fonthashes.emwidths
local fontexheights = fonthashes.exheights
local variables = interfaces.variables
-local texattribute = tex.attribute
+local texsetattribute = tex.setattribute
+local texgetattribute = tex.getattribute
local unsetvalue = attributes.unsetvalue
local chardata = characters.data
@@ -462,135 +462,6 @@ function handlers.resize(head,style,penalties)
return true
end
--- respacing
-
--- local mathpunctuation = attributes.private("mathpunctuation")
---
--- local respace = { } processors.respace = respace
-
--- only [nd,ll,ul][po][nd,ll,ul]
-
--- respace[math_char] = function(pointer,what,n,parent) -- not math_noad .. math_char ... and then parent
--- pointer = parent
--- if pointer and pointer.subtype == noad_ord then
--- local a = pointer[mathpunctuation]
--- if a and a > 0 then
--- pointer[mathpunctuation] = 0
--- local current_nucleus = pointer.nucleus
--- if current_nucleus.id == math_char then
--- local current_char = current_nucleus.char
--- local fc = chardata[current_char]
--- fc = fc and fc.category
--- if fc == "nd" or fc == "ll" or fc == "lu" then
--- local next_noad = pointer.next
--- if next_noad and next_noad.id == math_noad and next_noad.subtype == noad_punct then
--- local next_nucleus = next_noad.nucleus
--- if next_nucleus.id == math_char then
--- local next_char = next_nucleus.char
--- local nc = chardata[next_char]
--- nc = nc and nc.category
--- if nc == "po" then
--- local last_noad = next_noad.next
--- if last_noad and last_noad.id == math_noad and last_noad.subtype == noad_ord then
--- local last_nucleus = last_noad.nucleus
--- if last_nucleus.id == math_char then
--- local last_char = last_nucleus.char
--- local lc = chardata[last_char]
--- lc = lc and lc.category
--- if lc == "nd" or lc == "ll" or lc == "lu" then
--- local ord = new_node(math_noad) -- todo: pool
--- ord.subtype, ord.nucleus, ord.sub, ord.sup, ord.attr = noad_ord, next_noad.nucleus, next_noad.sub, next_noad.sup, next_noad.attr
--- -- next_noad.nucleus, next_noad.sub, next_noad.sup, next_noad.attr = nil, nil, nil, nil
--- next_noad.nucleus, next_noad.sub, next_noad.sup = nil, nil, nil -- else crash with attributes ref count
--- --~ next_noad.attr = nil
--- ord.next = last_noad
--- pointer.next = ord
--- free_node(next_noad)
--- end
--- end
--- end
--- end
--- end
--- end
--- end
--- end
--- end
--- end
--- end
-
--- local comma = 0x002C
--- local period = 0x002E
---
--- respace[math_char] = function(pointer,what,n,parent)
--- pointer = parent
--- if pointer and pointer.subtype == noad_punct then
--- local current_nucleus = pointer.nucleus
--- if current_nucleus.id == math_char then
--- local current_nucleus = pointer.nucleus
--- if current_nucleus.id == math_char then
--- local current_char = current_nucleus.char
--- local a = pointer[mathpunctuation]
--- if not a or a == 0 then
--- if current_char == comma then
--- -- default tex: 2,5 or 2, 5 --> 2, 5
--- elseif current_char == period then
--- -- default tex: 2.5 or 2. 5 --> 2.5
--- pointer.subtype = noad_ord
--- end
--- elseif a == 1 then
--- local next_noad = pointer.next
--- if next_noad and next_noad.id == math_noad then
--- local next_nucleus = next_noad.nucleus
--- if next_nucleus.id == math_char and next_nucleus.char == 0 then
--- nodes.remove(pointer,next_noad,true)
--- end
--- if current_char == comma then
--- -- default tex: 2,5 or 2, 5 --> 2, 5
--- elseif current_char == period then
--- -- default tex: 2.5 or 2. 5 --> 2.5
--- pointer.subtype = noad_ord
--- end
--- end
--- elseif a == 2 then
--- if current_char == comma or current_char == period then
--- local next_noad = pointer.next
--- if next_noad and next_noad.id == math_noad then
--- local next_nucleus = next_noad.nucleus
--- if next_nucleus.id == math_char and next_nucleus.char == 0 then
--- if current_char == comma then
--- -- adaptive: 2, 5 --> 2, 5
--- elseif current_char == period then
--- -- adaptive: 2. 5 --> 2. 5
--- end
--- nodes.remove(pointer,next_noad,true)
--- else
--- if current_char == comma then
--- -- adaptive: 2,5 --> 2,5
--- pointer.subtype = noad_ord
--- elseif current_char == period then
--- -- adaptive: 2.5 --> 2.5
--- pointer.subtype = noad_ord
--- end
--- end
--- end
--- end
--- end
--- end
--- end
--- end
--- end
---
--- function handlers.respace(head,style,penalties)
--- processnoads(head,respace,"respace")
--- return true
--- end
-
--- The following code is dedicated to Luigi Scarso who pointed me
--- to the fact that \not= is not producing valid pdf-a code.
--- The code does not solve this for virtual characters but it does
--- a decent job on collapsing so that fonts that have the right
--- glyph will have a decent unicode point. In the meantime this code
--- has been moved elsewhere.
local collapse = { } processors.collapse = collapse
@@ -824,7 +695,7 @@ function mathematics.setalternate(fam,tag)
local mathalternates = tfmdata.shared and tfmdata.shared.mathalternates
if mathalternates then
local m = mathalternates[tag]
- tex.attribute[a_mathalternate] = m and m.attribute or unsetvalue
+ texsetattribute(a_mathalternate,m and m.attribute or unsetvalue)
end
end
@@ -947,11 +818,7 @@ trackers.register("math.italics", function(v)
if k > 0 then
return setcolor(new_rule(k,ex,ex),c_positive_d)
else
- return concat_nodes {
- old_kern(k),
- setcolor(new_rule(-k,ex,ex),c_negative_d),
- old_kern(k),
- }
+ return old_kern(k) .. setcolor(new_rule(-k,ex,ex),c_negative_d) .. old_kern(k)
end
end
else
@@ -1063,14 +930,14 @@ function mathematics.setitalics(n)
enable()
end
if n == variables.reset then
- texattribute[a_mathitalics] = unsetvalue
+ texsetattribute(a_mathitalics,unsetvalue)
else
- texattribute[a_mathitalics] = tonumber(n) or unsetvalue
+ texsetattribute(a_mathitalics,tonumber(n) or unsetvalue)
end
end
function mathematics.resetitalics()
- texattribute[a_mathitalics] = unsetvalue
+ texsetattribute(a_mathitalics,unsetvalue)
end
-- variants
diff --git a/tex/context/base/math-ren.lua b/tex/context/base/math-ren.lua
index 2e7dba13d..5c4c13369 100644
--- a/tex/context/base/math-ren.lua
+++ b/tex/context/base/math-ren.lua
@@ -63,7 +63,3 @@ mathematics.renderset = renderset
function commands.mathrenderset(list)
context(renderset(list))
end
-
--- function commands.setmatrendering(list)
--- tex.setattribute(renderset(list))
--- end
diff --git a/tex/context/base/math-stc.mkvi b/tex/context/base/math-stc.mkvi
index ae601bc4c..5f92f3801 100644
--- a/tex/context/base/math-stc.mkvi
+++ b/tex/context/base/math-stc.mkvi
@@ -395,11 +395,23 @@
%D The next one deals with under and over extensibles (arrows mostly):
-\unexpanded\def\math_stackers_double#where#category#codepoint#text%
+\installcorenamespace {mathclasses}
+
+\letvalue{\??mathclasses }\mathord
+\letvalue{\??mathclasses rel}\mathrel
+\letvalue{\??mathclasses ord}\mathord
+
+\def\math_class_by_parameter#1%
+ {\normalexpanded{\noexpand\math_class_by_parameter_indeed{#1\c!mathclass}}}
+
+\def\math_class_by_parameter_indeed#1%
+ {\csname\??mathclasses\ifcsname\??mathclasses#1\endcsname#1\fi\endcsname}
+
+\unexpanded\def\math_stackers_make_double#top#bottom#category#codepoint#codeextra#text%
{\begingroup
\edef\currentmathstackers{#category}%
\mathstackersparameter\c!left\relax
- \ifmmode\mathrel\else\dontleavehmode\fi
+ \ifmmode\math_class_by_parameter\mathstackersparameter\else\dontleavehmode\fi
{\edef\currentmathstackers{#category}%
\edef\m_math_stackers_text_middle {#text}%
%
@@ -436,12 +448,18 @@
%
\ifdim\htdp\scratchboxtwo>\zeropoint
\kern-\scratchwidth
- \ifcase#where\relax
+ \ifcase#top\else
\math_stackers_top\bgroup
\raise\dimexpr\scratchheight+\scratchtopoffset\relax
\box\scratchboxtwo
\egroup
- \else
+ \fi
+ \scratchunicode#codeextra\relax
+ \ifcase\scratchunicode\else
+ \kern-\scratchwidth
+ \setbox\scratchboxtwo\math_stackers_content
+ \fi
+ \ifcase#bottom\else
\math_stackers_bottom\bgroup
\lower\dimexpr\scratchdepth+\ht\scratchboxtwo+\scratchbottomoffset\relax
\box\scratchboxtwo
@@ -449,36 +467,53 @@
\fi
\fi}%
\mathstackersparameter\c!right\relax
- \endgroup}
+ \edef\p_limits{\mathstackersparameter\c!mathlimits}%
+ \ifx\p_limits\v!yes
+ \expandafter\endgroup\expandafter\limits
+ \else
+ \expandafter\endgroup
+ \fi}
-\unexpanded\def\definemathoverextensible {\dotripleempty\math_extensiblies_define_over }
-\unexpanded\def\definemathunderextensible{\dotripleempty\math_extensiblies_define_under}
+\unexpanded\def\definemathoverextensible {\dotripleempty \math_extensiblies_define_over }
+\unexpanded\def\definemathunderextensible {\dotripleempty \math_extensiblies_define_under}
+\unexpanded\def\definemathdoubleextensible{\doquadrupleempty\math_extensiblies_define_double}
\def\math_extensiblies_define_over[#1][#2][#3]%
{\ifthirdargument
- \setuevalue{#2}{\math_stackers_double\zerocount{#1}{\number#3}}%
+ \setuevalue{#2}{\math_stackers_make_double\plusone \zerocount{#1}{\number#3}{0}}%
\else
- \setuevalue{#1}{\math_stackers_double\zerocount\noexpand\currentmathstackers{\number#2}}%
+ \setuevalue{#1}{\math_stackers_make_double\plusone \zerocount\noexpand\currentmathstackers{\number#2}{0}}%
\fi}
\def\math_extensiblies_define_under[#1][#2][#3]%
{\ifthirdargument
- \setuevalue{#2}{\math_stackers_double\plusone{#1}{\number#3}}%
+ \setuevalue{#2}{\math_stackers_make_double\zerocount\plusone{#1}{\number#3}{0}}%
\else
- \setuevalue{#1}{\math_stackers_double\plusone\noexpand\currentmathstackers{\number#2}}%
+ \setuevalue{#1}{\math_stackers_make_double\zerocount\plusone\noexpand\currentmathstackers{\number#2}{0}}%
\fi}
-\unexpanded\def\mathover {\begingroup\dosingleempty\math_stackers_handle_over }
-\unexpanded\def\mathunder{\begingroup\dosingleempty\math_stackers_handle_under}
+\def\math_extensiblies_define_double[#1][#2][#3][#4]%
+ {\ifthirdargument
+ \setuevalue{#2}{\math_stackers_make_double\plusone \plusone{#1}{\number#3}{\number#4}}%
+ \else
+ \setuevalue{#1}{\math_stackers_make_double\plusone \plusone\noexpand\currentmathstackers{\number#2}{\number#3}}%
+ \fi}
+
+\unexpanded\def\mathover {\begingroup\dosingleempty\math_stackers_handle_over }
+\unexpanded\def\mathunder {\begingroup\dosingleempty\math_stackers_handle_under }
+\unexpanded\def\mathdouble{\begingroup\dodoubleempty\math_stackers_handle_double}
\def\math_stackers_handle_over[#category]%
- {\math_stackers_handle_double\zerocount{\iffirstargument#category\else\v!top \fi}} % will be defined later on
+ {\math_stackers_direct_double\plusone\zerocount{\iffirstargument#category\else\v!top \fi}} % will be defined later on
\def\math_stackers_handle_under[#category]#codepoint#bottomtext%
- {\math_stackers_handle_double\plusone {\iffirstargument#category\else\v!bottom\fi}} % will be defined later on
+ {\math_stackers_direct_double\zerocount\plusone{\iffirstargument#category\else\v!bottom\fi}} % will be defined later on
+
+\def\math_stackers_handle_double[#category]#codepoint#bottomtext%
+ {\math_stackers_direct_double\plusone\plusone {\iffirstargument#category\else\v!bottom\fi}} % will be defined later on
-\def\math_stackers_handle_double#location#category#codepoint#text%
- {\math_stackers_double#location{#category}{#codepoint}{#text}%
+\def\math_stackers_direct_double#top#bottom#category#codepoint#text%
+ {\math_stackers_make_double#top#bottom{#category}{#codepoint}{#text}%
\endgroup}
%D Here is a bonus macro that takes three texts. It can be used to get consistent
@@ -558,20 +593,26 @@
[\c!order=\v!reverse]
\definemathstackers
- [\v!top]
+ [\v!both]
[\v!mathematics]
- [\c!location=\v!top,
+ [\c!location=\v!top, % ?
\c!strut=\v!no,
\c!middlecommand=\mathematics,
\c!hoffset=\zeropoint]
\definemathstackers
+ [\v!top]
+ [\v!both]
+
+\definemathstackers
[\v!bottom]
- [\v!mathematics]
- [\c!location=\v!top, % ?
- \c!strut=\v!no,
- \c!middlecommand=\mathematics,
- \c!hoffset=\zeropoint]
+ [\v!both]
+
+\definemathstackers
+ [vfenced]
+ [\v!both]
+ [\c!mathclass=\s!ord,
+ \c!mathlimits=\v!yes]
% These are compatibity definitions, math only.
@@ -680,8 +721,23 @@
% stuff in the backend (okay, we still need to deal with some cut and paste
% issues but at least we now know what we deal with.
-\definemathunderextensible [\v!bottom] [underbar] ["203E]
-\definemathoverextensible [\v!top] [overbar] ["203E]
+\definemathunderextensible [vfenced] [underbar] ["203E]
+\definemathoverextensible [vfenced] [overbar] ["203E]
+\definemathoverextensible [vfenced] [doublebar] ["203E] ["203E]
+
+\definemathoverextensible [vfenced] [overbrace] ["FE3DE] % ["023DE]
+\definemathunderextensible [vfenced] [underbrace] ["FE3DF] % ["023DF]
+\definemathdoubleextensible [vfenced] [doublebrace] ["FE3DE] ["FE3DF]
+
+\definemathoverextensible [vfenced] [overparent] ["FE3DC] % ["023DC]
+\definemathunderextensible [vfenced] [underparent] ["FE3DD] % ["023DD]
+\definemathdoubleextensible [vfenced] [doubleparent] ["FE3DC] ["FE3DD]
+
+\definemathoverextensible [vfenced] [overbracket] ["FE3B4] % ["023B4]
+\definemathunderextensible [vfenced] [underbracket] ["FE3B5] % ["023B5]
+\definemathdoubleextensible [vfenced] [doublebracket] ["FE3B4] ["FE3B5]
+
+% \unexpanded\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits}
%D Some bonus ones (for the moment here):
diff --git a/tex/context/base/meta-pdf.lua b/tex/context/base/meta-pdf.lua
index e51290e42..c49ad92ae 100644
--- a/tex/context/base/meta-pdf.lua
+++ b/tex/context/base/meta-pdf.lua
@@ -23,6 +23,8 @@ local report_mptopdf = logs.reporter("graphics","mptopdf")
local mplib, metapost, lpdf, context = mplib, metapost, lpdf, context
+local texgetattribute = tex.getattribute
+
local pdfrgbcode = lpdf.rgbcode
local pdfcmykcode = lpdf.cmykcode
local pdfgraycode = lpdf.graycode
@@ -84,7 +86,7 @@ end
local function flushconcat()
if m_stack_concat then
- mpscode(f_concatm(unpack(m_stack_concat)))
+ mpscode(f_concat(unpack(m_stack_concat)))
m_stack_concat = nil
end
end
@@ -539,7 +541,7 @@ function mptopdf.convertmpstopdf(name)
resetall()
local ok, m_data, n = resolvers.loadbinfile(name, 'tex') -- we need a binary load !
if ok then
- mps.colormodel = tex.attribute[a_colorspace]
+ mps.colormodel = texgetattribute(a_colorspace)
statistics.starttiming(mptopdf)
mptopdf.nofconverted = mptopdf.nofconverted + 1
pdfcode(formatters["\\letterpercent\\space mptopdf begin: n=%s, file=%s"](mptopdf.nofconverted,file.basename(name)))
diff --git a/tex/context/base/meta-pdf.mkiv b/tex/context/base/meta-pdf.mkiv
index a8fdaff42..3469419d4 100644
--- a/tex/context/base/meta-pdf.mkiv
+++ b/tex/context/base/meta-pdf.mkiv
@@ -37,7 +37,7 @@
\def\PDFMPformoffset{\ifdefined\objectoffset\objectoffset\else\zeropoint\fi} % obsolete, will go
-\def\convertMPtoPDF#1#2#3% scaling no longer supported at this level (so #2 & #3 are ignored)
+\unexpanded\def\convertMPtoPDF#1#2#3% scaling no longer supported at this level (so #2 & #3 are ignored)
{\dostarttagged\t!mpgraphic\empty
\naturalvbox attr \imageattribute 1 \bgroup
\message{[MP to PDF]}%
diff --git a/tex/context/base/mlib-pps.lua b/tex/context/base/mlib-pps.lua
index 93bddc2dd..4a887150d 100644
--- a/tex/context/base/mlib-pps.lua
+++ b/tex/context/base/mlib-pps.lua
@@ -19,7 +19,8 @@ local formatters = string.formatters
local mplib, metapost, lpdf, context = mplib, metapost, lpdf, context
-local texbox = tex.box
+local texgetbox = tex.getbox
+local texsetbox = tex.setbox
local copy_list = node.copy_list
local free_list = node.flush_list
local setmetatableindex = table.setmetatableindex
@@ -227,8 +228,8 @@ local function freeboxes()
local tn = textexts[n]
if tn then
free_list(tn)
- -- texbox[scratchbox] = tn
- -- texbox[scratchbox] = nil -- this frees too
+ -- texsetbox("scratchbox",tn)
+ -- texsetbox("scratchbox",nil) -- this frees too
if trace_textexts then
report_textexts("freeing box %s",n)
end
@@ -244,15 +245,15 @@ end
metapost.resettextexts = freeboxes
function metapost.settext(box,slot)
- textexts[slot] = copy_list(texbox[box])
- texbox[box] = nil
+ textexts[slot] = copy_list(texgetbox(box))
+ texsetbox(box,nil)
-- this will become
- -- textexts[slot] = texbox[box]
+ -- textexts[slot] = texgetbox(box)
-- unsetbox(box)
end
function metapost.gettext(box,slot)
- texbox[box] = copy_list(textexts[slot])
+ texsetbox(box,copy_list(textexts[slot]))
if trace_textexts then
report_textexts("putting text %s in box %s",slot,box)
end
diff --git a/tex/context/base/mult-de.mkii b/tex/context/base/mult-de.mkii
index 893a9d358..60eccd7f7 100644
--- a/tex/context/base/mult-de.mkii
+++ b/tex/context/base/mult-de.mkii
@@ -801,6 +801,8 @@
\setinterfaceconstant{marking}{beschriftung}
\setinterfaceconstant{marstyle}{beschrstil}
\setinterfaceconstant{mask}{mask}
+\setinterfaceconstant{mathclass}{mathclass}
+\setinterfaceconstant{mathlimits}{mathlimits}
\setinterfaceconstant{mathstyle}{mathstyle}
\setinterfaceconstant{max}{max}
\setinterfaceconstant{maxdepth}{maxdepth}
diff --git a/tex/context/base/mult-def.lua b/tex/context/base/mult-def.lua
index fdb8803bf..10e99888e 100644
--- a/tex/context/base/mult-def.lua
+++ b/tex/context/base/mult-def.lua
@@ -10363,9 +10363,15 @@ return {
["pe"]="بست",
["ro"]="strut",
},
+ ["mathclass"]={
+ ["en"]="mathclass",
+ },
["mathstyle"]={
["en"]="mathstyle",
},
+ ["mathlimits"]={
+ ["en"]="mathlimits",
+ },
["style"]={
["cs"]="pismeno",
["de"]="stil",
diff --git a/tex/context/base/mult-def.mkiv b/tex/context/base/mult-def.mkiv
index cb165b055..6fff33f6a 100644
--- a/tex/context/base/mult-def.mkiv
+++ b/tex/context/base/mult-def.mkiv
@@ -88,6 +88,9 @@
\def\s!current {current}
+\def\s!rel {rel}
+\def\s!ord {ord}
+
\def\c!HL {HL}
\def\c!VL {VL}
\def\c!NL {NL}
diff --git a/tex/context/base/mult-en.mkii b/tex/context/base/mult-en.mkii
index c3ab2fc16..49076741c 100644
--- a/tex/context/base/mult-en.mkii
+++ b/tex/context/base/mult-en.mkii
@@ -801,6 +801,8 @@
\setinterfaceconstant{marking}{marking}
\setinterfaceconstant{marstyle}{marstyle}
\setinterfaceconstant{mask}{mask}
+\setinterfaceconstant{mathclass}{mathclass}
+\setinterfaceconstant{mathlimits}{mathlimits}
\setinterfaceconstant{mathstyle}{mathstyle}
\setinterfaceconstant{max}{max}
\setinterfaceconstant{maxdepth}{maxdepth}
diff --git a/tex/context/base/mult-fr.mkii b/tex/context/base/mult-fr.mkii
index 1ba4f3c8c..945c5f74f 100644
--- a/tex/context/base/mult-fr.mkii
+++ b/tex/context/base/mult-fr.mkii
@@ -801,6 +801,8 @@
\setinterfaceconstant{marking}{marquage}
\setinterfaceconstant{marstyle}{stylemarquage}
\setinterfaceconstant{mask}{mask}
+\setinterfaceconstant{mathclass}{mathclass}
+\setinterfaceconstant{mathlimits}{mathlimits}
\setinterfaceconstant{mathstyle}{mathstyle}
\setinterfaceconstant{max}{max}
\setinterfaceconstant{maxdepth}{maxdepth}
diff --git a/tex/context/base/mult-it.mkii b/tex/context/base/mult-it.mkii
index 0d1ea911d..20fe0be3f 100644
--- a/tex/context/base/mult-it.mkii
+++ b/tex/context/base/mult-it.mkii
@@ -801,6 +801,8 @@
\setinterfaceconstant{marking}{marcatura}
\setinterfaceconstant{marstyle}{stilemarcatura}
\setinterfaceconstant{mask}{mask}
+\setinterfaceconstant{mathclass}{mathclass}
+\setinterfaceconstant{mathlimits}{mathlimits}
\setinterfaceconstant{mathstyle}{mathstyle}
\setinterfaceconstant{max}{max}
\setinterfaceconstant{maxdepth}{maxdepth}
diff --git a/tex/context/base/mult-nl.mkii b/tex/context/base/mult-nl.mkii
index 5f1bada7a..11c25f4e9 100644
--- a/tex/context/base/mult-nl.mkii
+++ b/tex/context/base/mult-nl.mkii
@@ -801,6 +801,8 @@
\setinterfaceconstant{marking}{markering}
\setinterfaceconstant{marstyle}{marletter}
\setinterfaceconstant{mask}{masker}
+\setinterfaceconstant{mathclass}{mathclass}
+\setinterfaceconstant{mathlimits}{mathlimits}
\setinterfaceconstant{mathstyle}{mathstyle}
\setinterfaceconstant{max}{max}
\setinterfaceconstant{maxdepth}{maxdepth}
diff --git a/tex/context/base/mult-pe.mkii b/tex/context/base/mult-pe.mkii
index f55a7ab59..39ae60042 100644
--- a/tex/context/base/mult-pe.mkii
+++ b/tex/context/base/mult-pe.mkii
@@ -801,6 +801,8 @@
\setinterfaceconstant{marking}{نشانه‌گذاری}
\setinterfaceconstant{marstyle}{سبک‌حاش}
\setinterfaceconstant{mask}{mask}
+\setinterfaceconstant{mathclass}{mathclass}
+\setinterfaceconstant{mathlimits}{mathlimits}
\setinterfaceconstant{mathstyle}{mathstyle}
\setinterfaceconstant{max}{بیشترین}
\setinterfaceconstant{maxdepth}{maxdepth}
diff --git a/tex/context/base/mult-ro.mkii b/tex/context/base/mult-ro.mkii
index 34dd385a3..f61321e8b 100644
--- a/tex/context/base/mult-ro.mkii
+++ b/tex/context/base/mult-ro.mkii
@@ -801,6 +801,8 @@
\setinterfaceconstant{marking}{marcaje}
\setinterfaceconstant{marstyle}{stilmarcaj}
\setinterfaceconstant{mask}{mask}
+\setinterfaceconstant{mathclass}{mathclass}
+\setinterfaceconstant{mathlimits}{mathlimits}
\setinterfaceconstant{mathstyle}{mathstyle}
\setinterfaceconstant{max}{max}
\setinterfaceconstant{maxdepth}{maxdepth}
diff --git a/tex/context/base/mult-sys.mkiv b/tex/context/base/mult-sys.mkiv
index f0db9fa67..74e4d70ea 100644
--- a/tex/context/base/mult-sys.mkiv
+++ b/tex/context/base/mult-sys.mkiv
@@ -163,6 +163,9 @@
\definesystemconstant {both}
+\definesystemconstant {internal}
+\definesystemconstant {external}
+
\definesystemconstant {attribute}
\definesystemconstant {none}
diff --git a/tex/context/base/node-acc.lua b/tex/context/base/node-acc.lua
index 4380ec3a4..81ae496b2 100644
--- a/tex/context/base/node-acc.lua
+++ b/tex/context/base/node-acc.lua
@@ -35,7 +35,7 @@ local function injectspaces(head)
while n do
local id = n.id
if id == glue_code then -- todo: check for subtype related to spacing (13/14 but most seems to be 0)
---~ if n.spec.width > 0 then -- threshold
+ -- if n.spec.width > 0 then -- threshold
if p and p.id == glyph_code then
local g = copy_node(p)
local c = g.components
@@ -56,7 +56,7 @@ local function injectspaces(head)
s[a_characters] = 0
n[a_characters] = 0
end
---~ end
+ -- end
elseif id == hlist_code or id == vlist_code then
injectspaces(n.list,attribute)
-- elseif id == kern_code then -- the backend already collapses
@@ -83,58 +83,58 @@ nodes.handlers.accessibility = injectspaces
-- todo:
---~ local a_hyphenated = attributes.private('hyphenated')
---~
---~ local hyphenated, codes = { }, { }
---~
---~ local function compact(n)
---~ local t = { }
---~ for n in traverse_id(glyph_code,n) do
---~ t[#t+1] = utfchar(n.char) -- check for unicode
---~ end
---~ return concat(t,"")
---~ end
---~
---~ local function injectspans(head)
---~ for n in traverse_nodes(head) do
---~ local id = n.id
---~ if id == disc then
---~ local r, p = n.replace, n.pre
---~ if r and p then
---~ local str = compact(r)
---~ local hsh = hyphenated[str]
---~ if not hsh then
---~ hsh = #codes + 1
---~ hyphenated[str] = hsh
---~ codes[hsh] = str
---~ end
---~ n[a_hyphenated] = hsh
---~ end
---~ elseif id == hlist_code or id == vlist_code then
---~ injectspans(n.list)
---~ end
---~ end
---~ return head, true
---~ end
---~
---~ nodes.injectspans = injectspans
---~
---~ tasks.appendaction("processors", "words", "nodes.injectspans")
---~
---~ local function injectspans(head)
---~ for n in traverse_nodes(head) do
---~ local id = n.id
---~ if id == disc then
---~ local a = n[a_hyphenated]
---~ if a then
---~ local str = codes[a]
---~ local b = new_pdfliteral(format("/Span << /ActualText %s >> BDC", lpdf.tosixteen(str)))
---~ local e = new_pdfliteral("EMC")
---~ node.insert_before(head,n,b)
---~ node.insert_after(head,n,e)
---~ end
---~ elseif id == hlist_code or id == vlist_code then
---~ injectspans(n.list)
---~ end
---~ end
---~ end
+-- local a_hyphenated = attributes.private('hyphenated')
+--
+-- local hyphenated, codes = { }, { }
+--
+-- local function compact(n)
+-- local t = { }
+-- for n in traverse_id(glyph_code,n) do
+-- t[#t+1] = utfchar(n.char) -- check for unicode
+-- end
+-- return concat(t,"")
+-- end
+--
+-- local function injectspans(head)
+-- for n in traverse_nodes(head) do
+-- local id = n.id
+-- if id == disc then
+-- local r, p = n.replace, n.pre
+-- if r and p then
+-- local str = compact(r)
+-- local hsh = hyphenated[str]
+-- if not hsh then
+-- hsh = #codes + 1
+-- hyphenated[str] = hsh
+-- codes[hsh] = str
+-- end
+-- n[a_hyphenated] = hsh
+-- end
+-- elseif id == hlist_code or id == vlist_code then
+-- injectspans(n.list)
+-- end
+-- end
+-- return head, true
+-- end
+--
+-- nodes.injectspans = injectspans
+--
+-- tasks.appendaction("processors", "words", "nodes.injectspans")
+--
+-- local function injectspans(head)
+-- for n in traverse_nodes(head) do
+-- local id = n.id
+-- if id == disc then
+-- local a = n[a_hyphenated]
+-- if a then
+-- local str = codes[a]
+-- local b = new_pdfliteral(format("/Span << /ActualText %s >> BDC", lpdf.tosixteen(str)))
+-- local e = new_pdfliteral("EMC")
+-- node.insert_before(head,n,b)
+-- node.insert_after(head,n,e)
+-- end
+-- elseif id == hlist_code or id == vlist_code then
+-- injectspans(n.list)
+-- end
+-- end
+-- end
diff --git a/tex/context/base/node-aux.lua b/tex/context/base/node-aux.lua
index e3fc7ad6f..16e6d55a0 100644
--- a/tex/context/base/node-aux.lua
+++ b/tex/context/base/node-aux.lua
@@ -43,7 +43,7 @@ local unsetvalue = attributes.unsetvalue
local current_font = font.current
-local texbox = tex.box
+local texgetbox = tex.getbox
local report_error = logs.reporter("node-aux:error")
@@ -195,7 +195,7 @@ function nodes.firstcharacter(n,untagged) -- tagged == subtype > 255
end
function nodes.firstcharinbox(n)
- local l = texbox[n].list
+ local l = texgetbox(n).list
if l then
for g in traverse_id(glyph_code,l) do
return g.char
@@ -369,21 +369,3 @@ local function locate(start,wantedid,wantedsubtype)
end
nodes.locate = locate
-
-function nodes.concat(list)
- local head, tail
- for i=1,#list do
- local li = list[i]
- if not li then
- -- skip
- elseif head then
- tail.next = li
- li.prev = tail
- tail = li.next and slide_nodes(li) or li
- else
- head = li
- tail = li.next and slide_nodes(li) or li
- end
- end
- return head, tail
-end
diff --git a/tex/context/base/node-fnt.lua b/tex/context/base/node-fnt.lua
index 54359117e..6d5ed6ca0 100644
--- a/tex/context/base/node-fnt.lua
+++ b/tex/context/base/node-fnt.lua
@@ -48,12 +48,31 @@ local run = 0
local setfontdynamics = { }
local fontprocesses = { }
+-- setmetatableindex(setfontdynamics, function(t,font)
+-- local tfmdata = fontdata[font]
+-- local shared = tfmdata.shared
+-- local v = shared and shared.dynamics and otf.setdynamics or false
+-- t[font] = v
+-- return v
+-- end)
+
setmetatableindex(setfontdynamics, function(t,font)
local tfmdata = fontdata[font]
local shared = tfmdata.shared
- local v = shared and shared.dynamics and otf.setdynamics or false
- t[font] = v
- return v
+ local f = shared and shared.dynamics and otf.setdynamics or false
+ if f then
+ local v = { }
+ t[font] = v
+ setmetatableindex(v,function(t,k)
+ local v = f(font,k)
+ t[k] = v
+ return v
+ end)
+ return v
+ else
+ t[font] = false
+ return false
+ end
end)
setmetatableindex(fontprocesses, function(t,font)
@@ -75,8 +94,8 @@ fonts.hashes.processes = fontprocesses
function handlers.characters(head)
-- either next or not, but definitely no already processed list
starttiming(nodes)
- local usedfonts, attrfonts, done = { }, { }, false
- local a, u, prevfont, prevattr = 0, 0, nil, 0
+ local usedfonts, attrfonts = { }, { }
+ local a, u, prevfont, prevattr, done = 0, 0, nil, 0, false
if trace_fontrun then
run = run + 1
report_fonts()
@@ -107,16 +126,8 @@ function handlers.characters(head)
attrfonts[font] = used
end
if not used[attr] then
- local sd = setfontdynamics[font]
- if sd then -- always true ?
- local d = sd(font,attr) -- can we cache this one?
- if d then
- used[attr] = d
- a = a + 1
- else
- -- can't happen ... otherwise best use nil/false distinction
- end
- end
+ used[attr] = setfontdynamics[font][attr]
+ a = a + 1
end
else
local used = usedfonts[font]
@@ -125,9 +136,7 @@ function handlers.characters(head)
if fp then
usedfonts[font] = fp
u = u + 1
- else
- -- can't happen ... otherwise best use nil/false distinction
- end
+ end
end
end
prevfont = font
@@ -141,34 +150,25 @@ function handlers.characters(head)
report_fonts("dynamics: %s",(a > 0 and concat(keys(attrfonts)," ")) or "none")
report_fonts()
end
+ -- in context we always have at least 2 processors
if u == 0 then
-- skip
elseif u == 1 then
local font, processors = next(usedfonts)
- local n = #processors
- if n > 0 then
- local h, d = processors[1](head,font,0)
- head = h or head
- done = done or d
- if n > 1 then
- for i=2,n do
- local h, d = processors[i](head,font,0)
- head = h or head
- done = done or d
- end
+ for i=1,#processors do
+ local h, d = processors[i](head,font,0)
+ if d then
+ head = h or head
+ done = true
end
end
else
for font, processors in next, usedfonts do
- local n = #processors
- local h, d = processors[1](head,font,0)
- head = h or head
- done = done or d
- if n > 1 then
- for i=2,n do
- local h, d = processors[i](head,font,0)
+ for i=1,#processors do
+ local h, d = processors[i](head,font,0)
+ if d then
head = h or head
- done = done or d
+ done = true
end
end
end
@@ -178,38 +178,22 @@ function handlers.characters(head)
elseif a == 1 then
local font, dynamics = next(attrfonts)
for attribute, processors in next, dynamics do -- attr can switch in between
- local n = #processors
- if n == 0 then
- report_fonts("no processors associated with dynamic %s",attribute)
- else
- local h, d = processors[1](head,font,attribute)
- head = h or head
- done = done or d
- if n > 1 then
- for i=2,n do
- local h, d = processors[i](head,font,attribute)
- head = h or head
- done = done or d
- end
+ for i=1,#processors do
+ local h, d = processors[i](head,font,attribute)
+ if d then
+ head = h or head
+ done = true
end
end
end
else
for font, dynamics in next, attrfonts do
for attribute, processors in next, dynamics do -- attr can switch in between
- local n = #processors
- if n == 0 then
- report_fonts("no processors associated with dynamic %s",attribute)
- else
- local h, d = processors[1](head,font,attribute)
- head = h or head
- done = done or d
- if n > 1 then
- for i=2,n do
- local h, d = processors[i](head,font,attribute)
- head = h or head
- done = done or d
- end
+ for i=1,#processors do
+ local h, d = processors[i](head,font,attribute)
+ if d then
+ head = h or head
+ done = true
end
end
end
@@ -222,5 +206,178 @@ function handlers.characters(head)
return head, true
end
+
+-- local formatters = string.formatters
+
+-- local function make(processors,font,attribute)
+-- _G.__temp = processors
+-- local t = { }
+-- for i=1,#processors do
+-- if processors[i] then
+-- t[#t+1] = formatters["local p_%s = _G.__temp[%s]"](i,i)
+-- end
+-- end
+-- t[#t+1] = "return function(head,done)"
+-- if #processors == 1 then
+-- t[#t+1] = formatters["return p_%s(head,%s,%s)"](1,font,attribute or 0)
+-- else
+-- for i=1,#processors do
+-- if processors[i] then
+-- t[#t+1] = formatters["local h,d=p_%s(head,%s,%s) if d then head=h or head done=true end"](i,font,attribute or 0)
+-- end
+-- end
+-- t[#t+1] = "return head, done"
+-- end
+-- t[#t+1] = "end"
+-- t = concat(t,"\n")
+-- t = load(t)(processors)
+-- _G.__temp = nil
+-- return t
+-- end
+
+-- setmetatableindex(fontprocesses, function(t,font)
+-- local tfmdata = fontdata[font]
+-- local shared = tfmdata.shared -- we need to check shared, only when same features
+-- local processes = shared and shared.processes
+-- if processes and #processes > 0 then
+-- processes = make(processes,font,0)
+-- t[font] = processes
+-- return processes
+-- else
+-- t[font] = false
+-- return false
+-- end
+-- end)
+
+-- setmetatableindex(setfontdynamics, function(t,font)
+-- local tfmdata = fontdata[font]
+-- local shared = tfmdata.shared
+-- local f = shared and shared.dynamics and otf.setdynamics or false
+-- if f then
+-- local v = { }
+-- t[font] = v
+-- setmetatableindex(v,function(t,k)
+-- local v = f(font,k)
+-- v = make(v,font,k)
+-- t[k] = v
+-- return v
+-- end)
+-- return v
+-- else
+-- t[font] = false
+-- return false
+-- end
+-- end)
+
+-- function handlers.characters(head)
+-- -- either next or not, but definitely no already processed list
+-- starttiming(nodes)
+-- local usedfonts, attrfonts
+-- local a, u, prevfont, prevattr, done = 0, 0, nil, 0, false
+-- if trace_fontrun then
+-- run = run + 1
+-- report_fonts()
+-- report_fonts("checking node list, run %s",run)
+-- report_fonts()
+-- local n = head
+-- while n do
+-- local id = n.id
+-- if id == glyph_code then
+-- local font = n.font
+-- local attr = n[0] or 0
+-- report_fonts("font %03i, dynamic %03i, glyph %s",font,attr,utf.char(n.char))
+-- else
+-- report_fonts("[%s]",nodecodes[n.id])
+-- end
+-- n = n.next
+-- end
+-- end
+-- for n in traverse_id(glyph_code,head) do
+-- -- if n.subtype<256 then -- all are 1
+-- local font = n.font
+-- local attr = n[0] or 0 -- zero attribute is reserved for fonts in context
+-- if font ~= prevfont or attr ~= prevattr then
+-- if attr > 0 then
+-- if not attrfonts then
+-- attrfonts = {
+-- [font] = {
+-- [attr] = setfontdynamics[font][attr]
+-- }
+-- }
+-- a = 1
+-- else
+-- local used = attrfonts[font]
+-- if not used then
+-- attrfonts[font] = {
+-- [attr] = setfontdynamics[font][attr]
+-- }
+-- a = a + 1
+-- elseif not used[attr] then
+-- used[attr] = setfontdynamics[font][attr]
+-- a = a + 1
+-- end
+-- end
+-- else
+-- if not usedfonts then
+-- local fp = fontprocesses[font]
+-- if fp then
+-- usedfonts = {
+-- [font] = fp
+-- }
+-- u = 1
+-- end
+-- else
+-- local used = usedfonts[font]
+-- if not used then
+-- local fp = fontprocesses[font]
+-- if fp then
+-- usedfonts[font] = fp
+-- u = u + 1
+-- end
+-- end
+-- end
+-- end
+-- prevfont = font
+-- prevattr = attr
+-- end
+-- -- end
+-- end
+-- if trace_fontrun then
+-- report_fonts()
+-- report_fonts("statics : %s",(u > 0 and concat(keys(usedfonts)," ")) or "none")
+-- report_fonts("dynamics: %s",(a > 0 and concat(keys(attrfonts)," ")) or "none")
+-- report_fonts()
+-- end
+-- if not usedfonts then
+-- -- skip
+-- elseif u == 1 then
+-- local font, processors = next(usedfonts)
+-- head, done = processors(head,done)
+-- else
+-- for font, processors in next, usedfonts do
+-- head, done = processors(head,done)
+-- end
+-- end
+-- if not attrfonts then
+-- -- skip
+-- elseif a == 1 then
+-- local font, dynamics = next(attrfonts)
+-- for attribute, processors in next, dynamics do
+-- head, done = processors(head,done)
+-- end
+-- else
+-- for font, dynamics in next, attrfonts do
+-- for attribute, processors in next, dynamics do
+-- head, done = processors(head,done)
+-- end
+-- end
+-- end
+-- stoptiming(nodes)
+-- if trace_characters then
+-- nodes.report(head,done)
+-- end
+-- return head, true
+-- end
+
handlers.protectglyphs = node.protect_glyphs
handlers.unprotectglyphs = node.unprotect_glyphs
diff --git a/tex/context/base/node-ini.lua b/tex/context/base/node-ini.lua
index 5a3986c3a..ae50215cb 100644
--- a/tex/context/base/node-ini.lua
+++ b/tex/context/base/node-ini.lua
@@ -13,13 +13,10 @@ modules.</p>
-- this module is being reconstructed
-local next, type = next, type
-local format, match, gsub = string.format, string.match, string.gsub
+local next, type, tostring = next, type, tostring
+local gsub = 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
+local sortedhash, sortedkeys, swapped = table.sortedhash, table.sortedkeys, table.swapped
--[[ldx--
<p>Access to nodes is what gives <l n='luatex'/> its power. Here we
@@ -54,20 +51,12 @@ into the <l n='tex'/> engine, but this is a not so natural extension.</p>
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 { }
-nodes = nodes or { }
-local nodes = nodes
-
-nodes.handlers = nodes.handlers or { }
+local allocate = utilities.storage.allocate
+local formatcolumns = utilities.formatters.formatcolumns
-- there will be more of this:
@@ -248,174 +237,4 @@ function nodes.showcodes()
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
diff --git a/tex/context/base/node-ini.mkiv b/tex/context/base/node-ini.mkiv
index 39d48a00a..e99653327 100644
--- a/tex/context/base/node-ini.mkiv
+++ b/tex/context/base/node-ini.mkiv
@@ -18,6 +18,10 @@
\newcount\filterstate \filterstate\plusone % hm, public
\registerctxluafile{node-ini}{1.001}
+\registerctxluafile{node-met}{1.001}
+
+\ctxlua{if nodes.gonuts then context.registerctxluafile("node-nut","1.001") end}
+
\registerctxluafile{node-res}{1.001}
\registerctxluafile{node-dir}{1.001}
\registerctxluafile{node-aux}{1.001}
diff --git a/tex/context/base/node-inj.lua b/tex/context/base/node-inj.lua
index 697370cfb..abbe9b449 100644
--- a/tex/context/base/node-inj.lua
+++ b/tex/context/base/node-inj.lua
@@ -11,6 +11,8 @@ if not modules then modules = { } end modules ['node-inj'] = {
-- test fonts. Btw, future versions of luatex will have extended glyph properties
-- that can be of help. Some optimizations can go away when we have faster machines.
+-- todo: make a special one for context
+
local next = next
local utfchar = utf.char
diff --git a/tex/context/base/node-ltp.lua b/tex/context/base/node-ltp.lua
new file mode 100644
index 000000000..97e61cf18
--- /dev/null
+++ b/tex/context/base/node-ltp.lua
@@ -0,0 +1,3207 @@
+if not modules then modules = { } end modules ['node-par'] = {
+ version = 1.001,
+ comment = "companion to node-par.mkiv",
+ author = "Hans Hagen",
+ copyright = "ConTeXt Development Team",
+ license = "see context related readme files",
+ comment = "a translation of the built in parbuilder, initial convertsin by Taco Hoekwater",
+}
+
+-- todo: remove nest_stack from linebreak.w
+-- todo: use ex field as signal (index in ?)
+-- todo: attr driven unknown/on/off
+-- todo: permit global steps i.e. using an attribute that sets min/max/step and overloads the font parameters
+-- todo: split the three passes into three functions
+-- todo: simplify the direction stack, no copy needed
+-- todo: add more mkiv like tracing
+-- todo: add a couple of plugin hooks
+-- todo: maybe split expansion code paths
+-- todo: fix line numbers (cur_list.pg_field needed)
+-- todo: make kerns stretch an option and disable it by default (definitely not shrink)
+-- todo: check and improve protrusion
+-- todo: arabic etc (we could use pretty large scales there) .. marks and cursive
+
+--[[
+
+ This code is derived from traditional TeX and has bits of pdfTeX, Aleph (Omega), and of course LuaTeX. So,
+ the basic algorithm for sure is not our work. On the other hand, the directional model in LuaTeX is cleaned
+ up as is other code. And of course there are hooks for callbacks.
+
+ The first version of the code below was a conversion of the C code that in turn was a conversion from the
+ original Pascal code. Around September 2008 we experimented with cq. discussed possible approaches to improved
+ typesetting of Arabic and as our policy is that extensions happen in Lua this means that we need a parbuilder
+ in Lua. Taco's first conversion still looked quite C-ish and in the process of cleaning up we uncovered some odd
+ bits and pieces in the original code as well. I did some first cleanup to get rid of C-artefacts, and Taco and I
+ spent the usual amount of Skyping to sort out problems. At that point we diverted to other LuaTeX issues.
+
+ A while later I decided to pick up this thread and decided to look into better ways to deal with font expansion
+ (aka hz). I got it running using a simpler method. One reason why the built-in mechanims is slow is that there is
+ lots of redudancy in calculations. Expanded widths are recalculated each time and because the hpakc routine does
+ it again that gives some overhead. In the process extra fonts are created with different dimensions so that the
+ backend can deal with it. The alternative method doesn't create fonts but passes an expansion factor to the
+ pdf generator. The small patch needed for the backend code worked more or less okay but was never intergated into
+ LuaTeX due to lack of time.
+
+ This all happened in 2010 while listening to Peter Gabriels "Scratch My Back" and Camels "Rayaz" so it was a
+ rather relaxed job.
+
+ In 2012 I picked up this thread. Because both languages are similar but also quite different it took some time
+ to get compatible output. Because the C code uses macros, careful checking was needed. Of course Lua's table model
+ and local variables brought some work as well. And still the code looks a bit C-ish. We could not divert too much
+ from the original model simply because it's well documented but future versions (or variants) might as well look
+ different.
+
+ Eventually I'll split this code into passes so that we can better see what happens, but first we need to reach
+ a decent level of stability. The current expansion results are not the same as the built-in but that was never
+ the objective. It all has to do with slightly different calculations.
+
+ The original C-code related to protrusion and expansion is not that efficient as many (redundant) function
+ calls take place in the linebreaker and packer. As most work related to fonts is done in the backend, we
+ can simply stick to width calculations here. Also, it is no problem at all that we use floating point
+ calculations (as Lua has only floats). The final result will look ok as the hpack will nicely compensate
+ for rounding errors as it will normally distribute the content well enough. And let's admit: most texies
+ won't see it anyway. As long as we're cross platform compatible it's fine.
+
+ We use the table checked_expansion to keep track of font related parameters (per paragraph). The table is
+ also the signal that we have adjustments > 1. In retrospect one might wonder if adjusting kerns is such a
+ good idea because other spacing is also not treated. If we would stick to the regular hpack routine
+ we do have to follow the same logic, but I decided to use a Lua hpacker so that constraint went away. And
+ anyway, instead of doing a lookup in the kern table (that we don't have in node mode) the set kern value
+ is used. Disabling kern scaling will become an option in Luatex some day. You can blame me for all errors
+ that crept in and I know that there are some.
+
+ To be honest, I slowly start to grasp the magic here as normally I start from scratch when implementing
+ something (as it's the only way I can understand things). This time I had a recently acquired stack of
+ Porcupine Tree disks to get me through.
+
+ Picking up this effort was inspired by discussions between Luigi Scarso and me about efficiency of Lua
+ code and we needed some stress tests to compare regular LuaTeX and LuajitTeX. One of the tests was
+ processing tufte.tex as that one has lots of hyphenations and is a tough one to get right.
+
+ tufte: boxed 1000 times, no flushing in backend:
+
+ \testfeatureonce{1000}{\setbox0\hbox{\tufte}}
+ \testfeatureonce{1000}{\setbox0\vbox{\tufte}}
+ \startparbuilder[basic]\testfeatureonce{1000}{\setbox0\vbox{\tufte}}\stopparbuilder
+
+ method normal hz comment
+
+ luatex tex hbox 9.64 9.64 baseline font feature processing, hyphenation etc: 9.74
+ tex vbox 9.84 10.16 0.20 linebreak / 0.52 with hz -> 0.32 hz overhead (150pct more)
+ lua vbox 17.28 18.43 7.64 linebreak / 8.79 with hz -> 1.33 hz overhead ( 20pct more)
+
+ luajittex tex hbox 6.33 6.33 baseline font feature processing, hyphenation etc: 6.33
+ tex vbox 6.53 6.81 0.20 linebreak / 0.48 with hz -> 0.28 hz overhead (expected 0.32)
+ lua vbox 11.06 11.81 4.53 linebreak / 5.28 with hz -> 0.75 hz overhead
+
+ Interesting is that the runtime for the built-in parbuilder indeed increases much when expansion
+ is enabled, but in the Lua variant the extra overhead is way less significant. This means that when we
+ retrofit the same approach into the core, the overhead of expansion can be sort of nilled.
+
+]]--
+
+local utfchar = utf.char
+local write, write_nl = texio.write, texio.write_nl
+local sub, format = string.sub, string.format
+local round = math.round
+local insert, remove = table.insert, table.remove
+
+local fonts, nodes, node = fonts, nodes, node
+
+local trace_basic = false trackers.register("builders.paragraphs.basic", function(v) trace_basic = v end)
+local trace_lastlinefit = false trackers.register("builders.paragraphs.lastlinefit", function(v) trace_lastlinefit = v end)
+local trace_adjusting = false trackers.register("builders.paragraphs.adjusting", function(v) trace_adjusting = v end)
+local trace_protruding = false trackers.register("builders.paragraphs.protruding", function(v) trace_protruding = v end)
+local trace_expansion = false trackers.register("builders.paragraphs.expansion", function(v) trace_expansion = v end)
+local trace_quality = false trackers.register("builders.paragraphs.quality", function(v) trace_quality = v end)
+
+local report_parbuilders = logs.reporter("nodes","parbuilders")
+local report_hpackers = logs.reporter("nodes","hpackers")
+
+local calculate_badness = tex.badness
+local texnest = tex.nest
+local texlists = tex.lists
+
+-- (t == 0 and 0) or (s <= 0 and 10000) or calculate_badness(t,s)
+
+-- local function calculate_badness(t,s)
+-- if t == 0 then
+-- return 0
+-- elseif s <= 0 then
+-- return 10000 -- infinite_badness
+-- else
+-- local r
+-- if t <= 7230584 then
+-- r = (t * 297) / s
+-- elseif s >= 1663497 then
+-- r = t / (s / 297)
+-- else
+-- r = t
+-- end
+-- if r > 1290 then
+-- return 10000 -- infinite_badness
+-- else
+-- return (r * r * r + 0x20000) / 0x40000
+-- end
+-- end
+-- end
+
+local parbuilders = builders.paragraphs
+local constructors = parbuilders.constructors
+
+local setmetatableindex = table.setmetatableindex
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local chardata = fonthashes.characters
+local quaddata = fonthashes.quads
+local parameters = fonthashes.parameters
+
+local slide_nodes = node.slide
+local new_node = node.new
+local copy_node = node.copy
+local copy_node_list = node.copy_list
+local flush_node = node.free
+local flush_node_list = node.flush_list
+local hpack_nodes = node.hpack
+local xpack_nodes = node.hpack
+local replace_node = nodes.replace
+local insert_node_after = node.insert_after
+local insert_node_before = node.insert_before
+local traverse_by_id = node.traverse_id
+
+local setnodecolor = nodes.tracers.colors.set
+
+local nodepool = nodes.pool
+
+local nodecodes = nodes.nodecodes
+local whatcodes = nodes.whatcodes
+local kerncodes = nodes.kerncodes
+local glyphcodes = nodes.glyphcodes
+local gluecodes = nodes.gluecodes
+local margincodes = nodes.margincodes
+local disccodes = nodes.disccodes
+local mathcodes = nodes.mathcodes
+local fillcodes = nodes.fillcodes
+
+local temp_code = nodecodes.temp
+local glyph_code = nodecodes.glyph
+local ins_code = nodecodes.ins
+local mark_code = nodecodes.mark
+local adjust_code = nodecodes.adjust
+local penalty_code = nodecodes.penalty
+local whatsit_code = nodecodes.whatsit
+local disc_code = nodecodes.disc
+local math_code = nodecodes.math
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local unset_code = nodecodes.unset
+local marginkern_code = nodecodes.marginkern
+
+local leaders_code = gluecodes.leaders
+
+local localpar_code = whatcodes.localpar
+local dir_code = whatcodes.dir
+local pdfrefximage_code = whatcodes.pdfrefximage
+local pdfrefxform_code = whatcodes.pdfrefxform
+
+local kerning_code = kerncodes.kerning -- font kern
+local userkern_code = kerncodes.userkern
+
+local ligature_code = glyphcodes.ligature
+
+local stretch_orders = nodes.fillcodes
+
+local leftmargin_code = margincodes.left
+local rightmargin_code = margincodes.right
+
+local automatic_disc_code = disccodes.automatic
+local regular_disc_code = disccodes.regular
+local first_disc_code = disccodes.first
+local second_disc_code = disccodes.second
+
+local endmath_code = mathcodes.endmath
+
+local nosubtype_code = 0
+
+local unhyphenated_code = nodecodes.unhyphenated or 1
+local hyphenated_code = nodecodes.hyphenated or 2
+local delta_code = nodecodes.delta or 3
+local passive_code = nodecodes.passive or 4
+
+local maxdimen = number.maxdimen
+
+local max_halfword = 0x7FFFFFFF
+local infinite_penalty = 10000
+local eject_penalty = -10000
+local infinite_badness = 10000
+local awful_badness = 0x3FFFFFFF
+
+local fit_very_loose_class = 0 -- fitness for lines stretching more than their stretchability
+local fit_loose_class = 1 -- fitness for lines stretching 0.5 to 1.0 of their stretchability
+local fit_decent_class = 2 -- fitness for all other lines
+local fit_tight_class = 3 -- fitness for lines shrinking 0.5 to 1.0 of their shrinkability
+
+local new_penalty = nodepool.penalty
+local new_dir = nodepool.textdir
+local new_leftmarginkern = nodepool.leftmarginkern
+local new_rightmarginkern = nodepool.rightmarginkern
+local new_leftskip = nodepool.leftskip
+local new_rightskip = nodepool.rightskip
+local new_lineskip = nodepool.lineskip
+local new_baselineskip = nodepool.baselineskip
+local new_temp = nodepool.temp
+local new_rule = nodepool.rule
+
+local is_rotated = nodes.is_rotated
+local is_parallel = nodes.textdir_is_parallel
+local is_opposite = nodes.textdir_is_opposite
+local textdir_is_equal = nodes.textdir_is_equal
+local pardir_is_equal = nodes.pardir_is_equal
+local glyphdir_is_equal = nodes.glyphdir_is_equal
+
+local dir_pops = nodes.dir_is_pop
+local dir_negations = nodes.dir_negation
+local is_skipable = node.protrusion_skippable
+
+-- helpers --
+
+-- It makes more sense to move the somewhat messy dir state tracking
+-- out of the main functions. First we create a stack allocator.
+
+local function new_dir_stack(dir) -- also use elsewhere
+ return { n = 0, dir }
+end
+
+-- The next function checks a dir node and returns the new dir state. By
+-- using s static table we are quite efficient. This function is used
+-- in the parbuilder.
+
+local function checked_line_dir(stack,current)
+ if not dir_pops[current] then
+ local n = stack.n + 1
+ stack.n = n
+ stack[n] = current
+ return current.dir
+ elseif n > 0 then
+ local n = stack.n
+ local dirnode = stack[n]
+ dirstack.n = n - 1
+ return dirnode.dir
+ else
+ report_parbuilders("warning: missing pop node (%a)",1) -- in line ...
+ end
+end
+
+-- The next function checks a dir nodes in a list and appends the negations
+-- that are currently needed (some day LuaTeX will be more tolerant). We use
+-- the negations for the next line.
+
+local function inject_dirs_at_end_of_line(stack,current,start,stop)
+ local e = start
+ local n = stack.n
+ local h = nil
+ while start and start ~= stop do
+ if start.id == whatsit_code and start.subtype == dir_code then
+ if not dir_pops[start.dir] then
+ n = n + 1
+ stack[n] = start
+ elseif n > 0 then
+ n = n - 1
+ else
+ report_parbuilders("warning: missing pop node (%a)",2) -- in line ...
+ end
+ end
+ start = start.next
+ end
+ for i=n,1,-1 do
+ h, current = insert_node_after(current,current,new_dir(dir_negations[stack[i].dir]))
+ end
+ stack.n = n
+ return current
+end
+
+local function inject_dirs_at_begin_of_line(stack,current)
+ local h = nil
+ for i=stack.n,1,-1 do
+ h, current = insert_node_after(current,current,new_dir(stack[i]))
+ end
+ stack.n = 0
+ return current
+end
+
+-- diagnostics --
+
+local dummy = function() end
+
+local diagnostics = {
+ start = dummy,
+ stop = dummy,
+ current_pass = dummy,
+ break_node = dummy,
+ feasible_break = dummy,
+}
+
+-- statistics --
+
+local nofpars, noflines, nofprotrudedlines, nofadjustedlines = 0, 0, 0, 0
+
+local function register_statistics(par)
+ local statistics = par.statistics
+ nofpars = nofpars + 1
+ noflines = noflines + statistics.noflines
+ nofprotrudedlines = nofprotrudedlines + statistics.nofprotrudedlines
+ nofadjustedlines = nofadjustedlines + statistics.nofadjustedlines
+end
+
+-- resolvers --
+
+local whatsiters = {
+ get_width = { },
+ get_dimensions = { },
+}
+
+local get_whatsit_width = whatsiters.get_width
+local get_whatsit_dimensions = whatsiters.get_dimensions
+
+local function get_width (n) return n.width end
+local function get_dimensions(n) return n.width, n.height, n.depth end
+
+get_whatsit_width[pdfrefximage_code] = get_width
+get_whatsit_width[pdfrefxform_code ] = get_width
+
+get_whatsit_dimensions[pdfrefximage_code] = get_dimensions
+get_whatsit_dimensions[pdfrefxform_code ] = get_dimensions
+
+-- expansion etc --
+
+local function calculate_fraction(x,n,d,max_answer)
+ local the_answer = x * n/d + 1/2 -- round ?
+ if the_answer > max_answer then
+ return max_answer
+ elseif the_answer < -max_answer then
+ return -max_answer
+ else
+ return the_answer
+ end
+end
+
+local function check_shrinkage(par,n)
+ -- called often, so maybe move inline
+ if n.shrink_order ~= 0 and n.shrink ~= 0 then
+ if par.no_shrink_error_yet then
+ par.no_shrink_error_yet = false
+ report_parbuilders("infinite glue shrinkage found in a paragraph and removed")
+ end
+ n = copy_node(n)
+ n.shrink_order = 0
+ end
+ return n
+end
+
+-- It doesn't really speed up much but the additional memory usage is
+-- rather small so it doesn't hurt too much.
+
+local expansions = { }
+local nothing = { stretch = 0, shrink = 0 }
+
+setmetatableindex(expansions,function(t,font)
+ local expansion = parameters[font].expansion -- can be an extra hash
+ if expansion and expansion.auto then
+ local factors = { }
+ local c = chardata[font]
+ setmetatableindex(factors,function(t,char)
+ local fc = c[char]
+ local ef = fc.expansion_factor
+ if ef and ef > 0 then
+ local stretch = expansion.stretch
+ local shrink = expansion.shrink
+ if stretch ~= 0 or shrink ~= 0 then
+ local factor = ef / 1000
+ local ef_quad = factor * quaddata[font] / 1000
+ local v = {
+ glyphstretch = stretch * ef_quad,
+ glyphshrink = shrink * ef_quad,
+ factor = factor,
+ stretch = stretch,
+ shrink = shrink ,
+ }
+ t[char] = v
+ return v
+ end
+ end
+ t[char] = nothing
+ return nothing
+ end)
+ t[font] = factors
+ return factors
+ else
+ t[font] = false
+ return false
+ end
+end)
+
+-- local function char_stretch_shrink(p)
+-- local data = expansions[p.font][p.char]
+-- if data then
+-- return data.glyphstretch, data.glyphshrink
+-- else
+-- return 0, 0
+-- end
+-- end
+--
+-- local cal_margin_kern_var = char_stretch_shrink
+
+-- local function kern_stretch_shrink(p,d)
+-- local l = p.prev
+-- if l and l.id == glyph_code then -- how about disc nodes?
+-- local r = p.next
+-- if r and r.id == glyph_code then
+-- local lf, rf = l.font, r.font
+-- if lf == rf then
+-- local data = expansions[lf][l.char]
+-- if data then
+-- local stretch = data.stretch
+-- local shrink = data.shrink
+-- if stretch ~= 0 then
+-- -- stretch = data.factor * (d * stretch - d)
+-- stretch = data.factor * d * (stretch - 1)
+-- end
+-- if shrink ~= 0 then
+-- -- shrink = data.factor * (d * shrink - d)
+-- shrink = data.factor * d * (shrink - 1)
+-- end
+-- return stretch, shrink
+-- end
+-- end
+-- end
+-- end
+-- return 0, 0
+-- end
+
+local function kern_stretch_shrink(p,d)
+ local left = p.prev
+ if left and left.id == glyph_code then -- how about disc nodes?
+ local data = expansions[left.font][left.char]
+ if data then
+ local stretch = data.stretch
+ local shrink = data.shrink
+ if stretch ~= 0 then
+ -- stretch = data.factor * (d * stretch - d)
+ stretch = data.factor * d * (stretch - 1)
+ end
+ if shrink ~= 0 then
+ -- shrink = data.factor * (d * shrink - d)
+ shrink = data.factor * d * (shrink - 1)
+ end
+ return stretch, shrink
+ end
+ end
+ return 0, 0
+end
+
+local function kern_stretch_shrink(p,d)
+ return 0, 0
+end
+
+-- state:
+
+local function check_expand_pars(checked_expansion,f)
+ local expansion = parameters[f].expansion
+ if not expansion then
+ checked_expansion[f] = false
+ return false
+ end
+ local step = expansion.step or 0
+ local stretch = expansion.stretch or 0
+ local shrink = expansion.shrink or 0
+ if step == 0 or (stretch == 0 and schrink == 0) then
+ checked_expansion[f] = false
+ return false
+ end
+ local par = checked_expansion.par
+ if par.cur_font_step < 0 then
+ par.cur_font_step = step
+ elseif par.cur_font_step ~= step then
+ report_parbuilders("using fonts with different step of expansion in one paragraph is not allowed")
+ checked_expansion[f] = false
+ return false
+ end
+ if stretch == 0 then
+ -- okay
+ elseif par.max_stretch_ratio < 0 then
+ par.max_stretch_ratio = stretch -- expansion_factor
+ elseif par.max_stretch_ratio ~= stretch then
+ report_parbuilders("using fonts with different stretch limit of expansion in one paragraph is not allowed")
+ checked_expansion[f] = false
+ return false
+ end
+ if shrink == 0 then
+ -- okay
+ elseif par.max_shrink_ratio < 0 then
+ par.max_shrink_ratio = shrink -- - expansion_factor
+ elseif par.max_shrink_ratio ~= shrink then
+ report_parbuilders("using fonts with different shrink limit of expansion in one paragraph is not allowed")
+ checked_expansion[f] = false
+ return false
+ end
+ if trace_adjusting then
+ report_parbuilders("expanding font %a using step %a, shrink %a and stretch %a",f,step,stretch,shrink)
+ end
+ local e = expansions[f]
+ checked_expansion[f] = e
+ return e
+end
+
+local function check_expand_lines(checked_expansion,f)
+ local expansion = parameters[f].expansion
+ if not expansion then
+ checked_expansion[f] = false
+ return false
+ end
+ local step = expansion.step or 0
+ local stretch = expansion.stretch or 0
+ local shrink = expansion.shrink or 0
+ if step == 0 or (stretch == 0 and schrink == 0) then
+ checked_expansion[f] = false
+ return false
+ end
+ if trace_adjusting then
+ report_parbuilders("expanding font %a using step %a, shrink %a and stretch %a",f,step,stretch,shrink)
+ end
+ local e = expansions[f]
+ checked_expansion[f] = e
+ return e
+end
+
+-- protrusion
+
+local function find(head) -- do we really want to recurse into an hlist?
+ while head do
+ local id = head.id
+ if id == glyph_code then
+ return head
+ elseif id == hlist_code then
+ local found = find(head.list)
+ if found then
+ return found
+ else
+ head = head.next
+ end
+ elseif is_skipable(head) then
+ head = head.next
+ else
+ return head
+ end
+ end
+ return nil
+end
+
+local function find_protchar_left(l) -- weird function
+ local ln = l.next
+ if ln and ln.id == hlist_code and not ln.list and ln.width == 0 and ln.height == 0 and ln.depth == 0 then
+ l = l.next
+ else -- if d then -- was always true
+ local id = l.id
+ while ln and not (id == glyph_code or id < math_code) do -- is there always a glyph?
+ l = ln
+ ln = l.next
+ id = ln.id
+ end
+ end
+ -- if l.id == glyph_code then
+ -- return l
+ -- end
+ return find(l) or l
+end
+
+local function find(head,tail)
+ local tail = tail or slide_nodes(head)
+ while tail do
+ local id = tail.id
+ if id == glyph_code then
+ return tail
+ elseif id == hlist_code then
+ local found = find(tail.list)
+ if found then
+ return found
+ else
+ tail = tail.prev
+ end
+ elseif is_skipable(tail) then
+ tail = tail.prev
+ else
+ return tail
+ end
+ end
+ return nil
+end
+
+local function find_protchar_right(l,r)
+ return r and find(l,r) or r
+end
+
+local function left_pw(p)
+ local font = p.font
+ local prot = chardata[font][p.char].left_protruding
+ if not prot or prot == 0 then
+ return 0
+ end
+ return prot * quaddata[font] / 1000, p
+end
+
+local function right_pw(p)
+ local font = p.font
+ local prot = chardata[font][p.char].right_protruding
+ if not prot or prot == 0 then
+ return 0
+ end
+ return prot * quaddata[font] / 1000, p
+end
+
+-- par parameters
+
+local function reset_meta(par)
+ local active = {
+ id = hyphenated_code,
+ line_number = max_halfword,
+ }
+ active.next = par.active -- head of metalist
+ par.active = active
+ par.passive = nil
+end
+
+local function add_to_width(line_break_dir,checked_expansion,s) -- split into two loops (normal and expansion)
+ local size = 0
+ local adjust_stretch = 0
+ local adjust_shrink = 0
+ while s do
+ local id = s.id
+ if id == glyph_code then
+ if is_rotated[line_break_dir] then -- can be shared
+ size = size + s.height + s.depth
+ else
+ size = size + s.width
+ end
+ if checked_expansion then
+ local data = checked_expansion[s.font]
+ if data then
+ data = data[s.char]
+ if data then
+ adjust_stretch = adjust_stretch + data.glyphstretch
+ adjust_shrink = adjust_shrink + data.glyphshrink
+ end
+ end
+ end
+ elseif id == hlist_code or id == vlist_code then
+ if is_parallel[s.dir][line_break_dir] then
+ size = size + s.width
+ else
+ size = size + s.depth + s.height
+ end
+ elseif id == kern_code then
+ if checked_expansion and s.subtype == kerning_code then
+ local d = s.kern
+ if d ~= 0 then
+ local stretch, shrink = kern_stretch_shrink(s,d)
+ adjust_stretch = adjust_stretch + stretch
+ adjust_shrink = adjust_shrink + shrink
+ end
+ end
+ size = size + s.kern
+ elseif id == rule_code then
+ size = size + s.width
+ else
+ report_parbuilders("unsupported node at location %a",6)
+ end
+ s = s.next
+ end
+ return size, adjust_stretch, adjust_shrink
+end
+
+local function compute_break_width(par,break_type,p) -- split in two
+ local break_width = par.break_width
+ if break_type > unhyphenated_code then
+ local disc_width = par.disc_width
+ local checked_expansion = par.checked_expansion
+ local line_break_dir = par.line_break_dir
+ local break_size = break_width.size + disc_width.size
+ local break_adjust_stretch = break_width.adjust_stretch + disc_width.adjust_stretch
+ local break_adjust_shrink = break_width.adjust_shrink + disc_width.adjust_shrink
+ local replace = p.replace
+ if replace then
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace)
+ break_size = break_size - size
+ break_adjust_stretch = break_adjust_stretch - adjust_stretch
+ break_adjust_shrink = break_adjust_shrink - adjust_shrink
+ end
+ local post = p.post
+ if post then
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,post)
+ break_size = break_size + size
+ break_adjust_stretch = break_adjust_stretch + adjust_stretch
+ break_adjust_shrink = break_adjust_shrink + adjust_shrink
+ end
+ break_width.size = break_size
+ break_width.adjust_stretch = break_adjust_stretch
+ break_width.adjust_shrink = break_adjust_shrink
+ if not post then
+ p = p.next
+ else
+ return
+ end
+ end
+ while p do -- skip spacing etc
+ local id = p.id
+ if id == glyph_code then
+ return -- happens often
+ elseif id == glue_code then
+ local spec = p.spec
+ local order = stretch_orders[spec.stretch_order]
+ break_width.size = break_width.size - spec.width
+ break_width[order] = break_width[order] - spec.stretch
+ break_width.shrink = break_width.shrink - spec.shrink
+ elseif id == penalty_code then
+ -- do nothing
+ elseif id == kern_code then
+ if p.subtype == userkern_code then
+ break_width.size = break_width.size - p.kern
+ else
+ return
+ end
+ elseif id == math_code then
+ break_width.size = break_width.size - p.surround
+ else
+ return
+ end
+ p = p.next
+ end
+end
+
+local function append_to_vlist(par, b)
+ local prev_depth = par.prev_depth
+ if prev_depth > par.ignored_dimen then
+ if b.id == hlist_code then
+ local d = par.baseline_skip.width - prev_depth - b.height -- deficiency of space between baselines
+ local s = d < par.line_skip_limit and new_lineskip(tex.lineskip) or new_baselineskip(d)
+ -- local s = d < par.line_skip_limit
+ -- if s then
+ -- s = new_lineskip()
+ -- s.spec = tex.lineskip
+ -- else
+ -- s = new_baselineskip(d)
+ -- end
+ local head_field = par.head_field
+ if head_field then
+ local n = slide_nodes(head_field)
+ n.next, s.prev = s, n
+ else
+ par.head_field = s
+ end
+ end
+ end
+ local head_field = par.head_field
+ if head_field then
+ local n = slide_nodes(head_field)
+ n.next, b.prev = b, n
+ else
+ par.head_field = b
+ end
+ if b.id == hlist_code then
+ local pd = b.depth
+ par.prev_depth = pd
+ texnest[texnest.ptr].prevdepth = pd
+ end
+end
+
+local function append_list(par, b)
+ local head_field = par.head_field
+ if head_field then
+ local n = slide_nodes(head_field)
+ n.next, b.prev = b, n
+ else
+ par.head_field = b
+ end
+end
+
+-- We can actually make par local to this module as we never break inside a break call and that way the
+-- array is reused. At some point the information will be part of the paragraph spec as passed.
+
+local function initialize_line_break(head,display)
+
+ local hang_indent = tex.hangindent or 0
+ local hsize = tex.hsize or 0
+ local hang_after = tex.hangafter or 0
+ local par_shape_ptr = tex.parshape
+ local left_skip = tex.leftskip -- nodes
+ local right_skip = tex.rightskip -- nodes
+ local pretolerance = tex.pretolerance
+ local tolerance = tex.tolerance
+ local adjust_spacing = tex.pdfadjustspacing
+ local protrude_chars = tex.pdfprotrudechars
+ local last_line_fit = tex.lastlinefit
+
+ local newhead = new_temp()
+ newhead.next = head
+
+ local adjust_spacing_status = adjust_spacing > 1 and -1 or 0
+
+ -- metatables
+
+ local par = {
+ head = newhead,
+ head_field = nil,
+ display = display,
+ font_in_short_display = 0,
+ no_shrink_error_yet = true, -- have we complained about infinite shrinkage?
+ second_pass = false, -- is this our second attempt to break this paragraph?
+ final_pass = false, -- is this our final attempt to break this paragraph?
+ threshold = 0, -- maximum badness on feasible lines
+
+ passive = nil, -- most recent node on passive list
+ printed_node = head, -- most recent node that has been printed
+ pass_number = 0, -- the number of passive nodes allocated on this pass
+ auto_breaking = 0, -- make auto_breaking accessible out of line_break
+
+ active_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 },
+ break_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 },
+ disc_width = { size = 0, adjust_stretch = 0, adjust_shrink = 0 },
+ fill_width = { stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 },
+ background = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 },
+
+ hang_indent = hang_indent,
+ hsize = hsize,
+ hang_after = hang_after,
+ par_shape_ptr = par_shape_ptr,
+ left_skip = left_skip,
+ right_skip = right_skip,
+ pretolerance = pretolerance,
+ tolerance = tolerance,
+
+ protrude_chars = protrude_chars,
+ adjust_spacing = adjust_spacing,
+ max_stretch_ratio = adjust_spacing_status,
+ max_shrink_ratio = adjust_spacing_status,
+ cur_font_step = adjust_spacing_status,
+ checked_expansion = false,
+ tracing_paragraphs = tex.tracingparagraphs > 0,
+
+ emergency_stretch = tex.emergencystretch or 0,
+ looseness = tex.looseness or 0,
+ line_penalty = tex.linepenalty or 0,
+ hyphen_penalty = tex.hyphenpenalty or 0,
+ broken_penalty = tex.brokenpenalty or 0,
+ inter_line_penalty = tex.interlinepenalty or 0,
+ club_penalty = tex.clubpenalty or 0,
+ widow_penalty = tex.widowpenalty or 0,
+ display_widow_penalty = tex.displaywidowpenalty or 0,
+ ex_hyphen_penalty = tex.exhyphenpenalty or 0,
+
+ adj_demerits = tex.adjdemerits or 0,
+ double_hyphen_demerits = tex.doublehyphendemerits or 0,
+ final_hyphen_demerits = tex.finalhyphendemerits or 0,
+
+ first_line = 0, -- tex.nest.modeline, -- 0, -- cur_list.pg_field
+
+ each_line_height = tex.pdfeachlineheight or 0, -- this will go away
+ each_line_depth = tex.pdfeachlinedepth or 0, -- this will go away
+ first_line_height = tex.pdffirstlineheight or 0, -- this will go away
+ last_line_depth = tex.pdflastlinedepth or 0, -- this will go away
+ ignored_dimen = tex.pdfignoreddimen or 0, -- this will go away
+
+ baseline_skip = tex.baselineskip or 0,
+ line_skip_limit = tex.lineskiplimit or 0,
+
+ prev_depth = texnest[texnest.ptr].prevdepth,
+
+ final_par_glue = slide_nodes(head), -- todo: we know tail already, slow
+
+ par_break_dir = tex.pardir,
+ line_break_dir = tex.pardir,
+
+ internal_pen_inter = 0, -- running localinterlinepenalty
+ internal_pen_broken = 0, -- running localbrokenpenalty
+ internal_left_box = nil, -- running localleftbox
+ internal_left_box_width = 0, -- running localleftbox width
+ init_internal_left_box = nil, -- running localleftbox
+ init_internal_left_box_width = 0, -- running localleftbox width
+ internal_right_box = nil, -- running localrightbox
+ internal_right_box_width = 0, -- running localrightbox width
+
+ best_place = { }, -- how to achieve minimal_demerits
+ best_pl_line = { }, -- corresponding line number
+ easy_line = 0, -- line numbers easy_line are equivalent in break nodes
+ last_special_line = 0, -- line numbers last_special_line all have the same width
+ first_width = 0, -- the width of all lines last_special_line, if no parshape has been specified
+ second_width = 0, -- the width of all lines last_special_line
+ first_indent = 0, -- left margin to go with first_width
+ second_indent = 0, -- left margin to go with second_width
+
+ best_bet = nil, -- use this passive node and its predecessors
+ fewest_demerits = 0, -- the demerits associated with best_bet
+ best_line = 0, -- line number following the last line of the new paragraph
+ line_diff = 0, -- the difference between the current line number and the optimum best_line
+
+ -- not yet used
+
+ best_pl_short = { }, -- shortfall corresponding to minimal_demerits
+ best_pl_glue = { }, -- corresponding glue stretch or shrink
+ do_last_line_fit = false,
+ last_line_fit = last_line_fit,
+
+ minimum_demerits = awful_badness,
+
+ minimal_demerits = {
+
+ [fit_very_loose_class] = awful_badness,
+ [fit_loose_class] = awful_badness,
+ [fit_decent_class] = awful_badness,
+ [fit_tight_class] = awful_badness,
+
+ },
+
+ prev_char_p = nil,
+
+ font_steps = { }, -- mine
+
+ statistics = {
+
+ noflines = 0,
+ nofprotrudedlines = 0,
+ nofadjustedlines = 0,
+
+ }
+
+ }
+
+ if adjust_spacing > 1 then
+ local checked_expansion = { par = par }
+ setmetatableindex(checked_expansion,check_expand_pars)
+ par.checked_expansion = checked_expansion
+ end
+
+ -- we need par for the error message
+
+ local background = par.background
+
+ local l = check_shrinkage(par,left_skip)
+ local r = check_shrinkage(par,right_skip)
+ local l_order = stretch_orders[l.stretch_order]
+ local r_order = stretch_orders[r.stretch_order]
+
+ background.size = l.width + r.width
+ background.shrink = l.shrink + r.shrink
+ background[l_order] = l.stretch
+ background[r_order] = r.stretch + background[r_order]
+
+ -- this will move up so that we can assign the whole par table
+
+ if not par_shape_ptr then
+ if hang_indent == 0 then
+ par.second_width = hsize
+ par.second_indent = 0
+ else
+ local abs_hang_after = hang_after >0 and hang_after or -hang_after
+ local abs_hang_indent = hang_indent>0 and hang_indent or -hang_indent
+ par.last_special_line = abs_hang_after
+ if hang_after < 0 then
+ par.first_width = hsize - abs_hang_indent
+ if hang_indent >= 0 then
+ par.first_indent = hang_indent
+ else
+ par.first_indent = 0
+ end
+ par.second_width = hsize
+ par.second_indent = 0
+ else
+ par.first_width = hsize
+ par.first_indent = 0
+ par.second_width = hsize - abs_hang_indent
+ if hang_indent >= 0 then
+ par.second_indent = hang_indent
+ else
+ par.second_indent = 0
+ end
+ end
+ end
+ else
+ local last_special_line = #par_shape_ptr
+ par.last_special_line = last_special_line
+ local ptr = par_shape_ptr[last_special_line]
+ par.second_width = ptr[2]
+ par.second_indent = ptr[1]
+ end
+
+ if par.looseness == 0 then
+ par.easy_line = par.last_special_line
+ else
+ par.easy_line = max_halfword
+ end
+
+ if pretolerance >= 0 then
+ par.threshold = pretolerance
+ par.second_pass = false
+ par.final_pass = false
+ else
+ par.threshold = tolerance
+ par.second_pass = true
+ par.final_pass = par.emergency_stretch <= 0
+ if trace_basic then
+ if par.final_pass then
+ report_parbuilders("enabling second and final pass")
+ else
+ report_parbuilders("enabling second pass")
+ end
+ end
+ end
+
+ if last_line_fit > 0 then
+ local spec = par.final_par_glue.spec
+ local stretch = spec.stretch
+ local stretch_order = spec.stretch_order
+ if stretch > 0 and stretch_order > 0 and background.fi == 0 and background.fil == 0 and background.fill == 0 and background.filll == 0 then
+ par.do_last_line_fit = true
+ local si = stretch_orders[stretch_order]
+ if trace_lastlinefit or trace_basic then
+ report_parbuilders("enabling last line fit, stretch order %a set to %a, linefit is %a",si,stretch,last_line_fit)
+ end
+ par.fill_width[si] = stretch
+ end
+ end
+
+ return par
+end
+
+local function post_line_break(par)
+
+ local prevgraf = texnest[texnest.ptr].prevgraf
+ local cur_line = prevgraf + 1 -- the current line number being justified
+ local cur_p = nil
+
+ local adjust_spacing = par.adjust_spacing
+ local protrude_chars = par.protrude_chars
+ local statistics = par.statistics
+
+ local p, s, k, w -- check when local
+
+ local q = par.best_bet.break_node
+ repeat -- goto first breakpoint
+ local r = q
+ q = q.prev_break
+ r.prev_break = cur_p
+ cur_p = r
+ until not q
+
+ local stack = new_dir_stack()
+
+ repeat
+
+ inject_dirs_at_begin_of_line(stack,par.head)
+
+ local q = nil
+ local r = cur_p.cur_break
+
+ local disc_break = false
+ local post_disc_break = false
+ local glue_break = false
+
+ if not r then
+ r = slide_nodes(par.head)
+ if r == par.final_par_glue then
+ q = r -- q refers to the last node of the line (and paragraph)
+ r = r.prev -- r refers to the node after which the dir nodes should be closed
+ end
+ else
+ local id = r.id
+ if id == glue_code then
+ -- r is normal skip
+ r = replace_node(r,new_rightskip(par.right_skip))
+ glue_break = true
+ q = r -- q refers to the last node of the line
+ r = r.prev -- r refers to the node after which the dir nodes should be closed
+ elseif id == disc_code then
+ -- todo: use insert_before/after
+ local prev_r = r.prev
+ local next_r = r.next
+ local subtype = r.subtype
+ local pre = r.pre
+ local post = r.post
+ local replace = r.replace
+ if subtype == second_disc_code then
+ if not (prev_r.id == disc_code and prev_r.subtype == first_disc_code) then
+ report_parbuilders('unsupported disc at location %a',3)
+ end
+ if pre then
+ flush_node_list(pre)
+ r.pre = nil
+ pre = nil -- signal
+ end
+ if replace then
+ local n = slide_nodes(replace)
+ prev_r.next = replace
+ replace.prev = prev_r
+ n.next = r
+ r.prev = n
+ r.replace = nil
+ replace = nil -- signal
+ end
+ local pre = prev_r.pre
+ local post = prev_r.post
+ local replace = prev_r.replace
+ if pre then
+ flush_node_list(pre)
+ prev_r.pre = nil
+ end
+ if replace then
+ flush_node_list(replace)
+ prev_r.replace = nil
+ end
+ if post then
+ flush_node_list(post)
+ prev_r.post = nil
+ end
+ elseif subtype == first_disc_code then
+ if not (v.id == disc_code and v.subtype == second_disc_code) then
+ report_parbuilders('unsupported disc at location %a',4)
+ end
+ next_r.subtype = regular_disc_code
+ next_r.replace = post
+ r.post = nil
+ end
+ if replace then
+ r.replace = nil -- free
+ flush_node_list(replace)
+ end
+ if pre then
+ local n = slide_nodes(pre)
+ prev_r.next = pre
+ pre.prev = prev_r
+ n.next = r
+ r.prev = n
+ r.pre = nil
+ end
+ if post then
+ local n = slide_nodes(post)
+ r.next = post
+ post.prev = r
+ n.next = next_r
+ next_r.prev = n
+ r.post = nil
+ post_disc_break = true
+ end
+ disc_break = true
+ elseif id == kern_code then
+ r.kern = 0
+ elseif r.id == math_code then
+ r.surround = 0
+ end
+ end
+ r = inject_dirs_at_end_of_line(stack,r,par.head.next,cur_p.cur_break)
+ local crb = cur_p.passive_right_box
+ if crb then
+ local s = copy_node(crb)
+ local e = r.next
+ r.next = s
+ s.prev = r
+ s.next = e
+ if e then
+ e.prev = s
+ end
+ r = s
+ end
+ if not q then
+ q = r
+ end
+ if q and q ~= par.head and protrude_chars > 0 then
+ local id = q.id
+ local c = (disc_break and (id == glyph_code or id ~= disc_code) and q) or q.prev
+ local p = find_protchar_right(par.head.next,c)
+ if p and p.id == glyph_code then
+ local w, last_rightmost_char = right_pw(p)
+ if last_rightmost_char and w ~= 0 then
+ -- so we inherit attributes, q is new pseudo head
+ q, c = insert_node_after(q,c,new_rightmarginkern(copy_node(last_rightmost_char),-w))
+ end
+ end
+ end
+ if not glue_break then
+ local h
+ h, q = insert_node_after(q,q,new_rightskip(par.right_skip)) -- q moves on as pseudo head
+ end
+ r = q.next
+ q.next = nil
+ local phead = par.head
+ q = phead.next
+ phead.next = r
+ if r then
+ r.prev = phead
+ end
+ local clb = cur_p.passive_left_box
+ if clb then -- here we miss some prev links
+ local s = copy_node(cb)
+ s = q.next
+ r.next = q
+ q = r
+ if s and cur_line == (par.first_line + 1) and s.id == hlist_code and not s.list then
+ q = q.next
+ r.next = s.next
+ s.next = r
+ end
+ end
+ if protrude_chars > 0 then
+ local p = find_protchar_left(q)
+ if p and p.id == glyph_code then
+ local w, last_leftmost_char = left_pw(p)
+ if last_leftmost_char and w ~= 0 then
+ -- so we inherit attributes, q is pseudo head and moves back
+ q = insert_node_before(q,q,new_leftmarginkern(copy_node(last_leftmost_char),-w))
+ end
+ end
+ end
+ local ls = par.left_skip
+ if ls and (ls.width ~= 0 or ls.stretch ~= 0 or ls.shrink ~= 0) then
+ q = insert_node_before(q,q,new_leftskip(ls))
+ end
+ local curwidth, cur_indent
+ if cur_line > par.last_special_line then
+ cur_indent = par.second_indent
+ cur_width = par.second_width
+ else
+ local psp = par.par_shape_ptr
+ if psp then
+ cur_indent = psp[cur_line][1]
+ cur_width = psp[cur_line][2]
+ else
+ cur_indent = par.first_indent
+ cur_width = par.first_width
+ end
+ end
+ statistics.noflines = statistics.noflines + 1
+ if adjust_spacing > 0 then
+ statistics.nofadjustedlines = statistics.nofadjustedlines + 1
+ just_box = xpack_nodes(q,cur_width,"cal_expand_ratio",par.par_break_dir) -- ,cur_p.analysis)
+ else
+ just_box = xpack_nodes(q,cur_width,"exactly",par.par_break_dir) -- ,cur_p.analysis)
+ end
+ if protrude_chars > 0 then
+ statistics.nofprotrudedlines = statistics.nofprotrudedlines + 1
+ end
+ -- wrong:
+ local adjust_head = texlists.adjust_head
+ local pre_adjust_head = texlists.pre_adjust_head
+ --
+ just_box.shift = cur_indent
+ if par.each_line_height ~= par.ignored_dimen then
+ just_box.height = par.each_line_height
+ end
+ if par.each_line_depth ~= par.ignored_dimen then
+ just_box.depth = par.each_line_depth
+ end
+ if par.first_line_height ~= par.ignored_dimen and (cur_line == par.first_line + 1) then
+ just_box.height = par.first_line_height
+ end
+ if par.last_line_depth ~= par.ignored_dimen and cur_line + 1 == par.best_line then
+ just_box.depth = par.last_line_depth
+ end
+ if texlists.pre_adjust_head ~= pre_adjust_head then
+ append_list(par, texlists.pre_adjust_head)
+ texlists.pre_adjust_head = pre_adjust_head
+ end
+ append_to_vlist(par, just_box)
+ if texlists.adjust_head ~= adjust_head then
+ append_list(par, texlists.adjust_head)
+ texlists.adjust_head = adjust_head
+ end
+ local pen
+ if cur_line + 1 ~= par.best_line then
+ if cur_p.passive_pen_inter then
+ pen = cur_p.passive_pen_inter
+ else
+ pen = par.inter_line_penalty
+ end
+ if cur_line == prevgraf + 1 then
+ pen = pen + par.club_penalty
+ end
+ if cur_line + 2 == par.best_line then
+ if par.display then
+ pen = pen + par.display_widow_penalty
+ else
+ pen = pen + par.widow_penalty
+ end
+ end
+ if disc_break then
+ if cur_p.passive_pen_broken ~= 0 then
+ pen = pen + cur_p.passive_pen_broken
+ else
+ pen = pen + par.broken_penalty
+ end
+ end
+ if pen ~= 0 then
+ append_to_vlist(par,new_penalty(pen))
+ end
+ end
+ cur_line = cur_line + 1
+ cur_p = cur_p.prev_break
+ if cur_p and not post_disc_break then
+ local phead = par.head
+ local r = phead
+ while true do
+ q = r.next
+ if q == cur_p.cur_break or q.id == glyph_code then
+ break
+ end
+ local id = q.id
+ if not (id == whatsit_code and q.subtype == localpar_code) then
+ if id < math_code or (id == kern_code and q.subtype ~= userkern_code) then
+ break
+ end
+ end
+ r = q
+ end
+ if r ~= phead then
+ r.next = nil
+ flush_node_list(phead.next)
+ phead.next = q
+ if q then
+ q.prev = phead
+ end
+ end
+ end
+ until not cur_p
+ if cur_line ~= par.best_line then -- or not par.head.next then
+ report_parbuilders("line breaking")
+ end
+ if par.head then -- added
+-- flush_node(par.head) -- the localpar_code whatsit
+ par.head = nil
+ end
+ cur_line = cur_line - 1
+ if trace_basic then
+ report_parbuilders("paragraph broken into %a lines",cur_line)
+ end
+ texnest[texnest.ptr].prevgraf = cur_line
+end
+
+local function wrap_up(par)
+ if par.tracing_paragraphs then
+ diagnostics.stop()
+ end
+ if par.do_last_line_fit then
+ local best_bet = par.best_bet
+ local active_short = best_bet.active_short
+ local active_glue = best_bet.active_glue
+ if active_short == 0 then
+ if trace_lastlinefit then
+ report_parbuilders("disabling last line fit, no active_short")
+ end
+ par.do_last_line_fit = false
+ else
+ local glue = par.final_par_glue
+ local spec = copy_node(glue.spec)
+ spec.width = spec.width + active_short - active_glue
+ spec.stretch = 0
+ -- flush_node(glue.spec) -- brrr, when we do this we can get an "invalid id stretch message", maybe dec refcount
+ glue.spec = spec
+ if trace_lastlinefit then
+ report_parbuilders("applying last line fit, short %a, glue %p",active_short,active_glue)
+ end
+ end
+ end
+ -- we have a bunch of glue and and temp nodes not freed
+ local head = par.head
+ if head.id == temp_code then
+ par.head = head.next
+ flush_node(head)
+ end
+ post_line_break(par)
+ reset_meta(par)
+ register_statistics(par)
+ return par.head_field
+end
+
+-- we could do active nodes differently ... table instead of linked list or a list
+-- with prev nodes
+
+local function deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion) -- no need for adjust if disabled
+ local active = par.active
+ local active_width = par.active_width
+ prev_r.next = r.next
+ -- removes r
+ -- r = nil
+ if prev_r == active then
+ r = active.next
+ if r.id == delta_code then
+ local aw = active_width.size + r.size active_width.size = aw cur_active_width.size = aw
+ local aw = active_width.stretch + r.stretch active_width.stretch = aw cur_active_width.stretch = aw
+ local aw = active_width.fi + r.fi active_width.fi = aw cur_active_width.fi = aw
+ local aw = active_width.fil + r.fil active_width.fil = aw cur_active_width.fil = aw
+ local aw = active_width.fill + r.fill active_width.fill = aw cur_active_width.fill = aw
+ local aw = active_width.filll + r.filll active_width.filll = aw cur_active_width.filll = aw
+ local aw = active_width.shrink + r.shrink active_width.shrink = aw cur_active_width.shrink = aw
+ if checked_expansion then
+ local aw = active_width.adjust_stretch + r.adjust_stretch active_width.adjust_stretch = aw cur_active_width.adjust_stretch = aw
+ local aw = active_width.adjust_shrink + r.adjust_shrink active_width.adjust_shrink = aw cur_active_width.adjust_shrink = aw
+ end
+ active.next = r.next
+ -- removes r
+ -- r = nil
+ end
+ elseif prev_r.id == delta_code then
+ r = prev_r.next
+ if r == active then
+ cur_active_width.size = cur_active_width.size - prev_r.size
+ cur_active_width.stretch = cur_active_width.stretch - prev_r.stretch
+ cur_active_width.fi = cur_active_width.fi - prev_r.fi
+ cur_active_width.fil = cur_active_width.fil - prev_r.fil
+ cur_active_width.fill = cur_active_width.fill - prev_r.fill
+ cur_active_width.filll = cur_active_width.filll - prev_r.filll
+ cur_active_width.shrink = cur_active_width.shrink - prev_r.shrink
+ if checked_expansion then
+ cur_active_width.adjust_stretch = cur_active_width.adjust_stretch - prev_r.adjust_stretch
+ cur_active_width.adjust_shrink = cur_active_width.adjust_shrink - prev_r.adjust_shrink
+ end
+ prev_prev_r.next = active
+ -- removes prev_r
+ -- prev_r = nil
+ prev_r = prev_prev_r
+ elseif r.id == delta_code then
+ local rn = r.size cur_active_width.size = cur_active_width.size + rn prev_r.size = prev_r.size + rn
+ local rn = r.stretch cur_active_width.stretch = cur_active_width.stretch + rn prev_r.stretch = prev_r.stretch + rn
+ local rn = r.fi cur_active_width.fi = cur_active_width.fi + rn prev_r.fi = prev_r.fi + rn
+ local rn = r.fil cur_active_width.fil = cur_active_width.fil + rn prev_r.fil = prev_r.fil + rn
+ local rn = r.fill cur_active_width.fill = cur_active_width.fill + rn prev_r.fill = prev_r.fill + rn
+ local rn = r.filll cur_active_width.filll = cur_active_width.filll + rn prev_r.filll = prev_r.fill + rn
+ local rn = r.shrink cur_active_width.shrink = cur_active_width.shrink + rn prev_r.shrink = prev_r.shrink + rn
+ if checked_expansion then
+ local rn = r.adjust_stretch cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + rn prev_r.adjust_stretch = prev_r.adjust_stretch + rn
+ local rn = r.adjust_shrink cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + rn prev_r.adjust_shrink = prev_r.adjust_shrink + rn
+ end
+ prev_r.next = r.next
+ -- removes r
+ -- r = nil
+ end
+ end
+ return prev_r, r
+end
+
+local function lastlinecrap(shortfall,active_short,active_glue,cur_active_width,fill_width,last_line_fit)
+ if active_short == 0 or active_glue <= 0 then
+ return false, 0, fit_decent_class, 0, 0
+ end
+ if cur_active_width.fi ~= fill_width.fi or cur_active_width.fil ~= fill_width.fil or cur_active_width.fill ~= fill_width.fill or cur_active_width.filll ~= fill_width.filll then
+ return false, 0, fit_decent_class, 0, 0
+ end
+ local adjustment = active_short > 0 and cur_active_width.stretch or cur_active_width.shrink
+ if adjustment <= 0 then
+ return false, 0, fit_decent_class, adjustment, 0
+ end
+ adjustment = calculate_fraction(adjustment,active_short,active_glue,maxdimen)
+ if last_line_fit < 1000 then
+ adjustment = calculate_fraction(adjustment,last_line_fit,1000,maxdimen) -- uses previous adjustment
+ end
+ local fit_class = fit_decent_class
+ if adjustment > 0 then
+ local stretch = cur_active_width.stretch
+ if adjustment > shortfall then
+ adjustment = shortfall
+ end
+ if adjustment > 7230584 and stretch < 1663497 then
+ return true, fit_very_loose_class, shortfall, adjustment, infinite_badness
+ end
+ -- if adjustment == 0 then -- badness = 0
+ -- return true, shortfall, fit_decent_class, 0, 0
+ -- elseif stretch <= 0 then -- badness = 10000
+ -- return true, shortfall, fit_very_loose_class, adjustment, 10000
+ -- end
+ -- local badness = (adjustment == 0 and 0) or (stretch <= 0 and 10000) or calculate_badness(adjustment,stretch)
+ local badness = calculate_badness(adjustment,stretch)
+ if badness > 99 then
+ return true, shortfall, fit_very_loose_class, adjustment, badness
+ elseif badness > 12 then
+ return true, shortfall, fit_loose_class, adjustment, badness
+ else
+ return true, shortfall, fit_decent_class, adjustment, badness
+ end
+ elseif adjustment < 0 then
+ local shrink = cur_active_width.shrink
+ if -adjustment > shrink then
+ adjustment = -shrink
+ end
+ local badness = calculate_badness(-adjustment,shrink)
+ if badness > 12 then
+ return true, shortfall, fit_tight_class, adjustment, badness
+ else
+ return true, shortfall, fit_decent_class, adjustment, badness
+ end
+ else
+ return false, 0, fit_decent_class, 0, 0
+ end
+end
+
+local function try_break(pi, break_type, par, first_p, cur_p, checked_expansion)
+
+ if pi >= infinite_penalty then
+ return -- this breakpoint is inhibited by infinite penalty
+ elseif pi <= -infinite_penalty then
+ pi = eject_penalty -- this breakpoint will be forced
+ end
+
+ local prev_prev_r = nil -- a step behind prev_r, if type(prev_r)=delta_code
+ local prev_r = par.active -- stays a step behind r
+ local r = nil -- runs through the active list
+ local no_break_yet = true -- have we found a feasible break at cur_p?
+ local node_r_stays_active = false -- should node r remain in the active list?
+ local line_width = 0 -- the current line will be justified to this width
+ local line_number = 0 -- line number of current active node
+ local old_line_number = 0 -- maximum line number in current equivalence class of lines
+
+ local protrude_chars = par.protrude_chars
+ local checked_expansion = par.checked_expansion
+ local break_width = par.break_width
+ local active_width = par.active_width
+ local background = par.background
+ local minimal_demerits = par.minimal_demerits
+ local best_place = par.best_place
+ local best_pl_line = par.best_pl_line
+ local best_pl_short = par.best_pl_short
+ local best_pl_glue = par.best_pl_glue
+ local do_last_line_fit = par.do_last_line_fit
+ local final_pass = par.final_pass
+ local tracing_paragraphs = par.tracing_paragraphs
+ -- local par_active = par.active
+
+ local cur_active_width = checked_expansion and { -- distance from current active node
+ size = active_width.size,
+ stretch = active_width.stretch,
+ fi = active_width.fi,
+ fil = active_width.fil,
+ fill = active_width.fill,
+ filll = active_width.filll,
+ shrink = active_width.shrink,
+ adjust_stretch = active_width.adjust_stretch,
+ adjust_shrink = active_width.adjust_shrink,
+ } or {
+ size = active_width.size,
+ stretch = active_width.stretch,
+ fi = active_width.fi,
+ fil = active_width.fil,
+ fill = active_width.fill,
+ filll = active_width.filll,
+ shrink = active_width.shrink,
+ }
+
+ while true do
+ r = prev_r.next
+ if r.id == delta_code then
+ cur_active_width.size = cur_active_width.size + r.size
+ cur_active_width.stretch = cur_active_width.stretch + r.stretch
+ cur_active_width.fi = cur_active_width.fi + r.fi
+ cur_active_width.fil = cur_active_width.fil + r.fil
+ cur_active_width.fill = cur_active_width.fill + r.fill
+ cur_active_width.filll = cur_active_width.filll + r.filll
+ cur_active_width.shrink = cur_active_width.shrink + r.shrink
+ if checked_expansion then
+ cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + r.adjust_stretch
+ cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + r.adjust_shrink
+ end
+ prev_prev_r = prev_r
+ prev_r = r
+ else
+ line_number = r.line_number
+ if line_number > old_line_number then
+ local minimum_demerits = par.minimum_demerits
+ if minimum_demerits < awful_badness and (old_line_number ~= par.easy_line or r == par.active) then
+ if no_break_yet then
+ no_break_yet = false
+ break_width.size = background.size
+ break_width.stretch = background.stretch
+ break_width.fi = background.fi
+ break_width.fil = background.fil
+ break_width.fill = background.fill
+ break_width.filll = background.filll
+ break_width.shrink = background.shrink
+ if checked_expansion then
+ break_width.adjust_stretch = 0
+ break_width.adjust_shrink = 0
+ end
+ if cur_p then
+ compute_break_width(par,break_type,cur_p)
+ end
+ end
+ if prev_r.id == delta_code then
+ prev_r.size = prev_r.size - cur_active_width.size + break_width.size
+ prev_r.stretch = prev_r.stretch - cur_active_width.stretc + break_width.stretch
+ prev_r.fi = prev_r.fi - cur_active_width.fi + break_width.fi
+ prev_r.fil = prev_r.fil - cur_active_width.fil + break_width.fil
+ prev_r.fill = prev_r.fill - cur_active_width.fill + break_width.fill
+ prev_r.filll = prev_r.filll - cur_active_width.filll + break_width.filll
+ prev_r.shrink = prev_r.shrink - cur_active_width.shrink + break_width.shrink
+ if checked_expansion then
+ prev_r.adjust_stretch = prev_r.adjust_stretch - cur_active_width.adjust_stretch + break_width.adjust_stretch
+ prev_r.adjust_shrink = prev_r.adjust_shrink - cur_active_width.adjust_shrink + break_width.adjust_shrink
+ end
+ elseif prev_r == par.active then
+ active_width.size = break_width.size
+ active_width.stretch = break_width.stretch
+ active_width.fi = break_width.fi
+ active_width.fil = break_width.fil
+ active_width.fill = break_width.fill
+ active_width.filll = break_width.filll
+ active_width.shrink = break_width.shrink
+ if checked_expansion then
+ active_width.adjust_stretch = break_width.adjust_stretch
+ active_width.adjust_shrink = break_width.adjust_shrink
+ end
+ else
+ local q = checked_expansion and {
+ id = delta_code,
+ subtype = nosubtype_code,
+ next = r,
+ size = break_width.size - cur_active_width.size,
+ stretch = break_width.stretch - cur_active_width.stretch,
+ fi = break_width.fi - cur_active_width.fi,
+ fil = break_width.fil - cur_active_width.fil,
+ fill = break_width.fill - cur_active_width.fill,
+ filll = break_width.filll - cur_active_width.filll,
+ shrink = break_width.shrink - cur_active_width.shrink,
+ adjust_stretch = break_width.adjust_stretch - cur_active_width.adjust_stretch,
+ adjust_shrink = break_width.adjust_shrink - cur_active_width.adjust_shrink,
+ } or {
+ id = delta_code,
+ subtype = nosubtype_code,
+ next = r,
+ size = break_width.size - cur_active_width.size,
+ stretch = break_width.stretch - cur_active_width.stretch,
+ fi = break_width.fi - cur_active_width.fi,
+ fil = break_width.fil - cur_active_width.fil,
+ fill = break_width.fill - cur_active_width.fill,
+ filll = break_width.filll - cur_active_width.filll,
+ shrink = break_width.shrink - cur_active_width.shrink,
+ }
+ prev_r.next = q
+ prev_prev_r = prev_r
+ prev_r = q
+ end
+ local adj_demerits = par.adj_demerits
+ local abs_adj_demerits = adj_demerits > 0 and adj_demerits or -adj_demerits
+ if abs_adj_demerits >= awful_badness - minimum_demerits then
+ minimum_demerits = awful_badness - 1
+ else
+ minimum_demerits = minimum_demerits + abs_adj_demerits
+ end
+ for fit_class = fit_very_loose_class, fit_tight_class do
+ if minimal_demerits[fit_class] <= minimum_demerits then
+ -- insert a new active node from best_place[fit_class] to cur_p
+ par.pass_number = par.pass_number + 1
+ local prev_break = best_place[fit_class]
+ local passive = {
+ id = passive_code,
+ subtype = nosubtype_code,
+ next = par.passive,
+ cur_break = cur_p,
+ serial = par.pass_number,
+ prev_break = prev_break,
+ passive_pen_inter = par.internal_pen_inter,
+ passive_pen_broken = par.internal_pen_broken,
+ passive_last_left_box = par.internal_left_box,
+ passive_last_left_box_width = par.internal_left_box_width,
+ passive_left_box = prev_break and prev_break.passive_last_left_box or par.init_internal_left_box,
+ passive_left_box_width = prev_break and prev_break.passive_last_left_box_width or par.init_internal_left_box_width,
+ passive_right_box = par.internal_right_box,
+ passive_right_box_width = par.internal_right_box_width,
+-- analysis = table.fastcopy(cur_active_width),
+ }
+ par.passive = passive
+ local q = {
+ id = break_type,
+ subtype = fit_class,
+ break_node = passive,
+ line_number = best_pl_line[fit_class] + 1,
+ total_demerits = minimal_demerits[fit_class], -- or 0,
+ next = r,
+ }
+ if do_last_line_fit then
+ local active_short = best_pl_short[fit_class]
+ local active_glue = best_pl_glue[fit_class]
+ q.active_short = active_short
+ q.active_glue = active_glue
+ if trace_lastlinefit then
+ report_parbuilders("setting short to %i and glue to %p using class %a",active_short,active_glue,fit_class)
+ end
+ end
+ -- q.next = r -- already done
+ prev_r.next = q
+ prev_r = q
+ if tracing_paragraphs then
+ diagnostics.break_node(par,q,fit_class,break_type,cur_p)
+ end
+ end
+ minimal_demerits[fit_class] = awful_badness
+ end
+ par.minimum_demerits = awful_badness
+ if r ~= par.active then
+ local q = checked_expansion and {
+ id = delta_code,
+ subtype = nosubtype_code,
+ next = r,
+ size = cur_active_width.size - break_width.size,
+ stretch = cur_active_width.stretch - break_width.stretch,
+ fi = cur_active_width.fi - break_width.fi,
+ fil = cur_active_width.fil - break_width.fil,
+ fill = cur_active_width.fill - break_width.fill,
+ filll = cur_active_width.filll - break_width.filll,
+ shrink = cur_active_width.shrink - break_width.shrink,
+ adjust_stretch = cur_active_width.adjust_stretch - break_width.adjust_stretch,
+ adjust_shrink = cur_active_width.adjust_shrink - break_width.adjust_shrink,
+ } or {
+ id = delta_code,
+ subtype = nosubtype_code,
+ next = r,
+ size = cur_active_width.size - break_width.size,
+ stretch = cur_active_width.stretch - break_width.stretch,
+ fi = cur_active_width.fi - break_width.fi,
+ fil = cur_active_width.fil - break_width.fil,
+ fill = cur_active_width.fill - break_width.fill,
+ filll = cur_active_width.filll - break_width.filll,
+ shrink = cur_active_width.shrink - break_width.shrink,
+ }
+ -- q.next = r -- already done
+ prev_r.next = q
+ prev_prev_r = prev_r
+ prev_r = q
+ end
+ end
+ if r == par.active then
+ return
+ end
+ if line_number > par.easy_line then
+ old_line_number = max_halfword - 1
+ line_width = par.second_width
+ else
+ old_line_number = line_number
+ if line_number > par.last_special_line then
+ line_width = par.second_width
+ elseif par.par_shape_ptr then
+ line_width = par.par_shape_ptr[line_number][2]
+ else
+ line_width = par.first_width
+ end
+ end
+ end
+ local artificial_demerits = false -- has d been forced to zero
+ local shortfall = line_width - cur_active_width.size - par.internal_right_box_width -- used in badness calculations
+ if not r.break_node then
+ shortfall = shortfall - par.init_internal_left_box_width
+ else
+ shortfall = shortfall - (r.break_node.passive_last_left_box_width or 0)
+ end
+ local pw, lp, rp -- used later on
+ if protrude_chars > 1 then
+ -- this is quite time consuming
+ local b = r.break_node
+ local l = b and b.cur_break or first_p
+ local o = cur_p and cur_p.prev
+ if cur_p and cur_p.id == disc_code and cur_p.pre then
+ o = slide_nodes(cur_p.pre)
+ else
+ o = find_protchar_right(l,o)
+ end
+ if o and o.id == glyph_code then
+ pw, rp = right_pw(o)
+ shortfall = shortfall + pw
+ end
+ local id = l.id
+ if id == glyph_code then
+ -- ok ?
+ elseif id == disc_code and l.post then
+ l = l.post -- TODO: first char could be a disc
+ else
+ l = find_protchar_left(l)
+ end
+ if l and l.id == glyph_code then
+ pw, lp = left_pw(l)
+ shortfall = shortfall + pw
+ end
+ end
+ if checked_expansion and shortfall ~= 0 then
+ local margin_kern_stretch = 0
+ local margin_kern_shrink = 0
+ if protrude_chars > 1 then
+ if lp then
+-- margin_kern_stretch, margin_kern_shrink = cal_margin_kern_var(lp)
+local data = expansions[lp.font][lp.char]
+if data then
+ margin_kern_stretch, margin_kern_shrink = data.glyphstretch, data.glyphshrink
+end
+ end
+ if rp then
+-- local mka, mkb = cal_margin_kern_var(rp)
+-- margin_kern_stretch = margin_kern_stretch + mka
+-- margin_kern_shrink = margin_kern_shrink + mkb
+local data = expansions[lp.font][lp.char]
+if data then
+ margin_kern_stretch = margin_kern_stretch + data.glyphstretch
+ margin_kern_shrink = margin_kern_shrink + data.glyphshrink
+end
+ end
+ end
+ local total = cur_active_width.adjust_stretch + margin_kern_stretch
+ if shortfall > 0 and total > 0 then
+ if total > shortfall then
+ shortfall = total / (par.max_stretch_ratio / par.cur_font_step) / 2
+ else
+ shortfall = shortfall - total
+ end
+ else
+ total = cur_active_width.adjust_shrink + margin_kern_shrink
+ if shortfall < 0 and total > 0 then
+ if total > - shortfall then
+ shortfall = - total / (par.max_shrink_ratio / par.cur_font_step) / 2
+ else
+ shortfall = shortfall + total
+ end
+ end
+ end
+ par.font_steps[line_number] = par.cur_font_step -- mine
+ else
+ par.font_steps[line_number] = 0 -- mine
+ end
+ local b = 0
+ local g = 0
+ local fit_class = fit_decent_class
+ local found = false
+ if shortfall > 0 then
+ if cur_active_width.fi ~= 0 or cur_active_width.fil ~= 0 or cur_active_width.fill ~= 0 or cur_active_width.filll ~= 0 then
+ if not do_last_line_fit then
+ -- okay
+ elseif not cur_p then
+ found, shortfall, fit_class, g, b = lastlinecrap(shortfall,r.active_short,r.active_glue,cur_active_width,par.fill_width,par.last_line_fit)
+ else
+ shortfall = 0
+ end
+ else
+ local stretch = cur_active_width.stretch
+ if shortfall > 7230584 and stretch < 1663497 then
+ b = infinite_badness
+ fit_class = fit_very_loose_class
+ else
+ b = calculate_badness(shortfall,stretch)
+ if b > 99 then
+ fit_class = fit_very_loose_class
+ elseif b > 12 then
+ fit_class = fit_loose_class
+ else
+ fit_class = fit_decent_class
+ end
+ end
+ end
+ else
+ local shrink = cur_active_width.shrink
+ if -shortfall > shrink then
+ b = infinite_badness + 1
+ else
+ b = calculate_badness(-shortfall,shrink)
+ end
+ if b > 12 then
+ fit_class = fit_tight_class
+ else
+ fit_class = fit_decent_class
+ end
+ end
+ if do_last_line_fit and not found then
+ if not cur_p then
+ -- g = 0
+ shortfall = 0
+ elseif shortfall > 0 then
+ g = cur_active_width.stretch
+ elseif shortfall < 0 then
+ g = cur_active_width.shrink
+ else
+ g = 0
+ end
+ end
+ -- ::FOUND::
+ local continue_only = false -- brrr
+ if b > infinite_badness or pi == eject_penalty then
+ if final_pass and par.minimum_demerits == awful_badness and r.next == par.active and prev_r == par.active then
+ artificial_demerits = true -- set demerits zero, this break is forced
+ node_r_stays_active = false
+ elseif b > par.threshold then
+ prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion)
+ continue_only = true
+ else
+ node_r_stays_active = false
+ end
+ else
+ prev_r = r
+ if b > par.threshold then
+ continue_only = true
+ else
+ node_r_stays_active = true
+ end
+ end
+ if not continue_only then
+ local d = 0
+ if not artificial_demerits then
+ d = par.line_penalty + b
+ if (d >= 0 and d or -d) >= 10000 then -- abs(d)
+ d = 100000000
+ else
+ d = d * d
+ end
+ if pi == 0 then
+ -- nothing
+ elseif pi > 0 then
+ d = d + pi * pi
+ elseif pi > eject_penalty then
+ d = d - pi * pi
+ end
+ if break_type == hyphenated_code and r.id == hyphenated_code then
+ if cur_p then
+ d = d + par.double_hyphen_demerits
+ else
+ d = d + par.final_hyphen_demerits
+ end
+ end
+ local delta = fit_class - r.subtype
+ if (delta >= 0 and delta or -delta) > 1 then -- abs(delta)
+ d = d + par.adj_demerits
+ end
+ end
+ if tracing_paragraphs then
+ diagnostics.feasible_break(par,cur_p,r,b,pi,d,artificial_demerits)
+ end
+ d = d + r.total_demerits -- this is the minimum total demerits from the beginning to cur_p via r
+ if d <= minimal_demerits[fit_class] then
+ minimal_demerits[fit_class] = d
+ best_place [fit_class] = r.break_node
+ best_pl_line [fit_class] = line_number
+ if do_last_line_fit then
+ best_pl_short[fit_class] = shortfall
+ best_pl_glue [fit_class] = g
+ if trace_lastlinefit then
+ report_parbuilders("storing last line fit short %a and glue %p in class %a",shortfall,g,fit_class)
+ end
+ end
+ if d < par.minimum_demerits then
+ par.minimum_demerits = d
+ end
+ end
+ if not node_r_stays_active then
+ prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion)
+ end
+ end
+ end
+ end
+end
+
+local function kern_break(par, cur_p, first_p, checked_expansion) -- move inline if needed
+ local v = cur_p.next
+ if par.auto_breaking and v.id == glue_code then
+ try_break(0, unhyphenated_code, par, first_p, cur_p, checked_expansion)
+ end
+ local active_width = par.active_width
+ if cur_p.id ~= math_code then
+ active_width.size = active_width.size + cur_p.kern
+ else
+ active_width.size = active_width.size + cur_p.surround
+ end
+end
+
+-- we can call the normal one for simple box building in the otr so we need
+-- frequent enabling/disabling
+
+local temp_head = new_temp()
+
+function constructors.methods.basic(head,d)
+ if trace_basic then
+ report_parbuilders("starting at %a",head)
+ end
+
+ local par = initialize_line_break(head,d)
+
+ local checked_expansion = par.checked_expansion
+ local active_width = par.active_width
+ local disc_width = par.disc_width
+ local background = par.background
+ local tracing_paragraphs = par.tracing_paragraphs
+
+ local dirstack = new_dir_stack()
+
+ if tracing_paragraphs then
+ diagnostics.start()
+ if par.pretolerance >= 0 then
+ diagnostics.current_pass(par,"firstpass")
+ end
+ end
+
+ while true do
+ reset_meta(par)
+ if par.threshold > infinite_badness then
+ par.threshold = infinite_badness
+ end
+ par.active.next = {
+ id = unhyphenated_code,
+ subtype = fit_decent_class,
+ next = par.active,
+ break_node = nil,
+ line_number = par.first_line + 1,
+ total_demerits = 0,
+ active_short = 0,
+ active_glue = 0,
+ }
+ active_width.size = background.size
+ active_width.stretch = background.stretch
+ active_width.fi = background.fi
+ active_width.fil = background.fil
+ active_width.fill = background.fill
+ active_width.filll = background.filll
+ active_width.shrink = background.shrink
+
+ if checked_expansion then
+ active_width.adjust_stretch = 0
+ active_width.adjust_shrink = 0
+ end
+
+ par.passive = nil -- = 0
+ par.printed_node = temp_head -- only when tracing, shared
+ par.printed_node.next = head
+ par.pass_number = 0
+ par.auto_breaking = true
+
+ local cur_p = head
+ local first_p = cur_p
+
+ par.font_in_short_display = 0
+
+ if cur_p and cur_p.id == whatsit_code and cur_p.subtype == localpar_code then
+ par.init_internal_left_box = cur_p.box_left
+ par.init_internal_left_box_width = cur_p.box_left_width
+ par.internal_pen_inter = cur_p.pen_inter
+ par.internal_pen_broken = cur_p.pen_broken
+ par.internal_left_box = par.init_internal_left_box
+ par.internal_left_box_width = par.init_internal_left_box_width
+ par.internal_right_box = cur_p.box_right
+ par.internal_right_box_width = cur_p.box_right_width
+ end
+
+ -- all passes are combined in this loop so maybe we should split this into
+ -- three function calls; we then also need to do the wrap_up elsewhere
+
+ -- split into normal and expansion loop
+
+ -- use an active local
+
+ local fontexp, lastfont -- we can pass fontexp to calculate width if needed
+
+ while cur_p and par.active.next ~= par.active do
+ while cur_p and cur_p.id == glyph_code do
+ if is_rotated[par.line_break_dir] then
+ active_width.size = active_width.size + cur_p.height + cur_p.depth
+ else
+ active_width.size = active_width.size + cur_p.width
+ end
+ if checked_expansion then
+ local data= checked_expansion[cur_p.font]
+ if data then
+ local currentfont = cur_p.font
+ if currentfont ~= lastfont then
+ fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer
+ lastfont = currentfont
+ end
+ if fontexps then
+ local expansion = fontexps[cur_p.char]
+ if expansion then
+ active_width.adjust_stretch = active_width.adjust_stretch + expansion.glyphstretch
+ active_width.adjust_shrink = active_width.adjust_shrink + expansion.glyphshrink
+ end
+ end
+ end
+ end
+ cur_p = cur_p.next
+ end
+ if not cur_p then -- TODO
+ report_parbuilders("problems with linebreak_tail")
+ os.exit()
+ end
+ local id = cur_p.id
+ if id == hlist_code or id == vlist_code then
+ if is_parallel[cur_p.dir][par.line_break_dir] then
+ active_width.size = active_width.size + cur_p.width
+ else
+ active_width.size = active_width.size + cur_p.depth + cur_p.height
+ end
+ elseif id == glue_code then
+ if par.auto_breaking then
+ local prev_p = cur_p.prev
+ if prev_p and prev_p ~= temp_head then
+ local id = prev_p.id
+ if id == glyph_code or
+ (id < math_code and (id ~= whatsit_code or prev_p.subtype ~= dir_code)) or -- was: precedes_break(prev_p)
+ (id == kern_code and prev_p.subtype ~= userkern_code) then
+ try_break(0, unhyphenated_code, par, first_p, cur_p, checked_expansion)
+ end
+ end
+ end
+ local spec = check_shrinkage(par,cur_p.spec)
+ local order = stretch_orders[spec.stretch_order]
+ cur_p.spec = spec
+ active_width.size = active_width.size + spec.width
+ active_width[order] = active_width[order] + spec.stretch
+ active_width.shrink = active_width.shrink + spec.shrink
+ elseif id == disc_code then
+ local subtype = cur_p.subtype
+ if subtype ~= second_disc_code then -- are there still second_disc_code in luatex
+ local line_break_dir = par.line_break_dir
+ if par.second_pass then -- todo: make second pass local
+ local actual_pen = subtype == automatic_disc_code and par.ex_hyphen_penalty or par.hyphen_penalty
+ local pre = cur_p.pre
+ if not pre then -- trivial pre-break
+ disc_width.size = 0
+ if checked_expansion then
+ disc_width.adjust_stretch = 0
+ disc_width.adjust_shrink = 0
+ end
+ try_break(actual_pen, hyphenated_code, par, first_p, cur_p, checked_expansion)
+ else
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre)
+ disc_width.size = size
+ active_width.size = active_width.size + size
+ if checked_expansion then
+ disc_width.adjust_stretch = adjust_stretch
+ disc_width.adjust_shrink = adjust_shrink
+ active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch
+ active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink
+ else
+ -- disc_width.adjust_stretch = 0
+ -- disc_width.adjust_shrink = 0
+ end
+ try_break(actual_pen, hyphenated_code, par, first_p, cur_p, checked_expansion)
+ if subtype == first_disc_code then
+ local cur_p_next = cur_p.next
+ if cur_p_next.id ~= disc_code or cur_p_next.subtype ~= second_disc_code then
+ report_parbuilders("unsupported disc at location %a",1)
+ else
+ local pre = cur_p_next.pre
+ if pre then
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre)
+ disc_width.size = disc_width.size + size
+ if checked_expansion then
+ disc_width.adjust_stretch = disc_width.adjust_stretch + adjust_stretch
+ disc_width.adjust_shrink = disc_width.adjust_shrink + adjust_shrink
+ end
+ try_break(actual_pen, hyphenated_code, par, first_p, cur_p_next, checked_expansion)
+ --
+ -- I will look into this some day ... comment in linebreak.w says that this fails,
+ -- maybe this is what Taco means with his comment in the luatex manual.
+ --
+ -- do_one_seven_eight(sub_disc_width_from_active_width);
+ -- do_one_seven_eight(reset_disc_width);
+ -- s = vlink_no_break(vlink(cur_p));
+ -- add_to_widths(s, line_break_dir, pdf_adjust_spacing,disc_width);
+ -- ext_try_break(...,first_p,vlink(cur_p));
+ --
+ else
+ report_parbuilders("unsupported disc at location %a",2)
+ end
+ end
+ end
+ -- beware, we cannot restore to a saved value as the try_break adapts active_width
+ active_width.size = active_width.size - disc_width.size
+ if checked_expansion then
+ active_width.adjust_stretch = active_width.adjust_stretch - disc_width.adjust_stretch
+ active_width.adjust_shrink = active_width.adjust_shrink - disc_width.adjust_shrink
+ end
+ end
+ end
+ local replace = cur_p.replace
+ if replace then
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace)
+ active_width.size = active_width.size + size
+ if checked_expansion then
+ active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch
+ active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink
+ end
+ end
+ end
+ elseif id == kern_code then
+ if cur_p.subtype == userkern_code then
+ kern_break(par,cur_p,first_p, checked_expansion)
+ else
+ active_width.size = active_width.size + cur_p.kern
+ if checked_expansion and cur_p.subtype == kerning_code then
+ local d = cur_p.kern
+ if d ~= 0 then
+ local stretch, shrink = kern_stretch_shrink(cur_p,d)
+ active_width.adjust_stretch = active_width.adjust_stretch + stretch
+ active_width.adjust_shrink = active_width.adjust_shrink + shrink
+ end
+ end
+ end
+ elseif id == math_code then
+ par.auto_breaking = cur_p.subtype == endmath_code
+ kern_break(par,cur_p, first_p, checked_expansion)
+ elseif id == rule_code then
+ active_width.size = active_width.size + cur_p.width
+ elseif id == penalty_code then
+ try_break(cur_p.penalty, unhyphenated_code, par, first_p, cur_p, checked_expansion)
+ elseif id == whatsit_code then
+ local subtype = cur_p.subtype
+ if subtype == localpar_code then
+ par.internal_pen_inter = cur_p.pen_inter
+ par.internal_pen_broken = cur_p.pen_broken
+ par.internal_left_box = cur_p.box_left
+ par.internal_left_box_width = cur_p.box_left_width
+ par.internal_right_box = cur_p.box_right
+ par.internal_right_box_width = cur_p.box_right_width
+ elseif subtype == dir_code then
+ par.line_break_dir = checked_line_dir(dirstack) or par.line_break_dir
+ else
+ local get_width = get_whatsit_width[subtype]
+ if get_width then
+ active_width.size = active_width.size + get_width(cur_p)
+ end
+ end
+ elseif id == mark_code or id == ins_code or id == adjust_code then
+ -- skip
+ else
+ report_parbuilders("node of type %a found in paragraph",type(id))
+ end
+ cur_p = cur_p.next
+ end
+ if not cur_p then
+ try_break(eject_penalty, hyphenated_code, par, first_p, cur_p, checked_expansion)
+ local p_active = par.active
+ local n_active = p_active.next
+ if n_active ~= p_active then
+ local r = n_active
+ par.fewest_demerits = awful_badness
+ repeat -- use local d
+ if r.id ~= delta_code and r.total_demerits < par.fewest_demerits then
+ par.fewest_demerits = r.total_demerits
+ par.best_bet = r
+ end
+ r = r.next
+ until r == p_active
+ par.best_line = par.best_bet.line_number
+ local asked_looseness = par.looseness
+ if asked_looseness == 0 then
+ return wrap_up(par)
+ end
+ local r = n_active
+ local actual_looseness = 0
+ -- minimize assignments to par but happens seldom
+ repeat
+ if r.id ~= delta_code then
+ local line_diff = r.line_number - par.best_line
+ par.line_diff = line_diff
+ if (line_diff < actual_looseness and asked_looseness <= line_diff) or
+ (line_diff > actual_looseness and asked_looseness >= line_diff) then
+ par.best_bet = r
+ actual_looseness = line_diff
+ par.fewest_demerits = r.total_demerits
+ elseif line_diff == actual_looseness and r.total_demerits < par.fewest_demerits then
+ par.best_bet = r
+ par.fewest_demerits = r.total_demerits
+ end
+ end
+ r = r.next
+ until r == p_active -- weird, loop list?
+ par.best_line = par.best_bet.line_number
+ if actual_looseness == asked_looseness or par.final_pass then
+ return wrap_up(par)
+ end
+ end
+ end
+ reset_meta(par) -- clean up the memory by removing the break nodes
+ if not par.second_pass then
+ if tracing_paragraphs then
+ diagnostics.current_pass(par,"secondpass")
+ end
+ par.threshold = par.tolerance
+ par.second_pass = true
+ par.final_pass = par.emergency_stretch <= 0
+ else
+ if tracing_paragraphs then
+ diagnostics.current_pass(par,"emergencypass")
+ end
+ par.background.stretch = par.background.stretch + par.emergency_stretch
+ par.final_pass = true
+ end
+ end
+ return wrap_up(par)
+end
+
+-- standard tex logging .. will be adapted .. missing font names and to many []
+
+local function write_esc(cs)
+ local esc = tex.escapechar
+ if esc then
+ write("log",utfchar(esc),cs)
+ else
+ write("log",cs)
+ end
+end
+
+function diagnostics.start()
+end
+
+function diagnostics.stop()
+ write_nl("log",'')
+end
+
+function diagnostics.current_pass(par,what)
+ write_nl("log",format("@%s",what))
+end
+
+local function short_display(a,font_in_short_display)
+ while a do
+ local id = a.id
+ if id == glyph_code then
+ local font = a.font
+ if font ~= font_in_short_display then
+ write("log",tex.fontidentifier(font) .. ' ')
+ font_in_short_display = font
+ end
+ if a.subtype == ligature_code then
+ font_in_short_display = short_display(a.components,font_in_short_display)
+ else
+ write("log",utfchar(a.char))
+ end
+-- elseif id == rule_code then
+-- write("log","|")
+-- elseif id == glue_code then
+-- if a.spec.writable then
+-- write("log"," ")
+-- end
+-- elseif id == math_code then
+-- write("log","$")
+ elseif id == disc_code then
+ font_in_short_display = short_display(a.pre,font_in_short_display)
+ font_in_short_display = short_display(a.post,font_in_short_display)
+ else -- no explicit checking
+ write("log",format("[%s]",nodecodes[id]))
+ end
+ a = a.next
+ end
+ return font_in_short_display
+end
+
+diagnostics.short_display = short_display
+
+function diagnostics.break_node(par, q, fit_class, break_type, cur_p) -- %d ?
+ local passive = par.passive
+ local typ_ind = break_type == hyphenated_code and '-' or ""
+ if par.do_last_line_fit then
+ local s = number.toscaled(q.active_short)
+ local g = number.toscaled(q.active_glue)
+ if cur_p then
+ write_nl("log",format("@@%d: line %d.%d%s t=%s s=%s g=%s",
+ passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g))
+ else
+ write_nl("log",format("@@%d: line %d.%d%s t=%s s=%s a=%s",
+ passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g))
+ end
+ else
+ write_nl("log",format("@@%d: line %d.%d%s t=%s",
+ passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits))
+ end
+ if not passive.prev_break then
+ write("log"," -> @0")
+ else
+ write("log",format(" -> @%d", passive.prev_break.serial or 0))
+ end
+end
+
+function diagnostics.feasible_break(par, cur_p, r, b, pi, d, artificial_demerits)
+ local printed_node = par.printed_node
+ if printed_node ~= cur_p then
+ write_nl("log","")
+ if not cur_p then
+ par.font_in_short_display = short_display(printed_node.next,par.font_in_short_display)
+ else
+ local save_link = cur_p.next
+ cur_p.next = nil
+ write_nl("log","")
+ par.font_in_short_display = short_display(printed_node.next,par.font_in_short_display)
+ cur_p.next = save_link
+ end
+ par.printed_node = cur_p
+ end
+ write_nl("log","@")
+ if not cur_p then
+ write_esc("par")
+ else
+ local id = cur_p.id
+ if id == glue_code then
+ -- print nothing
+ elseif id == penalty_code then
+ write_esc("penalty")
+ elseif id == disc_code then
+ write_esc("discretionary")
+ elseif id == kern_code then
+ write_esc("kern")
+ elseif id == math_code then
+ write_esc("math")
+ else
+ write_esc("unknown")
+ end
+ end
+ local via, badness, demerits = 0, '*', '*'
+ if r.break_node then
+ via = r.break_node.serial or 0
+ end
+ if b <= infinite_badness then
+ badness = tonumber(d) -- format("%d", b)
+ end
+ if not artificial_demerits then
+ demerits = tonumber(d) -- format("%d", d)
+ end
+ write("log",format(" via @%d b=%s p=%s d=%s", via, badness, pi, demerits))
+end
+
+-- reporting --
+
+statistics.register("alternative parbuilders", function()
+ if nofpars > 0 then
+ return format("%s paragraphs, %s lines (%s protruded, %s adjusted)", nofpars, noflines, nofprotrudedlines, nofadjustedlines)
+ end
+end)
+
+-- actually scaling kerns is not such a good idea and it will become
+-- configureable
+
+-- This is no way a replacement for the built in (fast) packer
+-- it's just an alternative for special (testing) purposes.
+--
+-- We could use two hpacks: one to be used in the par builder
+-- and one to be used for other purposes. The one in the par
+-- builder is much more simple as it does not need the expansion
+-- code but only need to register the effective expansion factor
+-- with the glyph.
+
+local function glyph_width_height_depth(curdir,pdir,p)
+ if is_rotated[curdir] then
+ if is_parallel[curdir][pdir] then
+ local half = (p.height + p.depth) / 2
+ return p.width, half, half
+ else
+ local half = p.width / 2
+ return p.height + p.depth, half, half
+ end
+ elseif is_rotated[pdir] then
+ if is_parallel[curdir][pdir] then
+ local half = (p.height + p.depth) / 2
+ return p.width, half, half
+ else
+ return p.height + p.depth, p.width, 0 -- weird
+ end
+ else
+ if glyphdir_is_equal[curdir][pdir] then
+ return p.width, p.height, p.depth
+ elseif is_opposite[curdir][pdir] then
+ return p.width, p.depth, p.height
+ else -- can this happen?
+ return p.height + p.depth, p.width, 0 -- weird
+ end
+ end
+end
+
+local function pack_width_height_depth(curdir,pdir,p)
+ if is_rotated[curdir] then
+ if is_parallel[curdir][pdir] then
+ local half = (p.height + p.depth) / 2
+ return p.width, half, half
+ else -- can this happen?
+ local half = p.width / 2
+ return p.height + p.depth, half, half
+ end
+ else
+ if pardir_is_equal[curdir][pdir] then
+ return p.width, p.height, p.depth
+ elseif is_opposite[curdir][pdir] then
+ return p.width, p.depth, p.height
+ else -- weird dimensions, can this happen?
+ -- return p.width, p.depth, p.height
+ return p.height + p.depth, p.width, 0
+ end
+ end
+end
+
+-- local function xpack(head,width,method,direction,analysis)
+--
+-- -- inspect(analysis)
+--
+-- local expansion = method == "cal_expand_ratio"
+-- local natural = analysis.size
+-- local font_stretch = analysis.adjust_stretch
+-- local font_shrink = analysis.adjust_shrink
+-- local font_expand_ratio = 0
+-- local delta = width - natural
+--
+-- local hlist = new_node("hlist")
+--
+-- hlist.list = head
+-- hlist.dir = direction or tex.textdir
+-- hlist.width = width
+-- hlist.height = height
+-- hlist.depth = depth
+--
+-- if delta == 0 then
+--
+-- hlist.glue_sign = 0
+-- hlist.glue_order = 0
+-- hlist.glue_set = 0
+--
+-- else
+--
+-- local order = analysis.filll ~= 0 and fillcodes.filll or
+-- analysis.fill ~= 0 and fillcodes.fill or
+-- analysis.fil ~= 0 and fillcodes.fil or
+-- analysis.fi ~= 0 and fillcodes.fi or 0
+--
+-- if delta > 0 then
+--
+-- if expansion and order == 0 and font_stretch > 0 then
+-- font_expand_ratio = (delta/font_stretch) * 1000
+-- else
+-- local stretch = analysis.stretch
+-- if stretch ~= 0 then
+-- hlist.glue_sign = 1 -- stretch
+-- hlist.glue_order = order
+-- hlist.glue_set = delta/stretch
+-- else
+-- hlist.glue_sign = 0 -- nothing
+-- hlist.glue_order = order
+-- hlist.glue_set = 0
+-- end
+-- end
+-- print("stretch",hlist.glue_sign,hlist.glue_order,hlist.glue_set)
+--
+-- else
+--
+-- if expansion and order == 0 and font_shrink > 0 then
+-- font_expand_ratio = (delta/font_shrink) * 1000
+-- else
+-- local shrink = analysis.shrink
+-- if shrink ~= 0 then
+-- hlist.glue_sign = 2 -- shrink
+-- hlist.glue_order = order
+-- hlist.glue_set = - delta/shrink
+-- else
+-- hlist.glue_sign = 0 -- nothing
+-- hlist.glue_order = order
+-- hlist.glue_set = 0
+-- end
+-- end
+-- print("shrink",hlist.glue_sign,hlist.glue_order,hlist.glue_set)
+--
+-- end
+--
+-- end
+--
+-- if not expansion or font_expand_ratio == 0 then
+-- -- nothing
+-- elseif font_expand_ratio > 0 then
+-- if font_expand_ratio > 1000 then
+-- font_expand_ratio = 1000
+-- end
+-- local current = head
+-- while current do
+-- local id = current.id
+-- if id == glyph_code then
+-- local stretch, shrink = char_stretch_shrink(current) -- get only one
+-- if stretch then
+-- if trace_expansion then
+-- setnodecolor(g,"hz:positive")
+-- end
+-- current.expansion_factor = font_expand_ratio * stretch
+-- end
+-- elseif id == kern_code then
+-- local kern = current.kern
+-- if kern ~= 0 and current.subtype == kerning_code then
+-- current.kern = font_expand_ratio * current.kern
+-- end
+-- end
+-- current = current.next
+-- end
+-- elseif font_expand_ratio < 0 then
+-- if font_expand_ratio < -1000 then
+-- font_expand_ratio = -1000
+-- end
+-- local current = head
+-- while current do
+-- local id = current.id
+-- if id == glyph_code then
+-- local stretch, shrink = char_stretch_shrink(current) -- get only one
+-- if shrink then
+-- if trace_expansion then
+-- setnodecolor(g,"hz:negative")
+-- end
+-- current.expansion_factor = font_expand_ratio * shrink
+-- end
+-- elseif id == kern_code then
+-- local kern = current.kern
+-- if kern ~= 0 and current.subtype == kerning_code then
+-- current.kern = font_expand_ratio * current.kern
+-- end
+-- end
+-- current = current.next
+-- end
+-- end
+-- return hlist, 0
+-- end
+
+-- local expansion_stack = { } -- no dealloc
+
+local function hpack(head,width,method,direction) -- fast version when head = nil
+
+ -- we can pass the adjust_width and adjust_height so that we don't need to recalculate them but
+ -- with the glue mess it's less trivial as we lack detail
+
+ local hlist = new_node("hlist")
+
+ if head == nil then
+ return hlist, 0
+ end
+
+ local cal_expand_ratio = method == "cal_expand_ratio" -- "subst_ex_font" -- is gone
+
+ direction = direction or tex.textdir
+
+ local pack_begin_line = 0
+ local line = 0
+
+ local height = 0
+ local depth = 0
+ local natural = 0
+ local font_stretch = 0
+ local font_shrink = 0
+ local font_expand_ratio = 0
+ local last_badness = 0
+ local disc_stack = { }
+ local disc_level = 0
+ local expansion_stack = cal_expand_ratio and { } -- todo: optionally pass this
+ local expansion_index = 0
+ local total_stretch = { [0] = 0, 0, 0, 0, 0 }
+ local total_shrink = { [0] = 0, 0, 0, 0, 0 }
+
+ local hpack_dir = direction
+
+ local adjust_head = texlists.adjust_head
+ local pre_adjust_head = texlists.pre_adjust_head
+ local adjust_tail = adjust_head and slide_nodes(adjust_head)
+ local pre_adjust_tail = pre_adjust_head and slide_nodes(pre_adjust_head)
+
+ hlist.list = head
+ hlist.dir = hpack_dir
+
+ new_dir_stack(hpack_dir)
+
+ local checked_expansion = false
+
+ if cal_expand_ratio then
+ checked_expansion = { }
+ setmetatableindex(checked_expansion,check_expand_lines)
+ end
+
+ -- this one also needs to check the font, so in the end indeed we might end up with two variants
+
+ local fontexps, lastfont
+
+ local current = head
+
+ while current do
+ local id = current.id
+ if id == glyph_code then
+ if cal_expand_ratio then
+ local currentfont = current.font
+ if currentfont ~= lastfont then
+ fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer
+ lastfont = currentfont
+ end
+ if fontexps then
+ local expansion = fontexps[current.char]
+ if expansion then
+ font_stretch = font_stretch + expansion.glyphstretch
+ font_shrink = font_shrink + expansion.glyphshrink
+ expansion_index = expansion_index + 1
+ expansion_stack[expansion_index] = current
+ end
+ end
+ end
+ -- use inline if no expansion
+ local wd, ht, dp = glyph_width_height_depth(hpack_dir,"TLT",current) -- was TRT ?
+ natural = natural + wd
+ if ht > height then
+ height = ht
+ end
+ if dp > depth then
+ depth = dp
+ end
+ current = current.next
+ elseif id == kern_code then
+ local kern = current.kern
+ if kern == 0 then
+ -- no kern
+ elseif current.subtype == kerning_code then -- check p.kern
+ if cal_expand_ratio then
+ local stretch, shrink = kern_stretch_shrink(current,kern)
+ font_stretch = font_stretch + stretch
+ font_shrink = font_shrink + shrink
+ expansion_index = expansion_index + 1
+ expansion_stack[expansion_index] = current
+ end
+ natural = natural + kern
+ else
+ natural = natural + kern
+ end
+ current = current.next
+ elseif id == disc_code then
+ if current.subtype ~= second_disc_code then
+ -- todo : local stretch, shrink = char_stretch_shrink(s)
+ local replace = current.replace
+ if replace then
+ disc_level = disc_level + 1
+ disc_stack[disc_level] = current.next
+ current = replace
+ else
+ current = current.next
+ end
+ else
+ -- -- pre post replace
+ --
+ -- local stretch, shrink = char_stretch_shrink(current.pre)
+ -- font_stretch = font_stretch + stretch
+ -- font_shrink = font_shrink + shrink
+ -- expansion_index = expansion_index + 1
+ -- expansion_stack[expansion_index] = current.pre
+ --
+ current = current.next
+ end
+ elseif id == glue_code then
+ local spec = current.spec
+ natural = natural + spec.width
+ local op = spec.stretch_order
+ local om = spec.shrink_order
+ total_stretch[op] = total_stretch[op] + spec.stretch
+ total_shrink [om] = total_shrink [om] + spec.shrink
+ if current.subtype >= leaders_code then
+ local leader = current.leader
+ local ht = leader.height
+ local dp = leader.depth
+ if ht > height then
+ height = ht
+ end
+ if dp > depth then
+ depth = dp
+ end
+ end
+ current = current.next
+ elseif id == hlist_code or id == vlist_code then
+ local sh = current.shift
+ local wd, ht, dp = pack_width_height_depth(hpack_dir,current.dir or hpack_dir,current) -- added: or pack_dir
+ local hs, ds = ht - sh, dp + sh
+ natural = natural + wd
+ if hs > height then
+ height = hs
+ end
+ if ds > depth then
+ depth = ds
+ end
+ current = current.next
+ elseif id == rule_code then
+ local wd = current.width
+ local ht = current.height
+ local dp = current.depth
+ natural = natural + wd
+ if ht > height then
+ height = ht
+ end
+ if dp > depth then
+ depth = dp
+ end
+ current = current.next
+ elseif id == math_code then
+ natural = natural + current.surround
+ current = current.next
+ elseif id == unset_code then
+ local wd = current.width
+ local ht = current.height
+ local dp = current.depth
+ local sh = current.shift
+ local hs = ht - sh
+ local ds = dp + sh
+ natural = natural + wd
+ if hs > height then
+ height = hs
+ end
+ if ds > depth then
+ depth = ds
+ end
+ current = current.next
+ elseif id == ins_code or id == mark_code then
+ local prev = current.prev
+ local next = current.next
+ if adjust_tail then -- todo
+ if next then
+ next.prev = prev
+ end
+ if prev then
+ prev.next = next
+ end
+ current.prev = adjust_tail
+ current.next = nil
+ adjust_tail.next = current
+ adjust_tail = current
+ else
+ adjust_head = current
+ adjust_tail = current
+ current.prev = nil
+ current.next = nil
+ end
+ current = next
+ elseif id == adjust_code then
+ local list = current.list
+ if adjust_tail then
+ adjust_tail.next = list
+ adjust_tail = slide_nodes(list)
+ else
+ adjust_head = list
+ adjust_tail = slide_nodes(list)
+ end
+ current = current.next
+ elseif id == whatsit_code then
+ local subtype = current.subtype
+ if subtype == dir_code then
+ hpack_dir = checked_line_dir(stack,current) or hpack_dir
+ else
+ local get_dimensions = get_whatsit_dimensions[subtype]
+ if get_dimensions then
+ local wd, ht, dp = get_dimensions(current)
+ natural = natural + wd
+ if ht > height then
+ height = ht
+ end
+ if dp > depth then
+ depth = dp
+ end
+ end
+ end
+ current = current.next
+ elseif id == marginkern_code then
+ if cal_expand_ratio then
+ local glyph = current.glyph
+ local char_pw = current.subtype == leftmargin_code and left_pw or right_pw
+ font_stretch = font_stretch - current.width - char_pw(glyph)
+ font_shrink = font_shrink - current.width - char_pw(glyph)
+ expansion_index = expansion_index + 1
+ expansion_stack[expansion_index] = glyph
+ end
+ natural = natural + current.width
+ current = current.next
+ else
+ current = current.next
+ end
+ if not current and disc_level > 0 then
+ current = disc_stack[disc_level]
+ disc_level = disc_level - 1
+ end
+ end
+ if adjust_tail then
+ adjust_tail.next = nil -- todo
+ end
+ if pre_adjust_tail then
+ pre_adjust_tail.next = nil -- todo
+ end
+ if mode == "additional" then
+ width = width + natural
+ end
+ hlist.width = width
+ hlist.height = height
+ hlist.depth = depth
+ local delta = width - natural
+ if delta == 0 then
+ hlist.glue_sign = 0
+ hlist.glue_order = 0
+ hlist.glue_set = 0
+ elseif delta > 0 then
+ local order = (total_stretch[4] ~= 0 and 4 or total_stretch[3] ~= 0 and 3) or
+ (total_stretch[2] ~= 0 and 2 or total_stretch[1] ~= 0 and 1) or 0
+ if cal_expand_ratio and order == 0 and font_stretch > 0 then
+ font_expand_ratio = (delta/font_stretch) * 1000 -- round(delta/font_stretch * 1000)
+ else
+ local tso = total_stretch[order]
+ if tso ~= 0 then
+ hlist.glue_sign = 1
+ hlist.glue_order = order
+ hlist.glue_set = delta/tso
+ else
+ hlist.glue_sign = 0
+ hlist.glue_order = order
+ hlist.glue_set = 0
+ end
+-- print("stretch",hlist.glue_sign,hlist.glue_order,hlist.glue_set)
+ if order == 0 and hlist.list then
+ last_badness = calculate_badness(delta,total_stretch[0])
+ if last_badness > tex.hbadness then
+ if last_badness > 100 then
+ diagnostics.underfull_hbox(hlist,pack_begin_line,line,last_badness)
+ else
+ diagnostics.loose_hbox(hlist,pack_begin_line,line,last_badness)
+ end
+ end
+ end
+ end
+ else
+ local order = total_shrink[4] ~= 0 and 4 or total_shrink[3] ~= 0 and 3
+ or total_shrink[2] ~= 0 and 2 or total_shrink[1] ~= 0 and 1 or 0
+ if cal_expand_ratio and order == 0 and font_shrink > 0 then
+ font_expand_ratio = (delta/font_shrink) * 1000 -- round(delta/font_shrink * 1000)
+ else -- why was this else commented
+ local tso = total_shrink[order]
+ if tso ~= 0 then
+ hlist.glue_sign = 2
+ hlist.glue_order = order
+ hlist.glue_set = -delta/tso
+ else
+ hlist.glue_sign = 0
+ hlist.glue_order = order
+ hlist.glue_set = 0
+ end
+-- print("shrink",hlist.glue_sign,hlist.glue_order,hlist.glue_set)
+ if total_shrink[order] < -delta and order == 0 and hlist.list then
+ last_badness = 1000000
+ hlist.glue_set = 1
+ local fuzz = - delta - total_shrink[0]
+ local hfuzz = tex.hfuzz
+ if fuzz > hfuzz or tex.hbadness < 100 then
+ local overfullrule = tex.overfullrule
+ if fuzz > hfuzz and overfullrule > 0 then
+ -- weird, is always called and no rules shows up
+ slide_nodes(list).next = new_rule(overfullrule,nil,nil,hlist.dir)
+ end
+ diagnostics.overfull_hbox(hlist,pack_begin_line,line,-delta) -- - added
+ end
+ elseif order == 0 and hlist.list and last_badness > tex.hbadness then
+ diagnostics.bad_hbox(hlist,pack_begin_line,line,last_badness)
+ end
+ end
+ end
+ if cal_expand_ratio and font_expand_ratio ~= 0 then
+ -- if font_expand_ratio > 1000 then
+ -- font_expand_ratio = 1000
+ -- elseif font_expand_ratio < -1000 then
+ -- font_expand_ratio = -1000
+ -- end
+
+ local fontexps, lastfont
+
+ if font_expand_ratio > 0 then
+ for i=1,expansion_index do
+ local g = expansion_stack[i]
+ if g.id == glyph_code then
+ local currentfont = g.font
+ if currentfont ~= lastfont then
+ fontexps = expansions[currentfont]
+ lastfont = currentfont
+ end
+ local data = fontexps[g.char]
+ if trace_expansion then
+ setnodecolor(g,"hz:positive")
+ end
+ g.expansion_factor = font_expand_ratio * data.glyphstretch
+ else
+ local stretch, shrink = kern_stretch_shrink(g,g.kern)
+ g.expansion_factor = font_expand_ratio * stretch
+ end
+ end
+ else
+ for i=1,expansion_index do
+ local g = expansion_stack[i]
+ if g.id == glyph_code then
+ local currentfont = g.font
+ if currentfont ~= lastfont then
+ fontexps = expansions[currentfont]
+ lastfont = currentfont
+ end
+ local data = fontexps[g.char]
+ if trace_expansion then
+ setnodecolor(g,"hz:negative")
+ end
+ g.expansion_factor = font_expand_ratio * data.glyphshrink
+ else
+ local stretch, shrink = kern_stretch_shrink(g,g.kern)
+ g.expansion_factor = font_expand_ratio * shrink
+ end
+ end
+ end
+
+ end
+ return hlist, last_badness
+end
+
+nodes.hpack = hpack
+hpack_nodes = hpack -- comment this for old fashioned expansion
+xpack_nodes = hpack -- comment this for old fashioned expansion
+
+local function common_message(hlist,pack_begin_line,line,str)
+ write_nl("")
+ if status.output_active then -- unset
+ write(str," has occurred while \\output is active")
+ end
+ if pack_begin_line > 0 then
+ write(str," in paragraph at lines ",pack_begin_line,"--",line)
+ elseif pack_begin_line < 0 then
+ write(str," in alignment at lines ",-pack_begin_line,"--",line)
+ else
+ write(str," detected at line ",line)
+ end
+ write_nl("")
+ diagnostics.short_display(hlist.list,false)
+ write_nl("")
+ -- diagnostics.start()
+ -- show_box(hlist.list)
+ -- diagnostics.stop()
+end
+
+function diagnostics.overfull_hbox(hlist,pack_begin_line,line,d)
+ common_message(hlist,pack_begin_line,line,format("Overfull \\hbox (%spt too wide)",number.toscaled(d)))
+end
+
+function diagnostics.bad_hbox(hlist,pack_begin_line,line,b)
+ common_message(hlist,pack_begin_line,line,format("Tight \\hbox (badness %i)",b))
+end
+
+function diagnostics.underfull_hbox(hlist,pack_begin_line,line,b)
+ common_message(hlist,pack_begin_line,line,format("Underfull \\hbox (badness %i)",b))
+end
+
+function diagnostics.loose_hbox(hlist,pack_begin_line,line,b)
+ common_message(hlist,pack_begin_line,line,format("Loose \\hbox (badness %i)",b))
+end
+
+-- for the moment here:
+
+local utfchar = utf.char
+local concat = table.concat
+
+local nodecodes = nodes.nodecodes
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glyph_code = nodecodes.glyph
+local kern_code = nodecodes.kern
+local setnodecolor = nodes.tracers.colors.set
+local parameters = fonts.hashes.parameters
+local basepoints = number.basepoints
+
+-- definecolor[hz:positive] [r=0.6]
+-- definecolor[hz:negative] [g=0.6]
+-- definecolor[hz:zero] [b=0.6]
+
+-- scale = multiplier + ef/multiplier
+
+local trace_verbose = false trackers.register("builders.paragraphs.expansion.verbose", function(v) trace_verbose = v end)
+
+local report_verbose = logs.reporter("fonts","expansion")
+
+local function colorize(n)
+ local size, font, ef, width, scale, list, flush, length
+ if trace_verbose then
+ width = 0
+ length = 0
+ list = { }
+ flush = function()
+ if length > 0 then
+ report_verbose("%0.3f : %10s %10s %s",scale,basepoints(width),basepoints(width*scale),concat(list,"",1,length))
+ width = 0
+ length = 0
+ end
+ end
+ else
+ length = 0
+ end
+ -- tricky: the built-in method creates dummy fonts and the last line normally has the
+ -- original font and that one then has ex.auto set
+ while n do
+ local id = n.id
+ if id == glyph_code then
+ local ne = n.expansion_factor
+ if ne == 0 then
+ if length > 0 then flush() end
+ else
+ local f = n.font
+ if f ~= font then
+ if length > 0 then
+ flush()
+ end
+ local pf = parameters[f]
+ local ex = pf.expansion
+ if ex and ex.auto then
+ size = pf.size
+ font = f -- save lookups
+ else
+ size = false
+ end
+ end
+ if size then
+ if ne ~= ef then
+ if length > 0 then
+ flush()
+ end
+ ef = ne
+ end
+ -- scale = 1.0 + ef / 1000 / 1000 / 1000
+ scale = 1.0 + ef / 1000000000
+ if scale > 1 then
+ setnodecolor(n,"hz:positive")
+ elseif scale < 1 then
+ setnodecolor(n,"hz:negative")
+ else
+ setnodecolor(n,"hz:zero")
+ end
+ if report_verbose then
+ length = length + 1
+ list[length] = utfchar(n.char)
+ width = width + n.width -- no kerning yet
+ end
+ end
+ end
+ elseif id == hlist_code or id == vlist_code then
+ if length > 0 then
+ flush()
+ end
+ colorize(n.list,flush)
+ else -- nothing to show on kerns
+ if length > 0 then
+ flush()
+ end
+ end
+ n = n.next
+ end
+ if length > 0 then
+ flush()
+ end
+end
+
+builders.paragraphs.expansion = builders.paragraphs.expansion or { }
+
+function builders.paragraphs.expansion.trace(head)
+ colorize(head,true)
+ return head
+end
+
+local tasks = nodes.tasks
+
+tasks.prependaction("shipouts","normalizers","builders.paragraphs.expansion.trace")
+tasks.disableaction("shipouts","builders.paragraphs.expansion.trace")
+
+trackers.register("builders.paragraphs.expansion.verbose", function(v)
+ if v then
+ tasks.enableaction("shipouts","builders.paragraphs.expansion.trace")
+ else
+ tasks.disableaction("shipouts","builders.paragraphs.expansion.trace")
+ end
+end)
diff --git a/tex/context/base/node-met.lua b/tex/context/base/node-met.lua
new file mode 100644
index 000000000..aff427185
--- /dev/null
+++ b/tex/context/base/node-met.lua
@@ -0,0 +1,616 @@
+if not modules then modules = { } end modules ['node-nut'] = {
+ 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"
+}
+
+-- This is an experimental module. Don't use nuts for generic code, at least not till
+-- the regular code is proven stable. No support otherwise.
+
+-- luatex: todo: copylist should return h, t
+-- todo: see if using insert_before and insert_after makes sense here
+
+-- This file is a side effect of the \LUATEX\ speed optimization project of Luigi
+-- Scarso and me. As \CONTEXT\ spends over half its time in \LUA, we though that
+-- using \LUAJIT\ could improve performance. We've published some of our experiences
+-- elsewhere, but to summarize: \LUAJITTEX\ benefits a lot from the faster virtual
+-- machine, but when jit is turned of we loose some again. We experimented with
+-- ffi (without messing up the \CONTEXT\ code too much) but there we also lost more
+-- than we gained (mostly due to lack of compatible userdata support: it's all or
+-- nothing). This made us decide to look into the \LUA||\TEX\ interfacing and by
+-- profiling and careful looking at the (of course then still beta source code) we
+-- could come up with some improvements. The first showed up in 0.75 and we've more
+-- on the agenda for 0.80. Although some interfaces could be sped up significantly
+-- in practice we're only talking of 5||10\% on a \CONTEXT\ run and maybe more when
+-- complex and extensive node list manipulations happens (we're talking of hundreds
+-- of millions cross boundary calls then for documents of hundreds pages). One of the
+-- changes in the \CONTEXT\ code base is that we went from indexed access to nodes to
+-- function calls (in principle faster weren't it that the accessors need to do more
+-- checking which makes them slower) and from there to optimizing these calls as well
+-- as providing fast variants for well defined situations. At first optimizations were
+-- put in a separate \type {node.fast} table although some improvements could be
+-- ported to the main node functions. Because we got the feeling that more gain was
+-- possible (especially when using more complex fonts and \MKIV\ functionality) we
+-- eventually abandoned this approach and dropped the \type {fast} table in favour of
+-- another hack. In the process we had done lots of profiling and testing so we knew
+-- where time was wasted,
+--
+-- As lots of testing and experimenting was part of this project, I could not have
+-- done without stacks of new \CD s and \DVD s. This time Porcupine Tree, No-Man
+-- and Archive were came to rescue.
+
+local type, select = type, select
+local setmetatableindex = table.setmetatableindex
+
+-- First we get the metatable of a node:
+
+local metatable = nil
+
+do
+ local glyph = node.new("glyph",0)
+ metatable = getmetatable(glyph)
+ node.free(glyph)
+end
+
+-- statistics.tracefunction(node, "node", "getfield","setfield")
+-- statistics.tracefunction(node.direct,"node.direct","getfield","setfield")
+
+-- We start with some helpers and provide all relevant basic functions in the
+-- node namespace as well.
+
+local gonuts = type(node.direct) == "table"
+-- local gonuts = false
+
+nodes = nodes or { }
+local nodes = nodes
+
+nodes.gonuts = gonuts
+
+local nodecodes = nodes.codes
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+nodes.tostring = node.tostring or tostring
+nodes.copy = node.copy
+nodes.copy_list = node.copy_list
+nodes.delete = node.delete
+nodes.dimensions = node.dimensions
+nodes.end_of_math = node.end_of_math
+nodes.flush_list = node.flush_list
+nodes.flush_node = node.flush_node
+nodes.free = node.free
+nodes.insert_after = node.insert_after
+nodes.insert_before = node.insert_before
+nodes.hpack = node.hpack
+nodes.new = node.new
+nodes.tail = node.tail
+nodes.traverse = node.traverse
+nodes.traverse_id = node.traverse_id
+nodes.slide = node.slide
+nodes.vpack = node.vpack
+
+nodes.first_glyph = node.first_glyph
+nodes.first_character = node.first_character
+nodes.has_glyph = node.has_glyph or node.first_glyph
+
+nodes.current_attr = node.current_attr
+nodes.do_ligature_n = node.do_ligature_n
+nodes.has_field = node.has_field
+nodes.last_node = node.last_node
+nodes.usedlist = node.usedlist
+nodes.protrusion_skippable = node.protrusion_skippable
+nodes.write = node.write
+
+nodes.has_attribute = node.has_attribute
+nodes.set_attribute = node.set_attribute
+nodes.unset_attribute = node.unset_attribute
+
+nodes.protect_glyphs = node.protect_glyphs
+nodes.unprotect_glyphs = node.unprotect_glyphs
+nodes.kerning = node.kerning
+nodes.ligaturing = node.ligaturing
+nodes.mlist_to_hlist = node.mlist_to_hlist
+
+
+if not gonuts or not node.getfield then
+ node.getfield = metatable.__index
+ node.setfield = metatable.__newindex
+end
+
+if not gonuts then
+ nodes.tonode = function(n) return n end
+ nodes.todirect = function(n) return n end
+ nodes.tonut = function(n) return n end
+end
+
+local getfield = node.getfield
+local setfield = node.setfield
+
+local getattr = getfield
+local setattr = setfield
+
+local getnext = node.getnext or function(n) return getfield(n,"next") end
+local getprev = node.getprev or function(n) return getfield(n,"prev") end
+local getid = node.getid or function(n) return getfield(n,"id") end
+local getchar = node.getchar or function(n) return getfield(n,"char") end
+local getfont = node.getfont or function(n) return getfield(n,"font") end
+local getsubtype = node.getsubtype or function(n) return getfield(n,"subtype") end
+local getlist = node.getlist or function(n) return getfield(n,"list") end
+local getleader = node.getleader or function(n) return getfield(n,"leader") end
+
+nodes.getfield = getfield
+nodes.getattr = getattr
+
+nodes.setfield = setfield
+nodes.setattr = setattr
+
+nodes.getnext = getnext
+nodes.getprev = getprev
+nodes.getid = getid
+nodes.getchar = getchar
+nodes.getfont = getfont
+nodes.getsubtype = getsubtype
+nodes.getlist = getlist
+nodes.getleader = getleader
+
+nodes.getbox = node.getbox or tex.getbox
+nodes.setbox = node.setbox or tex.setbox
+nodes.getskip = node.getskip or tex.get
+
+local n_new_node = nodes.new
+local n_free_node = nodes.free
+local n_setfield = nodes.setfield
+local n_getfield = nodes.getfield
+local n_getnext = nodes.getnext
+local n_getprev = nodes.getprev
+local n_getid = nodes.getid
+local n_getlist = nodes.getlist
+local n_copy_node = nodes.copy
+local n_copy_list = nodes.copy_list
+local n_find_tail = nodes.tail
+local n_insert_after = nodes.insert_after
+local n_insert_before = nodes.insert_before
+local n_slide = nodes.slide
+
+local n_remove_node = node.remove -- not yet nodes.remove
+
+-- if t.id == glue_code then
+-- local s = t.spec
+-- 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 = n_remove_node(head,current)
+ if t then
+ if free_too then
+ n_free_node(t)
+ t = nil
+ else
+ n_setfield(t,"next",nil)
+ n_setfield(t,"prev",nil)
+ end
+ end
+ return head, current, t
+end
+
+nodes.remove = remove
+
+function nodes.delete(head,current)
+ return remove(head,current,true)
+end
+
+-- local h, c = nodes.replace(head,current,new)
+-- local c = nodes.replace(false,current,new)
+-- local c = nodes.replace(current,new)
+--
+-- todo: check for new.next and find tail
+
+function nodes.replace(head,current,new) -- no head returned if false
+ if not new then
+ head, current, new = false, head, current
+-- current, new = head, current
+ end
+ local prev = n_getprev(current)
+ local next = n_getnext(current)
+ if next then
+ n_setfield(new,"next",next)
+ n_setfield(next,"prev",new)
+ end
+ if prev then
+ n_setfield(new,"prev",prev)
+ n_setfield(prev,"next",new)
+ end
+ if head then
+ if head == current then
+ head = new
+ end
+ n_free_node(current)
+ return head, new
+ else
+ n_free_node(current)
+ return new
+ end
+end
+
+local function count(stack,flat)
+ local n = 0
+ while stack do
+ local id = n_getid(stack)
+ if not flat and id == hlist_code or id == vlist_code then
+ local list = n_getlist(stack)
+ if list then
+ n = n + 1 + count(list) -- self counts too
+ else
+ n = n + 1
+ end
+ else
+ n = n + 1
+ end
+ stack = n_getnext(stack)
+ end
+ return n
+end
+
+nodes.count = count
+
+function nodes.append(head,current,...)
+ for i=1,select("#",...) do
+ head, current = n_insert_after(head,current,(select(i,...)))
+ end
+ return head, current
+end
+
+function nodes.prepend(head,current,...)
+ for i=1,select("#",...) do
+ head, current = n_insert_before(head,current,(select(i,...)))
+ end
+ return head, current
+end
+
+function nodes.linked(...)
+ local head, last
+ for i=1,select("#",...) do
+ local next = select(i,...)
+ if next then
+ if head then
+ n_setfield(last,"next",next)
+ n_setfield(next,"prev",last)
+ else
+ head = next
+ end
+ last = n_find_tail(next) -- we could skip the last one
+ end
+ end
+ return head
+end
+
+function nodes.concat(list) -- consider tail instead of slide
+ local head, tail
+ for i=1,#list do
+ local li = list[i]
+ if li then
+ if head then
+ n_setfield(tail,"next",li)
+ n_setfield(li,"prev",tail)
+ else
+ head = li
+ end
+ tail = n_slide(li)
+ end
+ end
+ return head, tail
+end
+
+--[[
+<p>At some point we ran into a problem that the glue specification
+of the zeropoint dimension was overwritten when adapting a glue spec
+node. This is a side effect of glue specs being shared. After a
+couple of hours tracing and debugging Taco and I came to the
+conclusion that it made no sense to complicate the spec allocator
+and settled on a writable flag. This all is a side effect of the
+fact that some glues use reserved memory slots (with the zeropoint
+glue being a noticeable one). So, next we wrap this into a function
+and hide it for the user. And yes, LuaTeX now gives a warning as
+well.</p>
+]]--
+
+function nodes.writable_spec(n) -- not pool
+ local spec = n_getfield(n,"spec")
+ if not spec then
+ spec = n_copy_node(glue_spec)
+ n_setfield(n,"spec",spec)
+ elseif not n_getfield(spec,"writable") then
+ spec = n_copy_node(spec)
+ n_setfield(n,"spec",spec)
+ end
+ return spec
+end
+
+if gonuts then
+
+ function nodes.reference(n)
+ return n and tonut(n) or "<none>"
+ end
+
+else
+
+ 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 n and lpegmatch(reference,tostring(n)) or "<none>"
+ end
+
+end
+
+-- Here starts an experiment with metatables. Of course this only works with nodes
+-- wrapped in userdata with a metatable.
+--
+-- Nodes are kind of special in the sense that you need to keep an eye on creation
+-- and destruction. This is quite natural if you consider that changing the content
+-- of a node would also change any copy (or alias). As there are too many pitfalls
+-- we don't have this kind of support built in \LUATEX, which means that macro
+-- packages are free to provide their own. One can even use local variants.
+--
+-- n1 .. n2 : append nodes, no copies
+-- n1 * 5 : append 4 copies of nodes
+-- 5 + n1 : strip first 5 nodes
+-- n1 - 5 : strip last 5 nodes
+-- n1 + n2 : inject n2 after first of n1
+-- n1 - n2 : inject n2 before last of n1
+-- n1^2 : two copies of nodes (keep orginal)
+-- - n1 : reverse nodes
+-- n1/f : apply function to nodes
+
+-- local s = nodes.typesetters.tonodes
+--
+-- local function w(lst)
+-- context.dontleavehmode()
+-- context(lst)
+-- context.par()
+-- end
+--
+-- local n1 = s("a")
+-- local n2 = s("b")
+-- local n3 = s("c")
+-- local n4 = s("d")
+-- local n5 = s("e")
+-- local n6 = s("f")
+-- local n7 = s("g")
+--
+-- local n0 = n1 .. (n2 * 10).. n3 .. (5 * n4) .. n5 .. ( 5 * n6 ) .. n7 / function(n) n.char = string.byte("!") return n end
+--
+-- w(#n0)
+--
+-- w(n0)
+--
+-- local n1 = s("a") * 10
+-- local n2 = s("b") * 10
+--
+-- local n0 = ((5 + n1) .. (n2 - 5) )
+-- local n0 = - n0
+--
+-- local n0 = nil .. n0^3 .. nil
+--
+-- w(n0)
+--
+-- w ( s("a") + s("b") ) w ( s("a") + 4*s("b") ) w ( 4*s("a") + s("b") ) w ( 4*s("a") + 4*s("b") )
+-- w ( s("a") - s("b") ) w ( s("a") - 4*s("b") ) w ( 4*s("a") - s("b") ) w ( 4*s("a") - 4*s("b") )
+
+local n_remove_node = nodes.remove
+
+metatable.__concat = function(n1,n2) -- todo: accept nut on one end
+ if not n1 then
+ return n2
+ elseif not n2 then
+ return n1
+ elseif n1 == n2 then
+ -- or abort
+ return n2 -- or n2 * 2
+ else
+ local tail = n_find_tail(n1)
+ n_setfield(tail,"next",n2)
+ n_setfield(n2,"prev",tail)
+ return n1
+ end
+end
+
+metatable.__mul = function(n,multiplier)
+ if type(multiplier) ~= "number" then
+ n, multiplier = multiplier, n
+ end
+ if multiplier <= 1 then
+ return n
+ elseif n_getnext(n) then
+ local head
+ for i=2,multiplier do
+ local h = n_copy_list(n)
+ if head then
+ local t = n_find_tail(h)
+ n_setfield(t,"next",head)
+ n_setfield(head,"prev",t)
+ end
+ head = h
+ end
+ local t = n_find_tail(n)
+ n_setfield(t,"next",head)
+ n_setfield(head,"prev",t)
+ else
+ local head
+ for i=2,multiplier do
+ local c = n_copy_node(n)
+ if head then
+ n_setfield(c,"next",head)
+ n_setfield(head,"prev",c)
+ end
+ head = c
+ end
+ n_setfield(n,"next",head)
+ n_setfield(head,"prev",n)
+ end
+ return n
+end
+
+metatable.__sub = function(first,second)
+ if type(second) == "number" then
+ local tail = n_find_tail(first)
+ for i=1,second do
+ local prev = n_getfield(tail,"prev")
+ n_free_node(tail) -- can become flushlist/flushnode
+ if prev then
+ tail = prev
+ else
+ return nil
+ end
+ end
+ if tail then
+ n_setfield(tail,"next",nil)
+ return first
+ else
+ return nil
+ end
+ else
+ -- aaaaa - bbb => aaaabbba
+ local firsttail = n_find_tail(first)
+ local prev = n_getprev(firsttail)
+ if prev then
+ local secondtail = n_find_tail(second)
+ n_setfield(secondtail,"next",firsttail)
+ n_setfield(firsttail,"prev",ltail)
+ n_setfield(prev,"next",second)
+ n_setfield(second,"prev",prev)
+ return first
+ else
+ local secondtail = n_find_tail(second)
+ n_setfield(secondtail,"next",first)
+ n_setfield(first,"prev",ltail)
+ return second
+ end
+ end
+end
+
+metatable.__add = function(first,second)
+ if type(first) == "number" then
+ local head = second
+ for i=1,first do
+ local second = n_getnext(head)
+ n_free_node(head) -- can become flushlist/flushnode
+ if second then
+ head = second
+ else
+ return nil
+ end
+ end
+ if head then
+ n_setfield(head,"prev",nil)
+ return head
+ else
+ return nil
+ end
+ else
+ -- aaaaa + bbb => abbbaaaa
+ local next = n_getnext(first)
+ if next then
+ local secondtail = n_find_tail(second)
+ n_setfield(first,"next",second)
+ n_setfield(second,"prev",first)
+ n_setfield(secondtail,"next",next)
+ n_setfield(next,"prev",secondtail)
+ else
+ n_setfield(first,"next",second)
+ n_setfield(second,"prev",first)
+ end
+ return first
+ end
+end
+
+metatable.__len = function(current)
+ local length = 0
+ while current do
+ current = n_getnext(current)
+ length = length + 1
+ end
+ return length
+end
+
+metatable.__div = function(list,action)
+ return action(list) or list -- always a value
+end
+
+metatable.__pow = function(n,multiplier)
+ local tail = n
+ local head = nil
+ if getnext(n) then
+ if multiplier == 1 then
+ head = n_copy_list(n)
+ else
+ for i=1,multiplier do
+ local h = n_copy_list(n)
+ if head then
+ local t = n_find_tail(h)
+ n_setfield(t,"next",head)
+ n_setfield(head,"prev",t)
+ end
+ head = h
+ end
+ end
+ else
+ if multiplier == 1 then
+ head = n_copy_node(n)
+ else
+ for i=2,multiplier do
+ local c = n_copy_node(n)
+ if head then
+ n_setfield(head,"next",c)
+ n_setfield(c,"prev",head)
+ end
+ head = c
+ end
+ end
+ end
+ -- todo: tracing
+ return head
+end
+
+metatable.__unm = function(head)
+ local last = head
+ local first = head
+ local current = n_getnext(head)
+ while current do
+ local next = n_getnext(current)
+ n_setfield(first,"prev",current)
+ n_setfield(current,"next",first)
+ first = current
+ current = next
+ end
+ n_setfield(first,"prev",nil)
+ n_setfield(last,"next",nil)
+ return first
+end
+
+-- see node-nut.lua for more info on going nuts
+
+if not gonuts then
+
+ local nuts = { }
+ nodes.nuts = nuts
+
+ local function dummy(f) return f end
+
+ nodes.vianuts = dummy
+ nodes.vianodes = dummy
+
+ for k, v in next, nodes do
+ if type(v) == "function" then
+ nuts[k] = v
+ end
+ end
+
+end
diff --git a/tex/context/base/node-pro.lua b/tex/context/base/node-pro.lua
index b98292abb..aa6692d7b 100644
--- a/tex/context/base/node-pro.lua
+++ b/tex/context/base/node-pro.lua
@@ -66,36 +66,12 @@ processors.tracer = tracer
processors.enabled = true -- this will become a proper state (like trackers)
--- function processors.pre_linebreak_filter(head,groupcode,size,packtype,direction)
--- local first, found = first_glyph(head) -- they really need to be glyphs
--- if found then
--- if trace_callbacks then
--- local before = nodes.count(head,true)
--- local head, done = actions(head,groupcode,size,packtype,direction) -- todo : pass first
--- local after = nodes.count(head,true)
--- if done then
--- tracer("pre_linebreak","changed",head,groupcode,before,after,true)
--- else
--- tracer("pre_linebreak","unchanged",head,groupcode,before,after,true)
--- end
--- return done and head or true
--- else
--- local head, done = actions(head,groupcode,size,packtype,direction) -- todo : pass first
--- return done and head or true
--- end
--- elseif trace_callbacks then
--- local n = nodes.count(head,false)
--- tracer("pre_linebreak","no chars",head,groupcode,n,n)
--- end
--- return true
--- end
-
-function processors.pre_linebreak_filter(head,groupcode)
+function processors.pre_linebreak_filter(head,groupcode) -- ,size,packtype,direction
local first, found = first_glyph(head) -- they really need to be glyphs
if found then
if trace_callbacks then
local before = nodes.count(head,true)
- local head, done = actions(head,groupcode)
+ local head, done = actions(head,groupcode) -- ,size,packtype,direction
local after = nodes.count(head,true)
if done then
tracer("pre_linebreak","changed",head,groupcode,before,after,true)
@@ -104,7 +80,7 @@ function processors.pre_linebreak_filter(head,groupcode)
end
return done and head or true
else
- local head, done = actions(head,groupcode)
+ local head, done = actions(head,groupcode) -- ,size,packtype,direction
return done and head or true
end
elseif trace_callbacks then
diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua
index 09e066434..baece6e50 100644
--- a/tex/context/base/node-ref.lua
+++ b/tex/context/base/node-ref.lua
@@ -16,61 +16,60 @@ if not modules then modules = { } end modules ['node-ref'] = {
-- is grouplevel still used?
-local format = string.format
-
-local allocate, mark = utilities.storage.allocate, utilities.storage.mark
+local attributes, nodes, node = attributes, nodes, node
-local cleanupreferences, cleanupdestinations = false, true
+local allocate = utilities.storage.allocate, utilities.storage.mark
+local mark = utilities.storage.allocate, utilities.storage.mark
-local attributes, nodes, node = attributes, nodes, node
-local nodeinjections = backends.nodeinjections
-local codeinjections = backends.codeinjections
+local nodeinjections = backends.nodeinjections
+local codeinjections = backends.codeinjections
-local transparencies = attributes.transparencies
-local colors = attributes.colors
-local references = structures.references
-local tasks = nodes.tasks
+local cleanupreferences = false
+local cleanupdestinations = true
-local hpack_list = node.hpack
-local list_dimensions = node.dimensions
+local transparencies = attributes.transparencies
+local colors = attributes.colors
+local references = structures.references
+local tasks = nodes.tasks
--- current.glue_set current.glue_sign
+local hpack_list = node.hpack
+local list_dimensions = node.dimensions
-local trace_backend = false trackers.register("nodes.backend", function(v) trace_backend = v end)
-local trace_references = false trackers.register("nodes.references", function(v) trace_references = v end)
-local trace_destinations = false trackers.register("nodes.destinations", function(v) trace_destinations = v end)
+local trace_backend = false trackers.register("nodes.backend", function(v) trace_backend = v end)
+local trace_references = false trackers.register("nodes.references", function(v) trace_references = v end)
+local trace_destinations = false trackers.register("nodes.destinations", function(v) trace_destinations = v end)
-local report_reference = logs.reporter("backend","references")
-local report_destination = logs.reporter("backend","destinations")
-local report_area = logs.reporter("backend","areas")
+local report_reference = logs.reporter("backend","references")
+local report_destination = logs.reporter("backend","destinations")
+local report_area = logs.reporter("backend","areas")
-local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
-local whatcodes = nodes.whatcodes
-local listcodes = nodes.listcodes
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+local whatcodes = nodes.whatcodes
+local listcodes = nodes.listcodes
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local glue_code = nodecodes.glue
-local whatsit_code = nodecodes.whatsit
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local whatsit_code = nodecodes.whatsit
-local leftskip_code = skipcodes.leftskip
-local rightskip_code = skipcodes.rightskip
-local parfillskip_code = skipcodes.parfillskip
+local leftskip_code = skipcodes.leftskip
+local rightskip_code = skipcodes.rightskip
+local parfillskip_code = skipcodes.parfillskip
-local localpar_code = whatcodes.localpar
-local dir_code = whatcodes.dir
+local localpar_code = whatcodes.localpar
+local dir_code = whatcodes.dir
-local line_code = listcodes.line
+local line_code = listcodes.line
-local nodepool = nodes.pool
+local nodepool = nodes.pool
-local new_kern = nodepool.kern
+local new_kern = nodepool.kern
-local traverse = node.traverse
-local find_node_tail = node.tail or node.slide
-local tosequence = nodes.tosequence
+local traverse = node.traverse
+local find_node_tail = node.tail or node.slide
+local tosequence = nodes.tosequence
-- local function dimensions(parent,start,stop)
-- stop = stop and stop.next
@@ -362,20 +361,19 @@ local function colorize(width,height,depth,n,reference,what)
end
end
-local nodepool = nodes.pool
+-- references:
-local new_kern = nodepool.kern
+local nodepool = nodes.pool
+local new_kern = nodepool.kern
-local texattribute = tex.attribute
-local texcount = tex.count
+local texsetattribute = tex.setattribute
+local texsetcount = tex.setcount
--- references:
-
-local stack = { }
-local done = { }
-local attribute = attributes.private('reference')
-local nofreferences = 0
-local topofstack = 0
+local stack = { }
+local done = { }
+local attribute = attributes.private('reference')
+local nofreferences = 0
+local topofstack = 0
nodes.references = {
attribute = attribute,
@@ -390,8 +388,8 @@ local function setreference(h,d,r)
-- the preroll permits us to determine samepage (but delayed also has some advantages)
-- so some part of the backend work is already done here
stack[topofstack] = { r, h, d, codeinjections.prerollreference(r) }
- -- texattribute[attribute] = topofstack -- todo -> at tex end
- texcount.lastreferenceattribute = topofstack
+ -- texsetattribute(attribute,topofstack) -- todo -> at tex end
+ texsetcount("lastreferenceattribute",topofstack)
end
function references.get(n) -- not public so functionality can change
@@ -540,7 +538,7 @@ function references.inject(prefix,reference,h,d,highlight,newwindow,layer) -- to
-- unknown ref, just don't set it and issue an error
else
-- check
- set.highlight, set.newwindow,set.layer = highlight, newwindow, layer
+ set.highlight, set.newwindow, set.layer = highlight, newwindow, layer
setreference(h,d,set) -- sets attribute / todo: for set[*].error
end
end
@@ -573,7 +571,7 @@ end
statistics.register("interactive elements", function()
if nofreferences > 0 or nofdestinations > 0 then
- return format("%s references, %s destinations",nofreferences,nofdestinations)
+ return string.format("%s references, %s destinations",nofreferences,nofdestinations)
else
return nil
end
diff --git a/tex/context/base/node-res.lua b/tex/context/base/node-res.lua
index 768aac404..ca9d67f91 100644
--- a/tex/context/base/node-res.lua
+++ b/tex/context/base/node-res.lua
@@ -35,6 +35,9 @@ local glyph_code = nodecodes.glyph
local allocate = utilities.storage.allocate
+local texgetbox = tex.getbox
+local texgetcount = tex.getcount
+
local reserved, nofreserved = { }, 0
local function register_node(n)
@@ -57,11 +60,10 @@ function pool.cleanup(nofboxes) -- todo
-- end
end
if nofboxes then
- local tb = tex.box
for i=0,nofboxes do
- local l = tb[i]
+ local l = texgetbox(i)
if l then
- free_node(tb[i])
+ free_node(l) -- also list ?
nl = nl + 1
end
end
@@ -293,12 +295,38 @@ function pool.noad()
return copy_node(noad)
end
-function pool.hlist()
- return copy_node(hlist)
+function pool.hlist(list,width,height,depth)
+ local n = copy_node(hlist)
+ if list then
+ n.list = list
+ end
+ if width then
+ n.width = width
+ end
+ if height then
+ n.height = height
+ end
+ if depth then
+ n.depth = depth
+ end
+ return n
end
-function pool.vlist()
- return copy_node(vlist)
+function pool.vlist(list,width,height,depth)
+ local n = copy_node(vlist)
+ if list then
+ n.list = list
+ end
+ if width then
+ n.width = width
+ end
+ if height then
+ n.height = height
+ end
+ if depth then
+ n.depth = depth
+ end
+ return n
end
--[[
@@ -396,7 +424,7 @@ function pool.special(str)
end
statistics.register("cleaned up reserved nodes", function()
- return format("%s nodes, %s lists of %s", pool.cleanup(tex.count["c_syst_last_allocated_box"]))
+ return format("%s nodes, %s lists of %s", pool.cleanup(texgetcount("c_syst_last_allocated_box")))
end) -- \topofboxstack
statistics.register("node memory usage", function() -- comes after cleanup !
diff --git a/tex/context/base/node-rul.lua b/tex/context/base/node-rul.lua
index 953beb186..5c64c0113 100644
--- a/tex/context/base/node-rul.lua
+++ b/tex/context/base/node-rul.lua
@@ -85,6 +85,9 @@ local variables = interfaces.variables
local dimenfactor = fonts.helpers.dimenfactor
local splitdimen = number.splitdimen
+local v_yes = variables.yes
+local v_foreground = variables.foreground
+
local nodecodes = nodes.nodecodes
local skipcodes = nodes.skipcodes
local whatcodes = nodes.whatcodes
@@ -150,7 +153,7 @@ local function processwords(attribute,data,flush,head,parent) -- we have hlistdi
else
-- possible extensions: when in same class then keep spanning
local newlevel, newclass = floor(aa/1000), aa%1000
---~ strip = not continue or level == 1 -- 0
+ -- strip = not continue or level == 1 -- 0
if f then
if class == newclass then -- and newlevel > level then
head, done = flush(head,f,l,d,level,parent,false), true
@@ -161,7 +164,7 @@ local function processwords(attribute,data,flush,head,parent) -- we have hlistdi
f, l, a = n, n, aa
level, class = newlevel, newclass
d = data[class]
- continue = d.continue == variables.yes
+ continue = d.continue == v_yes
end
else
if f then
@@ -169,8 +172,16 @@ local function processwords(attribute,data,flush,head,parent) -- we have hlistdi
end
f, l, a = nil, nil, nil
end
- elseif f and (id == disc_code or (id == kern_code and n.subtype == kerning_code)) then
- l = n
+-- elseif f and (id == disc_code or (id == kern_code and n.subtype == kerning_code)) then
+-- l = n
+ elseif id == disc_code then
+ if f then
+ l = n
+ end
+ elseif id == kern_code and n.subtype == kerning_code then
+ if f then
+ l = n
+ end
elseif id == hlist_code or id == vlist_code then
if f then
head, done = flush(head,f,l,d,level,parent,strip), true
@@ -188,13 +199,12 @@ local function processwords(attribute,data,flush,head,parent) -- we have hlistdi
if continue then
if id == penalty_code then
l = n
- elseif id == kern_code then
- l = n
+ -- elseif id == kern_code then
+ -- l = n
elseif id == glue_code then
-- catch \underbar{a} \underbar{a} (subtype test is needed)
local subtype = n.subtype
- if continue and n[attribute] and
- (subtype == userskip_code or subtype == spaceskip_code or subskip == xspaceskip_code) then
+ if n[attribute] and (subtype == userskip_code or subtype == spaceskip_code or subskip == xspaceskip_code) then
l = n
else
head, done = flush(head,f,l,d,level,parent,strip), true
@@ -261,7 +271,7 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a
local colorspace = ma > 0 and ma or f[a_colorspace] or 1
local color = ca > 0 and ca or f[a_color]
local transparency = ta > 0 and ta or f[a_transparency]
- local foreground = order == variables.foreground
+ local foreground = order == v_foreground
local e = dimenfactor(unit,fontdata[f.font]) -- what if no glyph node
diff --git a/tex/context/base/node-ser.lua b/tex/context/base/node-ser.lua
index 70743123c..ab59616bc 100644
--- a/tex/context/base/node-ser.lua
+++ b/tex/context/base/node-ser.lua
@@ -18,8 +18,8 @@ local context = context
local nodes = nodes
local node = node
-local traverse = node.traverse
-local is_node = node.is_node
+local traverse = nodes.traverse
+local is_node = nodes.is_node
local nodecodes = nodes.nodecodes
local noadcodes = nodes.noadcodes
diff --git a/tex/context/base/node-shp.lua b/tex/context/base/node-shp.lua
index 8f7a411a7..32024e5da 100644
--- a/tex/context/base/node-shp.lua
+++ b/tex/context/base/node-shp.lua
@@ -24,7 +24,7 @@ local mark_code = nodecodes.mark
local kern_code = nodecodes.kern
local glue_code = nodecodes.glue
-local texbox = tex.box
+local texgetbox = tex.getbox
local free_node = node.free
local remove_node = node.remove
@@ -73,7 +73,7 @@ end
-- interface
function commands.finalizebox(n)
- actions(texbox[n])
+ actions(texgetbox(n))
end
-- just in case we want to optimize lookups:
@@ -129,8 +129,8 @@ trackers.register("nodes.frequencies",function(v)
if type(v) == "string" then
frequencies.filename = v
end
- handlers.frequencies_shipouts_before = register("shipouts", "begin")
- handlers.frequencies_shipouts_after = register("shipouts", "end")
+ handlers.frequencies_shipouts_before = register("shipouts", "begin")
+ handlers.frequencies_shipouts_after = register("shipouts", "end")
handlers.frequencies_processors_before = register("processors", "begin")
handlers.frequencies_processors_after = register("processors", "end")
tasks.prependaction("shipouts", "before", "nodes.handlers.frequencies_shipouts_before")
diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua
index 916b2143d..bfdfa543b 100644
--- a/tex/context/base/node-tra.lua
+++ b/tex/context/base/node-tra.lua
@@ -22,6 +22,8 @@ nodes = nodes or { }
local nodes, node, context = nodes, node, context
+local texgetattribute = tex.getattribute
+
local tracers = nodes.tracers or { }
nodes.tracers = tracers
@@ -57,6 +59,7 @@ local localpar_code = whatcodes.localpar
local dir_code = whatcodes.dir
local nodepool = nodes.pool
+local new_rule = nodepool.rule
local dimenfactors = number.dimenfactors
local formatters = string.formatters
@@ -342,7 +345,7 @@ local function numbertodimen(d,unit,fmt,strip)
local str = formatters[fmt](d*dimenfactors[unit],unit)
return strip and lpegmatch(stripper,str) or str
end
- local id = node.id
+ local id = d.id
if id == kern_code then
local str = formatters[fmt](d.width*dimenfactors[unit],unit)
return strip and lpegmatch(stripper,str) or str
@@ -522,8 +525,49 @@ end
-- for the moment here
-nodes.visualizers = { }
+local visualizers = nodes.visualizers or { }
+nodes.visualizers = visualizers
-function nodes.visualizers.handler(head)
+function visualizers.handler(head)
return head, false
end
+
+-- we could cache attribute lists and set attr (copy will increment count) .. todo ..
+-- although tracers are used seldom
+
+local function setproperties(n,c,s)
+ local mm = texgetattribute(a_colormodel)
+ n[a_colormodel] = mm > 0 and mm or 1
+ n[a_color] = m_color[c]
+ n[a_transparency] = m_transparency[c]
+ return n
+end
+
+tracers.setproperties = setproperties
+
+function tracers.setlistv(n,c,s)
+ local f = n
+ local mc = m_color[c]
+ local mt = m_transparency[c]
+ local mm = texgetattribute(a_colormodel)
+ if mm <= 0 then
+ mm = 1
+ end
+ while n do
+ n[a_colormodel] = mm
+ n[a_color] = mc
+ n[a_transparency] = mt
+ n = n.next
+ end
+ return f
+end
+
+function tracers.resetproperties(n)
+ n[a_color] = unsetvalue
+ n[a_transparency] = unsetvalue
+ return n
+end
+
+function tracers.rule(w,h,d,c,s) -- so some day we can consider using literals (speedup)
+ return setproperties(new_rule(w,h,d),c,s)
+end
diff --git a/tex/context/base/node-typ.lua b/tex/context/base/node-typ.lua
index 6e1a31643..4a2ef8d49 100644
--- a/tex/context/base/node-typ.lua
+++ b/tex/context/base/node-typ.lua
@@ -6,21 +6,23 @@ if not modules then modules = { } end modules ['node-typ'] = {
license = "see context related readme files"
}
-local utfvalues = utf.values
+-- code has been moved to blob-ini.lua
-local currentfont = font.current
-local fontparameters = fonts.hashes.parameters
+local typesetters = nodes.typesetters or { }
+nodes.typesetters = typesetters
-local hpack = node.hpack
-local vpack = node.vpack
-local fast_hpack = nodes.fasthpack
+local hpack_node_list = nodes.hpack
+local vpack_node_list = nodes.vpack
+local fast_hpack_list = nodes.fasthpack
-local nodepool = nodes.pool
+local nodepool = nodes.pool
+local new_glyph = nodepool.glyph
+local new_glue = nodepool.glue
-local newglyph = nodepool.glyph
-local newglue = nodepool.glue
+local utfvalues = utf.values
-typesetters = typesetters or { }
+local currentfont = font.current
+local fontparameters = fonts.hashes.parameters
local function tonodes(str,fontid,spacing) -- quick and dirty
local head, prev = nil, nil
@@ -39,11 +41,11 @@ local function tonodes(str,fontid,spacing) -- quick and dirty
local next
if c == 32 then
if not spacedone then
- next = newglue(s,p,m)
+ next = new_glue(s,p,m)
spacedone = true
end
else
- next = newglyph(fontid or 1,c)
+ next = new_glyph(fontid or 1,c)
spacedone = false
end
if not next then
@@ -59,21 +61,33 @@ local function tonodes(str,fontid,spacing) -- quick and dirty
return head
end
-typesetters.tonodes = tonodes
-
-function typesetters.hpack(str,fontid,spacing)
- return hpack(tonodes(str,fontid,spacing),"exactly")
+local function tohpack(str,fontid,spacing)
+ return hpack_node_list(tonodes(str,fontid,spacing),"exactly")
end
-function typesetters.fast_hpack(str,fontid,spacing)
- return fast_hpack(tonodes(str,fontid,spacing),"exactly")
+local function tohpackfast(str,fontid,spacing)
+ return fast_hpack_list(tonodes(str,fontid,spacing),"exactly")
end
-function typesetters.vpack(str,fontid,spacing)
+local function tovpack(str,fontid,spacing)
-- vpack is just a hack, and a proper implentation is on the agenda
-- as it needs more info etc than currently available
- return vpack(tonodes(str,fontid,spacing))
+ return vpack_node_list(tonodes(str,fontid,spacing))
end
---~ node.write(typesetters.hpack("Hello World!"))
---~ node.write(typesetters.hpack("Hello World!",1,100*1024*10))
+local tovpackfast = tovpack
+
+typesetters.tonodes = tonodes
+typesetters.tohpack = tohpack
+typesetters.tohpackfast = tohpackfast
+typesetters.tovpack = tovpack
+typesetters.tovpackfast = tovpackfast
+
+typesetters.hpack = tohpack
+typesetters.fast_hpack = tohpackfast
+typesetters.vpack = tovpack
+
+-- node.write(nodes.typestters.hpack("Hello World!"))
+-- node.write(nodes.typestters.hpack("Hello World!",1,100*1024*10))
+
+string.tonodes = tonodes -- quite convenient
diff --git a/tex/context/base/pack-obj.lua b/tex/context/base/pack-obj.lua
index 1e4e0f59e..70876a346 100644
--- a/tex/context/base/pack-obj.lua
+++ b/tex/context/base/pack-obj.lua
@@ -13,8 +13,7 @@ reusable components.</p>
local commands, context = commands, context
-local texcount = tex.count
-local allocate = utilities.storage.allocate
+local allocate = utilities.storage.allocate
local collected = allocate()
local tobesaved = allocate()
diff --git a/tex/context/base/pack-rul.lua b/tex/context/base/pack-rul.lua
index a990936e7..909c0c168 100644
--- a/tex/context/base/pack-rul.lua
+++ b/tex/context/base/pack-rul.lua
@@ -10,16 +10,21 @@ if not modules then modules = { } end modules ['pack-rul'] = {
<p>An explanation is given in the history document <t>mk</t>.</p>
--ldx]]--
-local texsetdimen, texsetcount, texbox = tex.setdimen, tex.setcount, tex.box
-local hpack, free, copy, traverse_id = node.hpack, node.free, node.copy_list, node.traverse_id
-local texdimen, texcount = tex.dimen, tex.count
+local hpack = node.hpack
+local free = node.free
+local copy = node.copy_list
+local traverse_id = node.traverse_id
+local node_dimensions = node.dimensions
local hlist_code = nodes.nodecodes.hlist
local box_code = nodes.listcodes.box
-local node_dimensions = node.dimensions
+
+local texsetdimen = tex.setdimen
+local texsetcount = tex.setcount
+local texgetbox = tex.getbox
function commands.doreshapeframedbox(n)
- local box = texbox[n]
+ local box = texgetbox(n)
local noflines = 0
local firstheight = nil
local lastdepth = nil
@@ -76,17 +81,16 @@ function commands.doreshapeframedbox(n)
end
end
end
- -- print("reshape", noflines, firstheight or 0, lastdepth or 0)
- texsetcount("global","framednoflines", noflines)
- texsetdimen("global","framedfirstheight", firstheight or 0)
- texsetdimen("global","framedlastdepth", lastdepth or 0)
- texsetdimen("global","framedminwidth", minwidth)
- texsetdimen("global","framedmaxwidth", maxwidth)
- texsetdimen("global","framedaveragewidth", noflines > 0 and totalwidth/noflines or 0)
+ texsetcount("global","framednoflines",noflines)
+ texsetdimen("global","framedfirstheight",firstheight or 0)
+ texsetdimen("global","framedlastdepth",lastdepth or 0)
+ texsetdimen("global","framedminwidth",minwidth)
+ texsetdimen("global","framedmaxwidth",maxwidth)
+ texsetdimen("global","framedaveragewidth",noflines > 0 and totalwidth/noflines or 0)
end
function commands.doanalyzeframedbox(n)
- local box = texbox[n]
+ local box = texgetbox(n)
local noflines = 0
local firstheight = nil
local lastdepth = nil
@@ -102,8 +106,7 @@ function commands.doanalyzeframedbox(n)
end
end
end
- -- print("analyze", noflines, firstheight or 0, lastdepth or 0)
- texsetcount("global","framednoflines", noflines)
- texsetdimen("global","framedfirstheight", firstheight or 0)
- texsetdimen("global","framedlastdepth", lastdepth or 0)
+ texsetcount("global","framednoflines",noflines)
+ texsetdimen("global","framedfirstheight",firstheight or 0)
+ texsetdimen("global","framedlastdepth",lastdepth or 0)
end
diff --git a/tex/context/base/pack-rul.mkiv b/tex/context/base/pack-rul.mkiv
index e7db332b4..a591e5576 100644
--- a/tex/context/base/pack-rul.mkiv
+++ b/tex/context/base/pack-rul.mkiv
@@ -1749,17 +1749,45 @@
\edef\currentmathframed{#1}%
\dosingleempty\pack_framed_mathframed_indeed}
+% \def\pack_framed_mathframed_indeed[#1]#2% no fancy nesting supported here
+% {\iffirstargument
+% \setupcurrentmathframed[#1]%
+% \fi
+% \c_framed_mstyle\mathstyle
+% \doifnot{\mathframedparameter\c!location}\v!low{\let\normalstrut\pack_framed_math_strut}%
+% \inheritedmathframedframed{\Ustartmath\triggermathstyle\c_framed_mstyle#2\Ustopmath}%
+% \endgroup}
+
+\newcount\c_pack_framed_mc
+
+\def\pack_framed_math_pos
+ {\global\advance\c_pack_framed_mc\plusone
+ \xdef\pack_framed_mc_one{mcf:1:\number\c_pack_framed_mc}%
+ \xdef\pack_framed_mc_two{mcf:2:\number\c_pack_framed_mc}%
+ \xypos\pack_framed_mc_two}
+
\def\pack_framed_mathframed_indeed[#1]#2% no fancy nesting supported here
{\iffirstargument
\setupcurrentmathframed[#1]%
\fi
\c_framed_mstyle\mathstyle
- \doifnot{\mathframedparameter\c!location}\v!low{\let\normalstrut\pack_framed_math_strut}%
+ \edef\m_framed_location{\mathframedparameter\c!location}%
+ \ifx\m_framed_location\v!mathematics
+ \let\normalstrut\pack_framed_math_pos
+ \else\ifx\m_framed_location\v!low\else
+ \let\normalstrut\pack_framed_math_strut
+ \fi\fi
\inheritedmathframedframed{\Ustartmath\triggermathstyle\c_framed_mstyle#2\Ustopmath}%
\endgroup}
+\installframedlocator \v!mathematics
+ {}
+ {\lower\dimexpr\MPy\pack_framed_mc_two-\MPy\pack_framed_mc_one\relax
+ \hbox{\xypos\pack_framed_mc_one\box\b_framed_normal}}
+
\definemathframed[mframed]
\definemathframed[inmframed][\c!location=\v!low]
+\definemathframed[mcframed] [\c!location=\v!mathematics]
%D So instead of the rather versatile \type {\framed}, we use \type {\mframed}:
%D
diff --git a/tex/context/base/page-app.mkiv b/tex/context/base/page-app.mkiv
index 5f1c2f297..272245cce 100644
--- a/tex/context/base/page-app.mkiv
+++ b/tex/context/base/page-app.mkiv
@@ -106,7 +106,7 @@
\fi
\d_page_fitting_width \wd\b_page_fitting
\d_page_fitting_height\ht\b_page_fitting
- \startlocallayout % still valid?
+% wrong now: \startlocallayout % still valid?
\let\checkcurrentlayout\relax % else interference with odd/even layout
\processaction
[\fittingpageparameter\c!paper]
@@ -117,7 +117,7 @@
\startmakeup[fittingpage]%
\box\b_page_fitting
\stopmakeup
- \stoplocallayout % still valid?
+% wrong now: \stoplocallayout % still valid?
\egroup
\autostoptext}
diff --git a/tex/context/base/page-flt.lua b/tex/context/base/page-flt.lua
index ab7a534eb..11aa2be21 100644
--- a/tex/context/base/page-flt.lua
+++ b/tex/context/base/page-flt.lua
@@ -11,9 +11,6 @@ if not modules then modules = { } end modules ['page-flt'] = {
local insert, remove = table.insert, table.remove
local find = string.find
-local setdimen, setcount, texbox = tex.setdimen, tex.setcount, tex.box
-
-local copy_node_list = node.copy_list
local trace_floats = false trackers.register("graphics.floats", function(v) trace_floats = v end) -- name might change
@@ -24,10 +21,20 @@ local C, S, P, lpegmatch = lpeg.C, lpeg.S, lpeg.P, lpeg.match
-- we use floatbox, floatwidth, floatheight
-- text page leftpage rightpage (todo: top, bottom, margin, order)
-floats = floats or { }
-local floats = floats
+local copy_node_list = node.copy_list
+
+local setdimen = tex.setdimen
+local setcount = tex.setcount
+local texgetbox = tex.getbox
+local texsetbox = tex.setbox
+
+floats = floats or { }
+local floats = floats
-local noffloats, last, default, pushed = 0, nil, "text", { }
+local noffloats = 0
+local last = nil
+local default = "text"
+local pushed = { }
local function initialize()
return {
@@ -98,7 +105,7 @@ end
function floats.save(which,data)
which = which or default
- local b = texbox.floatbox
+ local b = texgetbox("floatbox")
if b then
local stack = stacks[which]
noffloats = noffloats + 1
@@ -108,7 +115,7 @@ function floats.save(which,data)
data = data or { },
box = copy_node_list(b),
}
- texbox.floatbox = nil
+ texsetbox("floatbox",nil)
insert(stack,t)
setcount("global","savednoffloats",#stacks[default])
if trace_floats then
@@ -125,10 +132,10 @@ function floats.resave(which)
if last then
which = which or default
local stack = stacks[which]
- local b = texbox.floatbox
+ local b = texgetbox("floatbox")
local w, h, d = b.width, b.height, b.depth
last.box = copy_node_list(b)
- texbox.floatbox = nil
+ texsetbox("floatbox",nil)
insert(stack,1,last)
setcount("global","savednoffloats",#stacks[default])
if trace_floats then
@@ -152,7 +159,7 @@ function floats.flush(which,n,bylabel)
else
interfaces.showmessage("floatblocks",3,t.n)
end
- texbox.floatbox = b
+ texsetbox("floatbox",b)
last = remove(stack,n)
last.box = nil
setcount("global","savednoffloats",#stacks[default]) -- default?
diff --git a/tex/context/base/page-inj.lua b/tex/context/base/page-inj.lua
index f9b56fddb..56e5a234e 100644
--- a/tex/context/base/page-inj.lua
+++ b/tex/context/base/page-inj.lua
@@ -8,6 +8,8 @@ if not modules then modules = { } end modules ["page-inj"] = {
-- Adapted a bit by HH: numbered states, tracking, delayed, order, etc.
+local type, tonumber = type, tonumber
+
local injections = pagebuilders.injections or { }
pagebuilders.injections = injections
@@ -19,6 +21,8 @@ local variables = interfaces.variables
local context = context
local commands = commands
+local texsetcount = tex.setcount
+
local v_yes = variables.yes
local v_previous = variables.previous
local v_next = variables.next
@@ -34,7 +38,7 @@ function injections.save(specification) -- maybe not public, just commands.*
state = tonumber(specification.state) or specification.state,
parameters = specification.userdata,
}
- tex.setcount("global","c_page_boxes_flush_n",#cache)
+ texsetcount("global","c_page_boxes_flush_n",#cache)
end
function injections.flushbefore() -- maybe not public, just commands.*
@@ -65,7 +69,7 @@ function injections.flushbefore() -- maybe not public, just commands.*
end
context.unprotect()
cache = delayed
- tex.setcount("global","c_page_boxes_flush_n",#cache)
+ texsetcount("global","c_page_boxes_flush_n",#cache)
end
end
@@ -95,7 +99,7 @@ function injections.flushafter() -- maybe not public, just commands.*
end
context.protect()
cache = delayed
- tex.setcount("global","c_page_boxes_flush_n",#cache)
+ texsetcount("global","c_page_boxes_flush_n",#cache)
end
end
diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua
index e6b500e8b..7e8e9ad8a 100644
--- a/tex/context/base/page-lin.lua
+++ b/tex/context/base/page-lin.lua
@@ -12,8 +12,6 @@ local trace_numbers = false trackers.register("lines.numbers", function(v) tra
local report_lines = logs.reporter("lines")
-local texbox = tex.box
-
local attributes, nodes, node, context = attributes, nodes, node, context
nodes.lines = nodes.lines or { }
@@ -23,6 +21,8 @@ lines.data = lines.data or { } -- start step tag
local data = lines.data
local last = #data
+local texgetbox = tex.getbox
+
lines.scratchbox = lines.scratchbox or 0
local leftmarginwidth = nodes.leftmarginwidth
@@ -208,7 +208,7 @@ local function identify(list)
end
function boxed.stage_zero(n)
- return identify(texbox[n].list)
+ return identify(texgetbox(n).list)
end
-- reset ranges per page
@@ -217,9 +217,9 @@ end
function boxed.stage_one(n,nested)
current_list = { }
- local head = texbox[n]
- if head then
- local list = head.list
+ local box = texgetbox(n)
+ if box then
+ local list = box.list
if nested then
list = identify(list)
end
@@ -268,7 +268,7 @@ function boxed.stage_two(n,m)
if #current_list > 0 then
m = m or lines.scratchbox
local t, tn = { }, 0
- for l in traverse_id(hlist_code,texbox[m].list) do
+ for l in traverse_id(hlist_code,texgetbox(m).list) do
tn = tn + 1
t[tn] = copy_node(l)
end
diff --git a/tex/context/base/page-lin.mkiv b/tex/context/base/page-lin.mkiv
index 0f8b78398..876d2e781 100644
--- a/tex/context/base/page-lin.mkiv
+++ b/tex/context/base/page-lin.mkiv
@@ -156,28 +156,28 @@
% todo: text
-\installcorenamespace{linennumberinglocation}
-\installcorenamespace{linennumberingalternative}
-
-\expandafter\let\csname\??linennumberinglocation\v!middle \endcsname \zerocount
-\expandafter\let\csname\??linennumberinglocation\v!left \endcsname \plusone
-\expandafter\let\csname\??linennumberinglocation\v!margin \endcsname \plusone
-\expandafter\let\csname\??linennumberinglocation\v!inmargin \endcsname \plusone
-\expandafter\let\csname\??linennumberinglocation\v!inleft \endcsname \plusone
-\expandafter\let\csname\??linennumberinglocation\v!right \endcsname \plustwo
-\expandafter\let\csname\??linennumberinglocation\v!inright \endcsname \plustwo
-\expandafter\let\csname\??linennumberinglocation\v!inner \endcsname \plusthree
-\expandafter\let\csname\??linennumberinglocation\v!outer \endcsname \plusfour
-\expandafter\let\csname\??linennumberinglocation\v!text \endcsname \plusfive
-\expandafter\let\csname\??linennumberinglocation\v!begin \endcsname \plussix
-\expandafter\let\csname\??linennumberinglocation\v!end \endcsname \plusseven
-
-\expandafter\let\csname\??linennumberingalternative\v!middle \endcsname \zerocount
-\expandafter\let\csname\??linennumberingalternative\v!right \endcsname \plusone
-\expandafter\let\csname\??linennumberingalternative\v!flushleft \endcsname \plusone
-\expandafter\let\csname\??linennumberingalternative\v!left \endcsname \plustwo
-\expandafter\let\csname\??linennumberingalternative\v!flushright\endcsname \plustwo
-\expandafter\let\csname\??linennumberingalternative\v!auto \endcsname \plusfive
+\installcorenamespace{linenumberinglocation}
+\installcorenamespace{linenumberingalternative}
+
+\expandafter\let\csname\??linenumberinglocation\v!middle \endcsname \zerocount
+\expandafter\let\csname\??linenumberinglocation\v!left \endcsname \plusone
+\expandafter\let\csname\??linenumberinglocation\v!margin \endcsname \plusone
+\expandafter\let\csname\??linenumberinglocation\v!inmargin \endcsname \plusone
+\expandafter\let\csname\??linenumberinglocation\v!inleft \endcsname \plusone
+\expandafter\let\csname\??linenumberinglocation\v!right \endcsname \plustwo
+\expandafter\let\csname\??linenumberinglocation\v!inright \endcsname \plustwo
+\expandafter\let\csname\??linenumberinglocation\v!inner \endcsname \plusthree
+\expandafter\let\csname\??linenumberinglocation\v!outer \endcsname \plusfour
+\expandafter\let\csname\??linenumberinglocation\v!text \endcsname \plusfive
+\expandafter\let\csname\??linenumberinglocation\v!begin \endcsname \plussix
+\expandafter\let\csname\??linenumberinglocation\v!end \endcsname \plusseven
+
+\expandafter\let\csname\??linenumberingalternative\v!middle \endcsname \zerocount
+\expandafter\let\csname\??linenumberingalternative\v!right \endcsname \plusone
+\expandafter\let\csname\??linenumberingalternative\v!flushleft \endcsname \plusone
+\expandafter\let\csname\??linenumberingalternative\v!left \endcsname \plustwo
+\expandafter\let\csname\??linenumberingalternative\v!flushright\endcsname \plustwo
+\expandafter\let\csname\??linenumberingalternative\v!auto \endcsname \plusfive
% \startlinenumbering[<startvalue>|continue|settings|name]
% \startlinenumbering[name][<startvalue>|continue|settings]
@@ -339,8 +339,8 @@
\else
\setfalse\c_page_lines_fake_number
\fi
- \c_page_lines_location \executeifdefined{\??linennumberinglocation \linenumberingparameter\c!location}\plusone \relax % left
- \c_page_lines_alignment\executeifdefined{\??linennumberingalternative\linenumberingparameter\c!align }\plusfive\relax % auto
+ \c_page_lines_location \executeifdefined{\??linenumberinglocation \linenumberingparameter\c!location}\plusone \relax % left
+ \c_page_lines_alignment\executeifdefined{\??linenumberingalternative\linenumberingparameter\c!align }\plusfive\relax % auto
\ifcase\c_page_lines_last_column\relax
\settrue \c_page_lines_fake_number
\or
diff --git a/tex/context/base/page-mix.lua b/tex/context/base/page-mix.lua
index f265ac8f9..f86e2f279 100644
--- a/tex/context/base/page-mix.lua
+++ b/tex/context/base/page-mix.lua
@@ -34,11 +34,14 @@ local new_glue = nodepool.glue
local hpack = node.hpack
local vpack = node.vpack
local freenode = node.free
+local concatnodes = nodes.concat
+
+local texgetbox = tex.getbox
+local texsetbox = tex.setbox
+local texgetskip = tex.getskip
-local texbox = tex.box
-local texskip = tex.skip
-local texdimen = tex.dimen
local points = number.points
+
local settings_to_hash = utilities.parsers.settings_to_hash
local variables = interfaces.variables
@@ -79,7 +82,7 @@ local function collectinserts(result,nxt,nxtid)
if not c then
c = { }
inserts[s] = c
- local width = texskip[s].width
+ local width = texgetskip(s).width
if not result.inserts[s] then
currentskips = currentskips + width
end
@@ -199,7 +202,7 @@ local function setsplit(specification) -- a rather large function
report_state("fatal error, no box")
return
end
- local list = texbox[box]
+ local list = texgetbox(box)
if not list then
report_state("fatal error, no list")
return
@@ -464,7 +467,7 @@ local function setsplit(specification) -- a rather large function
specification.overflow = overflow
specification.discarded = discarded
- texbox[specification.box].head = nil
+ texgetbox(specification.box).list = nil
return specification
end
@@ -613,9 +616,9 @@ function mixedcolumns.getsplit(result,n)
end
for c, list in next, r.inserts do
- -- tex.setbox("global",c,vpack(nodes.concat(list)))
- -- tex.setbox(c,vpack(nodes.concat(list)))
- texbox[c] = vpack(nodes.concat(list))
+ local b = vpack(concatnodes(list)) -- multiple arguments
+ -- texsetbox("global",c,b)
+ texsetbox(c,b)
r.inserts[c] = nil
end
diff --git a/tex/context/base/page-mix.mkiv b/tex/context/base/page-mix.mkiv
index ef26c5f70..56a1249ca 100644
--- a/tex/context/base/page-mix.mkiv
+++ b/tex/context/base/page-mix.mkiv
@@ -59,7 +59,7 @@
%\c!align=, % inherit
%\c!before=,
%\c!after=,
- %\c!rule=\v!none,
+ %\c!separator=\v!none,
%\c!setups=,
\c!frame=\v!off,
\c!strut=\v!no,
@@ -69,6 +69,7 @@
\c!maxwidth=\makeupwidth,
\c!grid=\v!tolerant,
\c!step=.25\lineheight, % needs some experimenting
+ %\c!splitmethod=\v!fixed, % will be default
\c!method=\ifinner\s!box\else\s!otr\fi] % automatic as suggested by WS
\let\startmixedcolumns\relax % defined later
@@ -163,7 +164,8 @@
\definemixedcolumns
[\s!itemgroupcolumns]
[\c!n=\itemgroupparameter\c!n,
- \c!rule=\v!off,
+ \c!separator=\v!none,
+ \c!splitmethod=\v!none,
\c!balance=\v!yes]
\unexpanded\def\strc_itemgroups_start_columns
@@ -294,7 +296,7 @@
\unexpanded\def\page_mix_command_inject_separator
{\bgroup
\hss
- \csname\??mixedcolumnsseparator\mixedcolumnsparameter\c!separator\endcsname
+ \csname\??mixedcolumnsseparator\mixedcolumnsparameter\c!separator\endcsname % was \c!rule
\hss
\egroup}
@@ -487,10 +489,17 @@
\usealignparameter\mixedcolumnsparameter
\usesetupsparameter\mixedcolumnsparameter}
+% \setvalue{\??mixedcolumnsstop\s!otr}%
+% {\par
+% \ifcase\c_page_mix_otr_nesting\or
+% \c_page_mix_routine\c_page_mix_routine_balance
+% \page_otr_trigger_output_routine
+% \fi}
+
\setvalue{\??mixedcolumnsstop\s!otr}%
{\par
\ifcase\c_page_mix_otr_nesting\or
- \c_page_mix_routine\c_page_mix_routine_balance
+ \doif{\mixedcolumnsparameter\c!balance}\v!yes{\c_page_mix_routine\c_page_mix_routine_balance}%
\page_otr_trigger_output_routine
\fi}
@@ -518,34 +527,13 @@
strutht = \number\strutht,
strutdp = \number\strutdp,
threshold = \number\d_page_mix_threshold,
+ splitmethod = "\mixedcolumnsparameter\c!splitmethod",
balance = "#1",
alternative = "\mixedcolumnsparameter\c!alternative",
grid = \ifgridsnapping true\else false\fi,
}}%
\deadcycles\zerocount}
-% \unexpanded\def\page_mix_routine_package
-% {\ctxcommand{mixfinalize()}%
-% \setbox\b_page_mix_collected\vbox \bgroup
-% \ifvoid\b_page_mix_preceding \else
-% \box\b_page_mix_preceding
-% \global\d_page_mix_preceding_height\zeropoint
-% \nointerlineskip
-% \fi
-% \hskip\d_page_mix_leftskip
-% \page_mix_hbox to \d_page_mix_max_width \bgroup
-% \letmixedcolumnsparameter\c!strut \v!no
-% \letmixedcolumnsparameter\c!align \empty % probably not needed as we could use a simple variant
-% \letmixedcolumnsparameter\c!setups\empty
-% \dorecurse\c_page_mix_n_of_columns {%
-% \inheritedmixedcolumnsframed{\page_mix_command_package_column}%
-% \ifnum\recurselevel<\c_page_mix_n_of_columns
-% \page_mix_command_inject_separator
-% \fi
-% }%
-% \egroup
-% \egroup}
-
\unexpanded\def\page_mix_routine_package
{\ctxcommand{mixfinalize()}%
\setbox\b_page_mix_collected\vbox \bgroup
@@ -557,9 +545,13 @@
\hskip\d_page_mix_leftskip
\page_mix_hbox to \d_page_mix_max_width \bgroup
\dorecurse\c_page_mix_n_of_columns{%
- % \inheritedmixedcolumnsframed{\page_mix_command_package_column}% needs reset of strut, align, setups etc
- \setbox\scratchbox\page_mix_command_package_column % needs packaging anyway
+ % needs packaging anyway
+ \setbox\scratchbox\page_mix_command_package_column
+ % for the moment a quick and dirty patch .. we need to go into the box (hence the \plusone) .. a slowdowner
+ \page_lines_add_numbers_to_box\scratchbox\recurselevel\c_page_mix_n_of_columns\plusone
+ % the framed needs a reset of strut, align, setups etc
\inheritedmixedcolumnsframedbox\currentmixedcolumns\scratchbox
+ % optional
\ifnum\recurselevel<\c_page_mix_n_of_columns
\page_mix_command_inject_separator
\fi
diff --git a/tex/context/base/page-pst.lua b/tex/context/base/page-pst.lua
index f714c25d9..2fc400a14 100644
--- a/tex/context/base/page-pst.lua
+++ b/tex/context/base/page-pst.lua
@@ -8,12 +8,16 @@ if not modules then modules = { } end modules ['page-pst'] = {
-- todo: adapt message
+local tonumber, next = tonumber, next
local format, validstring = string.format, string.valid
local sortedkeys = table.sortedkeys
local context = context
local commands = commands
+local texgetcount = tex.getcount
+local texsetcount = tex.setcount
+
local cache = { }
local function flush(page)
@@ -35,14 +39,14 @@ local function setnextpage()
elseif n > 0 then
-- upcoming page (realpageno)
end
- tex.setcount("global","c_page_postponed_blocks_next_page",n)
+ texsetcount("global","c_page_postponed_blocks_next_page",n)
end
function commands.flushpostponedblocks(page)
-- we need to flush previously pending pages as well and the zero
-- slot is the generic one so that one is always flushed
local t = sortedkeys(cache)
- local p = tonumber(page) or tex.count.realpageno or 0
+ local p = tonumber(page) or texgetcount("realpageno") or 0
for i=1,#t do
local ti = t[i]
if ti <= p then
@@ -57,7 +61,7 @@ end
function commands.registerpostponedblock(page)
if type(page) == "string" then
if string.find(page,"^+") then
- page = tex.count.realpageno + (tonumber(page) or 1) -- future delta page
+ page = texgetcount("realpageno") + (tonumber(page) or 1) -- future delta page
else
page = tonumber(page) or 0 -- preferred page or otherwise first possible occasion
end
diff --git a/tex/context/base/page-str.lua b/tex/context/base/page-str.lua
index f6314657f..35ce85609 100644
--- a/tex/context/base/page-str.lua
+++ b/tex/context/base/page-str.lua
@@ -12,18 +12,25 @@ if not modules then modules = { } end modules ['page-str'] = {
local concat, insert, remove = table.concat, table.insert, table.remove
-local find_tail, write_node, free_node, copy_nodelist = node.slide, node.write, node.free, node.copy_list
-local vpack_nodelist, hpack_nodelist = node.vpack, node.hpack
-local texdimen, texbox = tex.dimen, tex.box
-local settings_to_array = utilities.parsers.settings_to_array
-
local nodes, node = nodes, node
-local nodepool = nodes.pool
-local tasks = nodes.tasks
+local nodepool = nodes.pool
+local tasks = nodes.tasks
+
+local new_kern = nodepool.kern
+local new_glyph = nodepool.glyph
+
+local find_tail = node.slide
+local write_node = node.write
+local free_node = node.free
+local copy_nodelist = node.copy_list
+local vpack_nodelist = node.vpack
+local hpack_nodelist = node.hpack
+
+local settings_to_array = utilities.parsers.settings_to_array
-local new_kern = nodepool.kern
-local new_glyph = nodepool.glyph
+local texgetdimen = tex.getdimen
+local texgetbox = tex.getbox
local trace_collecting = false trackers.register("streams.collecting", function(v) trace_collecting = v end)
local trace_flushing = false trackers.register("streams.flushing", function(v) trace_flushing = v end)
@@ -175,7 +182,8 @@ function streams.synchronize(list) -- this is an experiment !
if trace_flushing then
report_streams("slot %s has max height %p and max depth %p",m,height,depth)
end
- local strutht, strutdp = texdimen.globalbodyfontstrutheight, texdimen.globalbodyfontstrutdepth
+ local strutht = texgetdimen("globalbodyfontstrutheight")
+ local strutdp = texgetdimen("globalbodyfontstrutdepth")
local struthtdp = strutht + strutdp
for i=1,#list do
local name = list[i]
@@ -198,7 +206,7 @@ function streams.synchronize(list) -- this is an experiment !
local n, delta = 0, delta_height -- for tracing
while delta > 0 do
-- we need to add some interline penalties
- local line = copy_nodelist(tex.box.strutbox)
+ local line = copy_nodelist(texgetbox("strutbox"))
line.height, line.depth = strutht, strutdp
if tail then
tail.next, line.prev = line, tail
diff --git a/tex/context/base/s-inf-03.pdf b/tex/context/base/s-inf-03.pdf
new file mode 100644
index 000000000..a2de80fab
--- /dev/null
+++ b/tex/context/base/s-inf-03.pdf
Binary files differ
diff --git a/tex/context/base/scrn-fld.lua b/tex/context/base/scrn-fld.lua
index 9836cbebe..69480b887 100644
--- a/tex/context/base/scrn-fld.lua
+++ b/tex/context/base/scrn-fld.lua
@@ -11,6 +11,8 @@ if not modules then modules = { } end modules ['scrn-fld'] = {
local variables = interfaces.variables
local v_yes = variables.yes
+local texsetbox = tex.setbox
+
local fields = { }
interactions.fields = fields
@@ -43,7 +45,7 @@ commands.definefieldset = defineset
commands.clonefield = clone
function commands.insertfield(name,specification)
- tex.box["b_scrn_field_body"] = insert(name,specification)
+ texsetbox("b_scrn_field_body",insert(name,specification))
end
-- (for the monent) only tex interface
diff --git a/tex/context/base/scrn-hlp.lua b/tex/context/base/scrn-hlp.lua
index 1e9d1f570..d344ce280 100644
--- a/tex/context/base/scrn-hlp.lua
+++ b/tex/context/base/scrn-hlp.lua
@@ -21,6 +21,8 @@ local hpack_nodelist = node.hpack
local register_list = nodes.pool.register
+local texgetbox = tex.getbox
+
local nodecodes = nodes.nodecodes
local hlist_code = nodecodes.hlist
@@ -51,7 +53,7 @@ function help.register(number,name,box)
interactions.javascripts.setpreamble("HelpTexts",helpscript)
helpscript = false
end
- local b = copy_nodelist(tex.box[box])
+ local b = copy_nodelist(texgetbox(box))
register_list(b)
data[number] = b
if name and name ~= "" then
@@ -84,7 +86,7 @@ end
function help.collect(box)
if next(data) then
- return collect(tex.box[box].list)
+ return collect(texgetbox(box).list)
end
end
diff --git a/tex/context/base/scrn-wid.lua b/tex/context/base/scrn-wid.lua
index a2b3e28b9..90aaed609 100644
--- a/tex/context/base/scrn-wid.lua
+++ b/tex/context/base/scrn-wid.lua
@@ -24,8 +24,12 @@ interactions.soundclips = soundclips
interactions.renderings = renderings
interactions.linkedlists = linkedlists
+local texsetbox = tex.setbox
+
local jobpasses = job.passes
+local texgetcount = tex.getcount
+
local codeinjections = backends.codeinjections
local nodeinjections = backends.nodeinjections
@@ -107,7 +111,7 @@ end
commands.registerattachment = attachments.register
function commands.insertattachment(specification)
- tex.box["b_scrn_attachment_link"] = attachments.insert(specification)
+ texsetbox("b_scrn_attachment_link",attachments.insert(specification))
end
-- Comment
@@ -121,7 +125,7 @@ function comments.insert(specification)
end
function commands.insertcomment(specification)
- tex.box["b_scrn_comment_link"] = comments.insert(specification)
+ texsetbox("b_scrn_comment_link",comments.insert(specification))
end
-- Soundclips
@@ -199,7 +203,7 @@ end
function commands.enhancelinkedlist(tag,n)
local ll = jobpasses.gettobesaved(tag)
if ll then
- ll[n] = texcount.realpageno
+ ll[n] = texgetcount("realpageno")
end
end
diff --git a/tex/context/base/scrn-wid.mkvi b/tex/context/base/scrn-wid.mkvi
index ae5f7c556..fad451651 100644
--- a/tex/context/base/scrn-wid.mkvi
+++ b/tex/context/base/scrn-wid.mkvi
@@ -16,6 +16,7 @@
\registerctxluafile{scrn-wid}{1.001}
% todo: expansion in comments (default is expanded)
+% todo: check renderings ... acrobat crashes too easily on missing one
\unprotect
@@ -566,8 +567,8 @@
\definereference[PauseCurrentRendering] [\v!PauseRendering {\currentrendering}]
\definereference[ResumeCurrentRendering][\v!ResumeRendering{\currentrendering}]
-\def\useexternalrendering{\doquadrupleempty\scrn_rendering_use}
-\def\setinternalrendering{\dodoubleempty \scrn_rendering_set}
+\unexpanded\def\useexternalrendering{\doquadrupleempty\scrn_rendering_use}
+\unexpanded\def\setinternalrendering{\dodoubleempty \scrn_rendering_set}
\def\scrn_rendering_use[#tag][#mime][#file][#option]%
{\ctxcommand{registerrendering{
@@ -578,7 +579,7 @@
option = "#option",
}}}
-\def\scrn_rendering_set[#tag][#option]% {content}
+\def\scrn_rendering_set[#tag][#option]% {content} % crappy
{\bgroup
\dowithnextbox
{\ctxcommand{registerrendering{
@@ -615,17 +616,9 @@
\unexpanded\def\placerenderingwindow
{\dodoubleempty\scrn_rendering_place_window}
-\def\scrn_rendering_place_window[#window][#rendering]%
+\def\scrn_rendering_place_window[#window][#rendering]% do all in lua
{\bgroup
\edef\currentrendering{\ifsecondargument#rendering\else#window\fi}%
- \doifelse{\renderingtype\currentrendering}{internal} % an object
- {\getobjectdimensions{IRO}\currentrendering
- \d_scrn_rendering_height\dimexpr\objectheight+\objectdepth\relax
- \d_scrn_rendering_width\objectwidth\relax
- \dogetobjectreferencepage{IRO}\currentrendering\m_scrn_rendering_page}%
- {\d_scrn_rendering_height\vsize
- \d_scrn_rendering_width\hsize
- \let\m_scrn_rendering_page\realpageno}%
% create fall back if needed
\edef\currentrenderingwindow{\namedrenderingwindowparameter{#window}\c!width}% stupid test, we need a proper one here
\ifx\currentrenderingwindow\empty
@@ -634,6 +627,21 @@
\else
\edef\currentrenderingwindow{#window}%
\fi
+ \edef\currentrenderingtype{\renderingtype\currentrendering}%
+ \ifx\currentrenderingtype\s!internal
+ \getobjectdimensions{IRO}\currentrendering
+ \d_scrn_rendering_height\dimexpr\objectheight+\objectdepth\relax
+ \d_scrn_rendering_width\objectwidth\relax
+ \dogetobjectreferencepage{IRO}\currentrendering\m_scrn_rendering_page
+ \else\ifx\currentrenderingwindow\s!default
+ \d_scrn_rendering_height\vsize
+ \d_scrn_rendering_width \hsize
+ \let\m_scrn_rendering_page\realpageno
+ \else
+ \d_scrn_rendering_height\renderingwindowparameter\c!height
+ \d_scrn_rendering_width \renderingwindowparameter\c!width
+ \let\m_scrn_rendering_page\realpageno
+ \fi\fi
% todo:
% \handlereferenceactions{\renderingwindowparameter\c!openpageaction }\dosetuprenderingopenpageaction
% \handlereferenceactions{\renderingwindowparameter\c!closepageaction}\dosetuprenderingclosepageaction
diff --git a/tex/context/base/spac-ali.lua b/tex/context/base/spac-ali.lua
index ceb278433..25cc6cd66 100644
--- a/tex/context/base/spac-ali.lua
+++ b/tex/context/base/spac-ali.lua
@@ -20,8 +20,6 @@ local hpack_nodes = node.hpack -- nodes.fasthpack not really faster here
local unsetvalue = attributes.unsetvalue
-local concat_nodes = nodes.concat
-
local nodecodes = nodes.nodecodes
local listcodes = nodes.listcodes
@@ -35,8 +33,8 @@ local new_stretch = nodepool.stretch
local a_realign = attributes.private("realign")
-local texattribute = tex.attribute
-local texcount = tex.count
+local texsetattribute = tex.setattribute
+local texgetcount = tex.getcount
local isleftpage = layouts.status.isleftpage
@@ -77,12 +75,12 @@ local function handler(head,leftpage,realpageno)
action = leftpage and 2 or 1
end
if action == 1 then
- current.list = hpack_nodes(concat_nodes{current.list,new_stretch(3)},current.width,"exactly")
+ current.list = hpack_nodes(current.list .. new_stretch(3),current.width,"exactly")
if trace_realign then
report_realign("flushing left, align %a, page %a, realpage %a",align,pageno,realpageno)
end
elseif action == 2 then
- current.list = hpack_nodes(concat_nodes{new_stretch(3),current.list},current.width,"exactly")
+ current.list = hpack_nodes(new_stretch(3) .. current.list,current.width,"exactly")
if trace_realign then
report_realign("flushing right. align %a, page %a, realpage %a",align,pageno,realpageno)
end
@@ -106,7 +104,7 @@ end
function alignments.handler(head)
local leftpage = isleftpage(true,false)
- local realpageno = texcount.realpageno
+ local realpageno = texgetcount("realpageno")
return handler(head,leftpage,realpageno)
end
@@ -120,7 +118,7 @@ function alignments.set(n)
report_realign("enabled")
end
end
- texattribute[a_realign] = texcount.realpageno * 10 + n
+ texsetattribute(a_realign,texgetcount("realpageno") * 10 + n)
end
commands.setrealign = alignments.set
diff --git a/tex/context/base/spac-chr.lua b/tex/context/base/spac-chr.lua
index 24364978a..f3c62bb77 100644
--- a/tex/context/base/spac-chr.lua
+++ b/tex/context/base/spac-chr.lua
@@ -74,7 +74,6 @@ local function inject_char_space(unicode,head,current,parent)
local font = current.font
local char = fontcharacters[font][parent]
local glue = new_glue(char and char.width or fontparameters[font].space)
- -- glue.attr = copy_node_list(current.attr)
glue.attr = current.attr
current.attr = nil
glue[a_character] = unicode
@@ -86,10 +85,8 @@ local function inject_nobreak_space(unicode,head,current,space,spacestretch,spac
local attr = current.attr
local glue = new_glue(space,spacestretch,spaceshrink)
local penalty = new_penalty(10000)
- -- glue.attr = copy_node_list(attr)
glue.attr = attr
current.attr = nil
- -- penalty.attr = attr
glue[a_character] = unicode
head, current = insert_node_after(head,current,penalty)
head, current = insert_node_after(head,current,glue)
diff --git a/tex/context/base/spac-ver.lua b/tex/context/base/spac-ver.lua
index 36fa357d0..406896e4d 100644
--- a/tex/context/base/spac-ver.lua
+++ b/tex/context/base/spac-ver.lua
@@ -23,8 +23,7 @@ if not modules then modules = { } end modules ['spac-ver'] = {
local next, type, tonumber = next, type, tonumber
local gmatch, concat = string.gmatch, table.concat
-local ceil, floor, max, min, round, abs = math.ceil, math.floor, math.max, math.min, math.round, math.abs
-local texlists, texdimen, texbox = tex.lists, tex.dimen, tex.box
+local ceil, floor = math.ceil, math.floor
local lpegmatch = lpeg.match
local unpack = unpack or table.unpack
local allocate = utilities.storage.allocate
@@ -33,12 +32,13 @@ local formatters = string.formatters
local P, C, R, S, Cc = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc
-local nodes, node, trackers, attributes, context, commands = nodes, node, trackers, attributes, context, commands
+local nodes, node, trackers, attributes, context, commands, tex = nodes, node, trackers, attributes, context, commands, tex
-local variables = interfaces.variables
+----- texlists = tex.lists
+local texgetdimen = tex.getdimen
+local texgetbox = tex.getbox
-local starttiming = statistics.starttiming
-local stoptiming = statistics.stoptiming
+local variables = interfaces.variables
-- vertical space handler
@@ -87,7 +87,6 @@ local new_gluespec = nodepool.gluespec
local nodecodes = nodes.nodecodes
local skipcodes = nodes.skipcodes
-local fillcodes = nodes.fillcodes
local penalty_code = nodecodes.penalty
local kern_code = nodecodes.kern
@@ -96,7 +95,6 @@ local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local whatsit_code = nodecodes.whatsit
-local userskip_code = skipcodes.userskip
local vspacing = builders.vspacing or { }
builders.vspacing = vspacing
@@ -288,20 +286,24 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is
local snapht, snapdp
if method["local"] then
-- snapping is done immediately here
- snapht, snapdp = texdimen.bodyfontstrutheight, texdimen.bodyfontstrutdepth
+ snapht = texgetdimen("bodyfontstrutheight")
+ snapdp = texgetdimen("bodyfontstrutdepth")
if t then
t[#t+1] = formatters["local: snapht %p snapdp %p"](snapht,snapdp)
end
elseif method["global"] then
- snapht, snapdp = texdimen.globalbodyfontstrutheight, texdimen.globalbodyfontstrutdepth
+ snapht = texgetdimen("globalbodyfontstrutheight")
+ snapdp = texgetdimen("globalbodyfontstrutdepth")
if t then
t[#t+1] = formatters["global: snapht %p snapdp %p"](snapht,snapdp)
end
else
-- maybe autolocal
-- snapping might happen later in the otr
- snapht, snapdp = texdimen.globalbodyfontstrutheight, texdimen.globalbodyfontstrutdepth
- local lsnapht, lsnapdp = texdimen.bodyfontstrutheight, texdimen.bodyfontstrutdepth
+ snapht = texgetdimen("globalbodyfontstrutheight")
+ snapdp = texgetdimen("globalbodyfontstrutdepth")
+ local lsnapht = texgetdimen("bodyfontstrutheight")
+ local lsnapdp = texgetdimen("bodyfontstrutdepth")
if snapht ~= lsnapht and snapdp ~= lsnapdp then
snapht, snapdp = lsnapht, lsnapdp
end
@@ -342,13 +344,16 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is
id = thebox and thebox.id
end
if thebox and id == vlist_code then
- local list, lh, ld = thebox.list
+ local list = thebox.list
+ local lh, ld
for n in traverse_nodes_id(hlist_code,list) do
- lh, ld = n.height, n.depth
+ lh = n.height
+ ld = n.depth
break
end
if lh then
- local ht, dp = thebox.height, thebox.depth
+ local ht = thebox.height
+ local dp = thebox.depth
if t then
t[#t+1] = formatters["first line: height %p depth %p"](lh,ld)
t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp)
@@ -379,10 +384,12 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is
if thebox and id == vlist_code then
local list, lh, ld = thebox.list
for n in traverse_nodes_id(hlist_code,list) do
- lh, ld = n.height, n.depth
+ lh = n.height
+ ld = n.depth
end
if lh then
- local ht, dp = thebox.height, thebox.depth
+ local ht = thebox.height
+ local dp = thebox.depth
if t then
t[#t+1] = formatters["last line: height %p depth %p" ](lh,ld)
t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp)
@@ -479,7 +486,7 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is
local lines = (ch+cd)/snaphtdp
if t then
local original = (h+d)/snaphtdp
- local whatever = (ch+cd)/(texdimen.globalbodyfontstrutheight + texdimen.globalbodyfontstrutdepth)
+ local whatever = (ch+cd)/(texgetdimen("globalbodyfontstrutheight") + texgetdimen("globalbodyfontstrutdepth"))
t[#t+1] = formatters["final lines: %s -> %s (%s)"](original,lines,whatever)
t[#t+1] = formatters["final height: %p -> %p"](h,ch)
t[#t+1] = formatters["final depth: %p -> %p"](d,cd)
@@ -495,7 +502,8 @@ local function snap_topskip(current,method)
local w = spec.width
local wd = w
if spec.writable then
- spec.width, wd = 0, 0
+ spec.width = 0
+ wd = 0
end
return w, wd
end
@@ -740,21 +748,11 @@ local topskip_code = skipcodes.topskip
local splittopskip_code = skipcodes.splittopskip
local free_glue_node = free_node
-local discard, largest, force, penalty, add, disable, nowhite, goback, together = 0, 1, 2, 3, 4, 5, 6, 7, 8
-
--- local function free_glue_node(n)
--- -- free_node(n.spec)
--- print("before",n)
--- logs.flush()
--- free_node(n)
--- print("after")
--- logs.flush()
--- end
function vspacing.snapbox(n,how)
local sv = snapmethods[how]
if sv then
- local box = texbox[n]
+ local box = texgetbox(n)
local list = box.list
if list then
local s = list[a_snapmethod]
@@ -763,7 +761,8 @@ function vspacing.snapbox(n,how)
-- report_snapper("box list not snapped, already done")
end
else
- local ht, dp = box.height, box.depth
+ local ht = box.height
+ local dp = box.depth
if false then -- todo: already_done
-- assume that the box is already snapped
if trace_vsnapping then
@@ -772,7 +771,8 @@ function vspacing.snapbox(n,how)
end
else
local h, d, ch, cd, lines = snap_hlist("box",box,sv,ht,dp)
- box.height, box.depth = ch, cd
+ box.height= ch
+ box.depth = cd
if trace_vsnapping then
report_snapper("box list snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s",
h,d,ch,cd,sv.name,sv.specification,"direct",lines,listtoutf(list))
@@ -805,6 +805,8 @@ end
-- penalty only works well when before skip
+local discard, largest, force, penalty, add, disable, nowhite, goback, together = 0, 1, 2, 3, 4, 5, 6, 7, 8 -- move into function when upvalue 60 issue
+
local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also pass tail
if trace then
reset_tracing(head)
@@ -823,11 +825,12 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
head = insert_node_before(head,current,p)
end
if glue_data then
+ local spec = glue_data.spec
if force_glue then
if trace then trace_done("flushed due to " .. why,glue_data) end
- head = forced_skip(head,current,glue_data.spec.width,"before",trace)
+ head = forced_skip(head,current,spec.width,"before",trace)
free_glue_node(glue_data)
- elseif glue_data.spec.writable then
+ elseif spec.writable then
if trace then trace_done("flushed due to " .. why,glue_data) end
head = insert_node_before(head,current,glue_data)
else
@@ -841,8 +844,9 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
end
if trace_vsnapping then
report_snapper("global ht/dp = %p/%p, local ht/dp = %p/%p",
- texdimen.globalbodyfontstrutheight, texdimen.globalbodyfontstrutdepth,
- texdimen.bodyfontstrutheight, texdimen.bodyfontstrutdepth)
+ texgetdimen("globalbodyfontstrutheight"), texgetdimen("globalbodyfontstrutdepth"),
+ texgetdimen("bodyfontstrutheight"), texgetdimen("bodyfontstrutdepth")
+ )
end
if trace then trace_info("start analyzing",where,what) end
while current do
@@ -865,7 +869,8 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
if sv then
-- check if already snapped
if list and already_done(id,list,a_snapmethod) then
- local ht, dp = current.height, current.depth
+ local ht = current.height
+ local dp = current.depth
-- assume that the box is already snapped
if trace_vsnapping then
report_snapper("mvl list already snapped at (%p,%p): %s",ht,dp,listtoutf(list))
@@ -936,9 +941,9 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
previous.spec = new_gluespec(pw + cw, pp + cp, pm + cm) -- else topskip can disappear
if trace then trace_natural("removed",current) end
head, current = remove_node(head, current, true)
- -- current = previous
+ -- current = previous
if trace then trace_natural("collapsed",previous) end
- -- current = current.next
+ -- current = current.next
else
if trace then trace_natural("filler",current) end
current = current.next
@@ -1075,7 +1080,8 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
if trace then trace_natural("ignored parskip",current) end
head, current = remove_node(head, current, true)
elseif glue_data then
- local ps, gs = current.spec, glue_data.spec
+ local ps = current.spec
+ local gs = glue_data.spec
if ps.writable and gs.writable and ps.width > gs.width then
glue_data.spec = copy_node(ps)
if trace then trace_natural("taking parskip",current) end
@@ -1131,11 +1137,14 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also
current = current.next
--
else -- other glue
- if snap and trace_vsnapping and current.spec.writable and current.spec.width ~= 0 then
- report_snapper("glue %p of type %a kept",current.spec.width,skipcodes[subtype])
- --~ current.spec.width = 0
+ if snap and trace_vsnapping then
+ local spec = current.spec
+ if spec.writable and spec.width ~= 0 then
+ report_snapper("glue %p of type %a kept",current.spec.width,skipcodes[subtype])
+ -- spec.width = 0
+ end
end
- if trace then trace_skip(formatted["glue of type %a"](subtype),sc,so,sp,current) end
+ if trace then trace_skip(formatter["glue of type %a"](subtype),sc,so,sp,current) end
flush("some glue")
current = current.next
end
@@ -1227,11 +1236,11 @@ function vspacing.pagehandler(newhead,where)
if stackhack then
stackhack = false
if trace_collect_vspacing then report("processing %s nodes: %s",newhead) end
---~ texlists.contrib_head = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod)
+ -- texlists.contrib_head = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod)
newhead = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod)
else
if trace_collect_vspacing then report("flushing %s nodes: %s",newhead) end
---~ texlists.contrib_head = newhead
+ -- texlists.contrib_head = newhead
end
else
if stackhead then
@@ -1258,97 +1267,21 @@ local ignore = table.tohash {
function vspacing.vboxhandler(head,where)
if head and not ignore[where] and head.next then
- -- starttiming(vspacing)
head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper
- -- stoptiming(vspacing)
end
return head
end
function vspacing.collapsevbox(n) -- for boxes but using global a_snapmethod
- local list = texbox[n].list
- if list then
- -- starttiming(vspacing)
- texbox[n].list = vpack_node(collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod))
- -- stoptiming(vspacing)
- end
-end
-
--- We will split this module so a few locals are repeated. Also this will be
--- rewritten.
-
-nodes.builders = nodes.builder or { }
-local builders = nodes.builders
-
-local actions = nodes.tasks.actions("vboxbuilders")
-
-function builders.vpack_filter(head,groupcode,size,packtype,maxdepth,direction)
- local done = false
- if head then
- starttiming(builders)
- if trace_vpacking then
- local before = nodes.count(head)
- head, done = actions(head,groupcode,size,packtype,maxdepth,direction)
- local after = nodes.count(head)
- if done then
- nodes.processors.tracer("vpack","changed",head,groupcode,before,after,true)
- else
- nodes.processors.tracer("vpack","unchanged",head,groupcode,before,after,true)
- end
- else
- head, done = actions(head,groupcode)
- end
- stoptiming(builders)
- end
- return head, done
-end
-
--- This one is special in the sense that it has no head and we operate on the mlv. Also,
--- we need to do the vspacing last as it removes items from the mvl.
-
-local actions = nodes.tasks.actions("mvlbuilders")
-
-local function report(groupcode,head)
- report_page_builder("trigger: %s",groupcode)
- report_page_builder(" vsize : %p",tex.vsize)
- report_page_builder(" pagegoal : %p",tex.pagegoal)
- report_page_builder(" pagetotal: %p",tex.pagetotal)
- report_page_builder(" list : %s",head and nodeidstostring(head) or "<empty>")
-end
-
-function builders.buildpage_filter(groupcode)
- local head, done = texlists.contrib_head, false
- -- if head and head.next and head.next.id == hlist_code and head.next.width == 1 then
- -- report_page_builder("trigger otr calculations")
- -- free_node_list(head)
- -- head = nil
- -- end
- if head then
- starttiming(builders)
- if trace_page_builder then
- report(groupcode,head)
- end
- head, done = actions(head,groupcode)
- stoptiming(builders)
- -- -- doesn't work here (not passed on?)
- -- tex.pagegoal = tex.vsize - tex.dimen.d_page_floats_inserted_top - tex.dimen.d_page_floats_inserted_bottom
- texlists.contrib_head = head
- return done and head or true
- else
- if trace_page_builder then
- report(groupcode)
+ local box = texgetbox(n)
+ if box then
+ local list = box.list
+ if list then
+ setfield(box,"list",vpack_node(collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod)))
end
- return nil, false
end
end
-callbacks.register('vpack_filter', builders.vpack_filter, "vertical spacing etc")
-callbacks.register('buildpage_filter', builders.buildpage_filter, "vertical spacing etc (mvl)")
-
-statistics.register("v-node processing time", function()
- return statistics.elapsedseconds(builders)
-end)
-
-- interface
commands.vspacing = vspacing.analyze
diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf
index bff528ee0..af631be91 100644
--- a/tex/context/base/status-files.pdf
+++ b/tex/context/base/status-files.pdf
Binary files differ
diff --git a/tex/context/base/status-lua.log b/tex/context/base/status-lua.log
new file mode 100644
index 000000000..71ade66ca
--- /dev/null
+++ b/tex/context/base/status-lua.log
@@ -0,0 +1,78 @@
+(cont-yes.mkiv
+
+ConTeXt ver: 2013.07.12 19:10 MKIV beta fmt: 2013.7.12 int: english/english
+
+system > 'cont-new.mkiv' loaded
+(cont-new.mkiv)
+system > 'cont-loc.mkiv' loaded
+(c:/data/develop/context/sources/cont-loc.mkiv)
+system > 'cont-exp.mkiv' loaded
+interface > macros > processed mkvi file 'c:/data/develop/context/sources/cont-exp.mkiv', delta 0
+interface > macros > processed mkvi file 'c:/data/develop/context/sources/cont-exp.mkiv', delta 0
+(c:/data/develop/context/sources/cont-exp.mkiv)
+system > files > jobname 's-inf-03', input './s-inf-03.mkiv', result 'status-lua.pdf'
+fonts > latin modern fonts are not preloaded
+languages > language 'en' is active
+(c:/data/develop/context/texmf/tex/context/base/s-inf-03.mkiv (c:/data/develop/context/sources/type-loc.mkiv) (type-imp-dejavu.mkiv) (type-imp-xits.mkiv (type-imp-texgyre.mkiv)){c:/data/develop/tex-context/tex/texmf-context/fonts/map/pdftex/context/mkiv-base.map} (virtual://buffer.noname.1
+references > unknown reference '[][]'
+references > unknown reference '[][attributes]'
+references > unknown reference '[][backends]'
+references > unknown reference '[][bibtex]'
+references > unknown reference '[][bit32]'
+references > unknown reference '[][blobs]'
+references > unknown reference '[][boolean]'
+references > unknown reference '[][buffers]'
+references > unknown reference '[][builders]'
+references > unknown reference '[][caches]'
+references > unknown reference '[][callback]'
+references > unknown reference '[][callbacks]'
+references > unknown reference '[][catcodes]'
+references > unknown reference '[][characters]'
+references > unknown reference '[][chemistry]'
+references > unknown reference '[][commands]'
+references > unknown reference '[][containers]'
+references > unknown reference '[][context]'
+references > unknown reference '[][converters]'
+references > unknown reference '[][coroutine]'
+references > unknown reference '[][ctxrunner]'
+references > unknown reference '[][debug]'
+references > unknown reference '[][dir]'
+references > unknown reference '[][directives]'
+references > unknown reference '[][document]'
+references > unknown reference '[][documentdata]'
+references > unknown reference '[][environment]'
+references > unknown reference '[][epdf]'
+references > unknown reference '[][experiments]'
+references > unknown reference '[][figures]'
+references > unknown reference '[][file]'
+references > unknown reference '[][floats]'
+references > unknown reference '[][font]'
+references > unknown reference '[][fontloader]'
+references > unknown reference '[][fonts]'
+references > unknown reference '[][functions]'
+references > unknown reference '[][graphics]'
+references > unknown reference '[][gzip]'
+references > unknown reference '[][img]'
+references > unknown reference '[][interactions]'
+references > unknown reference '[][interfaces]'
+references > unknown reference '[][io]'
+references > unknown reference '[][job]'
+references > unknown reference '[][lang]'
+references > unknown reference '[][languages]'
+references > unknown reference '[][layouts]'
+references > unknown reference '[][lfs]'
+references > unknown reference '[][libraries]'
+references > unknown reference '[][lmx]'
+references > unknown reference '[][logs]'
+references > unknown reference '[][lpdf]'
+references > unknown reference '[][lpeg]'
+references > unknown reference '[][ltn12]'
+references > unknown reference '[][lua]'
+references > unknown reference '[][luatex]'
+references > unknown reference '[][lxml]'
+references > unknown reference '[][math]'
+references > unknown reference '[][mathematics]'
+references > unknown reference '[][mbox]'
+references > unknown reference '[][md5]'
+references > unknown reference '[][metapost]'
+references > unknown reference '[][mime]' \ No newline at end of file
diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf
deleted file mode 100644
index c2a6132f1..000000000
--- a/tex/context/base/status-lua.pdf
+++ /dev/null
Binary files differ
diff --git a/tex/context/base/status-mkiv.lua b/tex/context/base/status-mkiv.lua
index 443eee60e..1e8d55c9c 100644
--- a/tex/context/base/status-mkiv.lua
+++ b/tex/context/base/status-mkiv.lua
@@ -3714,7 +3714,12 @@ return {
{
category = "lua",
filename = "m-database",
- status = "todo",
+ status = "okay",
+ },
+ {
+ category = "lua",
+ filename = "m-nodechart",
+ status = "okay",
},
{
category = "lua",
@@ -5090,7 +5095,12 @@ return {
{
category = "mkiv",
filename = "m-database",
- status = "todo",
+ status = "okay",
+ },
+ {
+ category = "mkiv",
+ filename = "m-nodechart",
+ status = "okay",
},
{
category = "tex",
diff --git a/tex/context/base/strc-ini.lua b/tex/context/base/strc-ini.lua
index 1e60e253f..09ed79288 100644
--- a/tex/context/base/strc-ini.lua
+++ b/tex/context/base/strc-ini.lua
@@ -20,12 +20,13 @@ but it does not make sense to store all processdata.
]]--
-local formatters = string.formatters
local lpegmatch = lpeg.match
-local count = tex.count
local type, next, tonumber, select = type, next, tonumber, select
-local settings_to_array, settings_to_hash = utilities.parsers.settings_to_array, utilities.parsers.settings_to_hash
-local allocate = utilities.storage.allocate
+
+local formatters = string.formatters
+local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_hash = utilities.parsers.settings_to_hash
+local allocate = utilities.storage.allocate
local catcodenumbers = catcodes.numbers -- better use the context(...) way to switch
diff --git a/tex/context/base/strc-itm.lua b/tex/context/base/strc-itm.lua
index 8a745f356..4945c282f 100644
--- a/tex/context/base/strc-itm.lua
+++ b/tex/context/base/strc-itm.lua
@@ -10,19 +10,19 @@ local structures = structures
local itemgroups = structures.itemgroups
local jobpasses = job.passes
-local setfield = jobpasses.save
-local getfield = jobpasses.getfield
+local setvariable = jobpasses.save
+local getvariable = jobpasses.getfield
function itemgroups.register(name,nofitems,maxwidth)
- setfield("itemgroup", { nofitems, maxwidth })
+ setvariable("itemgroup", { nofitems, maxwidth })
end
function itemgroups.nofitems(name,index)
- return getfield("itemgroup", index, 1, 0)
+ return getvariable("itemgroup", index, 1, 0)
end
function itemgroups.maxwidth(name,index)
- return getfield("itemgroup", index, 2, 0)
+ return getvariable("itemgroup", index, 2, 0)
end
-- interface (might become counter/dimension)
@@ -30,9 +30,9 @@ end
commands.registeritemgroup = itemgroups.register
function commands.nofitems(name,index)
- context(getfield("itemgroup", index, 1, 0))
+ context(getvariable("itemgroup", index, 1, 0))
end
function commands.maxitemwidth(name,index)
- context(getfield("itemgroup", index, 2, 0))
+ context(getvariable("itemgroup", index, 2, 0))
end
diff --git a/tex/context/base/strc-lnt.mkvi b/tex/context/base/strc-lnt.mkvi
index 4a2cd1cc0..2c26acec7 100644
--- a/tex/context/base/strc-lnt.mkvi
+++ b/tex/context/base/strc-lnt.mkvi
@@ -79,6 +79,8 @@
\letvalue\??linenotespreviousfrom\empty
\letvalue\??linenotespreviousto \empty
+% maybe do this in lua
+
\def\page_lines_in_from{\in[lr:b:\currentlinenotereference]}
\def\page_lines_in_to {\in[lr:e:\currentlinenotereference]}
@@ -113,14 +115,11 @@
\notationparameter\c!compressseparator
\else
\page_lines_in_from
+ \ifx\m_page_lines_current_from\m_page_lines_current_to\else\endash\page_lines_in_to\fi
\fi
\else
\page_lines_in_from
- \ifx\m_page_lines_current_from\m_page_lines_current_to
- \else
- \endash
- \page_lines_in_to
- \fi
+ \ifx\m_page_lines_current_from\m_page_lines_current_to\else\endash\page_lines_in_to\fi
\fi
\else
\page_lines_in_from
diff --git a/tex/context/base/strc-lst.lua b/tex/context/base/strc-lst.lua
index d5597109f..f6a355707 100644
--- a/tex/context/base/strc-lst.lua
+++ b/tex/context/base/strc-lst.lua
@@ -17,7 +17,6 @@ if not modules then modules = { } end modules ['strc-lst'] = {
local format, gmatch, gsub = string.format, string.gmatch, string.gsub
local tonumber = tonumber
-local texcount = tex.count
local concat, insert, remove = table.concat, table.insert, table.remove
local lpegmatch = lpeg.match
local simple_hash_to_string, settings_to_hash = utilities.parsers.simple_hash_to_string, utilities.parsers.settings_to_hash
@@ -30,6 +29,8 @@ local report_lists = logs.reporter("structure","lists")
local context = context
local commands = commands
+local texgetcount = tex.getcount
+
local structures = structures
local lists = structures.lists
local sections = structures.sections
@@ -208,7 +209,7 @@ function lists.enhance(n)
-- save in the right order (happens at shipout)
lists.tobesaved[#lists.tobesaved+1] = l
-- default enhancer (cross referencing)
- references.realpage = texcount.realpageno
+ references.realpage = texgetcount("realpageno")
-- tags
local kind = metadata.kind
local name = metadata.name
diff --git a/tex/context/base/strc-mar.lua b/tex/context/base/strc-mar.lua
index 26603fe72..02d676fb9 100644
--- a/tex/context/base/strc-mar.lua
+++ b/tex/context/base/strc-mar.lua
@@ -24,9 +24,10 @@ local glyph_code = nodecodes.glyph
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
-local traversenodes = node.traverse
+local traversenodes = nodes.traverse
+
local texsetattribute = tex.setattribute
-local texbox = tex.box
+local texgetbox = tex.getbox
local a_marks = attributes.private("structure","marks")
@@ -137,7 +138,7 @@ setmetatableindex(classes, function(t,k) local s = settings_to_array(k) t[k] = s
local lasts = { }
function marks.synchronize(class,n,option)
- local box = texbox[n]
+ local box = texgetbox(n)
if box then
local first, last = sweep(box.list,0,0)
if option == v_keep and first == 0 and last == 0 then
@@ -153,11 +154,16 @@ function marks.synchronize(class,n,option)
for i=1,#classlist do
local class = classlist[i]
local range = ranges[class]
- if not range then
- range = { }
+ if range then
+ range.first = first
+ range.last = last
+ else
+ range = {
+ first = first,
+ last = last,
+ }
ranges[class] = range
end
- range.first, range.last = first, last
if trace_marks_get or trace_marks_set then
report_marks("action %a, class %a, first %a, last %a","synchronize",class,range.first,range.last)
end
diff --git a/tex/context/base/strc-not.lua b/tex/context/base/strc-not.lua
index 8aae8878b..40b78d59f 100644
--- a/tex/context/base/strc-not.lua
+++ b/tex/context/base/strc-not.lua
@@ -8,7 +8,6 @@ if not modules then modules = { } end modules ['strc-not'] = {
local format = string.format
local next = next
-local texcount = tex.count
local trace_notes = false trackers.register("structures.notes", function(v) trace_notes = v end)
local trace_references = false trackers.register("structures.notes.references", function(v) trace_references = v end)
@@ -24,6 +23,9 @@ local notes = structures.notes
local references = structures.references
local counterspecials = counters.specials
+local texgetcount = tex.getcount
+local texgetbox = tex.getbox
+
notes.states = notes.states or { }
lists.enhancers = lists.enhancers or { }
@@ -189,7 +191,7 @@ local function hascontent(tag)
local ok = notestates[tag]
if ok then
if ok.kind == "insert" then
- ok = tex.box[ok.number]
+ ok = texgetbox(ok.number)
if ok then
ok = tbs.list
ok = lst and lst.next
@@ -257,7 +259,7 @@ function notes.checkpagechange(tag) -- called before increment !
end
elseif current then
-- we need to locate the next one, best guess
- if texcount.realpageno > current.pagenumber.number then
+ if texgetcount("realpageno") > current.pagenumber.number then
counters.reset(tag)
end
end
@@ -280,7 +282,7 @@ commands.postponenotes = notes.postpone
function notes.setsymbolpage(tag,n,l)
local l = l or listindex(tag,n)
if l then
- local p = texcount.realpageno
+ local p = texgetcount("realpageno")
if trace_notes or trace_references then
report_notes("note %a of %a with list index %a gets symbol page %a",n,tag,l,p)
end
@@ -382,7 +384,7 @@ function commands.flushnotes(tag,whatkind,how) -- store and postpone
local rp = get(tag,i)
rp = rp and rp.references
rp = rp and rp.symbolpage or 0
- if rp > texcount.realpageno then
+ if rp > texgetcount("realpageno") then
state.start = i
return
end
diff --git a/tex/context/base/strc-num.lua b/tex/context/base/strc-num.lua
index b0eae6b78..866dc146c 100644
--- a/tex/context/base/strc-num.lua
+++ b/tex/context/base/strc-num.lua
@@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['strc-num'] = {
local format = string.format
local next, type = next, type
local min, max = math.min, math.max
-local texcount, texsetcount = tex.count, tex.setcount
+local texsetcount = tex.setcount
-- Counters are managed here. They can have multiple levels which makes it easier to synchronize
-- them. Synchronization is sort of special anyway, as it relates to document structuring.
diff --git a/tex/context/base/strc-pag.lua b/tex/context/base/strc-pag.lua
index a71c6bca6..02ed5610f 100644
--- a/tex/context/base/strc-pag.lua
+++ b/tex/context/base/strc-pag.lua
@@ -6,8 +6,6 @@ if not modules then modules = { } end modules ['strc-pag'] = {
license = "see context related readme files"
}
-local texcount = tex.count
-
local allocate, mark = utilities.storage.allocate, utilities.storage.mark
local trace_pages = false trackers.register("structures.pages", function(v) trace_pages = v end)
@@ -33,6 +31,9 @@ local applyprocessor = processors.apply
local startapplyprocessor = processors.startapply
local stopapplyprocessor = processors.stopapply
+local texsetcount = tex.setcount
+local texgetcount = tex.getcount
+
-- storage
local collected, tobesaved = allocate(), allocate()
@@ -50,7 +51,8 @@ job.register('structures.pages.collected', tobesaved, initializer)
local specification = { } -- to be checked
function pages.save(prefixdata,numberdata)
- local realpage, userpage = texcount.realpageno, texcount.userpageno
+ local realpage = texgetcount("realpageno")
+ local userpage = texgetcount("userpageno")
if realpage > 0 then
if trace_pages then
report_pages("saving page %s.%s",realpage,userpage)
@@ -74,24 +76,24 @@ end
-- builder we have to make sure it starts at least at 1.
function counters.specials.userpage()
- local r = texcount.realpageno
+ local r = texgetcount("realpageno")
if r > 0 then
local t = tobesaved[r]
if t then
- t.number = texcount.userpageno
+ t.number = texgetcount("userpageno")
if trace_pages then
report_pages("forcing pagenumber of realpage %s to %s",r,t.number)
end
return
end
end
- local u = texcount.userpageno
+ local u = texgetcount("userpageno")
if u == 0 then
if trace_pages then
report_pages("forcing pagenumber of realpage %s to %s (probably a bug)",r,1)
end
counters.setvalue("userpage",1)
- texcount.userpageno = 1
+ texsetcount("userpageno",1) -- not global ?
end
end
@@ -253,8 +255,8 @@ function helpers.prefix(data,prefixspec)
end
function pages.is_odd(n)
- n = n or texcount.realpageno
- if texcount.pagenoshift % 2 == 0 then
+ n = n or texgetcount("realpageno")
+ if texgetcount("pagenoshift") % 2 == 0 then
return n % 2 == 0
else
return n % 2 ~= 0
diff --git a/tex/context/base/strc-ref.lua b/tex/context/base/strc-ref.lua
index 8e65a6b19..4c4a0fe7f 100644
--- a/tex/context/base/strc-ref.lua
+++ b/tex/context/base/strc-ref.lua
@@ -15,7 +15,6 @@ if not modules then modules = { } end modules ['strc-ref'] = {
-- todo: autoload components when :::
local format, find, gmatch, match, concat = string.format, string.find, string.gmatch, string.match, table.concat
-local texcount, texsetcount = tex.count, tex.setcount
local floor = math.floor
local rawget, tonumber = rawget, tonumber
local lpegmatch = lpeg.match
@@ -49,15 +48,15 @@ local constants = interfaces.constants
local context = context
local commands = commands
+local texgetcount = tex.getcount
+local texsetcount = tex.setcount
+local texconditionals = tex.conditionals
+
local v_default = variables.default
local v_url = variables.url
local v_file = variables.file
local v_unknown = variables.unknown
local v_yes = variables.yes
-
-local texcount = tex.count
-local texconditionals = tex.conditionals
-
local productcomponent = resolvers.jobs.productcomponent
local justacomponent = resolvers.jobs.justacomponent
@@ -212,7 +211,7 @@ local function referredpage(n)
end
end
-- fallback
- return texcount.realpageno
+ return texgetcount("realpageno")
end
-- setmetatableindex(referred,function(t,k) return referredpage(k) end )
@@ -224,7 +223,7 @@ function references.registerpage(n) -- called in the backend code
if n > maxreferred then
maxreferred = n
end
- tobereferred[n] = texcount.realpageno
+ tobereferred[n] = texgetcount("realpageno")
end
end
@@ -250,7 +249,7 @@ references.setnextorder = setnextorder
function references.setnextinternal(kind,name)
setnextorder(kind,name) -- always incremented with internal
- local n = texcount.locationcount + 1
+ local n = texgetcount("locationcount") + 1
texsetcount("global","locationcount",n)
return n
end
@@ -309,7 +308,7 @@ end
function references.enhance(prefix,tag)
local l = tobesaved[prefix][tag]
if l then
- l.references.realpage = texcount.realpageno
+ l.references.realpage = texgetcount("realpageno")
end
end
@@ -1545,7 +1544,7 @@ local function identify(prefix,reference)
end
local set = resolve(prefix,reference)
local bug = false
- texcount.referencehastexstate = set.has_tex and 1 or 0
+ texsetcount("referencehastexstate",set.has_tex and 1 or 0)
nofidentified = nofidentified + 1
set.n = nofidentified
for i=1,#set do
@@ -1673,14 +1672,14 @@ function references.setinternalreference(prefix,tag,internal,view) -- needs chec
t[tn] = "aut:" .. internal
end
local destination = references.mark(t,nil,nil,view) -- returns an attribute
- texcount.lastdestinationattribute = destination
+ texsetcount("lastdestinationattribute",destination)
return destination
end
end
function references.setandgetattribute(kind,prefix,tag,data,view) -- maybe do internal automatically here
local attr = references.set(kind,prefix,tag,data) and references.setinternalreference(prefix,tag,nil,view) or unsetvalue
- texcount.lastdestinationattribute = attr
+ texsetcount("lastdestinationattribute",attr)
return attr
end
@@ -2039,7 +2038,7 @@ function references.checkedrealpage(r)
realpageofpage(r) -- just initialize
end
if not r then
- return texcount.realpageno
+ return texgetcount("realpageno")
elseif r < 1 then
return 1
elseif r > nofrealpages then
@@ -2132,7 +2131,7 @@ end
function specials.deltapage(var,actions)
local p = tonumber(var.operation)
if p then
- p = references.checkedrealpage(p + texcount.realpageno)
+ p = references.checkedrealpage(p + texgetcount("realpageno"))
var.r = p
actions.realpage = actions.realpage or p -- first wins
end
diff --git a/tex/context/base/strc-reg.lua b/tex/context/base/strc-reg.lua
index f4682c90d..2356acb9b 100644
--- a/tex/context/base/strc-reg.lua
+++ b/tex/context/base/strc-reg.lua
@@ -7,7 +7,6 @@ if not modules then modules = { } end modules ['strc-reg'] = {
}
local next, type = next, type
-local texcount = tex.count
local format, gmatch = string.format, string.gmatch
local equal, concat, remove = table.are_equal, table.concat, table.remove
local utfchar = utf.char
@@ -33,6 +32,8 @@ local replacements = sorters.replacements
local processors = typesetters.processors
local splitprocessor = processors.split
+local texgetcount = tex.getcount
+
local variables = interfaces.variables
local context = context
local commands = commands
@@ -287,7 +288,7 @@ end
function registers.enhance(name,n)
local r = tobesaved[name].entries[n]
if r then
- r.references.realpage = texcount.realpageno
+ r.references.realpage = texgetcount("realpageno")
end
end
@@ -299,7 +300,7 @@ function registers.extend(name,tag,rawdata) -- maybe do lastsection internally
local r = tobesaved[name].entries[tag]
if r then
local rr = r.references
- rr.lastrealpage = texcount.realpageno
+ rr.lastrealpage = texgetcount("realpageno")
rr.lastsection = sections.currentid()
if rawdata then
if rawdata.entries then
diff --git a/tex/context/base/supp-box.lua b/tex/context/base/supp-box.lua
index 8e75b4f63..a8603ace3 100644
--- a/tex/context/base/supp-box.lua
+++ b/tex/context/base/supp-box.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['supp-box'] = {
license = "see context related readme files"
}
--- this is preliminary code
+-- this is preliminary code, use insert_before etc
local report_hyphenation = logs.reporter("languages","hyphenation")
@@ -30,7 +30,9 @@ local copy_list = node.copy_list
local copy_node = node.copy
local find_tail = node.tail
-local texbox = tex.box
+local texsetbox = tex.setbox
+local texgetbox = tex.getbox
+local texget = tex.get
local function hyphenatedlist(list)
while list do
@@ -60,7 +62,7 @@ end
local function checkedlist(list)
if type(list) == "number" then
- return texbox[list].list
+ return texgetbox(list).list
else
return list
end
@@ -116,7 +118,7 @@ commands.applytochars = applytochars
commands.applytowords = applytowords
function commands.vboxlisttohbox(original,target,inbetween)
- local current = texbox[original].list
+ local current = texgetbox(original).list
local head = nil
local tail = nil
while current do
@@ -142,12 +144,12 @@ function commands.vboxlisttohbox(original,target,inbetween)
end
local result = new_hlist()
result.list = head
- texbox[target] = result
+ texsetbox(target,result)
end
function commands.hboxtovbox(original)
- local b = texbox[original]
- local factor = tex.baselineskip.width / tex.hsize
+ local b = texgetbox(original)
+ local factor = texget("baselineskip").width / texget("hsize")
b.depth = 0
b.height = b.width * factor
end
diff --git a/tex/context/base/tabl-tbl.lua b/tex/context/base/tabl-tbl.lua
index 19548e7b3..21564a472 100644
--- a/tex/context/base/tabl-tbl.lua
+++ b/tex/context/base/tabl-tbl.lua
@@ -15,7 +15,7 @@ local tonumber = tonumber
local gsub, rep, sub, find = string.gsub, string.rep, string.sub, string.find
local P, C, Cc, Ct, lpegmatch = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.match
-local settexcount = tex.setcount
+local texsetcount = tex.setcount
local separator = P("|")
local nested = lpeg.patterns.nested
@@ -31,9 +31,9 @@ function commands.presettabulate(preamble)
end
local t = lpegmatch(pattern,preamble)
local m = #t - 2
- settexcount("global","c_tabl_tabulate_nofcolumns", m/2)
- settexcount("global","c_tabl_tabulate_has_rule_spec_first", t[1] == "" and 0 or 1)
- settexcount("global","c_tabl_tabulate_has_rule_spec_last", t[m+1] == "" and 0 or 1)
+ texsetcount("global","c_tabl_tabulate_nofcolumns", m/2)
+ texsetcount("global","c_tabl_tabulate_has_rule_spec_first", t[1] == "" and 0 or 1)
+ texsetcount("global","c_tabl_tabulate_has_rule_spec_last", t[m+1] == "" and 0 or 1)
for i=1,m,2 do
context.settabulateentry(t[i],t[i+1])
end
diff --git a/tex/context/base/tabl-xtb.lua b/tex/context/base/tabl-xtb.lua
index 3ffe8a219..b0af0d5c8 100644
--- a/tex/context/base/tabl-xtb.lua
+++ b/tex/context/base/tabl-xtb.lua
@@ -27,11 +27,12 @@ this mechamism will be improved so that it can replace its older cousin.
local commands, context, tex, node = commands, context, tex, node
-local texdimen = tex.dimen
-local texcount = tex.count
-local texbox = tex.box
+local texgetcount = tex.getcount
local texsetcount = tex.setcount
+local texgetbox = tex.getbox
+local texgetdimen = tex.getdimen
local texsetdimen = tex.setdimen
+local texget = tex.get
local format = string.format
local concat = table.concat
@@ -171,11 +172,11 @@ function xtables.create(settings)
settings.leftmargindistance = tonumber(settings.leftmargindistance) or 0
settings.rightmargindistance = tonumber(settings.rightmargindistance) or 0
settings.options = settings_to_hash(settings.option)
- settings.textwidth = tonumber(settings.textwidth) or tex.hsize
- settings.lineheight = tonumber(settings.lineheight) or texdimen.lineheight
+ settings.textwidth = tonumber(settings.textwidth) or texget("hsize")
+ settings.lineheight = tonumber(settings.lineheight) or texgetdimen("lineheight")
settings.maxwidth = tonumber(settings.maxwidth) or settings.textwidth/8
-- if #stack > 0 then
- -- settings.textwidth = tex.hsize
+ -- settings.textwidth = texget("hsize")
-- end
data.criterium_v = 2 * data.settings.lineheight
data.criterium_h = .75 * data.settings.textwidth
@@ -186,10 +187,10 @@ function xtables.initialize_reflow_width(option)
local r = data.currentrow
local c = data.currentcolumn + 1
local drc = data.rows[r][c]
- drc.nx = texcount.c_tabl_x_nx
- drc.ny = texcount.c_tabl_x_ny
+ drc.nx = texgetcount("c_tabl_x_nx")
+ drc.ny = texgetcount("c_tabl_x_ny")
local distances = data.distances
- local distance = texdimen.d_tabl_x_distance
+ local distance = texgetdimen("d_tabl_x_distance")
if distance > distances[c] then
distances[c] = distance
end
@@ -214,7 +215,7 @@ function xtables.set_reflow_width()
while row[c].span do -- can also be previous row ones
c = c + 1
end
- local tb = texbox.b_tabl_x
+ local tb = texgetbox("b_tabl_x")
local drc = row[c]
--
drc.list = true -- we don't need to keep the content around as we're in trial mode (no: copy_node_list(tb))
@@ -232,7 +233,7 @@ function xtables.set_reflow_width()
depths[r] = depth
end
--
- local dimensionstate = texcount.frameddimensionstate
+ local dimensionstate = texgetcount("frameddimensionstate")
local fixedcolumns = data.fixedcolumns
local fixedrows = data.fixedrows
if dimensionstate == 1 then
@@ -294,19 +295,19 @@ function xtables.initialize_reflow_height()
for x=1,drc.nx-1 do
w = w + widths[c+x]
end
- texdimen.d_tabl_x_width = w
+ texsetdimen("d_tabl_x_width",w)
local dimensionstate = drc.dimensionstate or 0
if dimensionstate == 1 or dimensionstate == 3 then
-- width was fixed so height is known
- texcount.c_tabl_x_skip_mode = 1
+ texsetcount("c_tabl_x_skip_mode",1)
elseif dimensionstate == 2 then
-- height is enforced
- texcount.c_tabl_x_skip_mode = 1
+ texsetcount("c_tabl_x_skip_mode",1)
elseif data.autowidths[c] then
-- width has changed so we need to recalculate the height
- texcount.c_tabl_x_skip_mode = 0
+ texsetcount("c_tabl_x_skip_mode",0)
else
- texcount.c_tabl_x_skip_mode = 1
+ texsetcount("c_tabl_x_skip_mode",1)
end
end
@@ -315,10 +316,10 @@ function xtables.set_reflow_height()
local c = data.currentcolumn
local rows = data.rows
local row = rows[r]
--- while row[c].span do -- we could adapt drc.nx instead
--- c = c + 1
--- end
- local tb = texbox.b_tabl_x
+ -- while row[c].span do -- we could adapt drc.nx instead
+ -- c = c + 1
+ -- end
+ local tb = texgetbox("b_tabl_x")
local drc = row[c]
if data.fixedrows[r] == 0 then -- and drc.dimensionstate < 2
local heights, height = data.heights, tb.height
@@ -330,8 +331,8 @@ function xtables.set_reflow_height()
depths[r] = depth
end
end
--- c = c + drc.nx - 1
--- data.currentcolumn = c
+ -- c = c + drc.nx - 1
+ -- data.currentcolumn = c
end
function xtables.initialize_construct()
@@ -357,9 +358,9 @@ function xtables.initialize_construct()
h = h + heights[r+y]
d = d + depths[r+y]
end
- texdimen.d_tabl_x_width = w
- texdimen.d_tabl_x_height = h + d
- texdimen.d_tabl_x_depth = 0
+ texsetdimen("d_tabl_x_width",w)
+ texsetdimen("d_tabl_x_height",h + d)
+ texsetdimen("d_tabl_x_depth",0)
end
function xtables.set_construct()
@@ -367,14 +368,14 @@ function xtables.set_construct()
local c = data.currentcolumn
local rows = data.rows
local row = rows[r]
--- while row[c].span do -- can also be previous row ones
--- c = c + 1
--- end
+ -- while row[c].span do -- can also be previous row ones
+ -- c = c + 1
+ -- end
local drc = row[c]
-- this will change as soon as in luatex we can reset a box list without freeing
- drc.list = copy_node_list(texbox.b_tabl_x)
--- c = c + drc.nx - 1
--- data.currentcolumn = c
+ drc.list = copy_node_list(texgetbox("b_tabl_x"))
+ -- c = c + drc.nx - 1
+ -- data.currentcolumn = c
end
local function showwidths(where,widths,autowidths)
@@ -669,8 +670,8 @@ function xtables.construct()
end
local kern = new_kern(step)
if stop then
- stop.prev = kern
stop.next = kern
+ kern.prev = stop
else -- can be first spanning next row (ny=...)
start = kern
end
@@ -724,6 +725,8 @@ function xtables.construct()
end
end
+-- todo: join as that is as efficient as fushing multiple
+
local function inject(row,copy,package)
local list = row[1]
if copy then
@@ -966,7 +969,7 @@ end
function xtables.next_row()
local r = data.currentrow + 1
- data.modes[r] = texcount.c_tabl_x_mode
+ data.modes[r] = texgetcount("c_tabl_x_mode")
data.currentrow = r
data.currentcolumn = 0
end
diff --git a/tex/context/base/task-ini.lua b/tex/context/base/task-ini.lua
index 0f477cb6e..107bfe226 100644
--- a/tex/context/base/task-ini.lua
+++ b/tex/context/base/task-ini.lua
@@ -103,7 +103,7 @@ appendaction("vboxbuilders", "normalizers", "builders.vspacing.vboxhandler")
-- experimental too
-appendaction("mvlbuilders","normalizers","typesetters.checkers.handler")
+appendaction("mvlbuilders", "normalizers","typesetters.checkers.handler")
appendaction("vboxbuilders","normalizers","typesetters.checkers.handler")
-- speedup: only kick in when used
diff --git a/tex/context/base/trac-deb.lua b/tex/context/base/trac-deb.lua
index fe167c343..4cc48c4a5 100644
--- a/tex/context/base/trac-deb.lua
+++ b/tex/context/base/trac-deb.lua
@@ -11,22 +11,25 @@ local lpeg, status = lpeg, status
local lpegmatch = lpeg.match
local format, concat, match = string.format, table.concat, string.match
local tonumber, tostring = tonumber, tostring
-local texdimen, textoks, texcount = tex.dimen, tex.toks, tex.count
-- maybe tracers -> tracers.tex (and tracers.lua for current debugger)
local report_system = logs.reporter("system","tex")
-tracers = tracers or { }
-local tracers = tracers
+tracers = tracers or { }
+local tracers = tracers
-tracers.lists = { }
-local lists = tracers.lists
+tracers.lists = { }
+local lists = tracers.lists
-tracers.strings = { }
-local strings = tracers.strings
+tracers.strings = { }
+local strings = tracers.strings
-strings.undefined = "undefined"
+local texgetdimen = tex.getdimen
+local texgettoks = tex.gettoks
+local texgetcount = tex.getcount
+
+strings.undefined = "undefined"
lists.scratch = {
0, 2, 4, 6, 8
@@ -71,16 +74,16 @@ function tracers.cs(csname)
end
function tracers.dimen(name)
- local d = texdimen[name]
+ local d = texgetdimen(name)
return d and number.topoints(d) or strings.undefined
end
function tracers.count(name)
- return texcount[name] or strings.undefined
+ return texgetcount(name) or strings.undefined
end
function tracers.toks(name,limit)
- local t = textoks[name]
+ local t = texgettoks(name)
return t and string.limit(t,tonumber(limit) or 40) or strings.undefined
end
diff --git a/tex/context/base/trac-inf.lua b/tex/context/base/trac-inf.lua
index eefc15a6f..79cbdba3f 100644
--- a/tex/context/base/trac-inf.lua
+++ b/tex/context/base/trac-inf.lua
@@ -11,20 +11,24 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local type, tonumber = type, tonumber
+local type, tonumber, select = type, tonumber, select
local format, lower = string.format, string.lower
local concat = table.concat
local clock = os.gettimeofday or os.clock -- should go in environment
-statistics = statistics or { }
-local statistics = statistics
+local setmetatableindex = table.setmetatableindex
+local serialize = table.serialize
+local formatters = string.formatters
-statistics.enable = true
-statistics.threshold = 0.01
+statistics = statistics or { }
+local statistics = statistics
+
+statistics.enable = true
+statistics.threshold = 0.01
local statusinfo, n, registered, timers = { }, 0, { }, { }
-table.setmetatableindex(timers,function(t,k)
+setmetatableindex(timers,function(t,k)
local v = { timing = 0, loadtime = 0 }
t[k] = v
return v
@@ -178,6 +182,19 @@ function statistics.timed(action)
report("total runtime: %s",elapsedtime("run"))
end
+-- goodie
+
+function statistics.tracefunction(base,tag,...)
+ for i=1,select("#",...) do
+ local name = select(i,...)
+ local stat = { }
+ local func = base[name]
+ setmetatableindex(stat,function(t,k) t[k] = 0 return 0 end)
+ base[name] = function(n,k,v) stat[k] = stat[k] + 1 return func(n,k,v) end
+ statistics.register(formatters["%s.%s"](tag,name),function() return serialize(stat,"calls") end)
+ end
+end
+
-- where, not really the best spot for this:
commands = commands or { }
diff --git a/tex/context/base/trac-jus.lua b/tex/context/base/trac-jus.lua
index 9d99f059d..38220a752 100644
--- a/tex/context/base/trac-jus.lua
+++ b/tex/context/base/trac-jus.lua
@@ -15,19 +15,16 @@ local a_alignstate = attributes.private("alignstate")
local a_justification = attributes.private("justification")
local tracers = nodes.tracers
-local setcolor = tracers.colors.set
-local settransparency = tracers.transparencies.set
+local tracedrule = tracers.rule
local new_rule = nodes.pool.rule
+local new_hlist = nodes.pool.hlist
local new_glue = nodes.pool.glue
local new_kern = nodes.pool.kern
-local concat_nodes = nodes.concat
-local hpack_nodes = node.hpack
-local copy_node = node.copy
local get_list_dimensions = node.dimensions
local hlist_code = nodes.nodecodes.hlist
-local tex_set_attribute = tex.setattribute
+local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
local min_threshold = 0
@@ -36,14 +33,14 @@ local max_threshold = 0
local function set(n)
nodes.tasks.enableaction("mvlbuilders", "typesetters.checkers.handler")
nodes.tasks.enableaction("vboxbuilders","typesetters.checkers.handler")
- tex_set_attribute(a_justification,n or 1)
+ texsetattribute(a_justification,n or 1)
function typesetters.checkers.set(n)
- tex_set_attribute(a_justification,n or 1)
+ texsetattribute(a_justification,n or 1)
end
end
local function reset()
- tex_set_attribute(a_justification,unsetvalue)
+ texsetattribute(a_justification,unsetvalue)
end
checkers.set = set
@@ -74,58 +71,22 @@ function checkers.handler(head)
if naturalwidth == 0 or delta == 0 then
-- special box
elseif delta >= max_threshold then
- local rule = new_rule(delta,naturalheight,naturaldepth)
- list = hpack_nodes(list,width,"exactly")
- if list.glue_set == 1 then
- setcolor(rule,"trace:dr")
- settransparency(rule,"trace:dr")
- else
- setcolor(rule,"trace:db")
- settransparency(rule,"trace:db")
- end
- rule = hpack_nodes(rule)
- rule.width = 0
- rule.height = 0
- rule.depth = 0
- current.list = concat_nodes { list, rule }
- -- current.list = concat_nodes { list, new_kern(-naturalwidth+width), rule }
+ local rule = tracedrule(delta,naturalheight,naturaldepth,list.glue_set == 1 and "trace:dr"or "trace:db")
+ current.list = list .. new_hlist(rule)
elseif delta <= min_threshold then
local alignstate = list[a_alignstate]
if alignstate == 1 then
- local rule = new_rule(-delta,naturalheight,naturaldepth)
- setcolor(rule,"trace:dc")
- settransparency(rule,"trace:dc")
- rule = hpack_nodes(rule)
- rule.height = 0
- rule.depth = 0
- rule.width = 0
- current.list = nodes.concat { rule, list }
+ local rule = tracedrule(-delta,naturalheight,naturaldepth,"trace:dc")
+ current.list = new_hlist(rule) .. list
elseif alignstate == 2 then
- local rule = new_rule(-delta/2,naturalheight,naturaldepth)
- setcolor(rule,"trace:dy")
- settransparency(rule,"trace:dy")
- rule = hpack_nodes(rule)
- rule.width = 0
- rule.height = 0
- rule.depth = 0
- current.list = concat_nodes { copy_node(rule), list, new_kern(delta/2), rule }
+ local rule = tracedrule(-delta/2,naturalheight,naturaldepth,"trace:dy")
+ current.list = new_hlist(rule^1) .. list .. new_kern(delta/2) .. new_hlist(rule)
elseif alignstate == 3 then
- local rule = new_rule(-delta,naturalheight,naturaldepth)
- setcolor(rule,"trace:dm")
- settransparency(rule,"trace:dm")
- rule = hpack_nodes(rule)
- rule.height = 0
- rule.depth = 0
- current.list = concat_nodes { list, new_kern(delta), rule }
+ local rule = tracedrule(-delta,naturalheight,naturaldepth,"trace:dm")
+ current.list = list .. new_kern(delta) .. new_hlist(rule)
else
- local rule = new_rule(-delta,naturalheight,naturaldepth)
- setcolor(rule,"trace:dg")
- settransparency(rule,"trace:dg")
- rule = hpack_nodes(rule)
- rule.height = 0
- rule.depth = 0
- rule.width = 0
- current.list = concat_nodes { list, new_kern(delta), rule }
+ local rule = tracedrule(-delta,naturalheight,naturaldepth,"trace:dg")
+ current.list = list .. new_kern(delta) .. new_hlist(rule)
end
end
end
diff --git a/tex/context/base/trac-log.lua b/tex/context/base/trac-log.lua
index 1f2520130..0ae5d87e3 100644
--- a/tex/context/base/trac-log.lua
+++ b/tex/context/base/trac-log.lua
@@ -68,13 +68,14 @@ local write_nl, write = texio and texio.write_nl or print, texio and texio.write
local format, gmatch, find = string.format, string.gmatch, string.find
local concat, insert, remove = table.concat, table.insert, table.remove
local topattern = string.topattern
-local texcount = tex and tex.count
local next, type, select = next, type, select
local utfchar = utf.char
local setmetatableindex = table.setmetatableindex
local formatters = string.formatters
+local texgetcount = tex and tex.getcount
+
--[[ldx--
<p>This is a prelude to a more extensive logging module. We no longer
provide <l n='xml'/> based logging as parsing is relatively easy anyway.</p>
@@ -129,7 +130,7 @@ setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end)
local report, subreport, status, settarget, setformats, settranslations
-local direct, subdirect, writer, pushtarget, poptarget
+local direct, subdirect, writer, pushtarget, poptarget, setlogfile
if tex and (tex.jobname or tex.formatname) then
@@ -270,11 +271,15 @@ if tex and (tex.jobname or tex.formatname) then
translations = t
end
+ setlogfile = ignore
+
else
logs.flush = ignore
- writer = write_nl
+ writer = function(s)
+ write_nl(s)
+ end
newline = function()
write_nl("\n")
@@ -334,6 +339,29 @@ else
setformats = ignore
settranslations = ignore
+ local f_timed = formatters["[%S] "]
+
+ setlogfile = function(name,keepopen)
+ if name and name ~= "" then
+ local localtime = os.localtime
+ local writeline = write_nl
+ if keepopen then
+ local f = io.open(name,"ab")
+ write_nl = function(s)
+ writeline(s)
+ f:write(f_timed(localtime()),s,"\n")
+ end
+ else
+ write_nl = function(s)
+ writeline(s)
+ local f = io.open(name,"ab")
+ f:write(f_timed(localtime()),s,"\n")
+ f:close()
+ end
+ end
+ end
+ end
+
end
logs.report = report
@@ -345,6 +373,8 @@ logs.poptarget = poptarget
logs.setformats = setformats
logs.settranslations = settranslations
+logs.setlogfile = setlogfile
+
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
@@ -529,8 +559,9 @@ local report_pages = logs.reporter("pages") -- not needed but saves checking whe
local real, user, sub
function logs.start_page_number()
- real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
--- real, user, sub = 0, 0, 0
+ real = texgetcount("realpageno")
+ user = texgetcount("userpageno")
+ sub = texgetcount("subpageno")
end
local timing = false
diff --git a/tex/context/base/trac-vis.lua b/tex/context/base/trac-vis.lua
index 762c71ab5..4a24dacf4 100644
--- a/tex/context/base/trac-vis.lua
+++ b/tex/context/base/trac-vis.lua
@@ -60,11 +60,9 @@ local rightskip_code = gluecodes.rightskip
local whatsitcodes = nodes.whatsitcodes
-local concat_nodes = nodes.concat
local hpack_nodes = node.hpack
local vpack_nodes = node.vpack
-local hpack_string = typesetters.hpack
-local fast_hpack_string = typesetters.fast_hpack
+local fast_hpack_string = nodes.typesetters.fast_hpack
local copy_node = node.copy
local copy_list = node.copy_list
local free_node = node.free
@@ -74,8 +72,9 @@ local insert_node_after = node.insert_after
local fast_hpack = nodes.fasthpack
local traverse_nodes = node.traverse
-local tex_attribute = tex.attribute
-local tex_box = tex.box
+local texgetattribute = tex.getattribute
+local texsetattribute = tex.setattribute
+local texgetbox = tex.getbox
local unsetvalue = attributes.unsetvalue
local current_font = font.current
@@ -247,11 +246,11 @@ local function setvisual(n,a,what) -- this will become more efficient when we ha
end
function visualizers.setvisual(n)
- tex_attribute[a_visual] = setvisual(n,tex_attribute[a_visual])
+ texsetattribute(a_visual,setvisual(n,texgetattribute(a_visual)))
end
function visualizers.setlayer(n)
- tex_attribute[a_layer] = layers[n] or unsetvalue
+ texsetattribute(a_layer,layers[n] or unsetvalue)
end
commands.setvisual = visualizers.setvisual
@@ -262,7 +261,7 @@ function commands.visual(n)
end
local function set(mode,v)
- tex_attribute[a_visual] = setvisual(mode,tex_attribute[a_visual],v)
+ texsetattribute(a_visual,setvisual(mode,texgetattribute(a_visual),v))
end
for mode, value in next, modes do
@@ -305,11 +304,7 @@ local function sometext(str,layer,color,textcolor) -- we can just paste verbatim
if textcolor then
setlistcolor(text.list,textcolor)
end
- local info = concat_nodes {
- rule,
- kern,
- text,
- }
+ local info = rule .. kern .. text
setlisttransparency(info,c_zero)
info = fast_hpack(info)
if layer then
@@ -343,10 +338,7 @@ local function fontkern(head,current)
setlisttransparency(list,c_text_d)
settransparency(rule,c_text_d)
text.shift = -5 * exheight
- info = concat_nodes {
- rule,
- text,
- }
+ info = rule .. text
info = fast_hpack(info)
info[a_layer] = l_fontkern
info.width = 0
@@ -426,9 +418,12 @@ local b_cache = { }
local function ruledbox(head,current,vertical,layer,what,simple)
local wd = current.width
if wd ~= 0 then
- local ht, dp = current.height, current.depth
- local next, prev = current.next, current.prev
- current.next, current.prev = nil, nil
+ local ht = current.height
+ local dp = current.depth
+ local next = current.next
+ local prev = current.prev
+ current.next = nil
+ current.prev = nil
local linewidth = emwidth/10
local baseline, baseskip
if dp ~= 0 and ht ~= 0 then
@@ -437,19 +432,16 @@ local function ruledbox(head,current,vertical,layer,what,simple)
if not baseline then
-- due to an optimized leader color/transparency we need to set the glue node in order
-- to trigger this mechanism
- local leader = concat_nodes {
- new_glue(2*linewidth), -- 2.5
- new_rule(6*linewidth,linewidth,0), -- 5.0
- new_glue(2*linewidth), -- 2.5
- }
+ local leader = new_glue(2*linewidth) .. new_rule(6*linewidth,linewidth,0) .. new_glue(2*linewidth)
-- setlisttransparency(leader,c_text)
leader = fast_hpack(leader)
-- setlisttransparency(leader,c_text)
baseline = new_glue(0)
baseline.leader = leader
baseline.subtype = cleaders_code
- baseline.spec.stretch = 65536
- baseline.spec.stretch_order = 2
+ local spec = baseline.spec
+ spec.stretch = 65536
+ spec.stretch_order = 2
setlisttransparency(baseline,c_text)
b_cache.baseline = baseline
end
@@ -471,10 +463,7 @@ local function ruledbox(head,current,vertical,layer,what,simple)
this = b_cache[what]
if not this then
local text = fast_hpack_string(what,usedfont)
- this = concat_nodes {
- new_kern(-text.width),
- text,
- }
+ this = new_kern(-text.width) .. text
setlisttransparency(this,c_text)
this = fast_hpack(this)
this.width = 0
@@ -483,27 +472,24 @@ local function ruledbox(head,current,vertical,layer,what,simple)
b_cache[what] = this
end
end
- local info = concat_nodes {
- this and copy_list(this) or nil, -- this also triggers the right mode (else sometimes no whatits)
- new_rule(linewidth,ht,dp),
- new_rule(wd-2*linewidth,-dp+linewidth,dp),
- new_rule(linewidth,ht,dp),
- new_kern(-wd+linewidth),
- new_rule(wd-2*linewidth,ht,-ht+linewidth),
- baseskip,
- baseline,
- }
+ -- we need to trigger the right mode (else sometimes no whatits)
+ local info =
+ (this and copy_list(this) or nil) ..
+ new_rule(linewidth,ht,dp) ..
+ new_rule(wd-2*linewidth,-dp+linewidth,dp) ..
+ new_rule(linewidth,ht,dp) ..
+ new_kern(-wd+linewidth) ..
+ new_rule(wd-2*linewidth,ht,-ht+linewidth)
+ if baseskip then
+ info = info .. baseskip .. baseline
+ end
setlisttransparency(info,c_text)
info = fast_hpack(info)
info.width = 0
info.height = 0
info.depth = 0
info[a_layer] = layer
- local info = concat_nodes {
- current,
- new_kern(-wd),
- info,
- }
+ local info = current .. new_kern(-wd) .. info
info = fast_hpack(info,wd)
if vertical then
info = vpack_nodes(info)
@@ -533,25 +519,27 @@ end
local function ruledglyph(head,current)
local wd = current.width
if wd ~= 0 then
- local ht, dp = current.height, current.depth
- local next, prev = current.next, current.prev
- current.next, current.prev = nil, nil
+ local ht = current.height
+ local dp = current.depth
+ local next = current.next
+ local prev = current.prev
+ current.next = nil
+ current.prev = nil
local linewidth = emwidth/20
local baseline
if dp ~= 0 and ht ~= 0 then
baseline = new_rule(wd-2*linewidth,linewidth,0)
end
local doublelinewidth = 2*linewidth
- local info = concat_nodes {
- -- could be a pdf rule
- new_rule(linewidth,ht,dp),
- new_rule(wd-doublelinewidth,-dp+linewidth,dp),
- new_rule(linewidth,ht,dp),
- new_kern(-wd+linewidth),
- new_rule(wd-doublelinewidth,ht,-ht+linewidth),
- new_kern(-wd+doublelinewidth),
- baseline,
- }
+ -- could be a pdf rule
+ local info =
+ new_rule(linewidth,ht,dp) ..
+ new_rule(wd-doublelinewidth,-dp+linewidth,dp) ..
+ new_rule(linewidth,ht,dp) ..
+ new_kern(-wd+linewidth) ..
+ new_rule(wd-doublelinewidth,ht,-ht+linewidth) ..
+ new_kern(-wd+doublelinewidth) ..
+ baseline
setlistcolor(info,c_glyph)
setlisttransparency(info,c_glyph_d)
info = fast_hpack(info)
@@ -559,11 +547,7 @@ local function ruledglyph(head,current)
info.height = 0
info.depth = 0
info[a_layer] = l_glyph
- local info = concat_nodes {
- current,
- new_kern(-wd),
- info,
- }
+ local info = current .. new_kern(-wd) .. info
info = fast_hpack(info)
info.width = wd
if next then
@@ -857,13 +841,13 @@ end
function visualizers.handler(head)
if usedfont then
starttiming(visualizers)
- -- local l = tex_attribute[a_layer]
- -- local v = tex_attribute[a_visual]
- -- tex_attribute[a_layer] = unsetvalue
- -- tex_attribute[a_visual] = unsetvalue
+ -- local l = texgetattribute(a_layer)
+ -- local v = texgetattribute(a_visual)
+ -- texsetattribute(a_layer,unsetvalue)
+ -- texsetattribute(a_visual,unsetvalue)
head = visualize(head)
- -- tex_attribute[a_layer] = l
- -- tex_attribute[a_visual] = v
+ -- texsetattribute(a_layer,l)
+ -- texsetattribute(a_visual,v)
-- -- cleanup()
stoptiming(visualizers)
end
@@ -871,7 +855,8 @@ function visualizers.handler(head)
end
function visualizers.box(n)
- tex_box[n].list = visualizers.handler(tex_box[n].list)
+ local box = texgetbox(n)
+ box.list = visualizers.handler(box.list)
end
local last = nil
@@ -903,7 +888,7 @@ end
function visualizers.markfonts(list)
last, used = 0, { }
- markfonts(type(n) == "number" and tex_box[n].list or n)
+ markfonts(type(n) == "number" and texgetbox(n).list or n)
end
function commands.markfonts(n)
diff --git a/tex/context/base/typo-bld.lua b/tex/context/base/typo-bld.lua
index ed700add7..bc9f66ee4 100644
--- a/tex/context/base/typo-bld.lua
+++ b/tex/context/base/typo-bld.lua
@@ -31,6 +31,7 @@ constructors.attribute = a_parbuilder
local unsetvalue = attributes.unsetvalue
local texsetattribute = tex.setattribute
local texnest = tex.nest
+local texlists = tex.lists
local nodepool = nodes.pool
local new_baselineskip = nodepool.baselineskip
@@ -183,3 +184,72 @@ commands.stopparbuilder = constructors.stop
commands.setparbuilder = constructors.set
commands.enableparbuilder = constructors.enable
commands.disableparbuilder = constructors.disable
+
+-- todo: move from nodes.builders to builders
+
+nodes.builders = nodes.builder or { }
+local builders = nodes.builders
+
+local actions = nodes.tasks.actions("vboxbuilders")
+
+function builders.vpack_filter(head,groupcode,size,packtype,maxdepth,direction)
+ local done = false
+ if head then
+ starttiming(builders)
+ if trace_vpacking then
+ local before = nodes.count(head)
+ head, done = actions(head,groupcode,size,packtype,maxdepth,direction)
+ local after = nodes.count(head)
+ if done then
+ nodes.processors.tracer("vpack","changed",head,groupcode,before,after,true)
+ else
+ nodes.processors.tracer("vpack","unchanged",head,groupcode,before,after,true)
+ end
+ else
+ head, done = actions(head,groupcode)
+ end
+ stoptiming(builders)
+ end
+ return head, done
+end
+
+-- This one is special in the sense that it has no head and we operate on the mlv. Also,
+-- we need to do the vspacing last as it removes items from the mvl.
+
+local actions = nodes.tasks.actions("mvlbuilders")
+
+local function report(groupcode,head)
+ report_page_builder("trigger: %s",groupcode)
+ report_page_builder(" vsize : %p",tex.vsize)
+ report_page_builder(" pagegoal : %p",tex.pagegoal)
+ report_page_builder(" pagetotal: %p",tex.pagetotal)
+ report_page_builder(" list : %s",head and nodeidstostring(head) or "<empty>")
+end
+
+function builders.buildpage_filter(groupcode)
+ local head, done = texlists.contrib_head, false
+ if head then
+ starttiming(builders)
+ if trace_page_builder then
+ report(groupcode,head)
+ end
+ head, done = actions(head,groupcode)
+ stoptiming(builders)
+ -- -- doesn't work here (not passed on?)
+ -- tex.pagegoal = tex.vsize - tex.dimen.d_page_floats_inserted_top - tex.dimen.d_page_floats_inserted_bottom
+ texlists.contrib_head = head
+ return done and head or true
+ else
+ if trace_page_builder then
+ report(groupcode)
+ end
+ return nil, false
+ end
+end
+
+callbacks.register('vpack_filter', builders.vpack_filter, "vertical spacing etc")
+callbacks.register('buildpage_filter', builders.buildpage_filter, "vertical spacing etc (mvl)")
+
+statistics.register("v-node processing time", function()
+ return statistics.elapsedseconds(builders)
+end)
diff --git a/tex/context/base/typo-brk.lua b/tex/context/base/typo-brk.lua
index d6326ebeb..a05cca25b 100644
--- a/tex/context/base/typo-brk.lua
+++ b/tex/context/base/typo-brk.lua
@@ -29,7 +29,7 @@ local remove_node = nodes.remove -- ! nodes
local tonodes = nodes.tonodes
-local texattribute = tex.attribute
+local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
local nodepool = nodes.pool
@@ -156,7 +156,7 @@ methods[5] = function(head,start,settings) -- x => p q r
end
local function process(namespace,attribute,head)
- local done, numbers = false, languages.numbers
+ local done, numbers = false, languages.numbers
local start, n = head, 0
while start do
local id = start.id
@@ -282,7 +282,7 @@ function breakpoints.set(n)
n = n.number
end
end
- texattribute[a_breakpoints] = n
+ texsetattribute(a_breakpoints,n)
end
breakpoints.handler = nodes.installattributehandler {
diff --git a/tex/context/base/typo-cap.lua b/tex/context/base/typo-cap.lua
index fdbf2e353..e9c98c846 100644
--- a/tex/context/base/typo-cap.lua
+++ b/tex/context/base/typo-cap.lua
@@ -20,7 +20,7 @@ local traverse_id = node.traverse_id
local copy_node = node.copy
local end_of_math = node.end_of_math
-local texattribute = tex.attribute
+local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
local nodecodes = nodes.nodecodes
@@ -167,7 +167,7 @@ local function Word(start,attribute,attr)
prev = prev.prev
end
if not prev or prev.id ~= glyph_code then
- --- only the first character is treated
+ -- only the first character is treated
for n in traverse_id(glyph_code,start.next) do
if n[attribute] == attr then
n[attribute] = unsetvalue
@@ -316,7 +316,7 @@ function cases.set(n)
n = unsetvalue
end
end
- texattribute[a_cases] = n
+ texsetattribute(a_cases,n)
-- return n -- bonus
end
diff --git a/tex/context/base/typo-cln.lua b/tex/context/base/typo-cln.lua
index be00ac10d..b4b682bff 100644
--- a/tex/context/base/typo-cln.lua
+++ b/tex/context/base/typo-cln.lua
@@ -7,7 +7,7 @@ if not modules then modules = { } end modules ['typo-cln'] = {
}
-- This quick and dirty hack took less time than listening to a CD (In
--- this case Dream Theaters' Octavium. Of course extensions will take
+-- this case Dream Theaters' Octavium). Of course extensions will take
-- more time.
local utfbyte = utf.byte
@@ -26,7 +26,7 @@ local variables = interfaces.variables
local nodecodes = nodes.nodecodes
local tasks = nodes.tasks
-local texattribute = tex.attribute
+local texsetattribute = tex.setattribute
local traverse_id = node.traverse_id
@@ -78,7 +78,7 @@ local enabled = false
function cleaners.set(n)
if n == variables.reset or not tonumber(n) or n == 0 then
- texattribute[a_cleaner] = unsetvalue
+ texsetattribute(a_cleaner,unsetvalue)
else
if not enabled then
tasks.enableaction("processors","typesetters.cleaners.handler")
@@ -87,7 +87,7 @@ function cleaners.set(n)
end
enabled = true
end
- texattribute[a_cleaner] = n
+ texsetattribute(a_cleaner,n)
end
end
diff --git a/tex/context/base/typo-dig.lua b/tex/context/base/typo-dig.lua
index 62d17fa3b..829e4cc7a 100644
--- a/tex/context/base/typo-dig.lua
+++ b/tex/context/base/typo-dig.lua
@@ -24,7 +24,7 @@ local traverse_id = node.traverse_id
local insert_node_before = node.insert_before
local insert_node_after = node.insert_after
-local texattribute = tex.attribute
+local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
local nodecodes = nodes.nodecodes
@@ -148,7 +148,7 @@ function digits.set(n) -- number or 'reset'
n = unsetvalue
end
end
- texattribute[a_digits] = n
+ texsetattribute(a_digits,n)
end
digits.handler = nodes.installattributehandler { -- we could avoid this wrapper
diff --git a/tex/context/base/typo-dir.lua b/tex/context/base/typo-dir.lua
index 7e5f8c2d3..fcf3e3acb 100644
--- a/tex/context/base/typo-dir.lua
+++ b/tex/context/base/typo-dir.lua
@@ -25,7 +25,7 @@ local insert_node_before = node.insert_before
local insert_node_after = node.insert_after
local remove_node = nodes.remove
-local texattribute = tex.attribute
+local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
local nodecodes = nodes.nodecodes
@@ -167,6 +167,8 @@ end
-- todo: use new dir functions
+-- todo: use end_of_math
+
local s_isol = fonts.analyzers.states.isol
function directions.process(namespace,attribute,start) -- todo: make faster
@@ -451,7 +453,7 @@ function directions.set(n) -- todo: names and numbers
n = unsetvalue
-- maybe tracing
end
- texattribute[a_directions] = n
+ texsetattribute(a_directions,n)
end
commands.setdirection = directions.set
diff --git a/tex/context/base/typo-itc.lua b/tex/context/base/typo-itc.lua
index b39ea2f23..9ef0aaed3 100644
--- a/tex/context/base/typo-itc.lua
+++ b/tex/context/base/typo-itc.lua
@@ -28,7 +28,8 @@ local insert_node_after = node.insert_after
local delete_node = nodes.delete
local end_of_math = node.end_of_math
-local texattribute = tex.attribute
+local texgetattribute = tex.getattribute
+local texsetattribute = tex.setattribute
local a_italics = attributes.private("italics")
local unsetvalue = attributes.unsetvalue
@@ -199,14 +200,14 @@ function italics.set(n)
enable()
end
if n == variables.reset then
- texattribute[a_italics] = unsetvalue
+ texsetattribute(a_italics,unsetvalue)
else
- texattribute[a_italics] = tonumber(n) or unsetvalue
+ texsetattribute(a_italics,tonumber(n) or unsetvalue)
end
end
function italics.reset()
- texattribute[a_italics] = unsetvalue
+ texsetattribute(a_italics,unsetvalue)
end
italics.handler = nodes.installattributehandler {
@@ -231,10 +232,10 @@ function commands.setupitaliccorrection(option) -- no grouping !
end
if options[variables.global] then
forcedvariant = variant
- texattribute[a_italics] = unsetvalue
+ texsetattribute(a_italics,unsetvalue)
else
forcedvariant = false
- texattribute[a_italics] = variant
+ texsetattribute(a_italics,variant)
end
if trace_italics then
report_italics("forcing %a, variant %a",forcedvariant,variant ~= unsetvalue and variant)
@@ -246,11 +247,11 @@ end
local stack = { }
function commands.pushitaliccorrection()
- table.insert(stack,{forcedvariant, texattribute[a_italics] })
+ table.insert(stack,{forcedvariant, texgetattribute(a_italics) })
end
function commands.popitaliccorrection()
local top = table.remove(stack)
forcedvariant = top[1]
- texattribute[a_italics] = top[2]
+ texsetattribute(a_italics,top[2])
end
diff --git a/tex/context/base/typo-krn.lua b/tex/context/base/typo-krn.lua
index fb28d3b2d..fb394044f 100644
--- a/tex/context/base/typo-krn.lua
+++ b/tex/context/base/typo-krn.lua
@@ -20,7 +20,7 @@ local insert_node_before = node.insert_before
local insert_node_after = node.insert_after
local end_of_math = node.end_of_math
-local texattribute = tex.attribute
+local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
local nodepool = nodes.pool
@@ -316,7 +316,7 @@ function kerns.set(factor)
else
factor = unsetvalue
end
- texattribute[a_kerns] = factor
+ texsetattribute(a_kerns,factor)
return factor
end
diff --git a/tex/context/base/typo-mar.lua b/tex/context/base/typo-mar.lua
index ec827883d..85d5c85a8 100644
--- a/tex/context/base/typo-mar.lua
+++ b/tex/context/base/typo-mar.lua
@@ -123,8 +123,6 @@ local free_node_list = node.flush_list
local insert_node_after = node.insert_after
local insert_node_before = node.insert_before
-local concat_nodes = nodes.concat
-
local nodecodes = nodes.nodecodes
local listcodes = nodes.listcodes
local gluecodes = nodes.gluecodes
@@ -155,9 +153,10 @@ local new_stretch = nodepool.stretch
local new_usernumber = nodepool.usernumber
local new_latelua = nodepool.latelua
-local texcount = tex.count
-local texdimen = tex.dimen
-local texbox = tex.box
+local texgetcount = tex.getcount
+local texgetdimen = tex.getdimen
+local texgetbox = tex.getbox
+local texget = tex.get
local points = number.points
@@ -243,7 +242,7 @@ end
function margins.save(t)
setmetatable(t,defaults)
- local content = texbox[t.number]
+ local content = texgetbox(t.number)
local location = t.location
local category = t.category
local inline = t.inline
@@ -309,23 +308,24 @@ function margins.save(t)
t.n = nofsaved
-- used later (we will clean up this natural mess later)
-- nice is to make a special status table mechanism
- local leftmargindistance = texdimen.naturalleftmargindistance
- local rightmargindistance = texdimen.naturalrightmargindistance
- t.strutdepth = texbox.strutbox.depth
- t.strutheight = texbox.strutbox.height
- t.leftskip = tex.leftskip.width -- we're not in forgetall
- t.rightskip = tex.rightskip.width -- we're not in forgetall
+ local leftmargindistance = texgetdimen("naturalleftmargindistance")
+ local rightmargindistance = texgetdimen("naturalrightmargindistance")
+ local strutbox = texgetbox("strutbox")
+ t.strutdepth = strutbox.depth
+ t.strutheight = strutbox.height
+ t.leftskip = texget("leftskip").width -- we're not in forgetall
+ t.rightskip = texget("rightskip").width -- we're not in forgetall
t.leftmargindistance = leftmargindistance -- todo:layoutstatus table
t.rightmargindistance = rightmargindistance
- t.leftedgedistance = texdimen.naturalleftedgedistance
- + texdimen.leftmarginwidth
+ t.leftedgedistance = texgetdimen("naturalleftedgedistance")
+ + texgetdimen("leftmarginwidth")
+ leftmargindistance
- t.rightedgedistance = texdimen.naturalrightedgedistance
- + texdimen.rightmarginwidth
+ t.rightedgedistance = texgetdimen("naturalrightedgedistance")
+ + texgetdimen("rightmarginwidth")
+ rightmargindistance
- t.lineheight = texdimen.lineheight
+ t.lineheight = texgetdimen("lineheight")
--
- -- t.realpageno = texcount.realpageno
+ -- t.realpageno = texgetcount("realpageno")
if inline then
context(new_usernumber(inline_mark,nofsaved))
store[nofsaved] = t -- no insert
@@ -447,7 +447,7 @@ local function realign(current,candidate)
end
end
- current.list = hpack_nodes(concat_nodes{anchornode,new_kern(-delta),current.list,new_kern(delta)})
+ current.list = hpack_nodes(anchornode .. new_kern(-delta) .. current.list .. new_kern(delta))
current.width = 0
end
@@ -490,7 +490,7 @@ local function markovershoot(current)
v_anchors = v_anchors + 1
cache[v_anchors] = stacked
local anchor = new_latelua(format("typesetters.margins.ha(%s)",v_anchors)) -- todo: alleen als offset > line
- current.list = hpack_nodes(concat_nodes{anchor,current.list})
+ current.list = hpack_nodes(anchor .. current.list)
end
local function getovershoot(location)
@@ -623,7 +623,7 @@ local function inject(parent,head,candidate)
elseif head.id == whatsit_code and head.subtype == localpar_code then
-- experimental
if head.dir == "TRT" then
- box.list = hpack_nodes(concat_nodes{new_kern(candidate.hsize),box.list,new_kern(-candidate.hsize)})
+ box.list = hpack_nodes(new_kern(candidate.hsize) .. box.list .. new_kern(-candidate.hsize))
end
insert_node_after(head,head,box)
else
diff --git a/tex/context/base/typo-par.lua b/tex/context/base/typo-par.lua
index b25ae4a5b..5f8bd8d4a 100644
--- a/tex/context/base/typo-par.lua
+++ b/tex/context/base/typo-par.lua
@@ -8,6 +8,9 @@ if not modules then modules = { } end modules ['typo-par'] = {
-- A playground for experiments.
+local tonumber, type, next = tonumber, type, next
+local ceil = math.ceil
+
local utfbyte = utf.byte
local utfchar = utf.char
@@ -26,7 +29,7 @@ local tasks = nodes.tasks
local variables = interfaces.variables
-local texattribute = tex.attribute
+local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
local glyph_code = nodecodes.glyph
@@ -91,9 +94,9 @@ local function process(namespace,attribute,head)
first = first.next
end
if first and first.id == glyph_code then
--- if texattribute[a_paragraph] >= 0 then
--- texattribute[a_paragraph] = unsetvalue
--- end
+ -- if texgetattribute(a_paragraph) >= 0 then
+ -- texsetattribute(a_paragraph,unsetvalue)
+ -- end
local char = first.char
local prev = first.prev
local next = first.next
@@ -103,7 +106,9 @@ local function process(namespace,attribute,head)
if next and next.id == kern_node then
next.kern = 0
end
- first.font = dropper.font or first.font
+ if dropper.font then
+ first.font = dropper.font
+ end
-- can be a helper
local ma = dropper.ma or 0
local ca = dropper.ca
@@ -142,7 +147,7 @@ local function process(namespace,attribute,head)
else
local lines = tonumber(dropper.n) or 0
if lines == 0 then -- safeguard, not too precise
- lines = math.ceil((height+voffset) / tex.baselineskip.width)
+ lines = ceil((height+voffset) / tex.baselineskip.width)
end
tex.hangafter = - lines
tex.hangindent = width + distance
@@ -159,7 +164,7 @@ local enabled = false
function paragraphs.set(n)
if n == variables.reset or not tonumber(n) or n == 0 then
- texattribute[a_paragraph] = unsetvalue
+ texsetattribute(a_paragraph,unsetvalue)
else
if not enabled then
tasks.enableaction("processors","typesetters.paragraphs.handler")
@@ -168,7 +173,7 @@ function paragraphs.set(n)
end
enabled = true
end
- texattribute[a_paragraph] = n
+ texsetattribute(a_paragraph,n)
end
end
diff --git a/tex/context/base/typo-rep.lua b/tex/context/base/typo-rep.lua
index 8451ce52b..01868f490 100644
--- a/tex/context/base/typo-rep.lua
+++ b/tex/context/base/typo-rep.lua
@@ -17,23 +17,23 @@ local report_stripping = logs.reporter("fonts","stripping")
local nodes, node = nodes, node
-local delete_node = nodes.delete
-local replace_node = nodes.replace
-local copy_node = node.copy
+local delete_node = nodes.delete
+local replace_node = nodes.replace
+local copy_node = node.copy
-local chardata = characters.data
-local collected = false
-local a_stripping = attributes.private("stripping")
-local fontdata = fonts.hashes.identifiers
-local tasks = nodes.tasks
+local chardata = characters.data
+local collected = false
+local a_stripping = attributes.private("stripping")
+local fontdata = fonts.hashes.identifiers
+local tasks = nodes.tasks
-local texattribute = tex.attribute
-local unsetvalue = attributes.unsetvalue
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
-local v_reset = interfaces.variables.reset
+local v_reset = interfaces.variables.reset
-local nodecodes = nodes.nodecodes
-local glyph_code = nodecodes.glyph
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
-- todo: other namespace -> typesetters
@@ -115,7 +115,7 @@ function stripping.set(n) -- number or 'reset'
n = unsetvalue
end
end
- texattribute[a_stripping] = n
+ texsetattribute(a_stripping,n)
end
-- why not in task-ini?
diff --git a/tex/context/base/typo-spa.lua b/tex/context/base/typo-spa.lua
index 5eba22889..a8df6e1f8 100644
--- a/tex/context/base/typo-spa.lua
+++ b/tex/context/base/typo-spa.lua
@@ -24,7 +24,7 @@ local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
local quaddata = fonthashes.quads
-local texattribute = tex.attribute
+local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
local v_reset = interfaces.variables.reset
@@ -209,11 +209,11 @@ function spacings.set(name)
n = data.number or unsetvalue
end
end
- texattribute[a_spacings] = n
+ texsetattribute(a_spacings,n)
end
function spacings.reset()
- texattribute[a_spacings] = unsetvalue
+ texsetattribute(a_spacings,unsetvalue)
end
spacings.handler = nodes.installattributehandler {
diff --git a/tex/context/base/util-dim.lua b/tex/context/base/util-dim.lua
index 47b2706b7..69061495f 100644
--- a/tex/context/base/util-dim.lua
+++ b/tex/context/base/util-dim.lua
@@ -22,6 +22,8 @@ local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
local formatters = string.formatters
+local texget = tex and tex.get or function() return 65536*10*100 end
+
--this might become another namespace
number = number or { }
@@ -137,7 +139,7 @@ capture takes place.</p>
--ldx]]--
local amount = (S("+-")^0 * R("09")^0 * P(".")^0 * R("09")^0) + Cc("0")
-local unit = R("az")^1
+local unit = R("az")^1 + P("%")
local dimenpair = amount/tonumber * (unit^1/dimenfactors + Cc(1)) -- tonumber is new
@@ -376,10 +378,10 @@ function dimen(a)
a = k
else
local value, unit = lpegmatch(dimenpair,a)
- if type(unit) == "function" then
- k = value/unit()
+ if value and unit then
+ k = value/unit -- to be considered: round
else
- k = value/unit
+ k = 0
end
known[a] = k
a = k
@@ -412,16 +414,16 @@ function string.todimen(str) -- maybe use tex.sp when available
end
end
---~ local known = { }
-
---~ function string.todimen(str) -- maybe use tex.sp
---~ local k = known[str]
---~ if not k then
---~ k = tex.sp(str)
---~ known[str] = k
---~ end
---~ return k
---~ end
+-- local known = { }
+--
+-- function string.todimen(str) -- maybe use tex.sp
+-- local k = known[str]
+-- if not k then
+-- k = tex.sp(str)
+-- known[str] = k
+-- end
+-- return k
+-- end
stringtodimen = string.todimen -- local variable defined earlier
@@ -439,7 +441,7 @@ probably use a hash instead of a one-element table.</p>
--ldx]]--
function number.percent(n,d) -- will be cleaned up once luatex 0.30 is out
- d = d or tex.hsize
+ d = d or texget("hsize")
if type(d) == "string" then
d = stringtodimen(d)
end
diff --git a/tex/context/base/util-jsn.lua b/tex/context/base/util-jsn.lua
index 29587cd38..bbe25d89d 100644
--- a/tex/context/base/util-jsn.lua
+++ b/tex/context/base/util-jsn.lua
@@ -42,8 +42,20 @@ local dquote = P('"')
local whitespace = lpeg.patterns.whitespace
local optionalws = whitespace^0
-local escape = C(P("\\u") / "0x" * S("09","AF","af")) / function(s) return utfchar(tonumber(s)) end
-local jstring = dquote * Cs((escape + (1-dquote))^0) * dquote
+local escapes = {
+ -- ["\\"] = "\\", -- lua will escape these
+ -- ["/"] = "/", -- no need to escape this one
+ ["b"] = "\010",
+ ["f"] = "\014",
+ ["n"] = "\n",
+ ["r"] = "\r",
+ ["t"] = "\t",
+}
+
+local escape_un = C(P("\\u") / "0x" * S("09","AF","af")) / function(s) return utfchar(tonumber(s)) end
+local escape_bs = P([[\]]) / "" * (P(1) / escapes) -- if not found then P(1) is returned i.e. the to be escaped char
+
+local jstring = dquote * Cs((escape_un + escape_bs + (1-dquote))^0) * dquote
local jtrue = P("true") * Cc(true)
local jfalse = P("false") * Cc(false)
local jnull = P("null") * Cc(nil)
diff --git a/tex/context/base/util-lua.lua b/tex/context/base/util-lua.lua
index 61d1190b2..e1dcdc94d 100644
--- a/tex/context/base/util-lua.lua
+++ b/tex/context/base/util-lua.lua
@@ -74,9 +74,16 @@ end
function luautilities.loadedluacode(fullname,forcestrip,name)
-- quite subtle ... doing this wrong incidentally can give more bytes
name = name or fullname
- local code = environment.loadpreprocessedfile and environment.loadpreprocessedfile(fullname) or loadfile(fullname)
+ local code, message
+ if environment.loadpreprocessedfile then
+ code, message = environment.loadpreprocessedfile(fullname)
+ else
+ code, message = loadfile(fullname)
+ end
if code then
code()
+ else
+ report_lua("loading of file %a failed:\n\t%s",fullname,message or "no message")
end
if forcestrip and luautilities.stripcode then
if type(forcestrip) == "function" then
@@ -97,15 +104,16 @@ function luautilities.loadedluacode(fullname,forcestrip,name)
end
function luautilities.strippedloadstring(code,forcestrip,name) -- not executed
+ local code, message = load(code)
+ if not code then
+ report_lua("loading of file %a failed:\n\t%s",name,message or "no message")
+ end
if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
- code = load(code)
- if not code then
- report_lua("fatal error %a in file %a",3,name)
- end
register(name)
- code = dump(code,true)
+ return load(dump(code,true)), 0 -- not yet executes
+ else
+ return code, 0
end
- return load(code), 0
end
function luautilities.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
diff --git a/tex/context/base/util-prs.lua b/tex/context/base/util-prs.lua
index 9b2a2b04c..7fe1e703b 100644
--- a/tex/context/base/util-prs.lua
+++ b/tex/context/base/util-prs.lua
@@ -410,7 +410,7 @@ function parsers.csvsplitter(specification)
end
whatever = quotedata + whatever
end
- local parser = Ct((Ct(whatever * (separator * whatever)^0) * S("\n\r"))^0 )
+ local parser = Ct((Ct(whatever * (separator * whatever)^0) * S("\n\r")^1)^0 )
return function(data)
return lpegmatch(parser,data)
end
diff --git a/tex/context/base/util-seq.lua b/tex/context/base/util-seq.lua
index 4e042de59..35e693285 100644
--- a/tex/context/base/util-seq.lua
+++ b/tex/context/base/util-seq.lua
@@ -321,6 +321,8 @@ function sequencers.nodeprocessor(t,nofarguments) -- todo: handle 'kind' in plug
else
calls[n] = format(" head, ok = %s(head%s) done = done or ok",localized,args)
end
+-- local s = " print('" .. tostring(group) .. " " .. tostring(action) .. " : ' .. tostring(head)) "
+-- calls[n] = s .. calls[n] .. s
end
end
end
diff --git a/tex/context/base/util-str.lua b/tex/context/base/util-str.lua
index 0c8c0e2d2..13e1e0922 100644
--- a/tex/context/base/util-str.lua
+++ b/tex/context/base/util-str.lua
@@ -339,7 +339,7 @@ local format_i = function(f)
if f and f ~= "" then
return format("format('%%%si',a%s)",f,n)
else
- return format("a%s",n)
+ return format("format('%%i',a%s)",n)
end
end
diff --git a/tex/context/base/util-tab.lua b/tex/context/base/util-tab.lua
index b7db4fa84..f18c719e4 100644
--- a/tex/context/base/util-tab.lua
+++ b/tex/context/base/util-tab.lua
@@ -293,13 +293,12 @@ function tables.encapsulate(core,capsule,protect)
end
end
--- we no longer have %q in keys as for this kind of tables we can
--- assume sane keys
+-- best keep [%q] keys (as we have some in older applications i.e. saving user data
-local f_hashed_string = formatters["[%s]=%q,"]
-local f_hashed_number = formatters["[%s]=%s,"]
-local f_hashed_boolean = formatters["[%s]=%l,"]
-local f_hashed_table = formatters["[%s]="]
+local f_hashed_string = formatters["[%q]=%q,"]
+local f_hashed_number = formatters["[%q]=%s,"]
+local f_hashed_boolean = formatters["[%q]=%l,"]
+local f_hashed_table = formatters["[%q]="]
local f_indexed_string = formatters["%q,"]
local f_indexed_number = formatters["%s,"]
@@ -521,7 +520,7 @@ local serialize = table.serialize -- the extensive one, the one we started with
function table.serialize(root,name,specification)
- if specification then
+ if type(specification) == "table" then
return serialize(root,name,specification) -- the original one
end
diff --git a/tex/context/base/util-tpl.lua b/tex/context/base/util-tpl.lua
index dcc4c1216..e0c405a42 100644
--- a/tex/context/base/util-tpl.lua
+++ b/tex/context/base/util-tpl.lua
@@ -159,6 +159,14 @@ end
templates.replace = replace
+function templates.replacer(str,how,recurse) -- reads nicer
+ return function(mapping)
+ return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
+ end
+end
+
+-- local cmd = templates.replacer([[foo %bar%]]) print(cmd { bar = "foo" })
+
function templates.load(filename,mapping,how,recurse)
local data = io.loaddata(filename) or ""
if mapping and next(mapping) then
diff --git a/tex/context/base/x-asciimath.lua b/tex/context/base/x-asciimath.lua
index 5ef741ce3..992c37eae 100644
--- a/tex/context/base/x-asciimath.lua
+++ b/tex/context/base/x-asciimath.lua
@@ -140,6 +140,8 @@ local reserved = {
}
+table.setmetatableindex(reserved,characters.entities)
+
local postmapper = Cs ( (
P("\\mathoptext ") * spaces * (P("\\bgroup ")/"{") * (1-P("\\egroup "))^1 * (P("\\egroup ")/"}") +
diff --git a/tex/context/fonts/ebgaramond.lfg b/tex/context/fonts/ebgaramond.lfg
new file mode 100644
index 000000000..43cc13c51
--- /dev/null
+++ b/tex/context/fonts/ebgaramond.lfg
@@ -0,0 +1,53 @@
+return {
+ name = "eb garamond",
+ version = "1.00",
+ comment = "Goodies that complement eb garamond.",
+ author = "Hans Hagen",
+ copyright = "ConTeXt development team",
+ designsizes = {
+ ["EBGaramond-Italic"] = {
+ ["8pt"] = "file:EBGaramond08-Italic",
+ ["9pt"] = "file:EBGaramond08-Italic",
+ ["9.5pt"] = "file:EBGaramond08-Italic",
+ ["10pt"] = "file:EBGaramond12-Italic",
+ ["11pt"] = "file:EBGaramond12-Italic",
+ ["12pt"] = "file:EBGaramond12-Italic",
+ default = "file:EBGaramond12-Italic",
+ },
+ ["EBGaramond-Regular"] = {
+ ["8pt"] = "file:EBGaramond08-Regular",
+ ["9pt"] = "file:EBGaramond08-Regular",
+ ["9.5pt"] = "file:EBGaramond08-Regular",
+ ["10pt"] = "file:EBGaramond12-Regular",
+ ["11pt"] = "file:EBGaramond12-Regular",
+ ["12pt"] = "file:EBGaramond12-Regular",
+ default = "file:EBGaramond12-Regular",
+ },
+ ["EBGaramond-SC"] = {
+ ["8pt"] = "file:EBGaramond08-SC",
+ ["9pt"] = "file:EBGaramond08-SC",
+ ["9.5pt"] = "file:EBGaramond08-SC",
+ ["10pt"] = "file:EBGaramond12-SC",
+ ["11pt"] = "file:EBGaramond12-SC",
+ ["12pt"] = "file:EBGaramond12-SC",
+ default = "file:EBGaramond12-SC",
+ },
+ ["EBGaramond-Bold"] = {
+ default = "file:EBGaramond12-Bold",
+ },
+ ["EBGaramond-AllSC"] = {
+ default = "file:EBGaramond12-AllSC",
+ },
+ ["EBGaramond-Initials"] = {
+ default = "file:EBGaramondInitials",
+ },
+ ["EBGaramond-InitialsF1"] = {
+ default = "file:EBGaramondInitialsF1",
+ },
+ ["EBGaramond-InitialsF2"] = {
+ default = "file:EBGaramondInitialsF2",
+ },
+ }
+}
+
+
diff --git a/tex/context/fonts/lm.lfg b/tex/context/fonts/lm.lfg
index 7fad13afd..8d7614718 100644
--- a/tex/context/fonts/lm.lfg
+++ b/tex/context/fonts/lm.lfg
@@ -1,4 +1,4 @@
--- In order to be ale to use beta math fonts, we use our own file name and
+-- In order to be able to use beta math fonts, we use our own file name and
-- always remap.
return {
diff --git a/tex/context/interface/keys-cs.xml b/tex/context/interface/keys-cs.xml
index ad0cf2dca..2499186f3 100644
--- a/tex/context/interface/keys-cs.xml
+++ b/tex/context/interface/keys-cs.xml
@@ -807,6 +807,8 @@
<cd:constant name='marking' value='znaceni'/>
<cd:constant name='marstyle' value='stylsnacky'/>
<cd:constant name='mask' value='mask'/>
+ <cd:constant name='mathclass' value='mathclass'/>
+ <cd:constant name='mathlimits' value='mathlimits'/>
<cd:constant name='mathstyle' value='mathstyle'/>
<cd:constant name='max' value='max'/>
<cd:constant name='maxdepth' value='maxdepth'/>
diff --git a/tex/context/interface/keys-de.xml b/tex/context/interface/keys-de.xml
index 5d107ca40..6464bd44e 100644
--- a/tex/context/interface/keys-de.xml
+++ b/tex/context/interface/keys-de.xml
@@ -807,6 +807,8 @@
<cd:constant name='marking' value='beschriftung'/>
<cd:constant name='marstyle' value='beschrstil'/>
<cd:constant name='mask' value='mask'/>
+ <cd:constant name='mathclass' value='mathclass'/>
+ <cd:constant name='mathlimits' value='mathlimits'/>
<cd:constant name='mathstyle' value='mathstyle'/>
<cd:constant name='max' value='max'/>
<cd:constant name='maxdepth' value='maxdepth'/>
diff --git a/tex/context/interface/keys-en.xml b/tex/context/interface/keys-en.xml
index d9166d107..8a4eb55a9 100644
--- a/tex/context/interface/keys-en.xml
+++ b/tex/context/interface/keys-en.xml
@@ -807,6 +807,8 @@
<cd:constant name='marking' value='marking'/>
<cd:constant name='marstyle' value='marstyle'/>
<cd:constant name='mask' value='mask'/>
+ <cd:constant name='mathclass' value='mathclass'/>
+ <cd:constant name='mathlimits' value='mathlimits'/>
<cd:constant name='mathstyle' value='mathstyle'/>
<cd:constant name='max' value='max'/>
<cd:constant name='maxdepth' value='maxdepth'/>
diff --git a/tex/context/interface/keys-fr.xml b/tex/context/interface/keys-fr.xml
index c98826cf3..604e4560b 100644
--- a/tex/context/interface/keys-fr.xml
+++ b/tex/context/interface/keys-fr.xml
@@ -807,6 +807,8 @@
<cd:constant name='marking' value='marquage'/>
<cd:constant name='marstyle' value='stylemarquage'/>
<cd:constant name='mask' value='mask'/>
+ <cd:constant name='mathclass' value='mathclass'/>
+ <cd:constant name='mathlimits' value='mathlimits'/>
<cd:constant name='mathstyle' value='mathstyle'/>
<cd:constant name='max' value='max'/>
<cd:constant name='maxdepth' value='maxdepth'/>
diff --git a/tex/context/interface/keys-it.xml b/tex/context/interface/keys-it.xml
index afe3b8360..ff23d0973 100644
--- a/tex/context/interface/keys-it.xml
+++ b/tex/context/interface/keys-it.xml
@@ -807,6 +807,8 @@
<cd:constant name='marking' value='marcatura'/>
<cd:constant name='marstyle' value='stilemarcatura'/>
<cd:constant name='mask' value='mask'/>
+ <cd:constant name='mathclass' value='mathclass'/>
+ <cd:constant name='mathlimits' value='mathlimits'/>
<cd:constant name='mathstyle' value='mathstyle'/>
<cd:constant name='max' value='max'/>
<cd:constant name='maxdepth' value='maxdepth'/>
diff --git a/tex/context/interface/keys-nl.xml b/tex/context/interface/keys-nl.xml
index 226c96839..6597300b3 100644
--- a/tex/context/interface/keys-nl.xml
+++ b/tex/context/interface/keys-nl.xml
@@ -807,6 +807,8 @@
<cd:constant name='marking' value='markering'/>
<cd:constant name='marstyle' value='marletter'/>
<cd:constant name='mask' value='masker'/>
+ <cd:constant name='mathclass' value='mathclass'/>
+ <cd:constant name='mathlimits' value='mathlimits'/>
<cd:constant name='mathstyle' value='mathstyle'/>
<cd:constant name='max' value='max'/>
<cd:constant name='maxdepth' value='maxdepth'/>
diff --git a/tex/context/interface/keys-pe.xml b/tex/context/interface/keys-pe.xml
index 9303c29fd..212941015 100644
--- a/tex/context/interface/keys-pe.xml
+++ b/tex/context/interface/keys-pe.xml
@@ -807,6 +807,8 @@
<cd:constant name='marking' value='نشانه‌گذاری'/>
<cd:constant name='marstyle' value='سبک‌حاش'/>
<cd:constant name='mask' value='mask'/>
+ <cd:constant name='mathclass' value='mathclass'/>
+ <cd:constant name='mathlimits' value='mathlimits'/>
<cd:constant name='mathstyle' value='mathstyle'/>
<cd:constant name='max' value='بیشترین'/>
<cd:constant name='maxdepth' value='maxdepth'/>
diff --git a/tex/context/interface/keys-ro.xml b/tex/context/interface/keys-ro.xml
index 29368c9bc..deb7ad559 100644
--- a/tex/context/interface/keys-ro.xml
+++ b/tex/context/interface/keys-ro.xml
@@ -807,6 +807,8 @@
<cd:constant name='marking' value='marcaje'/>
<cd:constant name='marstyle' value='stilmarcaj'/>
<cd:constant name='mask' value='mask'/>
+ <cd:constant name='mathclass' value='mathclass'/>
+ <cd:constant name='mathlimits' value='mathlimits'/>
<cd:constant name='mathstyle' value='mathstyle'/>
<cd:constant name='max' value='max'/>
<cd:constant name='maxdepth' value='maxdepth'/>
diff --git a/tex/generic/context/luatex/luatex-basics-gen.lua b/tex/generic/context/luatex/luatex-basics-gen.lua
index 4a46fbb07..26c1edc72 100644
--- a/tex/generic/context/luatex/luatex-basics-gen.lua
+++ b/tex/generic/context/luatex/luatex-basics-gen.lua
@@ -149,19 +149,29 @@ do
local cachepaths = kpse.expand_var('$TEXMFCACHE') or ""
- -- quite like tex live or so
+ -- quite like tex live or so (the weird $TEXMFCACHE test seems to be needed on miktex)
- if cachepaths == "" then
+ if cachepaths == "" or cachepaths == "$TEXMFCACHE" then
cachepaths = kpse.expand_var('$TEXMFVAR') or ""
end
- -- this also happened to be used
+ -- this also happened to be used (the weird $TEXMFVAR test seems to be needed on miktex)
- if cachepaths == "" then
+ if cachepaths == "" or cachepaths == "$TEXMFVAR" then
cachepaths = kpse.expand_var('$VARTEXMF') or ""
end
- -- and this is a last resort
+ -- and this is a last resort (hm, we could use TEMP or TEMPDIR)
+
+ if cachepaths == "" then
+ local fallbacks = { "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
+ for i=1,#fallbacks do
+ cachepaths = os.getenv(fallbacks[i]) or ""
+ if cachepath ~= "" and lfs.isdir(cachepath) then
+ break
+ end
+ end
+ end
if cachepaths == "" then
cachepaths = "."
@@ -267,7 +277,7 @@ function caches.savedata(path,name,data)
local luaname, lucname = makefullname(path,name)
if luaname then
texio.write(string.format("(save: %s)",luaname))
- table.tofile(luaname,data,true,{ reduce = true })
+ table.tofile(luaname,data,true)
if lucname and type(caches.compile) == "function" then
os.remove(lucname) -- better be safe
texio.write(string.format("(save: %s)",lucname))
diff --git a/tex/generic/context/luatex/luatex-basics-nod.lua b/tex/generic/context/luatex/luatex-basics-nod.lua
index 5ab9df7f9..58b27897d 100644
--- a/tex/generic/context/luatex/luatex-basics-nod.lua
+++ b/tex/generic/context/luatex/luatex-basics-nod.lua
@@ -88,17 +88,32 @@ function nodes.delete(head,current)
return nodes.remove(head,current,true)
end
-nodes.before = node.insert_before
-nodes.after = node.insert_after
-
function nodes.pool.kern(k)
local n = new_node("kern",1)
n.kern = k
return n
end
-function nodes.endofmath(n)
- for n in traverse_id(math_code,n.next) do
- return n
- end
-end
+-- experimental
+
+local getfield = node.getfield or function(n,tag) return n[tag] end end
+local setfield = node.setfield or function(n,tag,value) n[tag] = value end end
+
+nodes.getfield = getfield
+nodes.setfield = setfield
+
+nodes.getattr = getfield
+nodes.setattr = setfield
+
+if node.getid then nodes.getid = node.getid else function nodes.getid (n) return getfield(n,"id") end end
+if node.getsubtype then nodes.getsubtype = node.getsubtype else function nodes.getsubtype(n) return getfield(n,"subtype") end end
+if node.getnext then nodes.getnext = node.getnext else function nodes.getnext (n) return getfield(n,"next") end end
+if node.getprev then nodes.getprev = node.getprev else function nodes.getprev (n) return getfield(n,"prev") end end
+if node.getchar then nodes.getchar = node.getchar else function nodes.getchar (n) return getfield(n,"char") end end
+if node.getfont then nodes.getfont = node.getfont else function nodes.getfont (n) return getfield(n,"font") end end
+if node.getlist then nodes.getlist = node.getlist else function nodes.getlist (n) return getfield(n,"list") end end
+
+function nodes.tonut (n) return n end
+function nodes.tonode(n) return n end
+
+nodes.nuts = nodes -- we stay nodes
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 4cd0c4dc0..d7a1fab5b 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 06/10/13 22:51:12
+-- merge date : 07/12/13 19:10:11
do -- begin closure to overcome local limits and interference
@@ -95,6 +95,7 @@ if not modules then modules={} end modules ['l-lpeg']={
license="see context related readme files"
}
lpeg=require("lpeg")
+if not lpeg.print then function lpeg.print(...) print(lpeg.pcode(...)) end end
local type,next,tostring=type,next,tostring
local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.format
local floor=math.floor
@@ -213,7 +214,7 @@ patterns.decafloat=sign^-1*(digit^0*period*digit^1+digit^1*period*digit^0+digit^
patterns.propername=(uppercase+lowercase+underscore)*(uppercase+lowercase+underscore+digit)^0*endofstring
patterns.somecontent=(anything-newline-space)^1
patterns.beginline=#(1-newline)
-patterns.longtostring=Cs(whitespace^0/""*nonwhitespace^0*((whitespace^0/" "*(patterns.quoted+nonwhitespace)^1)^0))
+patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(P(-1)+Cc(" ")))^0))
local function anywhere(pattern)
return P { P(pattern)+1*V(1) }
end
@@ -1066,6 +1067,7 @@ local noquotes,hexify,handle,reduce,compact,inline,functions
local reserved=table.tohash {
'and','break','do','else','elseif','end','false','for','function','if',
'in','local','nil','not','or','repeat','return','then','true','until','while',
+ 'NaN','goto',
}
local function simple_table(t)
if #t>0 then
@@ -1691,6 +1693,7 @@ local function readall(f)
return f:read('*all')
else
local done=f:seek("set",0)
+ local step
if size<1024*1024 then
step=1024*1024
elseif size>16*1024*1024 then
@@ -2214,17 +2217,24 @@ end
function file.joinpath(tab,separator)
return tab and concat(tab,separator or io.pathseparator)
end
+local someslash=S("\\/")
local stripper=Cs(P(fwslash)^0/""*reslasher)
-local isnetwork=fwslash*fwslash*(1-fwslash)+(1-fwslash-colon)^1*colon
+local isnetwork=someslash*someslash*(1-someslash)+(1-fwslash-colon)^1*colon
local isroot=fwslash^1*-1
local hasroot=fwslash^1
+local reslasher=lpeg.replacer(S("\\/"),"/")
local deslasher=lpeg.replacer(S("\\/")^1,"/")
function file.join(...)
local lst={... }
local one=lst[1]
if lpegmatch(isnetwork,one) then
+ local one=lpegmatch(reslasher,one)
local two=lpegmatch(deslasher,concat(lst,"/",2))
- return one.."/"..two
+ if lpegmatch(hasroot,two) then
+ return one..two
+ else
+ return one.."/"..two
+ end
elseif lpegmatch(isroot,one) then
local two=lpegmatch(deslasher,concat(lst,"/",2))
if lpegmatch(hasroot,two) then
@@ -2241,7 +2251,9 @@ end
local drivespec=R("az","AZ")^1*colon
local anchors=fwslash+drivespec
local untouched=periods+(1-period)^1*P(-1)
-local splitstarter=(Cs(drivespec*(bwslash/"/"+fwslash)^0)+Cc(false))*Ct(lpeg.splitat(S("/\\")^1))
+local mswindrive=Cs(drivespec*(bwslash/"/"+fwslash)^0)
+local mswinuncpath=(bwslash+fwslash)*(bwslash+fwslash)*Cc("//")
+local splitstarter=(mswindrive+mswinuncpath+Cc(false))*Ct(lpeg.splitat(S("/\\")^1))
local absolute=fwslash
function file.collapsepath(str,anchor)
if not str then
@@ -2653,7 +2665,7 @@ local format_i=function(f)
if f and f~="" then
return format("format('%%%si',a%s)",f,n)
else
- return format("a%s",n)
+ return format("format('%%i',a%s)",n)
end
end
local format_d=format_i
@@ -3044,13 +3056,22 @@ if not caches.namespace or caches.namespace=="" or caches.namespace=="context" t
end
do
local cachepaths=kpse.expand_var('$TEXMFCACHE') or ""
- if cachepaths=="" then
+ if cachepaths=="" or cachepaths=="$TEXMFCACHE" then
cachepaths=kpse.expand_var('$TEXMFVAR') or ""
end
- if cachepaths=="" then
+ if cachepaths=="" or cachepaths=="$TEXMFVAR" then
cachepaths=kpse.expand_var('$VARTEXMF') or ""
end
if cachepaths=="" then
+ local fallbacks={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" }
+ for i=1,#fallbacks do
+ cachepaths=os.getenv(fallbacks[i]) or ""
+ if cachepath~="" and lfs.isdir(cachepath) then
+ break
+ end
+ end
+ end
+ if cachepaths=="" then
cachepaths="."
end
cachepaths=string.split(cachepaths,os.type=="windows" and ";" or ":")
@@ -3143,7 +3164,7 @@ function caches.savedata(path,name,data)
local luaname,lucname=makefullname(path,name)
if luaname then
texio.write(string.format("(save: %s)",luaname))
- table.tofile(luaname,data,true,{ reduce=true })
+ table.tofile(luaname,data,true)
if lucname and type(caches.compile)=="function" then
os.remove(lucname)
texio.write(string.format("(save: %s)",lucname))
@@ -3355,18 +3376,27 @@ end
function nodes.delete(head,current)
return nodes.remove(head,current,true)
end
-nodes.before=node.insert_before
-nodes.after=node.insert_after
function nodes.pool.kern(k)
local n=new_node("kern",1)
n.kern=k
return n
end
-function nodes.endofmath(n)
- for n in traverse_id(math_code,n.next) do
- return n
- end
-end
+local getfield=node.getfield or function(n,tag) return n[tag] end end
+local setfield=node.setfield or function(n,tag,value) n[tag]=value end end
+nodes.getfield=getfield
+nodes.setfield=setfield
+nodes.getattr=getfield
+nodes.setattr=setfield
+if node.getid then nodes.getid=node.getid else function nodes.getid (n) return getfield(n,"id") end end
+if node.getsubtype then nodes.getsubtype=node.getsubtype else function nodes.getsubtype(n) return getfield(n,"subtype") end end
+if node.getnext then nodes.getnext=node.getnext else function nodes.getnext (n) return getfield(n,"next") end end
+if node.getprev then nodes.getprev=node.getprev else function nodes.getprev (n) return getfield(n,"prev") end end
+if node.getchar then nodes.getchar=node.getchar else function nodes.getchar (n) return getfield(n,"char") end end
+if node.getfont then nodes.getfont=node.getfont else function nodes.getfont (n) return getfield(n,"font") end end
+if node.getlist then nodes.getlist=node.getlist else function nodes.getlist (n) return getfield(n,"list") end end
+function nodes.tonut (n) return n end
+function nodes.tonode(n) return n end
+nodes.nuts=nodes
end -- closure
@@ -4415,7 +4445,8 @@ function constructors.collectprocessors(what,tfmdata,features,trace,report)
local whathandler=handlers[what]
local whatfeatures=whathandler.features
local whatprocessors=whatfeatures.processors
- local processors=whatprocessors[properties.mode]
+ local mode=properties.mode
+ local processors=whatprocessors[mode]
if processors then
for i=1,#processors do
local step=processors[i]
@@ -4432,7 +4463,7 @@ function constructors.collectprocessors(what,tfmdata,features,trace,report)
end
end
elseif trace then
- report("no feature processors for mode %a for font %a",mode,tfmdata.properties.fullname)
+ report("no feature processors for mode %a for font %a",mode,properties.fullname)
end
end
return processes
@@ -4443,7 +4474,8 @@ function constructors.applymanipulators(what,tfmdata,features,trace,report)
local whathandler=handlers[what]
local whatfeatures=whathandler.features
local whatmanipulators=whatfeatures.manipulators
- local manipulators=whatmanipulators[properties.mode]
+ local mode=properties.mode
+ local manipulators=whatmanipulators[mode]
if manipulators then
for i=1,#manipulators do
local step=manipulators[i]
@@ -4452,7 +4484,7 @@ function constructors.applymanipulators(what,tfmdata,features,trace,report)
if value then
local action=step.action
if trace then
- report("applying feature manipulator %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname)
+ report("applying feature manipulator %a for mode %a for font %a",feature,mode,properties.fullname)
end
if action then
action(tfmdata,feature,value)
@@ -7527,11 +7559,24 @@ local injections=nodes.injections
local nodecodes=nodes.nodecodes
local glyph_code=nodecodes.glyph
local kern_code=nodecodes.kern
-local nodepool=nodes.pool
+local nuts=nodes.nuts
+local nodepool=nuts.pool
local newkern=nodepool.kern
-local traverse_id=node.traverse_id
-local insert_node_before=node.insert_before
-local insert_node_after=node.insert_after
+local tonode=nuts.tonode
+local tonut=nuts.tonut
+local getfield=nuts.getfield
+local getnext=nuts.getnext
+local getprev=nuts.getprev
+local getid=nuts.getid
+local getattr=nuts.getattr
+local getfont=nuts.getfont
+local getsubtype=nuts.getsubtype
+local getchar=nuts.getchar
+local setfield=nuts.setfield
+local setattr=nuts.setattr
+local traverse_id=nuts.traverse_id
+local insert_node_before=nuts.insert_before
+local insert_node_after=nuts.insert_after
local a_kernpair=attributes.private('kernpair')
local a_ligacomp=attributes.private('ligacomp')
local a_markbase=attributes.private('markbase')
@@ -7550,21 +7595,21 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne
local dx,dy=factor*(exit[1]-entry[1]),factor*(exit[2]-entry[2])
local ws,wn=tfmstart.width,tfmnext.width
local bound=#cursives+1
- start[a_cursbase]=bound
- nxt[a_curscurs]=bound
+ setattr(start,a_cursbase,bound)
+ setattr(nxt,a_curscurs,bound)
cursives[bound]={ rlmode,dx,dy,ws,wn }
return dx,dy,bound
end
function injections.setpair(current,factor,rlmode,r2lflag,spec,tfmchr)
local x,y,w,h=factor*spec[1],factor*spec[2],factor*spec[3],factor*spec[4]
if x~=0 or w~=0 or y~=0 or h~=0 then
- local bound=current[a_kernpair]
+ local bound=getattr(current,a_kernpair)
if bound then
local kb=kerns[bound]
kb[2],kb[3],kb[4],kb[5]=(kb[2] or 0)+x,(kb[3] or 0)+y,(kb[4] or 0)+w,(kb[5] or 0)+h
else
bound=#kerns+1
- current[a_kernpair]=bound
+ setattr(current,a_kernpair,bound)
kerns[bound]={ rlmode,x,y,w,h,r2lflag,tfmchr.width }
end
return x,y,w,h,bound
@@ -7575,7 +7620,7 @@ function injections.setkern(current,factor,rlmode,x,tfmchr)
local dx=factor*x
if dx~=0 then
local bound=#kerns+1
- current[a_kernpair]=bound
+ setattr(current,a_kernpair,bound)
kerns[bound]={ rlmode,dx }
return dx,bound
else
@@ -7584,25 +7629,25 @@ function injections.setkern(current,factor,rlmode,x,tfmchr)
end
function injections.setmark(start,base,factor,rlmode,ba,ma,index)
local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2])
- local bound=base[a_markbase]
+ local bound=getattr(base,a_markbase)
local index=1
if bound then
local mb=marks[bound]
if mb then
index=#mb+1
mb[index]={ dx,dy,rlmode }
- start[a_markmark]=bound
- start[a_markdone]=index
+ setattr(start,a_markmark,bound)
+ setattr(start,a_markdone,index)
return dx,dy,bound
else
- report_injections("possible problem, %U is base mark without data (id %a)",base.char,bound)
+ report_injections("possible problem, %U is base mark without data (id %a)",getchar(base),bound)
end
end
index=index or 1
bound=#marks+1
- base[a_markbase]=bound
- start[a_markmark]=bound
- start[a_markdone]=index
+ setattr(base,a_markbase,bound)
+ setattr(start,a_markmark,bound)
+ setattr(start,a_markdone,index)
marks[bound]={ [index]={ dx,dy,rlmode } }
return dx,dy,bound
end
@@ -7612,15 +7657,15 @@ end
local function trace(head)
report_injections("begin run")
for n in traverse_id(glyph_code,head) do
- if n.subtype<256 then
- local kp=n[a_kernpair]
- local mb=n[a_markbase]
- local mm=n[a_markmark]
- local md=n[a_markdone]
- local cb=n[a_cursbase]
- local cc=n[a_curscurs]
- local char=n.char
- report_injections("font %s, char %U, glyph %c",n.font,char,char)
+ if getsubtype(n)<256 then
+ local kp=getattr(n,a_kernpair)
+ local mb=getattr(n,a_markbase)
+ local mm=getattr(n,a_markmark)
+ local md=getattr(n,a_markdone)
+ local cb=getattr(n,a_cursbase)
+ local cc=getattr(n,a_curscurs)
+ local char=getchar(n)
+ report_injections("font %s, char %U, glyph %c",getfont(n),char,char)
if kp then
local k=kerns[kp]
if k[3] then
@@ -7661,21 +7706,23 @@ local function show_result(head)
local current=head
local skipping=false
while current do
- local id=current.id
+ local id=getid(current)
if id==glyph_code then
- report_injections("char: %C, width %p, xoffset %p, yoffset %p",current.char,current.width,current.xoffset,current.yoffset)
+ report_injections("char: %C, width %p, xoffset %p, yoffset %p",
+ getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset"))
skipping=false
elseif id==kern_code then
- report_injections("kern: %p",current.kern)
+ report_injections("kern: %p",getfield(current,"kern"))
skipping=false
elseif not skipping then
report_injections()
skipping=true
end
- current=current.next
+ current=getnext(current)
end
end
function injections.handler(head,where,keep)
+ head=tonut(head)
local has_marks,has_cursives,has_kerns=next(marks),next(cursives),next(kerns)
if has_marks or has_cursives then
if trace_injections then
@@ -7685,17 +7732,18 @@ function injections.handler(head,where,keep)
if has_kerns then
local nf,tm=nil,nil
for n in traverse_id(glyph_code,head) do
- if n.subtype<256 then
+ if getsubtype(n)<256 then
nofvalid=nofvalid+1
valid[nofvalid]=n
- if n.font~=nf then
- nf=n.font
- tm=fontdata[nf].resources.marks
+ local f=getfont(n)
+ if f~=nf then
+ nf=f
+ tm=fontdata[nf].resources.marks
end
if tm then
- mk[n]=tm[n.char]
+ mk[n]=tm[getchar(n)]
end
- local k=n[a_kernpair]
+ local k=getattr(n,a_kernpair)
if k then
local kk=kerns[k]
if kk then
@@ -7715,15 +7763,16 @@ function injections.handler(head,where,keep)
else
local nf,tm=nil,nil
for n in traverse_id(glyph_code,head) do
- if n.subtype<256 then
+ if getsubtype(n)<256 then
nofvalid=nofvalid+1
valid[nofvalid]=n
- if n.font~=nf then
- nf=n.font
+ local f=getfont(n)
+ if f~=nf then
+ nf=f
tm=fontdata[nf].resources.marks
end
if tm then
- mk[n]=tm[n.char]
+ mk[n]=tm[getchar(n)]
end
end
end
@@ -7732,7 +7781,7 @@ function injections.handler(head,where,keep)
local cx={}
if has_kerns and next(ky) then
for n,k in next,ky do
- n.yoffset=k
+ setfield(n,"yoffset",k)
end
end
if has_cursives then
@@ -7741,9 +7790,9 @@ function injections.handler(head,where,keep)
for i=1,nofvalid do
local n=valid[i]
if not mk[n] then
- local n_cursbase=n[a_cursbase]
+ local n_cursbase=getattr(n,a_cursbase)
if p_cursbase then
- local n_curscurs=n[a_curscurs]
+ local n_curscurs=getattr(n,a_curscurs)
if p_cursbase==n_curscurs then
local c=cursives[n_curscurs]
if c then
@@ -7766,20 +7815,20 @@ function injections.handler(head,where,keep)
end
end
elseif maxt>0 then
- local ny=n.yoffset
+ local ny=getfield(n,"yoffset")
for i=maxt,1,-1 do
ny=ny+d[i]
local ti=t[i]
- ti.yoffset=ti.yoffset+ny
+ setfield(ti,"yoffset",getfield(ti,"yoffset")+ny)
end
maxt=0
end
if not n_cursbase and maxt>0 then
- local ny=n.yoffset
+ local ny=getfield(n,"yoffset")
for i=maxt,1,-1 do
ny=ny+d[i]
local ti=t[i]
- ti.yoffset=ny
+ setfield(ti,"yoffset",ny)
end
maxt=0
end
@@ -7787,11 +7836,11 @@ function injections.handler(head,where,keep)
end
end
if maxt>0 then
- local ny=n.yoffset
+ local ny=getfield(n,"yoffset")
for i=maxt,1,-1 do
ny=ny+d[i]
local ti=t[i]
- ti.yoffset=ny
+ setfield(ti,"yoffset",ny)
end
maxt=0
end
@@ -7802,46 +7851,52 @@ function injections.handler(head,where,keep)
if has_marks then
for i=1,nofvalid do
local p=valid[i]
- local p_markbase=p[a_markbase]
+ local p_markbase=getattr(p,a_markbase)
if p_markbase then
local mrks=marks[p_markbase]
local nofmarks=#mrks
- for n in traverse_id(glyph_code,p.next) do
- local n_markmark=n[a_markmark]
+ for n in traverse_id(glyph_code,getnext(p)) do
+ local n_markmark=getattr(n,a_markmark)
if p_markbase==n_markmark then
- local index=n[a_markdone] or 1
+ local index=getattr(n,a_markdone) or 1
local d=mrks[index]
if d then
local rlmode=d[3]
local k=wx[p]
+ local px=getfield(p,"xoffset")
+ local ox=0
if k then
local x=k[2]
local w=k[4]
if w then
if rlmode and rlmode>=0 then
- n.xoffset=p.xoffset-p.width+d[1]-(w-x)
+ ox=px-getfield(p,"width")+d[1]-(w-x)
else
- n.xoffset=p.xoffset-d[1]-x
+ ox=px-d[1]-x
end
else
if rlmode and rlmode>=0 then
- n.xoffset=p.xoffset-p.width+d[1]
+ ox=px-getfield(p,"width")+d[1]
else
- n.xoffset=p.xoffset-d[1]-x
+ ox=px-d[1]-x
end
end
else
if rlmode and rlmode>=0 then
- n.xoffset=p.xoffset-p.width+d[1]
+ ox=px-getfield(p,"width")+d[1]
else
- n.xoffset=p.xoffset-d[1]
+ ox=px-d[1]
end
end
+ setfield(n,"xoffset",ox)
+ local py=getfield(p,"yoffset")
+ local oy=0
if mk[p] then
- n.yoffset=p.yoffset+d[2]
+ oy=py+d[2]
else
- n.yoffset=n.yoffset+p.yoffset+d[2]
+ oy=getfield(n,"yoffset")+py+d[2]
end
+ setfield(n,"yoffset",oy)
if nofmarks==1 then
break
else
@@ -7899,6 +7954,7 @@ function injections.handler(head,where,keep)
if not keep then
kerns={}
end
+head=tonode(head)
return head,true
elseif not keep then
kerns,cursives,marks={},{},{}
@@ -7908,14 +7964,14 @@ function injections.handler(head,where,keep)
trace(head)
end
for n in traverse_id(glyph_code,head) do
- if n.subtype<256 then
- local k=n[a_kernpair]
+ if getsubtype(n)<256 then
+ local k=getattr(n,a_kernpair)
if k then
local kk=kerns[k]
if kk then
local rl,x,y,w=kk[1],kk[2] or 0,kk[3],kk[4]
if y and y~=0 then
- n.yoffset=y
+ setfield(n,"yoffset",y)
end
if w then
local wx=w-x
@@ -7946,10 +8002,10 @@ function injections.handler(head,where,keep)
if not keep then
kerns={}
end
- return head,true
+ return tonode(head),true
else
end
- return head,false
+ return tonode(head),false
end
end -- closure
@@ -7977,6 +8033,7 @@ analyzers.useunicodemarks=false
local a_state=attributes.private('state')
local nodecodes=nodes.nodecodes
local glyph_code=nodecodes.glyph
+local disc_code=nodecodes.disc
local math_code=nodecodes.math
local traverse_id=node.traverse_id
local traverse_node_list=node.traverse
@@ -8043,7 +8100,7 @@ function analyzers.setstate(head,font)
first,last,n=nil,nil,0
end
elseif id==disc_code then
- current[a_state]=s_midi
+ current[a_state]=s_medi
last=current
else
if first and first==last then
@@ -8095,7 +8152,7 @@ local function analyzeprocessor(head,font,attr)
end
registerotffeature {
name="analyze",
- description="analysis of (for instance) character classes",
+ description="analysis of character classes",
default=true,
initializers={
node=analyzeinitializer,
@@ -8358,12 +8415,25 @@ registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
registertracker("otf.actions","otf.replacements,otf.positions")
registertracker("otf.injections","nodes.injections")
registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing")
-local insert_node_after=node.insert_after
-local delete_node=nodes.delete
-local copy_node=node.copy
-local find_node_tail=node.tail or node.slide
-local flush_node_list=node.flush_list
-local end_of_math=node.end_of_math
+local nuts=nodes.nuts
+local tonode=nuts.tonode
+local tonut=nuts.tonut
+local getfield=nuts.getfield
+local getnext=nuts.getnext
+local getprev=nuts.getprev
+local getid=nuts.getid
+local getattr=nuts.getattr
+local getfont=nuts.getfont
+local getsubtype=nuts.getsubtype
+local getchar=nuts.getchar
+local setfield=nuts.setfield
+local setattr=nuts.setattr
+local insert_node_after=nuts.insert_after
+local delete_node=nuts.delete
+local copy_node=nuts.copy
+local find_node_tail=nuts.tail
+local flush_node_list=nuts.flush_list
+local end_of_math=nuts.end_of_math
local setmetatableindex=table.setmetatableindex
local zwnj=0x200C
local zwj=0x200D
@@ -8472,83 +8542,83 @@ local function pref(kind,lookupname)
return formatters["feature %a, lookup %a"](kind,lookupname)
end
local function copy_glyph(g)
- local components=g.components
+ local components=getfield(g,"components")
if components then
- g.components=nil
+ setfield(g,"components",nil)
local n=copy_node(g)
- g.components=components
+ setfield(g,"components",components)
return n
else
return copy_node(g)
end
end
local function markstoligature(kind,lookupname,head,start,stop,char)
- if start==stop and start.char==char then
+ if start==stop and getchar(start)==char then
return head,start
else
- local prev=start.prev
- local next=stop.next
- start.prev=nil
- stop.next=nil
+ local prev=getprev(start)
+ local next=getnext(stop)
+ setfield(start,"prev",nil)
+ setfield(stop,"next",nil)
local base=copy_glyph(start)
if head==start then
head=base
end
- base.char=char
- base.subtype=ligature_code
- base.components=start
+ setfield(base,"char",char)
+ setfield(base,"subtype",ligature_code)
+ setfield(base,"components",start)
if prev then
- prev.next=base
+ setfield(prev,"next",base)
end
if next then
- next.prev=base
+ setfield(next,"prev",base)
end
- base.next=next
- base.prev=prev
+ setfield(base,"next",next)
+ setfield(base,"prev",prev)
return head,base
end
end
local function getcomponentindex(start)
- if start.id~=glyph_code then
+ if getid(start)~=glyph_code then
return 0
- elseif start.subtype==ligature_code then
+ elseif getsubtype(start)==ligature_code then
local i=0
- local components=start.components
+ local components=getfield(start,"components")
while components do
i=i+getcomponentindex(components)
- components=components.next
+ components=getnext(components)
end
return i
- elseif not marks[start.char] then
+ elseif not marks[getchar(start)] then
return 1
else
return 0
end
end
local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound)
- if start==stop and start.char==char then
- start.char=char
+ if start==stop and getchar(start)==char then
+ setfield(start,"char",char)
return head,start
end
- local prev=start.prev
- local next=stop.next
- start.prev=nil
- stop.next=nil
+ local prev=getprev(start)
+ local next=getnext(stop)
+ setfield(start,"prev",nil)
+ setfield(stop,"next",nil)
local base=copy_glyph(start)
if start==head then
head=base
end
- base.char=char
- base.subtype=ligature_code
- base.components=start
+ setfield(base,"char",char)
+ setfield(base,"subtype",ligature_code)
+ setfield(base,"components",start)
if prev then
- prev.next=base
+ setfield(prev,"next",base)
end
if next then
- next.prev=base
+ setfield(next,"prev",base)
end
- base.next=next
- base.prev=prev
+ setfield(base,"next",next)
+ setfield(base,"prev",prev)
if not discfound then
local deletemarks=markflag~="mark"
local components=start
@@ -8557,42 +8627,42 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
local head=base
local current=base
while start do
- local char=start.char
+ local char=getchar(start)
if not marks[char] then
baseindex=baseindex+componentindex
componentindex=getcomponentindex(start)
elseif not deletemarks then
- start[a_ligacomp]=baseindex+(start[a_ligacomp] or componentindex)
+ setattr(start,a_ligacomp,baseindex+(getattr(start,a_ligacomp) or componentindex))
if trace_marks then
- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp])
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),getattr(start,a_ligacomp))
end
head,current=insert_node_after(head,current,copy_node(start))
elseif trace_marks then
logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char))
end
- start=start.next
+ start=getnext(start)
end
- local start=current.next
- while start and start.id==glyph_code do
- local char=start.char
+ local start=getnext(current)
+ while start and getid(start)==glyph_code do
+ local char=getchar(start)
if marks[char] then
- start[a_ligacomp]=baseindex+(start[a_ligacomp] or componentindex)
+ setattr(start,a_ligacomp,baseindex+(getattr(start,a_ligacomp) or componentindex))
if trace_marks then
- logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp])
+ logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),getattr(start,a_ligacomp))
end
else
break
end
- start=start.next
+ start=getnext(start)
end
end
return head,base
end
function handlers.gsub_single(head,start,kind,lookupname,replacement)
if trace_singles then
- logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(start.char),gref(replacement))
+ logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
end
- start.char=replacement
+ setfield(start,"char",replacement)
return head,start,true
end
local function get_alternative_glyph(start,alternatives,value,trace_alternatives)
@@ -8618,7 +8688,7 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives
return false,trace_alternatives and formatters["invalid value %a, %s"](value,"out of range")
end
elseif value==0 then
- return start.char,trace_alternatives and formatters["invalid value %a, %s"](value,"no change")
+ return getchar(start),trace_alternatives and formatters["invalid value %a, %s"](value,"no change")
elseif value<1 then
return alternatives[1],trace_alternatives and formatters["invalid value %a, taking %a"](value,1)
else
@@ -8629,25 +8699,25 @@ end
local function multiple_glyphs(head,start,multiple)
local nofmultiples=#multiple
if nofmultiples>0 then
- start.char=multiple[1]
+ setfield(start,"char",multiple[1])
if nofmultiples>1 then
- local sn=start.next
+ local sn=getnext(start)
for k=2,nofmultiples do
local n=copy_node(start)
- n.char=multiple[k]
- n.next=sn
- n.prev=start
+ setfield(n,"char",multiple[k])
+ setfield(n,"next",sn)
+ setfield(n,"prev",start)
if sn then
- sn.prev=n
+ setfield(sn,"prev",n)
end
- start.next=n
+ setfield(start,"next",n)
start=n
end
end
return head,start,true
else
if trace_multiples then
- logprocess("no multiple for %s",gref(start.char))
+ logprocess("no multiple for %s",gref(getchar(start)))
end
return head,start,false
end
@@ -8657,34 +8727,34 @@ function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence
local choice,comment=get_alternative_glyph(start,alternative,value,trace_alternatives)
if choice then
if trace_alternatives then
- logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(start.char),choice,gref(choice),comment)
+ logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(getchar(start)),choice,gref(choice),comment)
end
- start.char=choice
+ setfield(start,"char",choice)
else
if trace_alternatives then
- logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(start.char),comment)
+ logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(getchar(start)),comment)
end
end
return head,start,true
end
function handlers.gsub_multiple(head,start,kind,lookupname,multiple)
if trace_multiples then
- logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(start.char),gref(multiple))
+ logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(getchar(start)),gref(multiple))
end
return multiple_glyphs(head,start,multiple)
end
function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
- local s,stop,discfound=start.next,nil,false
- local startchar=start.char
+ local s,stop,discfound=getnext(start),nil,false
+ local startchar=getchar(start)
if marks[startchar] then
while s do
- local id=s.id
- if id==glyph_code and s.font==currentfont and s.subtype<256 then
- local lg=ligature[s.char]
+ local id=getid(s)
+ if id==glyph_code and getfont(s)==currentfont and getsubtype(s)<256 then
+ local lg=ligature[getchar(s)]
if lg then
stop=s
ligature=lg
- s=s.next
+ s=getnext(s)
else
break
end
@@ -8696,9 +8766,9 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
local lig=ligature.ligature
if lig then
if trace_ligatures then
- local stopchar=stop.char
+ local stopchar=getchar(stop)
head,start=markstoligature(kind,lookupname,head,start,stop,lig)
- logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char))
+ logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start)))
else
head,start=markstoligature(kind,lookupname,head,start,stop,lig)
end
@@ -8709,18 +8779,18 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
else
local skipmark=sequence.flags[1]
while s do
- local id=s.id
- if id==glyph_code and s.subtype<256 then
- if s.font==currentfont then
- local char=s.char
+ local id=getid(s)
+ if id==glyph_code and getsubtype(s)<256 then
+ if getfont(s)==currentfont then
+ local char=getchar(s)
if skipmark and marks[char] then
- s=s.next
+ s=getnext(s)
else
local lg=ligature[char]
if lg then
stop=s
ligature=lg
- s=s.next
+ s=getnext(s)
else
break
end
@@ -8730,7 +8800,7 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
end
elseif id==disc_code then
discfound=true
- s=s.next
+ s=getnext(s)
else
break
end
@@ -8739,9 +8809,9 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
local lig=ligature.ligature
if lig then
if trace_ligatures then
- local stopchar=stop.char
+ local stopchar=getchar(stop)
head,start=toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound)
- logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char))
+ logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start)))
else
head,start=toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound)
end
@@ -8753,16 +8823,16 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
return head,start,false
end
function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence)
- local markchar=start.char
+ local markchar=getchar(start)
if marks[markchar] then
- local base=start.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- local basechar=base.char
+ local base=getprev(start)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ local basechar=getchar(base)
if marks[basechar] then
while true do
- base=base.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- basechar=base.char
+ base=getprev(base)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ basechar=getchar(base)
if not marks[basechar] then
break
end
@@ -8811,16 +8881,16 @@ function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence
return head,start,false
end
function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequence)
- local markchar=start.char
+ local markchar=getchar(start)
if marks[markchar] then
- local base=start.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- local basechar=base.char
+ local base=getprev(start)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ local basechar=getchar(base)
if marks[basechar] then
while true do
- base=base.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- basechar=base.char
+ base=getprev(base)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ basechar=getchar(base)
if not marks[basechar] then
break
end
@@ -8832,7 +8902,7 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ
end
end
end
- local index=start[a_ligacomp]
+ local index=getattr(start,a_ligacomp)
local baseanchors=descriptions[basechar]
if baseanchors then
baseanchors=baseanchors.anchors
@@ -8877,22 +8947,22 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ
return head,start,false
end
function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence)
- local markchar=start.char
+ local markchar=getchar(start)
if marks[markchar] then
- local base=start.prev
- local slc=start[a_ligacomp]
+ local base=getprev(start)
+ local slc=getattr(start,a_ligacomp)
if slc then
while base do
- local blc=base[a_ligacomp]
+ local blc=getattr(base,a_ligacomp)
if blc and blc~=slc then
- base=base.prev
+ base=getprev(base)
else
break
end
end
end
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- local basechar=base.char
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ local basechar=getchar(base)
local baseanchors=descriptions[basechar]
if baseanchors then
baseanchors=baseanchors.anchors
@@ -8930,20 +9000,20 @@ function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence
return head,start,false
end
function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence)
- local alreadydone=cursonce and start[a_cursbase]
+ local alreadydone=cursonce and getattr(start,a_cursbase)
if not alreadydone then
local done=false
- local startchar=start.char
+ local startchar=getchar(start)
if marks[startchar] then
if trace_cursive then
logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
end
else
- local nxt=start.next
- while not done and nxt and nxt.id==glyph_code and nxt.font==currentfont and nxt.subtype<256 do
- local nextchar=nxt.char
+ local nxt=getnext(start)
+ while not done and nxt and getid(nxt)==glyph_code and getfont(nxt)==currentfont and getsubtype(nxt)<256 do
+ local nextchar=getchar(nxt)
if marks[nextchar] then
- nxt=nxt.next
+ nxt=getnext(nxt)
else
local entryanchors=descriptions[nextchar]
if entryanchors then
@@ -8977,13 +9047,13 @@ function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence)
return head,start,done
else
if trace_cursive and trace_details then
- logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone)
+ logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone)
end
return head,start,false
end
end
function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence)
- local startchar=start.char
+ local startchar=getchar(start)
local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
if trace_kerns then
logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
@@ -8991,19 +9061,19 @@ function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence)
return head,start,false
end
function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
- local snext=start.next
+ local snext=getnext(start)
if not snext then
return head,start,false
else
local prev,done=start,false
local factor=tfmdata.parameters.factor
local lookuptype=lookuptypes[lookupname]
- while snext and snext.id==glyph_code and snext.font==currentfont and snext.subtype<256 do
- local nextchar=snext.char
+ while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
+ local nextchar=getchar(snext)
local krn=kerns[nextchar]
if not krn and marks[nextchar] then
prev=snext
- snext=snext.next
+ snext=getnext(snext)
else
local krn=kerns[nextchar]
if not krn then
@@ -9011,14 +9081,14 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
if lookuptype=="pair" then
local a,b=krn[2],krn[3]
if a and #a>0 then
- local startchar=start.char
+ local startchar=getchar(start)
local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
if trace_kerns then
logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
end
end
if b and #b>0 then
- local startchar=start.char
+ local startchar=getchar(start)
local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
if trace_kerns then
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
@@ -9031,7 +9101,7 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
elseif krn~=0 then
local k=setkern(snext,factor,rlmode,krn)
if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar))
+ logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
end
done=true
end
@@ -9066,13 +9136,13 @@ function chainmores.chainsub(head,start,stop,kind,chainname,currentcontext,looku
return head,start,false
end
function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements)
- local char=start.char
+ local char=getchar(start)
local replacement=replacements[char]
if replacement then
if trace_singles then
logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement))
end
- start.char=replacement
+ setfield(start,"char",replacement)
return head,start,true
else
return head,start,false
@@ -9083,9 +9153,9 @@ local function delete_till_stop(start,stop,ignoremarks)
if start==stop then
elseif ignoremarks then
repeat
- local next=start.next
- if not marks[next.char] then
- local components=next.components
+ local next=getnext(start)
+ if not marks[getchar(next)] then
+ local components=getfield(next,"components")
if components then
flush_node_list(components)
end
@@ -9095,8 +9165,8 @@ local function delete_till_stop(start,stop,ignoremarks)
until next==stop
else
repeat
- local next=start.next
- local components=next.components
+ local next=getnext(start)
+ local components=getfield(next,"components")
if components then
flush_node_list(components)
end
@@ -9113,8 +9183,8 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
logwarning("todo: check if we need to loop over the replacements: %s",concat(subtables," "))
end
while current do
- if current.id==glyph_code then
- local currentchar=current.char
+ if getid(current)==glyph_code then
+ local currentchar=getchar(current)
local lookupname=subtables[1]
local replacement=lookuphash[lookupname]
if not replacement then
@@ -9131,14 +9201,14 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
if trace_singles then
logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement))
end
- current.char=replacement
+ setfield(current,"char",replacement)
end
end
return head,start,true
elseif current==stop then
break
else
- current=current.next
+ current=getnext(current)
end
end
return head,start,false
@@ -9146,7 +9216,7 @@ end
chainmores.gsub_single=chainprocs.gsub_single
function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
delete_till_stop(start,stop)
- local startchar=start.char
+ local startchar=getchar(start)
local subtables=currentlookup.subtables
local lookupname=subtables[1]
local replacements=lookuphash[lookupname]
@@ -9175,8 +9245,8 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
local subtables=currentlookup.subtables
local value=featurevalue==true and tfmdata.shared.features[kind] or featurevalue
while current do
- if current.id==glyph_code then
- local currentchar=current.char
+ if getid(current)==glyph_code then
+ local currentchar=getchar(current)
local lookupname=subtables[1]
local alternatives=lookuphash[lookupname]
if not alternatives then
@@ -9191,7 +9261,7 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
if trace_alternatives then
logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment)
end
- start.char=choice
+ setfield(start,"char",choice)
else
if trace_alternatives then
logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment)
@@ -9205,14 +9275,14 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
elseif current==stop then
break
else
- current=current.next
+ current=getnext(current)
end
end
return head,start,false
end
chainmores.gsub_alternate=chainprocs.gsub_alternate
function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
- local startchar=start.char
+ local startchar=getchar(start)
local subtables=currentlookup.subtables
local lookupname=subtables[1]
local ligatures=lookuphash[lookupname]
@@ -9227,20 +9297,20 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
logwarning("%s: no ligatures starting with %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
end
else
- local s=start.next
+ local s=getnext(start)
local discfound=false
local last=stop
local nofreplacements=0
local skipmark=currentlookup.flags[1]
while s do
- local id=s.id
+ local id=getid(s)
if id==disc_code then
- s=s.next
+ s=getnext(s)
discfound=true
else
- local schar=s.char
+ local schar=getchar(s)
if skipmark and marks[schar] then
- s=s.next
+ s=getnext(s)
else
local lg=ligatures[schar]
if lg then
@@ -9248,7 +9318,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
if s==stop then
break
else
- s=s.next
+ s=getnext(s)
end
else
break
@@ -9265,7 +9335,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
if start==stop then
logprocess("%s: replacing character %s by ligature %s case 3",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2))
else
- logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char),gref(l2))
+ logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)),gref(l2))
end
end
head,start=toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound)
@@ -9274,7 +9344,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
if start==stop then
logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
else
- logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char))
+ logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)))
end
end
end
@@ -9283,7 +9353,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
end
chainmores.gsub_ligature=chainprocs.gsub_ligature
function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local markchar=start.char
+ local markchar=getchar(start)
if marks[markchar] then
local subtables=currentlookup.subtables
local lookupname=subtables[1]
@@ -9292,14 +9362,14 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext
markanchors=markanchors[markchar]
end
if markanchors then
- local base=start.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- local basechar=base.char
+ local base=getprev(start)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ local basechar=getchar(base)
if marks[basechar] then
while true do
- base=base.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- basechar=base.char
+ base=getprev(base)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ basechar=getchar(base)
if not marks[basechar] then
break
end
@@ -9346,7 +9416,7 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext
return head,start,false
end
function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local markchar=start.char
+ local markchar=getchar(start)
if marks[markchar] then
local subtables=currentlookup.subtables
local lookupname=subtables[1]
@@ -9355,14 +9425,14 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon
markanchors=markanchors[markchar]
end
if markanchors then
- local base=start.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- local basechar=base.char
+ local base=getprev(start)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ local basechar=getchar(base)
if marks[basechar] then
while true do
- base=base.prev
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- basechar=base.char
+ base=getprev(base)
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ basechar=getchar(base)
if not marks[basechar] then
break
end
@@ -9374,7 +9444,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon
end
end
end
- local index=start[a_ligacomp]
+ local index=getattr(start,a_ligacomp)
local baseanchors=descriptions[basechar].anchors
if baseanchors then
local baseanchors=baseanchors['baselig']
@@ -9413,7 +9483,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon
return head,start,false
end
function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local markchar=start.char
+ local markchar=getchar(start)
if marks[markchar] then
local subtables=currentlookup.subtables
local lookupname=subtables[1]
@@ -9422,20 +9492,20 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext
markanchors=markanchors[markchar]
end
if markanchors then
- local base=start.prev
- local slc=start[a_ligacomp]
+ local base=getprev(start)
+ local slc=getattr(start,a_ligacomp)
if slc then
while base do
- local blc=base[a_ligacomp]
+ local blc=getattr(base,a_ligacomp)
if blc and blc~=slc then
- base=base.prev
+ base=getprev(base)
else
break
end
end
end
- if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
- local basechar=base.char
+ if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+ local basechar=getchar(base)
local baseanchors=descriptions[basechar].anchors
if baseanchors then
baseanchors=baseanchors['basemark']
@@ -9471,9 +9541,9 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext
return head,start,false
end
function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- local alreadydone=cursonce and start[a_cursbase]
+ local alreadydone=cursonce and getattr(start,a_cursbase)
if not alreadydone then
- local startchar=start.char
+ local startchar=getchar(start)
local subtables=currentlookup.subtables
local lookupname=subtables[1]
local exitanchors=lookuphash[lookupname]
@@ -9487,11 +9557,11 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
end
else
- local nxt=start.next
- while not done and nxt and nxt.id==glyph_code and nxt.font==currentfont and nxt.subtype<256 do
- local nextchar=nxt.char
+ local nxt=getnext(start)
+ while not done and nxt and getid(nxt)==glyph_code and getfont(nxt)==currentfont and getsubtype(nxt)<256 do
+ local nextchar=getchar(nxt)
if marks[nextchar] then
- nxt=nxt.next
+ nxt=getnext(nxt)
else
local entryanchors=descriptions[nextchar]
if entryanchors then
@@ -9525,7 +9595,7 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
return head,start,done
else
if trace_cursive and trace_details then
- logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone)
+ logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone)
end
return head,start,false
end
@@ -9533,7 +9603,7 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
return head,start,false
end
function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local startchar=start.char
+ local startchar=getchar(start)
local subtables=currentlookup.subtables
local lookupname=subtables[1]
local kerns=lookuphash[lookupname]
@@ -9549,9 +9619,9 @@ function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lo
return head,start,false
end
function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
- local snext=start.next
+ local snext=getnext(start)
if snext then
- local startchar=start.char
+ local startchar=getchar(start)
local subtables=currentlookup.subtables
local lookupname=subtables[1]
local kerns=lookuphash[lookupname]
@@ -9561,26 +9631,26 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look
local lookuptype=lookuptypes[lookupname]
local prev,done=start,false
local factor=tfmdata.parameters.factor
- while snext and snext.id==glyph_code and snext.font==currentfont and snext.subtype<256 do
- local nextchar=snext.char
+ while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
+ local nextchar=getchar(snext)
local krn=kerns[nextchar]
if not krn and marks[nextchar] then
prev=snext
- snext=snext.next
+ snext=getnext(snext)
else
if not krn then
elseif type(krn)=="table" then
if lookuptype=="pair" then
local a,b=krn[2],krn[3]
if a and #a>0 then
- local startchar=start.char
+ local startchar=getchar(start)
local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
if trace_kerns then
logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
end
end
if b and #b>0 then
- local startchar=start.char
+ local startchar=getchar(start)
local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
if trace_kerns then
logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
@@ -9592,7 +9662,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look
if a and a~=0 then
local k=setkern(snext,factor,rlmode,a)
if trace_kerns then
- logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar))
+ logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
end
end
if b and b~=0 then
@@ -9603,7 +9673,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look
elseif krn~=0 then
local k=setkern(snext,factor,rlmode,krn)
if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar))
+ logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
end
done=true
end
@@ -9640,7 +9710,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
local seq=ck[3]
local s=#seq
if s==1 then
- match=current.id==glyph_code and current.font==currentfont and current.subtype<256 and seq[1][current.char]
+ match=getid(current)==glyph_code and getfont(current)==currentfont and getsubtype(current)<256 and seq[1][getchar(current)]
else
local f,l=ck[4],ck[5]
if f==1 and f==l then
@@ -9648,13 +9718,13 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if f==l then
else
local n=f+1
- last=last.next
+ last=getnext(last)
while n<=l do
if last then
- local id=last.id
+ local id=getid(last)
if id==glyph_code then
- if last.font==currentfont and last.subtype<256 then
- local char=last.char
+ if getfont(last)==currentfont and getsubtype(last)<256 then
+ local char=getchar(last)
local ccd=descriptions[char]
if ccd then
local class=ccd.class
@@ -9663,10 +9733,10 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if trace_skips then
show_skip(kind,chainname,char,ck,class)
end
- last=last.next
+ last=getnext(last)
elseif seq[n][char] then
if n<l then
- last=last.next
+ last=getnext(last)
end
n=n+1
else
@@ -9682,7 +9752,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
break
end
elseif id==disc_code then
- last=last.next
+ last=getnext(last)
else
match=false
break
@@ -9695,15 +9765,15 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
if match and f>1 then
- local prev=start.prev
+ local prev=getprev(start)
if prev then
local n=f-1
while n>=1 do
if prev then
- local id=prev.id
+ local id=getid(prev)
if id==glyph_code then
- if prev.font==currentfont and prev.subtype<256 then
- local char=prev.char
+ if getfont(prev)==currentfont and getsubtype(prev)<256 then
+ local char=getchar(prev)
local ccd=descriptions[char]
if ccd then
local class=ccd.class
@@ -9733,7 +9803,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
match=false
break
end
- prev=prev.prev
+ prev=getprev(prev)
elseif seq[n][32] then
n=n -1
else
@@ -9753,15 +9823,15 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
end
end
if match and s>l then
- local current=last and last.next
+ local current=last and getnext(last)
if current then
local n=l+1
while n<=s do
if current then
- local id=current.id
+ local id=getid(current)
if id==glyph_code then
- if current.font==currentfont and current.subtype<256 then
- local char=current.char
+ if getfont(current)==currentfont and getsubtype(current)<256 then
+ local char=getchar(current)
local ccd=descriptions[char]
if ccd then
local class=ccd.class
@@ -9791,7 +9861,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
match=false
break
end
- current=current.next
+ current=getnext(current)
elseif seq[n][32] then
n=n+1
else
@@ -9814,7 +9884,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
if match then
if trace_contexts then
local rule,lookuptype,f,l=ck[1],ck[2],ck[4],ck[5]
- local char=start.char
+ local char=getchar(start)
if ck[9] then
logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a, %a => %a",
cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype,ck[9],ck[10])
@@ -9844,12 +9914,12 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
repeat
if skipped then
while true do
- local char=start.char
+ local char=getchar(start)
local ccd=descriptions[char]
if ccd then
local class=ccd.class
if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
- start=start.next
+ start=getnext(start)
else
break
end
@@ -9874,7 +9944,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
i=i+1
end
if start then
- start=start.next
+ start=getnext(start)
else
end
until i>nofchainlookups
@@ -10001,6 +10071,7 @@ local function featuresprocessor(head,font,attr)
if not lookuphash then
return head,false
end
+ head=tonut(head)
if trace_steps then
checkstep(head)
end
@@ -10033,10 +10104,10 @@ local function featuresprocessor(head,font,attr)
local handler=handlers[typ]
local start=find_node_tail(head)
while start do
- local id=start.id
+ local id=getid(start)
if id==glyph_code then
- if start.font==font and start.subtype<256 then
- local a=start[0]
+ if getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
if a then
a=a==attr
else
@@ -10047,7 +10118,7 @@ local function featuresprocessor(head,font,attr)
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[start.char]
+ local lookupmatch=lookupcache[getchar(start)]
if lookupmatch then
head,start,success=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
if success then
@@ -10058,15 +10129,15 @@ local function featuresprocessor(head,font,attr)
report_missing_cache(typ,lookupname)
end
end
- if start then start=start.prev end
+ if start then start=getprev(start) end
else
- start=start.prev
+ start=getprev(start)
end
else
- start=start.prev
+ start=getprev(start)
end
else
- start=start.prev
+ start=getprev(start)
end
end
else
@@ -10081,17 +10152,17 @@ local function featuresprocessor(head,font,attr)
report_missing_cache(typ,lookupname)
else
while start do
- local id=start.id
+ local id=getid(start)
if id==glyph_code then
- if start.font==font and start.subtype<256 then
- local a=start[0]
+ if getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
if a then
- a=(a==attr) and (not attribute or start[a_state]==attribute)
+ a=(a==attr) and (not attribute or getattr(start,a_state)==attribute)
else
- a=not attribute or start[a_state]==attribute
+ a=not attribute or getattr(start,a_state)==attribute
end
if a then
- local lookupmatch=lookupcache[start.char]
+ local lookupmatch=lookupcache[getchar(start)]
if lookupmatch then
local ok
head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
@@ -10099,17 +10170,17 @@ local function featuresprocessor(head,font,attr)
success=true
end
end
- if start then start=start.next end
+ if start then start=getnext(start) end
else
- start=start.next
+ start=getnext(start)
end
else
- start=start.next
+ start=getnext(start)
end
elseif id==whatsit_code then
- local subtype=start.subtype
+ local subtype=getsubtype(start)
if subtype==dir_code then
- local dir=start.dir
+ local dir=getfield(start,"dir")
if dir=="+TRT" or dir=="+TLT" then
topstack=topstack+1
dirstack[topstack]=dir
@@ -10128,7 +10199,7 @@ local function featuresprocessor(head,font,attr)
report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
end
elseif subtype==localpar_code then
- local dir=start.dir
+ local dir=getfield(start,"dir")
if dir=="TRT" then
rlparmode=-1
elseif dir=="TLT" then
@@ -10141,31 +10212,31 @@ local function featuresprocessor(head,font,attr)
report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
end
end
- start=start.next
+ start=getnext(start)
elseif id==math_code then
- start=end_of_math(start).next
+ start=getnext(end_of_math(start))
else
- start=start.next
+ start=getnext(start)
end
end
end
else
while start do
- local id=start.id
+ local id=getid(start)
if id==glyph_code then
- if start.font==font and start.subtype<256 then
- local a=start[0]
+ if getfont(start)==font and getsubtype(start)<256 then
+ local a=getattr(start,0)
if a then
- a=(a==attr) and (not attribute or start[a_state]==attribute)
+ a=(a==attr) and (not attribute or getattr(start,a_state)==attribute)
else
- a=not attribute or start[a_state]==attribute
+ a=not attribute or getattr(start,a_state)==attribute
end
if a then
for i=1,ns do
local lookupname=subtables[i]
local lookupcache=lookuphash[lookupname]
if lookupcache then
- local lookupmatch=lookupcache[start.char]
+ local lookupmatch=lookupcache[getchar(start)]
if lookupmatch then
local ok
head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
@@ -10180,17 +10251,17 @@ local function featuresprocessor(head,font,attr)
report_missing_cache(typ,lookupname)
end
end
- if start then start=start.next end
+ if start then start=getnext(start) end
else
- start=start.next
+ start=getnext(start)
end
else
- start=start.next
+ start=getnext(start)
end
elseif id==whatsit_code then
- local subtype=start.subtype
+ local subtype=getsubtype(start)
if subtype==dir_code then
- local dir=start.dir
+ local dir=getfield(start,"dir")
if dir=="+TRT" or dir=="+TLT" then
topstack=topstack+1
dirstack[topstack]=dir
@@ -10209,7 +10280,7 @@ local function featuresprocessor(head,font,attr)
report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
end
elseif subtype==localpar_code then
- local dir=start.dir
+ local dir=getfield(start,"dir")
if dir=="TRT" then
rlparmode=-1
elseif dir=="TLT" then
@@ -10222,11 +10293,11 @@ local function featuresprocessor(head,font,attr)
report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
end
end
- start=start.next
+ start=getnext(start)
elseif id==math_code then
- start=end_of_math(start).next
+ start=getnext(end_of_math(start))
else
- start=start.next
+ start=getnext(start)
end
end
end
@@ -10238,6 +10309,7 @@ local function featuresprocessor(head,font,attr)
registerstep(head)
end
end
+ head=tonode(head)
return head,done
end
local function generic(lookupdata,lookupname,unicode,lookuphash)
diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua
index 89592fcac..88d6a2f0e 100644
--- a/tex/generic/context/luatex/luatex-fonts.lua
+++ b/tex/generic/context/luatex/luatex-fonts.lua
@@ -192,7 +192,7 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
-- with context. The mtx-fonts script can be used to genate this file (using the --names option).
-- In 2013/14 I will merge/move some generic files into luatex-fonts-* files (copies) so that
- -- intermediate updates of context not interfere. We can then also use the general merger and
+ -- intermediate updates of context don't interfere. We can then also use the general merger and
-- consider stripping debug code.
loadmodule('font-ini.lua')
@@ -209,7 +209,6 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule('font-ota.lua')
loadmodule('font-otn.lua')
loadmodule('font-otp.lua') -- optional
- ----------('luatex-fonts-chr.lua')
loadmodule('luatex-fonts-lua.lua')
loadmodule('font-def.lua')
loadmodule('luatex-fonts-def.lua')