summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/context/documents/general/manuals/luametatex.pdfbin1232220 -> 1232228 bytes
-rw-r--r--scripts/context/lua/mtxrun.lua6
-rw-r--r--scripts/context/stubs/mswin/mtxrun.lua6
-rw-r--r--scripts/context/stubs/unix/mtxrun6
-rw-r--r--scripts/context/stubs/win64/mtxrun.lua6
-rw-r--r--tex/context/base/mkii/cont-new.mkii2
-rw-r--r--tex/context/base/mkii/context.mkii2
-rw-r--r--tex/context/base/mkiv/catc-ini.lua8
-rw-r--r--tex/context/base/mkiv/catc-ini.mkiv2
-rw-r--r--tex/context/base/mkiv/char-ini.lua2
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--tex/context/base/mkiv/context.mkiv2
-rw-r--r--tex/context/base/mkiv/libs-ini.lua3
-rw-r--r--tex/context/base/mkiv/node-ini.lua32
-rw-r--r--tex/context/base/mkiv/spac-ali.lua2
-rw-r--r--tex/context/base/mkiv/spac-chr.lua26
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin26176 -> 26183 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin256343 -> 256336 bytes
-rw-r--r--tex/context/base/mkiv/toks-scn.lua10
-rw-r--r--tex/context/base/mkxl/anch-pos.mkxl12
-rw-r--r--tex/context/base/mkxl/blob-ini.mkxl2
-rw-r--r--tex/context/base/mkxl/catc-ini.lmt44
-rw-r--r--tex/context/base/mkxl/catc-ini.mkxl64
-rw-r--r--tex/context/base/mkxl/colo-ini.mkxl8
-rw-r--r--tex/context/base/mkxl/cont-new.mkxl2
-rw-r--r--tex/context/base/mkxl/context.mkxl14
-rw-r--r--tex/context/base/mkxl/file-mod.mklx6
-rw-r--r--tex/context/base/mkxl/font-lib.mklx2
-rw-r--r--tex/context/base/mkxl/font-mat.mklx14
-rw-r--r--tex/context/base/mkxl/font-ota.lmt569
-rw-r--r--tex/context/base/mkxl/lang-ini.mkxl4
-rw-r--r--tex/context/base/mkxl/luat-ini.mkxl10
-rw-r--r--tex/context/base/mkxl/math-ali.mkxl55
-rw-r--r--tex/context/base/mkxl/math-def.mkxl3
-rw-r--r--tex/context/base/mkxl/math-fen.mkxl2
-rw-r--r--tex/context/base/mkxl/math-ini.mkxl64
-rw-r--r--tex/context/base/mkxl/math-pln.mkxl2
-rw-r--r--tex/context/base/mkxl/meta-ini.mkxl69
-rw-r--r--tex/context/base/mkxl/mult-aux.mkxl8
-rw-r--r--tex/context/base/mkxl/node-ini.lmt36
-rw-r--r--tex/context/base/mkxl/node-ref.lmt811
-rw-r--r--tex/context/base/mkxl/node-rul.mkxl2
-rw-r--r--tex/context/base/mkxl/pack-rul.mkxl8
-rw-r--r--tex/context/base/mkxl/page-brk.mkxl2
-rw-r--r--tex/context/base/mkxl/page-mbk.mklx16
-rw-r--r--tex/context/base/mkxl/page-mix.mkxl2
-rw-r--r--tex/context/base/mkxl/scrn-but.mklx3
-rw-r--r--tex/context/base/mkxl/scrn-fld.mklx8
-rw-r--r--tex/context/base/mkxl/scrn-pag.mklx4
-rw-r--r--tex/context/base/mkxl/scrn-ref.mklx5
-rw-r--r--tex/context/base/mkxl/scrn-wid.mklx11
-rw-r--r--tex/context/base/mkxl/spac-ali.lmt134
-rw-r--r--tex/context/base/mkxl/spac-ali.mkxl349
-rw-r--r--tex/context/base/mkxl/spac-chr.lmt348
-rw-r--r--tex/context/base/mkxl/spac-chr.mkxl2
-rw-r--r--tex/context/base/mkxl/spac-hor.lmt38
-rw-r--r--tex/context/base/mkxl/spac-hor.mkxl102
-rw-r--r--tex/context/base/mkxl/spac-prf.lmt949
-rw-r--r--tex/context/base/mkxl/spac-prf.mklx12
-rw-r--r--tex/context/base/mkxl/spac-ver.mkxl58
-rw-r--r--tex/context/base/mkxl/strc-con.mklx28
-rw-r--r--tex/context/base/mkxl/strc-doc.mkxl40
-rw-r--r--tex/context/base/mkxl/strc-flt.mklx10
-rw-r--r--tex/context/base/mkxl/strc-itm.mklx12
-rw-r--r--tex/context/base/mkxl/strc-mat.mkxl29
-rw-r--r--tex/context/base/mkxl/strc-ref.mklx26
-rw-r--r--tex/context/base/mkxl/strc-reg.mkxl24
-rw-r--r--tex/context/base/mkxl/strc-sec.mkxl28
-rw-r--r--tex/context/base/mkxl/supp-box.mkxl2
-rw-r--r--tex/context/base/mkxl/syst-aux.mkxl8
-rw-r--r--tex/context/base/mkxl/syst-ini.mkxl8
-rw-r--r--tex/context/base/mkxl/tabl-ntb.mkxl14
-rw-r--r--tex/context/base/mkxl/tabl-tbl.mkxl12
-rw-r--r--tex/context/base/mkxl/tabl-tsp.mkxl4
-rw-r--r--tex/context/base/mkxl/toks-scn.mkxl5
-rw-r--r--tex/context/base/mkxl/trac-vis.lmt8
-rw-r--r--tex/context/base/mkxl/typo-cap.lmt420
-rw-r--r--tex/context/base/mkxl/typo-cap.mkxl18
-rw-r--r--tex/context/base/mkxl/typo-del.mkxl4
-rw-r--r--tex/context/base/mkxl/typo-mar.mkxl5
-rw-r--r--tex/context/modules/mkiv/m-scite.mkiv2
-rw-r--r--tex/context/modules/mkiv/s-system-macros.mkxl2
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua2
83 files changed, 3968 insertions, 714 deletions
diff --git a/doc/context/documents/general/manuals/luametatex.pdf b/doc/context/documents/general/manuals/luametatex.pdf
index 8bf43b633..a06bc7c1b 100644
--- a/doc/context/documents/general/manuals/luametatex.pdf
+++ b/doc/context/documents/general/manuals/luametatex.pdf
Binary files differ
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index 3f2bb0051..fa5dd6e8e 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -25221,7 +25221,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["libs-ini"] = package.loaded["libs-ini"] or true
--- original size: 6287, stripped down to: 4006
+-- original size: 6459, stripped down to: 4006
if not modules then modules={} end modules ['libs-ini']={
version=1.001,
@@ -25776,8 +25776,8 @@ end -- of closure
-- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua
-- skipped libraries : -
--- original bytes : 1023457
--- stripped bytes : 404622
+-- original bytes : 1023629
+-- stripped bytes : 404794
-- end library merge
diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua
index 3f2bb0051..fa5dd6e8e 100644
--- a/scripts/context/stubs/mswin/mtxrun.lua
+++ b/scripts/context/stubs/mswin/mtxrun.lua
@@ -25221,7 +25221,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["libs-ini"] = package.loaded["libs-ini"] or true
--- original size: 6287, stripped down to: 4006
+-- original size: 6459, stripped down to: 4006
if not modules then modules={} end modules ['libs-ini']={
version=1.001,
@@ -25776,8 +25776,8 @@ end -- of closure
-- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua
-- skipped libraries : -
--- original bytes : 1023457
--- stripped bytes : 404622
+-- original bytes : 1023629
+-- stripped bytes : 404794
-- end library merge
diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun
index 3f2bb0051..fa5dd6e8e 100644
--- a/scripts/context/stubs/unix/mtxrun
+++ b/scripts/context/stubs/unix/mtxrun
@@ -25221,7 +25221,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["libs-ini"] = package.loaded["libs-ini"] or true
--- original size: 6287, stripped down to: 4006
+-- original size: 6459, stripped down to: 4006
if not modules then modules={} end modules ['libs-ini']={
version=1.001,
@@ -25776,8 +25776,8 @@ end -- of closure
-- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua
-- skipped libraries : -
--- original bytes : 1023457
--- stripped bytes : 404622
+-- original bytes : 1023629
+-- stripped bytes : 404794
-- end library merge
diff --git a/scripts/context/stubs/win64/mtxrun.lua b/scripts/context/stubs/win64/mtxrun.lua
index 3f2bb0051..fa5dd6e8e 100644
--- a/scripts/context/stubs/win64/mtxrun.lua
+++ b/scripts/context/stubs/win64/mtxrun.lua
@@ -25221,7 +25221,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["libs-ini"] = package.loaded["libs-ini"] or true
--- original size: 6287, stripped down to: 4006
+-- original size: 6459, stripped down to: 4006
if not modules then modules={} end modules ['libs-ini']={
version=1.001,
@@ -25776,8 +25776,8 @@ end -- of closure
-- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua
-- skipped libraries : -
--- original bytes : 1023457
--- stripped bytes : 404622
+-- original bytes : 1023629
+-- stripped bytes : 404794
-- end library merge
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index 64a98aa95..db88cd563 100644
--- a/tex/context/base/mkii/cont-new.mkii
+++ b/tex/context/base/mkii/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2020.11.26 15:38}
+\newcontextversion{2020.11.27 20:07}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii
index 25607f8b0..5961be478 100644
--- a/tex/context/base/mkii/context.mkii
+++ b/tex/context/base/mkii/context.mkii
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2020.11.26 15:38}
+\edef\contextversion{2020.11.27 20:07}
%D For those who want to use this:
diff --git a/tex/context/base/mkiv/catc-ini.lua b/tex/context/base/mkiv/catc-ini.lua
index 9241f5a1b..4da00436b 100644
--- a/tex/context/base/mkiv/catc-ini.lua
+++ b/tex/context/base/mkiv/catc-ini.lua
@@ -31,15 +31,11 @@ end
-- this only happens at runtime
-for k, v in next, numbers do
- tex[k] = v -- downward compatible
+for name, number in next, numbers do
+ tex[name] = number -- downward compatible
end
-- nasty
table.setmetatableindex(numbers,function(t,k) if type(k) == "number" then t[k] = k return k end end)
table.setmetatableindex(names, function(t,k) if type(k) == "string" then t[k] = k return k end end)
-
-commands.registercatcodetable = catcodes.register
---------.definecatcodetable = characters.define -- not yet defined
---------.setcharactercodes = characters.setcodes -- not yet defined
diff --git a/tex/context/base/mkiv/catc-ini.mkiv b/tex/context/base/mkiv/catc-ini.mkiv
index a177b26ca..d0b2c3e16 100644
--- a/tex/context/base/mkiv/catc-ini.mkiv
+++ b/tex/context/base/mkiv/catc-ini.mkiv
@@ -177,7 +177,7 @@
\expandafter\xdef\csname\??catcodetablen\number\c_syst_catcodes_n\endcsname{\string#1}% logging
\newconstant#1%
#1\c_syst_catcodes_n
- \ctxcommand{registercatcodetable("\expandafter\gobbleoneargument\string#1",\number#1)}}
+ \ctxlua{catcodes.register("\expandafter\gobbleoneargument\string#1",\number#1)}}
\newtoks \everysetdefaultcatcodes
diff --git a/tex/context/base/mkiv/char-ini.lua b/tex/context/base/mkiv/char-ini.lua
index 1f8e72af7..ac31dbfc6 100644
--- a/tex/context/base/mkiv/char-ini.lua
+++ b/tex/context/base/mkiv/char-ini.lua
@@ -762,7 +762,7 @@ local is_spacing = allocate ( tohash {
} )
local is_mark = allocate ( tohash {
- "mn", "ms",
+ "mn", "ms", -- "mn", "mc",
} )
local is_punctuation = allocate ( tohash {
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index 319b6dfa1..ae825d74e 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -13,7 +13,7 @@
% \normalend % uncomment this to get the real base runtime
-\newcontextversion{2020.11.26 15:38}
+\newcontextversion{2020.11.27 20:07}
%D This file is loaded at runtime, thereby providing an excellent place for hacks,
%D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index aa1a49022..69a4cc899 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -45,7 +45,7 @@
%D {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2020.11.26 15:38}
+\edef\contextversion{2020.11.27 20:07}
%D Kind of special:
diff --git a/tex/context/base/mkiv/libs-ini.lua b/tex/context/base/mkiv/libs-ini.lua
index 7f1645b44..5b8390df2 100644
--- a/tex/context/base/mkiv/libs-ini.lua
+++ b/tex/context/base/mkiv/libs-ini.lua
@@ -156,6 +156,9 @@ function libraries.optionalloaded(name,libnames)
end
end
+-- For the moment the next blob is needed when we run \MTXRUN\ on top of \LUATEX\ and
+-- \LUAJITTEX\ but at some point we will {\em always} assume \LUAMETATEX\ as runner.
+
if FFISUPPORTED and ffi and ffi.load then
local ffiload = ffi.load
diff --git a/tex/context/base/mkiv/node-ini.lua b/tex/context/base/mkiv/node-ini.lua
index 3d49d01bd..701e3efa9 100644
--- a/tex/context/base/mkiv/node-ini.lua
+++ b/tex/context/base/mkiv/node-ini.lua
@@ -124,11 +124,10 @@ local noadoptions = allocate {
right = 0x14 + 0x08,
}
-local dirvalues = CONTEXTLMTXMODE > 0 and mark(getvalues("dir"))
-
-if not dirvalues then
- dirvalues = allocate { [0] = "lefttoright", [1] = "righttoleft" }
-end
+local dirvalues = allocate {
+ [0] = "lefttoright",
+ [1] = "righttoleft",
+}
local literalvalues = allocate {
[0] = "origin",
@@ -243,12 +242,9 @@ nodes.subtypes = allocate {
-- [nodecodes.user] = usercodes,
[nodecodes.vlist] = listcodes,
[nodecodes.whatsit] = whatcodes,
+ [nodecodes.marginkern] = margincodes
}
-if CONTEXTLMTXMODE == 0 then
- nodes.subtypes[nodecodes.marginkern] = margincodes
-end
-
table.setmetatableindex(nodes.subtypes,function(t,k)
local v = { }
t[k] = v
@@ -338,21 +334,3 @@ trackers.register("system.showcodes", nodes.showcodes)
if node.fix_node_lists then
node.fix_node_lists(false)
end
-
--- We use the real node code numbers.
-
-if environment.initex and CONTEXTLMTXMODE > 0 then
-
- local texchardef = tex.chardef
-
- if texchardef then
- for i=0,nodecodes.glyph do
- texchardef(nodecodes[i] .. "nodecode",i)
- end
- for i=0,#gluecodes do
- texchardef(gluecodes[i] .. "subtypecode",i)
- end
- -- tex.set("internalcodesmode",1) -- obsolete
- end
-
-end
diff --git a/tex/context/base/mkiv/spac-ali.lua b/tex/context/base/mkiv/spac-ali.lua
index 7a09ba5aa..2e2650f3b 100644
--- a/tex/context/base/mkiv/spac-ali.lua
+++ b/tex/context/base/mkiv/spac-ali.lua
@@ -112,7 +112,7 @@ local function handler(head,leftpage,realpageno) -- traverse_list
local head = setlink(new_stretch(3),list) -- prepend
setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
if trace_realign then
- report_realign("flushing right. align %a, page %a, realpage %a",align,pageno,realpageno)
+ report_realign("flushing right, align %a, page %a, realpage %a",align,pageno,realpageno)
end
elseif trace_realign then
report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno)
diff --git a/tex/context/base/mkiv/spac-chr.lua b/tex/context/base/mkiv/spac-chr.lua
index ac90926e1..fa6eb18a5 100644
--- a/tex/context/base/mkiv/spac-chr.lua
+++ b/tex/context/base/mkiv/spac-chr.lua
@@ -81,7 +81,7 @@ local fontquads = fonthashes.quads
local setmetatableindex = table.setmetatableindex
-local a_character = attributes.private("characters")
+local a_character = attributes.private("characters") -- this will become a property (or maybe even a field)
local a_alignstate = attributes.private("alignstate")
local c_zero = byte('0')
@@ -295,30 +295,6 @@ local methods = {
characters.methods = methods
--- function characters.handler(head) -- todo: use traverse_id
--- local current = head
--- while current do
--- local char, id = isglyph(current)
--- if char then
--- local next = getnext(current)
--- local method = methods[char]
--- if method then
--- if trace_characters then
--- report_characters("replacing character %C, description %a",char,lower(chardata[char].description))
--- end
--- local h = method(head,current)
--- if h then
--- head = remove_node(h,current,true)
--- end
--- end
--- current = next
--- else
--- current = getnext(current)
--- end
--- end
--- return head
--- end
-
-- this also works ok in math as we run over glyphs and these stay glyphs ... not sure
-- about scripts and such but that is not important anyway ... some day we can consider
-- special definitions in math
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index 8e4f09585..5f7f0b520 100644
--- a/tex/context/base/mkiv/status-files.pdf
+++ b/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index 3c6728c0d..d6aefd1d5 100644
--- a/tex/context/base/mkiv/status-lua.pdf
+++ b/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/toks-scn.lua b/tex/context/base/mkiv/toks-scn.lua
index ec5681cd7..98d2f66c0 100644
--- a/tex/context/base/mkiv/toks-scn.lua
+++ b/tex/context/base/mkiv/toks-scn.lua
@@ -294,11 +294,6 @@ local f_elseif = formatters[" elseif scankeywordcs('%s') then data['%s'] = sc
----- f_if_x = formatters[ " if not data['%s'] and scankeywordcs('%s') then data['%s'] = scan%s()"]
----- f_elseif_x = formatters[" elseif not data['%s'] and scankeywordcs('%s') then data['%s'] = scan%s()"]
--- if CONTEXTLMTXMODE > 0 then
--- f_if = formatters[" local key = scanletters() if key == '' then break elseif key == '%s' then data['%s'] = scan%s()"]
--- f_elseif = formatters[" elseif key == '%s' then data['%s'] = scan%s()"]
--- end
-
local f_local = formatters["local scan%s = scanners.%s"]
local f_scan = formatters["scan%s()"]
local f_shortcut = formatters["local %s = scanners.converters.%s"]
@@ -309,11 +304,6 @@ local f_scan_c = formatters["%s(scan%s())"]
-- see above
--- if CONTEXTLMTXMODE > 0 then
--- f_if_c = formatters[" local key = scanletters() if key == '' then break elseif key == '%s' then data['%s'] = %s(scan%s())"]
--- f_elseif_c = formatters[" elseif k == '%s' then data['%s'] = %s(scan%s())"]
--- end
-
local f_any = formatters[" else local key = scanword(true) if key then data[key] = scan%s() else break end end"]
local f_any_c = formatters[" else local key = scanword(true) if key then data[key] = %s(scan%s()) else break end end"]
local s_done = " else break end"
diff --git a/tex/context/base/mkxl/anch-pos.mkxl b/tex/context/base/mkxl/anch-pos.mkxl
index 53544fedc..6a2fbd5e1 100644
--- a/tex/context/base/mkxl/anch-pos.mkxl
+++ b/tex/context/base/mkxl/anch-pos.mkxl
@@ -396,18 +396,16 @@
{\the\t_anch_positions_tracers}
\permanent\protected\def\enableparpositions % global
- {\glet\registerparoptions\doregisterparoptions
+ {\enforced\aliased\glet\registerparoptions\doregisterparoptions
\global\positioningtrue}
\permanent\let\disableparpositions\relax
-\let\registerparoptions\relax
+\aliased\let\registerparoptions\relax
-\protected\def\doregisterparoptions
- {\iftrialtypesetting \else
- \ifinpagebody \else \ifmmode \else \ifinformula \else
- \anch_positions_register_par_options
- \fi \fi \fi
+\permanent\protected\def\doregisterparoptions
+ {\iftrialtypesetting \orelse\ifinpagebody \orelse\ifmmode \orelse\ifinformula \else
+ \anch_positions_register_par_options
\fi}
\def\anch_positions_register_par_options_normal
diff --git a/tex/context/base/mkxl/blob-ini.mkxl b/tex/context/base/mkxl/blob-ini.mkxl
index 3443836b7..1dcd55972 100644
--- a/tex/context/base/mkxl/blob-ini.mkxl
+++ b/tex/context/base/mkxl/blob-ini.mkxl
@@ -36,7 +36,7 @@
\aliased\let\heightanddepthofstring\totalofstring
\aliased\let\htdpofstring \hdofstring
-\let\hd\htdp % if yes then move this
+% \let\hd\htdp % if yes then move this
% This one takes anything that can be typeset
diff --git a/tex/context/base/mkxl/catc-ini.lmt b/tex/context/base/mkxl/catc-ini.lmt
new file mode 100644
index 000000000..ede8216a6
--- /dev/null
+++ b/tex/context/base/mkxl/catc-ini.lmt
@@ -0,0 +1,44 @@
+if not modules then modules = { } end modules ['catc-ini'] = {
+ version = 1.001,
+ comment = "companion to catc-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+catcodes = catcodes or { }
+catcodes.numbers = catcodes.numbers or { }
+catcodes.names = catcodes.names or { }
+
+storage.register("catcodes/numbers", catcodes.numbers, "catcodes.numbers")
+storage.register("catcodes/names", catcodes.names, "catcodes.names")
+
+local numbers = catcodes.numbers
+local names = catcodes.names
+
+-- We register the catcode tables in the \type {tex} namespace as we have been doing
+-- right from the start (when there wasn't much in that namespace). Normally
+-- registration of a table only happens when we're in so called ini mode. Also, the
+-- number of tables is rather small.
+
+function catcodes.register(name,number)
+ numbers[name] = number
+ local cnn = names[number]
+ if cnn then
+ cnn[#cnn+1] = name
+ else
+ names[number] = { name }
+ end
+ tex[name] = number -- downward compatible
+end
+
+-- At runtime we need to populate the \type {tex} namespace again.
+
+for name, number in next, numbers do
+ tex[name] = number -- downward compatible
+end
+
+-- We catch wrong usage.
+
+table.setmetatableindex(numbers,function(t,k) if type(k) == "number" then t[k] = k return k end end)
+table.setmetatableindex(names, function(t,k) if type(k) == "string" then t[k] = k return k end end)
diff --git a/tex/context/base/mkxl/catc-ini.mkxl b/tex/context/base/mkxl/catc-ini.mkxl
index 84d58b977..b7844fe89 100644
--- a/tex/context/base/mkxl/catc-ini.mkxl
+++ b/tex/context/base/mkxl/catc-ini.mkxl
@@ -11,8 +11,8 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D We've split the functionality of syst-cat.* over more files
-%D now so that we can load more selectively.
+%D We've split the functionality of syst-cat.* over more files now so that we can
+%D load more selectively.
\registerctxluafile{catc-ini}{}
@@ -50,12 +50,6 @@
% rather special and used in writing to file: \let\par\outputnewlinechar
-% \protected\def\initializenewlinechar % operating system dependent
-% {\begingroup
-% \newlinechar\newlineasciicode
-% \xdef\outputnewlinechar{^^J}%
-% \endgroup}
-
\permanent\protected\def\initializenewlinechar % operating system dependent
{\begingroup
\letcharcode\newlineasciicode\relax
@@ -63,17 +57,8 @@
\xdef\outputnewlinechar{\Uchar\newlineasciicode}%
\endgroup}
-%D We predefine some prefixes ahead of syst-aux and mult-sys.
-
-% We reserve 8 slots for catcodes.
-%
-% \def\??catcodelet {1>>} % let : \let
-% \def\??catcodedef {2>>} % def : \def
-% \def\??catcodeued {3>>} % ued : \protected\def
-% \def\??catcodeget {4>>} % \meaning
-%
-% \def\??catcodetablet{5>>}
-% \def\??catcodetablen{6>>}
+%D We predefine some prefixes ahead of syst-aux and mult-sys. We reserve 8 slots for
+%D catcodes.
\installsystemnamespace {catcodelet} % let : \let
\installsystemnamespace {catcodedef} % def : \def
@@ -91,9 +76,8 @@
\permanent\protected\def\newcatcodetable#1% we could move the cctdefcounter to lua
{\global\advance\c_syst_catcodes_n\plusone
\gdefcsname\??catcodetablen\number\c_syst_catcodes_n\endcsname{\string#1}% logging
- %\setnewconstant#1\c_syst_catcodes_n
\immutable\integerdef#1\c_syst_catcodes_n
- \ctxcommand{registercatcodetable("\expandafter\gobbleoneargument\string#1",\number#1)}}
+ \ctxlua{catcodes.register("\expandafter\gobbleoneargument\string#1",\number#1)}}
\newtoks \everysetdefaultcatcodes
@@ -199,24 +183,8 @@
\permanent\def\reinstatecatcodecommand{\afterassignment\syst_catcodes_reinstate_normal\c_syst_catcodes_b}
-% \def\syst_catcodes_reinstate_normal % can be used when a direct definition has been done
-% {\begingroup % and the selector has been lost
-% \uccode\c_syst_catcodes_hack\c_syst_catcodes_b
-% \catcode\uccode\c_syst_catcodes_hack\activecatcode
-% \uppercase{\xdef~{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}}%
-% \endgroup}
-
-% \def\syst_catcodes_reinstate_unexpanded % can be used when a direct definition has been done
-% {\begingroup % and the selector has been lost
-% \uccode\c_syst_catcodes_hack\c_syst_catcodes_b
-% \catcode\uccode\c_syst_catcodes_hack\activecatcode
-% \uppercase{\protected\xdef~{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}}%
-% \endgroup}
-
%D This can be used when a direct definition has been done and the selector has been
-%D lost.
-
-% problem: \next needs to be unique (as it gets bound)
+%D lost. A problem is that \type {\next} needs to be unique (as it gets bound) (still?).
\def\syst_catcodes_reinstate_normal
{\begingroup
@@ -243,13 +211,14 @@
%D {restorecatcodes,pushcatcodetable,popcatcodetable}
%D
%D We're not finished dealing \CATCODES\ yet. In \CONTEXT\ we use only one auxiliary
-%D file, which deals with tables of contents, registers, two pass tracking, references
-%D etc. This file, as well as files concerning graphics, is processed when needed,
-%D which can be in the mid of typesetting verbatim. However, when reading in data in
-%D verbatim mode, we should temporary restore the normal \CATCODES, and that's exactly
-%D what the next macros do. Saving the catcodes can be disabled by saying \type
-%D {\localcatcodestrue}. In \MKIV\ instead we can push and pop catcode tables and as
-%D we keep track of used tables users seldom need to deal with this themselves.
+%D file, which deals with tables of contents, registers, two pass tracking,
+%D references etc. This file, as well as files concerning graphics, is processed
+%D when needed, which can be in the mid of typesetting verbatim. However, when
+%D reading in data in verbatim mode, we should temporary restore the normal
+%D \CATCODES, and that's exactly what the next macros do. Saving the catcodes can be
+%D disabled by saying \type {\localcatcodestrue}. In \MKIV\ instead we can push and
+%D pop catcode tables and as we keep track of used tables users seldom need to deal
+%D with this themselves.
\newcount\c_syst_catcodes_level
@@ -277,11 +246,8 @@
\expandafter\catcodetable\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname
\fi}
-% \newtoks\everycatcodetable
-
\permanent\protected\def\setcatcodetable#1%
{\catcodetable#1%
-% \the\everycatcodetable
\syst_catcodes_trace_set}
%D Handy for debugging:
@@ -324,6 +290,6 @@
\newcatcodetable \inicatcodes
\initcatcodetable\inicatcodes
-\let\currentcatcodetable\catcodetable
+\mutable\let\currentcatcodetable\catcodetable
\endinput
diff --git a/tex/context/base/mkxl/colo-ini.mkxl b/tex/context/base/mkxl/colo-ini.mkxl
index b71ac42d9..e6ec0d103 100644
--- a/tex/context/base/mkxl/colo-ini.mkxl
+++ b/tex/context/base/mkxl/colo-ini.mkxl
@@ -61,10 +61,10 @@
\let\m_colo_weight_gray\v!yes
-\let\currentcolormodel \empty
-\let\currentcolorname \empty
-\let\currentcolorpalet \empty
-\let\currentcolorprefix\empty % \currentcolorpalet:
+\mutable\let\currentcolormodel \empty
+\mutable\let\currentcolorname \empty
+\mutable\let\currentcolorpalet \empty
+\mutable\let\currentcolorprefix\empty % \currentcolorpalet:
%D \macros
%D {definecolor,defineglobalcolor,definenamedcolor,definespotcolor,definemultitonecolor,
diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl
index 97b96b8cc..af62340bd 100644
--- a/tex/context/base/mkxl/cont-new.mkxl
+++ b/tex/context/base/mkxl/cont-new.mkxl
@@ -13,7 +13,7 @@
% \normalend % uncomment this to get the real base runtime
-\newcontextversion{2020.11.26 15:38}
+\newcontextversion{2020.11.27 20:07}
%D This file is loaded at runtime, thereby providing an excellent place for hacks,
%D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl
index c324d3917..d427c6c44 100644
--- a/tex/context/base/mkxl/context.mkxl
+++ b/tex/context/base/mkxl/context.mkxl
@@ -28,8 +28,8 @@
%D dependencies are more consistent. Beware, the version number has to match \type
%D {YYYY.MM.DD HH:MM} format.
-\edef\contextformat {\jobname}
-\edef\contextversion{2020.11.26 15:38}
+\immutable\edef\contextformat {\jobname}
+\immutable\edef\contextversion{2020.11.27 20:07}
%overloadmode 1 % check frozen / warning
%overloadmode 2 % check frozen / error
@@ -38,17 +38,17 @@
%D Kind of special:
-\chardef\contextlmtxmode\directlua{tex.print(CONTEXTLMTXMODE or 0)}\relax
+\immutable\chardef\contextlmtxmode\directlua{tex.print(CONTEXTLMTXMODE or 0)}\relax
%D For those who want to use this:
-\let\fmtname \contextformat
-\let\fmtversion\contextversion
+\aliased\let\fmtname \contextformat
+\aliased\let\fmtversion\contextversion
%D Loading:
-\edef\mksuffix {mkiv}
-\edef\contextmark{LMTX}
+\immutable\edef\mksuffix {mkiv}
+\immutable\edef\contextmark{LMTX}
\ifdefined\normalinput \else \let\normalinput\input \fi
diff --git a/tex/context/base/mkxl/file-mod.mklx b/tex/context/base/mkxl/file-mod.mklx
index a95ac3483..2f9f13f1c 100644
--- a/tex/context/base/mkxl/file-mod.mklx
+++ b/tex/context/base/mkxl/file-mod.mklx
@@ -31,9 +31,9 @@
\installcorenamespace{module}
-\let\currentmodule \s!unknown
-\let\currentmodulecategory \empty
-\let\currentmoduleparameters\empty
+\mutable\let\currentmodule \s!unknown
+\mutable\let\currentmodulecategory \empty
+\mutable\let\currentmoduleparameters\empty
\installmacrostack\currentmodule
\installmacrostack\currentmodulecategory
diff --git a/tex/context/base/mkxl/font-lib.mklx b/tex/context/base/mkxl/font-lib.mklx
index 4a0c1627f..509e8ed86 100644
--- a/tex/context/base/mkxl/font-lib.mklx
+++ b/tex/context/base/mkxl/font-lib.mklx
@@ -41,7 +41,7 @@
\registerctxluafile{font-oto}{}
\registerctxluafile{font-otj}{optimize}
\registerctxluafile{font-oup}{}
-\registerctxluafile{font-ota}{}
+\registerctxluafile{font-ota}{autosuffix}
\registerctxluafile{font-ots}{optimize}
\registerctxluafile{font-otd}{optimize}
\registerctxluafile{font-otc}{}
diff --git a/tex/context/base/mkxl/font-mat.mklx b/tex/context/base/mkxl/font-mat.mklx
index c81b7c5c7..b3008b6be 100644
--- a/tex/context/base/mkxl/font-mat.mklx
+++ b/tex/context/base/mkxl/font-mat.mklx
@@ -416,7 +416,7 @@
\newconditional\c_math_bold
-\protected\def\mr % math regular
+\permanent\protected\def\mr % math regular
{\ifmmode
\font_helpers_synchronize_math_family_mr
\else
@@ -425,7 +425,7 @@
\mathdefault
\setfalse\c_math_bold}
-\protected\def\mb % math bold
+\permanent\protected\def\mb % math bold
{\ifmmode
\font_helpers_synchronize_math_family_mb
\else
@@ -463,13 +463,13 @@
\fi
\to \everymathematics
-\protected\def\nobigmath {\synchronizebigmathflag\zerocount}
-\protected\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath}
-\protected\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath}
+\permanent\protected\def\nobigmath {\synchronizebigmathflag\zerocount}
+\permanent\protected\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath}
+\permanent\protected\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath}
-\let\bigmathfontsize\empty
+\mutable\let\bigmathfontsize\empty
-\protected\def\synchronizebigmath
+\permanent\protected\def\synchronizebigmath
{\ifx\bigmathfontsize\fontsize
% already in sync
\else
diff --git a/tex/context/base/mkxl/font-ota.lmt b/tex/context/base/mkxl/font-ota.lmt
new file mode 100644
index 000000000..8f6c059ef
--- /dev/null
+++ b/tex/context/base/mkxl/font-ota.lmt
@@ -0,0 +1,569 @@
+if not modules then modules = { } end modules ['font-ota'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- context only
+
+local type = type
+local setmetatableindex = table.setmetatableindex
+
+if not trackers then trackers = { register = function() end } end
+
+----- trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end)
+
+local fonts, nodes, node = fonts, nodes, node
+
+local allocate = utilities.storage.allocate
+
+local otf = fonts.handlers.otf
+
+local analyzers = fonts.analyzers
+local initializers = allocate()
+local methods = allocate()
+
+analyzers.initializers = initializers
+analyzers.methods = methods
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getprev = nuts.getprev
+local getprop = nuts.getprop
+local setprop = nuts.setprop
+local getsubtype = nuts.getsubtype
+local getchar = nuts.getchar
+local ischar = nuts.ischar
+
+local end_of_math = nuts.end_of_math
+
+local nodecodes = nodes.nodecodes
+local disc_code = nodecodes.disc
+local math_code = nodecodes.math
+
+local fontdata = fonts.hashes.identifiers
+local descriptiondata = fonts.hashes.descriptions
+local categories = characters and characters.categories or { } -- sorry, only in context
+local chardata = characters and characters.data
+
+local otffeatures = fonts.constructors.features.otf
+local registerotffeature = otffeatures.register
+
+--[[ldx--
+<p>Analyzers run per script and/or language and are needed in order to
+process features right.</p>
+--ldx]]--
+
+local setstate = nuts.setstate
+local getstate = nuts.getstate
+
+local classifiers = characters.classifiers
+
+-- never use these numbers directly
+
+local s_init = 1 local s_rphf = 7
+local s_medi = 2 local s_half = 8
+local s_fina = 3 local s_pref = 9
+local s_isol = 4 local s_blwf = 10
+local s_mark = 5 local s_pstf = 11
+local s_rest = 6
+
+local states = allocate {
+ init = s_init,
+ medi = s_medi,
+ med2 = s_medi,
+ fina = s_fina,
+ fin2 = s_fina,
+ fin3 = s_fina,
+ isol = s_isol,
+ mark = s_mark,
+ rest = s_rest,
+ rphf = s_rphf,
+ half = s_half,
+ pref = s_pref,
+ blwf = s_blwf,
+ pstf = s_pstf,
+}
+
+local features = allocate {
+ init = s_init,
+ medi = s_medi,
+ med2 = s_medi,
+ fina = s_fina,
+ fin2 = s_fina,
+ fin3 = s_fina,
+ isol = s_isol,
+ -- mark = s_mark,
+ -- rest = s_rest,
+ rphf = s_rphf,
+ half = s_half,
+ pref = s_pref,
+ blwf = s_blwf,
+ pstf = s_pstf,
+}
+
+local mappers = allocate {
+ l = s_init, -- left
+ d = s_medi, -- double
+ c = s_medi, -- joiner
+ r = s_fina, -- right
+ u = s_isol, -- nonjoiner
+}
+
+analyzers.states = states
+analyzers.features = features
+analyzers.useunicodemarks = false
+
+if not classifiers then
+
+ -- why not just always use categories[k] = "mn"
+
+ local f_arabic, l_arabic = characters.blockrange("arabic")
+ local f_syriac, l_syriac = characters.blockrange("syriac")
+ local f_mandiac, l_mandiac = characters.blockrange("mandiac")
+ local f_nko, l_nko = characters.blockrange("nko")
+ local f_ext_a, l_ext_a = characters.blockrange("arabicextendeda")
+
+ classifiers = setmetatableindex(function(t,k)
+ if type(k) == "number" then
+ local c = chardata[k]
+ local v = false
+ if c then
+ local arabic = c.arabic
+ if arabic then
+ v = mappers[arabic]
+ if not v then
+ log.report("analyze","error in mapping arabic %C",k)
+ -- error
+ v = false
+ end
+ elseif (k >= f_arabic and k <= l_arabic) or
+ (k >= f_syriac and k <= l_syriac) or
+ (k >= f_mandiac and k <= l_mandiac) or
+ (k >= f_nko and k <= l_nko) or
+ (k >= f_ext_a and k <= l_ext_a) then
+ if categories[k] == "mn" then
+ v = s_mark
+ else
+ v = s_rest
+ end
+ end
+ end
+ t[k] = v
+ return v
+ end
+ end)
+
+ characters.classifiers = classifiers
+
+end
+
+-- todo: analyzers per script/lang, cross font, so we need an font id hash -> script
+-- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace
+
+local is_letter = characters.is_letter
+local is_mark = characters.is_mark
+
+function analyzers.setstate(head,font) -- latin
+ local useunicodemarks = analyzers.useunicodemarks
+ local descriptions = descriptiondata[font]
+ local first = false
+ local last = false
+ local current = head
+ local done = false
+ -- only letters
+ while current do
+ local char, id = ischar(current,font)
+ if char then
+ if not getstate(current) then
+ -- local d = descriptions[char]
+ -- if d then
+ -- if d.class == "mark" or (useunicodemarks and categories[char] == "mn") then
+ if is_mark[char] then
+ setstate(current,s_mark)
+ elseif is_letter[char] then
+ if first then
+ setstate(current,s_medi)
+ else
+ setstate(current,s_init)
+ first = current
+ done = true
+ end
+ last = current
+ else
+ goto PICKUP
+ end
+ goto NEXT
+ -- end
+ end
+ ::PICKUP::
+ if first then
+ setstate(last,first == last and s_isol or s_fina)
+ end
+ first = false
+ elseif char == false then
+ -- other font
+ if first then
+ setstate(last,first == last and s_isol or s_fina)
+ end
+ first = false
+ if id == math_code then
+ current = end_of_math(current)
+ end
+ elseif id == disc_code then
+ -- always in the middle .. it doesn't make much sense to assign a property
+ -- here ... we might at some point decide to flag the components when present
+ -- but even then it's kind of bogus
+ setstate(current,s_medi)
+ last = current
+ else -- finish
+ if first then
+ setstate(last,first == last and s_isol or s_fina)
+ end
+ first = false
+ if id == math_code then
+ current = end_of_math(current)
+ end
+ end
+ ::NEXT::
+ current = getnext(current)
+ end
+ if first then
+ setstate(last,first == last and s_isol or s_fina)
+ end
+ return head, done
+end
+
+-- in the future we will use language/script attributes instead of the
+-- font related value, but then we also need dynamic features which is
+-- somewhat slower; and .. we need a chain of them
+
+local function analyzeinitializer(tfmdata,value) -- attr
+ local script, language = otf.scriptandlanguage(tfmdata) -- attr
+ local action = initializers[script]
+ if not action then
+ -- skip
+ elseif type(action) == "function" then
+ return action(tfmdata,value)
+ else
+ local action = action[language]
+ if action then
+ return action(tfmdata,value)
+ end
+ end
+end
+
+local function analyzeprocessor(head,font,attr)
+ local tfmdata = fontdata[font]
+ local script, language = otf.scriptandlanguage(tfmdata,attr)
+ local action = methods[script]
+ if not action then
+ -- skip
+ elseif type(action) == "function" then
+ return action(head,font,attr)
+ else
+ action = action[language]
+ if action then
+ return action(head,font,attr)
+ end
+ end
+ return head, false
+end
+
+registerotffeature {
+ name = "analyze",
+ description = "analysis of character classes",
+ default = true,
+ initializers = {
+ node = analyzeinitializer,
+ },
+ processors = {
+ position = 1,
+ node = analyzeprocessor,
+ }
+}
+
+-- latin
+
+methods.latn = analyzers.setstate
+-------.dflt = analyzers.setstate % can be an option or just the default
+
+local arab_warned = { }
+
+local function warning(current,what)
+ local char = getchar(current)
+ if not arab_warned[char] then
+ log.report("analyze","arab: character %C has no %a class",char,what)
+ arab_warned[char] = true
+ end
+end
+
+-- we can also use this trick for devanagari
+
+function methods.arab(head,font,attr)
+ local first, last, c_first, c_last
+ local current = head
+ local done = false
+ current = tonut(current)
+ while current do
+ local char, id = ischar(current,font)
+ if char and not getstate(current) then
+ done = true
+ local classifier = classifiers[char]
+ if not classifier then
+ if last then
+ if c_last == s_medi or c_last == s_fina then
+ setstate(last,s_fina)
+ else
+ warning(last,"fina")
+ setstate(last,s_error)
+ end
+ first = nil
+ last = nil
+ elseif first then
+ if c_first == s_medi or c_first == s_fina then
+ setstate(first,s_isol)
+ else
+ warning(first,"isol")
+ setstate(first,s_error)
+ end
+ first = nil
+ end
+ elseif classifier == s_mark then
+ setstate(current,s_mark)
+ elseif classifier == s_isol then
+ if last then
+ if c_last == s_medi or c_last == s_fina then
+ setstate(last,s_fina)
+ else
+ warning(last,"fina")
+ setstate(last,s_error)
+ end
+ first = nil
+ last = nil
+ elseif first then
+ if c_first == s_medi or c_first == s_fina then
+ setstate(first,s_isol)
+ else
+ warning(first,"isol")
+ setstate(first,s_error)
+ end
+ first = nil
+ end
+ setstate(current,s_isol)
+ elseif classifier == s_medi then
+ if first then
+ last = current
+ c_last = classifier
+ setstate(current,s_medi)
+ else
+ setstate(current,s_init)
+ first = current
+ c_first = classifier
+ end
+ elseif classifier == s_fina then
+ if last then
+ if getstate(last) ~= s_init then
+ setstate(last,s_medi)
+ end
+ setstate(current,s_fina)
+ first, last = nil, nil
+ elseif first then
+ -- if getstate(first) ~= s_init then
+ -- -- needs checking
+ -- setstate(first,s_medi)
+ -- end
+ setstate(current,s_fina)
+ first = nil
+ else
+ setstate(current,s_isol)
+ end
+ else -- classifier == s_rest
+ setstate(current,s_rest)
+ if last then
+ if c_last == s_medi or c_last == s_fina then
+ setstate(last,s_fina)
+ else
+ warning(last,"fina")
+ setstate(last,s_error)
+ end
+ first = nil
+ last = nil
+ elseif first then
+ if c_first == s_medi or c_first == s_fina then
+ setstate(first,s_isol)
+ else
+ warning(first,"isol")
+ setstate(first,s_error)
+ end
+ first = nil
+ end
+ end
+ else
+ if last then
+ if c_last == s_medi or c_last == s_fina then
+ setstate(last,s_fina)
+ else
+ warning(last,"fina")
+ setstate(last,s_error)
+ end
+ first = nil
+ last = nil
+ elseif first then
+ if c_first == s_medi or c_first == s_fina then
+ setstate(first,s_isol)
+ else
+ warning(first,"isol")
+ setstate(first,s_error)
+ end
+ first = nil
+ end
+ if id == math_code then -- a bit duplicate as we test for glyphs twice
+ current = end_of_math(current)
+ end
+ end
+ current = getnext(current)
+ end
+ if last then
+ if c_last == s_medi or c_last == s_fina then
+ setstate(last,s_fina)
+ else
+ warning(last,"fina")
+ setstate(last,s_error)
+ end
+ elseif first then
+ if c_first == s_medi or c_first == s_fina then
+ setstate(first,s_isol)
+ else
+ warning(first,"isol")
+ setstate(first,s_error)
+ end
+ end
+ return head, done
+end
+
+methods.syrc = methods.arab
+methods.mand = methods.arab
+methods.nko = methods.arab
+
+-- a quick first attemp .. more later
+
+do
+
+ -- https://github.com/n8willis/opentype-shaping-documents/blob/master/opentype-shaping-mongolian.md#joining-properties
+ -- todo syrc
+
+ local joining = setmetatableindex(function(t,k)
+ if type(k) == "number" then
+ local c = chardata[k]
+ local v = false
+ if c then
+ local mongolian = c.mongolian
+ --
+ v = mongolian
+ end
+ t[k] = v
+ return v
+ end
+ end)
+
+ function methods.mong(head,font,attr)
+ local first, last
+ local current = head
+ local done = false
+ local prevjoin = nil
+ local prestate = nil
+ current = tonut(current)
+
+ local function wrapup()
+ if last then
+ if last ~= first then
+ local s = getstate(last)
+ if s == s_medi then
+ setstate(last,s_fina)
+ elseif s == s_init then
+ setstate(last,s_isol)
+ end
+ end
+ last = nil
+ first = nil
+ prevjoin = nil
+ prestate = nil
+ end
+ end
+
+ while current do
+ local char, id = ischar(current,font)
+ if char and not getstate(current) then
+ local currjoin = joining[char]
+ done = true
+ if not last then
+ setstate(current,s_isol)
+ prevjoin = currjoin
+ first = current
+ last = current
+ prevstate = s_isol
+ elseif currjoin == "t" then -- transparent
+ -- keep state
+ last = current
+ elseif prevjoin == "d" or prevjoin == "jc" or prevjoin == "l" then
+ if currjoin == "d" or prevjoin == "jc" or prevjoin == "r" then
+ local s = getstate(last)
+ if s == s_isol then
+ setstate(last,s_init)
+ elseif s == s_fina then
+ setstate(last,s_medi)
+ end
+ setstate(current,s_fina)
+ prevstate = s_fina
+ elseif prevjoin == "nj" or prevjoin == "l" then
+ local s = getstate(last)
+ if s == s_medi then
+ setstate(last,s_fina)
+ elseif s == s_init then
+ setstate(last,s_isol)
+ end
+ setstate(current,s_isol)
+ prevstate = s_isol
+ end
+ prevjoin = currjoin
+ last = current
+ elseif prevjoin == "nj" or prevjoin == "r" then
+ if s == s_medi then
+ setstate(last,s_fina)
+ elseif s == s_init then
+ setstate(last,s_isol)
+ end
+ setstate(current,s_isol)
+ prevjoin = currjoin
+ prevstate = s_isol
+ last = current
+ elseif last then
+ wrapup()
+ end
+ else
+ if last then
+ wrapup()
+ end
+ if id == math_code then -- a bit duplicate as we test for glyphs twice
+ current = end_of_math(current)
+ end
+ end
+ current = getnext(current)
+ end
+ if last then
+ wrapup()
+ end
+ return head, done
+ end
+
+end
+
+directives.register("otf.analyze.useunicodemarks",function(v)
+ analyzers.useunicodemarks = v
+end)
diff --git a/tex/context/base/mkxl/lang-ini.mkxl b/tex/context/base/mkxl/lang-ini.mkxl
index e55075d84..e115ce9f8 100644
--- a/tex/context/base/mkxl/lang-ini.mkxl
+++ b/tex/context/base/mkxl/lang-ini.mkxl
@@ -552,9 +552,9 @@
\permanent\protected\def\language
{\doifelsenextoptionalcs\lang_basics_set_current\normallanguage}
- \let\setlanguage\language % we make these synonyms
+ \aliased\let\setlanguage\language % we make these synonyms
- \let\patterns\gobbleoneargument
+ \aliased\let\patterns\gobbleoneargument
\popoverloadmode
diff --git a/tex/context/base/mkxl/luat-ini.mkxl b/tex/context/base/mkxl/luat-ini.mkxl
index 4f6556eda..472e8326e 100644
--- a/tex/context/base/mkxl/luat-ini.mkxl
+++ b/tex/context/base/mkxl/luat-ini.mkxl
@@ -273,23 +273,23 @@
%
% \installctxfunction\foo{commands.foo}
-\protected\def\installctxfunction#1#2% expandable
+\permanent\protected\def\installctxfunction#1#2% expandable
{\edef\m_syst_name{\csstring#1}%
\global\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxfunction(\!!bs#2\!!es,true)}\relax}
-\protected\def\installctxscanner#1#2% expandable
+\permanent\protected\def\installctxscanner#1#2% expandable
{\edef\m_syst_name{\csstring#1}%
\global\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name",\!!bs#2\!!es,true)}\relax}
-\protected\def\installprotectedctxfunction#1#2% protected
+\permanent\protected\def\installprotectedctxfunction#1#2% protected
{\edef\m_syst_name{\csstring#1}%
\global\protected\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxfunction(\!!bs#2\!!es,true)}\relax}
-\protected\def\installprotectedctxscanner#1#2% protected
+\permanent\protected\def\installprotectedctxscanner#1#2% protected
{\edef\m_syst_name{\csstring#1}%
\global\protected\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name",\!!bs#2\!!es,true)}\relax}
-\protected\def\resetctxscanner#1%
+\permanent\protected\def\resetctxscanner#1%
{\edef\m_syst_name{\csstring#1}%
\gletcsname\m_syst_name\endcsname\relax}
diff --git a/tex/context/base/mkxl/math-ali.mkxl b/tex/context/base/mkxl/math-ali.mkxl
index 70566d5b6..d7d7088c1 100644
--- a/tex/context/base/mkxl/math-ali.mkxl
+++ b/tex/context/base/mkxl/math-ali.mkxl
@@ -38,6 +38,7 @@
\newtoks\t_math_align_c
\newskip\d_math_eqalign_distance
+\newskip\d_math_eqalign_rulethickness
\protected\def\math_eqalign_distance
{\relax
@@ -806,7 +807,9 @@
[\c!distance=\emwidth,
\c!left=,
\c!right=,
- \c!align=\v!middle]
+ \c!align=\v!middle,
+ \c!rulecolor=,
+ \c!rulethickness=\linewidth]
\appendtoks
\frozen\instance\setuevalue{\e!start\currentmathmatrix}{\math_matrix_start[\currentmathmatrix]}%
@@ -894,15 +897,55 @@
% \crcr
% \noalign{\vskip-\struthtdp}}
+\def\math_matrix_check_rule_step#1%
+ {\doifelsenumber{#1}
+ {\scratchdimen#1\d_math_eqalign_rulethickness}
+ {\edef\p_rulecolor{#1}}}
+
+\def\math_matrix_check_rule[#1]%
+ {\d_math_eqalign_rulethickness\mathmatrixparameter\c!rulethickness\relax
+ \scratchdimen\d_math_eqalign_rulethickness
+ \edef\p_rulecolor{\mathmatrixparameter\c!rulecolor}%
+ \iftok{#1}\emptytoks\else
+ \rawprocesscommalist[#1]\math_matrix_check_rule_step
+ \fi
+ \ifempty\p_rulecolor\else
+ \dousecolorparameter\p_rulecolor
+ \fi}
+
+\noaligned\permanent\tolerant\protected\def\math_matrix_HL[#1]#*%
+ {\noalign\bgroup
+ \math_matrix_check_rule[#1]%
+ \divide\scratchdimen\plustwo
+ \autorule\s!height\scratchdimen\s!depth\scratchdimen\relax
+ \egroup}
+
+\permanent\tolerant\protected\def\math_matrix_VL[#1]#*%
+ {\NC
+ \math_matrix_check_rule[#1]%
+ \divide\d_math_eqalign_distance\plustwo
+ \hskip-\d_math_eqalign_distance
+ \autorule\s!width\scratchdimen\relax
+ \hskip-\d_math_eqalign_distance
+ \NC}
+
+\newtoks\everymathmatrix
+
+\appendtoks
+ \enforced\let\NR\math_matrix_NR
+ \enforced\let\NC\math_matrix_NC
+ \enforced\let\MC\math_matrix_NC
+ \enforced\let\HL\math_matrix_HL
+ \enforced\let\VL\math_matrix_VL
+ \enforced\let\TB\math_common_TB
+\to \everymathmatrix
+
\def\math_matrix_start_processing
{\dontleavehmode
\bgroup
\tabskip\zeropoint
\math_matrix_pickup
- \enforced\let\NR\math_matrix_NR
- \enforced\let\NC\math_matrix_NC
- \enforced\let\MC\math_matrix_NC
- \enforced\let\TB\math_common_TB
+ \the\everymathmatrix
%
\enforced\let\endmath\relax
%
@@ -940,6 +983,8 @@
\fi
\fi
\d_math_eqalign_distance\mathmatrixparameter\c!distance\relax
+ % \d_math_eqalign_rulethickness\mathmatrixparameter\c!rulethickness\relax
+ % \edef\p_rulecolor{\mathmatrixparameter\c!rulecolor}
\edef\math_matrix_set_style{\mathmatrixparameter\c!style}}
\def\math_matrix_set_defaults
diff --git a/tex/context/base/mkxl/math-def.mkxl b/tex/context/base/mkxl/math-def.mkxl
index 29ad9b465..040005293 100644
--- a/tex/context/base/mkxl/math-def.mkxl
+++ b/tex/context/base/mkxl/math-def.mkxl
@@ -80,7 +80,8 @@
\permanent\protected\def\setoperatorlimits#1#2% operator limits
{\savenormalmeaning{#1}%
- \expandafter\def\expandafter#1\expandafter{\csname normal\csstring#1\endcsname#2}}
+ %frozen\protected\expandafter\def\expandafter#1\expandafter{\csname normal\csstring#1\endcsname#2}}
+ \frozen\protected\edef#1{\expandafter\noexpand\csname normal\csstring#1\endcsname\noexpand#2}}
\pushoverloadmode
diff --git a/tex/context/base/mkxl/math-fen.mkxl b/tex/context/base/mkxl/math-fen.mkxl
index f18d72c85..2e491f28b 100644
--- a/tex/context/base/mkxl/math-fen.mkxl
+++ b/tex/context/base/mkxl/math-fen.mkxl
@@ -390,7 +390,7 @@
\newconditional\c_math_fenced_done
\newconditional\c_math_fenced_unknown \settrue\c_math_fenced_unknown
-\protected\def\installmathfencepair#1#2#3#4%
+\permanent\protected\def\installmathfencepair#1#2#3#4%
{\letcsname\??mathleft \normalmeaning#1\endcsname#2%
\letcsname\??mathright\normalmeaning#3\endcsname#4}
diff --git a/tex/context/base/mkxl/math-ini.mkxl b/tex/context/base/mkxl/math-ini.mkxl
index 7838d8fde..91946bcdb 100644
--- a/tex/context/base/mkxl/math-ini.mkxl
+++ b/tex/context/base/mkxl/math-ini.mkxl
@@ -409,18 +409,18 @@
% todo: only in mmode
% these commands are semi-public but should not be used directly (lua names wil change)
-\protected\def\math_set_attribute #1#2{\ifmmode\clf_setmathattribute{#1}{#2}\fi}
-\protected\def\math_set_alphabet #1{\ifmmode\clf_setmathalphabet{#1}\fi}
-\protected\def\math_set_font_style #1{\ifmmode\clf_setmathstyle{#1}\fi}
-\protected\def\math_set_font_alternate#1{\ifmmode\clf_setmathalternate\defaultmathfamily{#1}\fi}
+\permanent\protected\def\setmathattribute #1#2{\ifmmode\clf_setmathattribute{#1}{#2}\fi}
+\permanent\protected\def\setmathalphabet #1{\ifmmode\clf_setmathalphabet{#1}\fi}
+\permanent\protected\def\setmathfontstyle #1{\ifmmode\clf_setmathstyle{#1}\fi}
+\permanent\protected\def\setmathfontalternate#1{\ifmmode\clf_setmathalternate\defaultmathfamily{#1}\fi}
\installcorenamespace{mathstylealternative} % might become a setuphandler
-\protected\def\math_set_font_style_alternate#1%
+\permanent\protected\def\setmathfontstylealternate#1%
{\ifcsname\??mathstylealternative\fontclass:#1\endcsname
- \expandafter\math_set_font_alternate\lastnamedcs
+ \expandafter\setmathfontalternate\lastnamedcs
\orelse\ifcsname\??mathstylealternative#1\endcsname
- \expandafter\math_set_font_alternate\lastnamedcs
+ \expandafter\setmathfontalternate\lastnamedcs
\fi}
\permanent\tolerant\protected\def\setupmathrendering[#1]#*[#2]% the name might change
@@ -457,10 +457,10 @@
\enforced\let\dotlessj\dotlessj
\popoverloadmode
-\permanent\protected\def\mathaltcalligraphic{\math_set_font_alternate{calligraphic}\cal} % set via goody file
-\permanent\protected\def\mathaltitalic {\math_set_font_alternate{italic}} % set via goody file
-\permanent\protected\def\mathslashedzero {\begingroup\math_set_font_alternate{zero}∅\endgroup} % set via goody file or automatic
-\permanent\protected\def\mathdotless {\math_set_font_alternate{dotless}} % set via goody file or automatic
+\permanent\protected\def\mathaltcalligraphic{\setmathfontalternate{calligraphic}\cal} % set via goody file
+\permanent\protected\def\mathaltitalic {\setmathfontalternate{italic}} % set via goody file
+\permanent\protected\def\mathslashedzero {\begingroup\setmathfontalternate{zero}∅\endgroup} % set via goody file or automatic
+\permanent\protected\def\mathdotless {\setmathfontalternate{dotless}} % set via goody file or automatic
\permanent\protected\def\mathdotlessi {\begingroup\mathdotless i\endgroup}
\permanent\protected\def\mathdotlessj {\begingroup\mathdotless j\endgroup}
@@ -477,35 +477,29 @@
\enforced\let\dotlessj\autodotlessj
\to \everymathematics
-\let\setmathattribute \math_set_attribute
-\let\setmathalphabet \math_set_alphabet
-\let\setmathfontstyle \math_set_font_style
-\let\setmathfontalternate \math_set_font_alternate
-\let\setmathfontalternative \math_set_font_alternate
-\let\setmathfontstylealternate \math_set_font_style_alternate
-\let\setmathfontstylealternative\math_set_font_style_alternate
+\aliased\let\setmathfontalternative \setmathfontalternate
+\aliased\let\setmathfontstylealternative\setmathfontstylealternate
+\aliased\let\mathalternate \setmathfontalternate
-\let\mathalternate \math_set_font_alternate
+\permanent\protected\def\mathupright {\setmathattribute\s!regular\s!tf\setmathfontstylealternate\s!tf}
+\permanent\protected\def\mathitalic {\setmathattribute\s!regular\s!it\setmathfontstylealternate\s!it}
+\permanent\protected\def\mathscript {\setmathalphabet \s!script \setmathfontstylealternate\s!script}
+\permanent\protected\def\mathfraktur {\setmathalphabet \s!fraktur \setmathfontstylealternate\s!fraktur}
+\permanent\protected\def\mathblackboard{\setmathalphabet \s!blackboard \setmathfontstylealternate\s!blackboard}
-\permanent\protected\def\mathupright {\math_set_attribute\s!regular\s!tf\math_set_font_style_alternate\s!tf}
-\permanent\protected\def\mathitalic {\math_set_attribute\s!regular\s!it\math_set_font_style_alternate\s!it}
-\permanent\protected\def\mathscript {\math_set_alphabet \s!script \math_set_font_style_alternate\s!script}
-\permanent\protected\def\mathfraktur {\math_set_alphabet \s!fraktur \math_set_font_style_alternate\s!fraktur}
-\permanent\protected\def\mathblackboard{\math_set_alphabet \s!blackboard \math_set_font_style_alternate\s!blackboard}
+\permanent\protected\def\mathrm {\setmathattribute\s!rm\s!tf \setmathfontstylealternate\s!tf}
+\permanent\protected\def\mathss {\setmathattribute\s!ss\s!tf \setmathfontstylealternate\s!tf}
+\permanent\protected\def\mathtt {\setmathattribute\s!tt\s!tf \setmathfontstylealternate\s!tf}
-\permanent\protected\def\mathrm {\math_set_attribute\s!rm\s!tf \math_set_font_style_alternate\s!tf}
-\permanent\protected\def\mathss {\math_set_attribute\s!ss\s!tf \math_set_font_style_alternate\s!tf}
-\permanent\protected\def\mathtt {\math_set_attribute\s!tt\s!tf \math_set_font_style_alternate\s!tf}
+\permanent\protected\def\mathtf {\setmathfontstyle\s!tf \setmathfontstylealternate\s!tf}
+\permanent\protected\def\mathsl {\setmathfontstyle\s!it \setmathfontstylealternate\s!it} % no sl
+\permanent\protected\def\mathit {\setmathfontstyle\s!it \setmathfontstylealternate\s!it}
-\permanent\protected\def\mathtf {\math_set_font_style\s!tf \math_set_font_style_alternate\s!tf}
-\permanent\protected\def\mathsl {\math_set_font_style\s!it \math_set_font_style_alternate\s!it} % no sl
-\permanent\protected\def\mathit {\math_set_font_style\s!it \math_set_font_style_alternate\s!it}
+\permanent\protected\def\mathbf {\setmathfontstyle\s!bf \setmathfontstylealternate\s!bf}
+\permanent\protected\def\mathbs {\setmathfontstyle\s!bi \setmathfontstylealternate\s!bi} % no sl
+\permanent\protected\def\mathbi {\setmathfontstyle\s!bi \setmathfontstylealternate\s!bi}
-\permanent\protected\def\mathbf {\math_set_font_style\s!bf \math_set_font_style_alternate\s!bf}
-\permanent\protected\def\mathbs {\math_set_font_style\s!bi \math_set_font_style_alternate\s!bi} % no sl
-\permanent\protected\def\mathbi {\math_set_font_style\s!bi \math_set_font_style_alternate\s!bi}
-
-\let\mathdefault\mathitalic
+\aliased\let\mathdefault\mathitalic
\appendtoks
\edef\p_default{\mathematicsparameter\c!default}%
diff --git a/tex/context/base/mkxl/math-pln.mkxl b/tex/context/base/mkxl/math-pln.mkxl
index c5d814fbe..e386eb72d 100644
--- a/tex/context/base/mkxl/math-pln.mkxl
+++ b/tex/context/base/mkxl/math-pln.mkxl
@@ -23,7 +23,7 @@
% might change
-\protected\def\hrulefill{\leaders\hrule\hfill}
+\permanent\protected\def\hrulefill{\leaders\hrule\hfill}
%protected\def\dotfill {\cleaders\hbox{\normalstartimath\mathsurround\zeropoint\mkern1.5mu.\mkern1.5mu\normalstopimath}\hfill}
% will move
diff --git a/tex/context/base/mkxl/meta-ini.mkxl b/tex/context/base/mkxl/meta-ini.mkxl
index c715cbca5..4bf9134f9 100644
--- a/tex/context/base/mkxl/meta-ini.mkxl
+++ b/tex/context/base/mkxl/meta-ini.mkxl
@@ -403,12 +403,15 @@
\aliased\let\stopMPclip\relax
+\mutable\def\width {0 } % left-over
+\mutable\def\height{0 } % left-over
+
\protected\def\meta_grab_clip_path#1#2#3%
{\begingroup
\d_overlay_width #2\relax
\d_overlay_height#3\relax
- \edef\width {\the\d_overlay_width \space}%
- \edef\height{\the\d_overlay_height\space}%
+ \edef\width {\the\d_overlay_width \space}% hm
+ \edef\height{\the\d_overlay_height\space}% hm
\edef\currentMPclip{#1}%
\ifcsname\??mpclip\currentMPclip\endcsname
\meta_grab_clip_path_yes
@@ -992,22 +995,10 @@
% \setupcolors[state=stop,conversion=never] % quite tricky ... type mismatch
-% \startMPextensions
-% color OverlayColor,OverlayLineColor;
-% \stopMPextensions
-
\startMPinitializations
CurrentLayout:="\currentlayout";
\stopMPinitializations
-% \startMPinitializations
-% OverlayWidth:=\overlaywidth;
-% OverlayHeight:=\overlayheight;
-% OverlayDepth:=\overlaydepth;
-% OverlayLineWidth:=\overlaylinewidth;
-% OverlayOffset:=\overlayoffset;
-% \stopMPinitializations
-
%D A dirty trick, ** in colo-ini.lua (mpcolor). We cannot use a vardef, because
%D that fails with spot colors.
@@ -1016,53 +1007,11 @@
def OverlayColor =\ifempty\overlaycolor black \else\MPcolor{\overlaycolor} \fi enddef;
\stopMPinitializations
-% \newcount\c_overlay_colormodel
-% \newcount\c_overlay_color
-% \newcount\c_overlay_transparency
-% \newcount\c_overlay_linecolor
-% \newcount\c_overlay_linetransparency
-
-% \appendtoks
-% \c_overlay_colormodel \c_attr_colormodel
-% \c_overlay_color \colo_helpers_inherited_current_ca\overlaycolor
-% \c_overlay_transparency \colo_helpers_inherited_current_ta\overlaycolor
-% \c_overlay_linecolor \colo_helpers_inherited_current_ca\overlaylinecolor
-% \c_overlay_linetransparency\colo_helpers_inherited_current_ta\overlaylinecolor
-% \to \everyMPgraphic
-
-% \startMPinitializations
-% BaseLineSkip:=\the\baselineskip;
-% LineHeight:=\the\baselineskip;
-% BodyFontSize:=\the\bodyfontsize;
-% %
-% TopSkip:=\the\topskip;
-% StrutHeight:=\strutheight;
-% StrutDepth:=\strutdepth;
-% %
-% CurrentWidth:=\the\hsize;
-% CurrentHeight:=\the\vsize;
-% HSize:=\the\hsize ;
-% VSize:=\the\vsize ;
-% %
-% EmWidth:=\the\emwidth;
-% ExHeight:=\the\exheight;
-% \stopMPinitializations
-
\appendtoks
\disablediscretionaries
%\disablecompoundcharacters
\to \everyMPgraphic
-% \appendtoks % before color, inefficient, replace by low level copy
-% \doregistercolor{currentcolor}\currentcolorname
-% \to \everyMPgraphic
-
-% \color[green]{abc \startMPcode
-% fill fullcircle scaled 3cm withoutcolor;
-% fill fullcircle scaled 2cm withcolor \MPcolor{currentcolor} ;
-% fill fullcircle scaled 1cm withcolor \MPcolor{red} ;
-% \stopMPcode def}
-
\appendtoks
\baselineskip1\baselineskip
\lineheight 1\lineheight
@@ -1099,14 +1048,6 @@
enddef ;
\stopMPextensions
-% \startMPextensions
-% PageFraction := 1 ;
-% \stopMPextensions
-
-% \startMPinitializations
-% PageFraction := if \lastpage>1: (\realfolio-1)/(\lastpage-1) else: 1 fi ;
-% \stopMPinitializations
-
\startMPdefinitions {metapost}
if unknown context_bare : input mp-bare.mpiv ; fi ;
\stopMPdefinitions
diff --git a/tex/context/base/mkxl/mult-aux.mkxl b/tex/context/base/mkxl/mult-aux.mkxl
index 9614f6cea..a8ab97fb1 100644
--- a/tex/context/base/mkxl/mult-aux.mkxl
+++ b/tex/context/base/mkxl/mult-aux.mkxl
@@ -352,11 +352,11 @@
\expandafter\noexpand\csname let#2parameter\endcsname
\expandafter\noexpand\csname reset#2parameter\endcsname}}
-\let\dousecurrentstyleparameter\relax
-\let\dousecurrentcolorparameter\relax
+\mutable\let\dousecurrentstyleparameter\relax
+\mutable\let\dousecurrentcolorparameter\relax
-\let\currentstyleparameter\empty
-\let\currentcolorparameter\empty
+\mutable\let\currentstyleparameter\empty
+\mutable\let\currentcolorparameter\empty
\protected\def\mult_interfaces_install_style_and_color_handler#1#2#3#4%
{\frozen\protected\def#2##1##2% style color
diff --git a/tex/context/base/mkxl/node-ini.lmt b/tex/context/base/mkxl/node-ini.lmt
index 5cce9030d..0fba0a4d9 100644
--- a/tex/context/base/mkxl/node-ini.lmt
+++ b/tex/context/base/mkxl/node-ini.lmt
@@ -162,40 +162,6 @@ nodes.literalvalues = literalvalues
nodes.nodecodes = nodecodes
--- local subtypes = allocate {
--- [nodecodes.glue] = gluecodes,
--- [nodecodes.dir] = dircodes,
--- [nodecodes.boundary] = boundarycodes,
--- [nodecodes.noad] = noadcodes,
--- [nodecodes.whatsit] = whatcodes,
--- [nodecodes.glyph] = glyphcodes,
--- [nodecodes.kern] = kerncodes,
--- [nodecodes.penalty] = penaltycodes,
--- [nodecodes.math] = mathcodes,
--- [nodecodes.disc] = disccodes,
--- [nodecodes.accent] = accentcodes,
--- [nodecodes.radical] = radicalcodes,
--- [nodecodes.fence] = fencecodes,
--- [nodecodes.par] = parcodes,
--- [nodecodes.rule] = rulecodes,
-
--- [nodecodes.vlist] = listcodes,
--- [nodecodes.hlist] = listcodes,
-
--- -- [nodecodes.list] = listcodes,
-
--- -- [nodecodes.parameter] = parametercodes,
--- -- [nodecodes.user] = usercodes,
--- }
-
--- for k in next, table.sortedkeys(subtypes) do
--- local v = nodecodes[k]
--- print(k,v)
--- if k and subtypes[k] then
--- subtypes[v] = subtypes[k]
--- end
--- end
-
local subtypes = allocate {
glue = gluecodes,
dir = dircodes,
@@ -276,5 +242,3 @@ end
for i=0,#gluecodes do
texsetintegervalue(gluecodes[i] .. "subtypecode",i,"immutable")
end
-
--- tex.set("internalcodesmode",1) -- obsolete
diff --git a/tex/context/base/mkxl/node-ref.lmt b/tex/context/base/mkxl/node-ref.lmt
new file mode 100644
index 000000000..583f979b2
--- /dev/null
+++ b/tex/context/base/mkxl/node-ref.lmt
@@ -0,0 +1,811 @@
+if not modules then modules = { } end modules ['node-ref'] = {
+ version = 1.001,
+ optimize = true,
+ comment = "companion to node-ref.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- We supported pdf right from the start and in mkii this has resulted in
+-- extensive control over the links. Nowadays pdftex provides a lot more
+-- control over margins but as mkii supports multiple backends we stuck to
+-- our own mechanisms. In mkiv again we implement our own handling. Eventually
+-- we will even disable the pdf primitives.
+
+-- helper, will end up in luatex
+
+-- is grouplevel still used?
+
+local tonumber = tonumber
+local concat = table.concat
+
+local attributes, nodes, node = attributes, nodes, node
+
+local allocate = utilities.storage.allocate, utilities.storage.mark
+local mark = utilities.storage.allocate, utilities.storage.mark
+
+local nodeinjections = backends.nodeinjections
+local codeinjections = backends.codeinjections
+
+local cleanupreferences = false
+local cleanupdestinations = true
+
+local transparencies = attributes.transparencies
+local colors = attributes.colors
+local references = structures.references
+local enableaction = nodes.tasks.enableaction
+
+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_areas = false trackers.register("nodes.areas", function(v) trace_areas = v end)
+local show_references = false trackers.register("nodes.references.show", function(v) show_references = tonumber(v) or (v and 2.25 or false) end)
+local show_destinations = false trackers.register("nodes.destinations.show", function(v) show_destinations = tonumber(v) or (v and 2.00 or false) end)
+
+local report_reference = logs.reporter("backend","references")
+local report_destination = logs.reporter("backend","destinations")
+local report_area = logs.reporter("backend","areas")
+
+local texsetcount = tex.setcount
+----- texsetattribute = tex.setattribute
+
+local nuts = nodes.nuts
+local nodepool = nuts.pool
+
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setlink = nuts.setlink
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local getwidth = nuts.getwidth
+local setwidth = nuts.setwidth
+local getheight = nuts.getheight
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local getsubtype = nuts.getsubtype
+local getwhd = nuts.getwhd
+local getdirection = nuts.getdirection
+local setshift = nuts.setshift
+local getboxglue = nuts.getboxglue
+
+local hpack_list = nuts.hpack
+local vpack_list = nuts.vpack
+local getdimensions = nuts.dimensions
+local getrangedimensions = nuts.rangedimensions
+local traverse = nuts.traverse
+local find_node_tail = nuts.tail
+local start_of_par = nuts.start_of_par
+
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+local listcodes = nodes.listcodes
+
+local dirvalues = nodes.dirvalues
+local lefttoright_code = dirvalues.lefttoright
+local righttoleft_code = dirvalues.righttoleft
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local glyph_code = nodecodes.glyph
+local rule_code = nodecodes.rule
+local dir_code = nodecodes.dir
+local par_code = nodecodes.par
+
+local leftskip_code = gluecodes.leftskip
+local rightskip_code = gluecodes.rightskip
+local parfillleftskip_code = gluecodes.parfillleftskip
+local parfillskip_code = gluecodes.parfillskip
+
+----- linelist_code = listcodes.line
+
+local new_rule = nodepool.rule
+local new_kern = nodepool.kern
+local new_hlist = nodepool.hlist
+
+local flush_node = nuts.flush
+
+local tosequence = nodes.tosequence
+
+local implement = interfaces.implement
+
+-- Normally a (destination) area is a box or a simple stretch if nodes but when it is
+-- a paragraph we have a problem: we cannot calculate the height well. This happens
+-- with footnotes or content broken across a page.
+
+-- skip is somewhat messy
+-- when we have a line line we can look at the next line and make a shape
+-- see dimensions: this is tricky with split off boxes like inserts
+-- where we can end up with a first and last spanning lines so maybe
+-- we need to do vlists differently
+-- no need for dir here if we inject in the right spot as then we can
+-- pick up the dir elsewhere (in lmtx)
+
+local inject_areas do
+
+ local function hlist_dimensions(start,stop,parent)
+ local last = stop and getnext(stop)
+ if parent then
+ return getrangedimensions(parent,start,last)
+ else
+ return getdimensions(start,last)
+ end
+ end
+
+ local function vlist_dimensions(start,stop) -- also needs the stretch and so
+ local temp
+ if stop then
+ temp = getnext(stop)
+ setnext(stop,nil)
+ end
+ local v = vpack_list(start) -- use helper but happens seldom anyway so ...
+ local w, h, d = getwhd(v)
+ setlist(v) -- not needed
+ flush_node(v)
+ if temp then
+ setnext(stop,temp)
+ end
+ return w, h, d
+ end
+
+ -- not ok when vlist at mvl level
+
+ local function dimensions(parent,start,stop) -- in principle we could move some to the caller
+ if start == stop then
+ local id = getid(start)
+ if id == hlist_code or id == vlist_code or id == rule_code or id == glyph_code then
+ local sw, sh, sd = getwhd(start)
+ local pw, ph, pd = getwhd(parent)
+ local ht = sh == 0 and ph or sh -- changed
+ local dp = sd == 0 and pd or sd -- changed
+ if trace_areas then
+ report_area("dimensions taken of %a (%p,%p,%p) with parent (%p,%p,%p) -> (%p,%p,%p)",
+ nodecodes[id],sw,sh,sd,pw,ph,pd,sw,ht,dp)
+ end
+ return sw, ht, dp
+ else
+ if trace_areas then
+ report_area("dimensions calculated of %a",nodecodes[id])
+ end
+ return hlist_dimensions(start,stop) -- one node only so simple
+ end
+ elseif parent then
+ -- todo: if no prev and no next and parent
+ -- todo: we need a a list_dimensions for a vlist
+ if getid(parent) == vlist_code then
+ --
+ -- we can as well calculate here because we only have kerns and glue
+ --
+ local last = stop and getnext(stop)
+ local first = nil
+ local last = nil
+ local current = start
+ local noflines = 0
+ while current do -- can be loop
+ local id = getid(current)
+ if id == hlist_code or id == vlist_code or id == rule_code then
+ if noflines == 0 then
+ first = current
+ noflines = 1
+ else
+ noflines = noflines + 1
+ end
+ last = current
+ end
+ if current == stop then
+ break
+ else
+ current = getnext(current)
+ end
+ end
+ if noflines > 1 then
+ if trace_areas then
+ report_area("dimensions taken of vlist")
+ end
+ local w, h, d = vlist_dimensions(first,last,parent)
+ local ht = getheight(first)
+ return w, ht, d + h - ht, first
+ elseif first then
+ if trace_areas then
+ report_area("dimensions taken of first line in vlist")
+ end
+ local w, h, d = getwhd(first)
+ return w, h, d, first
+ else
+ if trace_areas then
+ report_area("dimensions taken of vlist (probably wrong)")
+ end
+ return hlist_dimensions(start,stop,parent)
+ end
+ else
+ if trace_areas then
+ report_area("dimensions taken of range starting with %a using parent",nodecodes[id])
+ end
+ return hlist_dimensions(start,stop,parent)
+ end
+ else
+ if trace_areas then
+ report_area("dimensions taken of range starting with %a",nodecodes[id])
+ end
+ return hlist_dimensions(start,stop)
+ end
+ end
+
+ -- Setting these once and not passign them each nested call is faster and this injector is
+ -- actually one of the more costly calls in a run (when we have lots of references to
+ -- check) and it's also a bti less code.
+
+ local attribute, make, stack, done
+
+ local function inject_range(head,first,last,reference,parent,pardir,txtdir)
+ local width, height, depth, line = dimensions(parent,first,last)
+ if txtdir == righttoleft_code then
+ width = - width
+ elseif txtdir == lefttoright_code then
+ -- go on
+ elseif pardir == righttoleft_code then
+ width = - width
+ end
+ local result, resolved = make(width,height,depth,reference)
+ if result and resolved then
+ if line then
+ -- special case, we only treat the first line in a vlist
+ local l = getlist(line)
+ if trace_areas then
+ report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","line",
+ reference,pardir or "?",txtdir or "?",
+ tosequence(l,nil,true),width,height,depth)
+ end
+ setlist(line,result)
+ setlink(result,l)
+ return head, last
+ elseif head == first then
+ if trace_areas then
+ report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","head",
+ reference,pardir or "?",txtdir or "?",
+ tosequence(first,last,true),width,height,depth)
+ end
+ setlink(result,first)
+ return result, last
+ else
+ if trace_areas then
+ report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","middle",
+ reference,pardir or "?",txtdir or "?",
+ tosequence(first,last,true),width,height,depth)
+ end
+ if first == last and getid(parent) == vlist_code and getid(first) == hlist_code then
+ if trace_areas then
+ -- think of a button without \dontleavehmode in the mvl
+ report_area("compensating for link in vlist")
+ end
+ setlink(result,getlist(first))
+ setlist(first,result)
+ else
+ setlink(getprev(first),result,first)
+ end
+ return head, last
+ end
+ else
+ return head, last
+ end
+ end
+
+ -- Somehow this one no longer got used. See node-ref.lua for the implementation.
+ --
+ -- local function inject_list(id,current,reference,pardir,txtdir)
+ -- end
+
+ local function inject(head,skip,parent,pardir,txtdir)
+ local first, last, firstdir, reference
+ local current = head
+ while current do
+ local id = getid(current)
+ if id == hlist_code or id == vlist_code then
+ local r = getattr(current,attribute)
+ -- test \goto{test}[page(2)] test \gotobox{test}[page(2)]
+ -- test \goto{\TeX}[page(2)] test \gotobox{\hbox {x} \hbox {x}}[page(2)]
+ if r then
+ if not reference then
+ reference, first, last, firstdir = r, current, current, txtdir
+ elseif r == reference then
+ -- same link
+ last = current
+ elseif (done[reference] or 0) == 0 then
+ if not skip or r > skip then -- maybe no > test
+ head, current = inject_range(head,first,last,reference,parent,pardir,firstdir)
+ reference, first, last, firstdir = nil, nil, nil, nil
+ end
+ else
+ reference, first, last, firstdir = r, current, current, txtdir
+ end
+ done[r] = (done[r] or 0) + 1
+ end
+ local list = getlist(current)
+ if list then
+ local h
+ h, pardir, txtdir = inject(list,r or skip or 0,current,pardir,txtdir)
+ if h ~= current then
+ setlist(current,h)
+ end
+ end
+ if r then
+ done[r] = done[r] - 1
+ end
+ goto NEXT
+ elseif id == dir_code then
+ local direction, pop = getdirection(current)
+ txtdir = not pop and direction -- we might need a stack
+ goto NEXT
+ elseif id == par_code then
+ if start_of_par(current) then
+ pardir = getdirection(current)
+ end
+ goto NEXT
+ elseif id == glue_code then
+ local subtype = getsubtype(current)
+ if subtype == leftskip_code or subtype == parfillleftskip_code then
+ goto NEXT
+ elseif subtype == rightskip_code or subtype == parfillskip_code then
+ if reference and (done[reference] or 0) == 0 then
+ head, current = inject_range(head,first,last,reference,parent,pardir,firstdir)
+ reference, first, last, firstdir = nil, nil, nil, nil
+ end
+ goto NEXT
+ end
+ end
+ do
+ local r = getattr(current,attribute)
+ if not r then
+ -- just go on, can be kerns
+ elseif not reference then
+ reference, first, last, firstdir = r, current, current, txtdir
+ elseif r == reference then
+ last = current
+ elseif (done[reference] or 0) == 0 then -- or (id == glue_code and getsubtype(current) == right_skip_code) then
+ if not skip or r > skip then -- maybe no > test
+ head, current = inject_range(head,first,last,reference,parent,pardir,firstdir)
+ reference, first, last, firstdir = nil, nil, nil, nil
+ end
+ else
+ reference, first, last, firstdir = r, current, current, txtdir
+ end
+ end
+ ::NEXT::
+ current = getnext(current)
+ end
+ if reference and (done[reference] or 0) == 0 then
+ head = inject_range(head,first,last,reference,parent,pardir,firstdir)
+ end
+ return head, pardir, txtdir
+ end
+
+ inject_areas = function(head,a,m,s,d)
+ attribute = a
+ make = m
+ stack = s
+ done = d
+ return (inject(head))
+ end
+
+end
+
+-- tracing: todo: use predefined colors
+
+local colorize, justadd do
+
+ local a_color = attributes.private('color')
+ local a_colormodel = attributes.private('colormodel')
+ local a_transparency = attributes.private('transparency')
+ local u_transparency = nil
+ local u_colors = { }
+ local force_gray = true
+
+ local register_color = colors.register
+
+ local function addstring(what,str,shift) --todo make a pluggable helper (in font-ctx)
+ if str then
+ local typesetters = nuts.typesetters
+ if typesetters then
+ local hashes = fonts.hashes
+ local infofont = fonts.infofont()
+ local emwidth = hashes.emwidths [infofont]
+ local exheight = hashes.exheights[infofont]
+ if what == "reference" then
+ str = str .. " "
+ shift = - (shift or 2.25) * exheight
+ else
+ str = str .. " "
+ shift = (shift or 2) * exheight
+ end
+ local text = typesetters.tohpack(str,infofont)
+ local rule = new_rule(emwidth/5,4*exheight,3*exheight)
+ setshift(text,shift)
+ return hpack_list(setlink(text,rule))
+ end
+ end
+ end
+
+ colorize = function(width,height,depth,n,reference,what,sr,offset)
+ if force_gray then
+ n = 0
+ end
+ u_transparency = u_transparency or transparencies.register(nil,2,.65)
+ local ucolor = u_colors[n]
+ if not ucolor then
+ if n == 1 then
+ u_color = register_color(nil,'rgb',.75,0,0)
+ elseif n == 2 then
+ u_color = register_color(nil,'rgb',0,.75,0)
+ elseif n == 3 then
+ u_color = register_color(nil,'rgb',0,0,.75)
+ else
+ n = 0
+ u_color = register_color(nil,'gray',.5)
+ end
+ u_colors[n] = u_color
+ end
+ if width == 0 then
+ -- probably a strut as placeholder
+ report_area("%s %s has no %s dimensions, width %p, height %p, depth %p",what,reference,"horizontal",width,height,depth)
+ width = 65536
+ end
+ if height + depth <= 0 then
+ report_area("%s %s has no %s dimensions, width %p, height %p, depth %p",what,reference,"vertical",width,height,depth)
+ height = 65536/2
+ depth = height
+ end
+ local rule = new_rule(width,height,depth) -- todo: use tracer rule
+ setattr(rule,a_colormodel,1) -- gray color model
+ setattr(rule,a_color,u_color)
+ setattr(rule,a_transparency,u_transparency)
+ if width < 0 then
+ local kern = new_kern(width)
+ setwidth(rule,-width)
+ setnext(kern,rule)
+ setprev(rule,kern)
+ return kern
+ elseif sr and sr ~= "" then
+ local text = addstring(what,sr,shift)
+ if text then
+ local kern = new_kern(-getwidth(text))
+ setlink(kern,text,rule)
+ return kern
+ end
+ end
+ return rule
+ end
+
+ justadd = function(what,sr,shift,current) -- needs testing
+ if sr and sr ~= "" then
+ local text = addstring(what,sr,shift)
+ if text then
+ local kern = new_kern(-getwidth(text))
+ setlink(kern,text,current)
+ return new_hlist(kern)
+ end
+ end
+ end
+
+end
+
+local nofreferences = 0
+
+do
+
+ local stack = { }
+ local done = { }
+ local attribute = attributes.private('reference')
+ local topofstack = 0
+
+ nodes.references = {
+ attribute = attribute,
+ stack = stack,
+ done = done,
+ }
+
+ -- todo: get rid of n (n is just a number, can be used for tracing, obsolete)
+
+ local function setreference(h,d,r) -- h and d can be nil
+ topofstack = topofstack + 1
+ -- 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 or false, d or false, codeinjections.prerollreference(r) }
+ -- texsetattribute(attribute,topofstack) -- todo -> at tex end
+ texsetcount("lastreferenceattribute",topofstack)
+ end
+
+ function references.get(n) -- not public so functionality can change
+ local sn = stack[n]
+ return sn and sn[1]
+ end
+
+ local function makereference(width,height,depth,reference) -- height and depth are of parent
+ local sr = stack[reference]
+ if sr then
+ if trace_references then
+ report_reference("resolving attribute %a",reference)
+ end
+ local resolved = sr[1]
+ local ht = sr[2]
+ local dp = sr[3]
+ local set = sr[4]
+ local n = sr[5]
+ -- logs.report("temp","child: ht=%p dp=%p, parent: ht=%p dp=%p",ht,dp,height,depth)
+ if ht then
+ if height < ht then height = ht end
+ if depth < dp then depth = dp end
+ end
+ -- logs.report("temp","used: ht=%p dp=%p",height,depth)
+ local annot = nodeinjections.reference(width,height,depth,set,resolved.mesh)
+ if annot then
+ annot = tonut(annot) -- todo
+ nofreferences = nofreferences + 1
+ local result, current, texts
+ if show_references then
+ local d = resolved
+ if d then
+ local r = d.reference
+ local p = d.prefix
+ if r then
+ if p then
+ texts = p .. "|" .. r
+ else
+ texts = r
+ end
+ else
+ -- t[#t+1] = d.internal or "?"
+ end
+ end
+ end
+ if trace_references then
+ local step = 65536
+ result = new_hlist(colorize(width,height-step,depth-step,2,reference,"reference",texts,show_references)) -- step subtracted so that we can see seperate links
+ current = result
+ elseif texts then
+ texts = justadd("reference",texts,show_references,current)
+ if texts then
+ current = texts
+ end
+ end
+ if current then
+ setlink(current,annot)
+ else
+ result = annot
+ end
+ references.registerpage(n)
+ result = new_hlist(result)
+ if cleanupreferences then stack[reference] = nil end
+ return result, resolved
+ elseif trace_references then
+ report_reference("unable to resolve annotation %a",reference)
+ end
+ elseif trace_references then
+ report_reference("unable to resolve attribute %a",reference)
+ end
+ end
+
+ function nodes.references.handler(head)
+ if head and topofstack > 0 then
+ return inject_areas(head,attribute,makereference,stack,done)
+ else
+ return head
+ end
+ end
+
+ function references.inject(prefix,reference,specification) -- todo: use currentreference is possible
+ local set, bug = references.identify(prefix,reference)
+ if bug or #set == 0 then
+ -- unknown ref, just don't set it and issue an error
+ else
+ set.highlight = specification.highlight
+ set.newwindow = specification.newwindow
+ set.layer = specification.layer
+ setreference(specification.height,specification.depth,set) -- sets attribute / todo: for set[*].error
+ end
+ end
+
+ -- function references.injectinternal(internal,specification)
+ -- references.inject("","internal("..internal..")",specification)
+ -- if bug or #set == 0 then
+ -- -- unknown ref, just don't set it and issue an error
+ -- else
+ -- -- nil prefix when ""
+ -- -- check
+ -- set.highlight = specification.highlight
+ -- set.newwindow = specification.newwindow
+ -- set.layer = specification.layer
+ -- setreference(specification.height,specification.depth,set) -- sets attribute / todo: for set[*].error
+ -- end
+ -- end
+
+ function references.injectcurrentset(h,d) -- used inside doifelse
+ local currentset = references.currentset
+ if currentset then
+ setreference(h,d,currentset) -- sets attribute / todo: for set[*].error
+ end
+ end
+
+end
+
+local nofdestinations = 0
+
+do
+
+ local stack = { }
+ local done = { }
+ local attribute = attributes.private('destination')
+ local topofstack = 0
+
+ nodes.destinations = {
+ attribute = attribute,
+ stack = stack,
+ done = done,
+ }
+
+ local function setdestination(n,h,d,name,view) -- n = grouplevel, name == table
+ topofstack = topofstack + 1
+ stack[topofstack] = { n, h, d, name, view }
+ return topofstack
+ end
+
+ local function makedestination(width,height,depth,reference)
+ local sr = stack[reference]
+ if sr then
+ if trace_destinations then
+ report_destination("resolving attribute %a",reference)
+ end
+ local resolved = sr[1]
+ local ht = sr[2]
+ local dp = sr[3]
+ local name = sr[4]
+ local view = sr[5]
+ if ht then
+ if height < ht then height = ht end
+ if depth < dp then depth = dp end
+ end
+ local result, current, texts
+ if show_destinations then
+ if name and #name > 0 then
+ local t = { }
+ for i=1,#name do
+ local s = name[i]
+ if type(s) == "number" then
+ local d = references.internals[s]
+ if d then
+ d = d.references
+ local r = d.reference
+ local p = d.usedprefix
+ if r then
+ if p then
+ t[#t+1] = p .. "|" .. r
+ else
+ t[#t+1] = r
+ end
+ else
+ -- t[#t+1] = d.internal or "?"
+ end
+ end
+ else
+ -- in fact we have a prefix:name here
+ end
+ end
+ if #t > 0 then
+ texts = concat(t," & ")
+ end
+ end
+ end
+ if trace_destinations then
+ local step = 0
+ if width == 0 then
+ step = 4*65536
+ width, height, depth = 5*step, 5*step, 0
+ end
+ local rule = new_hlist(colorize(width,height,depth,3,reference,"destination",texts,show_destinations))
+ if not result then
+ result, current = rule, rule
+ else
+ setlink(current,rule)
+ current = rule
+ end
+ width, height = width - step, height - step
+ elseif texts then
+ texts = justadd("destination",texts,show_destinations,current)
+ if texts then
+ current = texts
+ end
+ end
+ nofdestinations = nofdestinations + 1
+ local annot = nodeinjections.destination(width,height,depth,name,view)
+ if annot then
+ annot = tonut(annot) -- obsolete soon
+ if result then
+ setlink(current,annot)
+ else
+ result = annot
+ end
+ current = find_node_tail(annot)
+ end
+ if result then
+ result = new_hlist(result)
+ end
+ if cleanupdestinations then stack[reference] = nil end
+ return result, resolved
+ elseif trace_destinations then
+ report_destination("unable to resolve attribute %a",reference)
+ end
+ end
+
+ function nodes.destinations.handler(head)
+ if head and topofstack > 0 then
+ return inject_areas(head,attribute,makedestination,stack,done)
+ else
+ return head
+ end
+ end
+
+ -- will move
+
+ function references.mark(reference,h,d,view)
+ return setdestination(tex.currentgrouplevel,h,d,reference,view)
+ end
+
+end
+
+implement {
+ name = "injectreference",
+ actions = references.inject,
+ arguments = {
+ "string",
+ "string",
+ {
+ { "highlight", "boolean" },
+ { "newwindow", "boolean" },
+ { "layer" },
+ { "height", "dimen" },
+ { "depth", "dimen" },
+ { "view" },
+ }
+ }
+}
+
+-- implement {
+-- name = "injectinternalreference",
+-- actions = references.injectinternal,
+-- arguments = {
+-- "integer",
+-- {
+-- { "highlight", "boolean" },
+-- { "newwindow", "boolean" },
+-- { "layer" },
+-- { "height", "dimen" },
+-- { "depth", "dimen" },
+-- { "view" },
+-- }
+-- }
+-- }
+
+implement {
+ name = "injectcurrentreference",
+ actions = references.injectcurrentset,
+}
+
+implement {
+ name = "injectcurrentreferencehtdp",
+ actions = references.injectcurrentset,
+ arguments = { "dimen", "dimen" },
+}
+
+statistics.register("interactive elements", function()
+ if nofreferences > 0 or nofdestinations > 0 then
+ return string.format("%s references, %s destinations",nofreferences,nofdestinations)
+ else
+ return nil
+ end
+end)
diff --git a/tex/context/base/mkxl/node-rul.mkxl b/tex/context/base/mkxl/node-rul.mkxl
index 569f0d284..97417c1d8 100644
--- a/tex/context/base/mkxl/node-rul.mkxl
+++ b/tex/context/base/mkxl/node-rul.mkxl
@@ -383,7 +383,7 @@
\fi
\normalexpanded{\t_node_shifts_checklist{\the\t_node_shifts_checklist\node_shifts_redefine{\currentshift}}}% order ?
\node_shifts_define
- \setuevalue\currentshift{\node_shifts_direct{\currentshift}}%
+ \frozen\instance\setuevalue\currentshift{\node_shifts_direct{\currentshift}}%
\to \everydefineshift
\protected\def\node_shifts_define
diff --git a/tex/context/base/mkxl/pack-rul.mkxl b/tex/context/base/mkxl/pack-rul.mkxl
index 23de8d5cb..8ca6c69d5 100644
--- a/tex/context/base/mkxl/pack-rul.mkxl
+++ b/tex/context/base/mkxl/pack-rul.mkxl
@@ -453,7 +453,7 @@
\to \everyoverlay
\permanent\tolerant\protected\def\defineoverlay[#1]#*[#2]% wil be overloaded
- {\def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}%
+ {\def\pack_framed_define_overlay_indeed##1{\defcsname\??overlay##1\endcsname{\executedefinedoverlay{##1}{#2}}}%
\processcommalist[#1]\pack_framed_define_overlay_indeed}
\permanent\protected\def\executedefinedoverlay#1#2% we can share the definitions
@@ -1595,9 +1595,9 @@
\dp\scratchbox\dp\b_framed_normal
\setbox\b_framed_normal\box\scratchbox}
-\def\installframedlocator#1#2#3%
- {\setvalue{\??framedlocatorbefore#1}{#2}%
- \setvalue{\??framedlocatorafter #1}{#3}}
+\permanent\protected\def\installframedlocator#1#2#3%
+ {\defcsname\??framedlocatorbefore#1\endcsname{#2}%
+ \defcsname\??framedlocatorafter #1\endcsname{#3}}
\def\pack_framed_locator_before#1{\begincsname\??framedlocatorbefore#1\endcsname}
\def\pack_framed_locator_after #1{\begincsname\??framedlocatorafter #1\endcsname}
diff --git a/tex/context/base/mkxl/page-brk.mkxl b/tex/context/base/mkxl/page-brk.mkxl
index dace10eed..3e3a1c1d4 100644
--- a/tex/context/base/mkxl/page-brk.mkxl
+++ b/tex/context/base/mkxl/page-brk.mkxl
@@ -308,7 +308,7 @@
\def\page_breaks_columns_handle_direct#1%
{\begincsname\??columnbreakmethod\currentoutputroutine:#1\endcsname}
-\protected\def\installcolumnbreakmethod#1#2#3% #1=otr-id #2=tag #3=action
+\permanent\protected\def\installcolumnbreakmethod#1#2#3% #1=otr-id #2=tag #3=action
{\setvalue{\??columnbreakmethod#1:#2}{#3}}
\aliased\let\installcolumnbreakhandler\installcolumnbreakmethod % will go
diff --git a/tex/context/base/mkxl/page-mbk.mklx b/tex/context/base/mkxl/page-mbk.mklx
index fcab1abf5..05b09c79e 100644
--- a/tex/context/base/mkxl/page-mbk.mklx
+++ b/tex/context/base/mkxl/page-mbk.mklx
@@ -171,7 +171,7 @@
\page_margin_blocks_set_l_box
\page_margin_blocks_set_r_box}
-\protected\def\page_margin_blocks_place_r_yes
+\permanent\protected\def\page_margin_blocks_place_r_yes
{\setbox\b_page_margin_blocks_prepared\hbox to \rightmarginwidth
{\marginblockparameter\c!left
\box\b_page_margin_blocks_prepared
@@ -179,7 +179,7 @@
\vsmashbox\b_page_margin_blocks_prepared
\box\b_page_margin_blocks_prepared}
-\protected\def\page_margin_blocks_place_l_yes
+\permanent\protected\def\page_margin_blocks_place_l_yes
{\setbox\b_page_margin_blocks_prepared\hbox to \leftmarginwidth
{\marginblockparameter\c!right
\box\b_page_margin_blocks_prepared
@@ -187,14 +187,14 @@
\vsmashbox\b_page_margin_blocks_prepared
\box\b_page_margin_blocks_prepared}
-\protected\def\page_margin_blocks_place_r_nop{\hskip\rightmarginwidth}
-\protected\def\page_margin_blocks_place_l_nop{\hskip\leftmarginwidth}
+\permanent\protected\def\page_margin_blocks_place_r_nop{\hskip\rightmarginwidth}
+\permanent\protected\def\page_margin_blocks_place_l_nop{\hskip\leftmarginwidth}
-\let\placerightmarginblock\page_margin_blocks_place_r_nop
-\let\placeleftmarginblock \page_margin_blocks_place_l_nop
+\aliased\let\placerightmarginblock\page_margin_blocks_place_r_nop
+\aliased\let\placeleftmarginblock \page_margin_blocks_place_l_nop
-\def\page_margin_blocks_set_r_box{\let\placerightmarginblock\page_margin_blocks_place_r_yes}
-\def\page_margin_blocks_set_l_box{\let\placeleftmarginblock \page_margin_blocks_place_l_yes}
+\def\page_margin_blocks_set_r_box{\enforced\aliased\let\placerightmarginblock\page_margin_blocks_place_r_yes}
+\def\page_margin_blocks_set_l_box{\enforced\aliased\let\placeleftmarginblock \page_margin_blocks_place_l_yes}
% margin floats (keyword 'margin' in option list)
diff --git a/tex/context/base/mkxl/page-mix.mkxl b/tex/context/base/mkxl/page-mix.mkxl
index c94a1f252..7fb4512e5 100644
--- a/tex/context/base/mkxl/page-mix.mkxl
+++ b/tex/context/base/mkxl/page-mix.mkxl
@@ -341,7 +341,7 @@
\installcorenamespace{mixedcolumnsseparator}
-\protected\def\installmixedcolumnseparator#1#2%
+\permanent\protected\def\installmixedcolumnseparator#1#2%
{\setvalue{\??mixedcolumnsseparator#1}{#2}}
\installmixedcolumnseparator\v!rule
diff --git a/tex/context/base/mkxl/scrn-but.mklx b/tex/context/base/mkxl/scrn-but.mklx
index 60073a6b7..3df4be248 100644
--- a/tex/context/base/mkxl/scrn-but.mklx
+++ b/tex/context/base/mkxl/scrn-but.mklx
@@ -327,6 +327,9 @@
\aliased\let\setupinteractionmenus\setupinteractionmenu
+\mutable\let\currentinteractionmenudistance\empty
+\mutable\let\currentinteractionmenustate \empty
+
\let\scrn_menu_action\relax
\let\scrn_menu_define_original\defineinteractionmenu
diff --git a/tex/context/base/mkxl/scrn-fld.mklx b/tex/context/base/mkxl/scrn-fld.mklx
index fb249c01f..674be425a 100644
--- a/tex/context/base/mkxl/scrn-fld.mklx
+++ b/tex/context/base/mkxl/scrn-fld.mklx
@@ -110,6 +110,14 @@
\setupforms
[\c!method=XML] % no need for everyjob initialization as this is the default
+\mutable\let\currentfieldbackgroundcolor \empty
+\mutable\let\currentfieldbackgroundcolorvalue\empty
+\mutable\let\currentfieldbodycategory \empty
+\mutable\let\currentfieldframecolor \empty
+\mutable\let\currentfieldframecolorvalue \empty
+\mutable\let\currentfieldlabel \empty
+\mutable\let\currentfieldstackname \empty
+
\appendtoks
\iflocation
\clf_exportformdata{\formsparameter\c!export}%
diff --git a/tex/context/base/mkxl/scrn-pag.mklx b/tex/context/base/mkxl/scrn-pag.mklx
index a500b6695..80e16f63d 100644
--- a/tex/context/base/mkxl/scrn-pag.mklx
+++ b/tex/context/base/mkxl/scrn-pag.mklx
@@ -35,6 +35,10 @@
\newdimen\canvasbleedoffset
\newdimen\canvasartoffset
+\mutable\let\currentinteractionscreendelay \empty
+\mutable\let\currentinteractionscreenheight\empty
+\mutable\let\currentinteractionscreenwidth \empty
+
\newconditional\c_scrn_canvas_tight_page
\def\scrn_canvas_calculate
diff --git a/tex/context/base/mkxl/scrn-ref.mklx b/tex/context/base/mkxl/scrn-ref.mklx
index 806f2f48a..63f76a092 100644
--- a/tex/context/base/mkxl/scrn-ref.mklx
+++ b/tex/context/base/mkxl/scrn-ref.mklx
@@ -51,6 +51,11 @@
\enabledirectives[destinations.offset=\the\dimexpr\interactionparameter\c!focusoffset\relax]%
\to \everysetupinteraction
+\mutable\let\currentinteractioncloseaction \empty
+\mutable\let\currentinteractionclosepageaction\empty
+\mutable\let\currentinteractionopenaction \empty
+\mutable\let\currentinteractionopenpageaction \empty
+
%D We have to make sure of some settings:
\def\scrn_reference_set_text_actions
diff --git a/tex/context/base/mkxl/scrn-wid.mklx b/tex/context/base/mkxl/scrn-wid.mklx
index 384a60a60..225bdc161 100644
--- a/tex/context/base/mkxl/scrn-wid.mklx
+++ b/tex/context/base/mkxl/scrn-wid.mklx
@@ -94,6 +94,12 @@
\c!depth=\v!fit,
\c!location=\v!high]
+\mutable\let\currentattachmentdepth \empty
+\mutable\let\currentattachmentheight \empty
+\mutable\let\currentattachmentregistered\empty
+\mutable\let\currentattachmentsymbol \empty
+\mutable\let\currentattachmentwidth \empty
+
\permanent\tolerant\protected\def\registerattachment[#tag]#spacer[#settings]% we save (globally) at the lua end
{\ifarguments\else
\begingroup
@@ -397,6 +403,11 @@
\c!buffer=\v!comment,
\c!location=\v!high]
+\mutable\let\currentcommentdepth \empty
+\mutable\let\currentcommentheight\empty
+\mutable\let\currentcommentsymbol\empty
+\mutable\let\currentcommentwidth \empty
+
\appendtoks
\frozen\instance\setuevalue \currentcomment {\scrn_comment_argument[\currentcomment]}%
\frozen\instance\setuevalue{\e!start\currentcomment}{\scrn_comment_start [\currentcomment]}%
diff --git a/tex/context/base/mkxl/spac-ali.lmt b/tex/context/base/mkxl/spac-ali.lmt
new file mode 100644
index 000000000..5c434fcdf
--- /dev/null
+++ b/tex/context/base/mkxl/spac-ali.lmt
@@ -0,0 +1,134 @@
+if not modules then modules = { } end modules ['spac-ali'] = {
+ version = 1.001,
+ optimize = true,
+ comment = "companion to spac-ali.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local div = math.div
+local format = string.format
+
+local tasks = nodes.tasks
+local enableaction = tasks.enableaction
+
+local nuts = nodes.nuts
+
+local setlist = nuts.setlist
+local setlink = nuts.setlink
+local getdirection = nuts.getdirection
+local takeattr = nuts.takeattr
+local getwidth = nuts.getwidth
+local findtail = nuts.tail
+
+local righttoleft_code = nodes.dirvalues.righttoleft
+local linelist_code = nodes.listcodes.line
+
+local hpack_nodes = nuts.hpack
+local nextlist = nuts.traversers.list
+
+local new_stretch = nuts.pool.stretch
+
+local a_realign = attributes.private("realign")
+
+local texsetattribute = tex.setattribute
+local texgetcount = tex.getcount
+
+local isleftpage = layouts.status.isleftpage
+
+typesetters = typesetters or { }
+local alignments = { }
+typesetters.alignments = alignments
+
+local report_realign = logs.reporter("typesetters","margindata")
+local trace_realign = trackers.register("typesetters.margindata", function(v) trace_margindata = v end)
+
+local nofrealigned = 0
+
+-- leftskip rightskip parfillskip
+-- raggedleft 0 + 0 -
+-- raggedright 0 0 fil
+-- raggedcenter 0 + 0 + -
+
+local function handler(head,leftpage,realpageno) -- traverse_list
+ for current, id, subtype, list in nextlist, head do
+ if subtype == linelist_code then
+ local a = takeattr(current,a_realign)
+ if a and a > 0 then
+ local pageno = div(a,10)
+ if pageno ~= realpageno then
+ local align = a % 10
+ local action = 0
+ if align == 1 then -- flushright
+ action = leftpage and 1 or 2
+ elseif align == 2 then -- flushleft
+ action = leftpage and 2 or 1
+ end
+ -- WS: watch this
+ local direction = getdirection(current)
+ -- or should this happen at the tex end:
+ if direction == righttoleft_code then
+ if action == 1 then
+ action = 2
+ elseif action == 2 then
+ action = 1
+ end
+ end
+ -- Currently we just prepend and append which kind of spoils the normalization unless
+ -- we extend our specs and also introduce left/right anchored stuff.
+ if action == 1 then
+ local head = list
+ setlink(findtail(list),new_stretch(3)) -- append
+ setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
+ if trace_realign then
+ report_realign("flushing left, align %a, page %a, realpage %a",align,pageno,realpageno)
+ end
+ elseif action == 2 then
+ local head = setlink(new_stretch(3),list) -- prepend
+ setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
+ if trace_realign then
+ report_realign("flushing right, align %a, page %a, realpage %a",align,pageno,realpageno)
+ end
+ elseif trace_realign then
+ report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno)
+ end
+ nofrealigned = nofrealigned + 1
+ end
+ end
+ end
+ handler(list,leftpage,realpageno)
+ end
+ return head
+end
+
+function alignments.handler(head)
+ return handler(head,isleftpage(),texgetcount("realpageno"))
+end
+
+local enabled = false
+
+function alignments.set(n)
+ if not enabled then
+ enableaction("shipouts","typesetters.alignments.handler")
+ enabled = true
+ if trace_realign then
+ report_realign("enabled")
+ end
+ end
+ texsetattribute(a_realign,texgetcount("realpageno") * 10 + n)
+end
+
+interfaces.implement {
+ name = "setrealign",
+ actions = alignments.set,
+ arguments = "integer",
+}
+
+statistics.register("realigning", function()
+ if nofrealigned > 0 then
+ return format("%s processed",nofrealigned)
+ else
+ return nil
+ end
+end)
diff --git a/tex/context/base/mkxl/spac-ali.mkxl b/tex/context/base/mkxl/spac-ali.mkxl
index b19c9c8db..d72371659 100644
--- a/tex/context/base/mkxl/spac-ali.mkxl
+++ b/tex/context/base/mkxl/spac-ali.mkxl
@@ -19,7 +19,7 @@
%D variants. Starting at the last day of 2011 both methods are merged into one and
%D caching has been added, which makes switching twice as fast.
-\registerctxluafile{spac-ali}{optimize}
+\registerctxluafile{spac-ali}{autosuffix,optimize}
\definesystemattribute[realign] [public] % might be combined with the next one
\definesystemattribute[alignstate][public] % will make a single attributes for several states
@@ -29,7 +29,6 @@
\c_attr_alignstate\attributeunsetvalue
\to \everyforgetall
-\permanent\protected\def\resetrealignsignal{\c_attr_realign\attributeunsetvalue}
\permanent\protected\def\signalinnerrealign{\clf_setrealign\plustwo}
\permanent\protected\def\signalouterrealign{\clf_setrealign\plusone}
@@ -147,8 +146,8 @@
\installcorenamespace{bidi}
-\letvalue{\??bidi\v!left }\checkedlefttoright \letvalue{\??bidi l2r}\checkedlefttoright
-\letvalue{\??bidi\v!right}\checkedrighttoleft \letvalue{\??bidi r2l}\checkedrighttoleft
+\letcsname\??bidi\v!left \endcsname\checkedlefttoright \letcsname\??bidi l2r\endcsname\checkedlefttoright
+\letcsname\??bidi\v!right\endcsname\checkedrighttoleft \letcsname\??bidi r2l\endcsname\checkedrighttoleft
\permanent\protected\def\usebidiparameter#1%
{\begincsname\??bidi#1\c!bidi\endcsname}
@@ -197,7 +196,7 @@
\def\spac_align_set_raggedness_middle{\ifzeropt\hsize\plussix\bodyfontsize\else.5\hsize\fi}
-\protected\def\setraggedness#1% tricky .. we keep the global tolerance otherwise ... to be reconsidered
+\permanent\protected\def\setraggedness#1% tricky .. we keep the global tolerance otherwise ... to be reconsidered
{\ifnum\tolerance<\c_spac_tolerance_minimum
\tolerance\c_spac_tolerance_minimum % small values have unwanted side effects
\else
@@ -557,8 +556,7 @@
\rawprocesscommacommand[\m_spac_align_asked]\spac_align_collect
\fi
\normalexpanded{\t_spac_align_collected
- {% \resetrealignsignal % can go as it is always set
- \setfalse\raggedonelinerstate % bad
+ {\setfalse\raggedonelinerstate % bad
\the\t_spac_align_collected
\spac_align_flush_horizontal
\spac_align_flush_vertical
@@ -636,112 +634,91 @@
% Maybe we need something different in columns.
-\protected\def\installalign#1#2% beware: commands must be unexpandable!
+\permanent\protected\def\installalign#1#2% beware: commands must be unexpandable!
{\ifcsname\??aligncommand#1\endcsname \else
- \setvalue{\??aligncommand#1}{\toksapp\t_spac_align_collected{#2}}%
+ \defcsname\??aligncommand#1\endcsname{\toksapp\t_spac_align_collected{#2}}%
\fi}
-% beware, toks stuff and states are set at a differt time, so installalign is
-% only for special options
-%
-% \setvalue{\??aligncommand whatever}%
-% {\c_spac_align_state_horizontal\plushundred
-% \toksapp\t_spac_align_collected{.....}}
-%
-% this one could deal with both
-%
-% \protected\def\installalignoption#1#2%
-% {\ifcsname\??aligncommand#1\endcsname \else
-% \setvalue{\??aligncommand#1}%
-% {\spac_align_set_horizontal_none
-% \c_spac_align_state_horizontal\plushundred % don't set
-% \toksapp\t_spac_align_collected{#2}}%
-% \fi}
-%
-% \installalignoption
-% {whatever}
-% {}
-
% The keywords:
-\letvalue{\??aligncommand\empty }\empty
-\setvalue{\??aligncommand\v!broad }{\c_spac_align_state_broad \plusone }
-\setvalue{\??aligncommand\v!wide }{\c_spac_align_state_broad \plustwo }
-
-\setvalue{\??aligncommand\v!bottom }{\c_spac_align_state_page \plusone }
-\setvalue{\??aligncommand\v!height }{\c_spac_align_state_page \plustwo }
-\setvalue{\??aligncommand\v!line }{\c_spac_align_state_page \plusthree
- % this will become another keyword (undocumented anyway)
- \toksapp\t_spac_align_collected{\settrue\raggedonelinerstate}}
-
-\setvalue{\??aligncommand\v!high }{\c_spac_align_state_vertical \plusthree}
-\setvalue{\??aligncommand\v!low }{\c_spac_align_state_vertical \plustwo }
-\setvalue{\??aligncommand\v!lohi }{\c_spac_align_state_vertical \plusone }
-
-\setvalue{\??aligncommand\v!flushright }{\c_spac_align_state_horizontal\plusthree}
-\setvalue{\??aligncommand\v!flushleft }{\c_spac_align_state_horizontal\plustwo }
-\setvalue{\??aligncommand\v!middle }{\c_spac_align_state_horizontal\plusone }
-\setvalue{\??aligncommand\v!no }{\c_spac_align_state_horizontal\plustwo }
-\setvalue{\??aligncommand\v!yes }{\c_spac_align_state_horizontal\zerocount}
-\setvalue{\??aligncommand\v!width }{\c_spac_align_state_horizontal\zerocount}
-\setvalue{\??aligncommand\v!normal }{\c_spac_align_state_horizontal\zerocount}
-\setvalue{\??aligncommand\v!reset }{\c_spac_align_state_page \zerocount
- \c_spac_align_state_horizontal\zerocount}
-\setvalue{\??aligncommand\v!inner }{\c_spac_align_state_horizontal\plusfour }
-\setvalue{\??aligncommand\v!outer }{\c_spac_align_state_horizontal\plusfive }
-\setvalue{\??aligncommand\v!flushinner }{\c_spac_align_state_horizontal\plusfour }
-\setvalue{\??aligncommand\v!flushouter }{\c_spac_align_state_horizontal\plusfive }
-\setvalue{\??aligncommand\v!right }{\c_spac_align_state_horizontal\plustwo }
-\setvalue{\??aligncommand\v!left }{\c_spac_align_state_horizontal\plusthree}
-\setvalue{\??aligncommand\v!center }{\c_spac_align_state_horizontal\plusone
- \c_spac_align_state_broad \plustwo }
-\setvalue{\??aligncommand\v!disable }{\c_spac_align_state_horizontal\plussix }
-\setvalue{\??aligncommand\v!last }{\c_spac_align_state_horizontal\plusseven}
-\setvalue{\??aligncommand\v!end }{\c_spac_align_state_horizontal\pluseight}
-\setvalue{\??aligncommand\v!paragraph }{\c_spac_align_state_horizontal\plusnine}
-
-\setvalue{\??aligncommand\v!lefttoright }{\c_spac_align_state_direction \plusone }
-\setvalue{\??aligncommand\v!righttoleft }{\c_spac_align_state_direction \plustwo }
-\setvalue{\??aligncommand l2r}{\c_spac_align_state_direction \plusone }
-\setvalue{\??aligncommand r2l}{\c_spac_align_state_direction \plustwo }
-
-\setvalue{\??aligncommand\v!table }{\c_spac_align_state_vertical \plusthree
- \c_spac_align_state_broad \plusone
- \c_spac_align_state_horizontal\plustwo }
-
-\setvalue{\??aligncommand\v!lesshyphenation}{\toksapp\t_spac_align_collected{\lesshyphens}}
-\setvalue{\??aligncommand\v!morehyphenation}{\toksapp\t_spac_align_collected{\morehyphens}}
-
-\setvalue{\??aligncommand\v!hanging }{\toksapp\t_spac_align_collected{\font_protruding_enable }}
-\setvalue{\??aligncommand\v!hangingboth }{\toksapp\t_spac_align_collected{\font_protruding_enable_b}}
-\setvalue{\??aligncommand\v!nothanging }{\toksapp\t_spac_align_collected{\font_protruding_disable}}
-\setvalue{\??aligncommand\v!hz }{\toksapp\t_spac_align_collected{\font_expansion_enable }}
-\setvalue{\??aligncommand\v!fullhz }{\toksapp\t_spac_align_collected{\font_expansion_enable_k}}
-\setvalue{\??aligncommand\v!nohz }{\toksapp\t_spac_align_collected{\font_expansion_disable }}
-%setvalue{\??aligncommand\v!spacing }{\toksapp\t_spac_align_collected{\normalspacing\zerocount}} % not yet
-%setvalue{\??aligncommand\v!nospacing }{\toksapp\t_spac_align_collected{\normalspacing\plusone}} % not yet
-\setvalue{\??aligncommand\v!hyphenated }{\toksapp\t_spac_align_collected{\dohyphens}}
-\setvalue{\??aligncommand\v!nothyphenated }{\toksapp\t_spac_align_collected{\nohyphens}}
-
-\setvalue{\??aligncommand\v!tolerant }{\toksapp\t_spac_align_collected{\spac_align_set_tolerant}}
-\setvalue{\??aligncommand\v!verytolerant }{\toksapp\t_spac_align_collected{\spac_align_set_very_tolerant}}
-\setvalue{\??aligncommand\v!stretch }{\toksapp\t_spac_align_collected{\spac_align_set_stretch}}
-\setvalue{\??aligncommand\v!extremestretch }{\toksapp\t_spac_align_collected{\spac_align_set_extreme_stretch}}
-
-\setvalue{\??aligncommand \v!final}{\c_spac_align_state_par_fill\plusone}
-\setvalue{\??aligncommand1*\v!final}{\c_spac_align_state_par_fill\plusone}
-\setvalue{\??aligncommand2*\v!final}{\c_spac_align_state_par_fill\plustwo} % hardcoded multiplier
-\setvalue{\??aligncommand3*\v!final}{\c_spac_align_state_par_fill\plusthree}
-\setvalue{\??aligncommand4*\v!final}{\c_spac_align_state_par_fill\plusfour}
+\letcsname\??aligncommand\empty \endcsname\empty
+\defcsname\??aligncommand\v!broad \endcsname{\c_spac_align_state_broad \plusone }
+\defcsname\??aligncommand\v!wide \endcsname{\c_spac_align_state_broad \plustwo }
+
+\defcsname\??aligncommand\v!bottom \endcsname{\c_spac_align_state_page \plusone }
+\defcsname\??aligncommand\v!height \endcsname{\c_spac_align_state_page \plustwo }
+\defcsname\??aligncommand\v!line \endcsname{\c_spac_align_state_page \plusthree
+ % this will become another keyword (undocumented anyway)
+ \toksapp\t_spac_align_collected{\settrue\raggedonelinerstate}}
+
+\defcsname\??aligncommand\v!high \endcsname{\c_spac_align_state_vertical \plusthree}
+\defcsname\??aligncommand\v!low \endcsname{\c_spac_align_state_vertical \plustwo }
+\defcsname\??aligncommand\v!lohi \endcsname{\c_spac_align_state_vertical \plusone }
+
+\defcsname\??aligncommand\v!flushright \endcsname{\c_spac_align_state_horizontal\plusthree}
+\defcsname\??aligncommand\v!flushleft \endcsname{\c_spac_align_state_horizontal\plustwo }
+\defcsname\??aligncommand\v!middle \endcsname{\c_spac_align_state_horizontal\plusone }
+\defcsname\??aligncommand\v!no \endcsname{\c_spac_align_state_horizontal\plustwo }
+\defcsname\??aligncommand\v!yes \endcsname{\c_spac_align_state_horizontal\zerocount}
+\defcsname\??aligncommand\v!width \endcsname{\c_spac_align_state_horizontal\zerocount}
+\defcsname\??aligncommand\v!normal \endcsname{\c_spac_align_state_horizontal\zerocount}
+\defcsname\??aligncommand\v!reset \endcsname{\c_spac_align_state_page \zerocount
+ \c_spac_align_state_horizontal\zerocount}
+\defcsname\??aligncommand\v!inner \endcsname{\c_spac_align_state_horizontal\plusfour }
+\defcsname\??aligncommand\v!outer \endcsname{\c_spac_align_state_horizontal\plusfive }
+\defcsname\??aligncommand\v!flushinner \endcsname{\c_spac_align_state_horizontal\plusfour }
+\defcsname\??aligncommand\v!flushouter \endcsname{\c_spac_align_state_horizontal\plusfive }
+\defcsname\??aligncommand\v!right \endcsname{\c_spac_align_state_horizontal\plustwo }
+\defcsname\??aligncommand\v!left \endcsname{\c_spac_align_state_horizontal\plusthree}
+\defcsname\??aligncommand\v!center \endcsname{\c_spac_align_state_horizontal\plusone
+ \c_spac_align_state_broad \plustwo }
+\defcsname\??aligncommand\v!disable \endcsname{\c_spac_align_state_horizontal\plussix }
+\defcsname\??aligncommand\v!last \endcsname{\c_spac_align_state_horizontal\plusseven}
+\defcsname\??aligncommand\v!end \endcsname{\c_spac_align_state_horizontal\pluseight}
+\defcsname\??aligncommand\v!paragraph \endcsname{\c_spac_align_state_horizontal\plusnine}
+
+\defcsname\??aligncommand\v!lefttoright \endcsname{\c_spac_align_state_direction \plusone }
+\defcsname\??aligncommand\v!righttoleft \endcsname{\c_spac_align_state_direction \plustwo }
+\defcsname\??aligncommand l2r\endcsname{\c_spac_align_state_direction \plusone }
+\defcsname\??aligncommand r2l\endcsname{\c_spac_align_state_direction \plustwo }
+
+\defcsname\??aligncommand\v!table \endcsname{\c_spac_align_state_vertical \plusthree
+ \c_spac_align_state_broad \plusone
+ \c_spac_align_state_horizontal\plustwo }
+
+\defcsname\??aligncommand\v!lesshyphenation\endcsname{\toksapp\t_spac_align_collected{\lesshyphens}}
+\defcsname\??aligncommand\v!morehyphenation\endcsname{\toksapp\t_spac_align_collected{\morehyphens}}
+
+\defcsname\??aligncommand\v!hanging \endcsname{\toksapp\t_spac_align_collected{\font_protruding_enable }}
+\defcsname\??aligncommand\v!hangingboth \endcsname{\toksapp\t_spac_align_collected{\font_protruding_enable_b}}
+\defcsname\??aligncommand\v!nothanging \endcsname{\toksapp\t_spac_align_collected{\font_protruding_disable}}
+\defcsname\??aligncommand\v!hz \endcsname{\toksapp\t_spac_align_collected{\font_expansion_enable }}
+\defcsname\??aligncommand\v!fullhz \endcsname{\toksapp\t_spac_align_collected{\font_expansion_enable_k}}
+\defcsname\??aligncommand\v!nohz \endcsname{\toksapp\t_spac_align_collected{\font_expansion_disable }}
+%defcsname\??aligncommand\v!spacing \endcsname{\toksapp\t_spac_align_collected{\normalspacing\zerocount}} % not yet
+%defcsname\??aligncommand\v!nospacing \endcsname{\toksapp\t_spac_align_collected{\normalspacing\plusone}} % not yet
+\defcsname\??aligncommand\v!hyphenated \endcsname{\toksapp\t_spac_align_collected{\dohyphens}}
+\defcsname\??aligncommand\v!nothyphenated \endcsname{\toksapp\t_spac_align_collected{\nohyphens}}
+
+\defcsname\??aligncommand\v!tolerant \endcsname{\toksapp\t_spac_align_collected{\spac_align_set_tolerant}}
+\defcsname\??aligncommand\v!verytolerant \endcsname{\toksapp\t_spac_align_collected{\spac_align_set_very_tolerant}}
+\defcsname\??aligncommand\v!stretch \endcsname{\toksapp\t_spac_align_collected{\spac_align_set_stretch}}
+\defcsname\??aligncommand\v!extremestretch \endcsname{\toksapp\t_spac_align_collected{\spac_align_set_extreme_stretch}}
+
+\defcsname\??aligncommand \v!final\endcsname{\c_spac_align_state_par_fill\plusone}
+\defcsname\??aligncommand1*\v!final\endcsname{\c_spac_align_state_par_fill\plusone}
+\defcsname\??aligncommand2*\v!final\endcsname{\c_spac_align_state_par_fill\plustwo} % hardcoded multiplier
+\defcsname\??aligncommand3*\v!final\endcsname{\c_spac_align_state_par_fill\plusthree}
+\defcsname\??aligncommand4*\v!final\endcsname{\c_spac_align_state_par_fill\plusfour}
% a one shot (only usefull in e.g. framed, also needs tolerance and stretch)
-\setvalue{\??aligncommand \v!more}{\toksapp\t_spac_align_collected{\looseness\plusone}}
-\setvalue{\??aligncommand1*\v!more}{\toksapp\t_spac_align_collected{\looseness\plusone}}
-\setvalue{\??aligncommand2*\v!more}{\toksapp\t_spac_align_collected{\looseness\plustwo}}
+\defcsname\??aligncommand \v!more\endcsname{\toksapp\t_spac_align_collected{\looseness\plusone}}
+\defcsname\??aligncommand1*\v!more\endcsname{\toksapp\t_spac_align_collected{\looseness\plusone}}
+\defcsname\??aligncommand2*\v!more\endcsname{\toksapp\t_spac_align_collected{\looseness\plustwo}}
-% \setvalue{\??aligncommand ... }{\toksapp\t_spac_align_collected{\nopenalties}}
-% \setvalue{\??aligncommand ... }{\toksapp\t_spac_align_collected{\setdefaultpenalties}}
+%defcsname\??aligncommand ...\endcsname{\toksapp\t_spac_align_collected{\nopenalties}}
+%defcsname\??aligncommand ...\endcsname{\toksapp\t_spac_align_collected{\setdefaultpenalties}}
\definehspace [\v!final] [\emspaceamount]
@@ -762,8 +739,8 @@
\newtoks \t_spac_every_swap_align
\appendtoks
- \setvalue{\??aligncommand\v!right}{\c_spac_align_state_horizontal\plusthree}%
- \setvalue{\??aligncommand\v!left }{\c_spac_align_state_horizontal\plustwo }%
+ \defcsname\??aligncommand\v!right\endcsname{\c_spac_align_state_horizontal\plusthree}%
+ \defcsname\??aligncommand\v!left \endcsname{\c_spac_align_state_horizontal\plustwo }%
\to \t_spac_every_swap_align
\permanent\protected\def\enablereversealignment
@@ -809,11 +786,11 @@
\let\raggedbox\relax
-\def\dosetraggedvbox#1% can be more keys .. how about caching here (but seldom used)
+\permanent\protected\def\dosetraggedvbox#1% can be more keys .. how about caching here (but seldom used)
{\enforced\let\raggedbox\vbox
\processcommacommand[#1]\spac_align_set_ragged_vbox}
-\def\dosetraggedhbox#1% can be more keys .. how about caching here (but seldom used)
+\permanent\protected\def\dosetraggedhbox#1% can be more keys .. how about caching here (but seldom used)
{\enforced\let\raggedbox\hbox
\processcommacommand[#1]\spac_align_set_ragged_hbox}
@@ -848,24 +825,24 @@
\permanent\protected\def\spac_align_horizontal_flushright{\doalignedline\v!left}
\permanent\protected\def\spac_align_horizontal_center {\doalignedline\v!middle}
-\setvalue{\??alignvertical \v!left }{\enforced\let\raggedbox\spac_align_vertical_left}
-\setvalue{\??alignvertical \v!right }{\enforced\let\raggedbox\spac_align_vertical_right}
-\setvalue{\??alignvertical \v!middle }{\enforced\let\raggedbox\spac_align_vertical_middle}
-\setvalue{\??alignvertical \v!inner }{\enforced\let\raggedbox\spac_align_vertical_inner}
-\setvalue{\??alignvertical \v!outer }{\enforced\let\raggedbox\spac_align_vertical_outer}
-\setvalue{\??alignvertical \v!flushleft }{\enforced\let\raggedbox\spac_align_vertical_flushleft }
-\setvalue{\??alignvertical \v!flushright}{\enforced\let\raggedbox\spac_align_vertical_flushright}
-\setvalue{\??alignvertical \v!center }{\enforced\let\raggedbox\spac_align_vertical_center}
-\setvalue{\??alignvertical \v!no }{\enforced\let\raggedbox\spac_align_vertical_no}
-
-\setvalue{\??alignhorizontal\v!left }{\enforced\let\raggedbox\spac_align_horizontal_left}
-\setvalue{\??alignhorizontal\v!right }{\enforced\let\raggedbox\spac_align_horizontal_right}
-\setvalue{\??alignhorizontal\v!middle }{\enforced\let\raggedbox\spac_align_horizontal_middle}
-\setvalue{\??alignhorizontal\v!inner }{\enforced\let\raggedbox\spac_align_horizontal_inner}
-\setvalue{\??alignhorizontal\v!outer }{\enforced\let\raggedbox\spac_align_horizontal_outer}
-\setvalue{\??alignhorizontal\v!flushleft }{\enforced\let\raggedbox\spac_align_horizontal_flushleft}
-\setvalue{\??alignhorizontal\v!flushright}{\enforced\let\raggedbox\spac_align_horizontal_flushright}
-\setvalue{\??alignhorizontal\v!center }{\enforced\let\raggedbox\spac_align_horizontal_center}
+\defcsname\??alignvertical \v!left \endcsname{\enforced\let\raggedbox\spac_align_vertical_left}
+\defcsname\??alignvertical \v!right \endcsname{\enforced\let\raggedbox\spac_align_vertical_right}
+\defcsname\??alignvertical \v!middle \endcsname{\enforced\let\raggedbox\spac_align_vertical_middle}
+\defcsname\??alignvertical \v!inner \endcsname{\enforced\let\raggedbox\spac_align_vertical_inner}
+\defcsname\??alignvertical \v!outer \endcsname{\enforced\let\raggedbox\spac_align_vertical_outer}
+\defcsname\??alignvertical \v!flushleft \endcsname{\enforced\let\raggedbox\spac_align_vertical_flushleft }
+\defcsname\??alignvertical \v!flushright\endcsname{\enforced\let\raggedbox\spac_align_vertical_flushright}
+\defcsname\??alignvertical \v!center \endcsname{\enforced\let\raggedbox\spac_align_vertical_center}
+\defcsname\??alignvertical \v!no \endcsname{\enforced\let\raggedbox\spac_align_vertical_no}
+
+\defcsname\??alignhorizontal\v!left \endcsname{\enforced\let\raggedbox\spac_align_horizontal_left}
+\defcsname\??alignhorizontal\v!right \endcsname{\enforced\let\raggedbox\spac_align_horizontal_right}
+\defcsname\??alignhorizontal\v!middle \endcsname{\enforced\let\raggedbox\spac_align_horizontal_middle}
+\defcsname\??alignhorizontal\v!inner \endcsname{\enforced\let\raggedbox\spac_align_horizontal_inner}
+\defcsname\??alignhorizontal\v!outer \endcsname{\enforced\let\raggedbox\spac_align_horizontal_outer}
+\defcsname\??alignhorizontal\v!flushleft \endcsname{\enforced\let\raggedbox\spac_align_horizontal_flushleft}
+\defcsname\??alignhorizontal\v!flushright\endcsname{\enforced\let\raggedbox\spac_align_horizontal_flushright}
+\defcsname\??alignhorizontal\v!center \endcsname{\enforced\let\raggedbox\spac_align_horizontal_center}
% The next one can be in use so we keep it around but oen should
% be aware of possible interference.
@@ -874,7 +851,7 @@
{\protected\def\updateraggedskips{\dosetraggedskips{#1}{#2}{#3}{#4}{#5}{#6}{#7}}%
\updateraggedskips}
-\permanent\def\dosetraggedskips#1#2#3#4#5#6#7%
+\permanent\protected\def\dosetraggedskips#1#2#3#4#5#6#7%
{\raggedstatus #1\relax
\leftskip 1\leftskip \s!plus#2\relax
\rightskip 1\rightskip\s!plus#3\relax
@@ -951,7 +928,7 @@
{\everyleftofalignedline {\hskip\dimexpr#1+#4\relax}%
\everyrightofalignedline{\hskip\dimexpr#2+#3\relax}}}
-\permanent\def\doalignline#1#2% \\ == newline
+\permanent\protected\def\doalignline#1#2% \\ == newline
{\noindentation % was \noindent
\dontleavehmode % added in marrakesch at TUG 2006\begingroup
\begingroup
@@ -968,21 +945,21 @@
% plain commands
-\ifdefined\line \else \permanent\def\line {\hbox to\hsize} \fi
-\ifdefined\leftline \else \permanent\def\leftline #1{\line{#1\hss}} \fi
-\ifdefined\rightline \else \permanent\def\rightline #1{\line{\hss#1}} \fi
-\ifdefined\centerline \else \permanent\def\centerline#1{\line{\hss#1\hss}} \fi
+\ifdefined\line \else \permanent\protected\def\line {\hbox to\hsize} \fi
+\ifdefined\leftline \else \permanent\protected\def\leftline #1{\line{#1\hss}} \fi
+\ifdefined\rightline \else \permanent\protected\def\rightline #1{\line{\hss#1}} \fi
+\ifdefined\centerline \else \permanent\protected\def\centerline#1{\line{\hss#1\hss}} \fi
% direct commands
\installcorenamespace{alignwrapper}
-\setuvalue{\??alignwrapper\v!left }{\doalignline\relax \hss }
-\setuvalue{\??alignwrapper\v!middle}{\doalignline\hss \hss }
-\setuvalue{\??alignwrapper\v!right }{\doalignline\hss \relax}
-\setuvalue{\??alignwrapper\v!max }{\doalignline\relax \relax}
+\protected\defcsname\??alignwrapper\v!left \endcsname{\doalignline\relax \hss }
+\protected\defcsname\??alignwrapper\v!middle\endcsname{\doalignline\hss \hss }
+\protected\defcsname\??alignwrapper\v!right \endcsname{\doalignline\hss \relax}
+\protected\defcsname\??alignwrapper\v!max \endcsname{\doalignline\relax \relax}
-\def\spac_align_wrapper_middle {\doalignline\hss \hss}
+\def\spac_align_wrapper_middle{\doalignline\hss\hss}
\def\spac_align_wrapper_handle#1%
{\ifcsname\??alignwrapper#1\endcsname\expandafter\lastnamedcs\else\expandafter\spac_align_wrapper_middle\fi}
@@ -1014,15 +991,13 @@
\installcorenamespace{alignline}
-\letvalue{\??alignline\v!left }\leftaligned
-\letvalue{\??alignline\v!right }\rightaligned
-\letvalue{\??alignline\v!middle }\midaligned
-\letvalue{\??alignline\v!flushleft }\rightaligned % beware, makes no sense in locations / we will have a special locations handler
-\letvalue{\??alignline\v!flushright}\leftaligned % beware, makes no sense in locations / we will have a special locations handler
-\letvalue{\??alignline\v!center }\midaligned
-\letvalue{\??alignline\v!max }\maxaligned
-
-% \permanent\protected\def\doalignedline#1{\resetrealignsignal\csname\??alignline#1\endcsname}
+\letcsname\??alignline\v!left \endcsname\leftaligned
+\letcsname\??alignline\v!right \endcsname\rightaligned
+\letcsname\??alignline\v!middle \endcsname\midaligned
+\letcsname\??alignline\v!flushleft \endcsname\rightaligned % beware, makes no sense in locations / we will have a special locations handler
+\letcsname\??alignline\v!flushright\endcsname\leftaligned % beware, makes no sense in locations / we will have a special locations handler
+\letcsname\??alignline\v!center \endcsname\midaligned
+\letcsname\??alignline\v!max \endcsname\maxaligned
%D Experimental (will be redone when floats are redone as it's real messy
%D now). It can also be made faster (if needed).
@@ -1048,21 +1023,21 @@
\permanent\protected\def\doxcheckline % used for floats so multipass anyway
{\signalrightpage\doifelserightpage\donetrue\donefalse}
-\setvalue{\??alignline\v!inner }{\doxalignline\doxcheckline++\zeropoint \relax\hss }
-\setvalue{\??alignline\v!outer }{\doxalignline\doxcheckline++\zeropoint \hss \relax}
-\setvalue{\??alignline\v!innermargin}{\doxalignline\doxcheckline-+\innermargintotal\relax\hss }
-\setvalue{\??alignline\v!outermargin}{\doxalignline\doxcheckline+-\outermargintotal\hss \relax}
-\setvalue{\??alignline\v!inneredge }{\doxalignline\doxcheckline-+\inneredgetotal \relax\hss }
-\setvalue{\??alignline\v!outeredge }{\doxalignline\doxcheckline+-\outeredgetotal \hss \relax}
-\setvalue{\??alignline\v!backspace }{\doxalignline\doxcheckline-+\backspace \relax\hss }
-\setvalue{\??alignline\v!cutspace }{\doxalignline\doxcheckline+-\cutspace \hss \relax}
+\defcsname\??alignline\v!inner \endcsname{\doxalignline\doxcheckline++\zeropoint \relax\hss }
+\defcsname\??alignline\v!outer \endcsname{\doxalignline\doxcheckline++\zeropoint \hss \relax}
+\defcsname\??alignline\v!innermargin\endcsname{\doxalignline\doxcheckline-+\innermargintotal\relax\hss }
+\defcsname\??alignline\v!outermargin\endcsname{\doxalignline\doxcheckline+-\outermargintotal\hss \relax}
+\defcsname\??alignline\v!inneredge \endcsname{\doxalignline\doxcheckline-+\inneredgetotal \relax\hss }
+\defcsname\??alignline\v!outeredge \endcsname{\doxalignline\doxcheckline+-\outeredgetotal \hss \relax}
+\defcsname\??alignline\v!backspace \endcsname{\doxalignline\doxcheckline-+\backspace \relax\hss }
+\defcsname\??alignline\v!cutspace \endcsname{\doxalignline\doxcheckline+-\cutspace \hss \relax}
-\setvalue{\??alignline\v!leftmargin }{\doxalignline\donefalse --\leftmargintotal \hss \relax}
-\setvalue{\??alignline\v!rightmargin}{\doxalignline\donefalse ++\rightmargintotal\relax\hss }
-\setvalue{\??alignline\v!leftedge }{\doxalignline\donefalse --\leftedgetotal \hss \relax}
-\setvalue{\??alignline\v!rightedge }{\doxalignline\donefalse ++\rightedgetotal \relax\hss }
+\defcsname\??alignline\v!leftmargin \endcsname{\doxalignline\donefalse --\leftmargintotal \hss \relax}
+\defcsname\??alignline\v!rightmargin\endcsname{\doxalignline\donefalse ++\rightmargintotal\relax\hss }
+\defcsname\??alignline\v!leftedge \endcsname{\doxalignline\donefalse --\leftedgetotal \hss \relax}
+\defcsname\??alignline\v!rightedge \endcsname{\doxalignline\donefalse ++\rightedgetotal \relax\hss }
-\permanent\protected\def\doalignedline#1{\csname\??alignline#1\endcsname} % no \resetrealignsignal here ?
+\permanent\protected\def\doalignedline#1{\begincsname\??alignline#1\endcsname}
\permanent\protected\def\alignedline#1#2% setting default
{\ifcsname\??alignline#1\endcsname
@@ -1143,21 +1118,21 @@
\protected\def\spac_align_simple_right #1{{\hss#1}}
\protected\def\spac_align_simple_middle#1{{\hss#1\hss}}
-\letvalue{\??alignsimple \v!right }\spac_align_simple_left
-\letvalue{\??alignsimple \v!outer }\spac_align_simple_left % not managed! see linenumbers
-\letvalue{\??alignsimple \v!flushleft }\spac_align_simple_left
-\letvalue{\??alignsimple \v!left }\spac_align_simple_right
-\letvalue{\??alignsimple \v!inner }\spac_align_simple_right % not managed! see linenumbers
-\letvalue{\??alignsimple \v!flushright}\spac_align_simple_right
-\letvalue{\??alignsimple \v!middle }\spac_align_simple_middle
-
-\letvalue{\??alignsimplereverse\v!right }\spac_align_simple_right
-\letvalue{\??alignsimplereverse\v!outer }\spac_align_simple_right % not managed! see linenumbers
-\letvalue{\??alignsimplereverse\v!flushleft }\spac_align_simple_right
-\letvalue{\??alignsimplereverse\v!left }\spac_align_simple_left
-\letvalue{\??alignsimplereverse\v!inner }\spac_align_simple_left % not managed! see linenumbers
-\letvalue{\??alignsimplereverse\v!flushright}\spac_align_simple_left
-\letvalue{\??alignsimplereverse\v!middle }\spac_align_simple_middle
+\letcsname\??alignsimple \v!right \endcsname\spac_align_simple_left
+\letcsname\??alignsimple \v!outer \endcsname\spac_align_simple_left % not managed! see linenumbers
+\letcsname\??alignsimple \v!flushleft \endcsname\spac_align_simple_left
+\letcsname\??alignsimple \v!left \endcsname\spac_align_simple_right
+\letcsname\??alignsimple \v!inner \endcsname\spac_align_simple_right % not managed! see linenumbers
+\letcsname\??alignsimple \v!flushright\endcsname\spac_align_simple_right
+\letcsname\??alignsimple \v!middle \endcsname\spac_align_simple_middle
+
+\letcsname\??alignsimplereverse\v!right \endcsname\spac_align_simple_right
+\letcsname\??alignsimplereverse\v!outer \endcsname\spac_align_simple_right % not managed! see linenumbers
+\letcsname\??alignsimplereverse\v!flushleft \endcsname\spac_align_simple_right
+\letcsname\??alignsimplereverse\v!left \endcsname\spac_align_simple_left
+\letcsname\??alignsimplereverse\v!inner \endcsname\spac_align_simple_left % not managed! see linenumbers
+\letcsname\??alignsimplereverse\v!flushright\endcsname\spac_align_simple_left
+\letcsname\??alignsimplereverse\v!middle \endcsname\spac_align_simple_middle
\permanent\protected\def\simplealignedbox#1#2%
{\hbox \ifdim#1>\zeropoint to #1
@@ -1206,38 +1181,22 @@
\fi
\fi}
-% \installnamespace{alignsets}
-%
-% \setvalue{\??alignsets\v!right }#1#2{\let#1\relax\let#2\hss }
-% \setvalue{\??alignsets\v!left }#1#2{\let#1\hss \let#2\relax}
-% \setvalue{\??alignsets\v!flushright}#1#2{\let#1\hss \let#2\relax}
-% \setvalue{\??alignsets\v!flushleft }#1#2{\let#1\relax\let#2\hss }
-% \setvalue{\??alignsets\v!middle }#1#2{\let#1\hss \let#2\hss }
-% \setvalue{\??alignsets\v!low }#1#2{\let#1\vss \let#2\relax}
-% \setvalue{\??alignsets\v!high }#1#2{\let#1\relax\let#2\vss }
-% \setvalue{\??alignsets\v!lohi }#1#2{\let#1\vss \let#2\vss }
-% \setvalue{\??alignsets\s!unknown }#1#2{\let#1\relax\let#2\relax}
-%
-% \protected\def\spac_align_set_ss#1%
-% {\csname\??alignsetss\ifcsname\??alignsetss#1\endcsname#1\else\s!unknown\fi\endcsname}
-
% Some obsolete (old) helpers:
-\permanent\tolerant\protected\def\definehbox[#1][#2]%
- {\ifarguments\else\setvalue{hbox#1}##1{\hbox to #2{\begstrut##1\endstrut\hss}}\fi}
+\permanent\tolerant\protected\def\definehbox[#1]#*[#2]%
+ {\ifarguments\else\frozen\instance\protected\defcsname hbox#1\endcsname##1{\hbox to #2{\begstrut##1\endstrut\hss}}\fi}
%D Some direction related helpers:
\installcorenamespace {reverse}
-\setvalue{\??reverse\v!normal }{\ifconditional\inlinelefttoright\else\s!reverse\fi}
-\setvalue{\??reverse\v!reverse}{\ifconditional\inlinelefttoright \s!reverse\fi}
+\defcsname\??reverse\v!normal \endcsname{\ifconditional\inlinelefttoright\else\s!reverse\fi}
+\defcsname\??reverse\v!reverse\endcsname{\ifconditional\inlinelefttoright \s!reverse\fi}
\permanent\def\usedirectionparameterreverse#1{\begincsname\??reverse#1\c!direction\endcsname}
%D Now official:
-\permanent\protected\def\spaceorpar
- {\endgraf\ifhmode\space\fi}
+\permanent\protected\def\spaceorpar{\endgraf\ifhmode\space\fi}
\protect \endinput
diff --git a/tex/context/base/mkxl/spac-chr.lmt b/tex/context/base/mkxl/spac-chr.lmt
new file mode 100644
index 000000000..ac90926e1
--- /dev/null
+++ b/tex/context/base/mkxl/spac-chr.lmt
@@ -0,0 +1,348 @@
+if not modules then modules = { } end modules ['spac-chr'] = {
+ version = 1.001,
+ optimize = true,
+ comment = "companion to spac-chr.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local byte, lower = string.byte, string.lower
+
+-- beware: attribute copying is bugged ... there will be a proper luatex helper
+-- for this
+
+-- to be redone: characters will become tagged spaces instead as then we keep track of
+-- spaceskip etc
+
+-- todo: only setattr when export / use properties
+
+local next = next
+
+local trace_characters = false trackers.register("typesetters.characters", function(v) trace_characters = v end)
+local trace_nbsp = false trackers.register("typesetters.nbsp", function(v) trace_nbsp = v end)
+
+local report_characters = logs.reporter("typesetting","characters")
+
+local nodes, node = nodes, node
+
+local nuts = nodes.nuts
+
+local getboth = nuts.getboth
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local getlanguage = nuts.getlanguage
+local setchar = nuts.setchar
+local setattrlist = nuts.setattrlist
+local getfont = nuts.getfont
+local setsubtype = nuts.setsubtype
+local isglyph = nuts.isglyph
+
+local setcolor = nodes.tracers.colors.set
+
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+local remove_node = nuts.remove
+----- traverse_id = nuts.traverse_id
+----- traverse_char = nuts.traverse_char
+local nextchar = nuts.traversers.char
+local nextglyph = nuts.traversers.glyph
+
+local copy_node = nuts.copy
+
+local nodepool = nuts.pool
+local new_penalty = nodepool.penalty
+local new_glue = nodepool.glue
+local new_kern = nodepool.kern
+local new_rule = nodepool.rule
+
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+
+local glyph_code = nodecodes.glyph
+local spaceskip_code = gluecodes.spaceskip
+
+local chardata = characters.data
+local is_punctuation = characters.is_punctuation
+
+local typesetters = typesetters
+
+local unicodeblocks = characters.blocks
+
+local characters = typesetters.characters or { } -- can be predefined
+typesetters.characters = characters
+
+local fonthashes = fonts.hashes
+local fontparameters = fonthashes.parameters
+local fontcharacters = fonthashes.characters
+local fontquads = fonthashes.quads
+
+local setmetatableindex = table.setmetatableindex
+
+local a_character = attributes.private("characters")
+local a_alignstate = attributes.private("alignstate")
+
+local c_zero = byte('0')
+local c_period = byte('.')
+
+local function inject_quad_space(unicode,head,current,fraction)
+ if fraction ~= 0 then
+ fraction = fraction * fontquads[getfont(current)]
+ end
+ local glue = new_glue(fraction)
+ setattrlist(glue,current)
+ setattrlist(current) -- why reset all
+ setattr(glue,a_character,unicode)
+ return insert_node_after(head,current,glue)
+end
+
+local function inject_char_space(unicode,head,current,parent)
+ local font = getfont(current)
+ local char = fontcharacters[font][parent]
+ local glue = new_glue(char and char.width or fontparameters[font].space)
+ setattrlist(glue,current)
+ setattrlist(current) -- why reset all
+ setattr(glue,a_character,unicode)
+ return insert_node_after(head,current,glue)
+end
+
+local function inject_nobreak_space(unicode,head,current,space,spacestretch,spaceshrink)
+ local glue = new_glue(space,spacestretch,spaceshrink)
+ local penalty = new_penalty(10000)
+ setattrlist(glue,current)
+ setattrlist(current) -- why reset all
+ setattr(glue,a_character,unicode) -- bombs
+ head, current = insert_node_after(head,current,penalty)
+ if trace_nbsp then
+ local rule = new_rule(space)
+ local kern = new_kern(-space)
+ local penalty = new_penalty(10000)
+ setcolor(rule,"orange")
+ head, current = insert_node_after(head,current,rule)
+ head, current = insert_node_after(head,current,kern)
+ head, current = insert_node_after(head,current,penalty)
+ end
+ return insert_node_after(head,current,glue)
+end
+
+local function nbsp(head,current)
+ local para = fontparameters[getfont(current)]
+ local attr = getattr(current,a_alignstate) or 0
+ if attr >= 1 or attr <= 3 then -- flushright
+ head, current = inject_nobreak_space(0x00A0,head,current,para.space,0,0)
+ else
+ head, current = inject_nobreak_space(0x00A0,head,current,para.space,para.spacestretch,para.spaceshrink)
+ end
+ setsubtype(current,spaceskip_code)
+ return head, current
+end
+
+-- assumes nuts or nodes, depending on callers .. so no tonuts here
+
+function characters.replacenbsp(head,original)
+ local head, current = nbsp(head,original)
+ return remove_node(head,original,true)
+end
+
+function characters.replacenbspaces(head)
+ local wipe = false
+ for current, char, font in nextglyph, head do -- can be anytime so no traverse_char
+ if char == 0x00A0 then
+ if wipe then
+ head = remove_node(h,current,true)
+ wipe = false
+ end
+ local h = nbsp(head,current)
+ if h then
+ wipe = current
+ end
+ end
+ end
+ if wipe then
+ head = remove_node(head,current,true)
+ end
+ return head
+end
+
+-- This initialization might move someplace else if we need more of it. The problem is that
+-- this module depends on fonts so we have an order problem.
+
+local nbsphash = { } setmetatableindex(nbsphash,function(t,k)
+ -- this needs checking !
+ for i=unicodeblocks.devanagari.first,unicodeblocks.devanagari.last do nbsphash[i] = true end
+ for i=unicodeblocks.kannada .first,unicodeblocks.kannada .last do nbsphash[i] = true end
+ setmetatableindex(nbsphash,nil)
+ return nbsphash[k]
+end)
+
+local methods = {
+
+ -- The next one uses an attribute assigned to the character but still we
+ -- don't have the 'local' value.
+
+ -- maybe also 0x0008 : backspace
+
+ [0x001F] = function(head,current) -- kind of special
+ local next = getnext(current)
+ if next then
+ local char, font = isglyph(next)
+ if char then
+ head, current = remove_node(head,current,true)
+ if not is_punctuation[char] then
+ local p = fontparameters[font]
+ head, current = insert_node_before(head,current,new_glue(p.space,p.space_stretch,p.space_shrink))
+ end
+ end
+ end
+ end,
+
+ [0x00A0] = function(head,current) -- nbsp
+ local prev, next = getboth(current)
+ if next then
+ local char = isglyph(current)
+ if not char then
+ -- move on
+ elseif char == 0x200C or char == 0x200D then -- nzwj zwj
+ next = getnext(next)
+ if next then
+ char = isglyph(next)
+ if char and nbsphash[char] then
+ return false
+ end
+ end
+ elseif nbsphash[char] then
+ return false
+ end
+ end
+ if prev then
+ local char = isglyph(prev)
+ if char and nbsphash[char] then
+ return false
+ end
+ end
+ return nbsp(head,current)
+ end,
+
+ [0x00AD] = function(head,current) -- softhyphen
+ return insert_node_after(head,current,languages.explicithyphen(current))
+ end,
+
+ [0x2000] = function(head,current) -- enquad
+ return inject_quad_space(0x2000,head,current,1/2)
+ end,
+
+ [0x2001] = function(head,current) -- emquad
+ return inject_quad_space(0x2001,head,current,1)
+ end,
+
+ [0x2002] = function(head,current) -- enspace
+ return inject_quad_space(0x2002,head,current,1/2)
+ end,
+
+ [0x2003] = function(head,current) -- emspace
+ return inject_quad_space(0x2003,head,current,1)
+ end,
+
+ [0x2004] = function(head,current) -- threeperemspace
+ return inject_quad_space(0x2004,head,current,1/3)
+ end,
+
+ [0x2005] = function(head,current) -- fourperemspace
+ return inject_quad_space(0x2005,head,current,1/4)
+ end,
+
+ [0x2006] = function(head,current) -- sixperemspace
+ return inject_quad_space(0x2006,head,current,1/6)
+ end,
+
+ [0x2007] = function(head,current) -- figurespace
+ return inject_char_space(0x2007,head,current,c_zero)
+ end,
+
+ [0x2008] = function(head,current) -- punctuationspace
+ return inject_char_space(0x2008,head,current,c_period)
+ end,
+
+ [0x2009] = function(head,current) -- breakablethinspace
+ return inject_quad_space(0x2009,head,current,1/8) -- same as next
+ end,
+
+ [0x200A] = function(head,current) -- hairspace
+ return inject_quad_space(0x200A,head,current,1/8) -- same as previous (todo)
+ end,
+
+ [0x200B] = function(head,current) -- zerowidthspace
+ return inject_quad_space(0x200B,head,current,0)
+ end,
+
+ [0x202F] = function(head,current) -- narrownobreakspace
+ return inject_nobreak_space(0x202F,head,current,fontquads[getfont(current)]/8)
+ end,
+
+ [0x205F] = function(head,current) -- math thinspace
+ return inject_nobreak_space(0x205F,head,current,4*fontquads[getfont(current)]/18)
+ end,
+
+ -- The next one is also a bom so maybe only when we have glyphs around it
+
+ -- [0xFEFF] = function(head,current) -- zerowidthnobreakspace
+ -- return head, current
+ -- end,
+
+}
+
+characters.methods = methods
+
+-- function characters.handler(head) -- todo: use traverse_id
+-- local current = head
+-- while current do
+-- local char, id = isglyph(current)
+-- if char then
+-- local next = getnext(current)
+-- local method = methods[char]
+-- if method then
+-- if trace_characters then
+-- report_characters("replacing character %C, description %a",char,lower(chardata[char].description))
+-- end
+-- local h = method(head,current)
+-- if h then
+-- head = remove_node(h,current,true)
+-- end
+-- end
+-- current = next
+-- else
+-- current = getnext(current)
+-- end
+-- end
+-- return head
+-- end
+
+-- this also works ok in math as we run over glyphs and these stay glyphs ... not sure
+-- about scripts and such but that is not important anyway ... some day we can consider
+-- special definitions in math
+
+function characters.handler(head)
+ local wipe = false
+ for current, char in nextchar, head do
+ local method = methods[char]
+ if method then
+ if wipe then
+ head = remove_node(head,wipe,true)
+ wipe = false
+ end
+ if trace_characters then
+ report_characters("replacing character %C, description %a",char,lower(chardata[char].description))
+ end
+ local h = method(head,current)
+ if h then
+ wipe = current
+ end
+ end
+ end
+ if wipe then
+ head = remove_node(head,wipe,true)
+ end
+ return head
+end
diff --git a/tex/context/base/mkxl/spac-chr.mkxl b/tex/context/base/mkxl/spac-chr.mkxl
index 57700704f..82c8be0ec 100644
--- a/tex/context/base/mkxl/spac-chr.mkxl
+++ b/tex/context/base/mkxl/spac-chr.mkxl
@@ -15,7 +15,7 @@
\unprotect
-\registerctxluafile{spac-chr}{optimize}
+\registerctxluafile{spac-chr}{autosuffix,optimize}
\definesystemattribute[characters][public]
diff --git a/tex/context/base/mkxl/spac-hor.lmt b/tex/context/base/mkxl/spac-hor.lmt
new file mode 100644
index 000000000..7db8d4d6f
--- /dev/null
+++ b/tex/context/base/mkxl/spac-hor.lmt
@@ -0,0 +1,38 @@
+if not modules then modules = { } end modules ['spac-hor'] = {
+ version = 1.001,
+ comment = "companion to spac-hor.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local chardata = characters.data
+local peekchar = tokens.scanners.peekchar
+local ctx_space = context.space
+
+local can_have_space = table.tohash {
+ "lu", "ll", "lt", "lm", "lo", -- letters
+ -- "mn", "mc", "me", -- marks
+ "nd", "nl", "no", -- numbers
+ "ps", "pi", -- initial
+ -- "pe", "pf", -- final
+ -- "pc", "pd", "po", -- punctuation
+ "sm", "sc", "sk", "so", -- symbols
+ -- "zs", "zl", "zp", -- separators
+ -- "cc", "cf", "cs", "co", "cn", -- others
+}
+
+interfaces.implement {
+ name = "autoinsertnextspace",
+ protected = true,
+ public = true,
+ actions = function()
+ local char = peekchar()
+ if char then
+ local d = chardata[char]
+ if d and can_have_space[d.category] then
+ ctx_space()
+ end
+ end
+ end,
+}
diff --git a/tex/context/base/mkxl/spac-hor.mkxl b/tex/context/base/mkxl/spac-hor.mkxl
index b4704319f..687e7c370 100644
--- a/tex/context/base/mkxl/spac-hor.mkxl
+++ b/tex/context/base/mkxl/spac-hor.mkxl
@@ -15,9 +15,9 @@
\unprotect
-\registerctxluafile{spac-hor}{}
+\registerctxluafile{spac-hor}{autosuffix}
-\let\parfillrightskip\parfillskip
+\aliased\let\parfillrightskip\parfillskip
\bitwiseflip \normalizelinemode \parindentskipcode
\bitwiseflip \normalizelinemode \normalizelinecode
@@ -126,7 +126,7 @@
\installcorenamespace{indentingmethod}
\permanent\protected\def\installindentingmethod#1#2%
- {\setvalue{\??indentingmethod#1}{#2}}
+ {\defcsname\??indentingmethod#1\endcsname{#2}}
\installindentingmethod \v!no {\parindent\zeropoint}
\installindentingmethod \v!not {\parindent\zeropoint}
@@ -281,10 +281,10 @@
\begincsname\??indentnext\p_indentnext\endcsname
\fi}
-\letvalue{\??indentnext }\donothing
-\letvalue{\??indentnext\v!yes }\spac_indentation_variant_yes
-\letvalue{\??indentnext\v!no }\spac_indentation_variant_no
-\letvalue{\??indentnext\v!auto}\spac_indentation_variant_auto
+\letcsname\??indentnext \endcsname\donothing
+\letcsname\??indentnext\v!yes \endcsname\spac_indentation_variant_yes
+\letcsname\??indentnext\v!no \endcsname\spac_indentation_variant_no
+\letcsname\??indentnext\v!auto\endcsname\spac_indentation_variant_auto
%D An example of usage:
%D
@@ -383,16 +383,6 @@
\installspacingmethod \v!packed {\newfrenchspacing} % slighly more after punctuation
\installspacingmethod \v!broad {\nonfrenchspacing} % more depending on what punctuation
-%% \permanent\protected\def\setupspacing
-%% {\doifelsenextoptionalcs\spac_spacecodes_setup_yes\spac_spacecodes_setup_nop}
-%%
-%% \def\spac_spacecodes_setup_yes[#1]%
-%% {\begincsname\??spacecodemethod#1\endcsname
-%% \updateraggedskips}
-%%
-%% \def\spac_spacecodes_setup_nop
-%% {\updateraggedskips}
-
\permanent\tolerant\protected\def\setupspacing[#1]%
{\ifarguments\or
\begincsname\??spacecodemethod#1\endcsname
@@ -481,7 +471,7 @@
\letcatcodecommand \ctxcatcodes \tildeasciicode \nonbreakablespace % overloaded later
-% \def\space { }
+% \def\space { }
\permanent\protected\def\removelastspace{\ifhmode\unskip\fi}
\permanent\protected\def\nospace {\removelastspace\ignorespaces}
@@ -645,12 +635,12 @@
\c!default=\v!middle]
\appendtoks
- \frozen\instance\setuevalue{\e!start\currentnarrower}{\spac_narrower_start[\currentnarrower]}%
- \frozen\instance\setuevalue{\e!stop \currentnarrower}{\spac_narrower_stop}%
+ \frozen\instance\protected\defcsname\e!start\currentnarrower\endcsname{\spac_narrower_start[\currentnarrower]}%
+ \frozen\instance\protected\defcsname\e!stop \currentnarrower\endcsname{\spac_narrower_stop}%
\to \everydefinenarrower
\permanent\protected\def\installnarrowermethod#1#2%
- {\setvalue{\??narrowermethod#1}{#2}}
+ {\defcsname\??narrowermethod#1\endcsname{#2}}
\protected\def\spac_narrower_method_analyze#1%
{\ifcsname\??narrowermethod#1\endcsname
@@ -793,21 +783,15 @@
\newskip\leftskipadaption
\newskip\rightskipadaption
-\setvalue{\??skipadaptionleft \v!yes }{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi}
-\letvalue{\??skipadaptionleft \v!no }\zeropoint
-\letvalue{\??skipadaptionleft \empty }\zeropoint
-\setvalue{\??skipadaptionright\v!yes }{\narrowerparameter\c!right}
-\letvalue{\??skipadaptionright\v!no }\zeropoint
-\letvalue{\??skipadaptionright\empty }\zeropoint
-
-% \setvalue{\??skipadaptionleft \v!standard}{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi}
-% \setvalue{\??skipadaptionright\v!standard}{\narrowerparameter\c!right}
-
-\letcsnamecsname\csname\??skipadaptionleft \v!standard\endcsname\csname\??skipadaptionleft \v!yes\endcsname
-\letcsnamecsname\csname\??skipadaptionright\v!standard\endcsname\csname\??skipadaptionright\v!yes\endcsname
+\defcsname\??skipadaptionleft \v!yes\endcsname{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi}
+\letcsname\??skipadaptionleft \v!no \endcsname\zeropoint
+\letcsname\??skipadaptionleft \empty\endcsname\zeropoint
+\defcsname\??skipadaptionright\v!yes\endcsname{\narrowerparameter\c!right}
+\letcsname\??skipadaptionright\v!no \endcsname\zeropoint
+\letcsname\??skipadaptionright\empty\endcsname\zeropoint
-% \protected\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\csname\??skipadaptionleft #1\endcsname\else#1\fi\relax}
-% \protected\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\csname\??skipadaptionright#1\endcsname\else#1\fi\relax}
+\letcsname\??skipadaptionleft \v!standard\expandafter\endcsname\csname\??skipadaptionleft \v!yes\endcsname
+\letcsname\??skipadaptionright\v!standard\expandafter\endcsname\csname\??skipadaptionright\v!yes\endcsname
\permanent\protected\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\lastnamedcs\else#1\fi\relax}
\permanent\protected\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\lastnamedcs\else#1\fi\relax}
@@ -840,7 +824,7 @@
\installcorenamespace{tolerancemethods}
\permanent\protected\def\installtolerancemethod#1#2#3%
- {\setvalue{\??tolerancemethods#1:#2}{#3}}
+ {\defcsname\??tolerancemethods#1:#2\endcsname{#3}}
\installtolerancemethod \v!vertical \v!verystrict {\let\bottomtolerance\empty}
\installtolerancemethod \v!vertical \v!strict {\def\bottomtolerance{.050}}
@@ -913,17 +897,13 @@
%D {\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi}
%D \stoptyping
%D
-%D But what is a \type{\strut}? Normally it's a rule of width
-%D zero, but when made visual, it's a rule and a negative skip.
-%D The mechanism for putting things in the margins described
-%D here cannot handle this situation very well. One
-%D characteristic of \type{\strut} is that the \type{\unhcopy}
-%D results in entering horizontal mode, which in return leads
-%D to some indentation.
-%D
-%D To serve our purpose a bit better, the macro \type{\strut}
-%D can be redefined as:
+%D But what is a \type {\strut}? Normally it's a rule of width zero, but when made
+%D visual, it's a rule and a negative skip. The mechanism for putting things in the
+%D margins described here cannot handle this situation very well. One characteristic
+%D of \type {\strut} is that the \type {\unhcopy} results in entering horizontal
+%D mode, which in return leads to some indentation.
%D
+%D To serve our purpose a bit better, the macro \type {\strut} can be redefined as:
%D \starttyping
%D \def\strut
%D {\relax\ifmmode\else\hskip0pt\fi\copy\strutbox}
@@ -940,9 +920,9 @@
%D \fi}
%D \stoptyping
%D
-%D In \CONTEXT\ however we save some processing time by putting
-%D an extra \type{\hbox} around the \type{\strutbox}.
-
+%D In \CONTEXT\ however we save some processing time by putting an extra \type
+%D {\hbox} around the \type {\strutbox}.
+%D
%D \starttyping
%D % \setuplayout[gridgrid=yes] \showgrid
%D
@@ -970,8 +950,8 @@
%D \stoptyping
\permanent\protected\def\justonespace{\removeunwantedspaces\space}
-%frozen\protected\def\justaperiod {\removeunwantedspaces.}
-%frozen\protected\def\justacomma {\removeunwantedspaces,}
+%permanent\protected\def\justaperiod {\removeunwantedspaces.}
+%permanent\protected\def\justacomma {\removeunwantedspaces,}
\installcorenamespace{hspace}
@@ -981,9 +961,9 @@
\permanent\tolerant\protected\def\definehspace[#1]#*[#2]#*[#3]% #1 = optional namespace
{\ifparameter#3\or
- \setvalue{\??hspace#1:#2}{#3}%
+ \defcsname\??hspace#1:#2\endcsname{#3}%
\else
- \setvalue{\??hspace:#1}{#2}%
+ \defcsname\??hspace :#1\endcsname{#2}%
\fi}
\permanent\tolerant\protected\def\hspace[#1]#*[#2]%
@@ -1081,7 +1061,7 @@
\installcorenamespace{spacemethods}
\permanent\protected\def\installspacemethod#1#2% needs to set \obeyedspace
- {\setvalue{\??spacemethods#1}{#2}}
+ {\defcsname\??spacemethods#1\endcsname{#2}}
\permanent\def\activatespacehandler#1%
{\csname\??spacemethods\ifcsname\??spacemethods#1\endcsname#1\else\v!off\fi\endcsname}
@@ -1127,21 +1107,17 @@
%D
%D \typebuffer \getbuffer
-\permanent\protected\def\autoinsertnextspace
- {\futurelet\nexttoken\spac_spaces_auto_insert_next}
-
-\permanent\def\spac_spaces_auto_insert_next
- {\clf_autonextspace{\normalmeaning\nexttoken}} % todo, just consult nexttoken at the lua end
+% \autoinsertnextspace % defined at the lua end
%D Moved from bib module:
\permanent\protected\def\outdented#1%
{\hskip-\hangindent#1\relax}
-%D Beware: due to char-def this becomes an active character but that
-%D might change sometime when we will replace all these specials to
-%D node insertions. We might even expand it to utf then as it then
-%D can be used in string comparison (not that much needed anyway).
+%D Beware: due to char-def this becomes an active character but that might change
+%D sometime when we will replace all these specials to node insertions. We might
+%D even expand it to utf then as it then can be used in string comparison (not that
+%D much needed anyway).
% \chardef\zwnj="200C
% \chardef\zwj ="200D
diff --git a/tex/context/base/mkxl/spac-prf.lmt b/tex/context/base/mkxl/spac-prf.lmt
new file mode 100644
index 000000000..2223c7730
--- /dev/null
+++ b/tex/context/base/mkxl/spac-prf.lmt
@@ -0,0 +1,949 @@
+ if not modules then modules = { } end modules ['spac-prf'] = {
+ version = 1.001,
+ comment = "companion to spac-prf.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is a playground, a byproduct of some experiments in a project where
+-- we needed something like this where it works ok, but nevertheless it's
+-- still experimental code. It is very likely to change (or extended).
+
+local unpack, rawget = unpack, rawget
+
+local formatters = string.formatters
+
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+local listcodes = nodes.listcodes
+
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local kern_code = nodecodes.kern
+local penalty_code = nodecodes.penalty
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local unset_code = nodecodes.unset
+local math_code = nodecodes.math
+local rule_code = nodecodes.rule
+local marginkern_code = nodecodes.marginkern
+
+local leaders_code = gluecodes.leaders
+local lineskip_code = gluecodes.lineskip
+local baselineskip_code = gluecodes.baselineskip
+
+local linelist_code = listcodes.line
+
+local texlists = tex.lists
+local settexattribute = tex.setattribute
+
+local nuts = nodes.nuts
+local tonut = nodes.tonut
+local tonode = nuts.tonode
+
+local getreplace = nuts.getreplace
+local getattr = nuts.getattr
+local getid = nuts.getid
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getsubtype = nuts.getsubtype
+local getlist = nuts.getlist
+local gettexbox = nuts.getbox
+local getwhd = nuts.getwhd
+local getglue = nuts.getglue
+local getkern = nuts.getkern
+local getshift = nuts.getshift
+local getwidth = nuts.getwidth
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
+local getboxglue = nuts.getboxglue
+
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setattr = nuts.setattr
+local setwhd = nuts.setwhd
+local setshift = nuts.setshift
+local setwidth = nuts.setwidth
+local setheight = nuts.setheight
+local setdepth = nuts.setdepth
+
+local properties = nodes.properties.data
+local setprop = nuts.setprop
+local getprop = nuts.getprop
+local theprop = nuts.theprop
+
+local floor = math.floor
+local ceiling = math.ceil
+
+local new_rule = nuts.pool.rule
+local new_glue = nuts.pool.glue
+local new_kern = nuts.pool.kern
+local hpack_nodes = nuts.hpack
+local find_node_tail = nuts.tail
+local setglue = nuts.setglue
+
+local a_visual = attributes.private("visual")
+local a_snapmethod = attributes.private("snapmethod")
+local a_profilemethod = attributes.private("profilemethod")
+----- a_specialcontent = attributes.private("specialcontent")
+
+local variables = interfaces.variables
+local v_none = variables.none
+local v_fixed = variables.fixed
+local v_strict = variables.strict
+
+local setcolor = nodes.tracers.colors.set
+local settransparency = nodes.tracers.transparencies.set
+
+local enableaction = nodes.tasks.enableaction
+
+local profiling = { }
+builders.profiling = profiling
+
+local report = logs.reporter("profiling")
+
+local show_profile = false trackers.register("profiling.show", function(v) show_profile = v end)
+local trace_profile = false trackers.register("profiling.trace",function(v) trace_profile = v end)
+
+local function getprofile(line,step)
+
+ -- only l2r
+ -- no hz yet
+
+ local line = tonut(line)
+ local current = getlist(line)
+
+ if not current then
+ return
+ end
+
+ local glue_set, glue_order, glue_sign = getboxglue(line)
+
+ local heights = { }
+ local depths = { }
+ local width = 0
+ local position = 0
+ local step = step or 65536 -- * 2 -- 2pt
+ local margin = step / 4
+ local min = 0
+ local max = ceiling(getwidth(line)/step) + 1
+ local wd = 0
+ local ht = 0
+ local dp = 0
+
+ for i=min,max do
+ heights[i] = 0
+ depths [i] = 0
+ end
+
+ -- remember p
+
+ local function progress()
+ position = width
+ width = position + wd
+ p = floor((position - margin)/step + 0.5)
+ w = floor((width + margin)/step - 0.5)
+ if p < 0 then
+ p = 0
+ end
+ if w < 0 then
+ w = 0
+ end
+ if p > w then
+ w, p = p, w
+ end
+ if w > max then
+ for i=max+1,w+1 do
+ heights[i] = 0
+ depths [i] = 0
+ end
+ max = w
+ end
+ for i=p,w do
+ if ht > heights[i] then
+ heights[i] = ht
+ end
+ if dp > depths[i] then
+ depths[i] = dp
+ end
+ end
+ end
+
+ local function process(current) -- called nested in disc replace
+ while current do
+ local id = getid(current)
+ if id == glyph_code then
+ wd, ht, dp = getwhd(current)
+ progress()
+ elseif id == kern_code then
+ wd = getkern(current)
+ ht = 0
+ dp = 0
+ progress()
+ elseif id == disc_code then
+ local replace = getreplace(current)
+ if replace then
+ process(replace)
+ end
+ elseif id == glue_code then
+ local width, stretch, shrink, stretch_order, shrink_order = getglue(current)
+ if glue_sign == 1 then
+ if stretch_order == glue_order then
+ wd = width + stretch * glue_set
+ else
+ wd = width
+ end
+ elseif glue_sign == 2 then
+ if shrink_order == glue_order then
+ wd = width - shrink * glue_set
+ else
+ wd = width
+ end
+ else
+ wd = width
+ end
+ if getsubtype(current) >= leaders_code then
+ local leader = getleader(current)
+ local w
+ w, ht, dp = getwhd(leader) -- can become getwhd(current) after 1.003
+ else
+ ht = 0
+ dp = 0
+ end
+ progress()
+ elseif id == hlist_code then
+ -- we could do a nested check .. but then we need to push / pop glue
+ local shift = getshift(current)
+ local w, h, d = getwhd(current)
+ -- if getattr(current,a_specialcontent) then
+ if getprop(current,"specialcontent") then
+ -- like a margin note, maybe check for wd
+ wd = w
+ ht = 0
+ dp = 0
+ else
+ wd = w
+ ht = h - shift
+ dp = d + shift
+ end
+ progress()
+ elseif id == vlist_code or id == unset_code then
+ local shift = getshift(current) -- todo
+ wd, ht, dp = getwhd(current)
+ progress()
+ elseif id == rule_code then
+ wd, ht, dp = getwhd(current)
+ progress()
+ elseif id == math_code then
+ wd = getkern(current) + getwidth(current) -- surround
+ ht = 0
+ dp = 0
+ progress()
+ elseif id == marginkern_code then
+ -- not in lmtx
+ wd = getwidth(current)
+ ht = 0
+ dp = 0
+ progress()
+ else
+-- print(nodecodes[id])
+ end
+ current = getnext(current)
+ end
+ end
+
+ process(current)
+
+ return {
+ heights = heights,
+ depths = depths,
+ min = min, -- not needed
+ max = max,
+ step = step,
+ }
+
+end
+
+profiling.get = getprofile
+
+local function getpagelist()
+ local pagehead = texlists.page_head
+ if pagehead then
+ pagehead = tonut(texlists.page_head)
+ pagetail = find_node_tail(pagehead)
+ else
+ pagetail = nil
+ end
+ return pagehead, pagetail
+end
+
+local function setprofile(n,step)
+ local p = rawget(properties,n)
+ if p then
+ local pp = p.profile
+ if not pp then
+ pp = getprofile(n,step)
+ p.profile = pp
+ end
+ return pp
+ else
+ local pp = getprofile(n,step)
+ properties[n] = { profile = pp }
+ return pp
+ end
+end
+
+local function hasprofile(n)
+ local p = rawget(properties,n)
+ if p then
+ return p.profile
+ end
+end
+
+local function addstring(height,depth)
+ local typesetters = nuts.typesetters
+ local hashes = fonts.hashes
+ local infofont = fonts.infofont()
+ local emwidth = hashes.emwidths [infofont]
+ local exheight = hashes.exheights[infofont]
+ local httext = height
+ local dptext = depth
+ local httext = typesetters.tohpack(height,infofont)
+ local dptext = typesetters.tohpack(depth,infofont)
+ setshift(httext,- 1.2 * exheight)
+ setshift(dptext, 0.6 * exheight)
+ local text = hpack_nodes(setlink(
+ new_kern(-getwidth(httext)-emwidth),
+ httext,
+ new_kern(-getwidth(dptext)),
+ dptext
+ ))
+ setwhd(text,0,0,0)
+ return text
+end
+
+local function addprofile(node,profile,step)
+
+ local line = tonut(node)
+
+ if not profile then
+ profile = setprofile(line,step)
+ end
+
+ if not profile then
+ report("some error")
+ return node
+ end
+
+ if profile.shown then
+ return node
+ end
+
+ local list = getlist(line)
+ profile.shown = true
+
+ local heights = profile.heights
+ local depths = profile.depths
+ local step = profile.step
+
+ local head = nil
+ local tail = nil
+
+ local lastht = 0
+ local lastdp = 0
+ local lastwd = 0
+
+ local visual = "f:s:t" -- this can change !
+
+ local function progress()
+ if lastwd == 0 then
+ return
+ end
+ local what = nil
+ if lastht == 0 and lastdp == 0 then
+ what = new_kern(lastwd)
+ else
+ what = new_rule(lastwd,lastht,lastdp)
+ setcolor(what,visual)
+ settransparency(what,visual)
+ end
+ if tail then
+ setlink(tail,what)
+ else
+ head = what
+ end
+ tail = what
+ end
+
+-- inspect(profile)
+
+ for i=profile.min,profile.max do
+ local ht = heights[i]
+ local dp = depths[i]
+ if ht ~= lastht or dp ~= lastdp and lastwd > 0 then
+ progress()
+ lastht = ht
+ lastdp = dp
+ lastwd = step
+ else
+ lastwd = lastwd + step
+ end
+ end
+ if lastwd > 0 then
+ progress()
+ end
+
+ local rule = hpack_nodes(head)
+
+ setwhd(rule,0,0,0)
+
+ -- if texttoo then
+ --
+ -- local text = addstring(
+ -- formatters["%0.4f"](getheight(rule)/65536),
+ -- formatters["%0.4f"](getdepth(rule) /65536)
+ -- )
+ --
+ -- setlink(text,rule)
+ --
+ -- rule = text
+ --
+ -- end
+
+ setlink(rule,list)
+ setlist(line,rule)
+
+end
+
+profiling.add = addprofile
+
+local methods = { }
+
+local function getdelta(t_profile,b_profile)
+ local t_heights = t_profile.heights
+ local t_depths = t_profile.depths
+ local t_max = t_profile.max
+ local b_heights = b_profile.heights
+ local b_depths = b_profile.depths
+ local b_max = b_profile.max
+
+ local max = t_max
+ local delta = 0
+
+ if t_max > b_max then
+ for i=b_max+1,t_max do
+ b_depths [i] = 0
+ b_heights[i] = 0
+ end
+ max = t_max
+ elseif b_max > t_max then
+ for i=t_max+1,b_max do
+ t_depths [i] = 0
+ t_heights[i] = 0
+ end
+ max = b_max
+ end
+
+ for i=0,max do
+ local ht = b_heights[i]
+ local dp = t_depths[i]
+ local hd = ht + dp
+ if hd > delta then
+ delta = hd
+ end
+ end
+
+ return delta
+end
+
+-- local properties = theprop(bot)
+-- local unprofiled = properties.unprofiled
+-- if not unprofiled then -- experiment
+-- properties.unprofiled = {
+-- height = height,
+-- strutht = strutht,
+-- }
+-- end
+
+-- lineskip | lineskiplimit
+
+local function inject(top,bot,amount) -- todo: look at penalties
+ local glue = new_glue(amount)
+ --
+ setattr(glue,a_profilemethod,0)
+ setattr(glue,a_visual,getattr(top,a_visual))
+ --
+ setlink(top,glue,bot)
+end
+
+methods[v_none] = function()
+ return false
+end
+
+methods[v_strict] = function(top,bot,t_profile,b_profile,specification)
+
+ local top = tonut(top)
+ local bot = tonut(bot)
+
+ local strutht = specification.height or texdimen.strutht
+ local strutdp = specification.depth or texdimen.strutdp
+ local lineheight = strutht + strutdp
+
+ local depth = getdepth(top)
+ local height = getheight(bot)
+ local total = depth + height
+ local distance = specification.distance or 0
+ local delta = lineheight - total
+
+ -- there is enough room between the lines so we don't need
+ -- to add extra distance
+
+ if delta >= distance then
+ inject(top,bot,delta)
+ return true
+ end
+
+ local delta = getdelta(t_profile,b_profile)
+ local skip = delta - total + distance
+
+ -- we don't want to be too tight so we limit the skip and
+ -- make sure we have at least lineheight
+
+ inject(top,bot,skip)
+ return true
+
+end
+
+-- todo: also set ht/dp of first / last (but what is that)
+
+methods[v_fixed] = function(top,bot,t_profile,b_profile,specification)
+
+ local top = tonut(top)
+ local bot = tonut(bot)
+
+ local strutht = specification.height or texdimen.strutht
+ local strutdp = specification.depth or texdimen.strutdp
+ local lineheight = strutht + strutdp
+
+ local depth = getdepth(top)
+ local height = getheight(bot)
+ local total = depth + height
+ local distance = specification.distance or 0
+ local delta = lineheight - total
+
+ local snapmethod = getattr(top,a_snapmethod)
+
+ if snapmethod then
+
+ -- no distance (yet)
+
+ if delta < lineheight then
+ setdepth(top,strutdp)
+ setheight(bot,strutht)
+ return true
+ end
+
+ local delta = getdelta(t_profile,b_profile)
+
+ local dp = strutdp
+ while depth > lineheight - strutdp do
+ depth = depth - lineheight
+ dp = dp + lineheight
+ end
+ setdepth(top,dp)
+ local ht = strutht
+ while height > lineheight - strutht do
+ height = height - lineheight
+ ht = ht + lineheight
+ end
+ setheight(bot,ht)
+ local lines = floor(delta/lineheight)
+ if lines > 0 then
+ inject(top,bot,-lines * lineheight)
+ end
+
+ return true
+
+ end
+
+ if total < lineheight then
+ setdepth(top,strutdp)
+ setheight(bot,strutht)
+ return true
+ end
+
+ if depth < strutdp then
+ setdepth(top,strutdp)
+ total = total - depth + strutdp
+ end
+ if height < strutht then
+ setheight(bot,strutht)
+ total = total - height + strutht
+ end
+
+ local delta = getdelta(t_profile,b_profile)
+
+ local target = total - delta
+ local factor = specification.factor or 1
+ local step = lineheight / factor
+ local correction = 0
+ local nofsteps = 0
+ while correction < target - step - distance do -- a loop is more accurate, for now
+ correction = correction + step
+ nofsteps = nofsteps + 1
+ end
+
+ if trace_profile then
+ report("top line : %s %05i > %s",t_profile.shown and "+" or "-",top,nodes.toutf(getlist(top)))
+ report("bottom line : %s %05i > %s",b_profile.shown and "+" or "-",bot,nodes.toutf(getlist(bot)))
+ report(" depth : %p",depth)
+ report(" height : %p",height)
+ report(" total : %p",total)
+ report(" lineheight : %p",lineheight)
+ report(" delta : %p",delta)
+ report(" target : %p",target)
+ report(" factor : %i",factor)
+ report(" distance : %p",distance)
+ report(" step : %p",step)
+ report(" nofsteps : %i",nofsteps)
+ -- report(" max lines : %s",lines == 0 and "unset" or lines)
+ report(" correction : %p",correction)
+ end
+
+ inject(top,bot,-correction) -- we could mess with the present glue (if present)
+
+ return true -- remove interlineglue
+
+end
+
+function profiling.distance(top,bot,specification)
+ local step = specification.step
+ local method = specification.method
+ local ptop = getprofile(top,step)
+ local pbot = getprofile(bot,step)
+ local action = methods[method or v_strict] or methods[v_strict]
+ return action(top,bot,ptop,pbot,specification)
+end
+
+local specifications = { } -- todo: save these !
+
+function profiling.fixedprofile(current)
+ local a = getattr(current,a_profilemethod)
+ if a then
+ local s = specifications[a]
+ if s then
+ return s.method == v_fixed
+ end
+ end
+ return false
+end
+
+local function profilelist(line,mvl)
+
+ local current = line
+
+ local top = nil
+ local bot = nil
+
+ local t_profile = nil
+ local b_profile = nil
+
+ local specification = nil
+ local lastattr = nil
+ local method = nil
+ local action = nil
+
+ local distance = 0
+ local lastglue = nil
+
+ local pagehead = nil
+ local pagetail = nil
+
+ if mvl then
+
+ pagehead, pagetail = getpagelist()
+
+ if pagetail then
+ local current = pagetail
+ while current do
+ local id = getid(current)
+ if id == hlist_code then
+ local subtype = getsubtype(current)
+ if subtype == linelist_code then
+ t_profile = hasprofile(current)
+ if t_profile then
+ top = current
+ end
+ end
+ break
+ elseif id == glue_code then
+ local wd = getwidth(current)
+ if not wd or wd == 0 then
+ -- go on
+ else
+ break
+ end
+ elseif id == penalty_code then
+ -- ok
+ else
+ break
+ end
+ current = getnext(current)
+ end
+ end
+
+ end
+
+ while current do
+
+ local attr = getattr(current,a_profilemethod)
+
+ if attr then
+
+ if attr ~= lastattr then
+ specification = specifications[attr]
+ method = specification and specification.method
+ action = method and methods[method] or methods[v_strict]
+ lastattr = attr
+ end
+
+ local id = getid(current)
+
+ if id == hlist_code then -- check subtype
+ local subtype = getsubtype(current)
+ if subtype == linelist_code then
+ if top == current then
+ -- skip
+ bot = nil -- to be sure
+ elseif top then
+ bot = current
+ b_profile = setprofile(bot)
+ if show_profile then
+ addprofile(bot,b_profile)
+ end
+ if not t_profile.done then
+ if action then
+ local ok = action(top,bot,t_profile,b_profile,specification)
+ if ok and lastglue and distance ~= 0 then
+ setglue(lastglue)
+ end
+ end
+ t_profile.done = true
+ end
+ top = bot
+ bot = nil
+ t_profile = b_profile
+ b_profile = nil
+ distance = 0
+ else
+ top = current
+ t_profile = setprofile(top)
+ bot = nil
+ if show_profile then
+ addprofile(top,t_profile)
+ end
+ end
+ else
+ top = nil
+ bot = nil
+ end
+ elseif id == glue_code then
+ if top then
+ local subtype = getsubtype(current)
+ -- if subtype == lineskip_code or subtype == baselineskip_code then
+ local wd = getwidth(current)
+ if wd > 0 then
+ distance = wd
+ lastglue = current
+ elseif wd < 0 then
+ top = nil
+ bot = nil
+ else
+ -- ok
+ end
+ -- else
+ -- top = nil
+ -- bot = nil
+ -- end
+ else
+ top = nil
+ bot = nil
+ end
+ elseif id == penalty_code then
+ -- okay
+ else
+ top = nil
+ bot = nil
+ end
+ else
+ top = nil
+ bot = nil
+ end
+ current = getnext(current)
+ end
+ if top then
+ t_profile = setprofile(top)
+ if show_profile then
+ addprofile(top,t_profile)
+ end
+ end
+end
+
+profiling.list = profilelist
+
+local enabled = false
+
+function profiling.set(specification)
+ if not enabled then
+ enableaction("mvlbuilders", "builders.profiling.pagehandler")
+ -- too expensive so we expect that this happens explicitly, we keep for reference:
+ -- enableaction("vboxbuilders","builders.profiling.vboxhandler")
+ enabled = true
+ end
+ local n = #specifications + 1
+ specifications[n] = specification
+ settexattribute(a_profilemethod,n)
+end
+
+function profiling.profilebox(specification)
+ local boxnumber = specification.box
+ local current = getlist(gettexbox(boxnumber))
+ local top = nil
+ local bot = nil
+ local t_profile = nil
+ local b_profile = nil
+ local method = specification and specification.method
+ local action = method and methods[method] or methods[v_strict]
+ local lastglue = nil
+ local distance = 0
+ while current do
+ local id = getid(current)
+ if id == hlist_code then
+ local subtype = getsubtype(current)
+ if subtype == linelist_code then
+ if top then
+ bot = current
+ b_profile = setprofile(bot)
+ if show_profile then
+ addprofile(bot,b_profile)
+ end
+ if not t_profile.done then
+ if action then
+ local ok = action(top,bot,t_profile,b_profile,specification)
+ if ok and lastglue and distance ~= 0 then
+ setglue(lastglue)
+ end
+ end
+ t_profile.done = true
+ end
+ top = bot
+ t_profile = b_profile
+ b_profile = nil
+ distance = 0
+ else
+ top = current
+ t_profile = setprofile(top)
+ if show_profile then
+ addprofile(top,t_profile)
+ end
+ bot = nil
+ end
+ else
+ top = nil
+ bot = nil
+ end
+ elseif id == glue_code then
+ local subtype = getsubtype(current)
+ if subtype == lineskip_code or subtype == baselineskip_code then
+ if top then
+ local wd = getwidth(current)
+ if wd > 0 then
+ distance = wd
+ lastglue = current
+ elseif wd < 0 then
+ top = nil
+ bot = nil
+ else
+ -- ok
+ end
+ else
+ top = nil
+ bot = nil
+ end
+ else
+ top = nil
+ bot = nil
+ end
+ elseif id == penalty_code then
+ -- okay
+ else
+ top = nil
+ bot = nil
+ end
+ current = getnext(current)
+ end
+
+ if top then
+ t_profile = setprofile(top) -- not needed
+ if show_profile then
+ addprofile(top,t_profile)
+ end
+ end
+
+end
+
+-- local ignore = table.tohash {
+-- "split_keep",
+-- "split_off",
+-- -- "vbox",
+-- }
+--
+-- function profiling.vboxhandler(head,where)
+-- if head and not ignore[where] then
+-- if getnext(head) then
+-- profilelist(head)
+-- end
+-- end
+-- return head
+-- end
+
+function profiling.pagehandler(head)
+ if head then
+ profilelist(head,true)
+ end
+ return head
+end
+
+interfaces.implement {
+ name = "setprofile",
+ actions = profiling.set,
+ arguments = {
+ {
+ { "name" },
+ { "height", "dimen" },
+ { "depth", "dimen" },
+ { "distance", "dimen" },
+ { "factor", "integer" },
+ { "lines", "integer" },
+ { "method" }
+ }
+ }
+}
+
+interfaces.implement {
+ name = "profilebox",
+ actions = profiling.profilebox,
+ arguments = {
+ {
+ { "box", "integer" },
+ { "height", "dimen" },
+ { "depth", "dimen" },
+ { "distance", "dimen" },
+ { "factor", "integer" },
+ { "lines", "integer" },
+ { "method" }
+ }
+ }
+}
diff --git a/tex/context/base/mkxl/spac-prf.mklx b/tex/context/base/mkxl/spac-prf.mklx
index 585437ac4..6b4a966f2 100644
--- a/tex/context/base/mkxl/spac-prf.mklx
+++ b/tex/context/base/mkxl/spac-prf.mklx
@@ -20,11 +20,11 @@
\unprotect
-\registerctxluafile{spac-prf}{}
+\registerctxluafile{spac-prf}{autosuffix}
\definesystemattribute[profilemethod][public]
-\installcorenamespace {profile} % beware, profiles are not like in mkii at all
+\installcorenamespace {profile}
\installcorenamespace {profiles}
\installcommandhandler \??profile {profile} \??profile
@@ -84,11 +84,11 @@
\ifparameter#settings\or
\edef\currentprofile{#profile}%
\setupcurrentprofile[#settings]%
+ \orelse\ifhastok={#profile}%
+ \let\currentprofile\v!none
+ \setupcurrentprofile[#profile]%
\else
- \doifassignmentelse{#profile}
- {\let\currentprofile\v!none
- \setupcurrentprofile[#profile]}%
- {\edef\currentprofile{#profile}}%
+ \edef\currentprofile{#profile}%
\fi
\dowithnextbox
{\profilegivenbox\currentprofile\nextbox
diff --git a/tex/context/base/mkxl/spac-ver.mkxl b/tex/context/base/mkxl/spac-ver.mkxl
index f2bb68093..fe74ee06e 100644
--- a/tex/context/base/mkxl/spac-ver.mkxl
+++ b/tex/context/base/mkxl/spac-ver.mkxl
@@ -648,33 +648,31 @@
\newdimen\openstrutheight
\newdimen\openstrutdepth
\newdimen\topskipgap
-\newdimen\struttotal
-
-\def\strutheightfactor {.72}
-\def\strutdepthfactor {.28}
-\def\baselinefactor {2.8}
+\newdimen\strutheight
+\newdimen\strutdepth
+\newdimen\struttotal
+\newdimen\strutwidth
\let\m_spac_vertical_baseline_stretch_factor \zerocount
\let\m_spac_vertical_baseline_shrink_factor \zerocount
-\def\minimumstrutheight {\zeropoint}
-\def\minimumstrutdepth {\zeropoint}
+\mutable\def\strutheightfactor {.72}
+\mutable\def\strutdepthfactor {.28}
+\mutable\def\baselinefactor {2.8}
+\mutable\def\topskipfactor {1.0}
+\mutable\def\maxdepthfactor {0.5}
-\def\normallineheight {\baselinefactor\exheight}
-\def\minimumlinedistance {\lineskip}
+\mutable\def\minimumstrutheight {\zeropoint}
+\mutable\def\minimumstrutdepth {\zeropoint}
-\def\strutheight {\zeropoint}
-\def\strutdepth {\zeropoint}
-\def\strutwidth {\zeropoint}
+\mutable\def\normallineheight {\baselinefactor\exheight}
+\mutable\def\minimumlinedistance {\lineskip}
-\let\spacingfactor \plusone
+\mutable\let\spacingfactor \plusone
-\def\topskipfactor {1.0}
-\def\maxdepthfactor {0.5}
-
-\def\systemtopskipfactor {\topskipfactor}
-\def\systemmaxdepthfactor {\maxdepthfactor}
+\mutable\def\systemtopskipfactor {\topskipfactor}
+\mutable\def\systemmaxdepthfactor{\maxdepthfactor}
\ifdefined\globalbodyfontsize \else
\newdimen\globalbodyfontsize
@@ -768,7 +766,7 @@
{\ifgridsnapping
\let\spacingfactor\plusone
\else
- \edef\spacingfactor{#1}%
+ \permanent\edef\spacingfactor{#1}%
\fi
\edef\systemtopskipfactor {\thewithoutunit\dimexpr#1\dimexpr\topskipfactor \points}%
\edef\systemmaxdepthfactor{\thewithoutunit\dimexpr#1\dimexpr\maxdepthfactor\points}%
@@ -927,8 +925,8 @@
\else
\struttotal\dimexpr\strutht+\strutdp\relax
\fi
- \edef\strutheight{\the\strutht}%
- \edef\strutdepth {\the\strutdp}%
+ \strutheight\strutht
+ \strutdepth \strutdp
\ifdim\strutwidth=\zeropoint
\spac_struts_set_hide
\else
@@ -1103,7 +1101,7 @@
\settestcrlf}
\permanent\protected\def\setteststrut
- {\def\strutwidth{.8pt}%
+ {\strutwidth.8\onepoint
\setstrut}
\permanent\protected\def\dontshowstruts
@@ -1111,10 +1109,10 @@
\settestcrlf}
\permanent\protected\def\unsetteststrut
- {\let\strutwidth\zeropoint
+ {\strutwidth\zeropoint
\setstrut}
-\def\autostrutfactor{1.1}
+\mutable\def\autostrutfactor{1.1}
\permanent\protected\def\setautostrut
{\begingroup
@@ -1240,7 +1238,7 @@
\let\pseudoendstrut\removeunwantedspaces
\permanent\protected\def\resetteststrut
- {\def\strutwidth{\zeropoint}% no let
+ {\strutwidth\zeropoint
\setstrut}
\ifdefined\setfontparameters \else
@@ -1260,7 +1258,7 @@
%D Handy:
-\def\baselinedistance{\the\lineheight}
+\permanent\def\baselinedistance{\the\lineheight}
%D We need \type {\normaloffinterlineskip} because the new definition contains an
%D assignment, and |<|don't ask me why|>| this assignment gives troubles in for
@@ -1273,7 +1271,7 @@
\lineskip \zeropoint
\lineskiplimit\maxdimen
% We also need this here now; thanks to taco for figuring that out!
- \def\minimumlinedistance{\zeropoint}}
+ \let\minimumlinedistance\zeropoint}
\overloaded\permanent\protected\def\nointerlineskip
{\prevdepth-\thousandpoint}
@@ -1302,10 +1300,6 @@
{\aftergroup\page_otr_synchronize_page_indeed
\global\enforced\let\page_otr_synchronize_page\relax}
-% \protected\def\page_otr_synchronize_page_indeed
-% {\clf_synchronizepage
-% \glet\page_otr_synchronize_page\page_otr_synchronize_page_yes}
-%
% This has to become an otr method: \s!page_otr_command_synchonize_page
\protected\def\page_otr_synchronize_page_indeed
@@ -2445,6 +2439,6 @@
% test \par
% test \par
-\protected\def\ignoreparskip{\c_spac_vspacing_ignore_parskip\plusone}
+\permanent\protected\def\ignoreparskip{\c_spac_vspacing_ignore_parskip\plusone}
\protect \endinput
diff --git a/tex/context/base/mkxl/strc-con.mklx b/tex/context/base/mkxl/strc-con.mklx
index 54397ce3a..21213a330 100644
--- a/tex/context/base/mkxl/strc-con.mklx
+++ b/tex/context/base/mkxl/strc-con.mklx
@@ -103,9 +103,29 @@
\installcorenamespace{constructionlevel} % frozen after definition
\installcorenamespace{constructionclass} % frozen after definition
-\let\currentconstructionmain \empty
-\let\currentconstructionlevel \empty
-\let\currentconstructionhandler\empty
+%aliased\let\currentconstructionhash \??construction
+
+\mutable\let\currentconstructionmain \empty
+\mutable\let\currentconstructionlevel \empty
+\mutable\let\currentconstructionhandler \empty
+
+\mutable\let\currentconstructionattribute \empty
+\mutable\let\currentconstructionbookmark \empty
+\mutable\let\currentconstructioncatcodes \empty
+\mutable\let\currentconstructioncoding \empty
+\mutable\let\currentconstructionexpansion \empty
+\mutable\let\currentconstructionincrementnumber\empty
+\mutable\let\currentconstructionlabel \empty
+\mutable\let\currentconstructionlist \empty
+\mutable\let\currentconstructionlistentry \empty
+\mutable\let\currentconstructionlistnumber \empty
+\mutable\let\currentconstructionmarking \empty
+\mutable\let\currentconstructionnumber \empty
+\mutable\let\currentconstructionreference \empty
+\mutable\let\currentconstructionreferenceprefix\empty
+\mutable\let\currentconstructionsynchronize \empty
+\mutable\let\currentconstructiontitle \empty
+\mutable\let\currentconstructionxmlsetup \empty
\settrue\c_strc_constructions_define_commands % use with care, might become a proper key
@@ -308,8 +328,6 @@
% we also need to make sure that no stretch creeps in (new per 2015-02-02, for Alan)
\settrue\c_strc_constructions_distance_none}
-\overloaded\let\currentconstructionhash\??construction
-
\protected\setvalue{\??constructionstarthandler\v!construction}% this will be redone (reorganized) .. too much boxing
{\dostarttaggedchained\t!construction\currentconstruction\currentconstructionhash
% \dotagsetconstruction
diff --git a/tex/context/base/mkxl/strc-doc.mkxl b/tex/context/base/mkxl/strc-doc.mkxl
index 046f0b086..50b71d9d2 100644
--- a/tex/context/base/mkxl/strc-doc.mkxl
+++ b/tex/context/base/mkxl/strc-doc.mkxl
@@ -19,6 +19,46 @@
%D This will move:
+\mutable\let\currentstructureattribute \empty
+\mutable\let\currentstructurebackreference \empty
+\mutable\let\currentstructurebookmark \empty
+\mutable\let\currentstructurecatcodes \empty
+\mutable\let\currentstructurecoding \empty
+\mutable\let\currentstructurecoupling \empty
+\mutable\let\currentstructureexpansion \empty
+\mutable\let\currentstructureincrementnumber \empty
+\mutable\let\currentstructurelabel \empty
+\mutable\let\currentstructurelevel \empty
+\mutable\let\currentstructurelist \empty
+\mutable\let\currentstructurelistattribute \empty
+\mutable\let\currentstructuremarking \empty
+\mutable\let\currentstructurename \empty
+\mutable\let\currentstructureownnumber \empty
+\mutable\let\currentstructureplaceholder \empty
+\mutable\let\currentstructurereference \empty
+\mutable\let\currentstructurereferenceattribute \empty
+\mutable\let\currentstructurereferenceprefix \empty
+\mutable\let\currentstructuresaveinlist \empty
+\mutable\let\currentstructureshownumber \empty
+\mutable\let\currentstructuretitle \empty
+\mutable\let\currentstructurexmlsetup \empty
+
+\mutable\let\currentstructurecomponentattribute \empty
+\mutable\let\currentstructurecomponentbookmark \empty
+\mutable\let\currentstructurecomponentcatcodes \empty
+\mutable\let\currentstructurecomponentcoding \empty
+\mutable\let\currentstructurecomponentexpansion \empty
+\mutable\let\currentstructurecomponentlabel \empty
+\mutable\let\currentstructurecomponentlevel \empty
+\mutable\let\currentstructurecomponentlist \empty
+\mutable\let\currentstructurecomponentmarking \empty
+\mutable\let\currentstructurecomponentname \empty
+\mutable\let\currentstructurecomponentreference \empty
+\mutable\let\currentstructurecomponentreferenceprefix\empty
+\mutable\let\currentstructurecomponentsynchronize \empty
+\mutable\let\currentstructurecomponenttitle \empty
+\mutable\let\currentstructurecomponentxmlsetup \empty
+
\permanent\protected\def\setstructuresynchronization#1% todo: use ctxcontext
{\clf_setinternalreference
prefix {\currentstructurereferenceprefix}%
diff --git a/tex/context/base/mkxl/strc-flt.mklx b/tex/context/base/mkxl/strc-flt.mklx
index 500219f56..31622a336 100644
--- a/tex/context/base/mkxl/strc-flt.mklx
+++ b/tex/context/base/mkxl/strc-flt.mklx
@@ -187,6 +187,12 @@
\d_page_floats_compress_distance\floatparameter\c!compressdistance\relax
\to \everysetupfloat
+\mutable\let\currentfloatattribute \empty
+\mutable\let\currentfloatcounter \empty
+\mutable\let\currentfloatgroup \empty
+\mutable\let\currentfloatnumber \empty
+\mutable\let\currentfloatsynchronize\empty
+
%D We need to do it again here:
\setupfloat
@@ -1030,8 +1036,6 @@
% todo: optional user pars
-\let\currentfloatattribute\empty % to be checked
-
\def\floatcaptionattribute
{\iflocation
\ifempty\currentfloatattribute
@@ -1231,7 +1235,7 @@
\setvalue{\??floatmovement+2*\v!line}{\strc_floats_move_down_line{2}}
\setvalue{\??floatmovement 2*\v!line}{\strc_floats_move_down_line{2}}
-\protected\def\installfloatmovement#1#2{\setvalue{\??floatmovement#1}{#2}}
+\permanent\protected\def\installfloatmovement#1#2{\setvalue{\??floatmovement#1}{#2}}
\def\strc_floats_move_down#setting%
{\begincsname\??floatmovement#setting\endcsname}
diff --git a/tex/context/base/mkxl/strc-itm.mklx b/tex/context/base/mkxl/strc-itm.mklx
index df6272310..e2f2244a5 100644
--- a/tex/context/base/mkxl/strc-itm.mklx
+++ b/tex/context/base/mkxl/strc-itm.mklx
@@ -228,15 +228,15 @@
\let \m_strc_itemgroups_indenting \empty
\let \m_strc_itemgroups_destination \empty
-\let \currentitemlevel \!!zerocount % public
-\def \currentnofitems {\the\c_strc_itemgroups_max_items}
-\def \currentitemnumber {\strc_counters_raw_sub\v_strc_itemgroups_counter\currentitemlevel} % public
+\mutable\let \currentitemlevel \!!zerocount % public
+\mutable\def \currentnofitems {\the\c_strc_itemgroups_max_items}
+\mutable\def \currentitemnumber {\strc_counters_raw_sub\v_strc_itemgroups_counter\currentitemlevel} % public
\newtoks \itemgroupcommands % maybe public
-\def \currentitemgroupsymbol {n} % here we cannot use a _ in the name
-\let \currentitemgroupconversionset \empty % here we cannot use a _ in the name
-\let \currentitemgroupsegments \empty
+\mutable\def \currentitemgroupsymbol {n} % here we cannot use a _ in the name
+\mutable\let \currentitemgroupconversionset \empty % here we cannot use a _ in the name
+\mutable\let \currentitemgroupsegments \empty
\def\strc_itemgroups_register_status
{\clf_registeritemgroup{\currentparentitemgroup}\c_strc_itemgroups_nesting\c_strc_itemgroups_n_of_items\dimexpr\itemgroupparameter\c!maxwidth\relax}
diff --git a/tex/context/base/mkxl/strc-mat.mkxl b/tex/context/base/mkxl/strc-mat.mkxl
index 8ebd79a73..991c3202e 100644
--- a/tex/context/base/mkxl/strc-mat.mkxl
+++ b/tex/context/base/mkxl/strc-mat.mkxl
@@ -315,15 +315,15 @@
\glet#1\relax
\fi\fi}
-\let\currentplaceformulaattribute\relax
-\let\currentformulaattribute \relax
-\let\currentsubformulaattribute \relax
-\let\currentformulasattribute \relax
+\mutable\let\currentplaceformulaattribute\relax
+\mutable\let\currentformulaattribute \relax
+\mutable\let\currentsubformulaattribute \relax
+\mutable\let\currentformulasattribute \relax
-\let\currentplaceformulanumber\relax
-\let\currentformulanumber \relax
-\let\currentsubformulanumber \relax
-\let\currentformulasnumber \relax
+\mutable\let\currentplaceformulanumber\relax
+\mutable\let\currentformulanumber \relax
+\mutable\let\currentsubformulanumber \relax
+\mutable\let\currentformulasnumber \relax
\mutable\let\currentformulasreference \empty
\mutable\let\currentformulareference \empty
@@ -349,10 +349,10 @@
\glet\currentnestedformulasuffix\empty
\to \everyresetformulas
-\let\currentplaceformulasynchronize\relax
-\let\currentformulasynchronize \relax
-\let\currentsubformulasynchronize \relax
-\let\currentformulassynchronize \relax
+\mutable\let\currentplaceformulasynchronize\relax
+\mutable\let\currentformulasynchronize \relax
+\mutable\let\currentsubformulasynchronize \relax
+\mutable\let\currentformulassynchronize \relax
\appendtoks
\glet\currentplaceformulasynchronize \relax
@@ -361,6 +361,11 @@
\glet\currentnestedformulasynchronize\relax
\to \everyresetformulas
+\mutable\let\currentsubformulasattribute \empty
+\mutable\let\currentsubformulasnumber \empty
+\mutable\let\currentsubformulasreference \empty
+\mutable\let\currentsubformulassynchronize\empty
+
% currently we do the number, some day we will do the (sub) formula
\def\strc_formulas_handle_current_references
diff --git a/tex/context/base/mkxl/strc-ref.mklx b/tex/context/base/mkxl/strc-ref.mklx
index 45f0ff713..10100fa03 100644
--- a/tex/context/base/mkxl/strc-ref.mklx
+++ b/tex/context/base/mkxl/strc-ref.mklx
@@ -29,7 +29,7 @@
\registerctxluafile{strc-rsc}{}
\registerctxluafile{strc-ref}{}
-\registerctxluafile{node-ref}{optimize}
+\registerctxluafile{node-ref}{autosuffix,optimize}
\unprotect
@@ -58,12 +58,32 @@
%D page number in an unnumbered document). By setting the \type{interaction}
%D variable, one can influences the way interactive references are set.
-\let\referenceprefix\empty
-
\installcorenamespace{referencing}
\installdirectcommandhandler \??referencing {referencing} % \??referencing
+\mutable\let\referenceprefix \empty
+
+\mutable\let\currentreferenceattribute \empty
+\mutable\let\currentreferencecoding \empty
+\mutable\let\currentreferencecontent \empty
+\mutable\let\currentreferencedata \empty
+\mutable\let\currentreferenceexpansion \empty
+\mutable\let\currentreferenceformatautocase\empty
+\mutable\let\currentreferenceformatlabel \empty
+\mutable\let\currentreferenceformatsetups \empty
+\mutable\let\currentreferenceformattype \empty
+\mutable\let\currentreferencekind \empty
+\mutable\let\currentreferencelabels \empty
+\mutable\let\currentreferencenumber \empty
+\mutable\let\currentreferenceorder \empty
+\mutable\let\currentreferencepage \empty
+\mutable\let\currentreferencerealpage \empty
+\mutable\let\currentreferencetext \empty
+\mutable\let\currentreferencetitle \empty
+\mutable\let\currentreferenceuserdata \empty
+
+
\newif\ifreferencing \referencingtrue
\appendtoks
diff --git a/tex/context/base/mkxl/strc-reg.mkxl b/tex/context/base/mkxl/strc-reg.mkxl
index f44819bc1..38ecae4a7 100644
--- a/tex/context/base/mkxl/strc-reg.mkxl
+++ b/tex/context/base/mkxl/strc-reg.mkxl
@@ -122,6 +122,30 @@
%D test \index{test+one} test \index{test+two} more \index{more}
%D \stoptyping
+\mutable\let\currentregistercharacter \empty
+\mutable\let\currentregistercoding \empty
+\mutable\let\currentregisterentries \empty
+\mutable\let\currentregisterentriesa \empty
+\mutable\let\currentregisterentriesb \empty
+\mutable\let\currentregisterentriesc \empty
+\mutable\let\currentregisterexpansion \empty
+\mutable\let\currentregisterkeys \empty
+\mutable\let\currentregisterkeysa \empty
+\mutable\let\currentregisterkeysb \empty
+\mutable\let\currentregisterkeysc \empty
+\mutable\let\currentregisterlabel \empty
+\mutable\let\currentregistermaxwidth \empty
+\mutable\let\currentregistername \empty
+\mutable\let\currentregisternumber \empty
+\mutable\let\currentregisterownnumber \empty
+\mutable\let\currentregisterpageindex \empty
+\mutable\let\currentregisterpagesymbol \empty
+\mutable\let\currentregistersectionindex\empty
+\mutable\let\currentregisterseeindex \empty
+\mutable\let\currentregisterseeword \empty
+\mutable\let\currentregistersynchronize \empty
+\mutable\let\currentregisterxmlsetup \empty
+
\newconditional\c_strc_registers_defining
\setnewconstant\c_strc_registers_maxlevel \plusfive
diff --git a/tex/context/base/mkxl/strc-sec.mkxl b/tex/context/base/mkxl/strc-sec.mkxl
index 58f942b5f..9025b9930 100644
--- a/tex/context/base/mkxl/strc-sec.mkxl
+++ b/tex/context/base/mkxl/strc-sec.mkxl
@@ -99,6 +99,16 @@
\permanent\def\namedstructureheadlocation#1% expandable, maybe [#1]
{\csname\??savedinternalreference\ifcsname\??savedinternalreference#1\endcsname#1\else\s!default\fi\endcsname}
+\mutable\let\currentheadbackreference \empty
+\mutable\let\currentheaddefault \empty
+\mutable\let\currentheadincrement \empty
+\mutable\let\currentheadinteraction \empty
+\mutable\let\currentheadlabeltag \empty
+\mutable\let\currentheadnumber \!!zerocount
+\mutable\let\currentheadrenderingalternative\empty
+\mutable\let\currentheadrenderingsetup \empty
+\mutable\let\currentheadtext \empty
+
% The next directive only makes sense when we have sort of garanteed outcome (math is not so
% nice for instance).
%
@@ -790,8 +800,8 @@
{\strc_sectioning_delayed_flush
\normalexpanded{\setmarking[\currenthead]{li::\currentstructurelistnumber}}}
-\let\deepstructurenumbercommand\relax
-\let\deepstructuretitlecommand \relax
+\mutable\let\deepstructurenumbercommand\relax
+\mutable\let\deepstructuretitlecommand \relax
\permanent\protected\def\fullheadnumber
{\edef\currentheadlabeltag{\currentsectionblock\c!label}%
@@ -814,11 +824,11 @@
\fi
\dostoptagged}
-\let\currenthead \empty
-\let\currentheadcoupling\empty
-\let\currentheadsection \empty
-\let\currentheadlevel \!!zerocount
-\let\currentheadcounter \!!zerocount
+\mutable\let\currenthead \empty
+\mutable\let\currentheadcoupling\empty
+\mutable\let\currentheadsection \empty
+\mutable\let\currentheadlevel \!!zerocount
+\mutable\let\currentheadcounter \!!zerocount
\let\strc_show_used\relax
@@ -1182,7 +1192,7 @@
%permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax}
\permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\previoushead\relax}
-\let\previoushead\empty
+\mutable\let\previoushead\empty
\def\strc_sectioning_handle_page_nop
{\edef\p_continue{\headparameter\c!continue}%
@@ -1259,8 +1269,6 @@
\permanent\tolerant\protected\def\setupheadnumber[#1]#*[#2]% todo: reset if at other level
{\setstructurenumber{\thenamedheadlevel{#1}}{\number#2}}
-\def\currentheadnumber{0} % ==> \currentheadnumber
-
\permanent\protected\def\determineheadnumber[#1]%
{\xdef\currentheadnumber{\getstructurenumber{\thenamedheadlevel{#1}}}}
diff --git a/tex/context/base/mkxl/supp-box.mkxl b/tex/context/base/mkxl/supp-box.mkxl
index 721667822..ac39b396a 100644
--- a/tex/context/base/mkxl/supp-box.mkxl
+++ b/tex/context/base/mkxl/supp-box.mkxl
@@ -814,7 +814,7 @@
\newevery \everyshapebox \relax
-\def\shapesignal{.12345678pt} % or 12345sp
+\permanent\dimensiondef\shapesignal.12345678pt % or 12345sp
\permanent\protected\def\reshapebox#1%
{\doreshapebox
diff --git a/tex/context/base/mkxl/syst-aux.mkxl b/tex/context/base/mkxl/syst-aux.mkxl
index 064416275..057aa5e98 100644
--- a/tex/context/base/mkxl/syst-aux.mkxl
+++ b/tex/context/base/mkxl/syst-aux.mkxl
@@ -2829,7 +2829,7 @@
%D
%D A fully expandable message:
-\let\immediatemessage\clf_immediatemessage % {} mandate / todo permanent at lua end
+\aliased\let\immediatemessage\clf_immediatemessage % {} mandate / todo permanent at lua end
%D \macros
%D {rawgetparameters}
@@ -5737,10 +5737,10 @@
\permanent\protected\def\settrialtypesetting {\the\everysettrialtypesetting } % obeys grouping so
\permanent\protected\def\resettrialtypesetting{\the\everyresettrialtypesetting} % this one is seldom needed
-\let\iftrialtypesetting\iffalse % so we have no \trialtypesettingtrue|false in mkiv !
+\aliased\let\iftrialtypesetting\iffalse % so we have no \trialtypesettingtrue|false in mkiv !
-\appendtoks \let\iftrialtypesetting\iftrue \to \everysettrialtypesetting
-\appendtoks \let\iftrialtypesetting\iffalse \to \everyresettrialtypesetting
+\appendtoks \enforced\aliased\let\iftrialtypesetting\iftrue \to \everysettrialtypesetting
+\appendtoks \enforced\aliased\let\iftrialtypesetting\iffalse \to \everyresettrialtypesetting
%D \macros
%D {twodigitrounding}
diff --git a/tex/context/base/mkxl/syst-ini.mkxl b/tex/context/base/mkxl/syst-ini.mkxl
index 0f507d978..bdae879fa 100644
--- a/tex/context/base/mkxl/syst-ini.mkxl
+++ b/tex/context/base/mkxl/syst-ini.mkxl
@@ -626,7 +626,7 @@
\newif\ifscratchconditionone
\newif\ifscratchconditiontwo
-\let\htdp\boxtotal
+\aliased\let\htdp\boxtotal
%D A few shortcuts:
@@ -723,12 +723,14 @@
\tracingstats\plusone
-%D This is only used when we load \CONTEXT:
+%D This is only used when we load \CONTEXT. Nesting is not supported here.
\permanent\def\pushoverloadmode
- {\edef\popoverloadmode{\overloadmode\the\overloadmode}%
+ {\enforced\permanent\protected\edef\popoverloadmode{\overloadmode\the\overloadmode\enforced\let\popoverloadmode\relax}%
\overloadmode\zerocount}
+\aliased\let\popoverloadmode\relax
+
\newtoks\everydump
\pushoverloadmode
diff --git a/tex/context/base/mkxl/tabl-ntb.mkxl b/tex/context/base/mkxl/tabl-ntb.mkxl
index 67288c83e..aa29237b5 100644
--- a/tex/context/base/mkxl/tabl-ntb.mkxl
+++ b/tex/context/base/mkxl/tabl-ntb.mkxl
@@ -1679,7 +1679,7 @@
\newbox\TABLEsplitbox % public, don't change
-\let\extratblsplitheight\zeropoint % additional space taken by before/afterTABLEsplitbox
+\mutable\let\extratblsplitheight\zeropoint % additional space taken by before/afterTABLEsplitbox
\def\tabl_ntb_split_box
{\resettsplit
@@ -1707,13 +1707,13 @@
% ! ! ! ! TODO: naast \postprocessTABLEsplitbox ook evt \postprocessTABLEbox voor niet split
-\let\postprocessTABLEsplitbox\gobbleoneargument
-\let\postprocessTABLEbox \gobbleoneargument
+\mutable\let\postprocessTABLEsplitbox\gobbleoneargument % maybe just a parameter
+\mutable\let\postprocessTABLEbox \gobbleoneargument % maybe just a parameter
-\let\beforeTABLEsplitbox\relax
-\let\afterTABLEsplitbox \relax
-\let\beforeTABLEbox \relax
-\let\afterTABLEbox \relax
+\mutable\let\beforeTABLEsplitbox\relax % maybe just a parameter
+\mutable\let\afterTABLEsplitbox \relax % maybe just a parameter
+\mutable\let\beforeTABLEbox \relax % maybe just a parameter
+\mutable\let\afterTABLEbox \relax % maybe just a parameter
\def\tabl_ntb_check_widths_one{\tabl_ntb_check_widths_indeed\zerocount} % 0 = trial run
\def\tabl_ntb_check_widths_two{\tabl_ntb_check_widths_indeed\plusone } % 1 = real run
diff --git a/tex/context/base/mkxl/tabl-tbl.mkxl b/tex/context/base/mkxl/tabl-tbl.mkxl
index 75c47df50..cacaef12c 100644
--- a/tex/context/base/mkxl/tabl-tbl.mkxl
+++ b/tex/context/base/mkxl/tabl-tbl.mkxl
@@ -232,9 +232,9 @@
\newtoks \everytabulate % public ?
\protected\def\tolerantTABLEbreaktrue {\settrue \c_tabl_tabulate_tolerant_break} % used in styles !
-\protected\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated
+%protected\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated
-\def\noftabulaterows{\number\c_tabl_tabulate_noflines} % handy for testing if a table is empty
+\permanent\def\noftabulaterows{\number\c_tabl_tabulate_noflines} % handy for testing if a table is empty
\installcorenamespace{tabulatebox}
\installcorenamespace{tabulatesetup}
@@ -769,7 +769,7 @@
{\global\d_tabl_tabulate_vrulethickness#1\d_tabl_tabulate_vrulethickness_default}
{\xdef\m_tabl_tabulate_vrule_color{#1}}}
-\def\tabl_tabulate_set_entry#1#2% rulespec template
+\permanent\protected\def\tabl_tabulate_set_entry#1#2% rulespec template
{\c_tabl_tabulate_align\v_tabl_tabulate_align
\c_tabl_tabulate_modus\zerocount
\setfalse\c_tabl_tabulate_pwidth_set
@@ -807,7 +807,7 @@
\tabl_tabulate_set_width_simple
\fi}
-\def\tabl_tabulate_set_last_entry#1% rulespec
+\permanent\protected\def\tabl_tabulate_set_last_entry#1% rulespec
{\glet\m_tabl_tabulate_color\empty
\glet\m_tabl_tabulate_vrule_color\empty
\edef\currenttabulationtrulespec{#1}%
@@ -822,8 +822,8 @@
\tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
\tabl_tabulate_column_vrule_inject}}
-\let\settabulateentry \tabl_tabulate_set_entry % used at the lua end
-\let\settabulatelastentry\tabl_tabulate_set_last_entry % used at the lua end
+\aliased\let\settabulateentry \tabl_tabulate_set_entry % used at the lua end
+\aliased\let\settabulatelastentry\tabl_tabulate_set_last_entry % used at the lua end
\def\tabl_tabulate_normalize_splitline
{\ifcase\c_tabl_tabulate_splitlinemode
diff --git a/tex/context/base/mkxl/tabl-tsp.mkxl b/tex/context/base/mkxl/tabl-tsp.mkxl
index f09a5d9d8..561ed73cb 100644
--- a/tex/context/base/mkxl/tabl-tsp.mkxl
+++ b/tex/context/base/mkxl/tabl-tsp.mkxl
@@ -253,9 +253,9 @@
\resettsplit
-\def\tsplitdirectwidth{\hsize}
+\mutable\def\tsplitdirectwidth{\hsize}
-\protected\def\handletsplit
+\permanent\protected\def\handletsplit
{\page_split_float_check_caption{\wd\b_split_content}%
\global\setfalse\splitfloatfirstdone
\testpagesync % new, sync, but still tricky
diff --git a/tex/context/base/mkxl/toks-scn.mkxl b/tex/context/base/mkxl/toks-scn.mkxl
index 12abf0cb8..e8da7063d 100644
--- a/tex/context/base/mkxl/toks-scn.mkxl
+++ b/tex/context/base/mkxl/toks-scn.mkxl
@@ -18,9 +18,6 @@
\registerctxluafile{toks-scn}{}
\registerctxluafile{cldf-scn}{}
\registerctxluafile{cldf-stp}{}
-
-\ifcase \contextlmtxmode \else
- \registerctxluafile{cldf-lmt}{}
-\fi
+\registerctxluafile{cldf-lmt}{}
\protect \endinput
diff --git a/tex/context/base/mkxl/trac-vis.lmt b/tex/context/base/mkxl/trac-vis.lmt
index 7ac5964da..96f3215f7 100644
--- a/tex/context/base/mkxl/trac-vis.lmt
+++ b/tex/context/base/mkxl/trac-vis.lmt
@@ -936,6 +936,8 @@ local ruledglue do
-- local keepskip_code = gluecodes.keepskip or gluecodes.userskip
local leftskip_code = gluecodes.leftskip
local rightskip_code = gluecodes.rightskip
+ local lefthangskip_code = gluecodes.lefthangskip
+ local righthangskip_code = gluecodes.righthangskip
local parfillleftskip_code = gluecodes.parfillleftskip or parfillskip_code
local parfillrightskip_code = gluecodes.parfillrightskip or parfillskip_code
local indentskip_code = gluecodes.indentskip
@@ -956,8 +958,6 @@ local ruledglue do
[gluecodes.topskip] = "TS",
[gluecodes.splittopskip] = "ST",
[gluecodes.tabskip] = "AS",
- [gluecodes.lefthangskip] = "LH",
- [gluecodes.righthangskip] = "RH",
[gluecodes.thinmuskip] = "MS",
[gluecodes.medmuskip] = "MM",
[gluecodes.thickmuskip] = "ML",
@@ -972,6 +972,8 @@ local ruledglue do
-- false = "HS",
[leftskip_code] = "LS",
[rightskip_code] = "RS",
+ [lefthangskip_code] = "LH",
+ [righthangskip_code] = "RH",
[spaceskip_code] = "SP",
[xspaceskip_code] = "XS",
[zerospaceskip_code] = "ZS",
@@ -995,6 +997,8 @@ local ruledglue do
info = sometext(amount,l_glue,c_space)
elseif subtype == leftskip_code or subtype == rightskip_code then
info = sometext(amount,l_glue,c_skip_a)
+ elseif subtype == lefthangskip_code or subtype == righthangskip_code then
+ info = sometext(amount,l_glue,c_skip_b)
elseif subtype == parfillleftskip_code or subtype == parfillrightskip_code or subtype == indentskip_code or subtype == correctionskip_code then
info = sometext(amount,l_glue,c_indent)
elseif subtype == userskip_code then
diff --git a/tex/context/base/mkxl/typo-cap.lmt b/tex/context/base/mkxl/typo-cap.lmt
new file mode 100644
index 000000000..c5c91243e
--- /dev/null
+++ b/tex/context/base/mkxl/typo-cap.lmt
@@ -0,0 +1,420 @@
+if not modules then modules = { } end modules ['typo-cap'] = {
+ version = 1.001,
+ optimize = true,
+ comment = "companion to typo-cap.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- see typo-cap.lua for a word traverser variant
+
+local next, type, tonumber = next, type, tonumber
+local format, insert = string.format, table.insert
+local div, getrandom = math.div, utilities.randomizer.get
+
+local trace_casing = false trackers.register("typesetters.casing", function(v) trace_casing = v end)
+
+local report_casing = logs.reporter("typesetting","casing")
+
+local nodes, node = nodes, node
+
+local nuts = nodes.nuts
+
+local getnext = nuts.getnext
+local getid = nuts.getid
+local takeattr = nuts.takeattr
+local getfont = nuts.getfont
+local getsubtype = nuts.getsubtype
+local getchar = nuts.getchar
+local isglyph = nuts.isglyph
+local getdisc = nuts.getdisc
+
+local setchar = nuts.setchar
+local setfont = nuts.setfont
+
+local copy_node = nuts.copy
+local end_of_math = nuts.end_of_math
+local insert_after = nuts.insert_after
+local find_attribute = nuts.find_attribute
+
+local nextglyph = nuts.traversers.glyph
+
+local nodecodes = nodes.nodecodes
+local kerncodes = nodes.kerncodes
+
+local glyph_code = nodecodes.glyph
+local kern_code = nodecodes.kern
+local disc_code = nodecodes.disc
+local math_code = nodecodes.math
+
+local fontkern_code = kerncodes.fontkern
+
+local enableaction = nodes.tasks.enableaction
+
+local newkern = nuts.pool.kern
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local fontchar = fonthashes.characters
+
+local currentfont = font.current
+
+local variables = interfaces.variables
+local v_reset = variables.reset
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+typesetters = typesetters or { }
+local typesetters = typesetters
+
+typesetters.cases = typesetters.cases or { }
+local cases = typesetters.cases
+
+cases.actions = { }
+local actions = cases.actions
+local a_cases = attributes.private("case")
+
+local extract = bit32.extract
+local run = 0 -- a trick to make neighbouring ranges work
+local blocked = { }
+
+local function set(tag,font)
+ if run == 0x40 then -- 2^6
+ run = 1
+ else
+ run = run + 1
+ end
+ local a = font * 0x10000 + tag * 0x100 + run
+ blocked[a] = false
+ return a
+end
+
+local function get(a)
+ return
+ extract(a, 8, 8), -- tag
+ extract(a,16,12), -- font
+ extract(a, 0, 8) -- run
+end
+
+-- a previous implementation used char(0) as placeholder for the larger font, so we needed
+-- to remove it before it can do further harm ... that was too tricky as we use char 0 for
+-- other cases too
+--
+-- we could do the whole glyph run here (till no more attributes match) but then we end up
+-- with more code .. maybe i will clean this up anyway as the lastfont hack is somewhat ugly
+-- ... on the other hand, we need to deal with cases like:
+--
+-- \WORD {far too \Word{many \WORD{more \word{pushed} in between} useless} words}
+
+local uccodes = characters.uccodes
+local lccodes = characters.lccodes
+local categories = characters.categories
+
+-- true false true == mixed
+
+local function replacer(start,codes)
+ local char, fnt = isglyph(start)
+ local dc = codes[char]
+ if dc then
+ local ifc = fontchar[fnt]
+ if type(dc) == "table" then
+ for i=1,#dc do
+ if not ifc[dc[i]] then
+ return start, false
+ end
+ end
+ for i=#dc,1,-1 do
+ local chr = dc[i]
+ if i == 1 then
+ setchar(start,chr)
+ else
+ local g = copy_node(start)
+ setchar(g,chr)
+ insert_after(start,start,g)
+ end
+ end
+ elseif ifc[dc] then
+ setchar(start,dc)
+ end
+ end
+ return start
+end
+
+local registered, n = { }, 0
+
+local function register(name,f)
+ if type(f) == "function" then
+ n = n + 1
+ actions[n] = f
+ registered[name] = n
+ return n
+ else
+ local n = registered[f]
+ registered[name] = n
+ return n
+ end
+end
+
+cases.register = register
+
+local function WORD(start,attr,lastfont,n,count,where,first)
+ lastfont[n] = false
+ return replacer(first or start,uccodes)
+end
+
+local function word(start,attr,lastfont,n,count,where,first)
+ lastfont[n] = false
+ return replacer(first or start,lccodes)
+end
+
+local function Words(start,attr,lastfont,n,count,where,first) -- looks quite complex
+ if where == "post" then
+ return
+ end
+ if count == 1 and where ~= "post" then
+ replacer(first or start,uccodes)
+ return start, true
+ else
+ return start, true
+ end
+end
+
+local function Word(start,attr,lastfont,n,count,where,first)
+ blocked[attr] = true
+ return Words(start,attr,lastfont,n,count,where,first)
+end
+
+local function camel(start,attr,lastfont,n,count,where,first)
+ word(start,attr,lastfont,n,count,where,first)
+ Words(start,attr,lastfont,n,count,where,first)
+ return start, true
+end
+
+local function mixed(start,attr,lastfont,n,count,where,first)
+ if where == "post" then
+ return
+ end
+ local used = first or start
+ local char = getchar(used)
+ local dc = uccodes[char]
+ if not dc then
+ -- quit
+ elseif dc == char then
+ local lfa = lastfont[n]
+ if lfa then
+ setfont(used,lfa)
+ end
+ else
+ replacer(used,uccodes)
+ end
+ return start, true
+end
+
+local function Capital(start,attr,lastfont,n,count,where,first,once) -- 3
+ local used = first or start
+ if count == 1 and where ~= "post" then
+ local lfa = lastfont[n]
+ if lfa then
+ local dc = uccodes[getchar(used)]
+ if dc then
+ setfont(used,lfa)
+ end
+ end
+ end
+ local s, c = replacer(first or start,uccodes)
+ if once then
+ lastfont[n] = false -- here
+ end
+ return start, c
+end
+
+local function capital(start,attr,lastfont,n,where,count,first,count) -- 4
+ return Capital(start,attr,lastfont,n,where,count,first,true)
+end
+
+local function none(start,attr,lastfont,n,count,where,first)
+ return start, true
+end
+
+local function randomized(start,attr,lastfont,n,count,where,first)
+ local used = first or start
+ local char = getchar(used)
+ local font = getfont(used)
+ local tfm = fontchar[font]
+ lastfont[n] = false
+ local kind = categories[char]
+ if kind == "lu" then
+ while true do
+ local n = getrandom("capital lu",0x41,0x5A)
+ if tfm[n] then -- this also intercepts tables
+ setchar(used,n)
+ return start
+ end
+ end
+ elseif kind == "ll" then
+ while true do
+ local n = getrandom("capital ll",0x61,0x7A)
+ if tfm[n] then -- this also intercepts tables
+ setchar(used,n)
+ return start
+ end
+ end
+ end
+ return start
+end
+
+register(variables.WORD, WORD) -- 1
+register(variables.word, word) -- 2
+register(variables.Word, Word) -- 3
+register(variables.Words, Words) -- 4
+register(variables.capital,capital) -- 5
+register(variables.Capital,Capital) -- 6
+register(variables.none, none) -- 7 (dummy)
+register(variables.random, randomized) -- 8
+register(variables.mixed, mixed) -- 9
+register(variables.camel, camel) -- 10
+
+register(variables.cap, variables.capital) -- clone
+register(variables.Cap, variables.Capital) -- clone
+
+-- This can be more clever: when we unset we can actually use the same attr ref if
+-- needed. Using properties to block further usage is not faster.
+
+function cases.handler(head) -- not real fast but also not used on much data
+ local start = head
+ local lastfont = { }
+ local lastattr = nil
+ local count = 0
+ local previd = nil
+ local prev = nil
+ while start do -- while because start can jump ahead
+ local id = getid(start)
+ if id == glyph_code then
+ local attr = takeattr(start,a_cases)
+ if attr and attr > 0 and not blocked[attr] then
+ if attr ~= lastattr then
+ lastattr = attr
+ count = 1
+ else
+ count = count + 1
+ end
+ local n, id, m = get(attr)
+ if lastfont[n] == nil then
+ lastfont[n] = id
+ end
+ local action = actions[n] -- map back to low number
+ if action then
+ local quit
+ start, quit = action(start,attr,lastfont,n,count)
+ if trace_casing then
+ report_casing("case trigger %a, instance %a, fontid %a, result %a",n,m,id,quit and "-" or "+")
+ end
+ elseif trace_casing then
+ report_casing("unknown case trigger %a",n)
+ end
+ end
+ elseif id == disc_code then
+ local attr = takeattr(start,a_cases)
+ if attr and attr > 0 and not blocked[attr] then
+ if attr ~= lastattr then
+ lastattr = attr
+ count = 0
+ end
+ local n, id, m = get(attr)
+ if lastfont[n] == nil then
+ lastfont[n] = id
+ end
+ local action = actions[n] -- map back to low number
+ if action then
+ local pre, post, replace = getdisc(start)
+ if replace then
+ local cnt = count
+ for g in nextglyph, replace do
+ cnt = cnt + 1
+ takeattr(g,a_cases)
+ local h, quit = action(start,attr,lastfont,n,cnt,"replace",g)
+ if quit then
+ break
+ end
+ end
+ end
+ if pre then
+ local cnt = count
+ for g in nextglyph, pre do
+ cnt = cnt + 1
+ takeattr(g,a_cases)
+ local h, quit = action(start,attr,lastfont,n,cnt,"pre",g)
+ if quit then
+ break
+ end
+ end
+ end
+ if post then
+ local cnt = count
+ for g in nextglyph, post do
+ cnt = cnt + 1
+ takeattr(g,a_cases)
+ local h, quit = action(start,attr,lastfont,n,cnt,"post",g)
+ if quit then
+ break
+ end
+ end
+ end
+ end
+ count = count + 1
+ end
+ elseif id == math_code then
+ start = end_of_math(start)
+ count = 0
+ elseif count > 0 then
+ if prev_id == kern_code and getsubtype(prev) == fontkern_code then
+ -- still inside a word ...normally kerns are added later
+ else
+ count = 0
+ end
+ end
+ if start then
+ prev = start
+ previd = id
+ start = getnext(start)
+ end
+ end
+ return head
+end
+
+local enabled = false
+
+function cases.set(n,id)
+ if n == v_reset then
+ n = unsetvalue
+ else
+ n = registered[n] or tonumber(n)
+ if n then
+ if not enabled then
+ enableaction("processors","typesetters.cases.handler")
+ if trace_casing then
+ report_casing("enabling case handler")
+ end
+ enabled = true
+ end
+ n = set(n,id or currentfont())
+ else
+ n = unsetvalue
+ end
+ end
+ texsetattribute(a_cases,n)
+ -- return n -- bonus
+end
+
+-- interface
+
+interfaces.implement {
+ name = "setcharactercasing",
+ -- public = true,
+ -- protected = true,
+ actions = cases.set,
+-- arguments = { "string" }
+ arguments = { "argument" }
+}
diff --git a/tex/context/base/mkxl/typo-cap.mkxl b/tex/context/base/mkxl/typo-cap.mkxl
index 5a6b73e5e..8c0cab502 100644
--- a/tex/context/base/mkxl/typo-cap.mkxl
+++ b/tex/context/base/mkxl/typo-cap.mkxl
@@ -18,7 +18,7 @@
%D Maybe we need a more clever system: either command or style mode etc. so
%D that we can avoid the grouped mess in a simple style switch.
-\registerctxluafile{typo-cap}{optimize}
+\registerctxluafile{typo-cap}{autosuffix,optimize}
% \definesystemattribute[case][public] % already predefined
@@ -73,13 +73,13 @@
% test \word{test TEST \TeX} test
% test \Word{test TEST \TeX} test
-\permanent\protected\def\setcharactercasing[#1]{\clf_setcharactercasing{#1}\fontid\font} % can be public implementor
+\permanent\protected\def\setcharactercasing[#1]{\clf_setcharactercasing{#1}} % can be public implementor
-\protected\def\typo_capitale_WORD {\clf_setcharactercasing{\v!WORD }\fontid\font}
-\protected\def\typo_capitale_word {\clf_setcharactercasing{\v!word }\fontid\font}
-\protected\def\typo_capitale_Word {\clf_setcharactercasing{\v!Word }\fontid\font}
-\protected\def\typo_capitale_Words{\clf_setcharactercasing{\v!Words}\fontid\font}
-\protected\def\typo_capitale_camel{\clf_setcharactercasing{\v!camel}\fontid\font}
+\protected\def\typo_capitale_WORD {\clf_setcharactercasing\v!WORD }
+\protected\def\typo_capitale_word {\clf_setcharactercasing\v!word }
+\protected\def\typo_capitale_Word {\clf_setcharactercasing\v!Word }
+\protected\def\typo_capitale_Words{\clf_setcharactercasing\v!Words}
+\protected\def\typo_capitale_camel{\clf_setcharactercasing\v!camel}
\pushoverloadmode
@@ -157,13 +157,13 @@
\def\typo_capitals_set_fake#1%
{\edef\currentcapitals{#1}%
- \clf_setcharactercasing{\currentcapitals}\fontid\font
+ \clf_setcharactercasing\currentcapitals
\usecapitalsstyleparameter\c!style}
\def\typo_capitals_set_real#1%
{\edef\currentcapitals{#1}%
\sc
- \clf_setcharactercasing{\currentcapitals}\fontid\font}
+ \clf_setcharactercasing\currentcapitals}
\permanent\protected\def\pseudosmallcapped{\triggergroupedcommandcs\font_style_pseudosmallcapped}
\permanent\protected\def\pseudoSmallcapped{\triggergroupedcommandcs\font_style_pseudoSmallcapped}
diff --git a/tex/context/base/mkxl/typo-del.mkxl b/tex/context/base/mkxl/typo-del.mkxl
index ab25f72d8..13f525f69 100644
--- a/tex/context/base/mkxl/typo-del.mkxl
+++ b/tex/context/base/mkxl/typo-del.mkxl
@@ -145,8 +145,8 @@
\newsignal\d_typo_subsentence_signal
\newcount \c_typo_subsentence_nesting
-\let\beforesubsentence\donothing
-\let\aftersubsentence \donothing
+\mutable\let\beforesubsentence\donothing % maybe just a parameter
+\mutable\let\aftersubsentence \donothing % maybe just a parameter
% todo: make this language option
%
diff --git a/tex/context/base/mkxl/typo-mar.mkxl b/tex/context/base/mkxl/typo-mar.mkxl
index 5d6f15f21..1fd904cc3 100644
--- a/tex/context/base/mkxl/typo-mar.mkxl
+++ b/tex/context/base/mkxl/typo-mar.mkxl
@@ -142,6 +142,11 @@
\newconditional\inhibitmargindata % This one is used at the Lua end!
\newtoks \everymargindatacontent % Later on we will set this one.
+\mutable\let\currentmargindatastrut \empty
+\mutable\let\currentmargindatawidth \empty
+\mutable\let\currentmarginfirstheight\empty
+\mutable\let\currentmarginreference \empty
+
\appendtoks
\settrue\inhibitmargindata
\to \everyforgetall
diff --git a/tex/context/modules/mkiv/m-scite.mkiv b/tex/context/modules/mkiv/m-scite.mkiv
index 7116a5b32..659d5f58d 100644
--- a/tex/context/modules/mkiv/m-scite.mkiv
+++ b/tex/context/modules/mkiv/m-scite.mkiv
@@ -339,7 +339,7 @@ moduledata.scite = scite
\unexpanded\def\buff_scite_slxb#1%
{% we can have a side float
\advance\hangindent\numexpr#1+2\relax\scitespaceskip
- \begstrut\hskip#1\scitespaceskip
+ \begstrut\hskip#1\scitespaceskip\relax
\ifcase\hangafter
\hangafter\plusone\relax
\fi}
diff --git a/tex/context/modules/mkiv/s-system-macros.mkxl b/tex/context/modules/mkiv/s-system-macros.mkxl
index 72fd3b7c2..6dcccd048 100644
--- a/tex/context/modules/mkiv/s-system-macros.mkxl
+++ b/tex/context/modules/mkiv/s-system-macros.mkxl
@@ -25,6 +25,8 @@
% \usemodule[article-basic] \setuplayout[tight] \setupbodyfont[7pt,tt]
\usemodule[article-basic] \setuplayout[tight] \setupbodyfont[5pt,tt]
+\setupbackgrounds[page][background=color,backgroundcolor=darkgray] \setupcolors[textcolor=white]
+
\setuppapersize
[A4,landscape]
[A4,landscape]
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index c60bc0ca6..2bb9d71cb 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 : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 2020-11-26 15:38
+-- merge date : 2020-11-27 20:07
do -- begin closure to overcome local limits and interference